This commit is contained in:
OTCv8 2021-04-07 20:41:28 +02:00
parent b938520faf
commit e93bcdc9cf
298 changed files with 0 additions and 60508 deletions

View File

@ -1,13 +0,0 @@
<?php
$data = file_get_contents("php://input");
$json = json_decode($data);
if(!$json || !$json->uid) {
die();
}
if($json->uid) {
file_put_contents("stats/".($json->uid).".log", "\n".$data."\n", FILE_APPEND);
}
echo "OK";
?>

View File

@ -1,26 +0,0 @@
<?php
$online_otservlist = 0;
try {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://otservlist.org/");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return data inplace of echoing on screen
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Skip SSL Verification
curl_setopt($ch, CURLOPT_ENCODING , "");
$site = curl_exec($ch);
curl_close($ch);
preg_match('/There are <strong>([0-9]*)<\/strong>/', $site, $matches);
$online_otservlist = $matches[1];
} catch(Exception $e) {}
$online_discord = 0;
try {
$online_discord = json_decode(file_get_contents("https://discordapp.com/api/guilds/628769144925585428/widget.json"))->presence_count;
} catch(Exception $e) {}
$response = array(
"online" => "$online_otservlist Players online",
"discord_online" => $online_discord,
"discord_link" => "https://discord.gg/t4ntS5p"
);
echo json_encode($response);
?>

View File

@ -1,69 +0,0 @@
<?php
// CONFIG
$files_dir = "/var/www/otclient/files";
$files_url = "http://otclient.ovh/files";
$files_and_dirs = array("init.lua", "data", "modules", "layouts");
$checksum_file = "checksums.txt";
$checksum_update_interval = 60; // seconds
$binaries = array(
"WIN32-WGL" => "otclient_gl.exe",
"WIN32-EGL" => "otclient_dx.exe",
"WIN32-WGL-GCC" => "otclient_gcc_gl.exe",
"WIN32-EGL-GCC" => "otclient_gcc_dx.exe",
"X11-GLX" => "otclient_linux",
"X11-EGL" => "otclient_linux",
"ANDROID-EGL" => "", // we can't update android binary
"ANDROID64-EGL" => "" // we can't update android binary
);
// CONFIG END
function sendError($error) {
echo(json_encode(array("error" => $error)));
die();
}
$data = json_decode(file_get_contents("php://input"));
//if(!$data) {
// sendError("Invalid input data");
//}
$version = $data->version ?: 0; // APP_VERSION from init.lua
$build = $data->build ?: ""; // 2.4, 2.4.1, 2.5, etc
$os = $data->os ?: "unknown"; // android, windows, mac, linux, unknown
$platform = $data->platform ?: ""; // WIN32-WGL, X11-GLX, ANDROID-EGL, etc
$args = $data->args; // custom args when calling Updater.check()
$binary = $binaries[$platform] ?: "";
$cache = null;
$cache_file = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $checksum_file;
if (file_exists($cache_file) && (filemtime($cache_file) + $checksum_update_interval > time())) {
$cache = json_decode(file_get_contents($cache_file), true);
}
if(!$cache) { // update cache
$dir = realpath($files_dir);
$rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
$cache = array();
foreach ($rii as $file) {
if (!$file->isFile())
continue;
$path = str_replace($dir, '', $file->getPathname());
$path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
$cache[$path] = hash_file("crc32b", $file->getPathname());
}
file_put_contents($cache_file . ".tmp", json_encode($cache));
rename($cache_file . ".tmp", $cache_file);
}
$ret = array("url" => $files_url, "files" => array(), "keepFiles" => false);
foreach($cache as $file => $checksum) {
$base = trim(explode("/", ltrim($file, "/"))[0]);
if(in_array($base, $files_and_dirs)) {
$ret["files"][$file] = $checksum;
}
if($base == $binary && !empty($binary)) {
$ret["binary"] = array("file" => $file, "checksum" => $checksum);
}
}
echo(json_encode($ret, JSON_PRETTY_PRINT));
?>

View File

@ -1,77 +0,0 @@
<?php
// CONFIG
$files_dir = "/var/www/otclient/files";
$files_url = "http://otclient.ovh/files";
$files_and_dirs = array("init.lua", "data", "modules", "layouts");
$checksum_file = "checksums.txt";
$checksum_update_interval = 60; // seconds
$binaries = array(
"WIN32-WGL" => "otclient_gl.exe",
"WIN32-EGL" => "otclient_dx.exe",
"WIN32-WGL-GCC" => "otclient_gcc_gl.exe",
"WIN32-EGL-GCC" => "otclient_gcc_dx.exe",
"X11-GLX" => "otclient_linux",
"X11-EGL" => "otclient_linux",
"ANDROID-EGL" => "", // we can't update android binary
"ANDROID64-EGL" => "" // we can't update android binary
);
// CONFIG END
function sendError($error) {
echo(json_encode(array("error" => $error)));
die();
}
$data = json_decode(file_get_contents("php://input"));
//if(!$data) {
// sendError("Invalid input data");
//}
$version = $data->version ?: 0; // APP_VERSION from init.lua
$build = $data->build ?: ""; // 2.4, 2.4.1, 2.5, etc
$os = $data->os ?: "unknown"; // android, windows, mac, linux, unknown
$platform = $data->platform ?: ""; // WIN32-WGL, X11-GLX, ANDROID-EGL, etc
$args = $data->args; // custom args when calling Updater.check()
$binary = $binaries[$platform] ?: "";
$forVersion = "";
if($args && $args->version) {
$forVersion = strval($args->version);
}
$cache = null;
$cache_file = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $checksum_file;
if (file_exists($cache_file) && (filemtime($cache_file) + $checksum_update_interval > time())) {
$cache = json_decode(file_get_contents($cache_file), true);
}
if(!$cache) { // update cache
$dir = realpath($files_dir);
$rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS));
$cache = array();
foreach ($rii as $file) {
if (!$file->isFile())
continue;
$path = str_replace($dir, '', $file->getPathname());
$path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
$cache[$path] = hash_file("crc32b", $file->getPathname());
}
file_put_contents($cache_file . ".tmp", json_encode($cache));
rename($cache_file . ".tmp", $cache_file);
}
$ret = array("url" => $files_url, "files" => array(), "keepFiles" => empty($forVersion) ? false : true);
foreach($cache as $file => $checksum) {
$base = trim(explode("/", ltrim($file, "/"))[0]);
if(strpos($file, "data/things") !== false && (empty($forVersion) || strpos($file, $forVersion) === false)) {
continue;
}
if(in_array($base, $files_and_dirs)) {
$ret["files"][$file] = $checksum;
}
if($base == $binary && !empty($binary)) {
$ret["binary"] = array("file" => $file, "checksum" => $checksum);
}
}
echo(json_encode($ret, JSON_PRETTY_PRINT));
?>

Binary file not shown.

View File

@ -1 +0,0 @@
adb uninstall com.otclientv8 && adb install otclientv8.apk && adb logcat -c && adb shell am start -n com.otclientv8/com.otclientv8.OTClientV8 && adb logcat | findstr /i otclient

View File

@ -1,5 +0,0 @@
Here are tools for server
all lua scripts are made for and tested on latest tfs (1.2/1.3)
add json.lua to data/lib/core and then in core.lua add: dofile('data/lib/core/json.lua')

View File

@ -1,399 +0,0 @@
-- add to lib/core, later add dofile in lib/core/core.lua
--
-- json.lua
--
-- Copyright (c) 2018 rxi
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy of
-- this software and associated documentation files (the "Software"), to deal in
-- the Software without restriction, including without limitation the rights to
-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-- of the Software, and to permit persons to whom the Software is furnished to do
-- so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in all
-- copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-- SOFTWARE.
--
json = { _version = "0.1.1" }
-------------------------------------------------------------------------------
-- Encode
-------------------------------------------------------------------------------
local encode
local escape_char_map = {
[ "\\" ] = "\\\\",
[ "\"" ] = "\\\"",
[ "\b" ] = "\\b",
[ "\f" ] = "\\f",
[ "\n" ] = "\\n",
[ "\r" ] = "\\r",
[ "\t" ] = "\\t",
}
local escape_char_map_inv = { [ "\\/" ] = "/" }
for k, v in pairs(escape_char_map) do
escape_char_map_inv[v] = k
end
local function escape_char(c)
return escape_char_map[c] or string.format("\\u%04x", c:byte())
end
local function encode_nil(val)
return "null"
end
local function encode_table(val, stack)
local res = {}
stack = stack or {}
-- Circular reference?
if stack[val] then error("circular reference") end
stack[val] = true
if val[1] ~= nil or next(val) == nil then
-- Treat as array -- check keys are valid and it is not sparse
local n = 0
for k in pairs(val) do
if type(k) ~= "number" then
error("invalid table: mixed or invalid key types")
end
n = n + 1
end
if n ~= #val then
error("invalid table: sparse array")
end
-- Encode
for i, v in ipairs(val) do
table.insert(res, encode(v, stack))
end
stack[val] = nil
return "[" .. table.concat(res, ",") .. "]"
else
-- Treat as an object
for k, v in pairs(val) do
if type(k) ~= "string" then
error("invalid table: mixed or invalid key types")
end
table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
end
stack[val] = nil
return "{" .. table.concat(res, ",") .. "}"
end
end
local function encode_string(val)
return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
end
local function encode_number(val)
-- Check for NaN, -inf and inf
if val ~= val or val <= -math.huge or val >= math.huge then
error("unexpected number value '" .. tostring(val) .. "'")
end
return string.format("%.14g", val)
end
local type_func_map = {
[ "nil" ] = encode_nil,
[ "table" ] = encode_table,
[ "string" ] = encode_string,
[ "number" ] = encode_number,
[ "boolean" ] = tostring,
}
encode = function(val, stack)
local t = type(val)
local f = type_func_map[t]
if f then
return f(val, stack)
end
error("unexpected type '" .. t .. "'")
end
function json.encode(val)
return ( encode(val) )
end
-------------------------------------------------------------------------------
-- Decode
-------------------------------------------------------------------------------
local parse
local function create_set(...)
local res = {}
for i = 1, select("#", ...) do
res[ select(i, ...) ] = true
end
return res
end
local space_chars = create_set(" ", "\t", "\r", "\n")
local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
local literals = create_set("true", "false", "null")
local literal_map = {
[ "true" ] = true,
[ "false" ] = false,
[ "null" ] = nil,
}
local function next_char(str, idx, set, negate)
for i = idx, #str do
if set[str:sub(i, i)] ~= negate then
return i
end
end
return #str + 1
end
local function decode_error(str, idx, msg)
local line_count = 1
local col_count = 1
for i = 1, idx - 1 do
col_count = col_count + 1
if str:sub(i, i) == "\n" then
line_count = line_count + 1
col_count = 1
end
end
error( string.format("%s at line %d col %d", msg, line_count, col_count) )
end
local function codepoint_to_utf8(n)
-- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
local f = math.floor
if n <= 0x7f then
return string.char(n)
elseif n <= 0x7ff then
return string.char(f(n / 64) + 192, n % 64 + 128)
elseif n <= 0xffff then
return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
elseif n <= 0x10ffff then
return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128,
f(n % 4096 / 64) + 128, n % 64 + 128)
end
error( string.format("invalid unicode codepoint '%x'", n) )
end
local function parse_unicode_escape(s)
local n1 = tonumber( s:sub(3, 6), 16 )
local n2 = tonumber( s:sub(9, 12), 16 )
-- Surrogate pair?
if n2 then
return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
else
return codepoint_to_utf8(n1)
end
end
local function parse_string(str, i)
local has_unicode_escape = false
local has_surrogate_escape = false
local has_escape = false
local last
for j = i + 1, #str do
local x = str:byte(j)
if x < 32 then
decode_error(str, j, "control character in string")
end
if last == 92 then -- "\\" (escape char)
if x == 117 then -- "u" (unicode escape sequence)
local hex = str:sub(j + 1, j + 5)
if not hex:find("%x%x%x%x") then
decode_error(str, j, "invalid unicode escape in string")
end
if hex:find("^[dD][89aAbB]") then
has_surrogate_escape = true
else
has_unicode_escape = true
end
else
local c = string.char(x)
if not escape_chars[c] then
decode_error(str, j, "invalid escape char '" .. c .. "' in string")
end
has_escape = true
end
last = nil
elseif x == 34 then -- '"' (end of string)
local s = str:sub(i + 1, j - 1)
if has_surrogate_escape then
s = s:gsub("\\u[dD][89aAbB]..\\u....", parse_unicode_escape)
end
if has_unicode_escape then
s = s:gsub("\\u....", parse_unicode_escape)
end
if has_escape then
s = s:gsub("\\.", escape_char_map_inv)
end
return s, j + 1
else
last = x
end
end
decode_error(str, i, "expected closing quote for string")
end
local function parse_number(str, i)
local x = next_char(str, i, delim_chars)
local s = str:sub(i, x - 1)
local n = tonumber(s)
if not n then
decode_error(str, i, "invalid number '" .. s .. "'")
end
return n, x
end
local function parse_literal(str, i)
local x = next_char(str, i, delim_chars)
local word = str:sub(i, x - 1)
if not literals[word] then
decode_error(str, i, "invalid literal '" .. word .. "'")
end
return literal_map[word], x
end
local function parse_array(str, i)
local res = {}
local n = 1
i = i + 1
while 1 do
local x
i = next_char(str, i, space_chars, true)
-- Empty / end of array?
if str:sub(i, i) == "]" then
i = i + 1
break
end
-- Read token
x, i = parse(str, i)
res[n] = x
n = n + 1
-- Next token
i = next_char(str, i, space_chars, true)
local chr = str:sub(i, i)
i = i + 1
if chr == "]" then break end
if chr ~= "," then decode_error(str, i, "expected ']' or ','") end
end
return res, i
end
local function parse_object(str, i)
local res = {}
i = i + 1
while 1 do
local key, val
i = next_char(str, i, space_chars, true)
-- Empty / end of object?
if str:sub(i, i) == "}" then
i = i + 1
break
end
-- Read key
if str:sub(i, i) ~= '"' then
decode_error(str, i, "expected string for key")
end
key, i = parse(str, i)
-- Read ':' delimiter
i = next_char(str, i, space_chars, true)
if str:sub(i, i) ~= ":" then
decode_error(str, i, "expected ':' after key")
end
i = next_char(str, i + 1, space_chars, true)
-- Read value
val, i = parse(str, i)
-- Set
res[key] = val
-- Next token
i = next_char(str, i, space_chars, true)
local chr = str:sub(i, i)
i = i + 1
if chr == "}" then break end
if chr ~= "," then decode_error(str, i, "expected '}' or ','") end
end
return res, i
end
local char_func_map = {
[ '"' ] = parse_string,
[ "0" ] = parse_number,
[ "1" ] = parse_number,
[ "2" ] = parse_number,
[ "3" ] = parse_number,
[ "4" ] = parse_number,
[ "5" ] = parse_number,
[ "6" ] = parse_number,
[ "7" ] = parse_number,
[ "8" ] = parse_number,
[ "9" ] = parse_number,
[ "-" ] = parse_number,
[ "t" ] = parse_literal,
[ "f" ] = parse_literal,
[ "n" ] = parse_literal,
[ "[" ] = parse_array,
[ "{" ] = parse_object,
}
parse = function(str, idx)
local chr = str:sub(idx, idx)
local f = char_func_map[chr]
if f then
return f(str, idx)
end
decode_error(str, idx, "unexpected character '" .. chr .. "'")
end
function json.decode(str)
if type(str) ~= "string" then
error("expected argument of type string, got " .. type(str))
end
local res, idx = parse(str, next_char(str, 1, space_chars, true))
idx = next_char(str, idx, space_chars, true)
if idx <= #str then
decode_error(str, idx, "trailing garbage")
end
return res
end

View File

@ -1,362 +0,0 @@
-- BETA VERSION, net tested yet
-- Instruction:
-- creaturescripts.xml <event type="extendedopcode" name="Shop" script="shop.lua" />
-- and in login.lua player:registerEvent("Shop")
-- create sql table shop_history
-- set variables
-- set up function init(), add there items and categories, follow examples
-- set up callbacks at the bottom to add player item/outfit/whatever you want
local SHOP_EXTENDED_OPCODE = 201
local SHOP_OFFERS = {}
local SHOP_CALLBACKS = {}
local SHOP_CATEGORIES = nil
local SHOP_BUY_URL = "http://otland.net" -- can be empty
local SHOP_AD = { -- can be nil
image = "https://s3.envato.com/files/62273611/PNG%20Blue/Banner%20blue%20468x60.png",
url = "http://otclient.ovh",
text = ""
}
local MAX_PACKET_SIZE = 50000
--[[ SQL TABLE
CREATE TABLE `shop_history` (
`id` int(11) NOT NULL,
`account` int(11) NOT NULL,
`player` int(11) NOT NULL,
`date` datetime NOT NULL,
`title` varchar(100) NOT NULL,
`cost` int(11) NOT NULL,
`details` varchar(500) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE `shop_history`
ADD PRIMARY KEY (`id`);
ALTER TABLE `shop_history`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
]]--
function init()
-- print(json.encode(g_game.getLocalPlayer():getOutfit())) -- in console in otclient, will print current outfit and mount
SHOP_CATEGORIES = {}
local category1 = addCategory({
type="item",
item=ItemType(2160):getClientId(),
count=100,
name="Items"
})
local category2 = addCategory({
type="outfit",
name="Outfits",
outfit={
mount=0,
feet=114,
legs=114,
body=116,
type=143,
auxType=0,
addons=3,
head=2,
rotating=true
}
})
local category3 = addCategory({
type="image",
image="http://otclient.ovh/images/137.png",
name="Category with http image"
})
local category4 = addCategory({
type="image",
image="/data/images/game/states/electrified.png",
name="Category with local image"
})
category1.addItem(1, 2160, 1, "1 Crystal coin", "description of cristal coin")
category1.addItem(5, 2160, 5, "5 Crystal coin", "description of cristal coin")
category1.addItem(50, 2160, 50, "50 Crystal coin", "description of cristal coin")
category1.addItem(90, 2160, 100, "100 Crystal coin", "description of cristal coin")
category1.addItem(200, 2493, 1, "Demon helmet1", "woo\ndemon helmet\nnice, you should buy it")
category1.addItem(1, 2160, 1, "1 Crystal coin1", "description of cristal coin")
category1.addItem(5, 2160, 5, "5 Crystal coin1", "description of cristal coin")
category1.addItem(50, 2160, 50, "50 Crystal coin1", "description of cristal coin")
category1.addItem(90, 2160, 100, "100 Crystal coin1", "description of cristal coin")
category1.addItem(200, 2493, 1, "Demon helmet2", "woo\ndemon helmet\nnice, you should buy it")
category1.addItem(1, 2160, 1, "1 Crystal coin3", "description of cristal coin")
category1.addItem(5, 2160, 5, "5 Crystal coin3", "description of cristal coin")
category1.addItem(50, 2160, 50, "50 Crystal coin3", "description of cristal coin")
category1.addItem(90, 2160, 100, "100 Crystal coin3", "description of cristal coin")
category1.addItem(200, 2493, 1, "Demon helmet3", "wooxD\ndemon helmet\nnice, you should buy it")
category2.addOutfit(500, {
mount=0,
feet=114,
legs=114,
body=116,
type=143,
auxType=0,
addons=3,
head=2,
rotating=true
}, "title of this cool outfit or whatever", "this is your new cool outfit. You can buy it here.\nsrlsy")
category2.addOutfit(100, {
mount=682,
feet=0,
legs=0,
body=0,
type=143,
auxType=0,
addons=0,
head=0,
rotating=true
}, "MOUNT!!!", "DOUBLE CLICK TO BUY THIS MOUNT. IDK NAME")
category2.addOutfit(100, {
mount=0,
feet=0,
legs=0,
body=0,
type=35,
auxType=0,
addons=0,
head=0,
rotating=true
}, "Demon outfit", "Want be a demon?\nNo problem")
category2.addOutfit(100, {
mount=0,
feet=0,
legs=0,
body=0,
type=35,
auxType=0,
addons=0,
head=0,
rotating=false
}, "Demon outfit2", "This one is not rotating")
category4.addImage(10000, "/data/images/game/states/haste.png", "Offer with local image", "another local image\n/data/images/game/states/haste.png")
category4.addImage(10000, "http://otclient.ovh/images/freezing.png", "Offer with remote image and custom buy action", "blalasdasd image\nhttp://otclient.ovh/images/freezing.png", customImageBuyAction)
end
function addCategory(data)
data['offers'] = {}
table.insert(SHOP_CATEGORIES, data)
table.insert(SHOP_CALLBACKS, {})
local index = #SHOP_CATEGORIES
return {
addItem = function(cost, itemId, count, title, description, callback)
if not callback then
callback = defaultItemBuyAction
end
table.insert(SHOP_CATEGORIES[index]['offers'], {
cost=cost,
type="item",
item=ItemType(itemId):getClientId(), -- displayed
itemId=itemId,
count=count,
title=title,
description=description
})
table.insert(SHOP_CALLBACKS[index], callback)
end,
addOutfit = function(cost, outfit, title, description, callback)
if not callback then
callback = defaultOutfitBuyAction
end
table.insert(SHOP_CATEGORIES[index]['offers'], {
cost=cost,
type="outfit",
outfit=outfit,
title=title,
description=description
})
table.insert(SHOP_CALLBACKS[index], callback)
end,
addImage = function(cost, image, title, description, callback)
if not callback then
callback = defaultImageBuyAction
end
table.insert(SHOP_CATEGORIES[index]['offers'], {
cost=cost,
type="image",
image=image,
title=title,
description=description
})
table.insert(SHOP_CALLBACKS[index], callback)
end
}
end
function getPoints(player)
local points = 0
local resultId = db.storeQuery("SELECT `premium_points` FROM `accounts` WHERE `id` = " .. player:getAccountId())
if resultId ~= false then
points = result.getDataInt(resultId, "premium_points")
result.free(resultId)
end
return points
end
function getStatus(player)
local status = {
ad = SHOP_AD,
points = getPoints(player),
buyUrl = SHOP_BUY_URL
}
return status
end
function sendJSON(player, action, data, forceStatus)
local status = nil
if not player:getStorageValue(1150001) or player:getStorageValue(1150001) + 10 < os.time() or forceStatus then
status = getStatus(player)
end
player:setStorageValue(1150001, os.time())
local buffer = json.encode({action = action, data = data, status = status})
local s = {}
for i=1, #buffer, MAX_PACKET_SIZE do
s[#s+1] = buffer:sub(i,i+MAX_PACKET_SIZE - 1)
end
local msg = NetworkMessage()
if #s == 1 then
msg:addByte(50)
msg:addByte(SHOP_EXTENDED_OPCODE)
msg:addString(s[1])
msg:sendToPlayer(player)
return
end
-- split message if too big
msg:addByte(50)
msg:addByte(SHOP_EXTENDED_OPCODE)
msg:addString("S" .. s[1])
msg:sendToPlayer(player)
for i=2,#s - 1 do
msg = NetworkMessage()
msg:addByte(50)
msg:addByte(SHOP_EXTENDED_OPCODE)
msg:addString("P" .. s[i])
msg:sendToPlayer(player)
end
msg = NetworkMessage()
msg:addByte(50)
msg:addByte(SHOP_EXTENDED_OPCODE)
msg:addString("E" .. s[#s])
msg:sendToPlayer(player)
end
function sendMessage(player, title, msg, forceStatus)
sendJSON(player, "message", {title=title, msg=msg}, forceStatus)
end
function onExtendedOpcode(player, opcode, buffer)
if opcode ~= SHOP_EXTENDED_OPCODE then
return false
end
local status, json_data = pcall(function() return json.decode(buffer) end)
if not status then
return false
end
local action = json_data['action']
local data = json_data['data']
if not action or not data then
return false
end
if SHOP_CATEGORIES == nil then
init()
end
if action == 'init' then
sendJSON(player, "categories", SHOP_CATEGORIES)
elseif action == 'buy' then
processBuy(player, data)
elseif action == "history" then
sendHistory(player)
end
return true
end
function processBuy(player, data)
local categoryId = tonumber(data["category"])
local offerId = tonumber(data["offer"])
local offer = SHOP_CATEGORIES[categoryId]['offers'][offerId]
local callback = SHOP_CALLBACKS[categoryId][offerId]
if not offer or not callback or data["title"] ~= offer["title"] or data["cost"] ~= offer["cost"] then
sendJSON(player, "categories", SHOP_CATEGORIES) -- refresh categories, maybe invalid
return sendMessage(player, "Error!", "Invalid offer")
end
local points = getPoints(player)
if not offer['cost'] or offer['cost'] > points or points < 1 then
return sendMessage(player, "Error!", "You don't have enough points to buy " .. offer['title'] .."!", true)
end
local status = callback(player, offer)
if status == true then
db.query("UPDATE `accounts` set `premium_points` = `premium_points` - " .. offer['cost'] .. " WHERE `id` = " .. player:getAccountId())
db.asyncQuery("INSERT INTO `shop_history` (`account`, `player`, `date`, `title`, `cost`, `details`) VALUES ('" .. player:getAccountId() .. "', '" .. player:getGuid() .. "', NOW(), " .. db.escapeString(offer['title']) .. ", " .. db.escapeString(offer['cost']) .. ", " .. db.escapeString(json.encode(offer)) .. ")")
return sendMessage(player, "Success!", "You bought " .. offer['title'] .."!", true)
end
if status == nil or status == false then
status = "Unknown error while buying " .. offer['title']
end
sendMessage(player, "Error!", status)
end
function sendHistory(player)
if player:getStorageValue(1150002) and player:getStorageValue(1150002) + 10 > os.time() then
return -- min 10s delay
end
player:setStorageValue(1150002, os.time())
local history = {}
local resultId = db.storeQuery("SELECT * FROM `shop_history` WHERE `account` = " .. player:getAccountId() .. " order by `id` DESC")
if resultId ~= false then
repeat
local details = result.getDataString(resultId, "details")
local status, json_data = pcall(function() return json.decode(details) end)
if not status then
json_data = {
type = "image",
title = result.getDataString(resultId, "title"),
cost = result.getDataInt(resultId, "cost")
}
end
table.insert(history, json_data)
history[#history]["description"] = "Bought on " .. result.getDataString(resultId, "date") .. " for " .. result.getDataInt(resultId, "cost") .. " points."
until not result.next(resultId)
result.free(resultId)
end
sendJSON(player, "history", history)
end
-- BUY CALLBACKS
-- May be useful: print(json.encode(offer))
function defaultItemBuyAction(player, offer)
-- todo: check if has capacity
if player:addItem(offer["itemId"], offer["count"], false) then
return true
end
return "Can't add item! Do you have enough space?"
end
function defaultOutfitBuyAction(player, offer)
return "default outfit buy action is not implemented"
end
function defaultImageBuyAction(player, offer)
return "default image buy action is not implemented"
end
function customImageBuyAction(player, offer)
return "custom image buy action is not implemented. Offer: " .. offer['title']
end

View File

@ -1,8 +0,0 @@
# OTClientV8 partial sources (90% of code)
To help you understand how OTClientV8 works, some parts of source code has been published.
All files from client/ dir has been shared, but there few places with hidden code due to various reasons
In the future more parts of OTCv8 will be available here
If you want buy access to full sources, contact kondrah#7945 on discord
Or send mail to otclient@otclient.ovh (but discord is better)

View File

@ -1,113 +0,0 @@
# CMAKE_CURRENT_LIST_DIR cmake 2.6 compatibility
if(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 6)
get_filename_component(CMAKE_CURRENT_LIST_DIR ${CMAKE_CURRENT_LIST_FILE} PATH)
endif(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 6)
# client options
add_definitions(-DCLIENT)
option(BOT_PROTECTION "Enable bot protection" ON)
if(BOT_PROTECTION)
add_definitions(-DBOT_PROTECTION)
message(STATUS "Bot protection: ON")
else(BOT_PROTECTION)
message(STATUS "Bot protection: OFF")
endif(BOT_PROTECTION)
set(client_SOURCES ${client_SOURCES}
# client
${CMAKE_CURRENT_LIST_DIR}/const.h
${CMAKE_CURRENT_LIST_DIR}/global.h
${CMAKE_CURRENT_LIST_DIR}/luafunctions_client.cpp
${CMAKE_CURRENT_LIST_DIR}/client.cpp
${CMAKE_CURRENT_LIST_DIR}/client.h
# core
${CMAKE_CURRENT_LIST_DIR}/animatedtext.cpp
${CMAKE_CURRENT_LIST_DIR}/animatedtext.h
${CMAKE_CURRENT_LIST_DIR}/animator.h
${CMAKE_CURRENT_LIST_DIR}/animator.cpp
${CMAKE_CURRENT_LIST_DIR}/container.cpp
${CMAKE_CURRENT_LIST_DIR}/container.h
${CMAKE_CURRENT_LIST_DIR}/creature.cpp
${CMAKE_CURRENT_LIST_DIR}/creature.h
${CMAKE_CURRENT_LIST_DIR}/declarations.h
${CMAKE_CURRENT_LIST_DIR}/effect.cpp
${CMAKE_CURRENT_LIST_DIR}/effect.h
${CMAKE_CURRENT_LIST_DIR}/game.cpp
${CMAKE_CURRENT_LIST_DIR}/game.h
${CMAKE_CURRENT_LIST_DIR}/shadermanager.cpp
${CMAKE_CURRENT_LIST_DIR}/shadermanager.h
${CMAKE_CURRENT_LIST_DIR}/item.cpp
${CMAKE_CURRENT_LIST_DIR}/item.h
${CMAKE_CURRENT_LIST_DIR}/localplayer.cpp
${CMAKE_CURRENT_LIST_DIR}/localplayer.h
${CMAKE_CURRENT_LIST_DIR}/map.cpp
${CMAKE_CURRENT_LIST_DIR}/map.h
${CMAKE_CURRENT_LIST_DIR}/mapio.cpp
${CMAKE_CURRENT_LIST_DIR}/mapview.cpp
${CMAKE_CURRENT_LIST_DIR}/mapview.h
${CMAKE_CURRENT_LIST_DIR}/minimap.cpp
${CMAKE_CURRENT_LIST_DIR}/minimap.h
${CMAKE_CURRENT_LIST_DIR}/lightview.cpp
${CMAKE_CURRENT_LIST_DIR}/lightview.h
${CMAKE_CURRENT_LIST_DIR}/missile.cpp
${CMAKE_CURRENT_LIST_DIR}/missile.h
${CMAKE_CURRENT_LIST_DIR}/outfit.cpp
${CMAKE_CURRENT_LIST_DIR}/outfit.h
${CMAKE_CURRENT_LIST_DIR}/player.cpp
${CMAKE_CURRENT_LIST_DIR}/player.h
${CMAKE_CURRENT_LIST_DIR}/spritemanager.cpp
${CMAKE_CURRENT_LIST_DIR}/spritemanager.h
${CMAKE_CURRENT_LIST_DIR}/statictext.cpp
${CMAKE_CURRENT_LIST_DIR}/statictext.h
${CMAKE_CURRENT_LIST_DIR}/thing.cpp
${CMAKE_CURRENT_LIST_DIR}/thing.h
${CMAKE_CURRENT_LIST_DIR}/thingtypemanager.cpp
${CMAKE_CURRENT_LIST_DIR}/thingtypemanager.h
${CMAKE_CURRENT_LIST_DIR}/thingtype.cpp
${CMAKE_CURRENT_LIST_DIR}/thingtype.h
${CMAKE_CURRENT_LIST_DIR}/itemtype.cpp
${CMAKE_CURRENT_LIST_DIR}/itemtype.h
${CMAKE_CURRENT_LIST_DIR}/tile.cpp
${CMAKE_CURRENT_LIST_DIR}/tile.h
${CMAKE_CURRENT_LIST_DIR}/houses.cpp
${CMAKE_CURRENT_LIST_DIR}/houses.h
${CMAKE_CURRENT_LIST_DIR}/towns.cpp
${CMAKE_CURRENT_LIST_DIR}/towns.h
${CMAKE_CURRENT_LIST_DIR}/creatures.cpp
${CMAKE_CURRENT_LIST_DIR}/creatures.h
# lua
${CMAKE_CURRENT_LIST_DIR}/luavaluecasts_client.cpp
${CMAKE_CURRENT_LIST_DIR}/luavaluecasts_client.h
# net
${CMAKE_CURRENT_LIST_DIR}/protocolcodes.cpp
${CMAKE_CURRENT_LIST_DIR}/protocolcodes.h
${CMAKE_CURRENT_LIST_DIR}/protocolgame.cpp
${CMAKE_CURRENT_LIST_DIR}/protocolgame.h
${CMAKE_CURRENT_LIST_DIR}/protocolgameparse.cpp
${CMAKE_CURRENT_LIST_DIR}/protocolgamesend.cpp
# ui
${CMAKE_CURRENT_LIST_DIR}/uicreature.cpp
${CMAKE_CURRENT_LIST_DIR}/uicreature.h
${CMAKE_CURRENT_LIST_DIR}/uiitem.cpp
${CMAKE_CURRENT_LIST_DIR}/uiitem.h
${CMAKE_CURRENT_LIST_DIR}/uimap.cpp
${CMAKE_CURRENT_LIST_DIR}/uimap.h
${CMAKE_CURRENT_LIST_DIR}/uiminimap.cpp
${CMAKE_CURRENT_LIST_DIR}/uiminimap.h
${CMAKE_CURRENT_LIST_DIR}/uiprogressrect.cpp
${CMAKE_CURRENT_LIST_DIR}/uiprogressrect.h
${CMAKE_CURRENT_LIST_DIR}/uimapanchorlayout.cpp
${CMAKE_CURRENT_LIST_DIR}/uimapanchorlayout.h
${CMAKE_CURRENT_LIST_DIR}/uisprite.cpp
${CMAKE_CURRENT_LIST_DIR}/uisprite.h
# util
${CMAKE_CURRENT_LIST_DIR}/position.h
)
set_source_files_properties(${CMAKE_CURRENT_LIST_DIR}/luafunctions.cpp
PROPERTIES LANGUAGE CXX COMPILE_FLAGS "-g0 -Os")

View File

@ -1,101 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "animatedtext.h"
#include "map.h"
#include "game.h"
#include <framework/core/clock.h>
#include <framework/core/eventdispatcher.h>
#include <framework/graphics/graphics.h>
AnimatedText::AnimatedText()
{
m_cachedText.setFont(g_fonts.getFont("verdana-11px-rounded"));
m_cachedText.setAlign(Fw::AlignLeft);
}
void AnimatedText::drawText(const Point& dest, const Rect& visibleRect)
{
static float tf = Otc::ANIMATED_TEXT_DURATION;
static float tftf = Otc::ANIMATED_TEXT_DURATION * Otc::ANIMATED_TEXT_DURATION;
Point p = dest;
Size textSize = m_cachedText.getTextSize();
float t = m_animationTimer.ticksElapsed();
p.x -= textSize.width() / 2;
if(g_game.getFeature(Otc::GameDiagonalAnimatedText)) {
p.x -= (4 * t / tf) + (8 * t * t / tftf);
}
p.y += (-48 * t) / tf;
p += m_offset;
Rect rect(p, textSize);
if(visibleRect.contains(rect)) {
float t0 = tf / 1.2;
Color color = m_color;
if(t > t0) {
color.setAlpha((float)(1 - (t - t0) / (tf - t0)));
}
m_cachedText.draw(rect, color);
}
}
void AnimatedText::onAppear()
{
m_animationTimer.restart();
// schedule removal
auto self = asAnimatedText();
g_dispatcher.scheduleEvent([self]() { g_map.removeThing(self); }, Otc::ANIMATED_TEXT_DURATION);
}
void AnimatedText::setColor(int color)
{
m_color = Color::from8bit(color);
}
void AnimatedText::setText(const std::string& text)
{
m_cachedText.setText(text);
}
bool AnimatedText::merge(const AnimatedTextPtr& other)
{
if(other->getColor() != m_color)
return false;
if(other->getCachedText().getFont() != m_cachedText.getFont())
return false;
if(m_animationTimer.ticksElapsed() > Otc::ANIMATED_TEXT_DURATION / 2.5)
return false;
try {
int number = stdext::safe_cast<int>(m_cachedText.getText());
int otherNumber = stdext::safe_cast<int>(other->getCachedText().getText());
m_cachedText.setText(std::to_string(number + otherNumber));
return true;
} catch(...) {}
return false;
}

View File

@ -1,64 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef ANIMATEDTEXT_H
#define ANIMATEDTEXT_H
#include "thing.h"
#include <framework/graphics/fontmanager.h>
#include <framework/core/timer.h>
#include <framework/graphics/cachedtext.h>
// @bindclass
class AnimatedText : public Thing
{
public:
AnimatedText();
void drawText(const Point& dest, const Rect& visibleRect);
void setColor(int color);
void setText(const std::string& text);
void setOffset(const Point& offset) { m_offset = offset; }
Color getColor() { return m_color; }
const CachedText& getCachedText() const { return m_cachedText; }
Point getOffset() { return m_offset; }
Timer getTimer() { return m_animationTimer; }
bool merge(const AnimatedTextPtr& other);
AnimatedTextPtr asAnimatedText() { return static_self_cast<AnimatedText>(); }
bool isAnimatedText() { return true; }
std::string getText() { return m_cachedText.getText(); }
protected:
virtual void onAppear();
private:
Color m_color;
Timer m_animationTimer;
CachedText m_cachedText;
Point m_offset;
};
#endif

View File

@ -1,244 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "declarations.h"
#include "animator.h"
#include <framework/core/clock.h>
#include <framework/core/filestream.h>
#include <framework/util/extras.h>
#include <framework/stdext/fastrand.h>
Animator::Animator()
{
m_animationPhases = 0;
m_startPhase = 0;
m_loopCount = 0;
m_async = false;
m_currentDuration = 0;
m_currentDirection = AnimDirForward;
m_currentLoop = 0;
m_lastPhaseTicks = 0;
m_isComplete = false;
m_phase = 0;
}
void Animator::unserialize(int animationPhases, const FileStreamPtr& fin)
{
m_animationPhases = animationPhases;
m_async = fin->getU8() == 0;
m_loopCount = fin->get32();
m_startPhase = fin->get8();
for(int i = 0; i < m_animationPhases; ++i) {
int minimum = fin->getU32();
int maximum = fin->getU32();
m_phaseDurations.push_back(std::make_pair(minimum, std::max(0, maximum - minimum)));
}
m_phase = getStartPhase();
VALIDATE(m_animationPhases == (int)m_phaseDurations.size());
VALIDATE(m_startPhase >= -1 && m_startPhase < m_animationPhases);
}
void Animator::serialize(const FileStreamPtr& fin)
{
fin->addU8(m_async ? 0 : 1);
fin->add32(m_loopCount);
fin->add8(m_startPhase);
for(auto& phase : m_phaseDurations) {
fin->addU32(phase.first);
fin->addU32(phase.first + phase.second);
}
}
void Animator::setPhase(int phase)
{
if(m_phase == phase) return;
if(m_async) {
if(phase == AnimPhaseAsync)
m_phase = 0;
else if(phase == AnimPhaseRandom)
m_phase = (int)stdext::random_range(0, (long)m_animationPhases);
else if(phase >= 0 && phase < m_animationPhases)
m_phase = phase;
else
m_phase = getStartPhase();
m_isComplete = false;
m_lastPhaseTicks = g_clock.millis();
m_currentDuration = getPhaseDuration(phase);
m_currentLoop = 0;
} else
calculateSynchronous();
}
int Animator::getPhase()
{
ticks_t ticks = g_clock.millis();
if(ticks != m_lastPhaseTicks && !m_isComplete) {
int elapsedTicks = (int)(ticks - m_lastPhaseTicks);
if(elapsedTicks >= m_currentDuration) {
int phase = 0;
if(m_loopCount < 0)
phase = getPingPongPhase();
else
phase = getLoopPhase();
if(m_phase != phase) {
int duration = getPhaseDuration(phase) - (elapsedTicks - m_currentDuration);
if(duration < 0 && !m_async) {
calculateSynchronous();
} else {
m_phase = phase;
m_currentDuration = std::max<int>(0, duration);
}
} else
m_isComplete = true;
} else
m_currentDuration -= elapsedTicks;
m_lastPhaseTicks = ticks;
}
return m_phase;
}
int Animator::getPhaseAt(Timer& timer, int lastPhase)
{
static int rand_val = 6;
ticks_t time = timer.ticksElapsed();
for (int i = lastPhase; i < m_animationPhases; ++i) {
int phaseDuration = m_phaseDurations[i].second == 0 ?
m_phaseDurations[i].first : m_phaseDurations[i].first + rand_val % (m_phaseDurations[i].second);
rand_val = rand_val * 7 + 11;
if (time < phaseDuration) {
timer.restart();
timer.adjust(-time);
return i;
}
time -= phaseDuration;
}
return -1;
/*
ticks_t total = 0;
for (const auto &pair : m_phaseDurations) {
total += std::get<1>(pair);
if (time < total) {
return index;
}
++index;
}
return std::min<int>(index, m_animationPhases - 1);
*/
}
int Animator::getStartPhase()
{
if(m_startPhase > -1)
return m_startPhase;
return (int)stdext::random_range(0, (long)m_animationPhases);
}
void Animator::resetAnimation()
{
m_isComplete = false;
m_currentDirection = AnimDirForward;
m_currentLoop = 0;
setPhase(AnimPhaseAutomatic);
}
int Animator::getPingPongPhase()
{
int count = m_currentDirection == AnimDirForward ? 1 : -1;
int nextPhase = m_phase + count;
if(nextPhase < 0 || nextPhase >= m_animationPhases) {
m_currentDirection = m_currentDirection == AnimDirForward ? AnimDirBackward : AnimDirForward;
count *= -1;
}
return m_phase + count;
}
int Animator::getLoopPhase()
{
int nextPhase = m_phase + 1;
if(nextPhase < m_animationPhases)
return nextPhase;
if(m_loopCount == 0)
return 0;
if(m_currentLoop < (m_loopCount - 1)) {
m_currentLoop++;
return 0;
}
return m_phase;
}
int Animator::getPhaseDuration(int phase)
{
VALIDATE(phase < (int)m_phaseDurations.size());
auto& data = m_phaseDurations.at(phase);
if (data.second == 0) return data.first;
int min = data.first;
int max = min + data.second;
return (int)stdext::random_range((long)min, (long)max);
}
void Animator::calculateSynchronous()
{
int totalDuration = 0;
for(int i = 0; i < m_animationPhases; i++)
totalDuration += getPhaseDuration(i);
ticks_t ticks = g_clock.millis();
int elapsedTicks = (int)(ticks % totalDuration);
int totalTime = 0;
for(int i = 0; i < m_animationPhases; i++) {
int duration = getPhaseDuration(i);
if(elapsedTicks >= totalTime && elapsedTicks < totalTime + duration) {
m_phase = i;
m_currentDuration = duration - (elapsedTicks - totalTime);
break;
}
totalTime += duration;
}
m_lastPhaseTicks = ticks;
}
ticks_t Animator::getTotalDuration()
{
ticks_t time = 0;
for (const auto &pair: m_phaseDurations) {
time += pair.first + pair.second;
}
return time;
}

View File

@ -1,87 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef ANIMATOR_H
#define ANIMATOR_H
#include "declarations.h"
#include <framework/core/declarations.h>
#include <framework/core/timer.h>
enum AnimationPhase : int16
{
AnimPhaseAutomatic = -1,
AnimPhaseRandom = 254,
AnimPhaseAsync = 255,
};
enum AnimationDirection : uint8
{
AnimDirForward = 0,
AnimDirBackward = 1
};
class Animator : public stdext::shared_object
{
public:
Animator();
void unserialize(int animationPhases, const FileStreamPtr& fin);
void serialize(const FileStreamPtr& fin);
void setPhase(int phase);
int getPhase();
int getPhaseAt(Timer& timer, int lastPhase = 0);
int getStartPhase();
int getAnimationPhases() { return m_animationPhases; }
bool isAsync() { return m_async; }
bool isComplete() { return m_isComplete; }
ticks_t getTotalDuration();
void resetAnimation();
private:
int getPingPongPhase();
int getLoopPhase();
int getPhaseDuration(int phase);
void calculateSynchronous();
int m_animationPhases;
int m_startPhase;
int m_loopCount;
bool m_async;
std::vector< std::pair<int, int> > m_phaseDurations;
int m_currentDuration;
AnimationDirection m_currentDirection;
int m_currentLoop;
ticks_t m_lastPhaseTicks;
bool m_isComplete;
int m_phase;
};
#endif

View File

@ -1,57 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "client.h"
#include <framework/core/modulemanager.h>
#include <framework/core/resourcemanager.h>
#include <framework/graphics/graphics.h>
#include "game.h"
#include "map.h"
#include "shadermanager.h"
#include "spritemanager.h"
#include "minimap.h"
#include <framework/core/configmanager.h>
Client g_client;
void Client::init(std::vector<std::string>& args)
{
// register needed lua functions
registerLuaFunctions();
g_map.init();
g_minimap.init();
g_game.init();
g_shaders.init();
g_things.init();
}
void Client::terminate()
{
g_creatures.terminate();
g_game.terminate();
g_map.terminate();
g_minimap.terminate();
g_things.terminate();
g_sprites.terminate();
g_shaders.terminate();
}

View File

@ -1,38 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CLIENT_H
#define CLIENT_H
#include "global.h"
class Client
{
public:
void init(std::vector<std::string>& args);
void terminate();
void registerLuaFunctions();
};
extern Client g_client;
#endif

View File

@ -1,614 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CLIENT_CONST_H
#define CLIENT_CONST_H
namespace Otc
{
enum : int {
TILE_PIXELS = 32,
MAX_ELEVATION = 24,
SEA_FLOOR = 7,
MAX_Z = 15,
UNDERGROUND_FLOOR = SEA_FLOOR+1,
AWARE_UNDEGROUND_FLOOR_RANGE = 2,
INVISIBLE_TICKS_PER_FRAME = 500,
INVISIBLE_TICKS_PER_FRAME_FAST = 100,
ITEM_TICKS_PER_FRAME = 500,
ITEM_TICKS_PER_FRAME_FAST = 100,
ANIMATED_TEXT_DURATION = 1000,
STATIC_DURATION_PER_CHARACTER = 60,
MIN_STATIC_TEXT_DURATION = 3000,
MAX_STATIC_TEXT_WIDTH = 200,
MAX_AUTOWALK_STEPS_RETRY = 10,
MAX_AUTOWALK_DIST = 127
};
enum DepthConst {
MAX_DEPTH = 16384 - 2048
};
enum DrawFlags {
DrawGround = 1,
DrawGroundBorders = 2,
DrawOnBottom = 4,
DrawOnTop = 8,
DrawItems = 16,
DrawCreatures = 32,
DrawEffects = 64,
DrawMissiles = 128,
DrawCreaturesInformation = 256,
DrawStaticTexts = 512,
DrawAnimatedTexts = 1024,
DrawAnimations = 2048,
DrawBars = 4096,
DrawNames = 8192,
DrawLights = 16384,
DrawManaBar = 32768,
DontDrawLocalPlayer = 65536,
DrawIcons = 131072,
DrawWalls = DrawOnBottom | DrawOnTop,
DrawEverything = DrawGround | DrawGroundBorders | DrawWalls | DrawItems |
DrawCreatures | DrawEffects | DrawMissiles | DrawCreaturesInformation |
DrawStaticTexts | DrawAnimatedTexts | DrawAnimations | DrawBars | DrawNames |
DrawLights | DrawManaBar | DrawIcons
};
enum DatOpts {
DatGround = 0,
DatGroundClip,
DatOnBottom,
DatOnTop,
DatContainer,
DatStackable,
DatForceUse,
DatMultiUse,
DatWritable,
DatWritableOnce,
DatFluidContainer,
DatSplash,
DatBlockWalk,
DatNotMoveable,
DatBlockProjectile,
DatBlockPathFind,
DatPickupable,
DatHangable,
DatHookSouth,
DatHookEast,
DatRotable,
DatLight,
DatDontHide,
DatTranslucent,
DatDisplacement,
DatElevation,
DatLyingCorpse,
DatAnimateAlways,
DatMinimapColor,
DatLensHelp,
DatFullGround,
DatIgnoreLook,
DatCloth,
DatAnimation, // lastest tibia
DatLastOpt = 255
};
enum InventorySlot {
InventorySlotHead = 1,
InventorySlotNecklace,
InventorySlotBackpack,
InventorySlotArmor,
InventorySlotRight,
InventorySlotLeft,
InventorySlotLegs,
InventorySlotFeet,
InventorySlotRing,
InventorySlotAmmo,
InventorySlotPurse,
InventorySlotExt1,
InventorySlotExt2,
InventorySlotExt3,
InventorySlotExt4,
LastInventorySlot
};
enum Statistic {
Health = 0,
MaxHealth,
FreeCapacity,
Experience,
Level,
LevelPercent,
Mana,
MaxMana,
MagicLevel,
MagicLevelPercent,
Soul,
Stamina,
LastStatistic
};
enum Skill {
Fist = 0,
Club,
Sword,
Axe,
Distance,
Shielding,
Fishing,
CriticalChance,
CriticalDamage,
LifeLeechChance,
LifeLeechAmount,
ManaLeechChance,
ManaLeechAmount,
LastSkill
};
enum Direction {
North = 0,
East,
South,
West,
NorthEast,
SouthEast,
SouthWest,
NorthWest,
InvalidDirection
};
enum FluidsColor {
FluidTransparent = 0,
FluidBlue,
FluidRed,
FluidBrown,
FluidGreen,
FluidYellow,
FluidWhite,
FluidPurple
};
enum FluidsType {
FluidNone = 0,
FluidWater,
FluidMana,
FluidBeer,
FluidOil,
FluidBlood,
FluidSlime,
FluidMud,
FluidLemonade,
FluidMilk,
FluidWine,
FluidHealth,
FluidUrine,
FluidRum,
FluidFruidJuice,
FluidCoconutMilk,
FluidTea,
FluidMead
};
enum FightModes {
FightOffensive = 1,
FightBalanced = 2,
FightDefensive = 3
};
enum ChaseModes {
DontChase = 0,
ChaseOpponent = 1
};
enum PVPModes {
WhiteDove = 0,
WhiteHand = 1,
YellowHand = 2,
RedFist = 3
};
enum PlayerSkulls {
SkullNone = 0,
SkullYellow,
SkullGreen,
SkullWhite,
SkullRed,
SkullBlack,
SkullOrange
};
enum PlayerShields {
ShieldNone = 0,
ShieldWhiteYellow, // 1 party leader
ShieldWhiteBlue, // 2 party member
ShieldBlue, // 3 party member sexp off
ShieldYellow, // 4 party leader sexp off
ShieldBlueSharedExp, // 5 party member sexp on
ShieldYellowSharedExp, // 6 // party leader sexp on
ShieldBlueNoSharedExpBlink, // 7 party member sexp inactive guilty
ShieldYellowNoSharedExpBlink, // 8 // party leader sexp inactive guilty
ShieldBlueNoSharedExp, // 9 party member sexp inactive innocent
ShieldYellowNoSharedExp, // 10 party leader sexp inactive innocent
ShieldGray // 11 member of another party
};
enum PlayerEmblems {
EmblemNone = 0,
EmblemGreen,
EmblemRed,
EmblemBlue,
EmblemMember,
EmblemOther
};
enum CreatureIcons {
NpcIconNone = 0,
NpcIconChat,
NpcIconTrade,
NpcIconQuest,
NpcIconTradeQuest
};
enum PlayerStates {
IconNone = 0,
IconPoison = 1,
IconBurn = 2,
IconEnergy = 4,
IconDrunk = 8,
IconManaShield = 16,
IconParalyze = 32,
IconHaste = 64,
IconSwords = 128,
IconDrowning = 256,
IconFreezing = 512,
IconDazzled = 1024,
IconCursed = 2048,
IconPartyBuff = 4096,
IconPzBlock = 8192,
IconPz = 16384,
IconBleeding = 32768,
IconHungry = 65536
};
enum MessageMode {
MessageNone = 0,
MessageSay = 1,
MessageWhisper = 2,
MessageYell = 3,
MessagePrivateFrom = 4,
MessagePrivateTo = 5,
MessageChannelManagement = 6,
MessageChannel = 7,
MessageChannelHighlight = 8,
MessageSpell = 9,
MessageNpcFrom = 10,
MessageNpcTo = 11,
MessageGamemasterBroadcast = 12,
MessageGamemasterChannel = 13,
MessageGamemasterPrivateFrom = 14,
MessageGamemasterPrivateTo = 15,
MessageLogin = 16,
MessageWarning = 17,
MessageGame = 18,
MessageFailure = 19,
MessageLook = 20,
MessageDamageDealed = 21,
MessageDamageReceived = 22,
MessageHeal = 23,
MessageExp = 24,
MessageDamageOthers = 25,
MessageHealOthers = 26,
MessageExpOthers = 27,
MessageStatus = 28,
MessageLoot = 29,
MessageTradeNpc = 30,
MessageGuild = 31,
MessagePartyManagement = 32,
MessageParty = 33,
MessageBarkLow = 34,
MessageBarkLoud = 35,
MessageReport = 36,
MessageHotkeyUse = 37,
MessageTutorialHint = 38,
MessageThankyou = 39,
MessageMarket = 40,
MessageMana = 41,
MessageBeyondLast = 42,
// deprecated
MessageMonsterYell = 43,
MessageMonsterSay = 44,
MessageRed = 45,
MessageBlue = 46,
MessageRVRChannel = 47,
MessageRVRAnswer = 48,
MessageRVRContinue = 49,
MessageGameHighlight = 50,
MessageNpcFromStartBlock = 51,
LastMessage = 52,
MessageInvalid = 255
};
enum GameFeature {
GameProtocolChecksum = 1,
GameAccountNames = 2,
GameChallengeOnLogin = 3,
GamePenalityOnDeath = 4,
GameNameOnNpcTrade = 5,
GameDoubleFreeCapacity = 6,
GameDoubleExperience = 7,
GameTotalCapacity = 8,
GameSkillsBase = 9,
GamePlayerRegenerationTime = 10,
GameChannelPlayerList = 11,
GamePlayerMounts = 12,
GameEnvironmentEffect = 13,
GameCreatureEmblems = 14,
GameItemAnimationPhase = 15,
GameMagicEffectU16 = 16,
GamePlayerMarket = 17,
GameSpritesU32 = 18,
GameTileAddThingWithStackpos = 19,
GameOfflineTrainingTime = 20,
GamePurseSlot = 21,
GameFormatCreatureName = 22,
GameSpellList = 23,
GameClientPing = 24,
GameExtendedClientPing = 25,
GameDoubleHealth = 28,
GameDoubleSkills = 29,
GameChangeMapAwareRange = 30,
GameMapMovePosition = 31,
GameAttackSeq = 32,
GameBlueNpcNameColor = 33,
GameDiagonalAnimatedText = 34,
GameLoginPending = 35,
GameNewSpeedLaw = 36,
GameForceFirstAutoWalkStep = 37,
GameMinimapRemove = 38,
GameDoubleShopSellAmount = 39,
GameContainerPagination = 40,
GameThingMarks = 41,
GameLooktypeU16 = 42,
GamePlayerStamina = 43,
GamePlayerAddons = 44,
GameMessageStatements = 45,
GameMessageLevel = 46,
GameNewFluids = 47,
GamePlayerStateU16 = 48,
GameNewOutfitProtocol = 49,
GamePVPMode = 50,
GameWritableDate = 51,
GameAdditionalVipInfo = 52,
GameBaseSkillU16 = 53,
GameCreatureIcons = 54,
GameHideNpcNames = 55,
GameSpritesAlphaChannel = 56,
GamePremiumExpiration = 57,
GameBrowseField = 58,
GameEnhancedAnimations = 59,
GameOGLInformation = 60,
GameMessageSizeCheck = 61,
GamePreviewState = 62,
GameLoginPacketEncryption = 63,
GameClientVersion = 64,
GameContentRevision = 65,
GameExperienceBonus = 66,
GameAuthenticator = 67,
GameUnjustifiedPoints = 68,
GameSessionKey = 69,
GameDeathType = 70,
GameIdleAnimations = 71,
GameKeepUnawareTiles = 72,
GameIngameStore = 73,
GameIngameStoreHighlights = 74,
GameIngameStoreServiceType = 75,
GameAdditionalSkills = 76,
GameDistanceEffectU16 = 77,
GamePrey = 78,
GameDoubleMagicLevel = 79,
GameExtendedOpcode = 80,
GameMinimapLimitedToSingleFloor = 81,
GameDoubleLevel = 83,
GameDoubleSoul = 84,
GameDoublePlayerGoodsMoney = 85,
GameCreatureWalkthrough = 86,
GameDoubleTradeMoney = 87,
// 90-99 otclientv8 features
GameNewWalking = 90,
GameSlowerManualWalking = 91,
GameItemTooltip = 93,
GameBot = 95,
GameBiggerMapCache = 96,
GameForceLight = 97,
GameNoDebug = 98,
GameBotProtection = 99,
// Custom features for customer
GameFasterAnimations = 101,
GameCenteredOutfits = 102,
GameSendIdentifiers = 103,
GameWingsAndAura = 104,
// advanced features
GamePacketSizeU32 = 110,
GamePacketCompression = 111,
LastGameFeature = 120
};
enum PathFindResult {
PathFindResultOk = 0,
PathFindResultSamePosition,
PathFindResultImpossible,
PathFindResultTooFar,
PathFindResultNoWay
};
enum PathFindFlags {
PathFindAllowNotSeenTiles = 1,
PathFindAllowCreatures = 2,
PathFindAllowNonPathable = 4,
PathFindAllowNonWalkable = 8,
PathFindIgnoreCreatures = 16
};
enum AutomapFlags {
MapMarkTick = 0,
MapMarkQuestion,
MapMarkExclamation,
MapMarkStar,
MapMarkCross,
MapMarkTemple,
MapMarkKiss,
MapMarkShovel,
MapMarkSword,
MapMarkFlag,
MapMarkLock,
MapMarkBag,
MapMarkSkull,
MapMarkDollar,
MapMarkRedNorth,
MapMarkRedSouth,
MapMarkRedEast,
MapMarkRedWest,
MapMarkGreenNorth,
MapMarkGreenSouth
};
enum VipState {
VipStateOffline = 0,
VipStateOnline = 1,
VipStatePending = 2
};
enum SpeedFormula {
SpeedFormulaA = 0,
SpeedFormulaB,
SpeedFormulaC,
LastSpeedFormula
};
enum Blessings {
BlessingNone = 0,
BlessingAdventurer = 1,
BlessingSpiritualShielding = 1 << 1,
BlessingEmbraceOfTibia = 1 << 2,
BlessingFireOfSuns = 1 << 3,
BlessingWisdomOfSolitude = 1 << 4,
BlessingSparkOfPhoenix = 1 << 5
};
enum DeathType {
DeathRegular = 0,
DeathBlessed = 1
};
enum StoreProductTypes {
ProductTypeOther = 0,
ProductTypeNameChange = 1
};
enum StoreErrorTypes {
StoreNoError = -1,
StorePurchaseError = 0,
StoreNetworkError = 1,
StoreHistoryError = 2,
StoreTransferError = 3,
StoreInformation = 4
};
enum StoreStates {
StateNone = 0,
StateNew = 1,
StateSale = 2,
StateTimed = 3
};
enum PreySlotNum_t : uint8_t {
PREY_SLOTNUM_FIRST,
PREY_SLOTNUM_SECOND,
PREY_SLOTNUM_THIRD,
PREY_SLOTNUM_LAST = PREY_SLOTNUM_THIRD
};
enum PreyState_t : uint8_t {
PREY_STATE_LOCKED = 0,
PREY_STATE_INACTIVE = 1,
PREY_STATE_ACTIVE = 2,
PREY_STATE_SELECTION = 3,
PREY_STATE_SELECTION_CHANGE_MONSTER = 4, // unused; hmm
PREY_STATE_SELECTION_FROMALL = 5,
PREY_STATE_CHANGE_FROMALL = 6, // unused :(
};
enum PreyMessageDialog_t : uint8_t {
//PREY_MESSAGEDIALOG_IMBUEMENT_SUCCESS = 0,
//PREY_MESSAGEDIALOG_IMBUEMENT_ERROR = 1,
//PREY_MESSAGEDIALOG_IMBUEMENT_ROLL_FAILED = 2,
//PREY_MESSAGEDIALOG_IMBUEMENT_STATION_NOT_FOUND = 3,
//PREY_MESSAGEDIALOG_IMBUEMENT_CHARM_SUCCESS = 10,
//PREY_MESSAGEDIALOG_IMBUEMENT_CHARM_ERROR = 11,
PREY_MESSAGEDIALOG_PREY_MESSAGE = 20,
PREY_MESSAGEDIALOG_PREY_ERROR = 21,
};
enum PreyResourceType_t : uint8_t {
PREY_RESOURCETYPE_BANK_GOLD = 0,
PREY_RESOURCETYPE_INVENTORY_GOLD = 1,
PREY_RESOURCETYPE_PREY_BONUS_REROLLS = 10
};
enum PreyBonusType_t : uint8_t {
PREY_BONUS_DAMAGE_BOOST = 0,
PREY_BONUS_DAMAGE_REDUCTION = 1,
PREY_BONUS_XP_BONUS = 2,
PREY_BONUS_IMPROVED_LOOT = 3,
PREY_BONUS_NONE = 4, // internal usage but still added to client;
PREY_BONUS_FIRST = PREY_BONUS_DAMAGE_BOOST,
PREY_BONUS_LAST = PREY_BONUS_IMPROVED_LOOT,
};
enum PreyAction_t : uint8_t {
PREY_ACTION_LISTREROLL = 0,
PREY_ACTION_BONUSREROLL = 1,
PREY_ACTION_MONSTERSELECTION = 2,
PREY_ACTION_REQUEST_ALL_MONSTERS = 3,
PREY_ACTION_CHANGE_FROM_ALL = 4,
PREY_ACTION_LOCK_PREY = 5,
};
enum PreyConfigState {
PREY_CONFIG_STATE_FREE,
PREY_CONFIG_STATE_PREMIUM,
PREY_CONFIG_STATE_TIBIACOINS
};
enum PreyUnlockState_t : uint8_t {
PREY_UNLOCK_STORE_AND_PREMIUM = 0,
PREY_UNLOCK_STORE = 1,
PREY_UNLOCK_NONE = 2,
};
}
#endif

View File

@ -1,143 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "container.h"
#include "item.h"
Container::Container(int id, int capacity, const std::string& name, const ItemPtr& containerItem, bool hasParent, bool isUnlocked, bool hasPages, int containerSize, int firstIndex)
{
m_id = id;
m_capacity = capacity;
m_name = name;
m_containerItem = containerItem;
m_hasParent = hasParent;
m_closed = false;
m_unlocked = isUnlocked;
m_hasPages = hasPages;
m_size = containerSize;
m_firstIndex = firstIndex;
}
ItemPtr Container::getItem(int slot)
{
if(slot < 0 || slot >= (int)m_items.size())
return nullptr;
return m_items[slot];
}
void Container::onOpen(const ContainerPtr& previousContainer)
{
callLuaField("onOpen", previousContainer);
}
void Container::onClose()
{
m_closed = true;
callLuaField("onClose");
}
void Container::onAddItem(const ItemPtr& item, int slot)
{
slot -= m_firstIndex;
m_size++;
// indicates that there is a new item on next page
if(m_hasPages && slot > m_capacity) {
callLuaField("onSizeChange", m_size);
return;
}
if(slot == 0)
m_items.push_front(item);
else
m_items.push_back(item);
updateItemsPositions();
callLuaField("onSizeChange", m_size);
callLuaField("onAddItem", slot, item);
}
ItemPtr Container::findItemById(uint itemId, int subType)
{
for(const ItemPtr item : m_items)
if(item->getId() == itemId && (subType == -1 || item->getSubType() == subType))
return item;
return nullptr;
}
void Container::onAddItems(const std::vector<ItemPtr>& items)
{
for(const ItemPtr& item : items)
m_items.push_back(item);
updateItemsPositions();
}
void Container::onUpdateItem(int slot, const ItemPtr& item)
{
slot -= m_firstIndex;
if(slot < 0 || slot >= (int)m_items.size()) {
g_logger.traceError("slot not found");
return;
}
ItemPtr oldItem = m_items[slot];
m_items[slot] = item;
item->setPosition(getSlotPosition(slot));
callLuaField("onUpdateItem", slot, item, oldItem);
}
void Container::onRemoveItem(int slot, const ItemPtr& lastItem)
{
slot -= m_firstIndex;
if(m_hasPages && slot >= (int)m_items.size()) {
m_size--;
callLuaField("onSizeChange", m_size);
return;
}
if(slot < 0 || slot >= (int)m_items.size()) {
g_logger.traceError("slot not found");
return;
}
ItemPtr item = m_items[slot];
m_items.erase(m_items.begin() + slot);
if(lastItem) {
onAddItem(lastItem, m_firstIndex + m_capacity - 1);
m_size--;
}
m_size--;
updateItemsPositions();
callLuaField("onSizeChange", m_size);
callLuaField("onRemoveItem", slot, item);
}
void Container::updateItemsPositions()
{
for(int slot = 0; slot < (int)m_items.size(); ++slot)
m_items[slot]->setPosition(getSlotPosition(slot));
}

View File

@ -1,80 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CONTAINER_H
#define CONTAINER_H
#include "declarations.h"
#include "item.h"
#include <framework/luaengine/luaobject.h>
// @bindclass
class Container : public LuaObject
{
protected:
Container(int id, int capacity, const std::string& name, const ItemPtr& containerItem, bool hasParent, bool isUnlocked, bool hasPages, int containerSize, int firstIndex);
public:
ItemPtr getItem(int slot);
std::deque<ItemPtr> getItems() { return m_items; }
int getItemsCount() { return m_items.size(); }
Position getSlotPosition(int slot) { return Position(0xffff, m_id | 0x40, slot); }
int getId() { return m_id; }
int getCapacity() { return m_capacity; }
ItemPtr getContainerItem() { return m_containerItem; }
std::string getName() { return m_name; }
bool hasParent() { return m_hasParent; }
bool isClosed() { return m_closed; }
bool isUnlocked() { return m_unlocked; }
bool hasPages() { return m_hasPages; }
int getSize() { return m_size; }
int getFirstIndex() { return m_firstIndex; }
ItemPtr findItemById(uint itemId, int subType);
protected:
void onOpen(const ContainerPtr& previousContainer);
void onClose();
void onAddItem(const ItemPtr& item, int slot);
void onAddItems(const std::vector<ItemPtr>& items);
void onUpdateItem(int slot, const ItemPtr& item);
void onRemoveItem(int slot, const ItemPtr& lastItem);
friend class Game;
private:
void updateItemsPositions();
int m_id;
int m_capacity;
ItemPtr m_containerItem;
std::string m_name;
bool m_hasParent;
bool m_closed;
bool m_unlocked;
bool m_hasPages;
int m_size;
int m_firstIndex;
std::deque<ItemPtr> m_items;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,298 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CREATURE_H
#define CREATURE_H
#include "thing.h"
#include "outfit.h"
#include "tile.h"
#include "mapview.h"
#include <framework/core/scheduledevent.h>
#include <framework/core/declarations.h>
#include <framework/core/timer.h>
#include <framework/graphics/fontmanager.h>
#include <framework/graphics/cachedtext.h>
#include <framework/ui/uiwidget.h>
// @bindclass
class Creature : public Thing
{
public:
enum {
SHIELD_BLINK_TICKS = 500,
VOLATILE_SQUARE_DURATION = 1000
};
Creature();
virtual ~Creature();
virtual void draw(const Point& dest, bool animate = true, LightView* lightView = nullptr);
virtual void drawOutfit(const Rect& destRect, Otc::Direction direction = Otc::InvalidDirection, const Color& color = Color::white);
void drawInformation(const Point& point, bool useGray, const Rect& parentRect, int drawFlags);
bool isInsideOffset(Point offset);
void setId(uint32 id) { m_id = id; }
void setName(const std::string& name);
void setManaPercent(int8 value) { m_manaPercent = value; }
void setHealthPercent(uint8 healthPercent);
void setDirection(Otc::Direction direction);
void setOutfit(const Outfit& outfit);
void setOutfitColor(const Color& color, int duration);
void setLight(const Light& light) { m_light = light; }
void setSpeed(uint16 speed);
void setBaseSpeed(double baseSpeed);
void setSkull(uint8 skull);
void setShield(uint8 shield);
void setEmblem(uint8 emblem);
void setType(uint8 type);
void setIcon(uint8 icon);
void setSkullTexture(const std::string& filename);
void setShieldTexture(const std::string& filename, bool blink);
void setEmblemTexture(const std::string& filename);
void setTypeTexture(const std::string& filename);
void setIconTexture(const std::string& filename);
void setPassable(bool passable) { m_passable = passable; }
void setSpeedFormula(double speedA, double speedB, double speedC);
void addTimedSquare(uint8 color);
void removeTimedSquare() { m_showTimedSquare = false; }
void showStaticSquare(const Color& color) { m_showStaticSquare = true; m_staticSquareColor = color; }
void hideStaticSquare() { m_showStaticSquare = false; }
void setInformationColor(const Color& color) { m_useCustomInformationColor = true; m_informationColor = color; }
void resetInformationColor() { m_useCustomInformationColor = false; }
Point getInformationOffset() { return m_informationOffset; }
void setInformationOffset(int x, int y) { m_informationOffset = Point(x, y); }
void setText(const std::string& text, const Color& color);
std::string getText();
void clearText() { setText("", Color::white); }
uint32 getId() { return m_id; }
std::string getName() { return m_name; }
uint8 getHealthPercent() { return m_healthPercent; }
int8 getManaPercent() { return m_manaPercent; }
Otc::Direction getDirection() { return m_direction; }
Otc::Direction getWalkDirection() { return m_walkDirection; }
Outfit getOutfit() { return m_outfit; }
Light getLight() { return m_light; }
uint16 getSpeed() { return m_speed; }
double getBaseSpeed() { return m_baseSpeed; }
uint8 getSkull() { return m_skull; }
uint8 getShield() { return m_shield; }
uint8 getEmblem() { return m_emblem; }
uint8 getType() { return m_type; }
uint8 getIcon() { return m_icon; }
bool isPassable() { return m_passable; }
Point getDrawOffset();
int getStepDuration(bool ignoreDiagonal = false, Otc::Direction dir = Otc::InvalidDirection);
Point getWalkOffset(bool inNextFrame = false) { return inNextFrame ? m_walkOffsetInNextFrame : m_walkOffset; }
Position getLastStepFromPosition() { return m_lastStepFromPosition; }
Position getLastStepToPosition() { return m_lastStepToPosition; }
float getStepProgress() { return m_walkTimer.ticksElapsed() / getStepDuration(); }
int getStepTicksLeft() { return getStepDuration() - m_walkTimer.ticksElapsed(); }
ticks_t getWalkTicksElapsed() { return m_walkTimer.ticksElapsed(); }
double getSpeedFormula(Otc::SpeedFormula formula) { return m_speedFormula[formula]; }
bool hasSpeedFormula();
std::array<double, Otc::LastSpeedFormula> getSpeedFormulaArray() { return m_speedFormula; }
virtual Point getDisplacement();
virtual int getDisplacementX();
virtual int getDisplacementY();
virtual int getExactSize(int layer = 0, int xPattern = 0, int yPattern = 0, int zPattern = 0, int animationPhase = 0);
PointF getJumpOffset() { return m_jumpOffset; }
void updateShield();
// walk related
int getWalkAnimationPhases();
virtual void turn(Otc::Direction direction);
void jump(int height, int duration);
virtual void walk(const Position& oldPos, const Position& newPos);
virtual void stopWalk();
void allowAppearWalk(uint16_t stepSpeed) { m_allowAppearWalk = true; m_stepDuration = stepSpeed; }
bool isWalking() { return m_walking; }
bool isRemoved() { return m_removed; }
bool isInvisible() { return m_outfit.getCategory() == ThingCategoryEffect && m_outfit.getAuxId() == 13; }
bool isDead() { return m_healthPercent <= 0; }
bool canBeSeen() { return !isInvisible() || isPlayer(); }
bool isCreature() { return true; }
bool canShoot(int distance);
const ThingTypePtr& getThingType();
ThingType *rawGetThingType();
virtual void onPositionChange(const Position& newPos, const Position& oldPos);
virtual void onAppear();
virtual void onDisappear();
virtual void onDeath();
virtual bool isPreWalking() { return false; }
virtual Position getPrewalkingPosition(bool beforePrewalk = false) { return m_position; }
TilePtr getWalkingTileOrTile() {
return m_walkingTile ? m_walkingTile : getTile();
}
virtual bool isServerWalking() { return true; }
void setElevation(uint8 elevation) {
m_elevation = elevation;
}
uint8 getElevation() {
return m_elevation;
}
// widgets
void addTopWidget(const UIWidgetPtr& widget);
void addBottomWidget(const UIWidgetPtr& widget);
void addDirectionalWidget(const UIWidgetPtr& widget);
void removeTopWidget(const UIWidgetPtr& widget);
void removeBottomWidget(const UIWidgetPtr& widget);
void removeDirectionalWidget(const UIWidgetPtr& widget);
std::list<UIWidgetPtr> getTopWidgets();
std::list<UIWidgetPtr> getBottomWidgets();
std::list<UIWidgetPtr> getDirectionalWdigets();
void clearWidgets();
void clearTopWidgets();
void clearBottomWidgets();
void clearDirectionalWidgets();
void drawTopWidgets(const Point& rect, const Otc::Direction direction);
void drawBottomWidgets(const Point& rect, const Otc::Direction direction);
// progress bar
uint8 getProgressBarPercent() { return m_progressBarPercent; }
void setProgressBar(uint32 duration, bool ltr);
void updateProgressBar(uint32 duration, bool ltr);
protected:
virtual void updateWalkAnimation(int totalPixelsWalked);
virtual void updateWalkOffset(int totalPixelsWalked, bool inNextFrame = false);
void updateWalkingTile();
virtual void nextWalkUpdate();
virtual void updateWalk();
virtual void terminateWalk();
void updateOutfitColor(Color color, Color finalColor, Color delta, int duration);
void updateJump();
uint32 m_id;
std::string m_name;
uint8 m_healthPercent;
int8 m_manaPercent;
Otc::Direction m_direction;
Otc::Direction m_walkDirection;
Outfit m_outfit;
Light m_light;
int m_speed;
double m_baseSpeed;
uint8 m_skull;
uint8 m_shield;
uint8 m_emblem;
uint8 m_type;
uint8 m_icon;
TexturePtr m_skullTexture;
TexturePtr m_shieldTexture;
TexturePtr m_emblemTexture;
TexturePtr m_typeTexture;
TexturePtr m_iconTexture;
stdext::boolean<true> m_showShieldTexture;
stdext::boolean<false> m_shieldBlink;
stdext::boolean<false> m_passable;
Color m_timedSquareColor;
Color m_staticSquareColor;
Color m_nameColor;
stdext::boolean<false> m_showTimedSquare;
stdext::boolean<false> m_showStaticSquare;
stdext::boolean<true> m_removed;
CachedText m_nameCache;
Color m_informationColor;
bool m_useCustomInformationColor = false;
Point m_informationOffset;
Color m_outfitColor;
ScheduledEventPtr m_outfitColorUpdateEvent;
Timer m_outfitColorTimer;
static std::array<double, Otc::LastSpeedFormula> m_speedFormula;
// walk related
int m_walkAnimationPhase;
int m_walkedPixels;
uint m_footStep;
Timer m_walkTimer;
ticks_t m_footLastStep;
TilePtr m_walkingTile;
stdext::boolean<false> m_walking;
stdext::boolean<false> m_allowAppearWalk;
ScheduledEventPtr m_walkUpdateEvent;
ScheduledEventPtr m_walkFinishAnimEvent;
EventPtr m_disappearEvent;
Point m_walkOffset;
Point m_walkOffsetInNextFrame;
Otc::Direction m_lastStepDirection;
Position m_lastStepFromPosition;
Position m_lastStepToPosition;
Position m_oldPosition;
uint8 m_elevation = 0;
uint16 m_stepDuration = 0;
// jump related
float m_jumpHeight = 0;
float m_jumpDuration = 0;
PointF m_jumpOffset;
Timer m_jumpTimer;
// for bot
StaticTextPtr m_text;
// widgets
std::list<UIWidgetPtr> m_bottomWidgets;
std::list<UIWidgetPtr> m_directionalWidgets;
std::list<UIWidgetPtr> m_topWidgets;
// progress bar
uint8 m_progressBarPercent;
ScheduledEventPtr m_progressBarUpdateEvent;
Timer m_progressBarTimer;
};
// @bindclass
class Npc : public Creature
{
public:
bool isNpc() { return true; }
};
// @bindclass
class Monster : public Creature
{
public:
bool isMonster() { return true; }
};
#endif

View File

@ -1,426 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "creatures.h"
#include "creature.h"
#include "map.h"
#include <framework/xml/tinyxml.h>
#include <framework/core/resourcemanager.h>
CreatureManager g_creatures;
static bool isInZone(const Position& pos/* placePos*/,
const Position& centerPos,
int radius)
{
if(radius == -1)
return true;
return ((pos.x >= centerPos.x - radius) && (pos.x <= centerPos.x + radius) &&
(pos.y >= centerPos.y - radius) && (pos.y <= centerPos.y + radius)
);
}
void CreatureManager::terminate()
{
clearSpawns();
clear();
m_nullCreature = nullptr;
}
void Spawn::load(TiXmlElement* node)
{
Position centerPos;
centerPos.x = node->readType<int>("centerx");
centerPos.y = node->readType<int>("centery");
centerPos.z = node->readType<int>("centerz");
setCenterPos(centerPos);
setRadius(node->readType<int32>("radius"));
CreatureTypePtr cType(nullptr);
for(TiXmlElement* cNode = node->FirstChildElement(); cNode; cNode = cNode->NextSiblingElement()) {
if(cNode->ValueStr() != "monster" && cNode->ValueStr() != "npc")
stdext::throw_exception(stdext::format("invalid spawn-subnode %s", cNode->ValueStr()));
std::string cName = cNode->Attribute("name");
stdext::tolower(cName);
stdext::trim(cName);
stdext::ucwords(cName);
if (!(cType = g_creatures.getCreatureByName(cName)))
continue;
cType->setSpawnTime(cNode->readType<int>("spawntime"));
Otc::Direction dir = Otc::North;
int16 dir_ = cNode->readType<int16>("direction");
if(dir_ >= Otc::East && dir_ <= Otc::West)
dir = (Otc::Direction)dir_;
cType->setDirection(dir);
Position placePos;
placePos.x = centerPos.x + cNode->readType<int>("x");
placePos.y = centerPos.y + cNode->readType<int>("y");
placePos.z = cNode->readType<int>("z");
cType->setRace(cNode->ValueStr() == "npc" ? CreatureRaceNpc : CreatureRaceMonster);
addCreature(placePos, cType);
}
}
void Spawn::save(TiXmlElement* node)
{
const Position& c = getCenterPos();
node->SetAttribute("centerx", c.x);
node->SetAttribute("centery", c.y);
node->SetAttribute("centerz", c.z);
node->SetAttribute("radius", getRadius());
TiXmlElement* creatureNode = nullptr;
for(const auto& pair : m_creatures) {
const CreatureTypePtr& creature = pair.second;
if(!(creatureNode = new TiXmlElement(creature->getRace() == CreatureRaceNpc ? "npc" : "monster")))
stdext::throw_exception("Spawn::save: Ran out of memory while allocating XML element! Terminating now.");
creatureNode->SetAttribute("name", creature->getName());
creatureNode->SetAttribute("spawntime", creature->getSpawnTime());
creatureNode->SetAttribute("direction", creature->getDirection());
const Position& placePos = pair.first;
VALIDATE(placePos.isValid());
creatureNode->SetAttribute("x", placePos.x - c.x);
creatureNode->SetAttribute("y", placePos.y - c.y);
creatureNode->SetAttribute("z", placePos.z);
node->LinkEndChild(creatureNode);
}
}
void Spawn::addCreature(const Position& placePos, const CreatureTypePtr& cType)
{
const Position& centerPos = getCenterPos();
int m_radius = getRadius();
if(!isInZone(placePos, centerPos, m_radius)) {
g_logger.warning(stdext::format("cannot place creature at %s (spawn's center position: %s, spawn radius: %d) (increment radius)",
stdext::to_string(placePos), stdext::to_string(centerPos),
m_radius
));
return;
}
g_map.addThing(cType->cast(), placePos, 4);
m_creatures.insert(std::make_pair(placePos, cType));
}
void Spawn::removeCreature(const Position& pos)
{
auto iterator = m_creatures.find(pos);
if(iterator != m_creatures.end()) {
VALIDATE(iterator->first.isValid());
VALIDATE(g_map.removeThingByPos(iterator->first, 4));
m_creatures.erase(iterator);
}
}
std::vector<CreatureTypePtr> Spawn::getCreatures()
{
std::vector<CreatureTypePtr> creatures;
for (auto p : m_creatures)
creatures.push_back(p.second);
return creatures;
}
CreaturePtr CreatureType::cast()
{
CreaturePtr ret(new Creature);
std::string cName = getName();
stdext::tolower(cName);
stdext::trim(cName);
stdext::ucwords(cName);
ret->setName(cName);
ret->setDirection(getDirection());
ret->setOutfit(getOutfit());
return ret;
}
CreatureManager::CreatureManager()
{
m_nullCreature = CreatureTypePtr(new CreatureType);
}
void CreatureManager::clearSpawns()
{
for(auto pair : m_spawns)
pair.second->clear();
m_spawns.clear();
}
void CreatureManager::loadMonsters(const std::string& file)
{
TiXmlDocument doc;
doc.Parse(g_resources.readFileContents(file).c_str());
if(doc.Error())
stdext::throw_exception(stdext::format("cannot open monsters file '%s': '%s'", file, doc.ErrorDesc()));
TiXmlElement* root = doc.FirstChildElement();
if(!root || root->ValueStr() != "monsters")
stdext::throw_exception("malformed monsters xml file");
for(TiXmlElement* monster = root->FirstChildElement(); monster; monster = monster->NextSiblingElement()) {
std::string fname = file.substr(0, file.find_last_of('/')) + '/' + monster->Attribute("file");
if(fname.substr(fname.length() - 4) != ".xml")
fname += ".xml";
loadSingleCreature(fname);
}
doc.Clear();
m_loaded = true;
}
void CreatureManager::loadSingleCreature(const std::string& file)
{
loadCreatureBuffer(g_resources.readFileContents(file));
}
void CreatureManager::loadNpcs(const std::string& folder)
{
std::string tmp = folder;
if(!stdext::ends_with(tmp, "/"))
tmp += "/";
if(!g_resources.directoryExists(tmp))
stdext::throw_exception(stdext::format("NPCs folder '%s' was not found.", folder));
const auto& fileList = g_resources.listDirectoryFiles(tmp);
for(const std::string& file : fileList)
loadCreatureBuffer(g_resources.readFileContents(tmp + file));
}
void CreatureManager::loadSpawns(const std::string& fileName)
{
if(!isLoaded()) {
g_logger.warning("creatures aren't loaded yet to load spawns.");
return;
}
if(m_spawnLoaded) {
g_logger.warning("attempt to reload spawns.");
return;
}
try {
TiXmlDocument doc;
doc.Parse(g_resources.readFileContents(fileName).c_str());
if(doc.Error())
stdext::throw_exception(stdext::format("cannot load spawns xml file '%s: '%s'", fileName, doc.ErrorDesc()));
TiXmlElement* root = doc.FirstChildElement();
if(!root || root->ValueStr() != "spawns")
stdext::throw_exception("malformed spawns file");
for(TiXmlElement* node = root->FirstChildElement(); node; node = node->NextSiblingElement()) {
if(node->ValueTStr() != "spawn")
stdext::throw_exception("invalid spawn node");
SpawnPtr spawn(new Spawn);
spawn->load(node);
m_spawns.insert(std::make_pair(spawn->getCenterPos(), spawn));
}
doc.Clear();
m_spawnLoaded = true;
} catch(std::exception& e) {
g_logger.error(stdext::format("Failed to load '%s': %s", fileName, e.what()));
}
}
void CreatureManager::saveSpawns(const std::string& fileName)
{
try {
TiXmlDocument doc;
doc.SetTabSize(2);
TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "UTF-8", "");
doc.LinkEndChild(decl);
TiXmlElement* root = new TiXmlElement("spawns");
doc.LinkEndChild(root);
for(auto pair : m_spawns) {
TiXmlElement* elem = new TiXmlElement("spawn");
pair.second->save(elem);
root->LinkEndChild(elem);
}
if(!doc.SaveFile("data"+fileName))
stdext::throw_exception(stdext::format("failed to save spawns XML %s: %s", fileName, doc.ErrorDesc()));
} catch(std::exception& e) {
g_logger.error(stdext::format("Failed to save '%s': %s", fileName, e.what()));
}
}
void CreatureManager::loadCreatureBuffer(const std::string& buffer)
{
TiXmlDocument doc;
doc.Parse(buffer.c_str());
if(doc.Error())
stdext::throw_exception(stdext::format("cannot load creature buffer: %s", doc.ErrorDesc()));
TiXmlElement* root = doc.FirstChildElement();
if(!root || (root->ValueStr() != "monster" && root->ValueStr() != "npc"))
stdext::throw_exception("invalid root tag name");
std::string cName = root->Attribute("name");
stdext::tolower(cName);
stdext::trim(cName);
stdext::ucwords(cName);
CreatureTypePtr newType(new CreatureType(cName));
for(TiXmlElement* attrib = root->FirstChildElement(); attrib; attrib = attrib->NextSiblingElement()) {
if(attrib->ValueStr() != "look")
continue;
internalLoadCreatureBuffer(attrib, newType);
break;
}
doc.Clear();
}
void CreatureManager::internalLoadCreatureBuffer(TiXmlElement* attrib, const CreatureTypePtr& m)
{
if(std::find(m_creatures.begin(), m_creatures.end(), m) != m_creatures.end())
return;
Outfit out;
int32 type = attrib->readType<int32>("type");
if(type > 0) {
out.setCategory(ThingCategoryCreature);
out.setId(type);
} else {
out.setCategory(ThingCategoryItem);
out.setAuxId(attrib->readType<int32>("typeex"));
}
{
out.setHead(attrib->readType<int>(("head")));
out.setBody(attrib->readType<int>(("body")));
out.setLegs(attrib->readType<int>(("legs")));
out.setFeet(attrib->readType<int>(("feet")));
out.setAddons(attrib->readType<int>(("addons")));
out.setMount(attrib->readType<int>(("mount")));
}
m->setOutfit(out);
m_creatures.push_back(m);
}
const CreatureTypePtr& CreatureManager::getCreatureByName(std::string name)
{
stdext::tolower(name);
stdext::trim(name);
stdext::ucwords(name);
auto it = std::find_if(m_creatures.begin(), m_creatures.end(),
[=] (const CreatureTypePtr& m) -> bool { return m->getName() == name; });
if(it != m_creatures.end())
return *it;
g_logger.warning(stdext::format("could not find creature with name: %s", name));
return m_nullCreature;
}
const CreatureTypePtr& CreatureManager::getCreatureByLook(int look)
{
auto findFun = [=] (const CreatureTypePtr& c) -> bool
{
const Outfit& o = c->getOutfit();
return o.getId() == look || o.getAuxId() == look;
};
auto it = std::find_if(m_creatures.begin(), m_creatures.end(), findFun);
if(it != m_creatures.end())
return *it;
g_logger.warning(stdext::format("could not find creature with looktype: %d", look));
return m_nullCreature;
}
SpawnPtr CreatureManager::getSpawn(const Position& centerPos)
{
auto it = m_spawns.find(centerPos);
if(it != m_spawns.end())
return it->second;
g_logger.debug(stdext::format("failed to find spawn at center %s",stdext::to_string(centerPos)));
return nullptr;
}
SpawnPtr CreatureManager::getSpawnForPlacePos(const Position& pos)
{
for (const auto& pair : m_spawns) {
const Position& centerPos = pair.first;
const SpawnPtr& spawn = pair.second;
if (isInZone(pos, centerPos, spawn->getRadius()))
return spawn;
}
return nullptr;
}
SpawnPtr CreatureManager::addSpawn(const Position& centerPos, int radius)
{
auto iter = m_spawns.find(centerPos);
if(iter != m_spawns.end()) {
if(iter->second->getRadius() != radius)
iter->second->setRadius(radius);
return iter->second;
}
SpawnPtr ret(new Spawn);
ret->setRadius(radius);
ret->setCenterPos(centerPos);
m_spawns.insert(std::make_pair(centerPos, ret));
return ret;
}
void CreatureManager::deleteSpawn(const SpawnPtr& spawn)
{
const Position& centerPos = spawn->getCenterPos();
auto it = m_spawns.find(centerPos);
if(it != m_spawns.end())
m_spawns.erase(it);
}
std::vector<SpawnPtr> CreatureManager::getSpawns()
{
std::vector<SpawnPtr> spawns;
for (auto p : m_spawns)
spawns.push_back(p.second);
return spawns;
}
/* vim: set ts=4 sw=4 et: */

View File

@ -1,147 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CREATURES_H
#define CREATURES_H
#include "declarations.h"
#include <framework/luaengine/luaobject.h>
#include "outfit.h"
enum CreatureAttr : uint8
{
CreatureAttrPosition = 0,
CreatureAttrName = 1,
CreatureAttrOutfit = 2,
CreatureAttrSpawnTime = 3,
CreatureAttrDir = 4,
CreatureAttrRace = 5
};
enum CreatureRace : uint8
{
CreatureRaceNpc = 0,
CreatureRaceMonster = 1
};
enum SpawnAttr : uint8
{
SpawnAttrRadius = 0,
SpawnAttrCenter = 1,
};
class Spawn : public LuaObject
{
public:
Spawn() = default;
Spawn(int32 radius) { setRadius(radius); }
void setRadius(int32 r) { m_attribs.set(SpawnAttrRadius, r) ;}
int32 getRadius() { return m_attribs.get<int32>(SpawnAttrRadius); }
void setCenterPos(const Position& pos) { m_attribs.set(SpawnAttrCenter, pos); }
Position getCenterPos() { return m_attribs.get<Position>(SpawnAttrCenter); }
std::vector<CreatureTypePtr> getCreatures();
void addCreature(const Position& placePos, const CreatureTypePtr& cType);
void removeCreature(const Position& pos);
void clear() { m_creatures.clear(); }
protected:
void load(TiXmlElement* node);
void save(TiXmlElement* node);
private:
stdext::dynamic_storage<uint8> m_attribs;
std::unordered_map<Position, CreatureTypePtr, PositionHasher> m_creatures;
friend class CreatureManager;
};
class CreatureType : public LuaObject
{
public:
CreatureType() = default;
CreatureType(const std::string& name) { setName(name); }
void setSpawnTime(int32 spawnTime) { m_attribs.set(CreatureAttrSpawnTime, spawnTime); }
int32 getSpawnTime() { return m_attribs.get<int32>(CreatureAttrSpawnTime); }
void setName(const std::string& name) { m_attribs.set(CreatureAttrName, name); }
std::string getName() { return m_attribs.get<std::string>(CreatureAttrName); }
void setOutfit(const Outfit& o) { m_attribs.set(CreatureAttrOutfit, o); }
Outfit getOutfit() { return m_attribs.get<Outfit>(CreatureAttrOutfit); }
void setDirection(Otc::Direction dir) { m_attribs.set(CreatureAttrDir, dir); }
Otc::Direction getDirection() { return m_attribs.get<Otc::Direction>(CreatureAttrDir); }
void setRace(CreatureRace race) { m_attribs.set(CreatureAttrRace, race); }
CreatureRace getRace() { return m_attribs.get<CreatureRace>(CreatureAttrRace); }
CreaturePtr cast();
private:
stdext::dynamic_storage<uint8> m_attribs;
};
class CreatureManager
{
public:
CreatureManager();
void clear() { m_creatures.clear(); }
void clearSpawns();
void terminate();
void loadMonsters(const std::string& file);
void loadSingleCreature(const std::string& file);
void loadNpcs(const std::string& folder);
void loadCreatureBuffer(const std::string& buffer);
void loadSpawns(const std::string& fileName);
void saveSpawns(const std::string& fileName);
const CreatureTypePtr& getCreatureByName(std::string name);
const CreatureTypePtr& getCreatureByLook(int look);
std::vector<SpawnPtr> getSpawns();
SpawnPtr getSpawn(const Position& centerPos);
SpawnPtr getSpawnForPlacePos(const Position& pos);
SpawnPtr addSpawn(const Position& centerPos, int radius);
void deleteSpawn(const SpawnPtr& spawn);
bool isLoaded() { return m_loaded; }
bool isSpawnLoaded() { return m_spawnLoaded; }
const std::vector<CreatureTypePtr>& getCreatures() { return m_creatures; }
protected:
void internalLoadCreatureBuffer(TiXmlElement* elem, const CreatureTypePtr& m);
private:
std::vector<CreatureTypePtr> m_creatures;
std::unordered_map<Position, SpawnPtr, PositionHasher> m_spawns;
stdext::boolean<false> m_loaded, m_spawnLoaded;
CreatureTypePtr m_nullCreature;
};
extern CreatureManager g_creatures;
#endif

View File

@ -1,118 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CLIENT_DECLARATIONS_H
#define CLIENT_DECLARATIONS_H
#include "global.h"
#include <framework/net/declarations.h>
#include <framework/ui/declarations.h>
// core
class Map;
class Game;
class MapView;
class LightView;
class Tile;
class Thing;
class Item;
class Container;
class Creature;
class Monster;
class Npc;
class Player;
class LocalPlayer;
class Effect;
class Missile;
class AnimatedText;
class StaticText;
class Animator;
class ThingType;
class ItemType;
class House;
class Town;
class CreatureType;
class Spawn;
class TileBlock;
typedef stdext::shared_object_ptr<MapView> MapViewPtr;
typedef stdext::shared_object_ptr<LightView> LightViewPtr;
typedef stdext::shared_object_ptr<Tile> TilePtr;
typedef stdext::shared_object_ptr<Thing> ThingPtr;
typedef stdext::shared_object_ptr<Item> ItemPtr;
typedef stdext::shared_object_ptr<Container> ContainerPtr;
typedef stdext::shared_object_ptr<Creature> CreaturePtr;
typedef stdext::shared_object_ptr<Monster> MonsterPtr;
typedef stdext::shared_object_ptr<Npc> NpcPtr;
typedef stdext::shared_object_ptr<Player> PlayerPtr;
typedef stdext::shared_object_ptr<LocalPlayer> LocalPlayerPtr;
typedef stdext::shared_object_ptr<Effect> EffectPtr;
typedef stdext::shared_object_ptr<Missile> MissilePtr;
typedef stdext::shared_object_ptr<AnimatedText> AnimatedTextPtr;
typedef stdext::shared_object_ptr<StaticText> StaticTextPtr;
typedef stdext::shared_object_ptr<Animator> AnimatorPtr;
typedef stdext::shared_object_ptr<ThingType> ThingTypePtr;
typedef stdext::shared_object_ptr<ItemType> ItemTypePtr;
typedef stdext::shared_object_ptr<House> HousePtr;
typedef stdext::shared_object_ptr<Town> TownPtr;
typedef stdext::shared_object_ptr<CreatureType> CreatureTypePtr;
typedef stdext::shared_object_ptr<Spawn> SpawnPtr;
typedef std::vector<ThingPtr> ThingList;
typedef std::vector<ThingTypePtr> ThingTypeList;
typedef std::vector<ItemTypePtr> ItemTypeList;
typedef std::list<HousePtr> HouseList;
typedef std::list<TownPtr> TownList;
typedef std::list<ItemPtr> ItemList;
typedef std::list<TilePtr> TileList;
typedef std::vector<ItemPtr> ItemVector;
typedef std::unordered_map<Position, TilePtr, PositionHasher> TileMap;
typedef std::unordered_map<Position, CreatureTypePtr, PositionHasher> CreatureMap;
typedef std::unordered_map<Position, SpawnPtr, PositionHasher> SpawnMap;
// net
class ProtocolLogin;
class ProtocolGame;
typedef stdext::shared_object_ptr<ProtocolGame> ProtocolGamePtr;
typedef stdext::shared_object_ptr<ProtocolLogin> ProtocolLoginPtr;
// ui
class UIItem;
class UICreature;
class UIMap;
class UIMinimap;
class UIProgressRect;
class UIMapAnchorLayout;
class UIPositionAnchor;
class UISprite;
typedef stdext::shared_object_ptr<UIItem> UIItemPtr;
typedef stdext::shared_object_ptr<UICreature> UICreaturePtr;
typedef stdext::shared_object_ptr<UISprite> UISpritePtr;
typedef stdext::shared_object_ptr<UIMap> UIMapPtr;
typedef stdext::shared_object_ptr<UIMinimap> UIMinimapPtr;
typedef stdext::shared_object_ptr<UIProgressRect> UIProgressRectPtr;
typedef stdext::shared_object_ptr<UIMapAnchorLayout> UIMapAnchorLayoutPtr;
typedef stdext::shared_object_ptr<UIPositionAnchor> UIPositionAnchorPtr;
#endif

View File

@ -1,98 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "effect.h"
#include "map.h"
#include "game.h"
#include <framework/core/eventdispatcher.h>
#include <framework/util/extras.h>
void Effect::draw(const Point& dest, int offsetX, int offsetY, bool animate, LightView* lightView)
{
if(m_id == 0)
return;
if(animate) {
if(g_game.getFeature(Otc::GameEnhancedAnimations) && rawGetThingType()->getAnimator()) {
// This requires a separate getPhaseAt method as using getPhase would make all magic effects use the same phase regardless of their appearance time
m_animationPhase = rawGetThingType()->getAnimator()->getPhaseAt(m_animationTimer, m_animationPhase);
} else {
// hack to fix some animation phases duration, currently there is no better solution
int ticks = EFFECT_TICKS_PER_FRAME;
if (m_id == 33) {
ticks <<= 2;
}
m_animationPhase = std::min<int>((int)(m_animationTimer.ticksElapsed() / ticks), getAnimationPhases() - 1);
}
}
int xPattern = m_position.x % getNumPatternX();
if(xPattern < 0)
xPattern += getNumPatternX();
int yPattern = m_position.y % getNumPatternY();
if(yPattern < 0)
yPattern += getNumPatternY();
rawGetThingType()->draw(dest, 0, xPattern, yPattern, 0, m_animationPhase, Color::white, lightView);
}
void Effect::onAppear()
{
m_animationTimer.restart();
int duration = 0;
if(g_game.getFeature(Otc::GameEnhancedAnimations)) {
duration = getThingType()->getAnimator() ? getThingType()->getAnimator()->getTotalDuration() : 1000;
} else {
duration = EFFECT_TICKS_PER_FRAME;
// hack to fix some animation phases duration, currently there is no better solution
if(m_id == 33) {
duration <<= 2;
}
duration *= getAnimationPhases();
}
// schedule removal
auto self = asEffect();
g_dispatcher.scheduleEvent([self]() { g_map.removeThing(self); }, duration);
}
void Effect::setId(uint32 id)
{
if(!g_things.isValidDatId(id, ThingCategoryEffect))
id = 0;
m_id = id;
}
const ThingTypePtr& Effect::getThingType()
{
return g_things.getThingType(m_id, ThingCategoryEffect);
}
ThingType *Effect::rawGetThingType()
{
return g_things.rawGetThingType(m_id, ThingCategoryEffect);
}

View File

@ -1,59 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef EFFECT_H
#define EFFECT_H
#include <framework/global.h>
#include <framework/core/timer.h>
#include "thing.h"
// @bindclass
class Effect : public Thing
{
enum {
EFFECT_TICKS_PER_FRAME = 75
};
public:
void draw(const Point& dest, bool animate = true, LightView* lightView = nullptr) override {}
void draw(const Point& dest, int offsetX = 0, int offsetY = 0, bool animate = true, LightView* lightView = nullptr);
void setId(uint32 id) override;
uint32 getId() { return m_id; }
EffectPtr asEffect() { return static_self_cast<Effect>(); }
bool isEffect() { return true; }
const ThingTypePtr& getThingType() override;
ThingType *rawGetThingType() override;
protected:
void onAppear();
private:
uint16 m_id;
Timer m_animationTimer;
int m_animationPhase = 0;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,477 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef GAME_H
#define GAME_H
#include "declarations.h"
#include "item.h"
#include "animatedtext.h"
#include "effect.h"
#include "creature.h"
#include "container.h"
#include "protocolgame.h"
#include "localplayer.h"
#include "outfit.h"
#include <framework/core/timer.h>
#include <bitset>
struct UnjustifiedPoints {
bool operator==(const UnjustifiedPoints& other) {
return killsDay == other.killsDay &&
killsDayRemaining == other.killsDayRemaining &&
killsWeek == other.killsWeek &&
killsWeekRemaining == other.killsWeekRemaining &&
killsMonth == other.killsMonth &&
killsMonthRemaining == other.killsMonthRemaining &&
skullTime == other.skullTime;
}
uint8 killsDay;
uint8 killsDayRemaining;
uint8 killsWeek;
uint8 killsWeekRemaining;
uint8 killsMonth;
uint8 killsMonthRemaining;
uint8 skullTime;
};
typedef std::tuple<std::string, uint, std::string, int, bool> Vip;
//@bindsingleton g_game
class Game
{
public:
Game();
void init();
void terminate();
private:
void resetGameStates();
protected:
void processConnectionError(const boost::system::error_code& error);
void processDisconnect();
void processPing();
void processPingBack();
void processNewPing(uint32_t pingId);
void processUpdateNeeded(const std::string& signature);
void processLoginError(const std::string& error);
void processLoginAdvice(const std::string& message);
void processLoginWait(const std::string& message, int time);
void processLoginToken(bool unknown);
void processLogin();
void processPendingGame();
void processEnterGame();
void processGameStart();
void processGameEnd();
void processDeath(int deathType, int penality);
void processGMActions(const std::vector<uint8>& actions);
void processInventoryChange(int slot, const ItemPtr& item);
void processAttackCancel(uint seq);
void processWalkCancel(Otc::Direction direction);
void processNewWalkCancel(Otc::Direction dir);
void processPredictiveWalkCancel(const Position& pos, Otc::Direction dir);
void processWalkId(uint32_t walkId);
void processPlayerHelpers(int helpers);
void processPlayerModes(Otc::FightModes fightMode, Otc::ChaseModes chaseMode, bool safeMode, Otc::PVPModes pvpMode);
// message related
void processTextMessage(Otc::MessageMode mode, const std::string& text);
void processTalk(const std::string& name, int level, Otc::MessageMode mode, const std::string& text, int channelId, const Position& pos);
// container related
void processOpenContainer(int containerId, const ItemPtr& containerItem, const std::string& name, int capacity, bool hasParent, const std::vector<ItemPtr>& items, bool isUnlocked, bool hasPages, int containerSize, int firstIndex);
void processCloseContainer(int containerId);
void processContainerAddItem(int containerId, const ItemPtr& item, int slot);
void processContainerUpdateItem(int containerId, int slot, const ItemPtr& item);
void processContainerRemoveItem(int containerId, int slot, const ItemPtr& lastItem);
// channel related
void processChannelList(const std::vector<std::tuple<int, std::string> >& channelList);
void processOpenChannel(int channelId, const std::string& name);
void processOpenPrivateChannel(const std::string& name);
void processOpenOwnPrivateChannel(int channelId, const std::string& name);
void processCloseChannel(int channelId);
// rule violations
void processRuleViolationChannel(int channelId);
void processRuleViolationRemove(const std::string& name);
void processRuleViolationCancel(const std::string& name);
void processRuleViolationLock();
// vip related
void processVipAdd(uint id, const std::string& name, uint status, const std::string& description, int iconId, bool notifyLogin);
void processVipStateChange(uint id, uint status);
// tutorial hint
void processTutorialHint(int id);
void processAddAutomapFlag(const Position& pos, int icon, const std::string& message);
void processRemoveAutomapFlag(const Position& pos, int icon, const std::string& message);
// outfit
void processOpenOutfitWindow(const Outfit& currentOutfit, const std::vector<std::tuple<int, std::string, int> >& outfitList,
const std::vector<std::tuple<int, std::string> >& mountList);
// npc trade
void processOpenNpcTrade(const std::vector<std::tuple<ItemPtr, std::string, int, int64_t, int64_t> >& items);
void processPlayerGoods(uint64_t money, const std::vector<std::tuple<ItemPtr, int> >& goods);
void processCloseNpcTrade();
// player trade
void processOwnTrade(const std::string& name, const std::vector<ItemPtr>& items);
void processCounterTrade(const std::string& name, const std::vector<ItemPtr>& items);
void processCloseTrade();
// edit text/list
void processEditText(uint id, int itemId, int maxLength, const std::string& text, const std::string& writer, const std::string& date);
void processEditList(uint id, int doorId, const std::string& text);
// questlog
void processQuestLog(const std::vector<std::tuple<int, std::string, bool> >& questList);
void processQuestLine(int questId, const std::vector<std::tuple<std::string, std::string> >& questMissions);
// modal dialogs >= 970
void processModalDialog(uint32 id, std::string title, std::string message, std::vector<std::tuple<int, std::string> > buttonList, int enterButton, int escapeButton, std::vector<std::tuple<int, std::string> > choiceList, bool priority);
friend class ProtocolGame;
friend class Map;
public:
// login related
void loginWorld(const std::string& account, const std::string& password, const std::string& worldName, const std::string& worldHost, int worldPort, const std::string& characterName, const std::string& authenticatorToken, const std::string& sessionKey);
void cancelLogin();
void forceLogout();
void safeLogout();
// walk related
void walk(Otc::Direction direction, bool withPreWalk);
void autoWalk(const std::vector<Otc::Direction>& dirs, Position startPos);
void turn(Otc::Direction direction);
void stop();
// item related
void look(const ThingPtr& thing, bool isBattleList = false);
void move(const ThingPtr& thing, const Position& toPos, int count);
void moveRaw(const Position& pos, int id, int stackpos, const Position& toPos, int count);
void moveToParentContainer(const ThingPtr& thing, int count);
void rotate(const ThingPtr& thing);
void wrap(const ThingPtr& thing);
void use(const ThingPtr& thing);
void useWith(const ItemPtr& fromThing, const ThingPtr& toThing, int subType = 0);
void useInventoryItem(int itemId, int subType = 0);
void useInventoryItemWith(int itemId, const ThingPtr& toThing, int subType = 0);
ItemPtr findItemInContainers(uint itemId, int subType);
// container related
int open(const ItemPtr& item, const ContainerPtr& previousContainer);
void openParent(const ContainerPtr& container);
void close(const ContainerPtr& container);
void refreshContainer(const ContainerPtr& container);
// attack/follow related
void attack(CreaturePtr creature, bool cancel = false);
void cancelAttack() { attack(nullptr, true); }
void follow(CreaturePtr creature);
void cancelFollow() { follow(nullptr); }
void cancelAttackAndFollow();
// talk related
void talk(const std::string& message);
void talkChannel(Otc::MessageMode mode, int channelId, const std::string& message);
void talkPrivate(Otc::MessageMode mode, const std::string& receiver, const std::string& message);
// channel related
void openPrivateChannel(const std::string& receiver);
void requestChannels();
void joinChannel(int channelId);
void leaveChannel(int channelId);
void closeNpcChannel();
void openOwnChannel();
void inviteToOwnChannel(const std::string& name);
void excludeFromOwnChannel(const std::string& name);
// party related
void partyInvite(int creatureId);
void partyJoin(int creatureId);
void partyRevokeInvitation(int creatureId);
void partyPassLeadership(int creatureId);
void partyLeave();
void partyShareExperience(bool active);
// outfit related
void requestOutfit();
void changeOutfit(const Outfit& outfit);
// vip related
void addVip(const std::string& name);
void removeVip(int playerId);
void editVip(int playerId, const std::string& description, int iconId, bool notifyLogin);
// fight modes related
void setChaseMode(Otc::ChaseModes chaseMode);
void setFightMode(Otc::FightModes fightMode);
void setSafeFight(bool on);
void setPVPMode(Otc::PVPModes pvpMode);
Otc::ChaseModes getChaseMode() { return m_chaseMode; }
Otc::FightModes getFightMode() { return m_fightMode; }
bool isSafeFight() { return m_safeFight; }
Otc::PVPModes getPVPMode() { return m_pvpMode; }
// pvp related
void setUnjustifiedPoints(UnjustifiedPoints unjustifiedPoints);
UnjustifiedPoints getUnjustifiedPoints() { return m_unjustifiedPoints; };
void setOpenPvpSituations(int openPvpSitations);
int getOpenPvpSituations() { return m_openPvpSituations; }
// npc trade related
void inspectNpcTrade(const ItemPtr& item);
void buyItem(const ItemPtr& item, int amount, bool ignoreCapacity, bool buyWithBackpack);
void sellItem(const ItemPtr& item, int amount, bool ignoreEquipped);
void closeNpcTrade();
// player trade related
void requestTrade(const ItemPtr& item, const CreaturePtr& creature);
void inspectTrade(bool counterOffer, int index);
void acceptTrade();
void rejectTrade();
// house window and editable items related
void editText(uint id, const std::string& text);
void editList(uint id, int doorId, const std::string& text);
// rule violations (only gms)
void openRuleViolation(const std::string& reporter);
void closeRuleViolation(const std::string& reporter);
void cancelRuleViolation();
// reports
void reportBug(const std::string& comment);
void reportRuleViolation(const std::string& target, int reason, int action, const std::string& comment, const std::string& statement, int statementId, bool ipBanishment);
void debugReport(const std::string& a, const std::string& b, const std::string& c, const std::string& d);
// questlog related
void requestQuestLog();
void requestQuestLine(int questId);
// 870 only
void equipItem(const ItemPtr& item);
void mount(bool mount);
void setOutfitExtensions(int mount, int wings, int aura, int shader);
// 910 only
void requestItemInfo(const ItemPtr& item, int index);
// >= 970 modal dialog
void answerModalDialog(uint32 dialog, int button, int choice);
// >= 984 browse field
void browseField(const Position& position);
void seekInContainer(int cid, int index);
// >= 1080 ingame store
void buyStoreOffer(int offerId, int productType, const std::string& name = "");
void requestTransactionHistory(int page, int entriesPerPage);
void requestStoreOffers(const std::string& categoryName, int serviceType = 0);
void openStore(int serviceType = 0);
void transferCoins(const std::string& recipient, int amount);
void openTransactionHistory(int entriesPerPage);
// >= 1100
void preyAction(int slot, int actionType, int index);
void preyRequest();
void applyImbuement(uint8_t slot, uint32_t imbuementId, bool protectionCharm);
void clearImbuement(uint8_t slot);
void closeImbuingWindow();
//void reportRuleViolation2();
void ping();
void newPing();
void setPingDelay(int delay) { m_pingDelay = delay; }
// otclient only
void changeMapAwareRange(int xrange, int yrange);
// dynamic support for game features
void resetFeatures() { m_features.reset(); }
void enableFeature(Otc::GameFeature feature) { m_features.set(feature, true); }
void disableFeature(Otc::GameFeature feature) { m_features.set(feature, false); }
void setFeature(Otc::GameFeature feature, bool enabled) { m_features.set(feature, enabled); }
bool getFeature(Otc::GameFeature feature) { return m_features.test(feature); }
void setProtocolVersion(int version);
int getProtocolVersion() { return m_protocolVersion; }
void setCustomProtocolVersion(int version) { m_customProtocolVersion = version; }
int getCustomProtocolVersion() { return m_customProtocolVersion != 0 ? m_customProtocolVersion : m_protocolVersion; }
void setClientVersion(int version);
int getClientVersion() { return m_clientVersion; }
void setCustomOs(int os) { m_clientCustomOs = os; }
int getOs();
bool canPerformGameAction();
bool checkBotProtection();
bool isOnline() { return m_online; }
bool isLogging() { return !m_online && m_protocolGame; }
bool isDead() { return m_dead; }
bool isAttacking() { return !!m_attackingCreature && !m_attackingCreature->isRemoved(); }
bool isFollowing() { return !!m_followingCreature && !m_followingCreature->isRemoved(); }
bool isConnectionOk() { return m_protocolGame && m_protocolGame->getElapsedTicksSinceLastRead() < 5000; }
int getPing() { return m_ping; }
ContainerPtr getContainer(int index) { if (m_containers.find(index) == m_containers.end()) { return nullptr; } return m_containers[index]; }
std::map<int, ContainerPtr> getContainers() { return m_containers; }
std::map<int, Vip> getVips() { return m_vips; }
CreaturePtr getAttackingCreature() { return m_attackingCreature; }
CreaturePtr getFollowingCreature() { return m_followingCreature; }
void setServerBeat(int beat) { m_serverBeat = beat; }
int getServerBeat() { return m_serverBeat; }
void setCanReportBugs(bool enable) { m_canReportBugs = enable; }
bool canReportBugs() { return m_canReportBugs; }
void setExpertPvpMode(bool enable) { m_expertPvpMode = enable; }
bool getExpertPvpMode() { return m_expertPvpMode; }
LocalPlayerPtr getLocalPlayer() { return m_localPlayer; }
ProtocolGamePtr getProtocolGame() { return m_protocolGame; }
std::string getCharacterName() { return m_characterName; }
std::string getWorldName() { return m_worldName; }
std::vector<uint8> getGMActions() { return m_gmActions; }
bool isGM() { return m_gmActions.size() > 0; }
Otc::Direction getLastWalkDir() { return m_lastWalkDir; }
std::string formatCreatureName(const std::string &name);
int findEmptyContainerId();
void setTibiaCoins(int coins, int transferableCoins)
{
m_coins = coins;
m_transferableCoins = transferableCoins;
}
int getTibiaCoins()
{
return m_coins;
}
int getTransferableTibiaCoins()
{
return m_transferableCoins;
}
void setMaxPreWalkingSteps(uint value) { m_maxPreWalkingSteps = value; }
uint getMaxPreWalkingSteps() { return m_maxPreWalkingSteps; }
void showRealDirection(bool value) { m_showRealDirection = value; }
bool shouldShowingRealDirection() { return m_showRealDirection; }
uint getWalkId() { return m_walkId; }
uint getWalkPreditionId() { return m_walkPrediction; }
void ignoreServerDirection(bool value) { m_ignoreServerDirection = value; }
bool isIgnoringServerDirection()
{
return m_ignoreServerDirection;
}
void enableTileThingLuaCallback(bool value) { m_tileThingsLuaCallback = value; }
bool isTileThingLuaCallbackEnabled() { return m_tileThingsLuaCallback; }
int getRecivedPacketsCount()
{
return m_protocolGame ? m_protocolGame->getRecivedPacketsCount() : 0;
}
int getRecivedPacketsSize()
{
return m_protocolGame ? m_protocolGame->getRecivedPacketsSize() : 0;
}
protected:
void enableBotCall() { m_denyBotCall = false; }
void disableBotCall() { m_denyBotCall = true; }
private:
void setAttackingCreature(const CreaturePtr& creature);
void setFollowingCreature(const CreaturePtr& creature);
LocalPlayerPtr m_localPlayer;
CreaturePtr m_attackingCreature;
CreaturePtr m_followingCreature;
ProtocolGamePtr m_protocolGame;
std::map<int, ContainerPtr> m_containers;
std::map<int, Vip> m_vips;
bool m_online;
bool m_denyBotCall;
bool m_dead;
bool m_expertPvpMode;
int m_serverBeat;
ticks_t m_ping;
uint m_pingSent;
uint m_pingReceived;
uint m_walkId = 0;
uint m_walkPrediction = 0;
uint m_maxPreWalkingSteps = 2;
stdext::timer m_pingTimer;
std::map<uint32_t, stdext::timer> m_newPingIds;
uint m_seq;
int m_pingDelay;
int m_newPingDelay;
Otc::FightModes m_fightMode;
Otc::ChaseModes m_chaseMode;
Otc::PVPModes m_pvpMode;
Otc::Direction m_lastWalkDir;
bool m_waitingForAnotherDir = false;
UnjustifiedPoints m_unjustifiedPoints;
int m_openPvpSituations;
bool m_safeFight;
bool m_canReportBugs;
std::vector<uint8> m_gmActions;
std::string m_characterName;
std::string m_worldName;
std::bitset<Otc::LastGameFeature> m_features;
ScheduledEventPtr m_pingEvent;
ScheduledEventPtr m_newPingEvent;
ScheduledEventPtr m_checkConnectionEvent;
bool m_connectionFailWarned;
int m_protocolVersion;
int m_customProtocolVersion = 0;
int m_clientVersion;
std::string m_clientSignature;
int m_clientCustomOs;
int m_coins;
int m_transferableCoins;
bool m_showRealDirection = false;
bool m_ignoreServerDirection = true;
bool m_tileThingsLuaCallback = false;
};
extern Game g_game;
#endif

View File

@ -1,32 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CLIENT_GLOBAL_H
#define CLIENT_GLOBAL_H
#include <framework/global.h>
// widely used headers
#include "const.h"
#include "position.h"
#endif

View File

@ -1,210 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "map.h"
#include <framework/core/resourcemanager.h>
HouseManager g_houses;
House::House()
{
}
House::House(uint32 hId, const std::string &name, const Position &pos)
{
setId(hId);
setName(name);
if(pos.isValid())
setEntry(pos);
}
void House::setTile(const TilePtr& tile)
{
tile->setFlag(TILESTATE_HOUSE);
tile->setHouseId(getId());
m_tiles.insert(std::make_pair(tile->getPosition(), tile));
}
TilePtr House::getTile(const Position& position)
{
TileMap::const_iterator iter = m_tiles.find(position);
if(iter != m_tiles.end())
return iter->second;
return nullptr;
}
void House::addDoor(const ItemPtr& door)
{
if (!door) return;
door->setDoorId(m_lastDoorId);
m_doors[m_lastDoorId++] = door;
}
void House::removeDoorById(uint32 doorId)
{
if(doorId >= m_lastDoorId)
stdext::throw_exception(stdext::format("Failed to remove door of id %d (would overflow), max id: %d",
doorId, m_lastDoorId));
m_doors[doorId] = nullptr;
}
void House::load(const TiXmlElement *elem)
{
std::string name = elem->Attribute("name");
if(name.empty())
name = stdext::format("Unnamed house #%lu", getId());
setName(name);
setRent(elem->readType<uint32>("rent"));
setSize(elem->readType<uint32>("size"));
setTownId(elem->readType<uint32>("townid"));
m_isGuildHall = elem->readType<bool>("guildhall");
Position entryPos;
entryPos.x = elem->readType<int>("entryx");
entryPos.y = elem->readType<int>("entryy");
entryPos.z = elem->readType<int>("entryz");
setEntry(entryPos);
}
void House::save(TiXmlElement* elem)
{
elem->SetAttribute("name", getName());
elem->SetAttribute("houseid", getId());
Position entry = getEntry();
elem->SetAttribute("entryx", entry.x);
elem->SetAttribute("entryy", entry.y);
elem->SetAttribute("entryz", entry.z);
elem->SetAttribute("rent", getRent());
elem->SetAttribute("townid", getTownId());
elem->SetAttribute("size", getSize());
elem->SetAttribute("guildhall", (int)m_isGuildHall);
}
HouseManager::HouseManager()
{
}
void HouseManager::addHouse(const HousePtr& house)
{
if(findHouse(house->getId()) == m_houses.end())
m_houses.push_back(house);
}
void HouseManager::removeHouse(uint32 houseId)
{
auto it = findHouse(houseId);
if(it != m_houses.end())
m_houses.erase(it);
}
HousePtr HouseManager::getHouse(uint32 houseId)
{
auto it = findHouse(houseId);
return it != m_houses.end() ? *it : nullptr;
}
HousePtr HouseManager::getHouseByName(std::string name)
{
auto it = std::find_if(m_houses.begin(), m_houses.end(),
[=] (const HousePtr& house) -> bool { return house->getName() == name; });
return it != m_houses.end() ? *it : nullptr;
}
void HouseManager::load(const std::string& fileName)
{
try {
TiXmlDocument doc;
doc.Parse(g_resources.readFileContents(fileName).c_str());
if(doc.Error())
stdext::throw_exception(stdext::format("failed to load '%s': %s (House XML)", fileName, doc.ErrorDesc()));
TiXmlElement *root = doc.FirstChildElement();
if(!root || root->ValueTStr() != "houses")
stdext::throw_exception("invalid root tag name");
for(TiXmlElement *elem = root->FirstChildElement(); elem; elem = elem->NextSiblingElement()) {
if(elem->ValueTStr() != "house")
stdext::throw_exception("invalid house tag.");
uint32 houseId = elem->readType<uint32>("houseid");
HousePtr house = getHouse(houseId);
if(!house)
house = HousePtr(new House(houseId)), addHouse(house);
house->load(elem);
}
} catch(std::exception& e) {
g_logger.error(stdext::format("Failed to load '%s': %s", fileName, e.what()));
}
sort();
}
void HouseManager::save(const std::string& fileName)
{
try {
TiXmlDocument doc;
doc.SetTabSize(2);
TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "UTF-8", "");
doc.LinkEndChild(decl);
TiXmlElement* root = new TiXmlElement("houses");
doc.LinkEndChild(root);
for(auto house : m_houses) {
TiXmlElement *elem = new TiXmlElement("house");
house->save(elem);
root->LinkEndChild(elem);
}
if(!doc.SaveFile("data"+fileName))
stdext::throw_exception(stdext::format("failed to save houses XML %s: %s", fileName, doc.ErrorDesc()));
} catch(std::exception& e) {
g_logger.error(stdext::format("Failed to save '%s': %s", fileName, e.what()));
}
}
HouseList HouseManager::filterHouses(uint32 townId)
{
HouseList ret;
for(const HousePtr& house : m_houses)
if(house->getTownId() == townId)
ret.push_back(house);
return ret;
}
HouseList::iterator HouseManager::findHouse(uint32 houseId)
{
return std::find_if(m_houses.begin(), m_houses.end(),
[=] (const HousePtr& house) -> bool { return house->getId() == houseId; });
}
void HouseManager::sort()
{
m_houses.sort([] (const HousePtr& lhs, const HousePtr& rhs) { return lhs->getName() < rhs->getName(); });
}
/* vim: set ts=4 sw=4 et: */

View File

@ -1,113 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef HOUSES_H
#define HOUSES_H
#include "declarations.h"
#include "tile.h"
#include <framework/luaengine/luaobject.h>
enum HouseAttr : uint8
{
HouseAttrId,
HouseAttrName,
HouseAttrTown,
HouseAttrEntry,
HouseAttrSize,
HouseAttrRent
};
class House : public LuaObject
{
public:
House();
House(uint32 hId, const std::string& name = "", const Position& pos=Position());
~House() { m_tiles.clear(); }
void setTile(const TilePtr& tile);
TilePtr getTile(const Position& pos);
void setName(const std::string& name) { m_attribs.set(HouseAttrName, name); }
std::string getName() { return m_attribs.get<std::string>(HouseAttrName); }
void setId(uint32 hId) { m_attribs.set(HouseAttrId, hId); }
uint32 getId() { return m_attribs.get<uint32>(HouseAttrId); }
void setTownId(uint32 tid) { m_attribs.set(HouseAttrTown, tid); }
uint32 getTownId() { return m_attribs.get<uint32>(HouseAttrTown); }
void setSize(uint32 s) { m_attribs.set(HouseAttrSize, s); }
uint32 getSize() { return m_attribs.get<uint32>(HouseAttrSize); }
void setRent(uint32 r) { m_attribs.set(HouseAttrRent, r); }
uint32 getRent() { return m_attribs.get<uint32>(HouseAttrRent); }
void setEntry(const Position& p) { m_attribs.set(HouseAttrEntry, p); }
Position getEntry() { return m_attribs.get<Position>(HouseAttrEntry); }
void addDoor(const ItemPtr& door);
void removeDoor(const ItemPtr& door) { removeDoorById(door->getDoorId()); }
void removeDoorById(uint32 doorId);
protected:
void load(const TiXmlElement* elem);
void save(TiXmlElement* elem);
private:
stdext::packed_storage<uint8> m_attribs;
TileMap m_tiles;
ItemVector m_doors;
uint32 m_lastDoorId;
stdext::boolean<false> m_isGuildHall;
friend class HouseManager;
};
class HouseManager {
public:
HouseManager();
void addHouse(const HousePtr& house);
void removeHouse(uint32 houseId);
HousePtr getHouse(uint32 houseId);
HousePtr getHouseByName(std::string name);
void load(const std::string& fileName);
void save(const std::string& fileName);
void sort();
void clear() { m_houses.clear(); }
HouseList getHouseList() { return m_houses; }
HouseList filterHouses(uint32 townId);
private:
HouseList m_houses;
protected:
HouseList::iterator findHouse(uint32 houseId);
};
extern HouseManager g_houses;
#endif

View File

@ -1,440 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "item.h"
#include "thingtypemanager.h"
#include "spritemanager.h"
#include "thing.h"
#include "tile.h"
#include "shadermanager.h"
#include "container.h"
#include "map.h"
#include "houses.h"
#include "game.h"
#include <framework/core/clock.h>
#include <framework/core/eventdispatcher.h>
#include <framework/graphics/graphics.h>
#include <framework/core/filestream.h>
#include <framework/core/binarytree.h>
#include <framework/util/stats.h>
Item::Item() :
m_clientId(0),
m_serverId(0),
m_countOrSubType(1),
m_color(Color::alpha),
m_async(true),
m_phase(0),
m_lastPhase(0)
{
}
ItemPtr Item::create(int id, int countOrSubtype)
{
ItemPtr item(new Item);
item->setId(id);
item->setCountOrSubType(countOrSubtype);
return item;
}
ItemPtr Item::createFromOtb(int id)
{
ItemPtr item(new Item);
item->setOtbId(id);
return item;
}
std::string Item::getName()
{
return g_things.findItemTypeByClientId(m_clientId)->getName();
}
void Item::draw(const Point& dest, bool animate, LightView* lightView)
{
if (m_clientId == 0)
return;
// determine animation phase
int animationPhase = calculateAnimationPhase(animate);
// determine x,y,z patterns
int xPattern = 0, yPattern = 0, zPattern = 0;
calculatePatterns(xPattern, yPattern, zPattern);
Color color(Color::white);
if (m_color != Color::alpha)
color = m_color;
size_t drawQueueSize = g_drawQueue->size();
rawGetThingType()->draw(dest, 0, xPattern, yPattern, zPattern, animationPhase, color, lightView);
if (m_marked) {
g_drawQueue->setMark(drawQueueSize, updatedMarkedColor());
}
}
void Item::draw(const Rect& dest, bool animate)
{
if (m_clientId == 0)
return;
// determine animation phase
int animationPhase = calculateAnimationPhase(animate);
// determine x,y,z patterns
int xPattern = 0, yPattern = 0, zPattern = 0;
calculatePatterns(xPattern, yPattern, zPattern);
Color color(Color::white);
if (m_color != Color::alpha)
color = m_color;
rawGetThingType()->draw(dest, 0, xPattern, yPattern, zPattern, animationPhase, color);
}
void Item::setId(uint32 id)
{
if(!g_things.isValidDatId(id, ThingCategoryItem))
id = 0;
m_serverId = g_things.findItemTypeByClientId(id)->getServerId();
m_clientId = id;
}
void Item::setOtbId(uint16 id)
{
if(!g_things.isValidOtbId(id))
id = 0;
auto itemType = g_things.getItemType(id);
m_serverId = id;
id = itemType->getClientId();
if(!g_things.isValidDatId(id, ThingCategoryItem))
id = 0;
m_clientId = id;
}
bool Item::isValid()
{
return g_things.isValidDatId(m_clientId, ThingCategoryItem);
}
void Item::unserializeItem(const BinaryTreePtr &in)
{
try {
while(in->canRead()) {
int attrib = in->getU8();
if(attrib == 0)
break;
switch(attrib) {
case ATTR_COUNT:
case ATTR_RUNE_CHARGES:
setCount(in->getU8());
break;
case ATTR_CHARGES:
setCount(in->getU16());
break;
case ATTR_HOUSEDOORID:
case ATTR_SCRIPTPROTECTED:
case ATTR_DUALWIELD:
case ATTR_DECAYING_STATE:
m_attribs.set(attrib, in->getU8());
break;
case ATTR_ACTION_ID:
case ATTR_UNIQUE_ID:
case ATTR_DEPOT_ID:
m_attribs.set(attrib, in->getU16());
break;
case ATTR_CONTAINER_ITEMS:
case ATTR_ATTACK:
case ATTR_EXTRAATTACK:
case ATTR_DEFENSE:
case ATTR_EXTRADEFENSE:
case ATTR_ARMOR:
case ATTR_ATTACKSPEED:
case ATTR_HITCHANCE:
case ATTR_DURATION:
case ATTR_WRITTENDATE:
case ATTR_SLEEPERGUID:
case ATTR_SLEEPSTART:
case ATTR_ATTRIBUTE_MAP:
m_attribs.set(attrib, in->getU32());
break;
case ATTR_TELE_DEST: {
Position pos;
pos.x = in->getU16();
pos.y = in->getU16();
pos.z = in->getU8();
m_attribs.set(attrib, pos);
break;
}
case ATTR_NAME:
case ATTR_TEXT:
case ATTR_DESC:
case ATTR_ARTICLE:
case ATTR_WRITTENBY:
m_attribs.set(attrib, in->getString());
break;
default:
stdext::throw_exception(stdext::format("invalid item attribute %d", attrib));
}
}
} catch(stdext::exception& e) {
g_logger.error(stdext::format("Failed to unserialize OTBM item: %s", e.what()));
}
}
void Item::serializeItem(const OutputBinaryTreePtr& out)
{
out->startNode(OTBM_ITEM);
out->addU16(getServerId());
out->addU8(ATTR_COUNT);
out->addU8(getCount());
out->addU8(ATTR_CHARGES);
out->addU16(getCountOrSubType());
Position dest = m_attribs.get<Position>(ATTR_TELE_DEST);
if(dest.isValid()) {
out->addU8(ATTR_TELE_DEST);
out->addPos(dest.x, dest.y, dest.z);
}
if(isDepot()) {
out->addU8(ATTR_DEPOT_ID);
out->addU16(getDepotId());
}
if(isHouseDoor()) {
out->addU8(ATTR_HOUSEDOORID);
out->addU8(getDoorId());
}
uint16 aid = m_attribs.get<uint16>(ATTR_ACTION_ID);
uint16 uid = m_attribs.get<uint16>(ATTR_UNIQUE_ID);
if(aid) {
out->addU8(ATTR_ACTION_ID);
out->addU16(aid);
}
if(uid) {
out->addU8(ATTR_UNIQUE_ID);
out->addU16(uid);
}
std::string text = getText();
if(g_things.getItemType(m_serverId)->isWritable() && !text.empty()) {
out->addU8(ATTR_TEXT);
out->addString(text);
}
std::string desc = getDescription();
if(!desc.empty()) {
out->addU8(ATTR_DESC);
out->addString(desc);
}
out->endNode();
for(auto i : m_containerItems)
i->serializeItem(out);
}
int Item::getSubType()
{
if(isSplash() || isFluidContainer())
return m_countOrSubType;
if(g_game.getClientVersion() >= 860)
return 0;
return 1;
}
int Item::getCount()
{
if(isStackable())
return m_countOrSubType;
return 1;
}
bool Item::isMoveable()
{
return !rawGetThingType()->isNotMoveable();
}
bool Item::isGround()
{
return rawGetThingType()->isGround();
}
ItemPtr Item::clone()
{
ItemPtr item = ItemPtr(new Item);
*(item.get()) = *this;
return item;
}
void Item::calculatePatterns(int& xPattern, int& yPattern, int& zPattern)
{
// Avoid crashes with invalid items
if(!isValid())
return;
if(isStackable() && getNumPatternX() == 4 && getNumPatternY() == 2) {
if(m_countOrSubType <= 0) {
xPattern = 0;
yPattern = 0;
} else if(m_countOrSubType < 5) {
xPattern = m_countOrSubType-1;
yPattern = 0;
} else if(m_countOrSubType < 10) {
xPattern = 0;
yPattern = 1;
} else if(m_countOrSubType < 25) {
xPattern = 1;
yPattern = 1;
} else if(m_countOrSubType < 50) {
xPattern = 2;
yPattern = 1;
} else {
xPattern = 3;
yPattern = 1;
}
} else if(isHangable()) {
const TilePtr& tile = getTile();
if(tile) {
if(tile->mustHookSouth())
xPattern = getNumPatternX() >= 2 ? 1 : 0;
else if(tile->mustHookEast())
xPattern = getNumPatternX() >= 3 ? 2 : 0;
}
} else if(isSplash() || isFluidContainer()) {
int color = Otc::FluidTransparent;
if(g_game.getFeature(Otc::GameNewFluids)) {
switch(m_countOrSubType) {
case Otc::FluidNone:
color = Otc::FluidTransparent;
break;
case Otc::FluidWater:
color = Otc::FluidBlue;
break;
case Otc::FluidMana:
color = Otc::FluidPurple;
break;
case Otc::FluidBeer:
color = Otc::FluidBrown;
break;
case Otc::FluidOil:
color = Otc::FluidBrown;
break;
case Otc::FluidBlood:
color = Otc::FluidRed;
break;
case Otc::FluidSlime:
color = Otc::FluidGreen;
break;
case Otc::FluidMud:
color = Otc::FluidBrown;
break;
case Otc::FluidLemonade:
color = Otc::FluidYellow;
break;
case Otc::FluidMilk:
color = Otc::FluidWhite;
break;
case Otc::FluidWine:
color = Otc::FluidPurple;
break;
case Otc::FluidHealth:
color = Otc::FluidRed;
break;
case Otc::FluidUrine:
color = Otc::FluidYellow;
break;
case Otc::FluidRum:
color = Otc::FluidBrown;
break;
case Otc::FluidFruidJuice:
color = Otc::FluidYellow;
break;
case Otc::FluidCoconutMilk:
color = Otc::FluidWhite;
break;
case Otc::FluidTea:
color = Otc::FluidBrown;
break;
case Otc::FluidMead:
color = Otc::FluidBrown;
break;
default:
color = Otc::FluidTransparent;
break;
}
} else
color = m_countOrSubType;
xPattern = (color % 4) % getNumPatternX();
yPattern = (color / 4) % getNumPatternY();
} else {
xPattern = m_position.x % std::max<int>(1, getNumPatternX());
yPattern = m_position.y % std::max<int>(1, getNumPatternY());
zPattern = m_position.z % std::max<int>(1, getNumPatternZ());
}
}
int Item::calculateAnimationPhase(bool animate)
{
if(getAnimationPhases() > 1) {
if(animate) {
if(getAnimator() != nullptr)
return getAnimator()->getPhase();
if(m_async)
return (g_clock.millis() % ((g_game.getFeature(Otc::GameEnhancedAnimations) ? Otc::ITEM_TICKS_PER_FRAME_FAST : Otc::ITEM_TICKS_PER_FRAME) * getAnimationPhases())) / Otc::ITEM_TICKS_PER_FRAME;
else {
if(g_clock.millis() - m_lastPhase >= (g_game.getFeature(Otc::GameEnhancedAnimations) ? Otc::ITEM_TICKS_PER_FRAME_FAST : Otc::ITEM_TICKS_PER_FRAME)) {
m_phase = (m_phase + 1) % getAnimationPhases();
m_lastPhase = g_clock.millis();
}
return m_phase;
}
} else
return getAnimationPhases()-1;
}
return 0;
}
int Item::getExactSize(int layer, int xPattern, int yPattern, int zPattern, int animationPhase)
{
calculatePatterns(xPattern, yPattern, zPattern);
animationPhase = calculateAnimationPhase(true);
return Thing::getExactSize(layer, xPattern, yPattern, zPattern, animationPhase);
}
const ThingTypePtr& Item::getThingType()
{
return g_things.getThingType(m_clientId, ThingCategoryItem);
}
ThingType* Item::rawGetThingType()
{
return g_things.rawGetThingType(m_clientId, ThingCategoryItem);
}
/* vim: set ts=4 sw=4 et :*/

View File

@ -1,172 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef ITEM_H
#define ITEM_H
#include <framework/global.h>
#include "thing.h"
#include "effect.h"
#include "itemtype.h"
enum ItemAttr : uint8
{
ATTR_END = 0,
//ATTR_DESCRIPTION = 1,
//ATTR_EXT_FILE = 2,
ATTR_TILE_FLAGS = 3,
ATTR_ACTION_ID = 4,
ATTR_UNIQUE_ID = 5,
ATTR_TEXT = 6,
ATTR_DESC = 7,
ATTR_TELE_DEST = 8,
ATTR_ITEM = 9,
ATTR_DEPOT_ID = 10,
//ATTR_EXT_SPAWN_FILE = 11,
ATTR_RUNE_CHARGES = 12,
//ATTR_EXT_HOUSE_FILE = 13,
ATTR_HOUSEDOORID = 14,
ATTR_COUNT = 15,
ATTR_DURATION = 16,
ATTR_DECAYING_STATE = 17,
ATTR_WRITTENDATE = 18,
ATTR_WRITTENBY = 19,
ATTR_SLEEPERGUID = 20,
ATTR_SLEEPSTART = 21,
ATTR_CHARGES = 22,
ATTR_CONTAINER_ITEMS = 23,
ATTR_NAME = 30,
ATTR_PLURALNAME = 31,
ATTR_ATTACK = 33,
ATTR_EXTRAATTACK = 34,
ATTR_DEFENSE = 35,
ATTR_EXTRADEFENSE = 36,
ATTR_ARMOR = 37,
ATTR_ATTACKSPEED = 38,
ATTR_HITCHANCE = 39,
ATTR_SHOOTRANGE = 40,
ATTR_ARTICLE = 41,
ATTR_SCRIPTPROTECTED = 42,
ATTR_DUALWIELD = 43,
ATTR_ATTRIBUTE_MAP = 128
};
// @bindclass
#pragma pack(push,1) // disable memory alignment
class Item : public Thing
{
public:
Item();
virtual ~Item() { }
static ItemPtr create(int id, int countOrSubtype = 1);
static ItemPtr createFromOtb(int id);
void draw(const Point& dest, bool animate = true, LightView* lightView = nullptr);
void draw(const Rect& dest, bool animate = true);
void setId(uint32 id);
void setOtbId(uint16 id);
void setCountOrSubType(int value) { m_countOrSubType = value; }
void setCount(int count) { m_countOrSubType = count; }
void setSubType(int subType) { m_countOrSubType = subType; }
void setColor(const Color& c) { m_color = c; }
void setTooltip(const std::string& str) { m_tooltip = str; }
int getCountOrSubType() { return m_countOrSubType; }
int getSubType();
int getCount();
uint32 getId() { return m_clientId; }
uint16 getClientId() { return m_clientId; }
uint16 getServerId() { return m_serverId; }
std::string getName();
bool isValid();
std::string getTooltip() { return m_tooltip; }
void unserializeItem(const BinaryTreePtr& in);
void serializeItem(const OutputBinaryTreePtr& out);
void setDepotId(uint16 depotId) { m_attribs.set(ATTR_DEPOT_ID, depotId); }
uint16 getDepotId() { return m_attribs.get<uint16>(ATTR_DEPOT_ID); }
void setDoorId(uint8 doorId) { m_attribs.set(ATTR_HOUSEDOORID, doorId); }
uint8 getDoorId() { return m_attribs.get<uint8>(ATTR_HOUSEDOORID); }
uint16 getUniqueId() { return m_attribs.get<uint16>(ATTR_ACTION_ID); }
uint16 getActionId() { return m_attribs.get<uint16>(ATTR_UNIQUE_ID); }
void setActionId(uint16 actionId) { m_attribs.set(ATTR_ACTION_ID, actionId); }
void setUniqueId(uint16 uniqueId) { m_attribs.set(ATTR_UNIQUE_ID, uniqueId); }
std::string getText() { return m_attribs.get<std::string>(ATTR_TEXT); }
std::string getDescription() { return m_attribs.get<std::string>(ATTR_DESC); }
void setDescription(std::string desc) { m_attribs.set(ATTR_DESC, desc); }
void setText(std::string txt) { m_attribs.set(ATTR_TEXT, txt); }
Position getTeleportDestination() { return m_attribs.get<Position>(ATTR_TELE_DEST); }
void setTeleportDestination(const Position& pos) { m_attribs.set(ATTR_TELE_DEST, pos); }
void setAsync(bool enable) { m_async = enable; }
bool isHouseDoor() { return m_attribs.has(ATTR_HOUSEDOORID); }
bool isDepot() { return m_attribs.has(ATTR_DEPOT_ID); }
bool isContainer() { return m_attribs.has(ATTR_CONTAINER_ITEMS); }
bool isDoor() { return m_attribs.has(ATTR_HOUSEDOORID); }
bool isTeleport() { return m_attribs.has(ATTR_TELE_DEST); }
bool isMoveable();
bool isGround();
ItemPtr clone();
ItemPtr asItem() { return static_self_cast<Item>(); }
bool isItem() { return true; }
ItemVector getContainerItems() { return m_containerItems; }
ItemPtr getContainerItem(int slot) { return m_containerItems[slot]; }
void addContainerItemIndexed(const ItemPtr& i, int slot) { m_containerItems[slot] = i; }
void addContainerItem(const ItemPtr& i) { m_containerItems.push_back(i); }
void removeContainerItem(int slot) { m_containerItems[slot] = nullptr; }
void clearContainerItems() { m_containerItems.clear(); }
void calculatePatterns(int& xPattern, int& yPattern, int& zPattern);
int calculateAnimationPhase(bool animate);
int getExactSize(int layer = 0, int xPattern = 0, int yPattern = 0, int zPattern = 0, int animationPhase = 0);
const ThingTypePtr& getThingType();
ThingType *rawGetThingType();
private:
uint16 m_clientId;
uint16 m_serverId;
uint16 m_countOrSubType;
stdext::packed_storage<uint8> m_attribs;
ItemVector m_containerItems;
Color m_color;
bool m_async;
std::string m_tooltip;
uint8 m_phase;
ticks_t m_lastPhase;
};
#pragma pack(pop)
#endif

View File

@ -1,93 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "thingtypemanager.h"
#include "thingtype.h"
#include "game.h"
#include <framework/core/filestream.h>
#include <framework/core/binarytree.h>
ItemType::ItemType()
{
m_category = ItemCategoryInvalid;
}
void ItemType::unserialize(const BinaryTreePtr& node)
{
m_null = false;
m_category = (ItemCategory)node->getU8();
node->getU32(); // flags
static uint16 lastId = 99;
while(node->canRead()) {
uint8 attr = node->getU8();
if(attr == 0 || attr == 0xFF)
break;
uint16 len = node->getU16();
switch(attr) {
case ItemTypeAttrServerId: {
uint16 serverId = node->getU16();
if(g_game.getClientVersion() < 960) {
if(serverId > 20000 && serverId < 20100) {
serverId -= 20000;
} else if(lastId > 99 && lastId != serverId - 1) {
while(lastId != serverId - 1) {
ItemTypePtr tmp(new ItemType);
tmp->setServerId(lastId++);
g_things.addItemType(tmp);
}
}
} else {
if(serverId > 30000 && serverId < 30100) {
serverId -= 30000;
} else if(lastId > 99 && lastId != serverId - 1) {
while(lastId != serverId - 1) {
ItemTypePtr tmp(new ItemType);
tmp->setServerId(lastId++);
g_things.addItemType(tmp);
}
}
}
setServerId(serverId);
lastId = serverId;
break;
}
case ItemTypeAttrClientId:
setClientId(node->getU16());
break;
case ItemTypeAttrName:
setName(node->getString(len));
break;
case ItemTypeAttrWritable:
m_attribs.set(ItemTypeAttrWritable, true);
break;
default:
node->skip(len); // skip attribute
break;
}
}
}

View File

@ -1,162 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef ITEMTYPE_H
#define ITEMTYPE_H
#include <framework/core/declarations.h>
#include <framework/luaengine/luaobject.h>
#include <framework/xml/tinyxml.h>
enum ItemCategory : uint8 {
ItemCategoryInvalid = 0,
ItemCategoryGround = 1,
ItemCategoryContainer = 2,
ItemCategoryWeapon = 3,
ItemCategoryAmmunition = 4,
ItemCategoryArmor = 5,
ItemCategoryCharges = 6,
ItemCategoryTeleport = 7,
ItemCategoryMagicField = 8,
ItemCategoryWritable = 9,
ItemCategoryKey = 10,
ItemCategorySplash = 11,
ItemCategoryFluid = 12,
ItemCategoryDoor = 13,
ItemCategoryDeprecated = 14,
ItemCategoryLast = 15
};
enum ItemTypeAttr : uint8 {
ItemTypeAttrServerId = 16,
ItemTypeAttrClientId = 17,
ItemTypeAttrName = 18, // deprecated
ItemTypeAttrDesc = 19, // deprecated
ItemTypeAttrSpeed = 20,
ItemTypeAttrSlot = 21, // deprecated
ItemTypeAttrMaxItems = 22, // deprecated
ItemTypeAttrWeight = 23, // deprecated
ItemTypeAttrWeapon = 24, // deprecated
ItemTypeAttrAmmunition = 25, // deprecated
ItemTypeAttrArmor = 26, // deprecated
ItemTypeAttrMagicLevel = 27, // deprecated
ItemTypeAttrMagicField = 28, // deprecated
ItemTypeAttrWritable = 29, // deprecated
ItemTypeAttrRotateTo = 30, // deprecated
ItemTypeAttrDecay = 31, // deprecated
ItemTypeAttrSpriteHash = 32,
ItemTypeAttrMinimapColor = 33,
ItemTypeAttr07 = 34,
ItemTypeAttr08 = 35,
ItemTypeAttrLight = 36,
ItemTypeAttrDecay2 = 37, // deprecated
ItemTypeAttrWeapon2 = 38, // deprecated
ItemTypeAttrAmmunition2 = 39, // deprecated
ItemTypeAttrArmor2 = 40, // deprecated
ItemTypeAttrWritable2 = 41, // deprecated
ItemTypeAttrLight2 = 42,
ItemTypeAttrTopOrder = 43,
ItemTypeAttrWrtiable3 = 44, // deprecated
ItemTypeAttrWareId = 45,
ItemTypeAttrLast = 46
};
enum ClientVersion
{
ClientVersion750 = 1,
ClientVersion755 = 2,
ClientVersion760 = 3,
ClientVersion770 = 3,
ClientVersion780 = 4,
ClientVersion790 = 5,
ClientVersion792 = 6,
ClientVersion800 = 7,
ClientVersion810 = 8,
ClientVersion811 = 9,
ClientVersion820 = 10,
ClientVersion830 = 11,
ClientVersion840 = 12,
ClientVersion841 = 13,
ClientVersion842 = 14,
ClientVersion850 = 15,
ClientVersion854_OLD = 16,
ClientVersion854 = 17,
ClientVersion855 = 18,
ClientVersion860_OLD = 19,
ClientVersion860 = 20,
ClientVersion861 = 21,
ClientVersion862 = 22,
ClientVersion870 = 23,
ClientVersion871 = 24,
ClientVersion872 = 25,
ClientVersion873 = 26,
ClientVersion900 = 27,
ClientVersion910 = 28,
ClientVersion920 = 29,
ClientVersion940 = 30,
ClientVersion944_V1 = 31,
ClientVersion944_V2 = 32,
ClientVersion944_V3 = 33,
ClientVersion944_V4 = 34,
ClientVersion946 = 35,
ClientVersion950 = 36,
ClientVersion952 = 37,
ClientVersion953 = 38,
ClientVersion954 = 39,
ClientVersion960 = 40,
ClientVersion961 = 41
};
class ItemType : public LuaObject
{
public:
ItemType();
void unserialize(const BinaryTreePtr& node);
void setServerId(uint16 serverId) { m_attribs.set(ItemTypeAttrServerId, serverId); }
uint16 getServerId() { return m_attribs.get<uint16>(ItemTypeAttrServerId); }
void setClientId(uint16 clientId) { m_attribs.set(ItemTypeAttrClientId, clientId); }
uint16 getClientId() { return m_attribs.get<uint16>(ItemTypeAttrClientId); }
void setCategory(ItemCategory category) { m_category = category; }
ItemCategory getCategory() { return m_category; }
void setName(const std::string& name) { m_attribs.set(ItemTypeAttrName, name); }
std::string getName() { return m_attribs.get<std::string>(ItemTypeAttrName); }
void setDesc(const std::string& desc) { m_attribs.set(ItemTypeAttrDesc, desc); }
std::string getDesc() { return m_attribs.get<std::string>(ItemTypeAttrDesc); }
bool isNull() { return m_null; }
bool isWritable() { return m_attribs.get<bool>(ItemTypeAttrWritable); }
private:
ItemCategory m_category;
stdext::boolean<true> m_null;
stdext::dynamic_storage<uint8> m_attribs;
};
#endif

View File

@ -1,69 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "lightview.h"
#include <framework/graphics/painter.h>
void LightView::addLight(const Point& pos, uint8_t color, uint8_t intensity)
{
if (!m_lights.empty()) {
Light& prevLight = m_lights.back();
if (prevLight.pos == pos && prevLight.color == color) {
prevLight.intensity = std::max(prevLight.intensity, intensity);
return;
}
}
m_lights.push_back(Light{ pos, color, intensity });
}
void LightView::setFieldBrightness(const Point& pos, size_t start, uint8_t color)
{
size_t index = (pos.y / Otc::TILE_PIXELS) * m_mapSize.width() + (pos.x / Otc::TILE_PIXELS);
if (index >= m_tiles.size()) return;
m_tiles[index].start = start;
m_tiles[index].color = color;
}
void LightView::draw() // render thread
{
static std::vector<uint8_t> buffer;
if(buffer.size() < 4u * m_mapSize.area())
buffer.resize(m_mapSize.area() * 4);
// hidden code
m_lightTexture->update();
glBindTexture(GL_TEXTURE_2D, m_lightTexture->getId());
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_mapSize.width(), m_mapSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
Point offset = m_src.topLeft();
Size size = m_src.size();
CoordsBuffer coords;
coords.addRect(RectF(m_dest.left(), m_dest.top(), m_dest.width(), m_dest.height()),
RectF((float)offset.x / Otc::TILE_PIXELS, (float)offset.y / Otc::TILE_PIXELS,
(float)size.width() / Otc::TILE_PIXELS, (float)size.height() / Otc::TILE_PIXELS));
g_painterNew->resetColor();
g_painterNew->setCompositionMode(Painter::CompositionMode_Multiply);
g_painterNew->drawTextureCoords(coords, m_lightTexture);
g_painterNew->resetCompositionMode();
}

View File

@ -1,66 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef LIGHTVIEW_H
#define LIGHTVIEW_H
#include "declarations.h"
#include "thingtype.h"
#include <framework/graphics/declarations.h>
#include <framework/graphics/drawqueue.h>
#include <set>
struct TileLight {
size_t start;
uint8_t color;
};
class LightView : public DrawQueueItem
{
public:
LightView(TexturePtr& lightTexture, const Size& mapSize, const Rect& dest, const Rect& src, uint8_t color, uint8_t intensity) :
DrawQueueItem(nullptr), m_lightTexture(lightTexture), m_mapSize(mapSize), m_dest(dest), m_src(src) {
m_globalLight = Color::from8bit(color) * ((float)intensity / 255.f);
m_tiles.resize(m_mapSize.area(), TileLight{ 0, 0 });
}
inline void addLight(const Point& pos, const Light& light)
{
return addLight(pos, light.color, light.intensity);
}
void addLight(const Point& pos, uint8_t color, uint8_t intensity);
void setFieldBrightness(const Point& pos, size_t start, uint8_t color);
size_t size() { return m_lights.size(); }
void draw() override;
private:
TexturePtr m_lightTexture;
Size m_mapSize;
Rect m_dest, m_src;
Color m_globalLight;
std::vector<Light> m_lights;
std::vector<TileLight> m_tiles;
};
#endif

View File

@ -1,623 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "localplayer.h"
#include "map.h"
#include "game.h"
#include "tile.h"
#include <framework/core/eventdispatcher.h>
#include <framework/graphics/graphics.h>
#include <framework/util/extras.h>
LocalPlayer::LocalPlayer()
{
m_states = 0;
m_vocation = 0;
m_blessings = Otc::BlessingNone;
m_walkLockExpiration = 0;
m_skillsLevel.fill(-1);
m_skillsBaseLevel.fill(-1);
m_skillsLevelPercent.fill(-1);
m_health = -1;
m_maxHealth = -1;
m_freeCapacity = -1;
m_experience = -1;
m_level = -1;
m_levelPercent = -1;
m_mana = -1;
m_maxMana = -1;
m_magicLevel = -1;
m_magicLevelPercent = -1;
m_baseMagicLevel = -1;
m_soul = -1;
m_stamina = -1;
m_baseSpeed = -1;
m_regenerationTime = -1;
m_offlineTrainingTime = -1;
m_totalCapacity = -1;
}
void LocalPlayer::draw(const Point& dest, bool animate, LightView* lightView)
{
Creature::draw(dest, animate, lightView);
}
void LocalPlayer::lockWalk(int millis)
{
m_walkLockExpiration = std::max<int>(m_walkLockExpiration, (ticks_t) g_clock.millis() + millis);
}
bool LocalPlayer::canWalk(Otc::Direction direction, bool ignoreLock) {
// cannot walk while locked
if ((m_walkLockExpiration != 0 && g_clock.millis() < m_walkLockExpiration) && !ignoreLock)
return false;
// paralyzed
if (m_speed == 0)
return false;
// last walk is not done yet
if (m_walking && (m_walkTimer.ticksElapsed() < getStepDuration()) && !isAutoWalking() && !isServerWalking())
return false;
auto tile = g_map.getTile(getPrewalkingPosition(true));
if (isPreWalking() && (!m_lastPrewalkDone || (tile && tile->isBlocking())))
return false;
// cannot walk while already walking
if ((m_walking && !isAutoWalking() && !isServerWalking()) && (!isPreWalking() || !m_lastPrewalkDone))
return false;
// Without new walking limit only to 1 prewalk
if (!m_preWalking.empty() && !g_game.getFeature(Otc::GameNewWalking))
return false;
// Limit pre walking steps
if (m_preWalking.size() >= g_game.getMaxPreWalkingSteps()) // max 3 extra steps
return false;
if (!m_preWalking.empty()) { // disallow diagonal extented prewalking walking
auto dir = m_position.getDirectionFromPosition(m_preWalking.back());
if ((dir == Otc::NorthWest || dir == Otc::NorthEast || dir == Otc::SouthWest || dir == Otc::SouthEast)) {
return false;
}
if (!g_map.getTile(getPrewalkingPosition())->isWalkable())
return false;
}
return true;
}
void LocalPlayer::walk(const Position& oldPos, const Position& newPos)
{
if (g_extras.debugWalking) {
g_logger.info(stdext::format("[%i] LocalPlayer::walk", (int)g_clock.millis()));
}
m_lastAutoWalkRetries = 0;
// a prewalk was going on
if (isPreWalking()) {
for (auto it = m_preWalking.begin(); it != m_preWalking.end(); ++it) {
if (*it == newPos) {
m_preWalking.erase(m_preWalking.begin(), ++it);
if(!isPreWalking()) // reset pre walking
updateWalk();
return;
}
}
if (g_extras.debugWalking) {
g_logger.info(stdext::format("[%i] LocalPlayer::walk invalid prewalk", (int)g_clock.millis()));
}
// invalid pre walk
m_preWalking.clear();
m_serverWalking = true;
if(m_serverWalkEndEvent)
m_serverWalkEndEvent->cancel();
Creature::walk(oldPos, newPos);
} else { // no prewalk was going on, this must be an server side automated walk
if (g_extras.debugWalking) {
g_logger.info(stdext::format("[%i] LocalPlayer::walk server walk", (int)g_clock.millis()));
}
m_serverWalking = true;
if(m_serverWalkEndEvent)
m_serverWalkEndEvent->cancel();
m_lastAutoWalkRetries = 0;
Creature::walk(oldPos, newPos);
}
}
void LocalPlayer::preWalk(Otc::Direction direction)
{
}
void LocalPlayer::cancelWalk(Otc::Direction direction)
{
if (g_game.getFeature(Otc::GameNewWalking)) {
return;
}
return cancelNewWalk(direction);
}
void LocalPlayer::cancelNewWalk(Otc::Direction dir)
{
if (g_extras.debugWalking) {
g_logger.info(stdext::format("[%i] cancelWalk", (int)g_clock.millis()));
}
bool clearedPrewalk = !m_preWalking.empty();
m_preWalking.clear();
g_map.requestVisibleTilesCacheUpdate();
if (clearedPrewalk) {
stopWalk();
}
m_idleTimer.restart();
if (retryAutoWalk()) return;
if (!g_game.isIgnoringServerDirection() || !g_game.getFeature(Otc::GameNewWalking)) {
setDirection(dir);
}
callLuaField("onCancelWalk", dir);
}
bool LocalPlayer::predictiveCancelWalk(const Position& pos, uint32_t predictionId, Otc::Direction dir)
{
if (g_extras.debugPredictiveWalking) {
g_logger.info(stdext::format("[%i] predictiveCancelWalk: %i - %i", (int)g_clock.millis(), predictionId, (int)m_preWalking.size()));
}
return false;
}
bool LocalPlayer::retryAutoWalk()
{
return false;
}
bool LocalPlayer::autoWalk(Position destination, bool retry)
{
// reset state
m_autoWalkDestination = Position();
m_lastAutoWalkPosition = Position();
if(m_autoWalkContinueEvent)
m_autoWalkContinueEvent->cancel();
m_autoWalkContinueEvent = nullptr;
if (!retry)
m_lastAutoWalkRetries = 0;
if(destination == getPrewalkingPosition())
return true;
m_autoWalkDestination = destination;
auto self(asLocalPlayer());
g_map.findPathAsync(getPrewalkingPosition(), destination, [self](PathFindResult_ptr result) {
if (self->m_autoWalkDestination != result->destination)
return;
if (g_extras.debugWalking) {
g_logger.info(stdext::format("Async path search finished with complexity %i/50000", result->complexity));
}
if (result->status != Otc::PathFindResultOk) {
if (self->m_lastAutoWalkRetries > 0 && self->m_lastAutoWalkRetries <= 3) { // try again in 300, 700, 1200 ms if canceled by server
self->m_autoWalkContinueEvent = g_dispatcher.scheduleEvent(std::bind(&LocalPlayer::autoWalk, self, result->destination, true), 200 + self->m_lastAutoWalkRetries * 100);
return;
}
self->m_autoWalkDestination = Position();
self->callLuaField("onAutoWalkFail", result->status);
return;
}
if(!g_game.getFeature(Otc::GameNewWalking) && result->path.size() > 127)
result->path.resize(127);
else if(result->path.size() > 4095)
result->path.resize(4095);
if (result->path.empty()) {
self->m_autoWalkDestination = Position();
self->callLuaField("onAutoWalkFail", result->status);
return;
}
auto finalAutowalkPos = self->getPrewalkingPosition().translatedToDirections(result->path).back();
if (self->m_autoWalkDestination != finalAutowalkPos) {
self->m_lastAutoWalkPosition = finalAutowalkPos;
}
g_game.autoWalk(result->path, result->start);
});
if(!retry)
lockWalk();
return true;
}
void LocalPlayer::stopAutoWalk()
{
m_autoWalkDestination = Position();
m_lastAutoWalkPosition = Position();
if (m_autoWalkContinueEvent) {
m_autoWalkContinueEvent->cancel();
m_autoWalkContinueEvent = nullptr;
}
}
void LocalPlayer::stopWalk() {
if (g_extras.debugWalking) {
g_logger.info(stdext::format("[%i] stopWalk", (int)g_clock.millis()));
}
Creature::stopWalk(); // will call terminateWalk
m_preWalking.clear();
}
void LocalPlayer::updateWalkOffset(int totalPixelsWalked, bool inNextFrame)
{
// pre walks offsets are calculated in the oposite direction
if(isPreWalking()) {
Point& walkOffset = inNextFrame ? m_walkOffsetInNextFrame : m_walkOffset;
walkOffset = Point(0,0);
if(m_walkDirection == Otc::North || m_walkDirection == Otc::NorthEast || m_walkDirection == Otc::NorthWest)
walkOffset.y = -totalPixelsWalked;
else if(m_walkDirection == Otc::South || m_walkDirection == Otc::SouthEast || m_walkDirection == Otc::SouthWest)
walkOffset.y = totalPixelsWalked;
if(m_walkDirection == Otc::East || m_walkDirection == Otc::NorthEast || m_walkDirection == Otc::SouthEast)
walkOffset.x = totalPixelsWalked;
else if(m_walkDirection == Otc::West || m_walkDirection == Otc::NorthWest || m_walkDirection == Otc::SouthWest)
walkOffset.x = -totalPixelsWalked;
} else
Creature::updateWalkOffset(totalPixelsWalked, inNextFrame);
}
void LocalPlayer::updateWalk()
{
if (!m_walking)
return;
float walkTicksPerPixel = ((float)(getStepDuration(true) + 10)) / 32.0f;
int totalPixelsWalked = std::min<int>(m_walkTimer.ticksElapsed() / walkTicksPerPixel, 32.0f);
int totalPixelsWalkedInNextFrame = std::min<int>((m_walkTimer.ticksElapsed() + 15) / walkTicksPerPixel, 32.0f);
// needed for paralyze effect
m_walkedPixels = std::max<int>(m_walkedPixels, totalPixelsWalked);
int walkedPixelsInNextFrame = std::max<int>(m_walkedPixels, totalPixelsWalkedInNextFrame);
// update walk animation and offsets
updateWalkAnimation(totalPixelsWalked);
updateWalkOffset(m_walkedPixels);
updateWalkOffset(walkedPixelsInNextFrame, true);
updateWalkingTile();
int stepDuration = getStepDuration();
// terminate walk only when client and server side walk are completed
if (m_walking && m_walkTimer.ticksElapsed() >= stepDuration)
m_lastPrewalkDone = true;
if(m_walking && m_walkTimer.ticksElapsed() >= stepDuration && !isPreWalking())
terminateWalk();
}
void LocalPlayer::terminateWalk()
{
if (g_extras.debugWalking) {
g_logger.info(stdext::format("[%i] terminateWalk", (int)g_clock.millis()));
}
Creature::terminateWalk();
m_idleTimer.restart();
m_preWalking.clear();
m_walking = false;
auto self = asLocalPlayer();
if(m_serverWalking) {
if(m_serverWalkEndEvent)
m_serverWalkEndEvent->cancel();
m_serverWalkEndEvent = g_dispatcher.scheduleEvent([self] {
self->m_serverWalking = false;
}, 100);
}
callLuaField("onWalkFinish");
}
void LocalPlayer::onAppear()
{
Creature::onAppear();
/* Does not seem to be needed anymore
// on teleports lock the walk
if(!m_oldPosition.isInRange(m_position,1,1))
lockWalk();
*/
}
void LocalPlayer::onPositionChange(const Position& newPos, const Position& oldPos)
{
Creature::onPositionChange(newPos, oldPos);
if(newPos == m_autoWalkDestination)
stopAutoWalk();
else if(m_autoWalkDestination.isValid() && newPos == m_lastAutoWalkPosition)
autoWalk(m_autoWalkDestination);
m_walkMatrix.updatePosition(newPos);
}
void LocalPlayer::turn(Otc::Direction direction)
{
Creature::setDirection(direction);
callLuaField("onTurn", direction);
}
void LocalPlayer::setStates(int states)
{
if(m_states != states) {
int oldStates = m_states;
m_states = states;
callLuaField("onStatesChange", states, oldStates);
}
}
void LocalPlayer::setSkill(Otc::Skill skill, int level, int levelPercent)
{
if(skill >= Otc::LastSkill) {
g_logger.traceError("invalid skill");
return;
}
int oldLevel = m_skillsLevel[skill];
int oldLevelPercent = m_skillsLevelPercent[skill];
if(level != oldLevel || levelPercent != oldLevelPercent) {
m_skillsLevel[skill] = level;
m_skillsLevelPercent[skill] = levelPercent;
callLuaField("onSkillChange", skill, level, levelPercent, oldLevel, oldLevelPercent);
}
}
void LocalPlayer::setBaseSkill(Otc::Skill skill, int baseLevel)
{
if(skill >= Otc::LastSkill) {
g_logger.traceError("invalid skill");
return;
}
int oldBaseLevel = m_skillsBaseLevel[skill];
if(baseLevel != oldBaseLevel) {
m_skillsBaseLevel[skill] = baseLevel;
callLuaField("onBaseSkillChange", skill, baseLevel, oldBaseLevel);
}
}
void LocalPlayer::setHealth(double health, double maxHealth)
{
if(m_health != health || m_maxHealth != maxHealth) {
double oldHealth = m_health;
double oldMaxHealth = m_maxHealth;
m_health = health;
m_maxHealth = maxHealth;
callLuaField("onHealthChange", health, maxHealth, oldHealth, oldMaxHealth);
// cannot walk while dying
if(health == 0) {
if(isPreWalking())
stopWalk();
lockWalk();
}
}
}
void LocalPlayer::setFreeCapacity(double freeCapacity)
{
if(m_freeCapacity != freeCapacity) {
double oldFreeCapacity = m_freeCapacity;
m_freeCapacity = freeCapacity;
callLuaField("onFreeCapacityChange", freeCapacity, oldFreeCapacity);
}
}
void LocalPlayer::setTotalCapacity(double totalCapacity)
{
if(m_totalCapacity != totalCapacity) {
double oldTotalCapacity = m_totalCapacity;
m_totalCapacity = totalCapacity;
callLuaField("onTotalCapacityChange", totalCapacity, oldTotalCapacity);
}
}
void LocalPlayer::setExperience(double experience)
{
if(m_experience != experience) {
double oldExperience = m_experience;
m_experience = experience;
callLuaField("onExperienceChange", experience, oldExperience);
}
}
void LocalPlayer::setLevel(double level, double levelPercent)
{
if(m_level != level || m_levelPercent != levelPercent) {
double oldLevel = m_level;
double oldLevelPercent = m_levelPercent;
m_level = level;
m_levelPercent = levelPercent;
callLuaField("onLevelChange", level, levelPercent, oldLevel, oldLevelPercent);
}
}
void LocalPlayer::setMana(double mana, double maxMana)
{
if(m_mana != mana || m_maxMana != maxMana) {
double oldMana = m_mana;
double oldMaxMana;
m_mana = mana;
m_maxMana = maxMana;
callLuaField("onManaChange", mana, maxMana, oldMana, oldMaxMana);
}
}
void LocalPlayer::setMagicLevel(double magicLevel, double magicLevelPercent)
{
if(m_magicLevel != magicLevel || m_magicLevelPercent != magicLevelPercent) {
double oldMagicLevel = m_magicLevel;
double oldMagicLevelPercent = m_magicLevelPercent;
m_magicLevel = magicLevel;
m_magicLevelPercent = magicLevelPercent;
callLuaField("onMagicLevelChange", magicLevel, magicLevelPercent, oldMagicLevel, oldMagicLevelPercent);
}
}
void LocalPlayer::setBaseMagicLevel(double baseMagicLevel)
{
if(m_baseMagicLevel != baseMagicLevel) {
double oldBaseMagicLevel = m_baseMagicLevel;
m_baseMagicLevel = baseMagicLevel;
callLuaField("onBaseMagicLevelChange", baseMagicLevel, oldBaseMagicLevel);
}
}
void LocalPlayer::setSoul(double soul)
{
if(m_soul != soul) {
double oldSoul = m_soul;
m_soul = soul;
callLuaField("onSoulChange", soul, oldSoul);
}
}
void LocalPlayer::setStamina(double stamina)
{
if(m_stamina != stamina) {
double oldStamina = m_stamina;
m_stamina = stamina;
callLuaField("onStaminaChange", stamina, oldStamina);
}
}
void LocalPlayer::setInventoryItem(Otc::InventorySlot inventory, const ItemPtr& item)
{
if(inventory >= Otc::LastInventorySlot) {
g_logger.traceError("invalid slot");
return;
}
if(m_inventoryItems[inventory] != item) {
ItemPtr oldItem = m_inventoryItems[inventory];
m_inventoryItems[inventory] = item;
callLuaField("onInventoryChange", inventory, item, oldItem);
}
}
void LocalPlayer::setVocation(int vocation)
{
if(m_vocation != vocation) {
int oldVocation = m_vocation;
m_vocation = vocation;
callLuaField("onVocationChange", vocation, oldVocation);
}
}
void LocalPlayer::setPremium(bool premium)
{
if(m_premium != premium) {
m_premium = premium;
callLuaField("onPremiumChange", premium);
}
}
void LocalPlayer::setRegenerationTime(double regenerationTime)
{
if(m_regenerationTime != regenerationTime) {
double oldRegenerationTime = m_regenerationTime;
m_regenerationTime = regenerationTime;
callLuaField("onRegenerationChange", regenerationTime, oldRegenerationTime);
}
}
void LocalPlayer::setOfflineTrainingTime(double offlineTrainingTime)
{
if(m_offlineTrainingTime != offlineTrainingTime) {
double oldOfflineTrainingTime = m_offlineTrainingTime;
m_offlineTrainingTime = offlineTrainingTime;
callLuaField("onOfflineTrainingChange", offlineTrainingTime, oldOfflineTrainingTime);
}
}
void LocalPlayer::setSpells(const std::vector<int>& spells)
{
if(m_spells != spells) {
std::vector<int> oldSpells = m_spells;
m_spells = spells;
callLuaField("onSpellsChange", spells, oldSpells);
}
}
void LocalPlayer::setBlessings(int blessings)
{
if(blessings != m_blessings) {
int oldBlessings = m_blessings;
m_blessings = blessings;
callLuaField("onBlessingsChange", blessings, oldBlessings);
}
}
bool LocalPlayer::hasSight(const Position& pos)
{
return m_position.isInRange(pos, g_map.getAwareRange().left - 1, g_map.getAwareRange().top - 1);
}

View File

@ -1,205 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef LOCALPLAYER_H
#define LOCALPLAYER_H
#include "player.h"
#include "walkmatrix.h"
// @bindclass
class LocalPlayer : public Player
{
enum {
PREWALK_TIMEOUT = 1000
};
public:
LocalPlayer();
void draw(const Point& dest, bool animate = true, LightView* lightView = nullptr) override;
void unlockWalk() { m_walkLockExpiration = 0; }
void lockWalk(int millis = 200);
void stopAutoWalk();
bool autoWalk(Position destination, bool retry = false);
bool canWalk(Otc::Direction direction, bool ignoreLock = false);
bool isWalkLocked() {
return (m_walkLockExpiration != 0 && g_clock.millis() < m_walkLockExpiration);
}
void turn(Otc::Direction) override;
void setStates(int states);
void setSkill(Otc::Skill skill, int level, int levelPercent);
void setBaseSkill(Otc::Skill skill, int baseLevel);
void setHealth(double health, double maxHealth);
void setFreeCapacity(double freeCapacity);
void setTotalCapacity(double totalCapacity);
void setExperience(double experience);
void setLevel(double level, double levelPercent);
void setMana(double mana, double maxMana);
void setMagicLevel(double magicLevel, double magicLevelPercent);
void setBaseMagicLevel(double baseMagicLevel);
void setSoul(double soul);
void setStamina(double stamina);
void setKnown(bool known) { m_known = known; }
void setPendingGame(bool pending) { m_pending = pending; }
void setInventoryItem(Otc::InventorySlot inventory, const ItemPtr& item);
void setVocation(int vocation);
void setPremium(bool premium);
void setRegenerationTime(double regenerationTime);
void setOfflineTrainingTime(double offlineTrainingTime);
void setSpells(const std::vector<int>& spells);
void setBlessings(int blessings);
int getStates() { return m_states; }
int getSkillLevel(Otc::Skill skill) { return m_skillsLevel[skill]; }
int getSkillBaseLevel(Otc::Skill skill) { return m_skillsBaseLevel[skill]; }
int getSkillLevelPercent(Otc::Skill skill) { return m_skillsLevelPercent[skill]; }
int getVocation() { return m_vocation; }
double getHealth() { return m_health; }
double getMaxHealth() { return m_maxHealth; }
double getFreeCapacity() { return m_freeCapacity; }
double getTotalCapacity() { return m_totalCapacity; }
double getExperience() { return m_experience; }
double getLevel() { return m_level; }
double getLevelPercent() { return m_levelPercent; }
double getMana() { return m_mana; }
double getMaxMana() { return std::max<double>(m_mana, m_maxMana); }
double getMagicLevel() { return m_magicLevel; }
double getMagicLevelPercent() { return m_magicLevelPercent; }
double getBaseMagicLevel() { return m_baseMagicLevel; }
double getSoul() { return m_soul; }
double getStamina() { return m_stamina; }
double getRegenerationTime() { return m_regenerationTime; }
double getOfflineTrainingTime() { return m_offlineTrainingTime; }
std::vector<int> getSpells() { return m_spells; }
ItemPtr getInventoryItem(Otc::InventorySlot inventory) { return m_inventoryItems[inventory]; }
int getBlessings() { return m_blessings; }
bool hasSight(const Position& pos);
bool isKnown() { return m_known; }
bool isAutoWalking() { return m_autoWalkDestination.isValid(); }
bool isServerWalking() override { return m_serverWalking; }
bool isPremium() { return m_premium; }
bool isPendingGame() { return m_pending; }
LocalPlayerPtr asLocalPlayer() { return static_self_cast<LocalPlayer>(); }
bool isLocalPlayer() override { return true; }
void onAppear() override;
void onPositionChange(const Position& newPos, const Position& oldPos) override;
// pre walking
void preWalk(Otc::Direction direction);
bool isPreWalking() override { return !m_preWalking.empty(); }
Position getPrewalkingPosition(bool beforePrewalk = false) override {
if(m_preWalking.empty())
return m_position;
else if (!beforePrewalk && m_preWalking.size() == 1)
return m_position;
auto ret = m_preWalking.rbegin();
if(!beforePrewalk)
ret++;
return *ret;
}
uint32_t getWalkPrediction(const Position& pos)
{
return m_walkMatrix.get(pos);
};
std::string dumpWalkMatrix()
{
return m_walkMatrix.dump();
}
void startServerWalking() { m_serverWalking = true; }
void finishServerWalking() { m_serverWalking = false; }
protected:
void walk(const Position& oldPos, const Position& newPos);
void cancelWalk(Otc::Direction direction = Otc::InvalidDirection);
void cancelNewWalk(Otc::Direction dir);
bool predictiveCancelWalk(const Position& pos, uint32_t predictionId, Otc::Direction dir);
bool retryAutoWalk();
void stopWalk();
friend class Game;
protected:
void updateWalkOffset(int totalPixelsWalked, bool inNextFrame = false) override;
void updateWalk() override;
void terminateWalk() override;
private:
// walk related
Position m_autoWalkDestination;
Position m_lastAutoWalkPosition;
int m_lastAutoWalkRetries = 0;
ScheduledEventPtr m_serverWalkEndEvent;
ScheduledEventPtr m_autoWalkContinueEvent;
ticks_t m_walkLockExpiration;
// walking and pre walking
std::list<Position> m_preWalking;
bool m_serverWalking = false;
bool m_lastPrewalkDone = false;
WalkMatrix m_walkMatrix;
bool m_premium = false;
bool m_known = false;
bool m_pending = false;
ItemPtr m_inventoryItems[Otc::LastInventorySlot];
Timer m_idleTimer;
std::array<int, Otc::LastSkill> m_skillsLevel;
std::array<int, Otc::LastSkill> m_skillsBaseLevel;
std::array<int, Otc::LastSkill> m_skillsLevelPercent;
std::vector<int> m_spells;
int m_states;
int m_vocation;
int m_blessings;
double m_health;
double m_maxHealth;
double m_freeCapacity;
double m_totalCapacity;
double m_experience;
double m_level;
double m_levelPercent;
double m_mana;
double m_maxMana;
double m_magicLevel;
double m_magicLevelPercent;
double m_baseMagicLevel;
double m_soul;
double m_stamina;
double m_regenerationTime;
double m_offlineTrainingTime;
};
#endif

View File

@ -1,933 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "client.h"
#include "luavaluecasts_client.h"
#include "game.h"
#include "tile.h"
#include "houses.h"
#include "towns.h"
#include "container.h"
#include "item.h"
#include "effect.h"
#include "missile.h"
#include "statictext.h"
#include "animatedtext.h"
#include "creature.h"
#include "player.h"
#include "localplayer.h"
#include "map.h"
#include "minimap.h"
#include "thingtypemanager.h"
#include "spritemanager.h"
#include "shadermanager.h"
#include "protocolgame.h"
#include "uiitem.h"
#include "uicreature.h"
#include "uimap.h"
#include "uiminimap.h"
#include "uimapanchorlayout.h"
#include "uiprogressrect.h"
#include "uisprite.h"
#include "outfit.h"
#include <framework/luaengine/luainterface.h>
void Client::registerLuaFunctions()
{
g_lua.registerSingletonClass("g_things");
g_lua.bindSingletonFunction("g_things", "loadDat", &ThingTypeManager::loadDat, &g_things);
#ifdef WITH_ENCRYPTION
g_lua.bindSingletonFunction("g_things", "saveDat", &ThingTypeManager::saveDat, &g_things);
g_lua.bindSingletonFunction("g_things", "dumpTextures", &ThingTypeManager::dumpTextures, &g_things);
g_lua.bindSingletonFunction("g_things", "replaceTextures", &ThingTypeManager::replaceTextures, &g_things);
#endif
g_lua.bindSingletonFunction("g_things", "loadOtb", &ThingTypeManager::loadOtb, &g_things);
g_lua.bindSingletonFunction("g_things", "loadXml", &ThingTypeManager::loadXml, &g_things);
g_lua.bindSingletonFunction("g_things", "loadOtml", &ThingTypeManager::loadOtml, &g_things);
g_lua.bindSingletonFunction("g_things", "isDatLoaded", &ThingTypeManager::isDatLoaded, &g_things);
g_lua.bindSingletonFunction("g_things", "isOtbLoaded", &ThingTypeManager::isOtbLoaded, &g_things);
g_lua.bindSingletonFunction("g_things", "getDatSignature", &ThingTypeManager::getDatSignature, &g_things);
g_lua.bindSingletonFunction("g_things", "getContentRevision", &ThingTypeManager::getContentRevision, &g_things);
g_lua.bindSingletonFunction("g_things", "getThingType", &ThingTypeManager::getThingType, &g_things);
g_lua.bindSingletonFunction("g_things", "getItemType", &ThingTypeManager::getItemType, &g_things);
g_lua.bindSingletonFunction("g_things", "getThingTypes", &ThingTypeManager::getThingTypes, &g_things);
g_lua.bindSingletonFunction("g_things", "findItemTypeByClientId", &ThingTypeManager::findItemTypeByClientId, &g_things);
g_lua.bindSingletonFunction("g_things", "findItemTypeByName", &ThingTypeManager::findItemTypeByName, &g_things);
g_lua.bindSingletonFunction("g_things", "findItemTypesByName", &ThingTypeManager::findItemTypesByName, &g_things);
g_lua.bindSingletonFunction("g_things", "findItemTypesByString", &ThingTypeManager::findItemTypesByString, &g_things);
g_lua.bindSingletonFunction("g_things", "findItemTypeByCategory", &ThingTypeManager::findItemTypeByCategory, &g_things);
g_lua.bindSingletonFunction("g_things", "findThingTypeByAttr", &ThingTypeManager::findThingTypeByAttr, &g_things);
g_lua.bindSingletonFunction("g_things", "getMarketCategories", &ThingTypeManager::getMarketCategories, &g_things);
g_lua.registerSingletonClass("g_houses");
g_lua.bindSingletonFunction("g_houses", "clear", &HouseManager::clear, &g_houses);
g_lua.bindSingletonFunction("g_houses", "load", &HouseManager::load, &g_houses);
g_lua.bindSingletonFunction("g_houses", "save", &HouseManager::save, &g_houses);
g_lua.bindSingletonFunction("g_houses", "getHouse", &HouseManager::getHouse, &g_houses);
g_lua.bindSingletonFunction("g_houses", "getHouseByName", &HouseManager::getHouseByName, &g_houses);
g_lua.bindSingletonFunction("g_houses", "addHouse", &HouseManager::addHouse, &g_houses);
g_lua.bindSingletonFunction("g_houses", "removeHouse", &HouseManager::removeHouse, &g_houses);
g_lua.bindSingletonFunction("g_houses", "getHouseList", &HouseManager::getHouseList, &g_houses);
g_lua.bindSingletonFunction("g_houses", "filterHouses", &HouseManager::filterHouses, &g_houses);
g_lua.bindSingletonFunction("g_houses", "sort", &HouseManager::sort, &g_houses);
g_lua.registerSingletonClass("g_towns");
g_lua.bindSingletonFunction("g_towns", "getTown", &TownManager::getTown, &g_towns);
g_lua.bindSingletonFunction("g_towns", "getTownByName",&TownManager::getTownByName,&g_towns);
g_lua.bindSingletonFunction("g_towns", "addTown", &TownManager::addTown, &g_towns);
g_lua.bindSingletonFunction("g_towns", "removeTown", &TownManager::removeTown, &g_towns);
g_lua.bindSingletonFunction("g_towns", "getTowns", &TownManager::getTowns, &g_towns);
g_lua.bindSingletonFunction("g_towns", "sort", &TownManager::sort, &g_towns);
g_lua.registerSingletonClass("g_sprites");
g_lua.bindSingletonFunction("g_sprites", "loadSpr", &SpriteManager::loadSpr, &g_sprites);
#ifdef WITH_ENCRYPTION
g_lua.bindSingletonFunction("g_sprites", "saveSpr", &SpriteManager::saveSpr, &g_sprites);
g_lua.bindSingletonFunction("g_sprites", "dumpSprites", &SpriteManager::dumpSprites, &g_sprites);
g_lua.bindSingletonFunction("g_sprites", "encryptSprites", &SpriteManager::encryptSprites, &g_sprites);
#endif
g_lua.bindSingletonFunction("g_sprites", "unload", &SpriteManager::unload, &g_sprites);
g_lua.bindSingletonFunction("g_sprites", "isLoaded", &SpriteManager::isLoaded, &g_sprites);
g_lua.bindSingletonFunction("g_sprites", "getSprSignature", &SpriteManager::getSignature, &g_sprites);
g_lua.bindSingletonFunction("g_sprites", "getSpritesCount", &SpriteManager::getSpritesCount, &g_sprites);
g_lua.registerSingletonClass("g_map");
g_lua.bindSingletonFunction("g_map", "isLookPossible", &Map::isLookPossible, &g_map);
g_lua.bindSingletonFunction("g_map", "isCovered", &Map::isCovered, &g_map);
g_lua.bindSingletonFunction("g_map", "isCompletelyCovered", &Map::isCompletelyCovered, &g_map);
g_lua.bindSingletonFunction("g_map", "addThing", &Map::addThing, &g_map);
g_lua.bindSingletonFunction("g_map", "getThing", &Map::getThing, &g_map);
g_lua.bindSingletonFunction("g_map", "removeThingByPos", &Map::removeThingByPos, &g_map);
g_lua.bindSingletonFunction("g_map", "removeThing", &Map::removeThing, &g_map);
g_lua.bindSingletonFunction("g_map", "colorizeThing", &Map::colorizeThing, &g_map);
g_lua.bindSingletonFunction("g_map", "removeThingColor", &Map::removeThingColor, &g_map);
g_lua.bindSingletonFunction("g_map", "clean", &Map::clean, &g_map);
g_lua.bindSingletonFunction("g_map", "cleanTile", &Map::cleanTile, &g_map);
g_lua.bindSingletonFunction("g_map", "cleanTexts", &Map::cleanTexts, &g_map);
g_lua.bindSingletonFunction("g_map", "getTile", &Map::getTile, &g_map);
g_lua.bindSingletonFunction("g_map", "getOrCreateTile", &Map::getOrCreateTile, &g_map);
g_lua.bindSingletonFunction("g_map", "getTiles", &Map::getTiles, &g_map);
g_lua.bindSingletonFunction("g_map", "setCentralPosition", &Map::setCentralPosition, &g_map);
g_lua.bindSingletonFunction("g_map", "getCentralPosition", &Map::getCentralPosition, &g_map);
g_lua.bindSingletonFunction("g_map", "getCreatureById", &Map::getCreatureById, &g_map);
g_lua.bindSingletonFunction("g_map", "removeCreatureById", &Map::removeCreatureById, &g_map);
g_lua.bindSingletonFunction("g_map", "getSpectators", &Map::getSpectators, &g_map);
g_lua.bindSingletonFunction("g_map", "getSpectatorsInRange", &Map::getSpectatorsInRange, &g_map);
g_lua.bindSingletonFunction("g_map", "getSpectatorsInRangeEx", &Map::getSpectatorsInRangeEx, &g_map);
g_lua.bindSingletonFunction("g_map", "getSpectatorsByPattern", &Map::getSpectatorsByPattern, &g_map);
g_lua.bindSingletonFunction("g_map", "findPath", &Map::findPath, &g_map);
g_lua.bindSingletonFunction("g_map", "loadOtbm", &Map::loadOtbm, &g_map);
g_lua.bindSingletonFunction("g_map", "saveOtbm", &Map::saveOtbm, &g_map);
g_lua.bindSingletonFunction("g_map", "loadOtcm", &Map::loadOtcm, &g_map);
g_lua.bindSingletonFunction("g_map", "saveOtcm", &Map::saveOtcm, &g_map);
g_lua.bindSingletonFunction("g_map", "getHouseFile", &Map::getHouseFile, &g_map);
g_lua.bindSingletonFunction("g_map", "setHouseFile", &Map::setHouseFile, &g_map);
g_lua.bindSingletonFunction("g_map", "getSpawnFile", &Map::getSpawnFile, &g_map);
g_lua.bindSingletonFunction("g_map", "setSpawnFile", &Map::setSpawnFile, &g_map);
g_lua.bindSingletonFunction("g_map", "createTile", &Map::createTile, &g_map);
g_lua.bindSingletonFunction("g_map", "setWidth", &Map::setWidth, &g_map);
g_lua.bindSingletonFunction("g_map", "setHeight", &Map::setHeight, &g_map);
g_lua.bindSingletonFunction("g_map", "getSize", &Map::getSize, &g_map);
g_lua.bindSingletonFunction("g_map", "setDescription", &Map::setDescription, &g_map);
g_lua.bindSingletonFunction("g_map", "getDescriptions", &Map::getDescriptions, &g_map);
g_lua.bindSingletonFunction("g_map", "clearDescriptions", &Map::clearDescriptions, &g_map);
g_lua.bindSingletonFunction("g_map", "setShowZone", &Map::setShowZone, &g_map);
g_lua.bindSingletonFunction("g_map", "setShowZones", &Map::setShowZones, &g_map);
g_lua.bindSingletonFunction("g_map", "setZoneColor", &Map::setZoneColor, &g_map);
g_lua.bindSingletonFunction("g_map", "setZoneOpacity", &Map::setZoneOpacity, &g_map);
g_lua.bindSingletonFunction("g_map", "getZoneOpacity", &Map::getZoneOpacity, &g_map);
g_lua.bindSingletonFunction("g_map", "getZoneColor", &Map::getZoneColor, &g_map);
g_lua.bindSingletonFunction("g_map", "showZones", &Map::showZones, &g_map);
g_lua.bindSingletonFunction("g_map", "showZone", &Map::showZone, &g_map);
g_lua.bindSingletonFunction("g_map", "setForceShowAnimations", &Map::setForceShowAnimations, &g_map);
g_lua.bindSingletonFunction("g_map", "isForcingAnimations", &Map::isForcingAnimations, &g_map);
g_lua.bindSingletonFunction("g_map", "isShowingAnimations", &Map::isShowingAnimations, &g_map);
g_lua.bindSingletonFunction("g_map", "setShowAnimations", &Map::setShowAnimations, &g_map);
g_lua.bindSingletonFunction("g_map", "findItemsById", &Map::findItemsById, &g_map);
g_lua.bindSingletonFunction("g_map", "getAwareRange", &Map::getAwareRangeAsSize, &g_map);
g_lua.bindSingletonFunction("g_map", "findEveryPath", &Map::findEveryPath, &g_map);
g_lua.bindSingletonFunction("g_map", "getMinimapColor", &Map::getMinimapColor, &g_map);
g_lua.bindSingletonFunction("g_map", "isPatchable", &Map::isPatchable, &g_map);
g_lua.bindSingletonFunction("g_map", "isWalkable", &Map::isWalkable, &g_map);
g_lua.bindSingletonFunction("g_map", "checkSightLine", &Map::checkSightLine, &g_map);
g_lua.bindSingletonFunction("g_map", "isSightClear", &Map::isSightClear, &g_map);
g_lua.registerSingletonClass("g_minimap");
g_lua.bindSingletonFunction("g_minimap", "clean", &Minimap::clean, &g_minimap);
g_lua.bindSingletonFunction("g_minimap", "loadImage", &Minimap::loadImage, &g_minimap);
g_lua.bindSingletonFunction("g_minimap", "saveImage", &Minimap::saveImage, &g_minimap);
g_lua.bindSingletonFunction("g_minimap", "loadOtmm", &Minimap::loadOtmm, &g_minimap);
g_lua.bindSingletonFunction("g_minimap", "saveOtmm", &Minimap::saveOtmm, &g_minimap);
g_lua.registerSingletonClass("g_creatures");
g_lua.bindSingletonFunction("g_creatures", "getCreatures", &CreatureManager::getCreatures, &g_creatures);
g_lua.bindSingletonFunction("g_creatures", "getCreatureByName", &CreatureManager::getCreatureByName, &g_creatures);
g_lua.bindSingletonFunction("g_creatures", "getCreatureByLook", &CreatureManager::getCreatureByLook, &g_creatures);
g_lua.bindSingletonFunction("g_creatures", "getSpawn", &CreatureManager::getSpawn, &g_creatures);
g_lua.bindSingletonFunction("g_creatures", "getSpawnForPlacePos", &CreatureManager::getSpawnForPlacePos, &g_creatures);
g_lua.bindSingletonFunction("g_creatures", "addSpawn", &CreatureManager::addSpawn, &g_creatures);
g_lua.bindSingletonFunction("g_creatures", "loadMonsters", &CreatureManager::loadMonsters, &g_creatures);
g_lua.bindSingletonFunction("g_creatures", "loadNpcs", &CreatureManager::loadNpcs, &g_creatures);
g_lua.bindSingletonFunction("g_creatures", "loadSingleCreature", &CreatureManager::loadSingleCreature, &g_creatures);
g_lua.bindSingletonFunction("g_creatures", "loadSpawns", &CreatureManager::loadSpawns, &g_creatures);
g_lua.bindSingletonFunction("g_creatures", "saveSpawns", &CreatureManager::saveSpawns, &g_creatures);
g_lua.bindSingletonFunction("g_creatures", "isLoaded", &CreatureManager::isLoaded, &g_creatures);
g_lua.bindSingletonFunction("g_creatures", "isSpawnLoaded", &CreatureManager::isSpawnLoaded, &g_creatures);
g_lua.bindSingletonFunction("g_creatures", "clear", &CreatureManager::clear, &g_creatures);
g_lua.bindSingletonFunction("g_creatures", "clearSpawns", &CreatureManager::clearSpawns, &g_creatures);
g_lua.bindSingletonFunction("g_creatures", "getSpawns", &CreatureManager::getSpawns, &g_creatures);
g_lua.bindSingletonFunction("g_creatures", "deleteSpawn", &CreatureManager::deleteSpawn, &g_creatures);
g_lua.registerSingletonClass("g_game");
g_lua.bindSingletonFunction("g_game", "loginWorld", &Game::loginWorld, &g_game);
g_lua.bindSingletonFunction("g_game", "cancelLogin", &Game::cancelLogin, &g_game);
g_lua.bindSingletonFunction("g_game", "forceLogout", &Game::forceLogout, &g_game);
g_lua.bindSingletonFunction("g_game", "safeLogout", &Game::safeLogout, &g_game);
g_lua.bindSingletonFunction("g_game", "walk", &Game::walk, &g_game);
g_lua.bindSingletonFunction("g_game", "autoWalk", &Game::autoWalk, &g_game);
g_lua.bindSingletonFunction("g_game", "turn", &Game::turn, &g_game);
g_lua.bindSingletonFunction("g_game", "stop", &Game::stop, &g_game);
g_lua.bindSingletonFunction("g_game", "look", &Game::look, &g_game);
g_lua.bindSingletonFunction("g_game", "move", &Game::move, &g_game);
g_lua.bindSingletonFunction("g_game", "moveRaw", &Game::moveRaw, &g_game);
g_lua.bindSingletonFunction("g_game", "moveToParentContainer", &Game::moveToParentContainer, &g_game);
g_lua.bindSingletonFunction("g_game", "rotate", &Game::rotate, &g_game);
g_lua.bindSingletonFunction("g_game", "wrap", &Game::wrap, &g_game);
g_lua.bindSingletonFunction("g_game", "use", &Game::use, &g_game);
g_lua.bindSingletonFunction("g_game", "useWith", &Game::useWith, &g_game);
g_lua.bindSingletonFunction("g_game", "useInventoryItem", &Game::useInventoryItem, &g_game);
g_lua.bindSingletonFunction("g_game", "useInventoryItemWith", &Game::useInventoryItemWith, &g_game);
g_lua.bindSingletonFunction("g_game", "findItemInContainers", &Game::findItemInContainers, &g_game);
g_lua.bindSingletonFunction("g_game", "open", &Game::open, &g_game);
g_lua.bindSingletonFunction("g_game", "openParent", &Game::openParent, &g_game);
g_lua.bindSingletonFunction("g_game", "close", &Game::close, &g_game);
g_lua.bindSingletonFunction("g_game", "refreshContainer", &Game::refreshContainer, &g_game);
g_lua.bindSingletonFunction("g_game", "attack", &Game::attack, &g_game);
g_lua.bindSingletonFunction("g_game", "cancelAttack", &Game::cancelAttack, &g_game);
g_lua.bindSingletonFunction("g_game", "follow", &Game::follow, &g_game);
g_lua.bindSingletonFunction("g_game", "cancelFollow", &Game::cancelFollow, &g_game);
g_lua.bindSingletonFunction("g_game", "cancelAttackAndFollow", &Game::cancelAttackAndFollow, &g_game);
g_lua.bindSingletonFunction("g_game", "talk", &Game::talk, &g_game);
g_lua.bindSingletonFunction("g_game", "talkChannel", &Game::talkChannel, &g_game);
g_lua.bindSingletonFunction("g_game", "talkPrivate", &Game::talkPrivate, &g_game);
g_lua.bindSingletonFunction("g_game", "openPrivateChannel", &Game::openPrivateChannel, &g_game);
g_lua.bindSingletonFunction("g_game", "requestChannels", &Game::requestChannels, &g_game);
g_lua.bindSingletonFunction("g_game", "joinChannel", &Game::joinChannel, &g_game);
g_lua.bindSingletonFunction("g_game", "leaveChannel", &Game::leaveChannel, &g_game);
g_lua.bindSingletonFunction("g_game", "closeNpcChannel", &Game::closeNpcChannel, &g_game);
g_lua.bindSingletonFunction("g_game", "openOwnChannel", &Game::openOwnChannel, &g_game);
g_lua.bindSingletonFunction("g_game", "inviteToOwnChannel", &Game::inviteToOwnChannel, &g_game);
g_lua.bindSingletonFunction("g_game", "excludeFromOwnChannel", &Game::excludeFromOwnChannel, &g_game);
g_lua.bindSingletonFunction("g_game", "partyInvite", &Game::partyInvite, &g_game);
g_lua.bindSingletonFunction("g_game", "partyJoin", &Game::partyJoin, &g_game);
g_lua.bindSingletonFunction("g_game", "partyRevokeInvitation", &Game::partyRevokeInvitation, &g_game);
g_lua.bindSingletonFunction("g_game", "partyPassLeadership", &Game::partyPassLeadership, &g_game);
g_lua.bindSingletonFunction("g_game", "partyLeave", &Game::partyLeave, &g_game);
g_lua.bindSingletonFunction("g_game", "partyShareExperience", &Game::partyShareExperience, &g_game);
g_lua.bindSingletonFunction("g_game", "requestOutfit", &Game::requestOutfit, &g_game);
g_lua.bindSingletonFunction("g_game", "changeOutfit", &Game::changeOutfit, &g_game);
g_lua.bindSingletonFunction("g_game", "addVip", &Game::addVip, &g_game);
g_lua.bindSingletonFunction("g_game", "removeVip", &Game::removeVip, &g_game);
g_lua.bindSingletonFunction("g_game", "editVip", &Game::editVip, &g_game);
g_lua.bindSingletonFunction("g_game", "setChaseMode", &Game::setChaseMode, &g_game);
g_lua.bindSingletonFunction("g_game", "setFightMode", &Game::setFightMode, &g_game);
g_lua.bindSingletonFunction("g_game", "setPVPMode", &Game::setPVPMode, &g_game);
g_lua.bindSingletonFunction("g_game", "setSafeFight", &Game::setSafeFight, &g_game);
g_lua.bindSingletonFunction("g_game", "getChaseMode", &Game::getChaseMode, &g_game);
g_lua.bindSingletonFunction("g_game", "getFightMode", &Game::getFightMode, &g_game);
g_lua.bindSingletonFunction("g_game", "getPVPMode", &Game::getPVPMode, &g_game);
g_lua.bindSingletonFunction("g_game", "getUnjustifiedPoints", &Game::getUnjustifiedPoints, &g_game);
g_lua.bindSingletonFunction("g_game", "getOpenPvpSituations", &Game::getOpenPvpSituations, &g_game);
g_lua.bindSingletonFunction("g_game", "isSafeFight", &Game::isSafeFight, &g_game);
g_lua.bindSingletonFunction("g_game", "inspectNpcTrade", &Game::inspectNpcTrade, &g_game);
g_lua.bindSingletonFunction("g_game", "buyItem", &Game::buyItem, &g_game);
g_lua.bindSingletonFunction("g_game", "sellItem", &Game::sellItem, &g_game);
g_lua.bindSingletonFunction("g_game", "closeNpcTrade", &Game::closeNpcTrade, &g_game);
g_lua.bindSingletonFunction("g_game", "requestTrade", &Game::requestTrade, &g_game);
g_lua.bindSingletonFunction("g_game", "inspectTrade", &Game::inspectTrade, &g_game);
g_lua.bindSingletonFunction("g_game", "acceptTrade", &Game::acceptTrade, &g_game);
g_lua.bindSingletonFunction("g_game", "rejectTrade", &Game::rejectTrade, &g_game);
g_lua.bindSingletonFunction("g_game", "openRuleViolation", &Game::openRuleViolation, &g_game);
g_lua.bindSingletonFunction("g_game", "closeRuleViolation", &Game::closeRuleViolation, &g_game);
g_lua.bindSingletonFunction("g_game", "cancelRuleViolation", &Game::cancelRuleViolation, &g_game);
g_lua.bindSingletonFunction("g_game", "reportBug", &Game::reportBug, &g_game);
g_lua.bindSingletonFunction("g_game", "reportRuleViolation", &Game::reportRuleViolation, &g_game);
g_lua.bindSingletonFunction("g_game", "debugReport", &Game::debugReport, &g_game);
g_lua.bindSingletonFunction("g_game", "editText", &Game::editText, &g_game);
g_lua.bindSingletonFunction("g_game", "editList", &Game::editList, &g_game);
g_lua.bindSingletonFunction("g_game", "requestQuestLog", &Game::requestQuestLog, &g_game);
g_lua.bindSingletonFunction("g_game", "requestQuestLine", &Game::requestQuestLine, &g_game);
g_lua.bindSingletonFunction("g_game", "equipItem", &Game::equipItem, &g_game);
g_lua.bindSingletonFunction("g_game", "equipItemId", &Game::equipItemId, &g_game);
g_lua.bindSingletonFunction("g_game", "mount", &Game::mount, &g_game);
g_lua.bindSingletonFunction("g_game", "setOutfitExtensions", &Game::setOutfitExtensions, &g_game);
g_lua.bindSingletonFunction("g_game", "requestItemInfo", &Game::requestItemInfo, &g_game);
g_lua.bindSingletonFunction("g_game", "ping", &Game::ping, &g_game);
g_lua.bindSingletonFunction("g_game", "setPingDelay", &Game::setPingDelay, &g_game);
g_lua.bindSingletonFunction("g_game", "changeMapAwareRange", &Game::changeMapAwareRange, &g_game);
g_lua.bindSingletonFunction("g_game", "canPerformGameAction", &Game::canPerformGameAction, &g_game);
g_lua.bindSingletonFunction("g_game", "canReportBugs", &Game::canReportBugs, &g_game);
g_lua.bindSingletonFunction("g_game", "checkBotProtection", &Game::checkBotProtection, &g_game);
g_lua.bindSingletonFunction("g_game", "isOnline", &Game::isOnline, &g_game);
g_lua.bindSingletonFunction("g_game", "isLogging", &Game::isLogging, &g_game);
g_lua.bindSingletonFunction("g_game", "isDead", &Game::isDead, &g_game);
g_lua.bindSingletonFunction("g_game", "isAttacking", &Game::isAttacking, &g_game);
g_lua.bindSingletonFunction("g_game", "isFollowing", &Game::isFollowing, &g_game);
g_lua.bindSingletonFunction("g_game", "isConnectionOk", &Game::isConnectionOk, &g_game);
g_lua.bindSingletonFunction("g_game", "getPing", &Game::getPing, &g_game);
g_lua.bindSingletonFunction("g_game", "getContainer", &Game::getContainer, &g_game);
g_lua.bindSingletonFunction("g_game", "getContainers", &Game::getContainers, &g_game);
g_lua.bindSingletonFunction("g_game", "getVips", &Game::getVips, &g_game);
g_lua.bindSingletonFunction("g_game", "getAttackingCreature", &Game::getAttackingCreature, &g_game);
g_lua.bindSingletonFunction("g_game", "getFollowingCreature", &Game::getFollowingCreature, &g_game);
g_lua.bindSingletonFunction("g_game", "getServerBeat", &Game::getServerBeat, &g_game);
g_lua.bindSingletonFunction("g_game", "getLocalPlayer", &Game::getLocalPlayer, &g_game);
g_lua.bindSingletonFunction("g_game", "getProtocolGame", &Game::getProtocolGame, &g_game);
g_lua.bindSingletonFunction("g_game", "getProtocolVersion", &Game::getProtocolVersion, &g_game);
g_lua.bindSingletonFunction("g_game", "setProtocolVersion", &Game::setProtocolVersion, &g_game);
g_lua.bindSingletonFunction("g_game", "getCustomProtocolVersion", &Game::getCustomProtocolVersion, &g_game);
g_lua.bindSingletonFunction("g_game", "setCustomProtocolVersion", &Game::setCustomProtocolVersion, &g_game);
g_lua.bindSingletonFunction("g_game", "getClientVersion", &Game::getClientVersion, &g_game);
g_lua.bindSingletonFunction("g_game", "setClientVersion", &Game::setClientVersion, &g_game);
g_lua.bindSingletonFunction("g_game", "setCustomOs", &Game::setCustomOs, &g_game);
g_lua.bindSingletonFunction("g_game", "getOs", &Game::getOs, &g_game);
g_lua.bindSingletonFunction("g_game", "getCharacterName", &Game::getCharacterName, &g_game);
g_lua.bindSingletonFunction("g_game", "getWorldName", &Game::getWorldName, &g_game);
g_lua.bindSingletonFunction("g_game", "getGMActions", &Game::getGMActions, &g_game);
g_lua.bindSingletonFunction("g_game", "getFeature", &Game::getFeature, &g_game);
g_lua.bindSingletonFunction("g_game", "setFeature", &Game::setFeature, &g_game);
g_lua.bindSingletonFunction("g_game", "enableFeature", &Game::enableFeature, &g_game);
g_lua.bindSingletonFunction("g_game", "disableFeature", &Game::disableFeature, &g_game);
g_lua.bindSingletonFunction("g_game", "resetFeatures", &Game::resetFeatures, &g_game);
g_lua.bindSingletonFunction("g_game", "isGM", &Game::isGM, &g_game);
g_lua.bindSingletonFunction("g_game", "answerModalDialog", &Game::answerModalDialog, &g_game);
g_lua.bindSingletonFunction("g_game", "browseField", &Game::browseField, &g_game);
g_lua.bindSingletonFunction("g_game", "seekInContainer", &Game::seekInContainer, &g_game);
g_lua.bindSingletonFunction("g_game", "getLastWalkDir", &Game::getLastWalkDir, &g_game);
g_lua.bindSingletonFunction("g_game", "buyStoreOffer", &Game::buyStoreOffer, &g_game);
g_lua.bindSingletonFunction("g_game", "requestTransactionHistory", &Game::requestTransactionHistory, &g_game);
g_lua.bindSingletonFunction("g_game", "requestStoreOffers", &Game::requestStoreOffers, &g_game);
g_lua.bindSingletonFunction("g_game", "openStore", &Game::openStore, &g_game);
g_lua.bindSingletonFunction("g_game", "transferCoins", &Game::transferCoins, &g_game);
g_lua.bindSingletonFunction("g_game", "openTransactionHistory", &Game::openTransactionHistory, &g_game);
g_lua.bindSingletonFunction("g_game", "preyAction", &Game::preyAction, &g_game);
g_lua.bindSingletonFunction("g_game", "preyRequest", &Game::preyRequest, &g_game);
g_lua.bindSingletonFunction("g_game", "applyImbuement", &Game::applyImbuement, &g_game);
g_lua.bindSingletonFunction("g_game", "clearImbuement", &Game::clearImbuement, &g_game);
g_lua.bindSingletonFunction("g_game", "closeImbuingWindow", &Game::closeImbuingWindow, &g_game);
g_lua.bindSingletonFunction("g_game", "setTibiaCoins", &Game::setTibiaCoins, &g_game);
g_lua.bindSingletonFunction("g_game", "getTibiaCoins", &Game::getTibiaCoins, &g_game);
g_lua.bindSingletonFunction("g_game", "getTransferableTibiaCoins", &Game::getTransferableTibiaCoins, &g_game);
g_lua.bindSingletonFunction("g_game", "getMaxPreWalkingSteps", &Game::getMaxPreWalkingSteps, &g_game);
g_lua.bindSingletonFunction("g_game", "setMaxPreWalkingSteps", &Game::setMaxPreWalkingSteps, &g_game);
g_lua.bindSingletonFunction("g_game", "ignoreServerDirection", &Game::ignoreServerDirection, &g_game);
g_lua.bindSingletonFunction("g_game", "showRealDirection", &Game::showRealDirection, &g_game);
g_lua.bindSingletonFunction("g_game", "enableTileThingLuaCallback", &Game::enableTileThingLuaCallback, &g_game);
g_lua.bindSingletonFunction("g_game", "isTileThingLuaCallbackEnabled", &Game::isTileThingLuaCallbackEnabled, &g_game);
g_lua.bindSingletonFunction("g_game", "getRecivedPacketsCount", &Game::getRecivedPacketsCount, &g_game);
g_lua.bindSingletonFunction("g_game", "getRecivedPacketsSize", &Game::getRecivedPacketsSize, &g_game);
g_lua.registerSingletonClass("g_shaders");
g_lua.bindSingletonFunction("g_shaders", "createShader", &ShaderManager::createShader, &g_shaders);
g_lua.bindSingletonFunction("g_shaders", "createOutfitShader", &ShaderManager::createOutfitShader, &g_shaders);
g_lua.bindSingletonFunction("g_shaders", "addTexture", &ShaderManager::addTexture, &g_shaders);
g_lua.bindGlobalFunction("getOutfitColor", Outfit::getColor);
g_lua.bindGlobalFunction("getAngleFromPos", Position::getAngleFromPositions);
g_lua.bindGlobalFunction("getDirectionFromPos", Position::getDirectionFromPositions);
g_lua.registerClass<ProtocolGame, Protocol>();
g_lua.bindClassStaticFunction<ProtocolGame>("create", []{ return ProtocolGamePtr(new ProtocolGame); });
g_lua.bindClassMemberFunction<ProtocolGame>("login", &ProtocolGame::login);
g_lua.bindClassMemberFunction<ProtocolGame>("sendExtendedOpcode", &ProtocolGame::sendExtendedOpcode);
g_lua.bindClassMemberFunction<ProtocolGame>("addPosition", &ProtocolGame::addPosition);
g_lua.bindClassMemberFunction<ProtocolGame>("setMapDescription", &ProtocolGame::setMapDescription);
g_lua.bindClassMemberFunction<ProtocolGame>("setFloorDescription", &ProtocolGame::setFloorDescription);
g_lua.bindClassMemberFunction<ProtocolGame>("setTileDescription", &ProtocolGame::setTileDescription);
g_lua.bindClassMemberFunction<ProtocolGame>("getOutfit", &ProtocolGame::getOutfit);
g_lua.bindClassMemberFunction<ProtocolGame>("getThing", &ProtocolGame::getThing);
g_lua.bindClassMemberFunction<ProtocolGame>("getCreature", &ProtocolGame::getCreature);
g_lua.bindClassMemberFunction<ProtocolGame>("getItem", &ProtocolGame::getItem);
g_lua.bindClassMemberFunction<ProtocolGame>("getPosition", &ProtocolGame::getPosition);
g_lua.registerClass<Container>();
g_lua.bindClassMemberFunction<Container>("getItem", &Container::getItem);
g_lua.bindClassMemberFunction<Container>("getItems", &Container::getItems);
g_lua.bindClassMemberFunction<Container>("getItemsCount", &Container::getItemsCount);
g_lua.bindClassMemberFunction<Container>("getSlotPosition", &Container::getSlotPosition);
g_lua.bindClassMemberFunction<Container>("getName", &Container::getName);
g_lua.bindClassMemberFunction<Container>("getId", &Container::getId);
g_lua.bindClassMemberFunction<Container>("getCapacity", &Container::getCapacity);
g_lua.bindClassMemberFunction<Container>("getContainerItem", &Container::getContainerItem);
g_lua.bindClassMemberFunction<Container>("hasParent", &Container::hasParent);
g_lua.bindClassMemberFunction<Container>("isClosed", &Container::isClosed);
g_lua.bindClassMemberFunction<Container>("isUnlocked", &Container::isUnlocked);
g_lua.bindClassMemberFunction<Container>("hasPages", &Container::hasPages);
g_lua.bindClassMemberFunction<Container>("getSize", &Container::getSize);
g_lua.bindClassMemberFunction<Container>("getFirstIndex", &Container::getFirstIndex);
g_lua.registerClass<Thing>();
g_lua.bindClassMemberFunction<Thing>("setId", &Thing::setId);
g_lua.bindClassMemberFunction<Thing>("setPosition", &Thing::setPosition);
g_lua.bindClassMemberFunction<Thing>("getId", &Thing::getId);
g_lua.bindClassMemberFunction<Thing>("getPosition", &Thing::getPosition);
g_lua.bindClassMemberFunction<Thing>("getStackPriority", &Thing::getStackPriority);
g_lua.bindClassMemberFunction<Thing>("getStackPos", &Thing::getStackPos);
g_lua.bindClassMemberFunction<Thing>("getAnimationPhases", &Thing::getAnimationPhases);
g_lua.bindClassMemberFunction<Thing>("getTile", &Thing::getTile);
g_lua.bindClassMemberFunction<Thing>("setMarked", &Thing::setMarked);
g_lua.bindClassMemberFunction<Thing>("isItem", &Thing::isItem);
g_lua.bindClassMemberFunction<Thing>("isMonster", &Thing::isMonster);
g_lua.bindClassMemberFunction<Thing>("isNpc", &Thing::isNpc);
g_lua.bindClassMemberFunction<Thing>("isCreature", &Thing::isCreature);
g_lua.bindClassMemberFunction<Thing>("isEffect", &Thing::isEffect);
g_lua.bindClassMemberFunction<Thing>("isMissile", &Thing::isMissile);
g_lua.bindClassMemberFunction<Thing>("isPlayer", &Thing::isPlayer);
g_lua.bindClassMemberFunction<Thing>("isLocalPlayer", &Thing::isLocalPlayer);
g_lua.bindClassMemberFunction<Thing>("isAnimatedText", &Thing::isAnimatedText);
g_lua.bindClassMemberFunction<Thing>("isStaticText", &Thing::isStaticText);
g_lua.bindClassMemberFunction<Thing>("isGround", &Thing::isGround);
g_lua.bindClassMemberFunction<Thing>("isGroundBorder", &Thing::isGroundBorder);
g_lua.bindClassMemberFunction<Thing>("isOnBottom", &Thing::isOnBottom);
g_lua.bindClassMemberFunction<Thing>("isOnTop", &Thing::isOnTop);
g_lua.bindClassMemberFunction<Thing>("isContainer", &Thing::isContainer);
g_lua.bindClassMemberFunction<Thing>("isForceUse", &Thing::isForceUse);
g_lua.bindClassMemberFunction<Thing>("isMultiUse", &Thing::isMultiUse);
g_lua.bindClassMemberFunction<Thing>("isRotateable", &Thing::isRotateable);
g_lua.bindClassMemberFunction<Thing>("isNotMoveable", &Thing::isNotMoveable);
g_lua.bindClassMemberFunction<Thing>("isPickupable", &Thing::isPickupable);
g_lua.bindClassMemberFunction<Thing>("isIgnoreLook", &Thing::isIgnoreLook);
g_lua.bindClassMemberFunction<Thing>("isStackable", &Thing::isStackable);
g_lua.bindClassMemberFunction<Thing>("isHookSouth", &Thing::isHookSouth);
g_lua.bindClassMemberFunction<Thing>("isTranslucent", &Thing::isTranslucent);
g_lua.bindClassMemberFunction<Thing>("isFullGround", &Thing::isFullGround);
g_lua.bindClassMemberFunction<Thing>("isMarketable", &Thing::isMarketable);
g_lua.bindClassMemberFunction<Thing>("getMarketData", &Thing::getMarketData);
g_lua.bindClassMemberFunction<Thing>("isUsable", &Thing::isUsable);
g_lua.bindClassMemberFunction<Thing>("isWrapable", &Thing::isWrapable);
g_lua.bindClassMemberFunction<Thing>("isUnwrapable", &Thing::isUnwrapable);
g_lua.bindClassMemberFunction<Thing>("isTopEffect", &Thing::isTopEffect);
g_lua.bindClassMemberFunction<Thing>("isLyingCorpse", &Thing::isLyingCorpse);
g_lua.bindClassMemberFunction<Thing>("getParentContainer", &Thing::getParentContainer);
g_lua.bindClassMemberFunction<Thing>("hide", &Thing::hide);
g_lua.bindClassMemberFunction<Thing>("show", &Thing::show);
g_lua.bindClassMemberFunction<Thing>("setHidden", &Thing::setHidden);
g_lua.bindClassMemberFunction<Thing>("isHidden", &Thing::isHidden);
g_lua.registerClass<House>();
g_lua.bindClassStaticFunction<House>("create", []{ return HousePtr(new House); });
g_lua.bindClassMemberFunction<House>("setId", &House::setId);
g_lua.bindClassMemberFunction<House>("getId", &House::getId);
g_lua.bindClassMemberFunction<House>("setName", &House::setName);
g_lua.bindClassMemberFunction<House>("getName", &House::getName);
g_lua.bindClassMemberFunction<House>("setTownId", &House::setTownId);
g_lua.bindClassMemberFunction<House>("getTownId", &House::getTownId);
g_lua.bindClassMemberFunction<House>("setTile", &House::setTile);
g_lua.bindClassMemberFunction<House>("getTile", &House::getTile);
g_lua.bindClassMemberFunction<House>("setEntry", &House::setEntry);
g_lua.bindClassMemberFunction<House>("getEntry", &House::getEntry);
g_lua.bindClassMemberFunction<House>("addDoor", &House::addDoor);
g_lua.bindClassMemberFunction<House>("removeDoor", &House::removeDoor);
g_lua.bindClassMemberFunction<House>("removeDoorById", &House::removeDoorById);
g_lua.bindClassMemberFunction<House>("setSize", &House::setSize);
g_lua.bindClassMemberFunction<House>("getSize", &House::getSize);
g_lua.bindClassMemberFunction<House>("setRent", &House::setRent);
g_lua.bindClassMemberFunction<House>("getRent", &House::getRent);
g_lua.registerClass<Spawn>();
g_lua.bindClassStaticFunction<Spawn>("create", []{ return SpawnPtr(new Spawn); });
g_lua.bindClassMemberFunction<Spawn>("setRadius", &Spawn::setRadius);
g_lua.bindClassMemberFunction<Spawn>("getRadius", &Spawn::getRadius);
g_lua.bindClassMemberFunction<Spawn>("setCenterPos", &Spawn::setCenterPos);
g_lua.bindClassMemberFunction<Spawn>("getCenterPos", &Spawn::getCenterPos);
g_lua.bindClassMemberFunction<Spawn>("addCreature", &Spawn::addCreature);
g_lua.bindClassMemberFunction<Spawn>("removeCreature", &Spawn::removeCreature);
g_lua.bindClassMemberFunction<Spawn>("getCreatures", &Spawn::getCreatures);
g_lua.registerClass<Town>();
g_lua.bindClassStaticFunction<Town>("create", []{ return TownPtr(new Town); });
g_lua.bindClassMemberFunction<Town>("setId", &Town::setId);
g_lua.bindClassMemberFunction<Town>("setName", &Town::setName);
g_lua.bindClassMemberFunction<Town>("setPos", &Town::setPos);
g_lua.bindClassMemberFunction<Town>("setTemplePos", &Town::setPos); // alternative method
g_lua.bindClassMemberFunction<Town>("getId", &Town::getId);
g_lua.bindClassMemberFunction<Town>("getName", &Town::getName);
g_lua.bindClassMemberFunction<Town>("getPos", &Town::getPos);
g_lua.bindClassMemberFunction<Town>("getTemplePos", &Town::getPos); // alternative method
g_lua.registerClass<CreatureType>();
g_lua.bindClassStaticFunction<CreatureType>("create", []{ return CreatureTypePtr(new CreatureType); });
g_lua.bindClassMemberFunction<CreatureType>("setName", &CreatureType::setName);
g_lua.bindClassMemberFunction<CreatureType>("setOutfit", &CreatureType::setOutfit);
g_lua.bindClassMemberFunction<CreatureType>("setSpawnTime", &CreatureType::setSpawnTime);
g_lua.bindClassMemberFunction<CreatureType>("getName", &CreatureType::getName);
g_lua.bindClassMemberFunction<CreatureType>("getOutfit", &CreatureType::getOutfit);
g_lua.bindClassMemberFunction<CreatureType>("getSpawnTime", &CreatureType::getSpawnTime);
g_lua.bindClassMemberFunction<CreatureType>("cast", &CreatureType::cast);
g_lua.registerClass<Creature, Thing>();
g_lua.bindClassStaticFunction<Creature>("create", []{ return CreaturePtr(new Creature); });
g_lua.bindClassMemberFunction<Creature>("getId", &Creature::getId);
g_lua.bindClassMemberFunction<Creature>("getName", &Creature::getName);
g_lua.bindClassMemberFunction<Creature>("setName", &Creature::setName);
g_lua.bindClassMemberFunction<Creature>("setManaPercent", &LocalPlayer::setManaPercent);
g_lua.bindClassMemberFunction<Creature>("getManaPercent", &LocalPlayer::getManaPercent);
g_lua.bindClassMemberFunction<Creature>("setHealthPercent", &Creature::setHealthPercent);
g_lua.bindClassMemberFunction<Creature>("getHealthPercent", &Creature::getHealthPercent);
g_lua.bindClassMemberFunction<Creature>("getSpeed", &Creature::getSpeed);
g_lua.bindClassMemberFunction<Creature>("setSpeed", &Creature::setSpeed);
g_lua.bindClassMemberFunction<Creature>("getBaseSpeed", &Creature::getBaseSpeed);
g_lua.bindClassMemberFunction<Creature>("setBaseSpeed", &Creature::setBaseSpeed);
g_lua.bindClassMemberFunction<Creature>("getSkull", &Creature::getSkull);
g_lua.bindClassMemberFunction<Creature>("getShield", &Creature::getShield);
g_lua.bindClassMemberFunction<Creature>("getEmblem", &Creature::getEmblem);
g_lua.bindClassMemberFunction<Creature>("setSkull", &Creature::setSkull);
g_lua.bindClassMemberFunction<Creature>("setShield", &Creature::setShield);
g_lua.bindClassMemberFunction<Creature>("setEmblem", &Creature::setEmblem);
g_lua.bindClassMemberFunction<Creature>("getType", &Creature::getType);
g_lua.bindClassMemberFunction<Creature>("getIcon", &Creature::getIcon);
g_lua.bindClassMemberFunction<Creature>("setOutfit", &Creature::setOutfit);
g_lua.bindClassMemberFunction<Creature>("getOutfit", &Creature::getOutfit);
g_lua.bindClassMemberFunction<Creature>("setOutfitColor", &Creature::setOutfitColor);
g_lua.bindClassMemberFunction<Creature>("getDirection", &Creature::getDirection);
g_lua.bindClassMemberFunction<Creature>("getWalkDirection", &Creature::getWalkDirection);
g_lua.bindClassMemberFunction<Creature>("getStepDuration", &Creature::getStepDuration);
g_lua.bindClassMemberFunction<Creature>("getStepProgress", &Creature::getStepProgress);
g_lua.bindClassMemberFunction<Creature>("getWalkTicksElapsed", &Creature::getWalkTicksElapsed);
g_lua.bindClassMemberFunction<Creature>("getStepTicksLeft", &Creature::getStepTicksLeft);
g_lua.bindClassMemberFunction<Creature>("setDirection", &Creature::setDirection);
g_lua.bindClassMemberFunction<Creature>("setSkullTexture", &Creature::setSkullTexture);
g_lua.bindClassMemberFunction<Creature>("setShieldTexture", &Creature::setShieldTexture);
g_lua.bindClassMemberFunction<Creature>("setEmblemTexture", &Creature::setEmblemTexture);
g_lua.bindClassMemberFunction<Creature>("setTypeTexture", &Creature::setTypeTexture);
g_lua.bindClassMemberFunction<Creature>("setIconTexture", &Creature::setIconTexture);
g_lua.bindClassMemberFunction<Creature>("showStaticSquare", &Creature::showStaticSquare);
g_lua.bindClassMemberFunction<Creature>("hideStaticSquare", &Creature::hideStaticSquare);
g_lua.bindClassMemberFunction<Creature>("isWalking", &Creature::isWalking);
g_lua.bindClassMemberFunction<Creature>("isInvisible", &Creature::isInvisible);
g_lua.bindClassMemberFunction<Creature>("isDead", &Creature::isDead);
g_lua.bindClassMemberFunction<Creature>("isRemoved", &Creature::isRemoved);
g_lua.bindClassMemberFunction<Creature>("canBeSeen", &Creature::canBeSeen);
g_lua.bindClassMemberFunction<Creature>("canShoot", &Creature::canShoot);
g_lua.bindClassMemberFunction<Creature>("jump", &Creature::jump);
g_lua.bindClassMemberFunction<Creature>("getPrewalkingPosition", &Creature::getPrewalkingPosition);
g_lua.bindClassMemberFunction<Creature>("setInformationColor", &Creature::setInformationColor);
g_lua.bindClassMemberFunction<Creature>("resetInformationColor", &Creature::resetInformationColor);
g_lua.bindClassMemberFunction<Creature>("setInformationOffset", &Creature::setInformationOffset);
g_lua.bindClassMemberFunction<Creature>("getInformationOffset", &Creature::getInformationOffset);
g_lua.bindClassMemberFunction<Creature>("setText", &Creature::setText);
g_lua.bindClassMemberFunction<Creature>("getText", &Creature::getText);
g_lua.bindClassMemberFunction<Creature>("clearText", &Creature::clearText);
// widgets
g_lua.bindClassMemberFunction<Creature>("addTopWidget", &Creature::addTopWidget);
g_lua.bindClassMemberFunction<Creature>("addBottomWidget", &Creature::addBottomWidget);
g_lua.bindClassMemberFunction<Creature>("addDirectionalWidget", &Creature::addDirectionalWidget);
g_lua.bindClassMemberFunction<Creature>("removeTopWidget", &Creature::removeTopWidget);
g_lua.bindClassMemberFunction<Creature>("removeBottomWidget", &Creature::removeBottomWidget);
g_lua.bindClassMemberFunction<Creature>("removeDirectionalWidget", &Creature::removeDirectionalWidget);
g_lua.bindClassMemberFunction<Creature>("getTopWidgets", &Creature::getTopWidgets);
g_lua.bindClassMemberFunction<Creature>("getBottomWidgets", &Creature::getBottomWidgets);
g_lua.bindClassMemberFunction<Creature>("getDirectionalWdigets", &Creature::getDirectionalWdigets);
g_lua.bindClassMemberFunction<Creature>("clearWidgets", &Creature::clearWidgets);
g_lua.bindClassMemberFunction<Creature>("clearTopWidgets", &Creature::clearTopWidgets);
g_lua.bindClassMemberFunction<Creature>("clearBottomWidgets", &Creature::clearBottomWidgets);
g_lua.bindClassMemberFunction<Creature>("clearDirectionalWidgets", &Creature::clearDirectionalWidgets);
// progress bar
g_lua.bindClassMemberFunction<Creature>("setProgressBar", &Creature::setProgressBar);
g_lua.bindClassMemberFunction<Creature>("getProgressBarPercent", &Creature::getProgressBarPercent);
g_lua.registerClass<ItemType>();
g_lua.bindClassMemberFunction<ItemType>("getServerId", &ItemType::getServerId);
g_lua.bindClassMemberFunction<ItemType>("getClientId", &ItemType::getClientId);
g_lua.bindClassMemberFunction<ItemType>("isWritable", &ItemType::isWritable);
g_lua.registerClass<ThingType>();
g_lua.bindClassStaticFunction<ThingType>("create", []{ return ThingTypePtr(new ThingType); });
g_lua.bindClassMemberFunction<ThingType>("getId", &ThingType::getId);
g_lua.bindClassMemberFunction<ThingType>("getClothSlot", &ThingType::getClothSlot);
g_lua.bindClassMemberFunction<ThingType>("getCategory", &ThingType::getCategory);
g_lua.bindClassMemberFunction<ThingType>("getSize", &ThingType::getSize);
g_lua.bindClassMemberFunction<ThingType>("getWidth", &ThingType::getWidth);
g_lua.bindClassMemberFunction<ThingType>("getHeight", &ThingType::getHeight);
g_lua.bindClassMemberFunction<ThingType>("getDisplacement", &ThingType::getDisplacement);
g_lua.bindClassMemberFunction<ThingType>("getDisplacementX", &ThingType::getDisplacementX);
g_lua.bindClassMemberFunction<ThingType>("getDisplacementY", &ThingType::getDisplacementY);
g_lua.bindClassMemberFunction<ThingType>("getExactSize", &ThingType::getExactSize);
g_lua.bindClassMemberFunction<ThingType>("getRealSize", &ThingType::getRealSize);
g_lua.bindClassMemberFunction<ThingType>("getLayers", &ThingType::getLayers);
g_lua.bindClassMemberFunction<ThingType>("getNumPatternX", &ThingType::getNumPatternX);
g_lua.bindClassMemberFunction<ThingType>("getNumPatternY", &ThingType::getNumPatternY);
g_lua.bindClassMemberFunction<ThingType>("getNumPatternZ", &ThingType::getNumPatternZ);
g_lua.bindClassMemberFunction<ThingType>("getAnimationPhases", &ThingType::getAnimationPhases);
g_lua.bindClassMemberFunction<ThingType>("getGroundSpeed", &ThingType::getGroundSpeed);
g_lua.bindClassMemberFunction<ThingType>("getMaxTextLength", &ThingType::getMaxTextLength);
g_lua.bindClassMemberFunction<ThingType>("getLight", &ThingType::getLight);
g_lua.bindClassMemberFunction<ThingType>("getMinimapColor", &ThingType::getMinimapColor);
g_lua.bindClassMemberFunction<ThingType>("getLensHelp", &ThingType::getLensHelp);
g_lua.bindClassMemberFunction<ThingType>("getClothSlot", &ThingType::getClothSlot);
g_lua.bindClassMemberFunction<ThingType>("getElevation", &ThingType::getElevation);
g_lua.bindClassMemberFunction<ThingType>("isGround", &ThingType::isGround);
g_lua.bindClassMemberFunction<ThingType>("isGroundBorder", &ThingType::isGroundBorder);
g_lua.bindClassMemberFunction<ThingType>("isOnBottom", &ThingType::isOnBottom);
g_lua.bindClassMemberFunction<ThingType>("isOnTop", &ThingType::isOnTop);
g_lua.bindClassMemberFunction<ThingType>("isContainer", &ThingType::isContainer);
g_lua.bindClassMemberFunction<ThingType>("isStackable", &ThingType::isStackable);
g_lua.bindClassMemberFunction<ThingType>("isForceUse", &ThingType::isForceUse);
g_lua.bindClassMemberFunction<ThingType>("isMultiUse", &ThingType::isMultiUse);
g_lua.bindClassMemberFunction<ThingType>("isWritable", &ThingType::isWritable);
g_lua.bindClassMemberFunction<ThingType>("isChargeable", &ThingType::isChargeable);
g_lua.bindClassMemberFunction<ThingType>("isWritableOnce", &ThingType::isWritableOnce);
g_lua.bindClassMemberFunction<ThingType>("isFluidContainer", &ThingType::isFluidContainer);
g_lua.bindClassMemberFunction<ThingType>("isSplash", &ThingType::isSplash);
g_lua.bindClassMemberFunction<ThingType>("isNotWalkable", &ThingType::isNotWalkable);
g_lua.bindClassMemberFunction<ThingType>("isNotMoveable", &ThingType::isNotMoveable);
g_lua.bindClassMemberFunction<ThingType>("blockProjectile", &ThingType::blockProjectile);
g_lua.bindClassMemberFunction<ThingType>("isNotPathable", &ThingType::isNotPathable);
g_lua.bindClassMemberFunction<ThingType>("setPathable", &ThingType::setPathable);
g_lua.bindClassMemberFunction<ThingType>("isPickupable", &ThingType::isPickupable);
g_lua.bindClassMemberFunction<ThingType>("isHangable", &ThingType::isHangable);
g_lua.bindClassMemberFunction<ThingType>("isHookSouth", &ThingType::isHookSouth);
g_lua.bindClassMemberFunction<ThingType>("isHookEast", &ThingType::isHookEast);
g_lua.bindClassMemberFunction<ThingType>("isRotateable", &ThingType::isRotateable);
g_lua.bindClassMemberFunction<ThingType>("hasLight", &ThingType::hasLight);
g_lua.bindClassMemberFunction<ThingType>("isDontHide", &ThingType::isDontHide);
g_lua.bindClassMemberFunction<ThingType>("isTranslucent", &ThingType::isTranslucent);
g_lua.bindClassMemberFunction<ThingType>("hasDisplacement", &ThingType::hasDisplacement);
g_lua.bindClassMemberFunction<ThingType>("hasElevation", &ThingType::hasElevation);
g_lua.bindClassMemberFunction<ThingType>("isLyingCorpse", &ThingType::isLyingCorpse);
g_lua.bindClassMemberFunction<ThingType>("isAnimateAlways", &ThingType::isAnimateAlways);
g_lua.bindClassMemberFunction<ThingType>("hasMiniMapColor", &ThingType::hasMiniMapColor);
g_lua.bindClassMemberFunction<ThingType>("hasLensHelp", &ThingType::hasLensHelp);
g_lua.bindClassMemberFunction<ThingType>("isFullGround", &ThingType::isFullGround);
g_lua.bindClassMemberFunction<ThingType>("isIgnoreLook", &ThingType::isIgnoreLook);
g_lua.bindClassMemberFunction<ThingType>("isCloth", &ThingType::isCloth);
g_lua.bindClassMemberFunction<ThingType>("isMarketable", &ThingType::isMarketable);
g_lua.bindClassMemberFunction<ThingType>("getMarketData", &ThingType::getMarketData);
g_lua.bindClassMemberFunction<ThingType>("isUsable", &ThingType::isUsable);
g_lua.bindClassMemberFunction<ThingType>("isWrapable", &ThingType::isWrapable);
g_lua.bindClassMemberFunction<ThingType>("isUnwrapable", &ThingType::isUnwrapable);
g_lua.bindClassMemberFunction<ThingType>("isTopEffect", &ThingType::isTopEffect);
g_lua.bindClassMemberFunction<ThingType>("getSprites", &ThingType::getSprites);
g_lua.bindClassMemberFunction<ThingType>("hasAttribute", &ThingType::hasAttr);
g_lua.bindClassMemberFunction<ThingType>("exportImage", &ThingType::exportImage);
g_lua.registerClass<Item, Thing>();
g_lua.bindClassStaticFunction<Item>("create", &Item::create);
g_lua.bindClassStaticFunction<Item>("createOtb", &Item::createFromOtb);
g_lua.bindClassMemberFunction<Item>("clone", &Item::clone);
g_lua.bindClassMemberFunction<Item>("getContainerItems", &Item::getContainerItems);
g_lua.bindClassMemberFunction<Item>("getContainerItem", &Item::getContainerItem);
g_lua.bindClassMemberFunction<Item>("addContainerItem", &Item::addContainerItem);
g_lua.bindClassMemberFunction<Item>("addContainerItemIndexed", &Item::addContainerItemIndexed);
g_lua.bindClassMemberFunction<Item>("removeContainerItem", &Item::removeContainerItem);
g_lua.bindClassMemberFunction<Item>("clearContainerItems", &Item::clearContainerItems);
g_lua.bindClassMemberFunction<Item>("getContainerItem", &Item::getContainerItem);
g_lua.bindClassMemberFunction<Item>("setCount", &Item::setCount);
g_lua.bindClassMemberFunction<Item>("getCount", &Item::getCount);
g_lua.bindClassMemberFunction<Item>("getSubType", &Item::getSubType);
g_lua.bindClassMemberFunction<Item>("getCountOrSubType", &Item::getCountOrSubType);
g_lua.bindClassMemberFunction<Item>("getId", &Item::getId);
g_lua.bindClassMemberFunction<Item>("getServerId", &Item::getServerId);
g_lua.bindClassMemberFunction<Item>("getName", &Item::getName);
g_lua.bindClassMemberFunction<Item>("getDescription", &Item::getDescription);
g_lua.bindClassMemberFunction<Item>("getText", &Item::getText);
g_lua.bindClassMemberFunction<Item>("setDescription", &Item::setDescription);
g_lua.bindClassMemberFunction<Item>("setText", &Item::setText);
g_lua.bindClassMemberFunction<Item>("getUniqueId", &Item::getUniqueId);
g_lua.bindClassMemberFunction<Item>("getActionId", &Item::getActionId);
g_lua.bindClassMemberFunction<Item>("setUniqueId", &Item::setUniqueId);
g_lua.bindClassMemberFunction<Item>("setActionId", &Item::setActionId);
g_lua.bindClassMemberFunction<Item>("getTeleportDestination", &Item::getTeleportDestination);
g_lua.bindClassMemberFunction<Item>("setTeleportDestination", &Item::setTeleportDestination);
g_lua.bindClassMemberFunction<Item>("isStackable", &Item::isStackable);
g_lua.bindClassMemberFunction<Item>("isMarketable", &Item::isMarketable);
g_lua.bindClassMemberFunction<Item>("isFluidContainer", &Item::isFluidContainer);
g_lua.bindClassMemberFunction<Item>("getMarketData", &Item::getMarketData);
g_lua.bindClassMemberFunction<Item>("getClothSlot", &Item::getClothSlot);
g_lua.bindClassMemberFunction<Item>("getTooltip", &Item::getTooltip);
g_lua.bindClassMemberFunction<Item>("setTooltip", &Item::setTooltip);
g_lua.registerClass<Effect, Thing>();
g_lua.bindClassStaticFunction<Effect>("create", []{ return EffectPtr(new Effect); });
g_lua.bindClassMemberFunction<Effect>("setId", &Effect::setId);
g_lua.registerClass<Missile, Thing>();
g_lua.bindClassStaticFunction<Missile>("create", []{ return MissilePtr(new Missile); });
g_lua.bindClassMemberFunction<Missile>("setId", &Missile::setId);
g_lua.bindClassMemberFunction<Missile>("getId", &Missile::getId);
g_lua.bindClassMemberFunction<Missile>("getSource", &Missile::getSource);
g_lua.bindClassMemberFunction<Missile>("getDestination", &Missile::getDestination);
g_lua.registerClass<StaticText, Thing>();
g_lua.bindClassStaticFunction<StaticText>("create", []{ return StaticTextPtr(new StaticText); });
g_lua.bindClassMemberFunction<StaticText>("addMessage", &StaticText::addMessage);
g_lua.bindClassMemberFunction<StaticText>("addColoredMessage", &StaticText::addColoredMessage);
g_lua.bindClassMemberFunction<StaticText>("setText", &StaticText::setText);
g_lua.bindClassMemberFunction<StaticText>("setFont", &StaticText::setFont);
g_lua.bindClassMemberFunction<StaticText>("setColor", &StaticText::setColor);
g_lua.bindClassMemberFunction<StaticText>("getColor", &StaticText::getColor);
g_lua.bindClassMemberFunction<StaticText>("getText", &StaticText::getText);
g_lua.registerClass<AnimatedText, Thing>();
g_lua.bindClassMemberFunction<AnimatedText>("getText", &AnimatedText::getText);
g_lua.bindClassMemberFunction<AnimatedText>("getOffset", &AnimatedText::getOffset);
g_lua.bindClassMemberFunction<AnimatedText>("getColor", &AnimatedText::getColor);
g_lua.registerClass<Player, Creature>();
g_lua.registerClass<Npc, Creature>();
g_lua.registerClass<Monster, Creature>();
g_lua.registerClass<LocalPlayer, Player>();
g_lua.bindClassMemberFunction<LocalPlayer>("unlockWalk", &LocalPlayer::unlockWalk);
g_lua.bindClassMemberFunction<LocalPlayer>("lockWalk", &LocalPlayer::lockWalk);
g_lua.bindClassMemberFunction<LocalPlayer>("isWalkLocked", &LocalPlayer::isWalkLocked);
g_lua.bindClassMemberFunction<LocalPlayer>("canWalk", &LocalPlayer::canWalk);
g_lua.bindClassMemberFunction<LocalPlayer>("setStates", &LocalPlayer::setStates);
g_lua.bindClassMemberFunction<LocalPlayer>("setSkill", &LocalPlayer::setSkill);
g_lua.bindClassMemberFunction<LocalPlayer>("setHealth", &LocalPlayer::setHealth);
g_lua.bindClassMemberFunction<LocalPlayer>("setTotalCapacity", &LocalPlayer::setTotalCapacity);
g_lua.bindClassMemberFunction<LocalPlayer>("setFreeCapacity", &LocalPlayer::setFreeCapacity);
g_lua.bindClassMemberFunction<LocalPlayer>("setExperience", &LocalPlayer::setExperience);
g_lua.bindClassMemberFunction<LocalPlayer>("setLevel", &LocalPlayer::setLevel);
g_lua.bindClassMemberFunction<LocalPlayer>("setMana", &LocalPlayer::setMana);
g_lua.bindClassMemberFunction<LocalPlayer>("setMagicLevel", &LocalPlayer::setMagicLevel);
g_lua.bindClassMemberFunction<LocalPlayer>("setSoul", &LocalPlayer::setSoul);
g_lua.bindClassMemberFunction<LocalPlayer>("setStamina", &LocalPlayer::setStamina);
g_lua.bindClassMemberFunction<LocalPlayer>("setKnown", &LocalPlayer::setKnown);
g_lua.bindClassMemberFunction<LocalPlayer>("setInventoryItem", &LocalPlayer::setInventoryItem);
g_lua.bindClassMemberFunction<LocalPlayer>("getStates", &LocalPlayer::getStates);
g_lua.bindClassMemberFunction<LocalPlayer>("getSkillLevel", &LocalPlayer::getSkillLevel);
g_lua.bindClassMemberFunction<LocalPlayer>("getSkillBaseLevel", &LocalPlayer::getSkillBaseLevel);
g_lua.bindClassMemberFunction<LocalPlayer>("getSkillLevelPercent", &LocalPlayer::getSkillLevelPercent);
g_lua.bindClassMemberFunction<LocalPlayer>("getHealth", &LocalPlayer::getHealth);
g_lua.bindClassMemberFunction<LocalPlayer>("getMaxHealth", &LocalPlayer::getMaxHealth);
g_lua.bindClassMemberFunction<LocalPlayer>("getFreeCapacity", &LocalPlayer::getFreeCapacity);
g_lua.bindClassMemberFunction<LocalPlayer>("getExperience", &LocalPlayer::getExperience);
g_lua.bindClassMemberFunction<LocalPlayer>("getLevel", &LocalPlayer::getLevel);
g_lua.bindClassMemberFunction<LocalPlayer>("getLevelPercent", &LocalPlayer::getLevelPercent);
g_lua.bindClassMemberFunction<LocalPlayer>("getMana", &LocalPlayer::getMana);
g_lua.bindClassMemberFunction<LocalPlayer>("getMaxMana", &LocalPlayer::getMaxMana);
g_lua.bindClassMemberFunction<LocalPlayer>("getMagicLevel", &LocalPlayer::getMagicLevel);
g_lua.bindClassMemberFunction<LocalPlayer>("getMagicLevelPercent", &LocalPlayer::getMagicLevelPercent);
g_lua.bindClassMemberFunction<LocalPlayer>("getSoul", &LocalPlayer::getSoul);
g_lua.bindClassMemberFunction<LocalPlayer>("getStamina", &LocalPlayer::getStamina);
g_lua.bindClassMemberFunction<LocalPlayer>("getOfflineTrainingTime", &LocalPlayer::getOfflineTrainingTime);
g_lua.bindClassMemberFunction<LocalPlayer>("getRegenerationTime", &LocalPlayer::getRegenerationTime);
g_lua.bindClassMemberFunction<LocalPlayer>("getBaseMagicLevel", &LocalPlayer::getBaseMagicLevel);
g_lua.bindClassMemberFunction<LocalPlayer>("getTotalCapacity", &LocalPlayer::getTotalCapacity);
g_lua.bindClassMemberFunction<LocalPlayer>("getInventoryItem", &LocalPlayer::getInventoryItem);
g_lua.bindClassMemberFunction<LocalPlayer>("getVocation", &LocalPlayer::getVocation);
g_lua.bindClassMemberFunction<LocalPlayer>("getBlessings", &LocalPlayer::getBlessings);
g_lua.bindClassMemberFunction<LocalPlayer>("isPremium", &LocalPlayer::isPremium);
g_lua.bindClassMemberFunction<LocalPlayer>("isKnown", &LocalPlayer::isKnown);
g_lua.bindClassMemberFunction<LocalPlayer>("isPreWalking", &LocalPlayer::isPreWalking);
g_lua.bindClassMemberFunction<LocalPlayer>("hasSight", &LocalPlayer::hasSight);
g_lua.bindClassMemberFunction<LocalPlayer>("isAutoWalking", &LocalPlayer::isAutoWalking);
g_lua.bindClassMemberFunction<LocalPlayer>("isServerWalking", &LocalPlayer::isServerWalking);
g_lua.bindClassMemberFunction<LocalPlayer>("stopAutoWalk", &LocalPlayer::stopAutoWalk);
g_lua.bindClassMemberFunction<LocalPlayer>("autoWalk", &LocalPlayer::autoWalk);
g_lua.bindClassMemberFunction<LocalPlayer>("preWalk", &LocalPlayer::preWalk);
g_lua.bindClassMemberFunction<LocalPlayer>("dumpWalkMatrix", &LocalPlayer::dumpWalkMatrix);
g_lua.bindClassMemberFunction<LocalPlayer>("startServerWalking", &LocalPlayer::startServerWalking);
g_lua.bindClassMemberFunction<LocalPlayer>("finishServerWalking", &LocalPlayer::finishServerWalking);
g_lua.registerClass<Tile>();
g_lua.bindClassMemberFunction<Tile>("clean", &Tile::clean);
g_lua.bindClassMemberFunction<Tile>("addThing", &Tile::addThing);
g_lua.bindClassMemberFunction<Tile>("getThing", &Tile::getThing);
g_lua.bindClassMemberFunction<Tile>("getThings", &Tile::getThings);
g_lua.bindClassMemberFunction<Tile>("getEffect", &Tile::getEffect);
g_lua.bindClassMemberFunction<Tile>("getEffects", &Tile::getEffects);
g_lua.bindClassMemberFunction<Tile>("getItems", &Tile::getItems);
g_lua.bindClassMemberFunction<Tile>("getThingStackPos", &Tile::getThingStackPos);
g_lua.bindClassMemberFunction<Tile>("getThingCount", &Tile::getThingCount);
g_lua.bindClassMemberFunction<Tile>("getTopThing", &Tile::getTopThing);
g_lua.bindClassMemberFunction<Tile>("removeThing", &Tile::removeThing);
g_lua.bindClassMemberFunction<Tile>("getTopLookThing", &Tile::getTopLookThing);
g_lua.bindClassMemberFunction<Tile>("getTopLookThingEx", &Tile::getTopLookThingEx);
g_lua.bindClassMemberFunction<Tile>("getTopUseThing", &Tile::getTopUseThing);
g_lua.bindClassMemberFunction<Tile>("getTopCreature", &Tile::getTopCreature);
g_lua.bindClassMemberFunction<Tile>("getTopCreatureEx", &Tile::getTopCreatureEx);
g_lua.bindClassMemberFunction<Tile>("getTopMoveThing", &Tile::getTopMoveThing);
g_lua.bindClassMemberFunction<Tile>("getTopMultiUseThing", &Tile::getTopMultiUseThing);
g_lua.bindClassMemberFunction<Tile>("getTopMultiUseThingEx", &Tile::getTopMultiUseThingEx);
g_lua.bindClassMemberFunction<Tile>("getPosition", &Tile::getPosition);
g_lua.bindClassMemberFunction<Tile>("getDrawElevation", &Tile::getDrawElevation);
g_lua.bindClassMemberFunction<Tile>("getCreatures", &Tile::getCreatures);
g_lua.bindClassMemberFunction<Tile>("getGround", &Tile::getGround);
g_lua.bindClassMemberFunction<Tile>("isWalkable", &Tile::isWalkable);
g_lua.bindClassMemberFunction<Tile>("isHouseTile", &Tile::isHouseTile);
g_lua.bindClassMemberFunction<Tile>("isFullGround", &Tile::isFullGround);
g_lua.bindClassMemberFunction<Tile>("isFullyOpaque", &Tile::isFullyOpaque);
g_lua.bindClassMemberFunction<Tile>("isLookPossible", &Tile::isLookPossible);
g_lua.bindClassMemberFunction<Tile>("isBlockingProjectile", &Tile::isBlockingProjectile);
g_lua.bindClassMemberFunction<Tile>("hasCreature", &Tile::hasCreature);
g_lua.bindClassMemberFunction<Tile>("hasBlockingCreature", &Tile::hasBlockingCreature);
g_lua.bindClassMemberFunction<Tile>("isEmpty", &Tile::isEmpty);
g_lua.bindClassMemberFunction<Tile>("isClickable", &Tile::isClickable);
g_lua.bindClassMemberFunction<Tile>("isPathable", &Tile::isPathable);
g_lua.bindClassMemberFunction<Tile>("overwriteMinimapColor", &Tile::overwriteMinimapColor);
g_lua.bindClassMemberFunction<Tile>("select", &Tile::select);
g_lua.bindClassMemberFunction<Tile>("unselect", &Tile::unselect);
g_lua.bindClassMemberFunction<Tile>("isSelected", &Tile::isSelected);
g_lua.bindClassMemberFunction<Tile>("remFlag", &Tile::remFlag);
g_lua.bindClassMemberFunction<Tile>("setFlag", &Tile::setFlag);
g_lua.bindClassMemberFunction<Tile>("setFlags", &Tile::setFlags);
g_lua.bindClassMemberFunction<Tile>("getFlags", &Tile::getFlags);
g_lua.bindClassMemberFunction<Tile>("hasFlag", &Tile::hasFlag);
g_lua.bindClassMemberFunction<Tile>("getElevation", &Tile::getElevation);
g_lua.bindClassMemberFunction<Tile>("hasElevation", &Tile::hasElevation);
g_lua.bindClassMemberFunction<Tile>("isBlocking", &Tile::isBlocking);
g_lua.bindClassMemberFunction<Tile>("canShoot", &Tile::canShoot);
// for bot
g_lua.bindClassMemberFunction<Tile>("setText", &Tile::setText);
g_lua.bindClassMemberFunction<Tile>("getText", &Tile::getText);
g_lua.bindClassMemberFunction<Tile>("setTimer", &Tile::setTimer);
g_lua.bindClassMemberFunction<Tile>("getTimer", &Tile::getTimer);
g_lua.bindClassMemberFunction<Tile>("setFill", &Tile::setFill);
g_lua.registerClass<UIItem, UIWidget>();
g_lua.bindClassStaticFunction<UIItem>("create", []{ return UIItemPtr(new UIItem); });
g_lua.bindClassMemberFunction<UIItem>("setItemId", &UIItem::setItemId);
g_lua.bindClassMemberFunction<UIItem>("setItemCount", &UIItem::setItemCount);
g_lua.bindClassMemberFunction<UIItem>("setItemSubType", &UIItem::setItemSubType);
g_lua.bindClassMemberFunction<UIItem>("setItemVisible", &UIItem::setItemVisible);
g_lua.bindClassMemberFunction<UIItem>("setItem", &UIItem::setItem);
g_lua.bindClassMemberFunction<UIItem>("setVirtual", &UIItem::setVirtual);
g_lua.bindClassMemberFunction<UIItem>("setShowCount", &UIItem::setShowCount);
g_lua.bindClassMemberFunction<UIItem>("clearItem", &UIItem::clearItem);
g_lua.bindClassMemberFunction<UIItem>("getItemId", &UIItem::getItemId);
g_lua.bindClassMemberFunction<UIItem>("getItemCount", &UIItem::getItemCount);
g_lua.bindClassMemberFunction<UIItem>("getItemSubType", &UIItem::getItemSubType);
g_lua.bindClassMemberFunction<UIItem>("getItemCountOrSubType", &UIItem::getItemCountOrSubType);
g_lua.bindClassMemberFunction<UIItem>("getItem", &UIItem::getItem);
g_lua.bindClassMemberFunction<UIItem>("isVirtual", &UIItem::isVirtual);
g_lua.bindClassMemberFunction<UIItem>("isItemVisible", &UIItem::isItemVisible);
g_lua.registerClass<UISprite, UIWidget>();
g_lua.bindClassStaticFunction<UISprite>("create", []{ return UISpritePtr(new UISprite); });
g_lua.bindClassMemberFunction<UISprite>("setSpriteId", &UISprite::setSpriteId);
g_lua.bindClassMemberFunction<UISprite>("clearSprite", &UISprite::clearSprite);
g_lua.bindClassMemberFunction<UISprite>("getSpriteId", &UISprite::getSpriteId);
g_lua.bindClassMemberFunction<UISprite>("setSpriteColor", &UISprite::setSpriteColor);
g_lua.bindClassMemberFunction<UISprite>("hasSprite", &UISprite::hasSprite);
g_lua.registerClass<UICreature, UIWidget>();
g_lua.bindClassStaticFunction<UICreature>("create", []{ return UICreaturePtr(new UICreature); } );
g_lua.bindClassMemberFunction<UICreature>("setCreature", &UICreature::setCreature);
g_lua.bindClassMemberFunction<UICreature>("setOutfit", &UICreature::setOutfit);
g_lua.bindClassMemberFunction<UICreature>("setFixedCreatureSize", &UICreature::setFixedCreatureSize);
g_lua.bindClassMemberFunction<UICreature>("getCreature", &UICreature::getCreature);
g_lua.bindClassMemberFunction<UICreature>("getOutfit", &UICreature::getOutfit);
g_lua.bindClassMemberFunction<UICreature>("isFixedCreatureSize", &UICreature::isFixedCreatureSize);
g_lua.bindClassMemberFunction<UICreature>("setAutoRotating", &UICreature::setAutoRotating);
g_lua.bindClassMemberFunction<UICreature>("setDirection", &UICreature::setDirection);
g_lua.bindClassMemberFunction<UICreature>("setScale", &UICreature::setScale);
g_lua.bindClassMemberFunction<UICreature>("getScale", &UICreature::getScale);
g_lua.registerClass<UIMap, UIWidget>();
g_lua.bindClassStaticFunction<UIMap>("create", []{ return UIMapPtr(new UIMap); });
g_lua.bindClassMemberFunction<UIMap>("drawSelf", &UIMap::drawSelf);
g_lua.bindClassMemberFunction<UIMap>("movePixels", &UIMap::movePixels);
g_lua.bindClassMemberFunction<UIMap>("setZoom", &UIMap::setZoom);
g_lua.bindClassMemberFunction<UIMap>("zoomIn", &UIMap::zoomIn);
g_lua.bindClassMemberFunction<UIMap>("zoomOut", &UIMap::zoomOut);
g_lua.bindClassMemberFunction<UIMap>("followCreature", &UIMap::followCreature);
g_lua.bindClassMemberFunction<UIMap>("setCameraPosition", &UIMap::setCameraPosition);
g_lua.bindClassMemberFunction<UIMap>("setMaxZoomIn", &UIMap::setMaxZoomIn);
g_lua.bindClassMemberFunction<UIMap>("setMaxZoomOut", &UIMap::setMaxZoomOut);
g_lua.bindClassMemberFunction<UIMap>("setMultifloor", &UIMap::setMultifloor);
g_lua.bindClassMemberFunction<UIMap>("lockVisibleFloor", &UIMap::lockVisibleFloor);
g_lua.bindClassMemberFunction<UIMap>("unlockVisibleFloor", &UIMap::unlockVisibleFloor);
g_lua.bindClassMemberFunction<UIMap>("setVisibleDimension", &UIMap::setVisibleDimension);
g_lua.bindClassMemberFunction<UIMap>("setDrawFlags", &UIMap::setDrawFlags);
g_lua.bindClassMemberFunction<UIMap>("setDrawTexts", &UIMap::setDrawTexts);
g_lua.bindClassMemberFunction<UIMap>("setDrawNames", &UIMap::setDrawNames);
g_lua.bindClassMemberFunction<UIMap>("setDrawHealthBars", &UIMap::setDrawHealthBars);
g_lua.bindClassMemberFunction<UIMap>("setDrawHealthBarsOnTop", &UIMap::setDrawHealthBarsOnTop);
g_lua.bindClassMemberFunction<UIMap>("setDrawLights", &UIMap::setDrawLights);
g_lua.bindClassMemberFunction<UIMap>("setDrawManaBar", &UIMap::setDrawManaBar);
g_lua.bindClassMemberFunction<UIMap>("setDrawPlayerBars", &UIMap::setDrawPlayerBars);
g_lua.bindClassMemberFunction<UIMap>("setAnimated", &UIMap::setAnimated);
g_lua.bindClassMemberFunction<UIMap>("setKeepAspectRatio", &UIMap::setKeepAspectRatio);
g_lua.bindClassMemberFunction<UIMap>("setMinimumAmbientLight", &UIMap::setMinimumAmbientLight);
g_lua.bindClassMemberFunction<UIMap>("setLimitVisibleRange", &UIMap::setLimitVisibleRange);
g_lua.bindClassMemberFunction<UIMap>("setFloorFading", &UIMap::setFloorFading);
g_lua.bindClassMemberFunction<UIMap>("setCrosshair", &UIMap::setCrosshair);
g_lua.bindClassMemberFunction<UIMap>("setShader", &UIMap::setShader);
g_lua.bindClassMemberFunction<UIMap>("isMultifloor", &UIMap::isMultifloor);
g_lua.bindClassMemberFunction<UIMap>("isDrawingTexts", &UIMap::isDrawingTexts);
g_lua.bindClassMemberFunction<UIMap>("isDrawingNames", &UIMap::isDrawingNames);
g_lua.bindClassMemberFunction<UIMap>("isDrawingHealthBars", &UIMap::isDrawingHealthBars);
g_lua.bindClassMemberFunction<UIMap>("isDrawingHealthBarsOnTop", &UIMap::isDrawingHealthBarsOnTop);
g_lua.bindClassMemberFunction<UIMap>("isDrawingLights", &UIMap::isDrawingLights);
g_lua.bindClassMemberFunction<UIMap>("isDrawingManaBar", &UIMap::isDrawingManaBar);
g_lua.bindClassMemberFunction<UIMap>("isLimitVisibleRangeEnabled", &UIMap::isLimitVisibleRangeEnabled);
g_lua.bindClassMemberFunction<UIMap>("isAnimating", &UIMap::isAnimating);
g_lua.bindClassMemberFunction<UIMap>("isKeepAspectRatioEnabled", &UIMap::isKeepAspectRatioEnabled);
g_lua.bindClassMemberFunction<UIMap>("getVisibleDimension", &UIMap::getVisibleDimension);
g_lua.bindClassMemberFunction<UIMap>("getFollowingCreature", &UIMap::getFollowingCreature);
g_lua.bindClassMemberFunction<UIMap>("getDrawFlags", &UIMap::getDrawFlags);
g_lua.bindClassMemberFunction<UIMap>("getCameraPosition", &UIMap::getCameraPosition);
g_lua.bindClassMemberFunction<UIMap>("getPosition", &UIMap::getPosition);
g_lua.bindClassMemberFunction<UIMap>("getPositionOffset", &UIMap::getPositionOffset);
g_lua.bindClassMemberFunction<UIMap>("getTile", &UIMap::getTile);
g_lua.bindClassMemberFunction<UIMap>("getMaxZoomIn", &UIMap::getMaxZoomIn);
g_lua.bindClassMemberFunction<UIMap>("getMaxZoomOut", &UIMap::getMaxZoomOut);
g_lua.bindClassMemberFunction<UIMap>("getZoom", &UIMap::getZoom);
g_lua.bindClassMemberFunction<UIMap>("getMinimumAmbientLight", &UIMap::getMinimumAmbientLight);
g_lua.bindClassMemberFunction<UIMap>("getShader", &UIMap::getShader);
g_lua.registerClass<UIMinimap, UIWidget>();
g_lua.bindClassStaticFunction<UIMinimap>("create", []{ return UIMinimapPtr(new UIMinimap); });
g_lua.bindClassMemberFunction<UIMinimap>("zoomIn", &UIMinimap::zoomIn);
g_lua.bindClassMemberFunction<UIMinimap>("zoomOut", &UIMinimap::zoomOut);
g_lua.bindClassMemberFunction<UIMinimap>("setZoom", &UIMinimap::setZoom);
g_lua.bindClassMemberFunction<UIMinimap>("setMixZoom", &UIMinimap::setMinZoom);
g_lua.bindClassMemberFunction<UIMinimap>("setMaxZoom", &UIMinimap::setMaxZoom);
g_lua.bindClassMemberFunction<UIMinimap>("setCameraPosition", &UIMinimap::setCameraPosition);
g_lua.bindClassMemberFunction<UIMinimap>("floorUp", &UIMinimap::floorUp);
g_lua.bindClassMemberFunction<UIMinimap>("floorDown", &UIMinimap::floorDown);
g_lua.bindClassMemberFunction<UIMinimap>("getTilePoint", &UIMinimap::getTilePoint);
g_lua.bindClassMemberFunction<UIMinimap>("getTilePosition", &UIMinimap::getTilePosition);
g_lua.bindClassMemberFunction<UIMinimap>("getTileRect", &UIMinimap::getTileRect);
g_lua.bindClassMemberFunction<UIMinimap>("getCameraPosition", &UIMinimap::getCameraPosition);
g_lua.bindClassMemberFunction<UIMinimap>("getMinZoom", &UIMinimap::getMinZoom);
g_lua.bindClassMemberFunction<UIMinimap>("getMaxZoom", &UIMinimap::getMaxZoom);
g_lua.bindClassMemberFunction<UIMinimap>("getZoom", &UIMinimap::getZoom);
g_lua.bindClassMemberFunction<UIMinimap>("getScale", &UIMinimap::getScale);
g_lua.bindClassMemberFunction<UIMinimap>("anchorPosition", &UIMinimap::anchorPosition);
g_lua.bindClassMemberFunction<UIMinimap>("fillPosition", &UIMinimap::fillPosition);
g_lua.bindClassMemberFunction<UIMinimap>("centerInPosition", &UIMinimap::centerInPosition);
g_lua.registerClass<UIProgressRect, UIWidget>();
g_lua.bindClassStaticFunction<UIProgressRect>("create", []{ return UIProgressRectPtr(new UIProgressRect); } );
g_lua.bindClassMemberFunction<UIProgressRect>("setPercent", &UIProgressRect::setPercent);
g_lua.bindClassMemberFunction<UIProgressRect>("getPercent", &UIProgressRect::getPercent);
g_lua.registerClass<UIMapAnchorLayout, UIAnchorLayout>();
}

View File

@ -1,337 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "luavaluecasts_client.h"
#include <framework/luaengine/luainterface.h>
int push_luavalue(const Outfit& outfit)
{
g_lua.createTable(0, 8);
g_lua.pushInteger(outfit.getId());
g_lua.setField("type");
g_lua.pushInteger(outfit.getAuxId());
g_lua.setField("auxType");
if(g_game.getFeature(Otc::GamePlayerAddons)) {
g_lua.pushInteger(outfit.getAddons());
g_lua.setField("addons");
}
g_lua.pushInteger(outfit.getHead());
g_lua.setField("head");
g_lua.pushInteger(outfit.getBody());
g_lua.setField("body");
g_lua.pushInteger(outfit.getLegs());
g_lua.setField("legs");
g_lua.pushInteger(outfit.getFeet());
g_lua.setField("feet");
if (g_game.getFeature(Otc::GamePlayerMounts)) {
g_lua.pushInteger(outfit.getMount());
g_lua.setField("mount");
}
if (g_game.getFeature(Otc::GameWingsAndAura)) {
g_lua.pushInteger(outfit.getWings());
g_lua.setField("wings");
g_lua.pushInteger(outfit.getAura());
g_lua.setField("aura");
}
if (g_game.getFeature(Otc::GameOutfitShaders)) {
g_lua.pushString(outfit.getShader());
g_lua.setField("shader");
}
return 1;
}
bool luavalue_cast(int index, Outfit& outfit)
{
if(g_lua.isTable(index)) {
g_lua.getField("type", index);
outfit.setId(g_lua.popInteger());
g_lua.getField("auxType", index);
outfit.setAuxId(g_lua.popInteger());
if(g_game.getFeature(Otc::GamePlayerAddons)) {
g_lua.getField("addons", index);
outfit.setAddons(g_lua.popInteger());
}
g_lua.getField("head", index);
outfit.setHead(g_lua.popInteger());
g_lua.getField("body", index);
outfit.setBody(g_lua.popInteger());
g_lua.getField("legs", index);
outfit.setLegs(g_lua.popInteger());
g_lua.getField("feet", index);
outfit.setFeet(g_lua.popInteger());
if (g_game.getFeature(Otc::GamePlayerMounts)) {
g_lua.getField("mount", index);
outfit.setMount(g_lua.popInteger());
}
if (g_game.getFeature(Otc::GameWingsAndAura)) {
g_lua.getField("wings", index);
outfit.setWings(g_lua.popInteger());
g_lua.getField("aura", index);
outfit.setAura(g_lua.popInteger());
}
//if (g_game.getFeature(Otc::GameOutfitShaders)) {
g_lua.getField("shader", index);
outfit.setShader(g_lua.popString());
//}
return true;
}
return false;
}
int push_luavalue(const Position& pos)
{
if(pos.isValid()) {
g_lua.createTable(0, 3);
g_lua.pushInteger(pos.x);
g_lua.setField("x");
g_lua.pushInteger(pos.y);
g_lua.setField("y");
g_lua.pushInteger(pos.z);
g_lua.setField("z");
} else
g_lua.pushNil();
return 1;
}
bool luavalue_cast(int index, Position& pos)
{
if(g_lua.isTable(index)) {
g_lua.getField("x", index);
pos.x = g_lua.popInteger();
g_lua.getField("y", index);
pos.y = g_lua.popInteger();
g_lua.getField("z", index);
pos.z = g_lua.popInteger();
return true;
}
return false;
}
int push_luavalue(const MarketData& data)
{
g_lua.createTable(0, 6);
g_lua.pushInteger(data.category);
g_lua.setField("category");
g_lua.pushString(data.name);
g_lua.setField("name");
g_lua.pushInteger(data.requiredLevel);
g_lua.setField("requiredLevel");
g_lua.pushInteger(data.restrictVocation);
g_lua.setField("restrictVocation");
g_lua.pushInteger(data.showAs);
g_lua.setField("showAs");
g_lua.pushInteger(data.tradeAs);
g_lua.setField("tradeAs");
return 1;
}
bool luavalue_cast(int index, MarketData& data)
{
if (g_lua.isTable(index)) {
g_lua.getField("category", index);
data.category = g_lua.popInteger();
g_lua.getField("name", index);
data.name = g_lua.popString();
g_lua.getField("requiredLevel", index);
data.requiredLevel = g_lua.popInteger();
g_lua.getField("restrictVocation", index);
data.restrictVocation = g_lua.popInteger();
g_lua.getField("showAs", index);
data.showAs = g_lua.popInteger();
g_lua.getField("tradeAs", index);
data.tradeAs = g_lua.popInteger();
return true;
}
return false;
}
int push_luavalue(const StoreCategory& category)
{
g_lua.createTable(0, 5);
g_lua.pushString(category.name);
g_lua.setField("name");
g_lua.pushString(category.description);
g_lua.setField("description");
g_lua.pushInteger(category.state);
g_lua.setField("state");
g_lua.pushString(category.icon);
g_lua.setField("icon");
g_lua.pushString(category.parent);
g_lua.setField("parent");
return 1;
}
bool luavalue_cast(int index, StoreCategory& data)
{
if (g_lua.isTable(index)) {
g_lua.getField("name", index);
data.name = g_lua.popString();
g_lua.getField("description", index);
data.description = g_lua.popString();
g_lua.getField("state", index);
data.state = g_lua.popInteger();
g_lua.getField("icon", index);
data.icon = g_lua.popString();
g_lua.getField("parent", index);
data.parent = g_lua.popString();
return true;
}
return false;
}
int push_luavalue(const StoreOffer& offer)
{
g_lua.createTable(0, 6);
g_lua.pushInteger(offer.id);
g_lua.setField("id");
g_lua.pushString(offer.name);
g_lua.setField("name");
g_lua.pushString(offer.description);
g_lua.setField("description");
g_lua.pushInteger(offer.price);
g_lua.setField("price");
g_lua.pushInteger(offer.state);
g_lua.setField("state");
g_lua.pushString(offer.icon);
g_lua.setField("icon");
return 1;
}
bool luavalue_cast(int index, StoreOffer& data)
{
if (g_lua.isTable(index)) {
g_lua.getField("id", index);
data.id = g_lua.popInteger();
g_lua.getField("name", index);
data.name = g_lua.popString();
g_lua.getField("description", index);
data.description = g_lua.popString();
g_lua.getField("state", index);
data.state = g_lua.popInteger();
g_lua.getField("price", index);
data.price = g_lua.popInteger();
g_lua.getField("icon", index);
data.icon = g_lua.popString();
return true;
}
return false;
}
int push_luavalue(const Imbuement& i)
{
g_lua.createTable(0, 11);
g_lua.pushInteger(i.id);
g_lua.setField("id");
g_lua.pushString(i.name);
g_lua.setField("name");
g_lua.pushString(i.description);
g_lua.setField("description");
g_lua.pushString(i.group);
g_lua.setField("group");
g_lua.pushInteger(i.imageId);
g_lua.setField("imageId");
g_lua.pushInteger(i.duration);
g_lua.setField("duration");
g_lua.pushBoolean(i.premiumOnly);
g_lua.setField("premiumOnly");
g_lua.createTable(i.sources.size(), 0);
for (size_t j = 0; j < i.sources.size(); ++j) {
g_lua.createTable(0, 2);
g_lua.pushObject(i.sources[j].first);
g_lua.setField("item");
g_lua.pushString(i.sources[j].second);
g_lua.setField("description");
g_lua.rawSeti(j + 1);
}
g_lua.setField("sources");
g_lua.pushInteger(i.cost);
g_lua.setField("cost");
g_lua.pushInteger(i.successRate);
g_lua.setField("successRate");
g_lua.pushInteger(i.protectionCost);
g_lua.setField("protectionCost");
return 1;
}
int push_luavalue(const Light& light)
{
g_lua.createTable(0, 2);
g_lua.pushInteger(light.color);
g_lua.setField("color");
g_lua.pushInteger(light.intensity);
g_lua.setField("intensity");
return 1;
}
bool luavalue_cast(int index, Light& light)
{
if(g_lua.isTable(index)) {
g_lua.getField("color", index);
light.color = g_lua.popInteger();
g_lua.getField("intensity", index);
light.intensity = g_lua.popInteger();
return true;
}
return false;
}
int push_luavalue(const UnjustifiedPoints& unjustifiedPoints)
{
g_lua.createTable(0, 7);
g_lua.pushInteger(unjustifiedPoints.killsDay);
g_lua.setField("killsDay");
g_lua.pushInteger(unjustifiedPoints.killsDayRemaining);
g_lua.setField("killsDayRemaining");
g_lua.pushInteger(unjustifiedPoints.killsWeek);
g_lua.setField("killsWeek");
g_lua.pushInteger(unjustifiedPoints.killsWeekRemaining);
g_lua.setField("killsWeekRemaining");
g_lua.pushInteger(unjustifiedPoints.killsMonth);
g_lua.setField("killsMonth");
g_lua.pushInteger(unjustifiedPoints.killsMonthRemaining);
g_lua.setField("killsMonthRemaining");
g_lua.pushInteger(unjustifiedPoints.skullTime);
g_lua.setField("skullTime");
return 1;
}
bool luavalue_cast(int index, UnjustifiedPoints& unjustifiedPoints)
{
if(g_lua.isTable(index)) {
g_lua.getField("killsDay", index);
unjustifiedPoints.killsDay = g_lua.popInteger();
g_lua.getField("killsDayRemaining", index);
unjustifiedPoints.killsDayRemaining = g_lua.popInteger();
g_lua.getField("killsWeek", index);
unjustifiedPoints.killsWeek = g_lua.popInteger();
g_lua.getField("killsWeekRemaining", index);
unjustifiedPoints.killsWeekRemaining = g_lua.popInteger();
g_lua.getField("killsMonth", index);
unjustifiedPoints.killsMonth = g_lua.popInteger();
g_lua.getField("killsMonthRemaining", index);
unjustifiedPoints.killsMonthRemaining = g_lua.popInteger();
g_lua.getField("skullTime", index);
unjustifiedPoints.skullTime = g_lua.popInteger();
return true;
}
return false;
}

View File

@ -1,62 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CLIENT_LUAVALUECASTS_H
#define CLIENT_LUAVALUECASTS_H
#include "global.h"
#include <framework/luaengine/declarations.h>
#include "game.h"
#include "outfit.h"
// outfit
int push_luavalue(const Outfit& outfit);
bool luavalue_cast(int index, Outfit& outfit);
// position
int push_luavalue(const Position& pos);
bool luavalue_cast(int index, Position& pos);
// market
int push_luavalue(const MarketData& data);
bool luavalue_cast(int index, MarketData& data);
// store category
int push_luavalue(const StoreCategory& category);
bool luavalue_cast(int index, StoreCategory& data);
// store offer
int push_luavalue(const StoreOffer& offer);
bool luavalue_cast(int index, StoreOffer& offer);
// imbuement
int push_luavalue(const Imbuement& offer);
// light
int push_luavalue(const Light& light);
bool luavalue_cast(int index, Light& light);
// unjustified points
int push_luavalue(const UnjustifiedPoints& unjustifiedPoints);
bool luavalue_cast(int index, UnjustifiedPoints& unjustifiedPoints);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,304 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MAP_H
#define MAP_H
#include "creature.h"
#include "houses.h"
#include "towns.h"
#include "creatures.h"
#include "animatedtext.h"
#include "statictext.h"
#include "tile.h"
#include <framework/core/clock.h>
enum OTBM_ItemAttr
{
OTBM_ATTR_DESCRIPTION = 1,
OTBM_ATTR_EXT_FILE = 2,
OTBM_ATTR_TILE_FLAGS = 3,
OTBM_ATTR_ACTION_ID = 4,
OTBM_ATTR_UNIQUE_ID = 5,
OTBM_ATTR_TEXT = 6,
OTBM_ATTR_DESC = 7,
OTBM_ATTR_TELE_DEST = 8,
OTBM_ATTR_ITEM = 9,
OTBM_ATTR_DEPOT_ID = 10,
OTBM_ATTR_SPAWN_FILE = 11,
OTBM_ATTR_RUNE_CHARGES = 12,
OTBM_ATTR_HOUSE_FILE = 13,
OTBM_ATTR_HOUSEDOORID = 14,
OTBM_ATTR_COUNT = 15,
OTBM_ATTR_DURATION = 16,
OTBM_ATTR_DECAYING_STATE = 17,
OTBM_ATTR_WRITTENDATE = 18,
OTBM_ATTR_WRITTENBY = 19,
OTBM_ATTR_SLEEPERGUID = 20,
OTBM_ATTR_SLEEPSTART = 21,
OTBM_ATTR_CHARGES = 22,
OTBM_ATTR_CONTAINER_ITEMS = 23,
OTBM_ATTR_ATTRIBUTE_MAP = 128,
/// just random numbers, they're not actually used by the binary reader...
OTBM_ATTR_WIDTH = 129,
OTBM_ATTR_HEIGHT = 130
};
enum OTBM_NodeTypes_t
{
OTBM_ROOTV2 = 1,
OTBM_MAP_DATA = 2,
OTBM_ITEM_DEF = 3,
OTBM_TILE_AREA = 4,
OTBM_TILE = 5,
OTBM_ITEM = 6,
OTBM_TILE_SQUARE = 7,
OTBM_TILE_REF = 8,
OTBM_SPAWNS = 9,
OTBM_SPAWN_AREA = 10,
OTBM_MONSTER = 11,
OTBM_TOWNS = 12,
OTBM_TOWN = 13,
OTBM_HOUSETILE = 14,
OTBM_WAYPOINTS = 15,
OTBM_WAYPOINT = 16
};
enum {
OTCM_SIGNATURE = 0x4D43544F,
OTCM_VERSION = 1
};
enum {
BLOCK_SIZE = 32
};
enum : uint8 {
Animation_Force,
Animation_Show
};
class TileBlock {
public:
TileBlock() { m_tiles.fill(nullptr); }
const TilePtr& create(const Position& pos) {
TilePtr& tile = m_tiles[getTileIndex(pos)];
tile = TilePtr(new Tile(pos));
return tile;
}
const TilePtr& getOrCreate(const Position& pos) {
TilePtr& tile = m_tiles[getTileIndex(pos)];
if(!tile)
tile = TilePtr(new Tile(pos));
return tile;
}
const TilePtr& get(const Position& pos) { return m_tiles[getTileIndex(pos)]; }
void remove(const Position& pos) { m_tiles[getTileIndex(pos)] = nullptr; }
uint getTileIndex(const Position& pos) { return ((pos.y % BLOCK_SIZE) * BLOCK_SIZE) + (pos.x % BLOCK_SIZE); }
const std::array<TilePtr, BLOCK_SIZE*BLOCK_SIZE>& getTiles() const { return m_tiles; }
private:
std::array<TilePtr, BLOCK_SIZE*BLOCK_SIZE> m_tiles;
};
struct AwareRange
{
int top;
int right;
int bottom;
int left;
int horizontal() { return left + right + 1; }
int vertical() { return top + bottom + 1; }
};
struct PathFindResult
{
Otc::PathFindResult status = Otc::PathFindResultNoWay;
std::vector<Otc::Direction> path;
int complexity = 0;
Position start;
Position destination;
};
using PathFindResult_ptr = std::shared_ptr<PathFindResult>;
struct Node {
float cost;
float totalCost;
Position pos;
Node *prev;
int distance;
int unseen;
};
//@bindsingleton g_map
class Map
{
public:
void init();
void terminate();
void addMapView(const MapViewPtr& mapView);
void removeMapView(const MapViewPtr& mapView);
void notificateTileUpdate(const Position& pos, bool updateMinimap = false);
void requestVisibleTilesCacheUpdate();
bool loadOtcm(const std::string& fileName);
void saveOtcm(const std::string& fileName);
void loadOtbm(const std::string& fileName);
void saveOtbm(const std::string& fileName);
// otbm attributes (description, size, etc.)
void setHouseFile(const std::string& file) { m_attribs.set(OTBM_ATTR_HOUSE_FILE, file); }
void setSpawnFile(const std::string& file) { m_attribs.set(OTBM_ATTR_SPAWN_FILE, file); }
void setDescription(const std::string& desc) { m_attribs.set(OTBM_ATTR_DESCRIPTION, desc); }
void clearDescriptions() { m_attribs.remove(OTBM_ATTR_DESCRIPTION); }
void setWidth(uint16 w) { m_attribs.set(OTBM_ATTR_WIDTH, w); }
void setHeight(uint16 h) { m_attribs.set(OTBM_ATTR_HEIGHT, h); }
std::string getHouseFile() { return m_attribs.get<std::string>(OTBM_ATTR_HOUSE_FILE); }
std::string getSpawnFile() { return m_attribs.get<std::string>(OTBM_ATTR_SPAWN_FILE); }
Size getSize() { return Size(m_attribs.get<uint16>(OTBM_ATTR_WIDTH), m_attribs.get<uint16>(OTBM_ATTR_HEIGHT)); }
std::vector<std::string> getDescriptions() { return stdext::split(m_attribs.get<std::string>(OTBM_ATTR_DESCRIPTION), "\n"); }
void clean();
void cleanDynamicThings();
void cleanTexts();
// thing related
void addThing(const ThingPtr& thing, const Position& pos, int stackPos = -1);
void setTileSpeed(const Position & pos, uint16_t speed, uint8_t blocking);
ThingPtr getThing(const Position& pos, int stackPos);
bool removeThing(const ThingPtr& thing);
bool removeThingByPos(const Position& pos, int stackPos);
void colorizeThing(const ThingPtr& thing, const Color& color);
void removeThingColor(const ThingPtr& thing);
StaticTextPtr getStaticText(const Position& pos);
// tile related
const TilePtr& createTile(const Position& pos);
template <typename... Items>
const TilePtr& createTileEx(const Position& pos, const Items&... items);
const TilePtr& getOrCreateTile(const Position& pos);
const TilePtr& getTile(const Position& pos);
const TileList getTiles(int floor = -1);
void cleanTile(const Position& pos);
// tile zone related
void setShowZone(tileflags_t zone, bool show);
void setShowZones(bool show);
void setZoneColor(tileflags_t flag, const Color& color);
void setZoneOpacity(float opacity) { m_zoneOpacity = opacity; }
float getZoneOpacity() { return m_zoneOpacity; }
Color getZoneColor(tileflags_t flag);
tileflags_t getZoneFlags() { return (tileflags_t)m_zoneFlags; }
bool showZones() { return m_zoneFlags != 0; }
bool showZone(tileflags_t zone) { return (m_zoneFlags & zone) == zone; }
void setForceShowAnimations(bool force);
bool isForcingAnimations();
bool isShowingAnimations();
void setShowAnimations(bool show);
std::map<Position, ItemPtr> findItemsById(uint16 clientId, uint32 max);
// known creature related
void addCreature(const CreaturePtr& creature);
CreaturePtr getCreatureById(uint32 id);
void removeCreatureById(uint32 id);
std::vector<CreaturePtr> getSightSpectators(const Position& centerPos, bool multiFloor);
std::vector<CreaturePtr> getSpectators(const Position& centerPos, bool multiFloor);
std::vector<CreaturePtr> getSpectatorsInRange(const Position& centerPos, bool multiFloor, int xRange, int yRange);
std::vector<CreaturePtr> getSpectatorsInRangeEx(const Position& centerPos, bool multiFloor, int minXRange, int maxXRange, int minYRange, int maxYRange);
void setLight(const Light& light) { m_light = light; }
void setCentralPosition(const Position& centralPosition);
bool isLookPossible(const Position& pos);
bool isCovered(const Position& pos, int firstFloor = 0);
bool isCompletelyCovered(const Position& pos, int firstFloor = 0);
bool isAwareOfPosition(const Position& pos, bool extended = false);
bool isAwareOfPositionForClean(const Position& pos, bool extended = false);
void setAwareRange(const AwareRange& range);
void resetAwareRange();
AwareRange getAwareRange() { return m_awareRange; }
Size getAwareRangeAsSize() { return Size(m_awareRange.horizontal(), m_awareRange.vertical()); }
Light getLight() { return m_light; }
Position getCentralPosition() { return m_centralPosition; }
int getFirstAwareFloor();
int getLastAwareFloor();
const std::vector<MissilePtr>& getFloorMissiles(int z) { return m_floorMissiles[z]; }
std::vector<AnimatedTextPtr> getAnimatedTexts() { return m_animatedTexts; }
std::vector<StaticTextPtr> getStaticTexts() { return m_staticTexts; }
std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> findPath(const Position& start, const Position& goal, int maxComplexity, int flags = 0);
PathFindResult_ptr newFindPath(const Position& start, const Position& goal, std::shared_ptr<std::list<Node*>> visibleNodes);
void findPathAsync(const Position & start, const Position & goal, std::function<void(PathFindResult_ptr)> callback);
// tuple = <cost, distance, prevPos>
std::map<std::string, std::tuple<int, int, int, std::string>> findEveryPath(const Position& start, int maxDistance, const std::map<std::string, std::string>& params);
int getMinimapColor(const Position& pos);
bool isPatchable(const Position& pos);
bool isWalkable(const Position& pos, bool ignoreCreatures);
private:
void removeUnawareThings();
uint getBlockIndex(const Position& pos) { return ((pos.y / BLOCK_SIZE) * (65536 / BLOCK_SIZE)) + (pos.x / BLOCK_SIZE); }
std::map<uint, TileBlock> m_tileBlocks[Otc::MAX_Z+1];
std::map<uint32, CreaturePtr> m_knownCreatures;
std::array<std::vector<MissilePtr>, Otc::MAX_Z+1> m_floorMissiles;
std::vector<AnimatedTextPtr> m_animatedTexts;
std::vector<StaticTextPtr> m_staticTexts;
std::vector<MapViewPtr> m_mapViews;
std::unordered_map<Position, std::string, PositionHasher> m_waypoints;
uint8 m_animationFlags;
uint32 m_zoneFlags;
std::map<uint32, Color> m_zoneColors;
float m_zoneOpacity;
Light m_light;
Position m_centralPosition;
Rect m_tilesRect;
stdext::packed_storage<uint8> m_attribs;
AwareRange m_awareRange;
static TilePtr m_nulltile;
};
extern Map g_map;
#endif

View File

@ -1,538 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "map.h"
#include "tile.h"
#include "game.h"
#include <framework/core/application.h>
#include <framework/core/eventdispatcher.h>
#include <framework/core/resourcemanager.h>
#include <framework/core/filestream.h>
#include <framework/core/binarytree.h>
#include <framework/xml/tinyxml.h>
#include <framework/ui/uiwidget.h>
void Map::loadOtbm(const std::string& fileName)
{
try {
if(!g_things.isOtbLoaded())
stdext::throw_exception("OTB isn't loaded yet to load a map.");
FileStreamPtr fin = g_resources.openFile(fileName);
if(!fin)
stdext::throw_exception(stdext::format("Unable to load map '%s'", fileName));
char identifier[4];
if(fin->read(identifier, 1, 4) < 4)
stdext::throw_exception("Could not read file identifier");
if(memcmp(identifier, "OTBM", 4) != 0 && memcmp(identifier, "\0\0\0\0", 4) != 0)
stdext::throw_exception(stdext::format("Invalid file identifier detected: %s", identifier));
BinaryTreePtr root = fin->getBinaryTree();
if(root->getU8())
stdext::throw_exception("could not read root property!");
uint32 headerVersion = root->getU32();
if(headerVersion > 3)
stdext::throw_exception(stdext::format("Unknown OTBM version detected: %u.", headerVersion));
setWidth(root->getU16());
setHeight(root->getU16());
uint32 headerMajorItems = root->getU8();
if(headerMajorItems > g_things.getOtbMajorVersion()) {
stdext::throw_exception(stdext::format("This map was saved with different OTB version. read %d what it's supposed to be: %d",
headerMajorItems, g_things.getOtbMajorVersion()));
}
root->skip(3);
uint32 headerMinorItems = root->getU32();
if(headerMinorItems > g_things.getOtbMinorVersion()) {
g_logger.warning(stdext::format("This map needs an updated OTB. read %d what it's supposed to be: %d or less",
headerMinorItems, g_things.getOtbMinorVersion()));
}
BinaryTreePtr node = root->getChildren()[0];
if(node->getU8() != OTBM_MAP_DATA)
stdext::throw_exception("Could not read root data node");
while(node->canRead()) {
uint8 attribute = node->getU8();
std::string tmp = node->getString();
switch (attribute) {
case OTBM_ATTR_DESCRIPTION:
setDescription(tmp);
break;
case OTBM_ATTR_SPAWN_FILE:
setSpawnFile(fileName.substr(0, fileName.rfind('/') + 1) + tmp);
break;
case OTBM_ATTR_HOUSE_FILE:
setHouseFile(fileName.substr(0, fileName.rfind('/') + 1) + tmp);
break;
default:
stdext::throw_exception(stdext::format("Invalid attribute '%d'", (int)attribute));
}
}
for(const BinaryTreePtr& nodeMapData : node->getChildren()) {
uint8 mapDataType = nodeMapData->getU8();
if(mapDataType == OTBM_TILE_AREA) {
Position basePos;
basePos.x = nodeMapData->getU16();
basePos.y = nodeMapData->getU16();
basePos.z = nodeMapData->getU8();
for(const BinaryTreePtr &nodeTile : nodeMapData->getChildren()) {
uint8 type = nodeTile->getU8();
if(unlikely(type != OTBM_TILE && type != OTBM_HOUSETILE))
stdext::throw_exception(stdext::format("invalid node tile type %d", (int)type));
HousePtr house = nullptr;
uint32 flags = TILESTATE_NONE;
Position pos = basePos + nodeTile->getPoint();
if(type == OTBM_HOUSETILE) {
uint32 hId = nodeTile->getU32();
TilePtr tile = getOrCreateTile(pos);
if(!(house = g_houses.getHouse(hId))) {
house = HousePtr(new House(hId));
g_houses.addHouse(house);
}
house->setTile(tile);
}
while(nodeTile->canRead()) {
uint8 tileAttr = nodeTile->getU8();
switch(tileAttr) {
case OTBM_ATTR_TILE_FLAGS: {
uint32 _flags = nodeTile->getU32();
if((_flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE)
flags |= TILESTATE_PROTECTIONZONE;
else if((_flags & TILESTATE_OPTIONALZONE) == TILESTATE_OPTIONALZONE)
flags |= TILESTATE_OPTIONALZONE;
else if((_flags & TILESTATE_HARDCOREZONE) == TILESTATE_HARDCOREZONE)
flags |= TILESTATE_HARDCOREZONE;
if((_flags & TILESTATE_NOLOGOUT) == TILESTATE_NOLOGOUT)
flags |= TILESTATE_NOLOGOUT;
if((_flags & TILESTATE_REFRESH) == TILESTATE_REFRESH)
flags |= TILESTATE_REFRESH;
break;
}
case OTBM_ATTR_ITEM: {
addThing(Item::createFromOtb(nodeTile->getU16()), pos);
break;
}
default: {
stdext::throw_exception(stdext::format("invalid tile attribute %d at pos %s",
(int)tileAttr, stdext::to_string(pos)));
}
}
}
for(const BinaryTreePtr& nodeItem : nodeTile->getChildren()) {
if(unlikely(nodeItem->getU8() != OTBM_ITEM))
stdext::throw_exception("invalid item node");
ItemPtr item = Item::createFromOtb(nodeItem->getU16());
item->unserializeItem(nodeItem);
if(item->isContainer()) {
for(const BinaryTreePtr& containerItem : nodeItem->getChildren()) {
if(containerItem->getU8() != OTBM_ITEM)
stdext::throw_exception("invalid container item node");
ItemPtr cItem = Item::createFromOtb(containerItem->getU16());
cItem->unserializeItem(containerItem);
item->addContainerItem(cItem);
}
}
if(house && item->isMoveable()) {
g_logger.warning(stdext::format("Moveable item found in house: %d at pos %s - escaping...", item->getId(), stdext::to_string(pos)));
item.reset();
}
addThing(item, pos);
}
if(const TilePtr& tile = getTile(pos)) {
if(house)
tile->setFlag(TILESTATE_HOUSE);
tile->setFlag(flags);
}
}
} else if(mapDataType == OTBM_TOWNS) {
TownPtr town = nullptr;
for(const BinaryTreePtr &nodeTown : nodeMapData->getChildren()) {
if(nodeTown->getU8() != OTBM_TOWN)
stdext::throw_exception("invalid town node.");
uint32 townId = nodeTown->getU32();
std::string townName = nodeTown->getString();
Position townCoords;
townCoords.x = nodeTown->getU16();
townCoords.y = nodeTown->getU16();
townCoords.z = nodeTown->getU8();
if(!(town = g_towns.getTown(townId)))
g_towns.addTown(TownPtr(new Town(townId, townName, townCoords)));
}
g_towns.sort();
} else if(mapDataType == OTBM_WAYPOINTS && headerVersion > 1) {
for(const BinaryTreePtr &nodeWaypoint : nodeMapData->getChildren()) {
if(nodeWaypoint->getU8() != OTBM_WAYPOINT)
stdext::throw_exception("invalid waypoint node.");
std::string name = nodeWaypoint->getString();
Position waypointPos;
waypointPos.x = nodeWaypoint->getU16();
waypointPos.y = nodeWaypoint->getU16();
waypointPos.z = nodeWaypoint->getU8();
if(waypointPos.isValid() && !name.empty() && m_waypoints.find(waypointPos) == m_waypoints.end())
m_waypoints.insert(std::make_pair(waypointPos, name));
}
} else
stdext::throw_exception(stdext::format("Unknown map data node %d", (int)mapDataType));
}
fin->close();
} catch(std::exception& e) {
g_logger.error(stdext::format("Failed to load '%s': %s", fileName, e.what()));
}
}
void Map::saveOtbm(const std::string& fileName)
{
try {
FileStreamPtr fin = g_resources.createFile(fileName);
if(!fin)
stdext::throw_exception(stdext::format("failed to open file '%s' for write", fileName));
std::string dir;
if(fileName.find_last_of('/') == std::string::npos)
dir = g_resources.getWorkDir();
else
dir = fileName.substr(0, fileName.find_last_of('/'));
uint32 version = 0;
if(g_things.getOtbMajorVersion() < ClientVersion820)
version = 1;
else
version = 2;
/// Usually when a map has empty house/spawn file it means the map is new.
/// TODO: Ask the user for a map name instead of those ugly uses of substr
std::string::size_type sep_pos;
std::string houseFile = getHouseFile();
std::string spawnFile = getSpawnFile();
std::string cpyf;
if((sep_pos = fileName.rfind('.')) != std::string::npos && stdext::ends_with(fileName, ".otbm"))
cpyf = fileName.substr(0, sep_pos);
if(houseFile.empty())
houseFile = cpyf + "-houses.xml";
if(spawnFile.empty())
spawnFile = cpyf + "-spawns.xml";
/// we only need the filename to save to, the directory should be resolved by the OTBM loader not here
if((sep_pos = spawnFile.rfind('/')) != std::string::npos)
spawnFile = spawnFile.substr(sep_pos + 1);
if((sep_pos = houseFile.rfind('/')) != std::string::npos)
houseFile = houseFile.substr(sep_pos + 1);
fin->addU32(0); // file version
OutputBinaryTreePtr root(new OutputBinaryTree(fin));
{
root->addU32(version);
Size mapSize = getSize();
root->addU16(mapSize.width());
root->addU16(mapSize.height());
root->addU32(g_things.getOtbMajorVersion());
root->addU32(g_things.getOtbMinorVersion());
root->startNode(OTBM_MAP_DATA);
{
root->addU8(OTBM_ATTR_DESCRIPTION);
root->addString(m_attribs.get<std::string>(OTBM_ATTR_DESCRIPTION));
root->addU8(OTBM_ATTR_SPAWN_FILE);
root->addString(spawnFile);
root->addU8(OTBM_ATTR_HOUSE_FILE);
root->addString(houseFile);
int px = -1, py = -1, pz =-1;
bool firstNode = true;
for(uint8_t z = 0; z <= Otc::MAX_Z; ++z) {
for(const auto& it : m_tileBlocks[z]) {
const TileBlock& block = it.second;
for(const TilePtr& tile : block.getTiles()) {
if(unlikely(!tile || tile->isEmpty()))
continue;
const Position& pos = tile->getPosition();
if(unlikely(!pos.isValid()))
continue;
if(pos.x < px || pos.x >= px + 256
|| pos.y < py || pos.y >= py + 256
|| pos.z != pz) {
if(!firstNode)
root->endNode(); /// OTBM_TILE_AREA
firstNode = false;
root->startNode(OTBM_TILE_AREA);
px = pos.x & 0xFF00;
py = pos.y & 0xFF00;
pz = pos.z;
root->addPos(px, py, pz);
}
root->startNode(tile->isHouseTile() ? OTBM_HOUSETILE : OTBM_TILE);
root->addPoint(Point(pos.x, pos.y) & 0xFF);
if(tile->isHouseTile())
root->addU32(tile->getHouseId());
if(tile->getFlags()) {
root->addU8(OTBM_ATTR_TILE_FLAGS);
root->addU32(tile->getFlags());
}
const auto& itemList = tile->getItems();
const ItemPtr& ground = tile->getGround();
if(ground) {
// Those types are called "complex" needs other stuff to be written.
// For containers, there is container items, for depot, depot it and so on.
if(!ground->isContainer() && !ground->isDepot()
&& !ground->isDoor() && !ground->isTeleport()) {
root->addU8(OTBM_ATTR_ITEM);
root->addU16(ground->getServerId());
} else
ground->serializeItem(root);
}
for(const ItemPtr& item : itemList)
if(!item->isGround())
item->serializeItem(root);
root->endNode(); // OTBM_TILE
}
}
}
if(!firstNode)
root->endNode(); // OTBM_TILE_AREA
root->startNode(OTBM_TOWNS);
for(const TownPtr& town : g_towns.getTowns()) {
root->startNode(OTBM_TOWN);
root->addU32(town->getId());
root->addString(town->getName());
Position townPos = town->getPos();
root->addPos(townPos.x, townPos.y, townPos.z);
root->endNode();
}
root->endNode();
if(version > 1) {
root->startNode(OTBM_WAYPOINTS);
for(const auto& it : m_waypoints) {
root->startNode(OTBM_WAYPOINT);
root->addString(it.second);
Position pos = it.first;
root->addPos(pos.x, pos.y, pos.z);
root->endNode();
}
root->endNode();
}
}
root->endNode(); // OTBM_MAP_DATA
}
root->endNode();
fin->flush();
fin->close();
} catch(std::exception& e) {
g_logger.error(stdext::format("Failed to save '%s': %s", fileName, e.what()));
}
}
bool Map::loadOtcm(const std::string& fileName)
{
try {
FileStreamPtr fin = g_resources.openFile(fileName);
if(!fin)
stdext::throw_exception("unable to open file");
uint32 signature = fin->getU32();
if(signature != OTCM_SIGNATURE)
stdext::throw_exception("invalid otcm file");
uint16 start = fin->getU16();
uint16 version = fin->getU16();
fin->getU32(); // flags
switch(version) {
case 1: {
fin->getString(); // description
uint32 datSignature = fin->getU32();
fin->getU16(); // protocol version
fin->getString(); // world name
if(datSignature != g_things.getDatSignature())
g_logger.warning("otcm map loaded was created with a different dat signature");
break;
}
default:
stdext::throw_exception("otcm version not supported");
}
fin->seek(start);
while(true) {
Position pos;
pos.x = fin->getU16();
pos.y = fin->getU16();
pos.z = fin->getU8();
// end of file
if(!pos.isValid())
break;
const TilePtr& tile = g_map.createTile(pos);
int stackPos = 0;
while(true) {
int id = fin->getU16();
// end of tile
if(id == 0xFFFF)
break;
int countOrSubType = fin->getU8();
ItemPtr item = Item::create(id);
item->setCountOrSubType(countOrSubType);
if(item->isValid())
tile->addThing(item, stackPos++);
}
g_map.notificateTileUpdate(pos);
}
fin->close();
return true;
} catch(stdext::exception& e) {
g_logger.error(stdext::format("failed to load OTCM map: %s", e.what()));
return false;
}
}
void Map::saveOtcm(const std::string& fileName)
{
try {
stdext::timer saveTimer;
FileStreamPtr fin = g_resources.createFile(fileName);
//TODO: compression flag with zlib
uint32 flags = 0;
// header
fin->addU32(OTCM_SIGNATURE);
fin->addU16(0); // data start, will be overwritten later
fin->addU16(OTCM_VERSION);
fin->addU32(flags);
// version 1 header
fin->addString("OTCM 1.0"); // map description
fin->addU32(g_things.getDatSignature());
fin->addU16(g_game.getClientVersion());
fin->addString(g_game.getWorldName());
// go back and rewrite where the map data starts
uint32 start = fin->tell();
fin->seek(4);
fin->addU16(start);
fin->seek(start);
for(uint8_t z = 0; z <= Otc::MAX_Z; ++z) {
for(const auto& it : m_tileBlocks[z]) {
const TileBlock& block = it.second;
for(const TilePtr& tile : block.getTiles()) {
if(!tile || tile->isEmpty())
continue;
Position pos = tile->getPosition();
fin->addU16(pos.x);
fin->addU16(pos.y);
fin->addU8(pos.z);
for(const ThingPtr& thing : tile->getThings()) {
if(thing->isItem()) {
ItemPtr item = thing->static_self_cast<Item>();
fin->addU16(item->getId());
fin->addU8(item->getCountOrSubType());
}
}
// end of tile
fin->addU16(0xFFFF);
}
}
}
// end of file
Position invalidPos;
fin->addU16(invalidPos.x);
fin->addU16(invalidPos.y);
fin->addU8(invalidPos.z);
fin->flush();
fin->close();
} catch(stdext::exception& e) {
g_logger.error(stdext::format("failed to save OTCM map: %s", e.what()));
}
}
/* vim: set ts=4 sw=4 et: */

View File

@ -1,537 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "mapview.h"
#include "creature.h"
#include "map.h"
#include "tile.h"
#include "statictext.h"
#include "animatedtext.h"
#include "missile.h"
#include "shadermanager.h"
#include "lightview.h"
#include "localplayer.h"
#include "game.h"
#include "spritemanager.h"
#include <framework/graphics/graphics.h>
#include <framework/graphics/image.h>
#include <framework/graphics/framebuffermanager.h>
#include <framework/core/eventdispatcher.h>
#include <framework/core/application.h>
#include <framework/core/resourcemanager.h>
#include <framework/graphics/texturemanager.h>
#include <framework/graphics/atlas.h>
#include <framework/util/extras.h>
#include <framework/core/adaptiverenderer.h>
MapView::MapView()
{
m_lockedFirstVisibleFloor = -1;
m_cachedFirstVisibleFloor = 7;
m_cachedLastVisibleFloor = 7;
m_fadeOutTime = 0;
m_fadeInTime = 0;
m_minimumAmbientLight = 0;
m_optimizedSize = Size(g_map.getAwareRange().horizontal(), g_map.getAwareRange().vertical()) * g_sprites.spriteSize();
setVisibleDimension(Size(15, 11));
}
MapView::~MapView()
{
#ifndef NDEBUG
VALIDATE(!g_app.isTerminated());
#endif
}
void MapView::drawTileTexts(const Rect& rect, const Rect& srcRect)
{
Position cameraPosition = getCameraPosition();
Point drawOffset = srcRect.topLeft();
float horizontalStretchFactor = rect.width() / (float)srcRect.width();
float verticalStretchFactor = rect.height() / (float)srcRect.height();
auto player = g_game.getLocalPlayer();
for (auto& tile : m_cachedVisibleTiles) {
Position tilePos = tile.first->getPosition();
if (tilePos.z != player->getPosition().z) continue;
Point p = transformPositionTo2D(tilePos, cameraPosition) - drawOffset;
p.x *= horizontalStretchFactor;
p.y *= verticalStretchFactor;
p += rect.topLeft();
p.y += 5;
tile.first->drawTexts(p);
}
}
void MapView::drawBackground(const Rect& rect, const TilePtr& crosshairTile) {
Position cameraPosition = getCameraPosition();
if (m_mustUpdateVisibleTilesCache) {
updateVisibleTilesCache();
}
if (g_game.getFeature(Otc::GameForceLight)) {
m_drawLight = true;
m_minimumAmbientLight = 0.05f;
}
Rect srcRect = calcFramebufferSource(rect.size());
g_drawQueue->setFrameBuffer(rect, m_optimizedSize, srcRect);
if (m_drawLight) {
Light ambientLight;
if (cameraPosition.z <= Otc::SEA_FLOOR)
ambientLight = g_map.getLight();
if (!m_lightTexture || m_lightTexture->getSize() != m_drawDimension)
m_lightTexture = TexturePtr(new Texture(m_drawDimension, false, true));
m_lightView = std::make_unique<LightView>(m_lightTexture, m_drawDimension, rect, srcRect, ambientLight.color,
std::max<int>(m_minimumAmbientLight * 255, ambientLight.intensity));
}
auto itm = m_cachedVisibleTiles.begin();
auto end = m_cachedVisibleTiles.end();
for (int z = m_cachedLastVisibleFloor; z >= m_cachedFirstFadingFloor; --z) {
float fading = 1.0;
if (m_floorFading > 0) {
fading = 0.;
if (m_floorFading > 0) {
fading = stdext::clamp<float>((float)m_fadingFloorTimers[z].elapsed_millis() / (float)m_floorFading, 0.f, 1.f);
if (z < m_cachedFirstVisibleFloor)
fading = 1.0 - fading;
}
if (fading == 0) break;
}
size_t floorStart = g_drawQueue->size();
size_t lightFloorStart = m_lightView ? m_lightView->size() : 0;
for (; itm != end; ++itm) {
Position tilePos = itm->first->getPosition();
if (tilePos.z != z)
break;
Point tileDrawPos = transformPositionTo2D(tilePos, cameraPosition);
if (m_lightView) {
ItemPtr ground = itm->first->getGround();
if (ground && ground->isGround() && !ground->isTranslucent()) {
m_lightView->setFieldBrightness(tileDrawPos, lightFloorStart, 0);
}
}
itm->first->drawBottom(tileDrawPos, m_lightView.get());
if (m_crosshair && itm->first == crosshairTile)
{
g_drawQueue->addTexturedRect(Rect(tileDrawPos, tileDrawPos + Otc::TILE_PIXELS - 1),
m_crosshair, Rect(0, 0, m_crosshair->getSize()));
}
itm->first->drawTop(tileDrawPos, m_lightView.get());
}
for (const MissilePtr& missile : g_map.getFloorMissiles(z)) {
missile->draw(transformPositionTo2D(missile->getPosition(), cameraPosition), true, m_lightView.get());
}
if (fading < 0.99)
g_drawQueue->setOpacity(floorStart, fading);
}
}
void MapView::drawForeground(const Rect& rect)
{
// this could happen if the player position is not known yet
Position cameraPosition = getCameraPosition();
if (!cameraPosition.isValid())
return;
Rect srcRect = calcFramebufferSource(rect.size());
Point drawOffset = srcRect.topLeft();
float horizontalStretchFactor = rect.width() / (float)srcRect.width();
float verticalStretchFactor = rect.height() / (float)srcRect.height();
// creatures
std::vector<std::pair<CreaturePtr, Point>> creatures;
for (const CreaturePtr& creature : g_map.getSpectatorsInRangeEx(cameraPosition, false, m_visibleDimension.width() / 2, m_visibleDimension.width() / 2 + 1, m_visibleDimension.height() / 2, m_visibleDimension.height() / 2 + 1)) {
if (!creature->canBeSeen())
continue;
PointF jumpOffset = creature->getJumpOffset();
Point creatureOffset = Point(16 - creature->getDisplacementX(), -creature->getDisplacementY() - 2);
Position pos = creature->getPrewalkingPosition();
Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset;
p += (creature->getDrawOffset() + creatureOffset) - Point(stdext::round(jumpOffset.x), stdext::round(jumpOffset.y));
p.x = p.x * horizontalStretchFactor;
p.y = p.y * verticalStretchFactor;
p += rect.topLeft();
creatures.push_back(std::make_pair(creature, p));
}
for (auto& c : creatures) {
int flags = Otc::DrawIcons;
if (m_drawNames) { flags |= Otc::DrawNames; }
if ((!c.first->isLocalPlayer() || m_drawPlayerBars) && !m_drawHealthBarsOnTop) {
if (m_drawHealthBars) { flags |= Otc::DrawBars; }
if (m_drawManaBar) { flags |= Otc::DrawManaBar; }
}
c.first->drawInformation(c.second, g_map.isCovered(c.first->getPrewalkingPosition(), m_cachedFirstVisibleFloor), rect, flags);
}
if (m_lightView) {
g_drawQueue->add(m_lightView.release());
}
// texts
int limit = g_adaptiveRenderer.textsLimit();
for (int i = 0; i < 2; ++i) {
for (const StaticTextPtr& staticText : g_map.getStaticTexts()) {
Position pos = staticText->getPosition();
if (pos.z != cameraPosition.z && staticText->getMessageMode() == Otc::MessageNone)
continue;
if ((staticText->getMessageMode() != Otc::MessageSay && staticText->getMessageMode() != Otc::MessageYell)) {
if (i == 0)
continue;
} else if (i == 1)
continue;
Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset + Point(8, 0);
p.x *= horizontalStretchFactor;
p.y *= verticalStretchFactor;
p += rect.topLeft();
staticText->drawText(p, rect);
if (--limit == 0)
break;
}
}
limit = g_adaptiveRenderer.textsLimit();
for (const AnimatedTextPtr& animatedText : g_map.getAnimatedTexts()) {
Position pos = animatedText->getPosition();
if (pos.z != cameraPosition.z)
continue;
Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset + Point(16, 8);
p.x *= horizontalStretchFactor;
p.y *= verticalStretchFactor;
p += rect.topLeft();
animatedText->drawText(p, rect);
if (--limit == 0)
break;
}
// tile texts
drawTileTexts(rect, srcRect);
// bars on top
if (m_drawHealthBarsOnTop) {
for (auto& c : creatures) {
int flags = 0;
if ((!c.first->isLocalPlayer() || m_drawPlayerBars)) {
if (m_drawHealthBars) { flags |= Otc::DrawBars; }
if (m_drawManaBar) { flags |= Otc::DrawManaBar; }
}
c.first->drawInformation(c.second, g_map.isCovered(c.first->getPrewalkingPosition(), m_cachedFirstVisibleFloor), rect, flags);
}
}
}
void MapView::updateVisibleTilesCache()
{
// hidden
}
void MapView::updateGeometry(const Size& visibleDimension, const Size& optimizedSize)
{
m_multifloor = true;
m_visibleDimension = visibleDimension;
m_drawDimension = visibleDimension + Size(3, 3);
m_virtualCenterOffset = (m_drawDimension / 2 - Size(1, 1)).toPoint();
m_visibleCenterOffset = m_virtualCenterOffset;
m_optimizedSize = m_drawDimension * g_sprites.spriteSize();
requestVisibleTilesCacheUpdate();
}
void MapView::onTileUpdate(const Position& pos)
{
requestVisibleTilesCacheUpdate();
}
void MapView::onMapCenterChange(const Position& pos)
{
requestVisibleTilesCacheUpdate();
}
void MapView::lockFirstVisibleFloor(int firstVisibleFloor)
{
m_lockedFirstVisibleFloor = firstVisibleFloor;
requestVisibleTilesCacheUpdate();
}
void MapView::unlockFirstVisibleFloor()
{
m_lockedFirstVisibleFloor = -1;
requestVisibleTilesCacheUpdate();
}
void MapView::setVisibleDimension(const Size& visibleDimension)
{
//if(visibleDimension == m_visibleDimension)
// return;
if(visibleDimension.width() % 2 != 1 || visibleDimension.height() % 2 != 1) {
g_logger.traceError("visible dimension must be odd");
return;
}
if(visibleDimension < Size(3,3)) {
g_logger.traceError("reach max zoom in");
return;
}
updateGeometry(visibleDimension, m_optimizedSize);
}
void MapView::optimizeForSize(const Size& visibleSize)
{
updateGeometry(m_visibleDimension, visibleSize);
}
void MapView::followCreature(const CreaturePtr& creature)
{
m_follow = true;
m_followingCreature = creature;
requestVisibleTilesCacheUpdate();
}
void MapView::setCameraPosition(const Position& pos)
{
m_follow = false;
m_customCameraPosition = pos;
requestVisibleTilesCacheUpdate();
}
Position MapView::getPosition(const Point& point, const Size& mapSize)
{
Position cameraPosition = getCameraPosition();
// if we have no camera, its impossible to get the tile
if(!cameraPosition.isValid())
return Position();
Rect srcRect = calcFramebufferSource(mapSize);
float sh = srcRect.width() / (float)mapSize.width();
float sv = srcRect.height() / (float)mapSize.height();
Point framebufferPos = Point(point.x * sh, point.y * sv);
Point realPos = (framebufferPos + srcRect.topLeft());
Point centerOffset = realPos / Otc::TILE_PIXELS;
Point tilePos2D = getVisibleCenterOffset() - m_drawDimension.toPoint() + centerOffset + Point(2,2);
if(tilePos2D.x + cameraPosition.x < 0 && tilePos2D.y + cameraPosition.y < 0)
return Position();
Position position = Position(tilePos2D.x, tilePos2D.y, 0) + cameraPosition;
if(!position.isValid())
return Position();
return position;
}
Point MapView::getPositionOffset(const Point& point, const Size& mapSize)
{
Position cameraPosition = getCameraPosition();
// if we have no camera, its impossible to get the tile
if (!cameraPosition.isValid())
return Point(0, 0);
Rect srcRect = calcFramebufferSource(mapSize);
float sh = srcRect.width() / (float)mapSize.width();
float sv = srcRect.height() / (float)mapSize.height();
Point framebufferPos = Point(point.x * sh, point.y * sv);
Point realPos = (framebufferPos + srcRect.topLeft());
return Point(realPos.x % Otc::TILE_PIXELS, realPos.y % Otc::TILE_PIXELS);
}
void MapView::move(int x, int y)
{
m_moveOffset.x += x;
m_moveOffset.y += y;
int32_t tmp = m_moveOffset.x / g_sprites.spriteSize();
bool requestTilesUpdate = false;
if(tmp != 0) {
m_customCameraPosition.x += tmp;
m_moveOffset.x %= g_sprites.spriteSize();
requestTilesUpdate = true;
}
tmp = m_moveOffset.y / g_sprites.spriteSize();
if(tmp != 0) {
m_customCameraPosition.y += tmp;
m_moveOffset.y %= g_sprites.spriteSize();
requestTilesUpdate = true;
}
if(requestTilesUpdate)
requestVisibleTilesCacheUpdate();
}
Rect MapView::calcFramebufferSource(const Size& destSize, bool inNextFrame)
{
float scaleFactor = g_sprites.spriteSize()/(float)Otc::TILE_PIXELS;
Point drawOffset = ((m_drawDimension - m_visibleDimension - Size(1,1)).toPoint()/2) * g_sprites.spriteSize();
if(isFollowingCreature())
drawOffset += m_followingCreature->getWalkOffset(inNextFrame) * scaleFactor;
Size srcSize = destSize;
Size srcVisible = m_visibleDimension * g_sprites.spriteSize();
srcSize.scale(srcVisible, Fw::KeepAspectRatio);
drawOffset.x += (srcVisible.width() - srcSize.width()) / 2;
drawOffset.y += (srcVisible.height() - srcSize.height()) / 2;
return Rect(drawOffset, srcSize);
}
int MapView::calcFirstVisibleFloor(bool forFading)
{
int z = 7;
// return forced first visible floor
if(m_lockedFirstVisibleFloor != -1) {
z = m_lockedFirstVisibleFloor;
} else {
Position cameraPosition = getCameraPosition();
// this could happens if the player is not known yet
if(cameraPosition.isValid()) {
// avoid rendering multifloors in far views
if(!m_multifloor) {
z = cameraPosition.z;
} else {
// if nothing is limiting the view, the first visible floor is 0
int firstFloor = 0;
// limits to underground floors while under sea level
if(cameraPosition.z > Otc::SEA_FLOOR)
firstFloor = std::max<int>(cameraPosition.z - Otc::AWARE_UNDEGROUND_FLOOR_RANGE, (int)Otc::UNDERGROUND_FLOOR);
// loop in 3x3 tiles around the camera
for(int ix = -1; ix <= 1 && firstFloor < cameraPosition.z && !forFading; ++ix) {
for(int iy = -1; iy <= 1 && firstFloor < cameraPosition.z; ++iy) {
Position pos = cameraPosition.translated(ix, iy);
// process tiles that we can look through, e.g. windows, doors
if((ix == 0 && iy == 0) || ((std::abs(ix) != std::abs(iy)) && g_map.isLookPossible(pos))) {
Position upperPos = pos;
Position coveredPos = pos;
while(coveredPos.coveredUp() && upperPos.up() && upperPos.z >= firstFloor) {
// check tiles physically above
TilePtr tile = g_map.getTile(upperPos);
if(tile && tile->limitsFloorsView(!g_map.isLookPossible(pos))) {
firstFloor = upperPos.z + 1;
break;
}
// check tiles geometrically above
tile = g_map.getTile(coveredPos);
if(tile && tile->limitsFloorsView(g_map.isLookPossible(pos))) {
firstFloor = coveredPos.z + 1;
break;
}
}
}
}
}
z = firstFloor;
}
}
}
// just ensure the that the floor is in the valid range
z = stdext::clamp<int>(z, 0, (int)Otc::MAX_Z);
return z;
}
int MapView::calcLastVisibleFloor()
{
if(!m_multifloor)
return calcFirstVisibleFloor();
int z = 7;
Position cameraPosition = getCameraPosition();
// this could happens if the player is not known yet
if(cameraPosition.isValid()) {
// view only underground floors when below sea level
if(cameraPosition.z > Otc::SEA_FLOOR)
z = cameraPosition.z + Otc::AWARE_UNDEGROUND_FLOOR_RANGE;
else
z = Otc::SEA_FLOOR;
}
if(m_lockedFirstVisibleFloor != -1)
z = std::max<int>(m_lockedFirstVisibleFloor, z);
// just ensure the that the floor is in the valid range
z = stdext::clamp<int>(z, 0, (int)Otc::MAX_Z);
return z;
}
Point MapView::transformPositionTo2D(const Position& position, const Position& relativePosition) {
return Point((m_virtualCenterOffset.x + (position.x - relativePosition.x) - (relativePosition.z - position.z)) * g_sprites.spriteSize(),
(m_virtualCenterOffset.y + (position.y - relativePosition.y) - (relativePosition.z - position.z)) * g_sprites.spriteSize());
}
Position MapView::getCameraPosition()
{
if (isFollowingCreature()) {
return m_followingCreature->getPrewalkingPosition();
}
return m_customCameraPosition;
}
void MapView::setDrawLights(bool enable)
{
m_drawLight = enable;
}
void MapView::setCrosshair(const std::string& file)
{
if (file == "")
m_crosshair = nullptr;
else
m_crosshair = g_textures.getTexture(file);
}
/* vim: set ts=4 sw=4 et: */

View File

@ -1,177 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MAPVIEW_H
#define MAPVIEW_H
#include "declarations.h"
#include <framework/graphics/paintershaderprogram.h>
#include <framework/graphics/declarations.h>
#include <framework/luaengine/luaobject.h>
#include <framework/core/declarations.h>
#include "lightview.h"
// @bindclass
class MapView : public LuaObject
{
public:
MapView();
~MapView();
void drawBackground(const Rect& rect, const TilePtr& crosshairTile = nullptr);
void drawForeground(const Rect& rect);
void drawTexts(const Rect& rect, const Rect& srcRect);
private:
void drawTileTexts(const Rect& rect, const Rect& srcRect);
void updateGeometry(const Size& visibleDimension, const Size& optimizedSize);
void updateVisibleTilesCache();
void requestVisibleTilesCacheUpdate() { m_mustUpdateVisibleTilesCache = true; }
protected:
void onTileUpdate(const Position& pos);
void onMapCenterChange(const Position& pos);
friend class Map;
public:
// floor visibility related
void lockFirstVisibleFloor(int firstVisibleFloor);
void unlockFirstVisibleFloor();
int getLockedFirstVisibleFloor() { return m_lockedFirstVisibleFloor; }
void setMultifloor(bool enable) { m_multifloor = enable; requestVisibleTilesCacheUpdate(); }
bool isMultifloor() { return m_multifloor; }
// map dimension related
void setVisibleDimension(const Size& visibleDimension);
void optimizeForSize(const Size & visibleSize);
Size getVisibleDimension() { return m_visibleDimension; }
Point getVisibleCenterOffset() { return m_visibleCenterOffset; }
int getCachedFirstVisibleFloor() { return m_cachedFirstVisibleFloor; }
int getCachedLastVisibleFloor() { return m_cachedLastVisibleFloor; }
// camera related
void followCreature(const CreaturePtr& creature);
CreaturePtr getFollowingCreature() { return m_followingCreature; }
bool isFollowingCreature() { return m_followingCreature && m_follow; }
void setCameraPosition(const Position& pos);
Position getCameraPosition();
void setMinimumAmbientLight(float intensity) { m_minimumAmbientLight = intensity; }
float getMinimumAmbientLight() { return m_minimumAmbientLight; }
// drawing related
void setDrawFlags(Otc::DrawFlags drawFlags) { m_drawFlags = drawFlags; requestVisibleTilesCacheUpdate(); }
Otc::DrawFlags getDrawFlags() { return m_drawFlags; }
void setDrawTexts(bool enable) { m_drawTexts = enable; }
bool isDrawingTexts() { return m_drawTexts; }
void setDrawNames(bool enable) { m_drawNames = enable; }
bool isDrawingNames() { return m_drawNames; }
void setDrawHealthBars(bool enable) { m_drawHealthBars = enable; }
bool isDrawingHealthBars() { return m_drawHealthBars; }
void setDrawHealthBarsOnTop(bool enable) { m_drawHealthBarsOnTop = enable; }
bool isDrawingHealthBarsOnTop() { return m_drawHealthBarsOnTop; }
void setDrawLights(bool enable);
bool isDrawingLights() { return m_drawLight; }
void setDrawManaBar(bool enable) { m_drawManaBar = enable; }
bool isDrawingManaBar() { return m_drawManaBar; }
void setDrawPlayerBars(bool enable) { m_drawPlayerBars = enable; }
void move(int x, int y);
void setAnimated(bool animated) { m_animated = animated; requestVisibleTilesCacheUpdate(); }
bool isAnimating() { return m_animated; }
void setFloorFading(int value) { m_floorFading = value; }
void setCrosshair(const std::string& file);
//void setShader(const PainterShaderProgramPtr& shader, float fadein, float fadeout);
//PainterShaderProgramPtr getShader() { return m_shader; }
Position getPosition(const Point& point, const Size& mapSize);
Point getPositionOffset(const Point& point, const Size& mapSize);
MapViewPtr asMapView() { return static_self_cast<MapView>(); }
private:
Rect calcFramebufferSource(const Size& destSize, bool inNextFrame = false);
int calcFirstVisibleFloor(bool forFading = false);
int calcLastVisibleFloor();
Point transformPositionTo2D(const Position& position, const Position& relativePosition);
stdext::timer m_mapRenderTimer;
int m_lockedFirstVisibleFloor;
int m_cachedFirstVisibleFloor;
int m_cachedFirstFadingFloor;
int m_cachedLastVisibleFloor;
int m_updateTilesPos;
int m_floorFading = 500;
TexturePtr m_crosshair = nullptr;
Size m_drawDimension;
Size m_visibleDimension;
Size m_optimizedSize;
Point m_virtualCenterOffset;
Point m_visibleCenterOffset;
Point m_moveOffset;
Position m_customCameraPosition;
Position m_lastCameraPosition;
stdext::boolean<true> m_mustUpdateVisibleTilesCache;
stdext::boolean<true> m_mustDrawVisibleTilesCache;
stdext::boolean<true> m_multifloor;
stdext::boolean<true> m_animated;
stdext::boolean<true> m_drawTexts;
stdext::boolean<true> m_drawNames;
stdext::boolean<true> m_drawHealthBars;
stdext::boolean<false> m_drawHealthBarsOnTop;
stdext::boolean<true> m_drawManaBar;
bool m_drawPlayerBars = true;
stdext::boolean<true> m_smooth;
stdext::timer m_fadingFloorTimers[Otc::MAX_Z + 1];
stdext::boolean<true> m_follow;
std::vector<std::pair<TilePtr, bool>> m_cachedVisibleTiles;
CreaturePtr m_followingCreature;
//PainterShaderProgramPtr m_shader;
Otc::DrawFlags m_drawFlags;
bool m_drawLight = false;
float m_minimumAmbientLight;
std::unique_ptr<LightView> m_lightView;
TexturePtr m_lightTexture;
Timer m_fadeTimer;
//PainterShaderProgramPtr m_nextShader;
float m_fadeInTime;
float m_fadeOutTime;
//stdext::boolean<true> m_shaderSwitchDone;
};
#endif

View File

@ -1,438 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "minimap.h"
#include "tile.h"
#include <framework/graphics/image.h>
#include <framework/graphics/texture.h>
#include <framework/graphics/painter.h>
#include <framework/graphics/image.h>
#include <framework/graphics/framebuffermanager.h>
#include <framework/core/resourcemanager.h>
#include <framework/core/filestream.h>
#include <zlib.h>
#include <framework/util/stats.h>
Minimap g_minimap;
void MinimapBlock::clean()
{
m_tiles.fill(MinimapTile());
m_texture.reset();
m_mustUpdate = false;
}
void MinimapBlock::update()
{
if(!m_mustUpdate)
return;
ImagePtr image(new Image(Size(MMBLOCK_SIZE, MMBLOCK_SIZE)));
bool shouldDraw = false;
for(int x=0;x<MMBLOCK_SIZE;++x) {
for(int y=0;y<MMBLOCK_SIZE;++y) {
uint8 c = getTile(x, y).color;
Color col = Color::alpha;
if(c != 255) {
col = Color::from8bit(c);
shouldDraw = true;
}
image->setPixel(x, y, col);
}
}
if(shouldDraw) {
m_texture = TexturePtr(new Texture(image));
} else
m_texture.reset();
m_mustUpdate = false;
}
void MinimapBlock::updateTile(int x, int y, const MinimapTile& tile)
{
if(m_tiles[getTileIndex(x,y)].color != tile.color)
m_mustUpdate = true;
m_tiles[getTileIndex(x,y)] = tile;
}
void Minimap::init()
{
}
void Minimap::terminate()
{
clean();
}
void Minimap::clean()
{
std::lock_guard<std::mutex> lock(m_lock);
for(int i=0;i<=Otc::MAX_Z;++i)
m_tileBlocks[i].clear();
}
void Minimap::draw(const Rect& screenRect, const Position& mapCenter, float scale, const Color& color)
{
if(screenRect.isEmpty())
return;
Rect mapRect = calcMapRect(screenRect, mapCenter, scale);
g_drawQueue->addFilledRect(screenRect, color);
if(MMBLOCK_SIZE*scale <= 1 || !mapCenter.isMapPosition()) {
return;
}
size_t drawQueueStart = g_drawQueue->size();
Point blockOff = getBlockOffset(mapRect.topLeft());
Point off = Point((mapRect.size() * scale).toPoint() - screenRect.size().toPoint())/2;
Point start = screenRect.topLeft() -(mapRect.topLeft() - blockOff)*scale - off;
for(int y = blockOff.y, ys = start.y;ys<screenRect.bottom();y += MMBLOCK_SIZE, ys += MMBLOCK_SIZE*scale) {
if(y < 0 || y >= 65536)
continue;
for(int x = blockOff.x, xs = start.x;xs<screenRect.right();x += MMBLOCK_SIZE, xs += MMBLOCK_SIZE*scale) {
if(x < 0 || x >= 65536)
continue;
Position blockPos(x, y, mapCenter.z);
if(!hasBlock(blockPos))
continue;
MinimapBlock& block = getBlock(Position(x, y, mapCenter.z));
block.update();
const TexturePtr& tex = block.getTexture();
if(tex) {
Rect src(0, 0, MMBLOCK_SIZE, MMBLOCK_SIZE);
Rect dest(xs, ys, MMBLOCK_SIZE * scale, MMBLOCK_SIZE * scale);
g_drawQueue->addTexturedRect(dest, tex, src);
}
}
}
g_drawQueue->setClip(drawQueueStart, screenRect);
}
Point Minimap::getTilePoint(const Position& pos, const Rect& screenRect, const Position& mapCenter, float scale)
{
if(screenRect.isEmpty() || pos.z != mapCenter.z)
return Point(-1,-1);
Rect mapRect = calcMapRect(screenRect, mapCenter, scale);
Point off = Point((mapRect.size() * scale).toPoint() - screenRect.size().toPoint())/2;
Point posoff = (Point(pos.x,pos.y) - mapRect.topLeft())*scale;
return posoff + screenRect.topLeft() - off + (Point(1,1)*scale)/2;
}
Position Minimap::getTilePosition(const Point& point, const Rect& screenRect, const Position& mapCenter, float scale)
{
if(screenRect.isEmpty())
return Position();
Rect mapRect = calcMapRect(screenRect, mapCenter, scale);
Point off = Point((mapRect.size() * scale).toPoint() - screenRect.size().toPoint())/2;
Point pos2d = (point - screenRect.topLeft() + off)/scale + mapRect.topLeft();
return Position(pos2d.x, pos2d.y, mapCenter.z);
}
Rect Minimap::getTileRect(const Position& pos, const Rect& screenRect, const Position& mapCenter, float scale)
{
if(screenRect.isEmpty() || pos.z != mapCenter.z)
return Rect();
int tileSize = 32 * scale;
Rect tileRect(0,0,tileSize, tileSize);
tileRect.moveCenter(getTilePoint(pos, screenRect, mapCenter, scale));
return tileRect;
}
Rect Minimap::calcMapRect(const Rect& screenRect, const Position& mapCenter, float scale)
{
int w = screenRect.width() / scale, h = std::ceil(screenRect.height() / scale);
Rect mapRect(0,0,w,h);
mapRect.moveCenter(Point(mapCenter.x, mapCenter.y));
return mapRect;
}
void Minimap::updateTile(const Position& pos, const TilePtr& tile)
{
MinimapTile minimapTile;
if(tile) {
minimapTile.color = tile->getMinimapColorByte();
minimapTile.flags |= MinimapTileWasSeen;
if(!tile->isWalkable(true))
minimapTile.flags |= MinimapTileNotWalkable;
if(!tile->isPathable())
minimapTile.flags |= MinimapTileNotPathable;
minimapTile.speed = std::min<int>((int)std::ceil(tile->getGroundSpeed() / 10.0f), 255);
} else {
minimapTile.color = 255;
minimapTile.flags |= MinimapTileEmpty;
minimapTile.speed = 1;
}
if(minimapTile != MinimapTile()) {
MinimapBlock& block = getBlock(pos);
Point offsetPos = getBlockOffset(Point(pos.x, pos.y));
block.updateTile(pos.x - offsetPos.x, pos.y - offsetPos.y, minimapTile);
block.justSaw();
}
}
const MinimapTile& Minimap::getTile(const Position& pos)
{
static MinimapTile nulltile;
if(pos.z <= Otc::MAX_Z && hasBlock(pos)) {
MinimapBlock& block = getBlock(pos);
Point offsetPos = getBlockOffset(Point(pos.x, pos.y));
return block.getTile(pos.x - offsetPos.x, pos.y - offsetPos.y);
}
return nulltile;
}
std::pair<MinimapBlock_ptr, MinimapTile> Minimap::threadGetTile(const Position& pos) {
std::lock_guard<std::mutex> lock(m_lock);
static MinimapTile nulltile;
if (pos.z <= Otc::MAX_Z && hasBlock(pos)) {
MinimapBlock_ptr block = m_tileBlocks[pos.z][getBlockIndex(pos)];
if (block) {
Point offsetPos = getBlockOffset(Point(pos.x, pos.y));
return std::make_pair(block, block->getTile(pos.x - offsetPos.x, pos.y - offsetPos.y));
}
}
return std::make_pair(nullptr, nulltile);
}
bool Minimap::loadImage(const std::string& fileName, const Position& topLeft, float colorFactor)
{
if(colorFactor <= 0.01f)
colorFactor = 1.0f;
try {
ImagePtr image = Image::load(fileName);
uint8 waterc = Color::to8bit(std::string("#3300cc"));
// non pathable colors
Color nonPathableColors[] = {
std::string("#ffff00"), // yellow
};
// non walkable colors
Color nonWalkableColors[] = {
std::string("#000000"), // oil, black
std::string("#006600"), // trees, dark green
std::string("#ff3300"), // walls, red
std::string("#666666"), // mountain, grey
std::string("#ff6600"), // lava, orange
std::string("#00ff00"), // positon
std::string("#ccffff"), // ice, very light blue
};
for(int y=0;y<image->getHeight();++y) {
for(int x=0;x<image->getWidth();++x) {
Color color = *(uint32*)image->getPixel(x,y);
uint8 c = Color::to8bit(color * colorFactor);
int flags = 0;
if(c == waterc || color.a() == 0) {
flags |= MinimapTileNotWalkable;
c = 255; // alpha
}
if(flags != 0) {
for(Color &col : nonWalkableColors) {
if(col == color) {
flags |= MinimapTileNotWalkable;
break;
}
}
}
if(flags != 0) {
for(Color &col : nonPathableColors) {
if(col == color) {
flags |= MinimapTileNotPathable;
break;
}
}
}
if(c == 255)
continue;
Position pos(topLeft.x + x, topLeft.y + y, topLeft.z);
MinimapBlock& block = getBlock(pos);
Point offsetPos = getBlockOffset(Point(pos.x, pos.y));
MinimapTile& tile = block.getTile(pos.x - offsetPos.x, pos.y - offsetPos.y);
if(!(tile.flags & MinimapTileWasSeen)) {
tile.color = c;
tile.flags = flags;
block.mustUpdate();
}
}
}
return true;
} catch(stdext::exception& e) {
g_logger.error(stdext::format("failed to load OTMM minimap: %s", e.what()));
return false;
}
}
void Minimap::saveImage(const std::string& fileName, const Rect& mapRect)
{
//TODO
}
bool Minimap::loadOtmm(const std::string& fileName)
{
try {
FileStreamPtr fin = g_resources.openFile(fileName);
if(!fin)
stdext::throw_exception("unable to open file");
uint32 signature = fin->getU32();
if(signature != OTMM_SIGNATURE)
stdext::throw_exception("invalid OTMM file");
uint16 start = fin->getU16();
uint16 version = fin->getU16();
fin->getU32(); // flags
switch(version) {
case 1: {
fin->getString(); // description
break;
}
default:
stdext::throw_exception("OTMM version not supported");
}
fin->seek(start);
uint blockSize = MMBLOCK_SIZE * MMBLOCK_SIZE * sizeof(MinimapTile);
std::vector<uchar> compressBuffer(compressBound(blockSize));
std::vector<uchar> decompressBuffer(blockSize);
while(true) {
Position pos;
pos.x = fin->getU16();
pos.y = fin->getU16();
pos.z = fin->getU8();
// end of file or file is corrupted
if(!pos.isValid() || pos.z >= Otc::MAX_Z+1)
break;
MinimapBlock& block = getBlock(pos);
ulong len = fin->getU16();
ulong destLen = blockSize;
fin->read(compressBuffer.data(), len);
int ret = uncompress(decompressBuffer.data(), &destLen, compressBuffer.data(), len);
if(ret != Z_OK || destLen != blockSize)
break;
memcpy((uchar*)&block.getTiles(), decompressBuffer.data(), blockSize);
block.mustUpdate();
block.justSaw();
}
fin->close();
return true;
} catch(stdext::exception& e) {
g_logger.error(stdext::format("failed to load OTMM minimap: %s", e.what()));
return false;
}
}
void Minimap::saveOtmm(const std::string& fileName)
{
try {
stdext::timer saveTimer;
FileStreamPtr fin = g_resources.createFile(fileName);
//TODO: compression flag with zlib
uint32 flags = 0;
// header
fin->addU32(OTMM_SIGNATURE);
fin->addU16(0); // data start, will be overwritten later
fin->addU16(OTMM_VERSION);
fin->addU32(flags);
// version 1 header
fin->addString("OTMM 1.0"); // description
// go back and rewrite where the map data starts
uint32 start = fin->tell();
fin->seek(4);
fin->addU16(start);
fin->seek(start);
uint blockSize = MMBLOCK_SIZE * MMBLOCK_SIZE * sizeof(MinimapTile);
std::vector<uchar> compressBuffer(compressBound(blockSize));
const int COMPRESS_LEVEL = 3;
for(uint8_t z = 0; z <= Otc::MAX_Z; ++z) {
for(auto& it : m_tileBlocks[z]) {
int index = it.first;
MinimapBlock& block = *it.second;
if(!block.wasSeen())
continue;
Position pos = getIndexPosition(index, z);
fin->addU16(pos.x);
fin->addU16(pos.y);
fin->addU8(pos.z);
ulong len = blockSize;
int ret = compress2(compressBuffer.data(), &len, (uchar*)&block.getTiles(), blockSize, COMPRESS_LEVEL);
VALIDATE(ret == Z_OK);
fin->addU16(len);
fin->write(compressBuffer.data(), len);
}
}
// end of file
Position invalidPos;
fin->addU16(invalidPos.x);
fin->addU16(invalidPos.y);
fin->addU8(invalidPos.z);
fin->flush();
fin->close();
} catch(stdext::exception& e) {
g_logger.error(stdext::format("failed to save OTMM minimap: %s", e.what()));
}
}

View File

@ -1,125 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MINIMAP_H
#define MINIMAP_H
#include "declarations.h"
#include <framework/graphics/declarations.h>
enum {
MMBLOCK_SIZE = 64,
OTMM_SIGNATURE = 0x4D4d544F,
OTMM_VERSION = 1
};
enum MinimapTileFlags {
MinimapTileWasSeen = 1,
MinimapTileNotPathable = 2,
MinimapTileNotWalkable = 4,
MinimapTileEmpty = 8
};
#pragma pack(push,1) // disable memory alignment
struct MinimapTile
{
MinimapTile() : flags(0), color(255), speed(10) { }
uint8 flags;
uint8 color;
uint8 speed;
bool hasFlag(MinimapTileFlags flag) const { return flags & flag; }
int getSpeed() const { return speed * 10; }
bool operator==(const MinimapTile& other) const { return color == other.color && flags == other.flags && speed == other.speed; }
bool operator!=(const MinimapTile& other) const { return !(*this == other); }
};
class MinimapBlock
{
public:
void clean();
void update();
void updateTile(int x, int y, const MinimapTile& tile);
MinimapTile& getTile(int x, int y) { return m_tiles[getTileIndex(x,y)]; }
void resetTile(int x, int y) { m_tiles[getTileIndex(x,y)] = MinimapTile(); }
uint getTileIndex(int x, int y) { return ((y % MMBLOCK_SIZE) * MMBLOCK_SIZE) + (x % MMBLOCK_SIZE); }
const TexturePtr& getTexture() { return m_texture; }
std::array<MinimapTile, MMBLOCK_SIZE * MMBLOCK_SIZE>& getTiles() { return m_tiles; }
void mustUpdate() { m_mustUpdate = true; }
void justSaw() { m_wasSeen = true; }
bool wasSeen() { return m_wasSeen; }
private:
TexturePtr m_texture;
std::array<MinimapTile, MMBLOCK_SIZE * MMBLOCK_SIZE> m_tiles;
stdext::boolean<true> m_mustUpdate;
stdext::boolean<false> m_wasSeen;
};
#pragma pack(pop)
using MinimapBlock_ptr = std::shared_ptr<MinimapBlock>;
class Minimap
{
public:
void init();
void terminate();
void clean();
void draw(const Rect& screenRect, const Position& mapCenter, float scale, const Color& color);
Point getTilePoint(const Position& pos, const Rect& screenRect, const Position& mapCenter, float scale);
Position getTilePosition(const Point& point, const Rect& screenRect, const Position& mapCenter, float scale);
Rect getTileRect(const Position& pos, const Rect& screenRect, const Position& mapCenter, float scale);
void updateTile(const Position& pos, const TilePtr& tile);
const MinimapTile& getTile(const Position& pos);
std::pair<MinimapBlock_ptr, MinimapTile> threadGetTile(const Position& pos);
bool loadImage(const std::string& fileName, const Position& topLeft, float colorFactor);
void saveImage(const std::string& fileName, const Rect& mapRect);
bool loadOtmm(const std::string& fileName);
void saveOtmm(const std::string& fileName);
private:
Rect calcMapRect(const Rect& screenRect, const Position& mapCenter, float scale);
bool hasBlock(const Position& pos) { return m_tileBlocks[pos.z].find(getBlockIndex(pos)) != m_tileBlocks[pos.z].end(); }
MinimapBlock& getBlock(const Position& pos) {
std::lock_guard<std::mutex> lock(m_lock);
auto& ptr = m_tileBlocks[pos.z][getBlockIndex(pos)];
if (!ptr)
ptr = std::make_shared<MinimapBlock>();
return *ptr;
}
Point getBlockOffset(const Point& pos) { return Point(pos.x - pos.x % MMBLOCK_SIZE,
pos.y - pos.y % MMBLOCK_SIZE); }
Position getIndexPosition(int index, int z) { return Position((index % (65536 / MMBLOCK_SIZE))*MMBLOCK_SIZE,
(index / (65536 / MMBLOCK_SIZE))*MMBLOCK_SIZE, z); }
uint getBlockIndex(const Position& pos) { return ((pos.y / MMBLOCK_SIZE) * (65536 / MMBLOCK_SIZE)) + (pos.x / MMBLOCK_SIZE); }
std::unordered_map<uint, MinimapBlock_ptr> m_tileBlocks[Otc::MAX_Z+1];
std::mutex m_lock;
};
extern Minimap g_minimap;
#endif

View File

@ -1,102 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "missile.h"
#include "thingtypemanager.h"
#include "map.h"
#include "tile.h"
#include <framework/core/clock.h>
#include <framework/core/eventdispatcher.h>
void Missile::draw(const Point& dest, bool animate, LightView* lightView)
{
if(m_id == 0 || !animate)
return;
int xPattern = 0, yPattern = 0;
if(m_direction == Otc::NorthWest) {
xPattern = 0;
yPattern = 0;
} else if(m_direction == Otc::North) {
xPattern = 1;
yPattern = 0;
} else if(m_direction == Otc::NorthEast) {
xPattern = 2;
yPattern = 0;
} else if(m_direction == Otc::East) {
xPattern = 2;
yPattern = 1;
} else if(m_direction == Otc::SouthEast) {
xPattern = 2;
yPattern = 2;
} else if(m_direction == Otc::South) {
xPattern = 1;
yPattern = 2;
} else if(m_direction == Otc::SouthWest) {
xPattern = 0;
yPattern = 2;
} else if(m_direction == Otc::West) {
xPattern = 0;
yPattern = 1;
} else {
xPattern = 1;
yPattern = 1;
}
float fraction = m_animationTimer.ticksElapsed() / m_duration;
rawGetThingType()->draw(dest + m_delta * fraction, 0, xPattern, yPattern, 0, 0, Color::white, lightView);
}
void Missile::setPath(const Position& fromPosition, const Position& toPosition)
{
m_source = fromPosition;
m_destination = toPosition;
m_direction = fromPosition.getDirectionFromPosition(toPosition);
m_position = fromPosition;
m_delta = Point(toPosition.x - fromPosition.x, toPosition.y - fromPosition.y);
m_duration = 150 * std::sqrt(m_delta.length());
m_delta *= Otc::TILE_PIXELS;
m_animationTimer.restart();
// schedule removal
auto self = asMissile();
g_dispatcher.scheduleEvent([self]() { g_map.removeThing(self); }, m_duration);
}
void Missile::setId(uint32 id)
{
if(!g_things.isValidDatId(id, ThingCategoryMissile))
id = 0;
m_id = id;
}
const ThingTypePtr& Missile::getThingType()
{
return g_things.getThingType(m_id, ThingCategoryMissile);
}
ThingType* Missile::rawGetThingType()
{
return g_things.rawGetThingType(m_id, ThingCategoryMissile);
}

View File

@ -1,63 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef SHOT_H
#define SHOT_H
#include <framework/global.h>
#include <framework/core/timer.h>
#include "thing.h"
// @bindclass
class Missile : public Thing
{
enum {
TICKS_PER_FRAME = 75
};
public:
void draw(const Point& dest, bool animate = true, LightView* lightView = nullptr);
void setId(uint32 id);
void setPath(const Position& fromPosition, const Position& toPosition);
uint32 getId() { return m_id; }
MissilePtr asMissile() { return static_self_cast<Missile>(); }
bool isMissile() { return true; }
const ThingTypePtr& getThingType();
ThingType *rawGetThingType();
Position getSource() { return m_source; }
Position getDestination() { return m_destination; }
private:
Timer m_animationTimer;
Point m_delta;
float m_duration;
uint16 m_id;
Otc::Direction m_direction;
Position m_source, m_destination;
};
#endif

View File

@ -1,141 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "outfit.h"
#include "game.h"
#include "spritemanager.h"
#include <framework/graphics/painter.h>
#include <framework/graphics/drawqueue.h>
Outfit::Outfit()
{
m_category = ThingCategoryCreature;
m_id = 128;
m_auxId = 0;
resetClothes();
}
void Outfit::draw(Point dest, Otc::Direction direction, uint walkAnimationPhase, bool animate, LightView* lightView)
{
// direction correction
if (m_category != ThingCategoryCreature)
direction = Otc::North;
else if (direction == Otc::NorthEast || direction == Otc::SouthEast)
direction = Otc::East;
else if (direction == Otc::NorthWest || direction == Otc::SouthWest)
direction = Otc::West;
auto type = g_things.rawGetThingType(m_category == ThingCategoryCreature ? m_id : m_auxId, m_category);
int animationPhase = walkAnimationPhase;
if (animate && m_category == ThingCategoryCreature) {
auto idleAnimator = type->getIdleAnimator();
if (idleAnimator) {
if (walkAnimationPhase > 0) {
animationPhase += idleAnimator->getAnimationPhases() - 1;;
} else {
animationPhase = idleAnimator->getPhase();
}
} else if (type->isAnimateAlways()) {
int phases = type->getAnimator() ? type->getAnimator()->getAnimationPhases() : type->getAnimationPhases();
int ticksPerFrame = 1000 / phases;
animationPhase = (g_clock.millis() % (ticksPerFrame * phases)) / ticksPerFrame;
}
} else if(animate) {
int animationPhases = type->getAnimationPhases();
int animateTicks = g_game.getFeature(Otc::GameEnhancedAnimations) ? Otc::ITEM_TICKS_PER_FRAME_FAST : Otc::ITEM_TICKS_PER_FRAME;
if (m_category == ThingCategoryEffect) {
animationPhases = std::max<int>(1, animationPhases - 2);
animateTicks = g_game.getFeature(Otc::GameEnhancedAnimations) ? Otc::INVISIBLE_TICKS_PER_FRAME_FAST : Otc::INVISIBLE_TICKS_PER_FRAME;
}
if (animationPhases > 1)
animationPhase = (g_clock.millis() % (animateTicks * animationPhases)) / animateTicks;
if (m_category == ThingCategoryEffect)
animationPhase = std::min<int>(animationPhase + 1, animationPhases);
}
int zPattern = m_mount > 0 ? std::min<int>(1, type->getNumPatternZ() - 1) : 0;
if (zPattern > 0) {
int mountAnimationPhase = walkAnimationPhase;
auto mountType = g_things.rawGetThingType(m_mount, ThingCategoryCreature);
auto idleAnimator = mountType->getIdleAnimator();
if (idleAnimator && animate) {
if (walkAnimationPhase > 0) {
mountAnimationPhase += idleAnimator->getAnimationPhases() - 1;
} else {
mountAnimationPhase = idleAnimator->getPhase();
}
}
dest -= mountType->getDisplacement();
mountType->draw(dest, 0, direction, 0, 0, mountAnimationPhase, Color::white, lightView);
dest += type->getDisplacement();
}
if (m_aura) {
auto auraType = g_things.rawGetThingType(m_aura, ThingCategoryCreature);
auraType->draw(dest, 0, direction, 0, 0, 0, Color::white, lightView);
}
if (m_wings && (direction == Otc::South || direction == Otc::West)) {
auto wingsType = g_things.rawGetThingType(m_wings, ThingCategoryCreature);
wingsType->draw(dest, 0, direction, 0, 0, animationPhase, Color::white, lightView);
}
for (int yPattern = 0; yPattern < type->getNumPatternY(); yPattern++) {
if (yPattern > 0 && !(getAddons() & (1 << (yPattern - 1)))) {
continue;
}
if (type->getLayers() <= 1) {
type->draw(dest, 0, direction, yPattern, zPattern, animationPhase, Color::white, lightView);
continue;
}
uint32_t colors = m_head + (m_body << 8) + (m_legs << 16) + (m_feet << 24);
type->drawOutfit(dest, direction, yPattern, zPattern, animationPhase, colors, Color::white, lightView);
}
if (m_wings && (direction == Otc::North || direction == Otc::East)) {
auto wingsType = g_things.rawGetThingType(m_wings, ThingCategoryCreature);
wingsType->draw(dest, 0, direction, 0, 0, animationPhase, Color::white, lightView);
}
}
void Outfit::draw(const Rect& dest, Otc::Direction direction, uint animationPhase, bool animate)
{
int size = g_drawQueue->size();
draw(Point(0, 0), direction, animationPhase, animate);
g_drawQueue->correctOutfit(dest, size);
}
void Outfit::resetClothes()
{
setHead(0);
setBody(0);
setLegs(0);
setFeet(0);
setMount(0);
}

View File

@ -1,73 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef OUTFIT_H
#define OUTFIT_H
#include <framework/util/color.h>
#include "thingtypemanager.h"
class Outfit
{
public:
Outfit();
static Color getColor(int color)
{
return Color::getOutfitColor(color);
}
void draw(Point dest, Otc::Direction direction, uint walkAnimationPhase, bool animate = true, LightView* lightView = nullptr);
void draw(const Rect& dest, Otc::Direction direction, uint animationPhase, bool animate = true);
void setId(int id) { m_id = id; }
void setAuxId(int id) { m_auxId = id; }
void setHead(int head) { m_head = head; }
void setBody(int body) { m_body = body; }
void setLegs(int legs) { m_legs = legs; }
void setFeet(int feet) { m_feet = feet; }
void setAddons(int addons) { m_addons = addons; }
void setMount(int mount) { m_mount = mount; }
void setWings(int wings) { m_wings = wings; }
void setAura(int aura) { m_aura = aura; }
void setCategory(ThingCategory category) { m_category = category; }
void resetClothes();
int getId() const { return m_id; }
int getAuxId() const { return m_auxId; }
int getHead() const { return m_head; }
int getBody() const { return m_body; }
int getLegs() const { return m_legs; }
int getFeet() const { return m_feet; }
int getAddons() const { return m_addons; }
int getMount() const { return m_mount; }
int getWings() const { return m_wings; }
int getAura() const { return m_aura; }
ThingCategory getCategory() const { return m_category; }
private:
ThingCategory m_category;
int m_id, m_auxId, m_head, m_body, m_legs, m_feet, m_addons, m_mount = 0, m_wings = 0, m_aura = 0;
};
#endif

View File

@ -1,23 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "player.h"

View File

@ -1,39 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef PLAYER_H
#define PLAYER_H
#include "creature.h"
// @bindclass
class Player : public Creature
{
public:
Player() { }
virtual ~Player() { }
PlayerPtr asPlayer() { return static_self_cast<Player>(); }
bool isPlayer() { return true; }
};
#endif

View File

@ -1,273 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef POSITION_H
#define POSITION_H
#include "const.h"
#include <framework/stdext/types.h>
#include <framework/const.h>
#include <framework/util/point.h>
#include <vector>
class Position
{
public:
Position() : x(65535), y(65535), z(255) { }
Position(uint16 x, uint16 y, uint8 z) : x(x), y(y), z(z) { }
Position translatedToDirection(Otc::Direction direction) {
Position pos = *this;
switch(direction) {
case Otc::North:
pos.y--;
break;
case Otc::East:
pos.x++;
break;
case Otc::South:
pos.y++;
break;
case Otc::West:
pos.x--;
break;
case Otc::NorthEast:
pos.x++;
pos.y--;
break;
case Otc::SouthEast:
pos.x++;
pos.y++;
break;
case Otc::SouthWest:
pos.x--;
pos.y++;
break;
case Otc::NorthWest:
pos.x--;
pos.y--;
break;
default:
break;
}
return pos;
}
Position translatedToReverseDirection(Otc::Direction direction) {
Position pos = *this;
switch(direction) {
case Otc::North:
pos.y++;
break;
case Otc::East:
pos.x--;
break;
case Otc::South:
pos.y--;
break;
case Otc::West:
pos.x++;
break;
case Otc::NorthEast:
pos.x--;
pos.y++;
break;
case Otc::SouthEast:
pos.x--;
pos.y--;
break;
case Otc::SouthWest:
pos.x++;
pos.y--;
break;
case Otc::NorthWest:
pos.x++;
pos.y++;
break;
default:
break;
}
return pos;
}
std::vector<Position> translatedToDirections(const std::vector<Otc::Direction>& dirs) const {
Position lastPos = *this;
std::vector<Position> positions;
if(!lastPos.isValid())
return positions;
positions.push_back(lastPos);
for(auto dir : dirs) {
lastPos = lastPos.translatedToDirection(dir);
if(!lastPos.isValid())
break;
positions.push_back(lastPos);
}
return positions;
}
static double getAngleFromPositions(const Position& fromPos, const Position& toPos) {
// Returns angle in radians from 0 to 2Pi. -1 means positions are equal.
int dx = toPos.x - fromPos.x;
int dy = toPos.y - fromPos.y;
if(dx == 0 && dy == 0)
return -1;
float angle = std::atan2(dy * -1, dx);
if(angle < 0)
angle += 2 * Fw::pi;
return angle;
}
double getAngleFromPosition(const Position& position) const {
return getAngleFromPositions(*this, position);
}
static Otc::Direction getDirectionFromPositions(const Position& fromPos,
const Position& toPos)
{
float angle = getAngleFromPositions(fromPos, toPos) * RAD_TO_DEC;
if(angle >= 360 - 22.5 || angle < 0 + 22.5)
return Otc::East;
else if(angle >= 45 - 22.5 && angle < 45 + 22.5)
return Otc::NorthEast;
else if(angle >= 90 - 22.5 && angle < 90 + 22.5)
return Otc::North;
else if(angle >= 135 - 22.5 && angle < 135 + 22.5)
return Otc::NorthWest;
else if(angle >= 180 - 22.5 && angle < 180 + 22.5)
return Otc::West;
else if(angle >= 225 - 22.5 && angle < 225 + 22.5)
return Otc::SouthWest;
else if(angle >= 270 - 22.5 && angle < 270 + 22.5)
return Otc::South;
else if(angle >= 315 - 22.5 && angle < 315 + 22.5)
return Otc::SouthEast;
else
return Otc::InvalidDirection;
}
Otc::Direction getDirectionFromPosition(const Position& position) const {
return getDirectionFromPositions(*this, position);
}
bool isMapPosition() const { return (x >=0 && y >= 0 && z >= 0 && x < 65535 && y < 65535 && z <= Otc::MAX_Z); }
bool isValid() const { return !(x == 65535 && y == 65535 && z == 255); }
float distance(const Position& pos) const { return sqrt(pow((pos.x - x), 2) + pow((pos.y - y), 2)); }
int manhattanDistance(const Position& pos) const { return std::abs(pos.x - x) + std::abs(pos.y - y); }
void translate(int dx, int dy, short dz = 0) { x += dx; y += dy; z += dz; }
Position translated(int dx, int dy, short dz = 0) const { Position pos = *this; pos.x += dx; pos.y += dy; pos.z += dz; return pos; }
Position operator+(const Position& other) const { return Position(x + other.x, y + other.y, z + other.z); }
Position& operator+=(const Position& other) { x+=other.x; y+=other.y; z +=other.z; return *this; }
Position operator-(const Position& other) const { return Position(x - other.x, y - other.y, z - other.z); }
Position& operator-=(const Position& other) { x-=other.x; y-=other.y; z-=other.z; return *this; }
// Point conversion(s)
Position operator+(const Point& other) const { return Position(x + other.x, y + other.y, z); }
Position& operator+=(const Point& other) { x += other.x; y += other.y; return *this; }
Position& operator=(const Position& other) { x = other.x; y = other.y; z = other.z; return *this; }
bool operator==(const Position& other) const { return other.x == x && other.y == y && other.z == z; }
bool operator!=(const Position& other) const { return other.x!=x || other.y!=y || other.z!=z; }
bool isInRange(const Position& pos, int xRange, int yRange, int zRange = 0) const { return std::abs(x-pos.x) <= xRange && std::abs(y-pos.y) <= yRange && std::abs(z - pos.z) <= zRange; }
bool isInRange(const Position& pos, int minXRange, int maxXRange, int minYRange, int maxYRange) const {
return (pos.x >= x-minXRange && pos.x <= x+maxXRange && pos.y >= y-minYRange && pos.y <= y+maxYRange && pos.z == z);
}
// operator less than for std::map
bool operator<(const Position& other) const { return x < other.x || y < other.y || z < other.z; }
bool up(int n = 1) {
int nz = z-n;
if(nz >= 0 && nz <= Otc::MAX_Z) {
z = nz;
return true;
}
return false;
}
bool down(int n = 1) {
int nz = z+n;
if(nz >= 0 && nz <= Otc::MAX_Z) {
z = nz;
return true;
}
return false;
}
bool coveredUp(int n = 1) {
int nx = x+n, ny = y+n, nz = z-n;
if(nx >= 0 && nx <= 65535 && ny >= 0 && ny <= 65535 && nz >= 0 && nz <= Otc::MAX_Z) {
x = nx; y = ny; z = nz;
return true;
}
return false;
}
bool coveredDown(int n = 1) {
int nx = x-n, ny = y-n, nz = z+n;
if(nx >= 0 && nx <= 65535 && ny >= 0 && ny <= 65535 && nz >= 0 && nz <= Otc::MAX_Z) {
x = nx; y = ny; z = nz;
return true;
}
return false;
}
std::string toString()
{
return std::to_string(x) + "," + std::to_string(y) + "," + std::to_string(z);
}
int x;
int y;
short z;
};
struct PositionHasher {
std::size_t operator()(const Position& pos) const {
return (((pos.x * 8192) + pos.y) * 16) + pos.z;
}
};
inline std::ostream& operator<<(std::ostream& out, const Position& pos)
{
out << (int)pos.x << " " << (int)pos.y << " " << (int)pos.z;
return out;
}
inline std::istream& operator>>(std::istream& in, Position& pos)
{
int x, y, z;
in >> x >> y >> z;
pos.x = x;
pos.y = y;
pos.z = z;
return in;
}
#endif

View File

@ -1,196 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "protocolcodes.h"
namespace Proto {
std::map<uint8, uint8> messageModesMap;
void buildMessageModesMap(int version) {
messageModesMap.clear();
if(version >= 1094) {
messageModesMap[Otc::MessageMana] = 43;
}
if(version >= 1055) { // might be 1054
messageModesMap[Otc::MessageNone] = 0;
messageModesMap[Otc::MessageSay] = 1;
messageModesMap[Otc::MessageWhisper] = 2;
messageModesMap[Otc::MessageYell] = 3;
messageModesMap[Otc::MessagePrivateFrom] = 4;
messageModesMap[Otc::MessagePrivateTo] = 5;
messageModesMap[Otc::MessageChannelManagement] = 6;
messageModesMap[Otc::MessageChannel] = 7;
messageModesMap[Otc::MessageChannelHighlight] = 8;
messageModesMap[Otc::MessageSpell] = 9;
messageModesMap[Otc::MessageNpcFromStartBlock] = 10;
messageModesMap[Otc::MessageNpcFrom] = 11;
messageModesMap[Otc::MessageNpcTo] = 12;
messageModesMap[Otc::MessageGamemasterBroadcast] = 13;
messageModesMap[Otc::MessageGamemasterChannel] = 14;
messageModesMap[Otc::MessageGamemasterPrivateFrom] = 15;
messageModesMap[Otc::MessageGamemasterPrivateTo] = 16;
messageModesMap[Otc::MessageLogin] = 17;
messageModesMap[Otc::MessageWarning] = 18; // Admin
messageModesMap[Otc::MessageGame] = 19;
messageModesMap[Otc::MessageGameHighlight] = 20;
messageModesMap[Otc::MessageFailure] = 21;
messageModesMap[Otc::MessageLook] = 22;
messageModesMap[Otc::MessageDamageDealed] = 23;
messageModesMap[Otc::MessageDamageReceived] = 24;
messageModesMap[Otc::MessageHeal] = 25;
messageModesMap[Otc::MessageExp] = 26;
messageModesMap[Otc::MessageDamageOthers] = 27;
messageModesMap[Otc::MessageHealOthers] = 28;
messageModesMap[Otc::MessageExpOthers] = 29;
messageModesMap[Otc::MessageStatus] = 30;
messageModesMap[Otc::MessageLoot] = 31;
messageModesMap[Otc::MessageTradeNpc] = 32;
messageModesMap[Otc::MessageGuild] = 33;
messageModesMap[Otc::MessagePartyManagement] = 34;
messageModesMap[Otc::MessageParty] = 35;
messageModesMap[Otc::MessageBarkLow] = 36;
messageModesMap[Otc::MessageBarkLoud] = 37;
messageModesMap[Otc::MessageReport] = 38;
messageModesMap[Otc::MessageHotkeyUse] = 39;
messageModesMap[Otc::MessageTutorialHint] = 40;
messageModesMap[Otc::MessageThankyou] = 41;
messageModesMap[Otc::MessageMarket] = 42;
} else if(version >= 1036) {
for(int i = Otc::MessageNone; i <= Otc::MessageBeyondLast; ++i) {
if(i >= Otc::MessageNpcTo)
messageModesMap[i] = i + 1;
else
messageModesMap[i] = i;
}
} else if(version >= 900) {
for(int i = Otc::MessageNone; i <= Otc::MessageBeyondLast; ++i)
messageModesMap[i] = i;
messageModesMap[Otc::MessageNpcFromStartBlock] = 10;
messageModesMap[Otc::MessageNpcFrom] = 11;
} else if(version >= 861) {
messageModesMap[Otc::MessageNone] = 0;
messageModesMap[Otc::MessageSay] = 1;
messageModesMap[Otc::MessageWhisper] = 2;
messageModesMap[Otc::MessageYell] = 3;
messageModesMap[Otc::MessageNpcTo] = 4;
messageModesMap[Otc::MessageNpcFromStartBlock] = 5;
messageModesMap[Otc::MessagePrivateFrom] = 6;
messageModesMap[Otc::MessagePrivateTo] = 6;
messageModesMap[Otc::MessageChannel] = 7;
messageModesMap[Otc::MessageChannelManagement] = 8;
messageModesMap[Otc::MessageGamemasterBroadcast] = 9;
messageModesMap[Otc::MessageGamemasterChannel] = 10;
messageModesMap[Otc::MessageGamemasterPrivateFrom] = 11;
messageModesMap[Otc::MessageGamemasterPrivateTo] = 11;
messageModesMap[Otc::MessageChannelHighlight] = 12;
messageModesMap[Otc::MessageMonsterSay] = 13;
messageModesMap[Otc::MessageMonsterYell] = 14;
messageModesMap[Otc::MessageWarning] = 15;
messageModesMap[Otc::MessageGame] = 16;
messageModesMap[Otc::MessageLogin] = 17;
messageModesMap[Otc::MessageStatus] = 18;
messageModesMap[Otc::MessageLook] = 19;
messageModesMap[Otc::MessageFailure] = 20;
messageModesMap[Otc::MessageBlue] = 21;
messageModesMap[Otc::MessageRed] = 22;
} else if(version >= 840) {
messageModesMap[Otc::MessageNone] = 0;
messageModesMap[Otc::MessageSay] = 1;
messageModesMap[Otc::MessageWhisper] = 2;
messageModesMap[Otc::MessageYell] = 3;
messageModesMap[Otc::MessageNpcTo] = 4;
messageModesMap[Otc::MessageNpcFromStartBlock] = 5;
messageModesMap[Otc::MessagePrivateFrom] = 6;
messageModesMap[Otc::MessagePrivateTo] = 6;
messageModesMap[Otc::MessageChannel] = 7;
messageModesMap[Otc::MessageChannelManagement] = 8;
messageModesMap[Otc::MessageRVRChannel] = 9;
messageModesMap[Otc::MessageRVRAnswer] = 10;
messageModesMap[Otc::MessageRVRContinue] = 11;
messageModesMap[Otc::MessageGamemasterBroadcast] = 12;
messageModesMap[Otc::MessageGamemasterChannel] = 13;
messageModesMap[Otc::MessageGamemasterPrivateFrom] = 14;
messageModesMap[Otc::MessageGamemasterPrivateTo] = 14;
messageModesMap[Otc::MessageChannelHighlight] = 15;
// 16, 17 ??
messageModesMap[Otc::MessageRed] = 18;
messageModesMap[Otc::MessageMonsterSay] = 19;
messageModesMap[Otc::MessageMonsterYell] = 20;
messageModesMap[Otc::MessageWarning] = 21;
messageModesMap[Otc::MessageGame] = 22;
messageModesMap[Otc::MessageLogin] = 23;
messageModesMap[Otc::MessageStatus] = 24;
messageModesMap[Otc::MessageLook] = 25;
messageModesMap[Otc::MessageFailure] = 26;
messageModesMap[Otc::MessageBlue] = 27;
} else if(version >= 760) {
messageModesMap[Otc::MessageNone] = 0;
messageModesMap[Otc::MessageSay] = 1;
messageModesMap[Otc::MessageWhisper] = 2;
messageModesMap[Otc::MessageYell] = 3;
messageModesMap[Otc::MessagePrivateFrom] = 4;
messageModesMap[Otc::MessagePrivateTo] = 4;
messageModesMap[Otc::MessageChannel] = 5;
messageModesMap[Otc::MessageRVRChannel] = 6;
messageModesMap[Otc::MessageRVRAnswer] = 7;
messageModesMap[Otc::MessageRVRContinue] = 8;
messageModesMap[Otc::MessageGamemasterBroadcast] = 9;
messageModesMap[Otc::MessageGamemasterChannel] = 10;
messageModesMap[Otc::MessageGamemasterPrivateFrom] = 11;
messageModesMap[Otc::MessageGamemasterPrivateTo] = 11;
messageModesMap[Otc::MessageChannelHighlight] = 12;
// 13, 14, 15 ??
messageModesMap[Otc::MessageMonsterSay] = 16;
messageModesMap[Otc::MessageMonsterYell] = 17;
messageModesMap[Otc::MessageWarning] = 18;
messageModesMap[Otc::MessageGame] = 19;
messageModesMap[Otc::MessageLogin] = 20;
messageModesMap[Otc::MessageStatus] = 21;
messageModesMap[Otc::MessageLook] = 22;
messageModesMap[Otc::MessageFailure] = 23;
messageModesMap[Otc::MessageBlue] = 24;
messageModesMap[Otc::MessageRed] = 25;
}
}
Otc::MessageMode translateMessageModeFromServer(uint8 mode)
{
auto it = std::find_if(messageModesMap.begin(), messageModesMap.end(), [=] (const std::pair<uint8, uint8>& p) { return p.second == mode; });
if(it != messageModesMap.end())
return (Otc::MessageMode)it->first;
return Otc::MessageInvalid;
}
uint8 translateMessageModeToServer(Otc::MessageMode mode)
{
if(mode < 0 || mode >= Otc::LastMessage)
return Otc::MessageInvalid;
auto it = messageModesMap.find(mode);
if(it != messageModesMap.end())
return it->second;
return Otc::MessageInvalid;
}
}

View File

@ -1,361 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef PROTOCOLCODES_H
#define PROTOCOLCODES_H
#include "global.h"
namespace Proto {
enum LoginServerOpts {
LoginServerError = 10,
LoginServerMotd = 20,
LoginServerUpdateNeeded = 30,
LoginServerCharacterList = 100
};
enum ItemOpcode {
StaticText = 96,
UnknownCreature = 97,
OutdatedCreature = 98,
Creature = 99
};
enum GameServerOpcodes : uint8
{
GameServerLoginOrPendingState = 10,
GameServerGMActions = 11,
GameServerEnterGame = 15,
GameServerUpdateNeeded = 17,
GameServerLoginError = 20,
GameServerLoginAdvice = 21,
GameServerLoginWait = 22,
GameServerLoginSuccess = 23,
GameServerLoginToken = 24,
GameServerStoreButtonIndicators = 25, // 1097
GameServerPingBack = 29,
GameServerPing = 30,
GameServerChallenge = 31,
GameServerDeath = 40,
GameServerSupplyStash = 41,
GameServerSpecialContainer = 42,
// all in game opcodes must be greater than 50
GameServerFirstGameOpcode = 50,
// otclient ONLY
GameServerExtendedOpcode = 50,
GameServerProgressBar = 59,
// NOTE: add any custom opcodes in this range
// OTClientV8 64-79
GameServerNewPing = 64,
GameServerChangeMapAwareRange = 66,
GameServerFeatures = 67,
GameServerNewCancelWalk = 69,
GameServerPredictiveCancelWalk = 70,
GameServerWalkId = 71,
GameServerFloorDescription = 75,
GameServerProcessesRequest = 80,
GameServerDllsRequest = 81,
GameServerWindowsRequests = 82,
GameServerClientCheck = 99,
// original tibia ONLY
GameServerFullMap = 100,
GameServerMapTopRow = 101,
GameServerMapRightRow = 102,
GameServerMapBottomRow = 103,
GameServerMapLeftRow = 104,
GameServerUpdateTile = 105,
GameServerCreateOnMap = 106,
GameServerChangeOnMap = 107,
GameServerDeleteOnMap = 108,
GameServerMoveCreature = 109,
GameServerOpenContainer = 110,
GameServerCloseContainer = 111,
GameServerCreateContainer = 112,
GameServerChangeInContainer = 113,
GameServerDeleteInContainer = 114,
GameServerItemDetail = 118,
GameServerSetInventory = 120,
GameServerDeleteInventory = 121,
GameServerOpenNpcTrade = 122,
GameServerPlayerGoods = 123,
GameServerCloseNpcTrade = 124,
GameServerOwnTrade = 125,
GameServerCounterTrade = 126,
GameServerCloseTrade = 127,
GameServerAmbient = 130,
GameServerGraphicalEffect = 131,
GameServerTextEffect = 132,
GameServerMissleEffect = 133,
GameServerMarkCreature = 134,
GameServerTrappers = 135,
GameServerCreatureHealth = 140,
GameServerCreatureLight = 141,
GameServerCreatureOutfit = 142,
GameServerCreatureSpeed = 143,
GameServerCreatureSkull = 144,
GameServerCreatureParty = 145,
GameServerCreatureUnpass = 146,
GameServerCreatureMarks = 147,
GameServerPlayerHelpers = 148,
GameServerCreatureType = 149,
GameServerEditText = 150,
GameServerEditList = 151,
GameServerNews = 152,
GameUnkown154 = 154,
GameServerBlessDialog = 155,
GameServerBlessings = 156,
GameServerPreset = 157,
GameServerPremiumTrigger = 158, // 1038
GameServerPlayerDataBasic = 159, // 950
GameServerPlayerData = 160,
GameServerPlayerSkills = 161,
GameServerPlayerState = 162,
GameServerClearTarget = 163,
GameServerPlayerModes = 167,
GameServerSpellDelay = 164, // 870
GameServerSpellGroupDelay = 165, // 870
GameServerMultiUseDelay = 166, // 870
GameServerSetStoreDeepLink = 168, // 1097
GameServerRestingAreaState = 169,
GameServerTalk = 170,
GameServerChannels = 171,
GameServerOpenChannel = 172,
GameServerOpenPrivateChannel = 173,
GameServerRuleViolationChannel = 174,
GameServerRuleViolationRemove = 175,
GameServerRuleViolationCancel = 176,
GameServerRuleViolationLock = 177,
GameServerOpenOwnChannel = 178,
GameServerCloseChannel = 179,
GameServerTextMessage = 180,
GameServerCancelWalk = 181,
GameServerWalkWait = 182,
GameServerUnjustifiedStats = 183,
GameServerPvpSituations = 184,
GameServerHunting = 187,
GameServerFloorChangeUp = 190,
GameServerFloorChangeDown = 191,
GameServerLootContainers = 192,
GameServerTournamentLeaderboard = 197,
GameServerChooseOutfit = 200,
GameServerImpactTracker = 204,
GameServerItemsPrices = 205,
GameServerSupplyTracker = 206,
GameServerLootTracker = 207,
GameServerQuestTracker = 208,
GameServerKillTracker = 209,
GameServerVipAdd = 210,
GameServerVipState = 211,
GameServerVipLogoutOrGroupData = 212,
GameServerCyclopediaNewDetails = 217,
GameServerCyclopedia = 218,
GameServerTutorialHint = 220,
GameServerCyclopediaMapData = 221,
GameServerDailyRewardState = 222,
GameServerCoinBalance = 223,
GameServerStoreError = 224, // 1080
GameServerRequestPurchaseData = 225, // 1080
GameServerOpenRewardWall = 226,
GameServerDailyReward = 228,
GameServerDailyRewardHistory = 229,
GameServerPreyFreeRolls = 230,
GameServerPreyTimeLeft = 231,
GameServerPreyData = 232,
GameServerPreyPrices = 233,
GameServerStoreOfferDescription = 234,
GameServerImbuementWindow = 235,
GameServerCloseImbuementWindow = 236,
GameServerMessageDialog = 237,
GameServerResourceBalance = 238,
GameServerTime = 239,
GameServerQuestLog = 240,
GameServerQuestLine = 241,
GameServerCoinBalanceUpdate = 242,
GameServerChannelEvent = 243, // 910
GameServerItemInfo = 244, // 910
GameServerPlayerInventory = 245, // 910
GameServerMarketEnter = 246, // 944
GameServerMarketLeave = 247, // 944
GameServerMarketDetail = 248, // 944
GameServerMarketBrowse = 249, // 944
GameServerModalDialog = 250, // 960
GameServerStore = 251, // 1080
GameServerStoreOffers = 252, // 1080
GameServerStoreTransactionHistory = 253, // 1080
GameServerStoreCompletePurchase = 254 // 1080
};
enum ClientOpcodes : uint8
{
ClientEnterAccount = 1,
ClientPendingGame = 10,
ClientEnterGame = 15,
ClientLeaveGame = 20,
ClientPing = 29,
ClientPingBack = 30,
// all in game opcodes must be equal or greater than 50
ClientFirstGameOpcode = 50,
// otclient ONLY
ClientExtendedOpcode = 50,
// NOTE: add any custom opcodes in this range
// OTClientV8 64-79
ClientNewPing = 64,
ClientChangeMapAwareRange = 66,
ClientNewWalk = 69,
ClientProcessesResponse = 80,
ClientDllsResponse = 81,
ClientWindowsResponse = 82,
// original tibia ONLY
ClientAutoWalk = 100,
ClientWalkNorth = 101,
ClientWalkEast = 102,
ClientWalkSouth = 103,
ClientWalkWest = 104,
ClientStop = 105,
ClientWalkNorthEast = 106,
ClientWalkSouthEast = 107,
ClientWalkSouthWest = 108,
ClientWalkNorthWest = 109,
ClientTurnNorth = 111,
ClientTurnEast = 112,
ClientTurnSouth = 113,
ClientTurnWest = 114,
ClientEquipItem = 119, // 910
ClientMove = 120,
ClientInspectNpcTrade = 121,
ClientBuyItem = 122,
ClientSellItem = 123,
ClientCloseNpcTrade = 124,
ClientRequestTrade = 125,
ClientInspectTrade = 126,
ClientAcceptTrade = 127,
ClientRejectTrade = 128,
ClientUseItem = 130,
ClientUseItemWith = 131,
ClientUseOnCreature = 132,
ClientRotateItem = 133,
ClientCloseContainer = 135,
ClientUpContainer = 136,
ClientEditText = 137,
ClientEditList = 138,
ClientWrapableItem = 139,
ClientLook = 140,
ClientLookCreature = 141,
ClientTalk = 150,
ClientRequestChannels = 151,
ClientJoinChannel = 152,
ClientLeaveChannel = 153,
ClientOpenPrivateChannel = 154,
ClientOpenRuleViolation = 155,
ClientCloseRuleViolation = 156,
ClientCancelRuleViolation = 157,
ClientCloseNpcChannel = 158,
ClientChangeFightModes = 160,
ClientAttack = 161,
ClientFollow = 162,
ClientInviteToParty = 163,
ClientJoinParty = 164,
ClientRevokeInvitation = 165,
ClientPassLeadership = 166,
ClientLeaveParty = 167,
ClientShareExperience = 168,
ClientDisbandParty = 169,
ClientOpenOwnChannel = 170,
ClientInviteToOwnChannel = 171,
ClientExcludeFromOwnChannel = 172,
ClientCancelAttackAndFollow = 190,
ClientUpdateTile = 201,
ClientRefreshContainer = 202,
ClientBrowseField = 203,
ClientSeekInContainer = 204,
ClientRequestOutfit = 210,
ClientChangeOutfit = 211,
ClientMount = 212, // 870
ApplyImbuemente = 213,
ClearingImbuement = 214,
CloseImbuingWindow = 215,
ClientAddVip = 220,
ClientRemoveVip = 221,
ClientEditVip = 222,
ClientBugReport = 230,
ClientRuleViolation = 231,
ClientDebugReport = 232,
ClientPreyAction = 235,
ClientPreyRequest = 237,
ClientTransferCoins = 239, // 1080
ClientRequestQuestLog = 240,
ClientRequestQuestLine = 241,
ClientNewRuleViolation = 242, // 910
ClientRequestItemInfo = 243, // 910
ClientMarketLeave = 244, // 944
ClientMarketBrowse = 245, // 944
ClientMarketCreate = 246, // 944
ClientMarketCancel = 247, // 944
ClientMarketAccept = 248, // 944
ClientAnswerModalDialog = 249, // 960
ClientOpenStore = 250, // 1080
ClientRequestStoreOffers = 251, // 1080
ClientBuyStoreOffer = 252, // 1080
ClientOpenTransactionHistory = 253, // 1080
ClientRequestTransactionHistory = 254 // 1080
};
enum CreatureType {
CreatureTypePlayer = 0,
CreatureTypeMonster,
CreatureTypeNpc,
CreatureTypeSummonOwn,
CreatureTypeSummonOther,
CreatureTypeUnknown = 0xFF
};
enum CreaturesIdRange {
PlayerStartId = 0x10000000,
PlayerEndId = 0x40000000,
MonsterStartId = 0x40000000,
MonsterEndId = 0x80000000,
NpcStartId = 0x80000000,
NpcEndId = 0xffffffff
};
void buildMessageModesMap(int version);
Otc::MessageMode translateMessageModeFromServer(uint8 mode);
uint8 translateMessageModeToServer(Otc::MessageMode mode);
}
#endif

View File

@ -1,86 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "protocolgame.h"
#include "game.h"
#include "player.h"
#include "item.h"
#include "localplayer.h"
void ProtocolGame::login(const std::string& accountName, const std::string& accountPassword, const std::string& host, uint16 port, const std::string& characterName, const std::string& authenticatorToken, const std::string& sessionKey, const std::string& worldName)
{
m_accountName = accountName;
m_accountPassword = accountPassword;
m_authenticatorToken = authenticatorToken;
m_sessionKey = sessionKey;
m_characterName = characterName;
m_worldName = worldName;
connect(host, port);
}
void ProtocolGame::onConnect()
{
m_firstRecv = true;
Protocol::onConnect();
m_localPlayer = g_game.getLocalPlayer();
if (g_game.getFeature(Otc::GameSendWorldName))
sendWorldName();
if (g_game.getFeature(Otc::GamePacketSizeU32))
enableBigPackets();
if(g_game.getFeature(Otc::GameProtocolChecksum))
enableChecksum();
if(!g_game.getFeature(Otc::GameChallengeOnLogin))
sendLoginPacket(0, 0);
recv();
}
void ProtocolGame::onRecv(const InputMessagePtr& inputMessage)
{
m_recivedPackeds += 1;
m_recivedPackedsSize += inputMessage->getMessageSize();
if(m_firstRecv) {
m_firstRecv = false;
if(g_game.getFeature(Otc::GameMessageSizeCheck)) {
int size = g_game.getFeature(Otc::GamePacketSizeU32) ? inputMessage->getU32() : inputMessage->getU16();
if(size != inputMessage->getUnreadSize()) {
g_logger.traceError("invalid message size");
return;
}
}
}
parseMessage(inputMessage);
recv();
}
void ProtocolGame::onError(const boost::system::error_code& error)
{
g_game.processConnectionError(error);
disconnect();
}

View File

@ -1,335 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef PROTOCOLGAME_H
#define PROTOCOLGAME_H
#include "declarations.h"
#include "protocolcodes.h"
#include <framework/net/protocol.h>
#include "creature.h"
class ProtocolGame : public Protocol
{
public:
void login(const std::string& accountName, const std::string& accountPassword, const std::string& host, uint16 port, const std::string& characterName, const std::string& authenticatorToken, const std::string& sessionKey, const std::string& worldName);
void send(const OutputMessagePtr& outputMessage, bool rawPacket = false);
void sendExtendedOpcode(uint8 opcode, const std::string& buffer);
void sendLoginPacket(uint challengeTimestamp, uint8 challengeRandom);
void sendWorldName();
void sendEnterGame();
void sendLogout();
void sendPing();
void sendPingBack();
void sendNewPing(uint32_t pingId, uint16_t localPing, uint16_t fps);
void sendAutoWalk(const std::vector<Otc::Direction>& path);
void sendWalkNorth();
void sendWalkEast();
void sendWalkSouth();
void sendWalkWest();
void sendStop();
void sendWalkNorthEast();
void sendWalkSouthEast();
void sendWalkSouthWest();
void sendWalkNorthWest();
void sendTurnNorth();
void sendTurnEast();
void sendTurnSouth();
void sendTurnWest();
void sendEquipItem(int itemId, int countOrSubType);
void sendMove(const Position& fromPos, int itemId, int stackpos, const Position& toPos, int count);
void sendInspectNpcTrade(int itemId, int count);
void sendBuyItem(int itemId, int subType, int amount, bool ignoreCapacity, bool buyWithBackpack);
void sendSellItem(int itemId, int subType, int amount, bool ignoreEquipped);
void sendCloseNpcTrade();
void sendRequestTrade(const Position& pos, int thingId, int stackpos, uint playerId);
void sendInspectTrade(bool counterOffer, int index);
void sendAcceptTrade();
void sendRejectTrade();
void sendUseItem(const Position& position, int itemId, int stackpos, int index);
void sendUseItemWith(const Position& fromPos, int itemId, int fromStackPos, const Position& toPos, int toThingId, int toStackPos);
void sendUseOnCreature(const Position& pos, int thingId, int stackpos, uint creatureId);
void sendRotateItem(const Position& pos, int thingId, int stackpos);
void sendWrapableItem(const Position& pos, int thingId, int stackpos);
void sendCloseContainer(int containerId);
void sendUpContainer(int containerId);
void sendEditText(uint id, const std::string& text);
void sendEditList(uint id, int doorId, const std::string& text);
void sendLook(const Position& position, int thingId, int stackpos);
void sendLookCreature(uint creatureId);
void sendTalk(Otc::MessageMode mode, int channelId, const std::string& receiver, const std::string& message, const Position& pos, Otc::Direction dir);
void sendRequestChannels();
void sendJoinChannel(int channelId);
void sendLeaveChannel(int channelId);
void sendOpenPrivateChannel(const std::string& receiver);
void sendOpenRuleViolation(const std::string& reporter);
void sendCloseRuleViolation(const std::string& reporter);
void sendCancelRuleViolation();
void sendCloseNpcChannel();
void sendChangeFightModes(Otc::FightModes fightMode, Otc::ChaseModes chaseMode, bool safeFight, Otc::PVPModes pvpMode);
void sendAttack(uint creatureId, uint seq);
void sendFollow(uint creatureId, uint seq);
void sendInviteToParty(uint creatureId);
void sendJoinParty(uint creatureId);
void sendRevokeInvitation(uint creatureId);
void sendPassLeadership(uint creatureId);
void sendLeaveParty();
void sendShareExperience(bool active);
void sendOpenOwnChannel();
void sendInviteToOwnChannel(const std::string& name);
void sendExcludeFromOwnChannel(const std::string& name);
void sendCancelAttackAndFollow();
void sendRefreshContainer(int containerId);
void sendRequestOutfit();
void sendChangeOutfit(const Outfit& outfit);
void sendOutfitExtensionStatus(int mount = -1, int wings = -1, int aura = -1, int shader = -1);
void sendApplyImbuement(uint8_t slot, uint32_t imbuementId, bool protectionCharm);
void sendClearImbuement(uint8_t slot);
void sendCloseImbuingWindow();
void sendAddVip(const std::string& name);
void sendRemoveVip(uint playerId);
void sendEditVip(uint playerId, const std::string& description, int iconId, bool notifyLogin);
void sendBugReport(const std::string& comment);
void sendRuleViolation(const std::string& target, int reason, int action, const std::string& comment, const std::string& statement, int statementId, bool ipBanishment);
void sendDebugReport(const std::string& a, const std::string& b, const std::string& c, const std::string& d);
void sendRequestQuestLog();
void sendRequestQuestLine(int questId);
void sendNewNewRuleViolation(int reason, int action, const std::string& characterName, const std::string& comment, const std::string& translation);
void sendRequestItemInfo(int itemId, int subType, int index);
void sendAnswerModalDialog(uint32 dialog, int button, int choice);
void sendBrowseField(const Position& position);
void sendSeekInContainer(int cid, int index);
void sendBuyStoreOffer(int offerId, int productType, const std::string& name);
void sendRequestTransactionHistory(int page, int entriesPerPage);
void sendRequestStoreOffers(const std::string& categoryName, int serviceType);
void sendOpenStore(int serviceType);
void sendTransferCoins(const std::string& recipient, int amount);
void sendOpenTransactionHistory(int entiresPerPage);
void sendPreyAction(int slot, int actionType, int index);
void sendPreyRequest();
void sendProcesses();
void sendDlls();
void sendWindows();
// otclient only
void sendChangeMapAwareRange(int xrange, int yrange);
void sendNewWalk(int walkId, int predictionId, const Position& pos, uint8_t flags, const std::vector<Otc::Direction>& path);
protected:
void onConnect();
void onRecv(const InputMessagePtr& inputMessage);
void onError(const boost::system::error_code& error);
friend class Game;
public:
void addPosition(const OutputMessagePtr& msg, const Position& position);
private:
void parseStoreButtonIndicators(const InputMessagePtr& msg);
void parseSetStoreDeepLink(const InputMessagePtr& msg);
void parseRestingAreaState(const InputMessagePtr& msg);
void parseStore(const InputMessagePtr& msg);
void parseStoreError(const InputMessagePtr& msg);
void parseStoreTransactionHistory(const InputMessagePtr& msg);
void parseStoreOffers(const InputMessagePtr& msg);
void parseCompleteStorePurchase(const InputMessagePtr& msg);
void parseRequestPurchaseData(const InputMessagePtr& msg);
void parseCoinBalance(const InputMessagePtr& msg);
void parseCoinBalanceUpdate(const InputMessagePtr& msg);
void parseBlessings(const InputMessagePtr& msg);
void parseUnjustifiedStats(const InputMessagePtr& msg);
void parsePvpSituations(const InputMessagePtr& msg);
void parsePreset(const InputMessagePtr& msg);
void parseCreatureType(const InputMessagePtr& msg);
void parsePlayerHelpers(const InputMessagePtr& msg);
void parseMessage(const InputMessagePtr& msg);
void parsePendingGame(const InputMessagePtr& msg);
void parseEnterGame(const InputMessagePtr& msg);
void parseLogin(const InputMessagePtr& msg);
void parseGMActions(const InputMessagePtr& msg);
void parseUpdateNeeded(const InputMessagePtr& msg);
void parseLoginError(const InputMessagePtr& msg);
void parseLoginAdvice(const InputMessagePtr& msg);
void parseLoginWait(const InputMessagePtr& msg);
void parseLoginToken(const InputMessagePtr& msg);
void parsePing(const InputMessagePtr& msg);
void parsePingBack(const InputMessagePtr& msg);
void parseNewPing(const InputMessagePtr& msg);
void parseChallenge(const InputMessagePtr& msg);
void parseDeath(const InputMessagePtr& msg);
void parseMapDescription(const InputMessagePtr& msg);
void parseFloorDescription(const InputMessagePtr& msg);
void parseMapMoveNorth(const InputMessagePtr& msg);
void parseMapMoveEast(const InputMessagePtr& msg);
void parseMapMoveSouth(const InputMessagePtr& msg);
void parseMapMoveWest(const InputMessagePtr& msg);
void parseUpdateTile(const InputMessagePtr& msg);
void parseTileAddThing(const InputMessagePtr& msg);
void parseTileTransformThing(const InputMessagePtr& msg);
void parseTileRemoveThing(const InputMessagePtr& msg);
void parseCreatureMove(const InputMessagePtr& msg);
void parseOpenContainer(const InputMessagePtr& msg);
void parseCloseContainer(const InputMessagePtr& msg);
void parseContainerAddItem(const InputMessagePtr& msg);
void parseContainerUpdateItem(const InputMessagePtr& msg);
void parseContainerRemoveItem(const InputMessagePtr& msg);
void parseAddInventoryItem(const InputMessagePtr& msg);
void parseRemoveInventoryItem(const InputMessagePtr& msg);
void parseOpenNpcTrade(const InputMessagePtr& msg);
void parsePlayerGoods(const InputMessagePtr& msg);
void parseCloseNpcTrade(const InputMessagePtr&);
void parseWorldLight(const InputMessagePtr& msg);
void parseMagicEffect(const InputMessagePtr& msg);
void parseAnimatedText(const InputMessagePtr& msg);
void parseDistanceMissile(const InputMessagePtr& msg);
void parseCreatureMark(const InputMessagePtr& msg);
void parseTrappers(const InputMessagePtr& msg);
void parseCreatureHealth(const InputMessagePtr& msg);
void parseCreatureLight(const InputMessagePtr& msg);
void parseCreatureOutfit(const InputMessagePtr& msg);
void parseCreatureSpeed(const InputMessagePtr& msg);
void parseCreatureSkulls(const InputMessagePtr& msg);
void parseCreatureShields(const InputMessagePtr& msg);
void parseCreatureUnpass(const InputMessagePtr& msg);
void parseEditText(const InputMessagePtr& msg);
void parseEditList(const InputMessagePtr& msg);
void parsePremiumTrigger(const InputMessagePtr& msg);
void parsePreyFreeRolls(const InputMessagePtr& msg);
void parsePreyTimeLeft(const InputMessagePtr& msg);
void parsePreyData(const InputMessagePtr& msg);
void parsePreyPrices(const InputMessagePtr& msg);
void parseStoreOfferDescription(const InputMessagePtr& msg);
void parsePlayerInfo(const InputMessagePtr& msg);
void parsePlayerStats(const InputMessagePtr& msg);
void parsePlayerSkills(const InputMessagePtr& msg);
void parsePlayerState(const InputMessagePtr& msg);
void parsePlayerCancelAttack(const InputMessagePtr& msg);
void parsePlayerModes(const InputMessagePtr& msg);
void parseSpellCooldown(const InputMessagePtr& msg);
void parseSpellGroupCooldown(const InputMessagePtr& msg);
void parseMultiUseCooldown(const InputMessagePtr& msg);
void parseTalk(const InputMessagePtr& msg);
void parseChannelList(const InputMessagePtr& msg);
void parseOpenChannel(const InputMessagePtr& msg);
void parseOpenPrivateChannel(const InputMessagePtr& msg);
void parseOpenOwnPrivateChannel(const InputMessagePtr& msg);
void parseCloseChannel(const InputMessagePtr& msg);
void parseRuleViolationChannel(const InputMessagePtr& msg);
void parseRuleViolationRemove(const InputMessagePtr& msg);
void parseRuleViolationCancel(const InputMessagePtr& msg);
void parseRuleViolationLock(const InputMessagePtr& msg);
void parseOwnTrade(const InputMessagePtr& msg);
void parseCounterTrade(const InputMessagePtr& msg);
void parseCloseTrade(const InputMessagePtr&);
void parseTextMessage(const InputMessagePtr& msg);
void parseCancelWalk(const InputMessagePtr& msg);
void parseWalkWait(const InputMessagePtr& msg);
void parseFloorChangeUp(const InputMessagePtr& msg);
void parseFloorChangeDown(const InputMessagePtr& msg);
void parseOpenOutfitWindow(const InputMessagePtr& msg);
void parseVipAdd(const InputMessagePtr& msg);
void parseVipState(const InputMessagePtr& msg);
void parseVipLogout(const InputMessagePtr& msg);
void parseVipGroupData(const InputMessagePtr& msg);
void parseTutorialHint(const InputMessagePtr& msg);
void parseCyclopediaMapData(const InputMessagePtr& msg);
void parseQuestLog(const InputMessagePtr& msg);
void parseQuestLine(const InputMessagePtr& msg);
void parseChannelEvent(const InputMessagePtr& msg);
void parseItemInfo(const InputMessagePtr& msg);
void parsePlayerInventory(const InputMessagePtr& msg);
void parseModalDialog(const InputMessagePtr& msg);
void parseClientCheck(const InputMessagePtr& msg);
void parseGameNews(const InputMessagePtr& msg);
void parseMessageDialog(const InputMessagePtr& msg);
void parseBlessDialog(const InputMessagePtr& msg);
void parseResourceBalance(const InputMessagePtr& msg);
void parseServerTime(const InputMessagePtr& msg);
void parseQuestTracker(const InputMessagePtr& msg);
void parseImbuementWindow(const InputMessagePtr& msg);
void parseCloseImbuementWindow(const InputMessagePtr& msg);
void parseCyclopediaNewDetails(const InputMessagePtr& msg);
void parseCyclopedia(const InputMessagePtr& msg);
void parseDailyRewardState(const InputMessagePtr& msg);
void parseOpenRewardWall(const InputMessagePtr& msg);
void parseDailyReward(const InputMessagePtr& msg);
void parseDailyRewardHistory(const InputMessagePtr& msg);
void parseKillTracker(const InputMessagePtr& msg);
void parseLootContainers(const InputMessagePtr& msg);
void parseSupplyStash(const InputMessagePtr& msg);
void parseSpecialContainer(const InputMessagePtr& msg);
void parseDepotState(const InputMessagePtr& msg);
void parseSupplyTracker(const InputMessagePtr& msg);
void parseTournamentLeaderboard(const InputMessagePtr& msg);
void parseImpactTracker(const InputMessagePtr& msg);
void parseItemsPrices(const InputMessagePtr& msg);
void parseLootTracker(const InputMessagePtr& msg);
void parseItemDetail(const InputMessagePtr& msg);
void parseHunting(const InputMessagePtr& msg);
void parseExtendedOpcode(const InputMessagePtr& msg);
void parseChangeMapAwareRange(const InputMessagePtr& msg);
void parseProgressBar(const InputMessagePtr& msg);
void parseFeatures(const InputMessagePtr& msg);
void parseCreaturesMark(const InputMessagePtr& msg);
void parseNewCancelWalk(const InputMessagePtr& msg);
void parsePredictiveCancelWalk(const InputMessagePtr& msg);
void parseWalkId(const InputMessagePtr& msg);
void parseProcessesRequest(const InputMessagePtr& msg);
void parseDllsRequest(const InputMessagePtr& msg);
void parseWindowsRequest(const InputMessagePtr& msg);
public:
void setMapDescription(const InputMessagePtr& msg, int x, int y, int z, int width, int height);
int setFloorDescription(const InputMessagePtr& msg, int x, int y, int z, int width, int height, int offset, int skip);
int setTileDescription(const InputMessagePtr& msg, Position position);
Outfit getOutfit(const InputMessagePtr& msg, bool ignoreMount = false);
ThingPtr getThing(const InputMessagePtr& msg);
ThingPtr getMappedThing(const InputMessagePtr & msg);
CreaturePtr getCreature(const InputMessagePtr& msg, int type = 0);
StaticTextPtr getStaticText(const InputMessagePtr& msg, int type = 0);
ItemPtr getItem(const InputMessagePtr& msg, int id = 0, bool hasDescription = true);
Position getPosition(const InputMessagePtr& msg);
Imbuement getImbuementInfo(const InputMessagePtr& msg);
int getRecivedPacketsCount() { return m_recivedPackeds; }
int getRecivedPacketsSize() { return m_recivedPackedsSize; }
private:
stdext::boolean<false> m_enableSendExtendedOpcode;
stdext::boolean<false> m_gameInitialized;
stdext::boolean<false> m_mapKnown;
stdext::boolean<true> m_firstRecv;
std::string m_accountName;
std::string m_accountPassword;
std::string m_authenticatorToken;
std::string m_sessionKey;
std::string m_characterName;
std::string m_worldName;
LocalPlayerPtr m_localPlayer;
int m_recivedPackeds = 0;
int m_recivedPackedsSize = 0;
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,76 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shadermanager.h"
#include <framework/graphics/paintershaderprogram.h>
#include <framework/graphics/graphics.h>
#include <framework/core/resourcemanager.h>
#include <framework/core/eventdispatcher.h>
ShaderManager g_shaders;
void ShaderManager::init()
{
PainterShaderProgram::release();
}
void ShaderManager::terminate()
{
m_shaders.clear();
}
void ShaderManager::createShader(const std::string& name, std::string vertex, std::string fragment, bool colorMatrix)
{
if (vertex.find("\n") == std::string::npos) { // file
vertex = g_resources.guessFilePath(vertex, "frag");
vertex = g_resources.readFileContents(vertex);
}
if (fragment.find("\n") == std::string::npos) { // file
fragment = g_resources.guessFilePath(fragment, "frag");
fragment = g_resources.readFileContents(fragment);
}
g_graphicsDispatcher.addEventEx("createShader", [&, name, vertex, fragment, colorMatrix] {
auto program = PainterShaderProgram::create(vertex, fragment, colorMatrix);
if (program)
m_shaders[name] = program;
});
}
void ShaderManager::addTexture(const std::string& name, const std::string& file)
{
g_graphicsDispatcher.addEventEx("addTexture", [&, name, file] {
auto program = getShader(name);
if (program)
program->addMultiTexture(file);
});
}
PainterShaderProgramPtr ShaderManager::getShader(const std::string& name)
{
VALIDATE_GRAPHICS_THREAD();
auto it = m_shaders.find(name);
if(it != m_shaders.end())
return it->second;
return nullptr;
}

View File

@ -1,52 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef SHADERMANAGER_H
#define SHADERMANAGER_H
#include "declarations.h"
#include <framework/graphics/paintershaderprogram.h>
//@bindsingleton g_shaders
class ShaderManager
{
public:
void init();
void terminate();
void createShader(const std::string& name, std::string vertex, std::string fragment, bool colorMatrix = false);
void createOutfitShader(const std::string& name, std::string vertex, std::string fragment)
{
return createShader(name, vertex, fragment, true);
}
void addTexture(const std::string& name, const std::string& file);
PainterShaderProgramPtr getShader(const std::string& name);
private:
std::unordered_map<std::string, PainterShaderProgramPtr> m_shaders;
};
extern ShaderManager g_shaders;
#endif

View File

@ -1,139 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "spritemanager.h"
#include "game.h"
#include <framework/core/resourcemanager.h>
#include <framework/core/filestream.h>
#include <framework/graphics/image.h>
#include <framework/graphics/atlas.h>
#include <framework/util/crypt.h>
SpriteManager g_sprites;
SpriteManager::SpriteManager()
{
m_spritesCount = 0;
m_signature = 0;
}
void SpriteManager::terminate()
{
unload();
}
bool SpriteManager::loadSpr(std::string file)
{
m_spritesCount = 0;
m_signature = 0;
m_spriteSize = 32;
m_loaded = false;
m_sprites.clear();
try {
file = g_resources.guessFilePath(file, "spr");
m_spritesFile = g_resources.openFile(file);
m_signature = m_spritesFile->getU32();
m_spritesCount = g_game.getFeature(Otc::GameSpritesU32) ? m_spritesFile->getU32() : m_spritesFile->getU16();
m_spritesOffset = m_spritesFile->tell();
m_loaded = true;
g_lua.callGlobalField("g_sprites", "onLoadSpr", file);
return true;
} catch(stdext::exception& e) {
g_logger.error(stdext::format("Failed to load sprites from '%s': %s", file, e.what()));
return false;
}
}
void SpriteManager::unload()
{
m_spritesCount = 0;
m_signature = 0;
m_spritesFile = nullptr;
m_sprites.clear();
}
ImagePtr SpriteManager::getSpriteImage(int id)
{
try {
int spriteDataSize = m_spriteSize * m_spriteSize * 4;
if (id == 0 || !m_spritesFile)
return nullptr;
m_spritesFile->seek(((id - 1) * 4) + m_spritesOffset);
uint32 spriteAddress = m_spritesFile->getU32();
// no sprite? return an empty texture
if (spriteAddress == 0)
return nullptr;
m_spritesFile->seek(spriteAddress);
// color key
if (m_spriteSize == 32) {
m_spritesFile->getU8();
m_spritesFile->getU8();
m_spritesFile->getU8();
}
uint16 pixelDataSize = m_spritesFile->getU16();
ImagePtr image(new Image(Size(m_spriteSize, m_spriteSize)));
uint8* pixels = image->getPixelData();
int writePos = 0;
int read = 0;
bool useAlpha = g_game.getFeature(Otc::GameSpritesAlphaChannel);
// decompress pixels
while (read < pixelDataSize && writePos < spriteDataSize) {
uint16 transparentPixels = m_spritesFile->getU16();
uint16 coloredPixels = m_spritesFile->getU16();
writePos += transparentPixels * 4;
if (useAlpha) {
m_spritesFile->read(&pixels[writePos], std::min<uint16>(coloredPixels * 4, spriteDataSize - writePos));
writePos += coloredPixels * 4;
read += 4 + (4 * coloredPixels);
} else {
for (int i = 0; i < coloredPixels && writePos < spriteDataSize; i++) {
pixels[writePos + 0] = m_spritesFile->getU8();
pixels[writePos + 1] = m_spritesFile->getU8();
pixels[writePos + 2] = m_spritesFile->getU8();
pixels[writePos + 3] = 0xFF;
writePos += 4;
}
read += 4 + (3 * coloredPixels);
}
}
return image;
} catch (stdext::exception & e) {
g_logger.error(stdext::format("Failed to get sprite id %d: %s", id, e.what()));
return nullptr;
}
}

View File

@ -1,71 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef SPRITEMANAGER_H
#define SPRITEMANAGER_H
#include <framework/core/declarations.h>
#include <framework/graphics/declarations.h>
//@bindsingleton g_sprites
class SpriteManager
{
enum {
SPRITE_SIZE = 32,
SPRITE_DATA_SIZE = SPRITE_SIZE*SPRITE_SIZE * 4
};
public:
SpriteManager();
void terminate();
bool loadSpr(std::string file);
void unload();
#ifdef WITH_ENCRYPTION
void saveSpr(std::string fileName);
void encryptSprites(std::string fileName);
void dumpSprites(std::string dir);
#endif
uint32 getSignature() { return m_signature; }
int getSpritesCount() { return m_spritesCount; }
ImagePtr getSpriteImage(int id);
bool isLoaded() { return m_loaded; }
int spriteSize() { return m_spriteSize; }
private:
stdext::boolean<false> m_loaded;
uint32 m_signature;
int m_spritesCount;
int m_spritesOffset;
int m_spriteSize = 32;
FileStreamPtr m_spritesFile;
std::vector<std::vector<uint8_t>> m_sprites;
};
extern SpriteManager g_sprites;
#endif

View File

@ -1,168 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "statictext.h"
#include "map.h"
#include <framework/core/clock.h>
#include <framework/core/eventdispatcher.h>
#include <framework/graphics/graphics.h>
#include <framework/graphics/fontmanager.h>
StaticText::StaticText()
{
m_mode = Otc::MessageNone;
m_color = Color::white;
m_cachedText.setFont(g_fonts.getFont("verdana-11px-rounded"));
m_cachedText.setAlign(Fw::AlignCenter);
}
void StaticText::drawText(const Point& dest, const Rect& parentRect)
{
Size textSize = m_cachedText.getTextSize();
Rect rect = Rect(dest - Point(textSize.width() / 2, textSize.height()) + Point(20, 5), textSize);
Rect boundRect = rect;
boundRect.bind(parentRect);
// draw only if the real center is not too far from the parent center, or its a yell
//if(g_map.isAwareOfPosition(m_position) || isYell()) {
m_cachedText.draw(boundRect, m_color);
//}
}
void StaticText::setFont(const std::string& fontName)
{
m_cachedText.setFont(g_fonts.getFont(fontName));
}
void StaticText::setText(const std::string& text)
{
m_cachedText.setText(text);
}
bool StaticText::addMessage(const std::string& name, Otc::MessageMode mode, const std::string& text)
{
return addColoredMessage(name, mode, { text, "" });
}
bool StaticText::addColoredMessage(const std::string& name, Otc::MessageMode mode, const std::vector<std::string>& texts)
{
if (texts.empty() || texts.size() % 2 != 0)
return false;
//TODO: this could be moved to lua
// first message
if (m_messages.size() == 0) {
m_name = name;
m_mode = mode;
}
// check if we can really own the message
else if (m_name != name || m_mode != mode) {
return false;
}
// too many messages
else if (m_messages.size() > 10) {
m_messages.pop_front();
m_updateEvent->cancel();
m_updateEvent = nullptr;
}
size_t len = 0;
for (size_t i = 0; i < texts.size(); i += 2) {
len += texts[i].length();
}
int delay = std::max<int>(Otc::STATIC_DURATION_PER_CHARACTER * len, Otc::MIN_STATIC_TEXT_DURATION);
if (isYell())
delay *= 2;
m_messages.push_back(StaticTextMessage{ texts, g_clock.millis() + delay });
compose();
if (!m_updateEvent)
scheduleUpdate();
return true;
}
void StaticText::update()
{
m_messages.pop_front();
if(m_messages.empty()) {
// schedule removal
auto self = asStaticText();
g_dispatcher.addEvent([self]() { g_map.removeThing(self); });
} else {
compose();
scheduleUpdate();
}
}
void StaticText::scheduleUpdate()
{
int delay = std::max<int>(m_messages.front().time - g_clock.millis(), 0);
auto self = asStaticText();
m_updateEvent = g_dispatcher.scheduleEvent([self]() {
self->m_updateEvent = nullptr;
self->update();
}, delay);
}
void StaticText::compose()
{
//TODO: this could be moved to lua
std::vector<std::string> texts;
if(m_mode == Otc::MessageSay) {
texts.push_back(m_name + " says:\n");
texts.push_back("#EFEF00");
m_color = Color(239, 239, 0);
} else if(m_mode == Otc::MessageWhisper) {
texts.push_back(m_name + " whispers:\n");
texts.push_back("#EFEF00");
m_color = Color(239, 239, 0);
} else if(m_mode == Otc::MessageYell) {
texts.push_back(m_name + " yells:\n");
texts.push_back("#EFEF00");
m_color = Color(239, 239, 0);
} else if(m_mode == Otc::MessageMonsterSay || m_mode == Otc::MessageMonsterYell || m_mode == Otc::MessageSpell
|| m_mode == Otc::MessageBarkLow || m_mode == Otc::MessageBarkLoud) {
m_color = Color(254, 101, 0);
} else if(m_mode == Otc::MessageNpcFrom || m_mode == Otc::MessageNpcFromStartBlock) {
texts.push_back(m_name + " says:\n");
texts.push_back("#5FF7F7");
m_color = Color(95, 247, 247);
} else {
g_logger.warning(stdext::format("Unknown speak type: %d", m_mode));
}
for(uint i = 0; i < m_messages.size(); ++i) {
for (size_t j = 0; j < m_messages[i].texts.size() - 1; j += 2) {
texts.push_back(m_messages[i].texts[j]);
texts.push_back(m_messages[i].texts[j + 1].empty() ? m_color.toHex() : m_messages[i].texts[j + 1]);
}
if (texts.size() >= 2 && i < m_messages.size() - 1) {
texts[texts.size() - 2] += "\n";
}
}
m_cachedText.setColoredText(texts);
m_cachedText.wrapText(275);
}

View File

@ -1,77 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef STATICTEXT_H
#define STATICTEXT_H
#include "thing.h"
#include <framework/graphics/cachedtext.h>
#include <framework/core/timer.h>
struct StaticTextMessage {
std::vector<std::string> texts;
ticks_t time;
};
// @bindclass
class StaticText : public Thing
{
public:
StaticText();
void drawText(const Point& dest, const Rect& parentRect);
std::string getName() { return m_name; }
std::string getText() { return m_cachedText.getText(); }
Otc::MessageMode getMessageMode() { return m_mode; }
std::vector<std::string> getFirstMessage() { return m_messages[0].texts; }
bool isYell() { return m_mode == Otc::MessageYell || m_mode == Otc::MessageMonsterYell || m_mode == Otc::MessageBarkLoud; }
void setText(const std::string& text);
void setFont(const std::string& fontName);
bool addMessage(const std::string& name, Otc::MessageMode mode, const std::string& text);
bool addColoredMessage(const std::string& name, Otc::MessageMode mode, const std::vector<std::string>& texts);
StaticTextPtr asStaticText() { return static_self_cast<StaticText>(); }
bool isStaticText() { return true; }
void setColor(const Color& color) { m_color = color; }
Color getColor() { return m_color; }
CachedText& getCachedText() { return m_cachedText; }
bool hasText() { return m_cachedText.hasText(); }
private:
void update();
void scheduleUpdate();
void compose();
stdext::boolean<false> m_yell;
std::deque<StaticTextMessage> m_messages;
std::string m_name;
Otc::MessageMode m_mode;
Color m_color;
CachedText m_cachedText;
ScheduledEventPtr m_updateEvent;
};
#endif

View File

@ -1,114 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "thing.h"
#include "spritemanager.h"
#include "thingtypemanager.h"
#include <framework/graphics/graphics.h>
#include "map.h"
#include "tile.h"
#include "game.h"
#include <framework/util/stats.h>
Thing::Thing() :
m_datId(0)
{
g_stats.addThing();
}
Thing::~Thing()
{
g_stats.removeThing();
}
void Thing::setPosition(const Position& position)
{
if(m_position == position)
return;
Position oldPos = m_position;
m_position = position;
onPositionChange(position, oldPos);
}
int Thing::getStackPriority()
{
// bug fix for old versions
if (g_game.getClientVersion() <= 800 && isSplash()) {
return 1;
}
if(isGround())
return 0;
else if(isGroundBorder())
return 1;
else if(isOnBottom())
return 2;
else if(isOnTop())
return 3;
else if(isCreature())
return 4;
else // common items
return 5;
}
const TilePtr& Thing::getTile()
{
return g_map.getTile(m_position);
}
ContainerPtr Thing::getParentContainer()
{
if(m_position.x == 0xffff && m_position.y & 0x40) {
int containerId = m_position.y ^ 0x40;
return g_game.getContainer(containerId);
}
return nullptr;
}
int Thing::getStackPos()
{
if(m_position.x == 65535 && isItem()) // is inside a container
return m_position.z;
else if(const TilePtr& tile = getTile())
return tile->getThingStackPos(static_self_cast<Thing>());
else {
g_logger.traceError("got a thing with invalid stackpos");
return -1;
}
}
const ThingTypePtr& Thing::getThingType()
{
return g_things.getNullThingType();
}
ThingType* Thing::rawGetThingType()
{
return g_things.getNullThingType().get();
}
Color Thing::updatedMarkedColor() {
if (!m_marked)
return Color::white;
m_markedColor.setAlpha(0.1f + std::abs(500 - g_clock.millis() % 1000) / 1000.0f); // 0.1-0.6
return m_markedColor;
}

View File

@ -1,157 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef THING_H
#define THING_H
#include "declarations.h"
#include "thingtype.h"
#include "thingtypemanager.h"
#include <framework/luaengine/luaobject.h>
#include <framework/graphics/drawqueue.h>
// @bindclass
#pragma pack(push,1) // disable memory alignment
class Thing : public LuaObject
{
public:
Thing();
virtual ~Thing();
virtual void draw(const Point& dest, bool animate = true, LightView* lightView = nullptr) { }
virtual void setId(uint32 id) { }
void setPosition(const Position& position);
virtual uint32 getId() { return 0; }
Position getPosition() { return m_position; }
int getStackPriority();
virtual const TilePtr& getTile();
ContainerPtr getParentContainer();
int getStackPos();
void setMarked(const std::string& color) {
if (color.empty()) {
m_marked = false;
return;
}
m_marked = true;
m_markedColor = Color(color);
}
Color updatedMarkedColor();
virtual bool isItem() { return false; }
virtual bool isEffect() { return false; }
virtual bool isMissile() { return false; }
virtual bool isCreature() { return false; }
virtual bool isNpc() { return false; }
virtual bool isMonster() { return false; }
virtual bool isPlayer() { return false; }
virtual bool isLocalPlayer() { return false; }
virtual bool isAnimatedText() { return false; }
virtual bool isStaticText() { return false; }
// type shortcuts
virtual const ThingTypePtr& getThingType();
virtual ThingType *rawGetThingType();
Size getSize() { return rawGetThingType()->getSize(); }
int getWidth() { return rawGetThingType()->getWidth(); }
int getHeight() { return rawGetThingType()->getHeight(); }
virtual Point getDisplacement() { return rawGetThingType()->getDisplacement(); }
virtual int getDisplacementX() { return rawGetThingType()->getDisplacementX(); }
virtual int getDisplacementY() { return rawGetThingType()->getDisplacementY(); }
virtual int getExactSize(int layer, int xPattern, int yPattern, int zPattern, int animationPhase) { return rawGetThingType()->getExactSize(layer, xPattern, yPattern, zPattern, animationPhase); }
int getLayers() { return rawGetThingType()->getLayers(); }
int getNumPatternX() { return rawGetThingType()->getNumPatternX(); }
int getNumPatternY() { return rawGetThingType()->getNumPatternY(); }
int getNumPatternZ() { return rawGetThingType()->getNumPatternZ(); }
int getAnimationPhases() { return rawGetThingType()->getAnimationPhases(); }
AnimatorPtr getAnimator() { return rawGetThingType()->getAnimator(); }
AnimatorPtr getIdleAnimator() { return rawGetThingType()->getIdleAnimator(); }
int getGroundSpeed() { return rawGetThingType()->getGroundSpeed(); }
int getMaxTextLength() { return rawGetThingType()->getMaxTextLength(); }
Light getLight() { return rawGetThingType()->getLight(); }
int getMinimapColor() { return rawGetThingType()->getMinimapColor(); }
int getLensHelp() { return rawGetThingType()->getLensHelp(); }
int getClothSlot() { return rawGetThingType()->getClothSlot(); }
int getElevation() { return rawGetThingType()->getElevation(); }
bool isGround() { return rawGetThingType()->isGround(); }
bool isGroundBorder() { return rawGetThingType()->isGroundBorder(); }
bool isOnBottom() { return rawGetThingType()->isOnBottom(); }
bool isOnTop() { return rawGetThingType()->isOnTop(); }
bool isContainer() { return rawGetThingType()->isContainer(); }
bool isStackable() { return rawGetThingType()->isStackable(); }
bool isForceUse() { return rawGetThingType()->isForceUse(); }
bool isMultiUse() { return rawGetThingType()->isMultiUse(); }
bool isWritable() { return rawGetThingType()->isWritable(); }
bool isChargeable() { return rawGetThingType()->isChargeable(); }
bool isWritableOnce() { return rawGetThingType()->isWritableOnce(); }
bool isFluidContainer() { return rawGetThingType()->isFluidContainer(); }
bool isSplash() { return rawGetThingType()->isSplash(); }
bool isNotWalkable() { return rawGetThingType()->isNotWalkable(); }
bool isNotMoveable() { return rawGetThingType()->isNotMoveable(); }
bool blockProjectile() { return rawGetThingType()->blockProjectile(); }
bool isNotPathable() { return rawGetThingType()->isNotPathable(); }
bool isPickupable() { return rawGetThingType()->isPickupable(); }
bool isHangable() { return rawGetThingType()->isHangable(); }
bool isHookSouth() { return rawGetThingType()->isHookSouth(); }
bool isHookEast() { return rawGetThingType()->isHookEast(); }
bool isRotateable() { return rawGetThingType()->isRotateable(); }
bool hasLight() { return rawGetThingType()->hasLight(); }
bool isDontHide() { return rawGetThingType()->isDontHide(); }
bool isTranslucent() { return rawGetThingType()->isTranslucent(); }
bool hasDisplacement() { return rawGetThingType()->hasDisplacement(); }
bool hasElevation() { return rawGetThingType()->hasElevation(); }
bool isLyingCorpse() { return rawGetThingType()->isLyingCorpse(); }
bool isAnimateAlways() { return rawGetThingType()->isAnimateAlways(); }
bool hasMiniMapColor() { return rawGetThingType()->hasMiniMapColor(); }
bool hasLensHelp() { return rawGetThingType()->hasLensHelp(); }
bool isFullGround() { return rawGetThingType()->isFullGround(); }
bool isIgnoreLook() { return rawGetThingType()->isIgnoreLook(); }
bool isCloth() { return rawGetThingType()->isCloth(); }
bool isMarketable() { return rawGetThingType()->isMarketable(); }
bool isUsable() { return rawGetThingType()->isUsable(); }
bool isWrapable() { return rawGetThingType()->isWrapable(); }
bool isUnwrapable() { return rawGetThingType()->isUnwrapable(); }
bool isTopEffect() { return rawGetThingType()->isTopEffect(); }
MarketData getMarketData() { return rawGetThingType()->getMarketData(); }
void hide() { m_hidden = true; }
void show() { m_hidden = false; }
void setHidden(bool value) { m_hidden = value; }
bool isHidden() { return m_hidden; }
virtual void onPositionChange(const Position& newPos, const Position& oldPos) { }
virtual void onAppear() { }
virtual void onDisappear() { }
protected:
Position m_position;
uint16 m_datId;
bool m_marked = false;
bool m_hidden = false;
Color m_markedColor;
};
#pragma pack(pop)
#endif

View File

@ -1,67 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef DATMANAGER_H
#define DATMANAGER_H
#include <framework/global.h>
#include <framework/core/declarations.h>
#include "thingtype.h"
//@bindsingleton g_thingsType
class ThingsType
{
public:
enum Categories {
Item = 0,
Creature,
Effect,
Missile,
LastCategory
};
bool load(const std::string& file);
void unload();
bool parseThingType(const FileStreamPtr& fin, ThingType& thingType);
ThingType *getEmptyThingType() { return &m_emptyThingType; }
ThingType *getThingType(uint16 id, Categories category);
uint32 getSignature() { return m_signature; }
bool isLoaded() { return m_loaded; }
uint16 getFirstItemId() { return 100; }
uint16 getMaxItemid() { return m_things[Item].size() + 99; }
bool isValidItemId(int id) { return id >= getFirstItemId() && id <= getMaxItemid(); }
private:
uint32 m_signature;
stdext::boolean<false> m_loaded;
ThingTypeList m_things[LastCategory];
static ThingType m_emptyThingType;
};
extern ThingsType g_thingsType;
#endif

View File

@ -1,777 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "thingtype.h"
#include "spritemanager.h"
#include "game.h"
#include "lightview.h"
#include <framework/graphics/graphics.h>
#include <framework/graphics/texture.h>
#include <framework/graphics/image.h>
#include <framework/graphics/texturemanager.h>
#include <framework/core/filestream.h>
#include <framework/otml/otml.h>
ThingType::ThingType()
{
m_category = ThingInvalidCategory;
m_id = 0;
m_null = true;
m_exactSize = 0;
m_realSize = 0;
m_animator = nullptr;
m_numPatternX = m_numPatternY = m_numPatternZ = 0;
m_animationPhases = 0;
m_layers = 0;
m_elevation = 0;
m_opacity = 1.0f;
}
void ThingType::serialize(const FileStreamPtr& fin)
{
for(int i = 0; i < ThingLastAttr; ++i) {
if(!hasAttr((ThingAttr)i))
continue;
int attr = i;
if(g_game.getClientVersion() >= 780) {
if(attr == ThingAttrChargeable)
attr = ThingAttrWritable;
else if(attr >= ThingAttrWritable)
attr += 1;
} else if(g_game.getClientVersion() >= 1000) {
if(attr == ThingAttrNoMoveAnimation)
attr = 16;
else if(attr >= ThingAttrPickupable)
attr += 1;
}
fin->addU8(attr);
switch(attr) {
case ThingAttrDisplacement: {
fin->addU16(m_displacement.x);
fin->addU16(m_displacement.y);
break;
}
case ThingAttrLight: {
Light light = m_attribs.get<Light>(attr);
fin->addU16(light.intensity);
fin->addU16(light.color);
break;
}
case ThingAttrMarket: {
MarketData market = m_attribs.get<MarketData>(attr);
fin->addU16(market.category);
fin->addU16(market.tradeAs);
fin->addU16(market.showAs);
fin->addString(market.name);
fin->addU16(market.restrictVocation);
fin->addU16(market.requiredLevel);
break;
}
case ThingAttrUsable:
case ThingAttrElevation:
case ThingAttrGround:
case ThingAttrWritable:
case ThingAttrWritableOnce:
case ThingAttrMinimapColor:
case ThingAttrCloth:
case ThingAttrLensHelp:
fin->addU16(m_attribs.get<uint16>(attr));
break;
default:
break;
};
}
fin->addU8(ThingLastAttr);
fin->addU8(m_size.width());
fin->addU8(m_size.height());
if(m_size.width() > 1 || m_size.height() > 1)
fin->addU8(m_realSize);
fin->addU8(m_layers);
fin->addU8(m_numPatternX);
fin->addU8(m_numPatternY);
fin->addU8(m_numPatternZ);
fin->addU8(m_animationPhases);
if(g_game.getFeature(Otc::GameEnhancedAnimations)) {
if(m_animationPhases > 1 && m_animator != nullptr) {
m_animator->serialize(fin);
}
}
for(uint i = 0; i < m_spritesIndex.size(); i++) {
if(g_game.getFeature(Otc::GameSpritesU32))
fin->addU32(m_spritesIndex[i]);
else
fin->addU16(m_spritesIndex[i]);
}
}
void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileStreamPtr& fin)
{
m_null = false;
m_id = clientId;
m_category = category;
int count = 0, attr = -1;
bool done = false;
for(int i = 0 ; i < ThingLastAttr;++i) {
count++;
attr = fin->getU8();
if(attr == ThingLastAttr) {
done = true;
break;
}
if(g_game.getClientVersion() >= 1000) {
/* In 10.10+ all attributes from 16 and up were
* incremented by 1 to make space for 16 as
* "No Movement Animation" flag.
*/
if(attr == 16)
attr = ThingAttrNoMoveAnimation;
else if(attr > 16)
attr -= 1;
} else if(g_game.getClientVersion() >= 860) {
/* Default attribute values follow
* the format of 8.6-9.86.
* Therefore no changes here.
*/
} else if(g_game.getClientVersion() >= 780) {
/* In 7.80-8.54 all attributes from 8 and higher were
* incremented by 1 to make space for 8 as
* "Item Charges" flag.
*/
if(attr == 8) {
m_attribs.set(ThingAttrChargeable, true);
continue;
} else if(attr > 8)
attr -= 1;
} else if(g_game.getClientVersion() >= 755) {
/* In 7.55-7.72 attributes 23 is "Floor Change". */
if(attr == 23)
attr = ThingAttrFloorChange;
} else if(g_game.getClientVersion() >= 740) {
/* In 7.4-7.5 attribute "Ground Border" did not exist
* attributes 1-15 have to be adjusted.
* Several other changes in the format.
*/
if(attr > 0 && attr <= 15)
attr += 1;
else if(attr == 16)
attr = ThingAttrLight;
else if(attr == 17)
attr = ThingAttrFloorChange;
else if(attr == 18)
attr = ThingAttrFullGround;
else if(attr == 19)
attr = ThingAttrElevation;
else if(attr == 20)
attr = ThingAttrDisplacement;
else if(attr == 22)
attr = ThingAttrMinimapColor;
else if(attr == 23)
attr = ThingAttrRotateable;
else if(attr == 24)
attr = ThingAttrLyingCorpse;
else if(attr == 25)
attr = ThingAttrHangable;
else if(attr == 26)
attr = ThingAttrHookSouth;
else if(attr == 27)
attr = ThingAttrHookEast;
else if(attr == 28)
attr = ThingAttrAnimateAlways;
/* "Multi Use" and "Force Use" are swapped */
if(attr == ThingAttrMultiUse)
attr = ThingAttrForceUse;
else if(attr == ThingAttrForceUse)
attr = ThingAttrMultiUse;
}
switch(attr) {
case ThingAttrDisplacement: {
if(g_game.getClientVersion() >= 755) {
m_displacement.x = fin->getU16();
m_displacement.y = fin->getU16();
} else {
m_displacement.x = 8;
m_displacement.y = 8;
}
m_attribs.set(attr, true);
break;
}
case ThingAttrLight: {
Light light;
light.intensity = fin->getU16();
light.color = fin->getU16();
m_attribs.set(attr, light);
break;
}
case ThingAttrMarket: {
MarketData market;
market.category = fin->getU16();
market.tradeAs = fin->getU16();
market.showAs = fin->getU16();
market.name = fin->getString();
market.restrictVocation = fin->getU16();
market.requiredLevel = fin->getU16();
m_attribs.set(attr, market);
break;
}
case ThingAttrElevation: {
m_elevation = fin->getU16();
m_attribs.set(attr, m_elevation);
break;
}
case ThingAttrUsable:
case ThingAttrGround:
case ThingAttrWritable:
case ThingAttrWritableOnce:
case ThingAttrMinimapColor:
case ThingAttrCloth:
case ThingAttrLensHelp:
m_attribs.set(attr, fin->getU16());
break;
default:
m_attribs.set(attr, true);
break;
};
}
if(!done)
stdext::throw_exception(stdext::format("corrupt data (id: %d, category: %d, count: %d, lastAttr: %d)",
m_id, m_category, count, attr));
bool hasFrameGroups = (category == ThingCategoryCreature && g_game.getFeature(Otc::GameIdleAnimations));
uint8 groupCount = hasFrameGroups ? fin->getU8() : 1;
m_animationPhases = 0;
int totalSpritesCount = 0;
std::vector<Size> sizes;
std::vector<int> total_sprites;
for(int i = 0; i < groupCount; ++i) {
uint8 frameGroupType = FrameGroupDefault;
if(hasFrameGroups)
frameGroupType = fin->getU8();
uint8 width = fin->getU8();
uint8 height = fin->getU8();
m_size = Size(width, height);
sizes.push_back(m_size);
if(width > 1 || height > 1) {
m_realSize = fin->getU8();
m_exactSize = std::min<int>(m_realSize, std::max<int>(width * 32, height * 32));
}
else
m_exactSize = 32;
m_layers = fin->getU8();
m_numPatternX = fin->getU8();
m_numPatternY = fin->getU8();
if(g_game.getClientVersion() >= 755)
m_numPatternZ = fin->getU8();
else
m_numPatternZ = 1;
int groupAnimationsPhases = fin->getU8();
m_animationPhases += groupAnimationsPhases;
if(groupAnimationsPhases > 1 && g_game.getFeature(Otc::GameEnhancedAnimations)) {
AnimatorPtr animator = AnimatorPtr(new Animator);
animator->unserialize(groupAnimationsPhases, fin);
switch (frameGroupType) {
case FrameGroupIdle:
m_idleAnimator = animator;
break;
case FrameGroupMoving:
m_animator = animator;
break;
}
}
int totalSprites = m_size.area() * m_layers * m_numPatternX * m_numPatternY * m_numPatternZ * groupAnimationsPhases;
total_sprites.push_back(totalSprites);
if((totalSpritesCount+totalSprites) > 4096)
stdext::throw_exception("a thing type has more than 4096 sprites");
m_spritesIndex.resize((totalSpritesCount+totalSprites));
for(int i = totalSpritesCount; i < (totalSpritesCount+totalSprites); i++)
m_spritesIndex[i] = g_game.getFeature(Otc::GameSpritesU32) ? fin->getU32() : fin->getU16();
totalSpritesCount += totalSprites;
}
if(sizes.size() > 1) {
// correction for some sprites
for (auto& s : sizes) {
m_size.setWidth(std::max<int>(m_size.width(), s.width()));
m_size.setHeight(std::max<int>(m_size.height(), s.height()));
}
size_t expectedSize = m_size.area() * m_layers * m_numPatternX * m_numPatternY * m_numPatternZ * m_animationPhases;
if (expectedSize != m_spritesIndex.size()) {
std::vector<int> sprites(std::move(m_spritesIndex));
m_spritesIndex.clear();
m_spritesIndex.reserve(expectedSize);
for (size_t i = 0, idx = 0; i < sizes.size(); ++i) {
int totalSprites = total_sprites[i];
if (m_size == sizes[i]) {
for (int j = 0; j < totalSprites; ++j) {
m_spritesIndex.push_back(sprites[idx++]);
}
continue;
}
size_t patterns = (totalSprites / sizes[i].area());
for (size_t p = 0; p < patterns; ++p) {
for (int x = 0; x < m_size.width(); ++x) {
for (int y = 0; y < m_size.height(); ++y) {
if (x < sizes[i].width() && y < sizes[i].height()) {
m_spritesIndex.push_back(sprites[idx++]);
continue;
}
m_spritesIndex.push_back(0);
}
}
}
}
//if (m_spritesIndex.size() != expectedSize) {
// g_logger.warning(stdext::format("Wrong thingtype: %i - %i - %i", clientId, m_spritesIndex.size(), expectedSize));
//}
}
}
if (m_idleAnimator && !m_animator) {
m_animator = m_idleAnimator;
m_idleAnimator = nullptr;
}
m_textures.resize(m_animationPhases);
m_texturesFramesRects.resize(m_animationPhases);
m_texturesFramesOriginRects.resize(m_animationPhases);
m_texturesFramesOffsets.resize(m_animationPhases);
m_lastUsage = g_clock.seconds();
}
void ThingType::exportImage(std::string fileName)
{
if (m_null)
stdext::throw_exception("cannot export null thingtype");
if (m_spritesIndex.size() == 0)
stdext::throw_exception("cannot export thingtype without sprites");
size_t spriteSize = g_sprites.spriteSize();
ImagePtr image(new Image(Size(spriteSize * m_size.width() * m_layers * m_numPatternX, spriteSize * m_size.height() * m_animationPhases * m_numPatternY * m_numPatternZ)));
for (int z = 0; z < m_numPatternZ; ++z) {
for (int y = 0; y < m_numPatternY; ++y) {
for (int x = 0; x < m_numPatternX; ++x) {
for (int l = 0; l < m_layers; ++l) {
for (int a = 0; a < m_animationPhases; ++a) {
for (int w = 0; w < m_size.width(); ++w) {
for (int h = 0; h < m_size.height(); ++h) {
image->blit(Point(spriteSize * (m_size.width() - w - 1 + m_size.width() * x + m_size.width() * m_numPatternX * l),
spriteSize * (m_size.height() - h - 1 + m_size.height() * y + m_size.height() * m_numPatternY * a + m_size.height() * m_numPatternY * m_animationPhases * z)),
g_sprites.getSpriteImage(m_spritesIndex[getSpriteIndex(w, h, l, x, y, z, a)]));
}
}
}
}
}
}
}
image->savePNG(fileName);
}
void ThingType::replaceSprites(std::map<uint32_t, ImagePtr>& replacements, std::string fileName)
{
if (m_null)
stdext::throw_exception("cannot export null thingtype");
if (m_spritesIndex.size() == 0)
stdext::throw_exception("cannot export thingtype without sprites");
size_t spriteSize = g_sprites.spriteSize();
ImagePtr image = Image::loadPNG(fileName);
if (!image)
stdext::throw_exception(stdext::format("can't load image from %s", fileName));
for (int z = 0; z < m_numPatternZ; ++z) {
for (int y = 0; y < m_numPatternY; ++y) {
for (int x = 0; x < m_numPatternX; ++x) {
for (int l = 0; l < m_layers; ++l) {
for (int a = 0; a < m_animationPhases; ++a) {
for (int w = 0; w < m_size.width(); ++w) {
for (int h = 0; h < m_size.height(); ++h) {
uint32_t sprite = m_spritesIndex[getSpriteIndex(w, h, l, x, y, z, a)];
ImagePtr orgSprite = g_sprites.getSpriteImage(m_spritesIndex[getSpriteIndex(w, h, l, x, y, z, a)]);
if (!orgSprite) continue;
Point src(spriteSize * (m_size.width() - w - 1 + m_size.width() * x + m_size.width() * m_numPatternX * l),
spriteSize * (m_size.height() - h - 1 + m_size.height() * y + m_size.height() * m_numPatternY * a + m_size.height() * m_numPatternY * m_animationPhases * z));
src = src * 2;
ImagePtr newSprite(new Image(Size(orgSprite->getSize() * 2)));
for (int x = 0; x < newSprite->getSize().width(); ++x) {
for (int y = 0; y < newSprite->getSize().height(); ++y) {
newSprite->setPixel(x, y, image->getPixel(src.x + x, src.y + y));
}
}
replacements[sprite] = newSprite;
}
}
}
}
}
}
}
}
void ThingType::unserializeOtml(const OTMLNodePtr& node)
{
for(const OTMLNodePtr& node2 : node->children()) {
if(node2->tag() == "opacity")
m_opacity = node2->value<float>();
else if(node2->tag() == "notprewalkable")
m_attribs.set(ThingAttrNotPreWalkable, node2->value<bool>());
else if(node2->tag() == "image")
m_customImage = node2->value();
else if(node2->tag() == "full-ground") {
if(node2->value<bool>())
m_attribs.set(ThingAttrFullGround, true);
else
m_attribs.remove(ThingAttrFullGround);
}
}
}
void ThingType::unload()
{
m_textures.clear();
m_texturesFramesRects.clear();
m_texturesFramesOriginRects.clear();
m_texturesFramesOffsets.clear();
m_textures.resize(m_animationPhases);
m_texturesFramesRects.resize(m_animationPhases);
m_texturesFramesOriginRects.resize(m_animationPhases);
m_texturesFramesOffsets.resize(m_animationPhases);
m_loaded = false;
}
DrawQueueItem* ThingType::draw(const Point& dest, int layer, int xPattern, int yPattern, int zPattern, int animationPhase, Color color, LightView* lightView)
{
if (m_null)
return nullptr;
if (animationPhase < 0 || animationPhase >= m_animationPhases)
return nullptr;
const TexturePtr& texture = getTexture(animationPhase); // texture might not exists, neither its rects.
if (!texture)
return nullptr;
uint frameIndex = getTextureIndex(layer, xPattern, yPattern, zPattern);
if (frameIndex >= m_texturesFramesRects[animationPhase].size())
return nullptr;
Point textureOffset = m_texturesFramesOffsets[animationPhase][frameIndex];
Rect textureRect = m_texturesFramesRects[animationPhase][frameIndex];
Rect screenRect(dest + (textureOffset - m_displacement - (m_size.toPoint() - Point(1, 1)) * Otc::TILE_PIXELS), textureRect.size());
bool useOpacity = m_opacity < 1.0f;
if (useOpacity)
color.setAlpha(m_opacity);
if (lightView && hasLight())
lightView->addLight(screenRect.center(), getLight());
return g_drawQueue->addTexturedRect(screenRect, texture, textureRect, color);
}
DrawQueueItem* ThingType::draw(const Rect& dest, int layer, int xPattern, int yPattern, int zPattern, int animationPhase, Color color)
{
if (m_null)
return nullptr;
if (animationPhase < 0 || animationPhase >= m_animationPhases)
return nullptr;
const TexturePtr& texture = getTexture(animationPhase); // texture might not exists, neither its rects.
if (!texture)
return nullptr;
uint frameIndex = getTextureIndex(layer, xPattern, yPattern, zPattern);
if (frameIndex >= m_texturesFramesRects[animationPhase].size())
return nullptr;
Point textureOffset = m_texturesFramesOffsets[animationPhase][frameIndex];
Rect textureRect = m_texturesFramesRects[animationPhase][frameIndex];
bool useOpacity = m_opacity < 1.0f;
if (useOpacity)
color.setAlpha(m_opacity);
Size size = m_size * Otc::TILE_PIXELS;
if (!size.isValid())
return nullptr;
// size correction for some too big items
if ((size.width() > 1 || size.height() > 1) &&
textureRect.width() <= Otc::TILE_PIXELS && textureRect.height() <= Otc::TILE_PIXELS) {
size = Size(Otc::TILE_PIXELS, Otc::TILE_PIXELS);
textureOffset = Point((Otc::TILE_PIXELS - textureRect.width()) / 2,
(Otc::TILE_PIXELS - textureRect.height()) / 2);
}
float scale = std::min<float>((float)dest.width() / size.width(), (float)dest.height() / size.height());
return g_drawQueue->addTexturedRect(Rect(dest.topLeft() + (textureOffset * scale), textureRect.size() * scale), texture, textureRect, color);
}
void ThingType::drawOutfit(const Point& dest, int xPattern, int yPattern, int zPattern, int animationPhase, int colors, Color color, LightView* lightView)
{
if (m_null)
return;
if (animationPhase < 0 || animationPhase >= m_animationPhases)
return;
const TexturePtr& texture = getTexture(animationPhase); // texture might not exists, neither its rects.
if (!texture)
return;
uint frameIndex = getTextureIndex(0, xPattern, yPattern, zPattern);
uint frameIndex2 = getTextureIndex(1, xPattern, yPattern, zPattern);
if (frameIndex >= m_texturesFramesRects[animationPhase].size() || frameIndex2 >= m_texturesFramesRects[animationPhase].size())
return;
Point textureOffset = m_texturesFramesOffsets[animationPhase][frameIndex];
Point textureOffset2 = m_texturesFramesOffsets[animationPhase][frameIndex2];
Rect textureRect = m_texturesFramesRects[animationPhase][frameIndex];
Rect textureRect2 = m_texturesFramesRects[animationPhase][frameIndex2];
Size size = textureRect.size();
if (!size.isValid())
return;
Rect screenRect(dest + (textureOffset - m_displacement - (m_size.toPoint() - Point(1, 1)) * Otc::TILE_PIXELS), textureRect.size());
bool useOpacity = m_opacity < 1.0f;
if (useOpacity)
color.setAlpha(m_opacity);
if (lightView && hasLight())
lightView->addLight(screenRect.center(), getLight());
Point offset = textureOffset - textureOffset2;
offset += textureRect2.topLeft() - textureRect.topLeft();
g_drawQueue->addOutfit(screenRect, texture, textureRect, offset, colors, color);
}
Rect ThingType::getDrawSize(const Point& dest, int layer, int xPattern, int yPattern, int zPattern, int animationPhase)
{
if (m_null)
return Rect(0, 0, 1, 1);
if (animationPhase < 0 || animationPhase >= m_animationPhases)
return Rect(0, 0, 1, 1);
const TexturePtr& texture = getTexture(animationPhase); // texture might not exists, neither its rects.
if (!texture)
return Rect(0, 0, 1, 1);
uint frameIndex = getTextureIndex(layer, xPattern, yPattern, zPattern);
if (frameIndex >= m_texturesFramesRects[animationPhase].size())
return Rect(0, 0, 1, 1);
Point textureOffset = m_texturesFramesOffsets[animationPhase][frameIndex];
Rect textureRect = m_texturesFramesRects[animationPhase][frameIndex];
return Rect(dest + textureOffset - m_displacement - (m_size.toPoint() - Point(1, 1)) * Otc::TILE_PIXELS, textureRect.size());
}
const TexturePtr& ThingType::getTexture(int animationPhase)
{
m_lastUsage = g_clock.seconds();
int spriteSize = g_sprites.spriteSize();
TexturePtr& animationPhaseTexture = m_textures[animationPhase];
if(!animationPhaseTexture) {
bool useCustomImage = false;
if(animationPhase == 0 && !m_customImage.empty())
useCustomImage = true;
// we don't need layers in common items, they will be pre-drawn
int textureLayers = 1;
int numLayers = m_layers;
if(m_category == ThingCategoryCreature && numLayers >= 2) {
// otcv8 optimization from 5 to 2 layers
textureLayers = 2;
numLayers = 2;
}
int indexSize = textureLayers * m_numPatternX * m_numPatternY * m_numPatternZ;
Size textureSize = getBestTextureDimension(m_size.width(), m_size.height(), indexSize);
ImagePtr fullImage;
if(useCustomImage)
fullImage = Image::load(m_customImage);
else
fullImage = ImagePtr(new Image(textureSize * spriteSize));
m_texturesFramesRects[animationPhase].resize(indexSize);
m_texturesFramesOriginRects[animationPhase].resize(indexSize);
m_texturesFramesOffsets[animationPhase].resize(indexSize);
for(int z = 0; z < m_numPatternZ; ++z) {
for(int y = 0; y < m_numPatternY; ++y) {
for(int x = 0; x < m_numPatternX; ++x) {
for(int l = 0; l < numLayers; ++l) {
bool spriteMask = (m_category == ThingCategoryCreature && l > 0);
int frameIndex = getTextureIndex(l % textureLayers, x, y, z);
Point framePos = Point(frameIndex % (textureSize.width() / m_size.width()) * m_size.width(),
frameIndex / (textureSize.width() / m_size.width()) * m_size.height()) * spriteSize;
if (!useCustomImage) {
for (int h = 0; h < m_size.height(); ++h) {
for (int w = 0; w < m_size.width(); ++w) {
uint spriteIndex = getSpriteIndex(w, h, spriteMask ? 1 : l, x, y, z, animationPhase);
ImagePtr spriteImage = g_sprites.getSpriteImage(m_spritesIndex[spriteIndex]);
if (!spriteImage) {
continue;
}
Point spritePos = Point(m_size.width() - w - 1,
m_size.height() - h - 1) * spriteSize;
fullImage->blit(framePos + spritePos, spriteImage);
}
}
}
Rect drawRect(framePos + Point(m_size.width(), m_size.height()) * spriteSize - Point(1,1), framePos);
for(int x = framePos.x; x < framePos.x + m_size.width() * spriteSize; ++x) {
for(int y = framePos.y; y < framePos.y + m_size.height() * spriteSize; ++y) {
uint8 *p = fullImage->getPixel(x,y);
if(p[3] != 0x00) {
drawRect.setTop (std::min<int>(y, (int)drawRect.top()));
drawRect.setLeft (std::min<int>(x, (int)drawRect.left()));
drawRect.setBottom(std::max<int>(y, (int)drawRect.bottom()));
drawRect.setRight (std::max<int>(x, (int)drawRect.right()));
}
}
}
m_texturesFramesRects[animationPhase][frameIndex] = drawRect;
m_texturesFramesOriginRects[animationPhase][frameIndex] = Rect(framePos, Size(m_size.width(), m_size.height()) * spriteSize);// *0.5;
m_texturesFramesOffsets[animationPhase][frameIndex] = (drawRect.topLeft() - framePos);
}
}
}
}
animationPhaseTexture = TexturePtr(new Texture(fullImage, true, false, true));
m_loaded = true;
}
return animationPhaseTexture;
}
Size ThingType::getBestTextureDimension(int w, int h, int count)
{
const int MAX = 32;
int k = 1;
while(k < w)
k<<=1;
w = k;
k = 1;
while(k < h)
k<<=1;
h = k;
int numSprites = w*h*count;
VALIDATE(numSprites <= MAX*MAX);
VALIDATE(w <= MAX);
VALIDATE(h <= MAX);
Size bestDimension = Size(MAX, MAX);
for(int i=w;i<=MAX;i<<=1) {
for(int j=h;j<=MAX;j<<=1) {
Size candidateDimension = Size(i, j);
if(candidateDimension.area() < numSprites)
continue;
if((candidateDimension.area() < bestDimension.area()) ||
(candidateDimension.area() == bestDimension.area() && candidateDimension.width() + candidateDimension.height() < bestDimension.width() + bestDimension.height()))
bestDimension = candidateDimension;
}
}
return bestDimension;
}
uint ThingType::getSpriteIndex(int w, int h, int l, int x, int y, int z, int a) {
uint index =
((((((a % m_animationPhases)
* m_numPatternZ + z)
* m_numPatternY + y)
* m_numPatternX + x)
* m_layers + l)
* m_size.height() + h)
* m_size.width() + w;
VALIDATE(index < m_spritesIndex.size());
return index;
}
uint ThingType::getTextureIndex(int l, int x, int y, int z) {
return ((l * m_numPatternZ + z)
* m_numPatternY + y)
* m_numPatternX + x;
}
int ThingType::getExactSize(int layer, int xPattern, int yPattern, int zPattern, int animationPhase)
{
if(m_null)
return 0;
getTexture(animationPhase); // we must calculate it anyway.
int frameIndex = getTextureIndex(layer, xPattern, yPattern, zPattern);
Size size = m_texturesFramesOriginRects[animationPhase][frameIndex].size() - m_texturesFramesOffsets[animationPhase][frameIndex].toSize();
return std::max<int>(size.width(), size.height());
}
void ThingType::setPathable(bool var)
{
if(var == true)
m_attribs.remove(ThingAttrNotPathable);
else
m_attribs.set(ThingAttrNotPathable, true);
}

View File

@ -1,290 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef THINGTYPE_H
#define THINGTYPE_H
#include "declarations.h"
#include "animator.h"
#include <framework/core/declarations.h>
#include <framework/otml/declarations.h>
#include <framework/graphics/texture.h>
#include <framework/graphics/coordsbuffer.h>
#include <framework/graphics/drawqueue.h>
#include <framework/luaengine/luaobject.h>
#include <framework/net/server.h>
enum NewDrawType : uint8 {
NewDrawNormal = 0,
NewDrawMount = 5,
NewDrawOutfit = 6,
NewDrawOutfitLayers = 7,
NewDrawMissle = 10
};
enum FrameGroupType : uint8 {
FrameGroupDefault = 0,
FrameGroupIdle = FrameGroupDefault,
FrameGroupMoving
};
enum ThingCategory : uint8 {
ThingCategoryItem = 0,
ThingCategoryCreature,
ThingCategoryEffect,
ThingCategoryMissile,
ThingInvalidCategory,
ThingLastCategory = ThingInvalidCategory
};
enum ThingAttr : uint8 {
ThingAttrGround = 0,
ThingAttrGroundBorder = 1,
ThingAttrOnBottom = 2,
ThingAttrOnTop = 3,
ThingAttrContainer = 4,
ThingAttrStackable = 5,
ThingAttrForceUse = 6,
ThingAttrMultiUse = 7,
ThingAttrWritable = 8,
ThingAttrWritableOnce = 9,
ThingAttrFluidContainer = 10,
ThingAttrSplash = 11,
ThingAttrNotWalkable = 12,
ThingAttrNotMoveable = 13,
ThingAttrBlockProjectile = 14,
ThingAttrNotPathable = 15,
ThingAttrPickupable = 16,
ThingAttrHangable = 17,
ThingAttrHookSouth = 18,
ThingAttrHookEast = 19,
ThingAttrRotateable = 20,
ThingAttrLight = 21,
ThingAttrDontHide = 22,
ThingAttrTranslucent = 23,
ThingAttrDisplacement = 24,
ThingAttrElevation = 25,
ThingAttrLyingCorpse = 26,
ThingAttrAnimateAlways = 27,
ThingAttrMinimapColor = 28,
ThingAttrLensHelp = 29,
ThingAttrFullGround = 30,
ThingAttrLook = 31,
ThingAttrCloth = 32,
ThingAttrMarket = 33,
ThingAttrUsable = 34,
ThingAttrWrapable = 35,
ThingAttrUnwrapable = 36,
ThingAttrTopEffect = 37,
// additional
ThingAttrOpacity = 100,
ThingAttrNotPreWalkable = 101,
ThingAttrFloorChange = 252,
ThingAttrNoMoveAnimation = 253, // 10.10: real value is 16, but we need to do this for backwards compatibility
ThingAttrChargeable = 254, // deprecated
ThingLastAttr = 255
};
enum SpriteMask {
SpriteMask = 1,
};
struct MarketData {
std::string name;
int category;
uint16 requiredLevel;
uint16 restrictVocation;
uint16 showAs;
uint16 tradeAs;
};
struct StoreCategory {
std::string name;
std::string description;
int state;
std::string icon;
std::string parent;
};
struct StoreOffer {
int id;
std::string name;
std::string description;
int price;
int state;
std::string icon;
};
struct Imbuement {
int id;
std::string name;
std::string description;
std::string group;
int imageId;
int duration;
bool premiumOnly;
std::vector<std::pair<ItemPtr, std::string>> sources;
int cost;
int successRate;
int protectionCost;
};
struct Light {
Point pos;
uint8_t color = 215;
uint8_t intensity = 0;
};
class ThingType : public LuaObject
{
public:
ThingType();
void unserialize(uint16 clientId, ThingCategory category, const FileStreamPtr& fin);
void unserializeOtml(const OTMLNodePtr& node);
void unload();
void serialize(const FileStreamPtr& fin);
void exportImage(std::string fileName);
void replaceSprites(std::map<uint32_t, ImagePtr>& replacements, std::string fileName);
DrawQueueItem* draw(const Point& dest, int layer, int xPattern, int yPattern, int zPattern, int animationPhase, Color color = Color::white, LightView* lightView = nullptr);
DrawQueueItem* draw(const Rect& dest, int layer, int xPattern, int yPattern, int zPattern, int animationPhase, Color color = Color::white);
void drawOutfit(const Point& dest, int xPattern, int yPattern, int zPattern, int animationPhase, int colors, Color color = Color::white, LightView* lightView = nullptr);
Rect getDrawSize(const Point& dest, int layer, int xPattern, int yPattern, int zPattern, int animationPhase);
uint16 getId() { return m_id; }
ThingCategory getCategory() { return m_category; }
bool isNull() { return m_null; }
bool hasAttr(ThingAttr attr) { return m_attribs.has(attr); }
bool isLoaded() { return m_loaded; }
ticks_t getLastUsage() { return m_lastUsage; }
Size getSize() { return m_size; }
int getWidth() { return m_size.width(); }
int getHeight() { return m_size.height(); }
int getExactSize(int layer = 0, int xPattern = 0, int yPattern = 0, int zPattern = 0, int animationPhase = 0);
int getRealSize() { return m_realSize; }
int getLayers() { return m_layers; }
int getNumPatternX() { return m_numPatternX; }
int getNumPatternY() { return m_numPatternY; }
int getNumPatternZ() { return m_numPatternZ; }
int getAnimationPhases() { return m_animationPhases; }
AnimatorPtr getAnimator() { return m_animator; }
AnimatorPtr getIdleAnimator() { return m_idleAnimator; }
Point getDisplacement() { return m_displacement; }
int getDisplacementX() { return getDisplacement().x; }
int getDisplacementY() { return getDisplacement().y; }
int getElevation() { return m_elevation; }
int getGroundSpeed() { return m_attribs.get<uint16>(ThingAttrGround); }
int getMaxTextLength() { return m_attribs.has(ThingAttrWritableOnce) ? m_attribs.get<uint16>(ThingAttrWritableOnce) : m_attribs.get<uint16>(ThingAttrWritable); }
Light getLight() { return m_attribs.get<Light>(ThingAttrLight); }
int getMinimapColor() { return m_attribs.get<uint16>(ThingAttrMinimapColor); }
int getLensHelp() { return m_attribs.get<uint16>(ThingAttrLensHelp); }
int getClothSlot() { return m_attribs.get<uint16>(ThingAttrCloth); }
MarketData getMarketData() { return m_attribs.get<MarketData>(ThingAttrMarket); }
bool isGround() { return m_attribs.has(ThingAttrGround); }
bool isGroundBorder() { return m_attribs.has(ThingAttrGroundBorder); }
bool isOnBottom() { return m_attribs.has(ThingAttrOnBottom); }
bool isOnTop() { return m_attribs.has(ThingAttrOnTop); }
bool isContainer() { return m_attribs.has(ThingAttrContainer); }
bool isStackable() { return m_attribs.has(ThingAttrStackable); }
bool isForceUse() { return m_attribs.has(ThingAttrForceUse); }
bool isMultiUse() { return m_attribs.has(ThingAttrMultiUse); }
bool isWritable() { return m_attribs.has(ThingAttrWritable); }
bool isChargeable() { return m_attribs.has(ThingAttrChargeable); }
bool isWritableOnce() { return m_attribs.has(ThingAttrWritableOnce); }
bool isFluidContainer() { return m_attribs.has(ThingAttrFluidContainer); }
bool isSplash() { return m_attribs.has(ThingAttrSplash); }
bool isNotWalkable() { return m_attribs.has(ThingAttrNotWalkable); }
bool isNotMoveable() { return m_attribs.has(ThingAttrNotMoveable); }
bool blockProjectile() { return m_attribs.has(ThingAttrBlockProjectile); }
bool isNotPathable() { return m_attribs.has(ThingAttrNotPathable); }
bool isPickupable() { return m_attribs.has(ThingAttrPickupable); }
bool isHangable() { return m_attribs.has(ThingAttrHangable); }
bool isHookSouth() { return m_attribs.has(ThingAttrHookSouth); }
bool isHookEast() { return m_attribs.has(ThingAttrHookEast); }
bool isRotateable() { return m_attribs.has(ThingAttrRotateable); }
bool hasLight() { return m_attribs.has(ThingAttrLight); }
bool isDontHide() { return m_attribs.has(ThingAttrDontHide); }
bool isTranslucent() { return m_attribs.has(ThingAttrTranslucent); }
bool hasDisplacement() { return m_attribs.has(ThingAttrDisplacement); }
bool hasElevation() { return m_attribs.has(ThingAttrElevation); }
bool isLyingCorpse() { return m_attribs.has(ThingAttrLyingCorpse); }
bool isAnimateAlways() { return m_attribs.has(ThingAttrAnimateAlways); }
bool hasMiniMapColor() { return m_attribs.has(ThingAttrMinimapColor); }
bool hasLensHelp() { return m_attribs.has(ThingAttrLensHelp); }
bool isFullGround() { return m_attribs.has(ThingAttrFullGround); }
bool isIgnoreLook() { return m_attribs.has(ThingAttrLook); }
bool isCloth() { return m_attribs.has(ThingAttrCloth); }
bool isMarketable() { return m_attribs.has(ThingAttrMarket); }
bool isUsable() { return m_attribs.has(ThingAttrUsable); }
bool isWrapable() { return m_attribs.has(ThingAttrWrapable); }
bool isUnwrapable() { return m_attribs.has(ThingAttrUnwrapable); }
bool isTopEffect() { return m_attribs.has(ThingAttrTopEffect); }
std::vector<int> getSprites() { return m_spritesIndex; }
// additional
float getOpacity() { return m_opacity; }
bool isNotPreWalkable() { return m_attribs.has(ThingAttrNotPreWalkable); }
void setPathable(bool var);
private:
const TexturePtr& getTexture(int animationPhase);
Size getBestTextureDimension(int w, int h, int count);
uint getSpriteIndex(int w, int h, int l, int x, int y, int z, int a);
uint getTextureIndex(int l, int x, int y, int z);
ThingCategory m_category;
uint16 m_id;
bool m_null;
stdext::dynamic_storage<uint8> m_attribs;
Size m_size;
Point m_displacement;
AnimatorPtr m_animator;
AnimatorPtr m_idleAnimator;
int m_animationPhases;
int m_exactSize;
int m_realSize;
int m_numPatternX, m_numPatternY, m_numPatternZ;
int m_layers;
int m_elevation;
float m_opacity;
std::string m_customImage;
std::vector<int> m_spritesIndex;
std::vector<TexturePtr> m_textures;
std::vector<std::vector<Rect>> m_texturesFramesRects;
std::vector<std::vector<Rect>> m_texturesFramesOriginRects;
std::vector<std::vector<Point>> m_texturesFramesOffsets;
bool m_loaded = false;
time_t m_lastUsage;
};
#endif

View File

@ -1,497 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "thingtypemanager.h"
#include "spritemanager.h"
#include "thing.h"
#include "thingtype.h"
#include "itemtype.h"
#include "creature.h"
#include "creatures.h"
#include "game.h"
#include <framework/core/resourcemanager.h>
#include <framework/core/filestream.h>
#include <framework/core/binarytree.h>
#include <framework/xml/tinyxml.h>
#include <framework/otml/otml.h>
#include <framework/util/stats.h>
ThingTypeManager g_things;
void ThingTypeManager::init()
{
m_nullThingType = ThingTypePtr(new ThingType);
m_nullItemType = ItemTypePtr(new ItemType);
m_datSignature = 0;
m_contentRevision = 0;
m_otbMinorVersion = 0;
m_otbMajorVersion = 0;
m_datLoaded = false;
m_xmlLoaded = false;
m_otbLoaded = false;
for (int i = 0; i < ThingLastCategory; ++i) {
m_thingTypes[i].resize(1, m_nullThingType);
m_checkIndex[i] = 0;
}
m_itemTypes.resize(1, m_nullItemType);
check();
}
void ThingTypeManager::terminate()
{
for(int i = 0; i < ThingLastCategory; ++i)
m_thingTypes[i].clear();
m_itemTypes.clear();
m_reverseItemTypes.clear();
m_marketCategories.clear();
m_nullThingType = nullptr;
m_nullItemType = nullptr;
if (m_checkEvent) {
m_checkEvent->cancel();
m_checkEvent = nullptr;
}
}
void ThingTypeManager::check()
{
// removes unused textures from memory after 60s, 500 checks / s
m_checkEvent = g_dispatcher.scheduleEvent(std::bind(&ThingTypeManager::check, &g_things), 1000);
for (size_t i = 0; i < ThingLastCategory; ++i) {
size_t limit = std::min<size_t>(m_checkIndex[i] + 100, m_thingTypes[i].size());
for (size_t j = m_checkIndex[i]; j < limit; ++j) {
if (m_thingTypes[i][j]->isLoaded() && m_thingTypes[i][j]->getLastUsage() + 60 < g_clock.seconds()) {
m_thingTypes[i][j]->unload();
}
}
m_checkIndex[i] = limit;
if (m_checkIndex[i] >= m_thingTypes[i].size()) {
m_checkIndex[i] = 0;
}
}
}
#ifdef WITH_ENCRYPTION
void ThingTypeManager::saveDat(std::string fileName)
{
if(!m_datLoaded)
stdext::throw_exception("failed to save, dat is not loaded");
try {
FileStreamPtr fin = g_resources.createFile(fileName);
if(!fin)
stdext::throw_exception(stdext::format("failed to open file '%s' for write", fileName));
fin->addU32(m_datSignature);
for(int category = 0; category < ThingLastCategory; ++category)
fin->addU16(m_thingTypes[category].size() - 1);
for(int category = 0; category < ThingLastCategory; ++category) {
uint16 firstId = 1;
if(category == ThingCategoryItem)
firstId = 100;
for(uint16 id = firstId; id < m_thingTypes[category].size(); ++id)
m_thingTypes[category][id]->serialize(fin);
}
fin->flush();
fin->close();
} catch(std::exception& e) {
g_logger.error(stdext::format("Failed to save '%s': %s", fileName, e.what()));
}
}
void ThingTypeManager::dumpTextures(std::string dir)
{
if (dir.empty()) {
g_logger.error("Empty dir for sprites dump");
return;
}
g_resources.makeDir(dir);
for (int category = 0; category < ThingLastCategory; ++category) {
g_resources.makeDir(dir + "/" + std::to_string((int)category));
uint16 firstId = 1;
if (category == ThingCategoryItem)
firstId = 100;
for (uint16 id = firstId; id < m_thingTypes[category].size(); ++id)
m_thingTypes[category][id]->exportImage(dir + "/" + std::to_string((int)category) + "/" + std::to_string(id) + ".png");
}
}
void ThingTypeManager::replaceTextures(std::string dir) {
if (dir.empty()) {
g_logger.error("Empty dir for sprites dump");
return;
}
std::map<uint32_t, ImagePtr> replacements;
for (int category = 0; category < ThingLastCategory; ++category) {
uint16 firstId = 1;
if (category == ThingCategoryItem)
firstId = 100;
for (uint16 id = firstId; id < m_thingTypes[category].size(); ++id) {
std::string fileName = dir + "/" + std::to_string((int)category) + "/" + std::to_string(id) + "_[][x2.000000].png";
m_thingTypes[category][id]->replaceSprites(replacements, fileName);
}
}
//g_sprites.saveReplacedSpr(dir + "/sprites.spr", replacements);
}
#endif
bool ThingTypeManager::loadDat(std::string file)
{
m_datLoaded = false;
m_datSignature = 0;
m_contentRevision = 0;
try {
file = g_resources.guessFilePath(file, "dat");
FileStreamPtr fin = g_resources.openFile(file);
m_datSignature = fin->getU32();
m_contentRevision = static_cast<uint16_t>(m_datSignature);
for(int category = 0; category < ThingLastCategory; ++category) {
int count = fin->getU16() + 1;
m_thingTypes[category].clear();
m_thingTypes[category].resize(count, m_nullThingType);
}
m_marketCategories.clear();
for(int category = 0; category < ThingLastCategory; ++category) {
uint16 firstId = 1;
if(category == ThingCategoryItem)
firstId = 100;
for(uint16 id = firstId; id < m_thingTypes[category].size(); ++id) {
ThingTypePtr type(new ThingType);
type->unserialize(id, (ThingCategory)category, fin);
m_thingTypes[category][id] = type;
if (type->isMarketable()) {
auto marketData = type->getMarketData();
m_marketCategories.insert(marketData.category);
}
}
}
m_datLoaded = true;
g_lua.callGlobalField("g_things", "onLoadDat", file);
return true;
} catch(stdext::exception& e) {
g_logger.error(stdext::format("Failed to read dat '%s': %s'", file, e.what()));
return false;
}
}
bool ThingTypeManager::loadOtml(std::string file)
{
try {
file = g_resources.guessFilePath(file, "otml");
OTMLDocumentPtr doc = OTMLDocument::parse(file);
for(const OTMLNodePtr& node : doc->children()) {
ThingCategory category;
if(node->tag() == "creatures")
category = ThingCategoryCreature;
else if(node->tag() == "items")
category = ThingCategoryItem;
else if(node->tag() == "effects")
category = ThingCategoryEffect;
else if(node->tag() == "missiles")
category = ThingCategoryMissile;
else {
throw OTMLException(node, "not a valid thing category");
}
for(const OTMLNodePtr& node2 : node->children()) {
uint16 id = stdext::safe_cast<uint16>(node2->tag());
ThingTypePtr type = getThingType(id, category);
if(!type)
throw OTMLException(node2, "thing not found");
type->unserializeOtml(node2);
}
}
return true;
} catch(std::exception& e) {
g_logger.error(stdext::format("Failed to read dat otml '%s': %s'", file, e.what()));
return false;
}
}
void ThingTypeManager::loadOtb(const std::string& file)
{
try {
FileStreamPtr fin = g_resources.openFile(file);
uint signature = fin->getU32();
if (signature != 0)
stdext::throw_exception("invalid otb file");
BinaryTreePtr root = fin->getBinaryTree();
root->skip(1); // otb first byte is always 0
signature = root->getU32();
if (signature != 0)
stdext::throw_exception("invalid otb file");
uint8 rootAttr = root->getU8();
if (rootAttr == 0x01) { // OTB_ROOT_ATTR_VERSION
uint16 size = root->getU16();
if (size != 4 + 4 + 4 + 128)
stdext::throw_exception("invalid otb root attr version size");
m_otbMajorVersion = root->getU32();
m_otbMinorVersion = root->getU32();
root->skip(4); // buildNumber
root->skip(128); // description
}
BinaryTreeVec children = root->getChildren();
m_reverseItemTypes.clear();
m_itemTypes.resize(children.size() + 1, m_nullItemType);
m_reverseItemTypes.resize(children.size() + 1, m_nullItemType);
for (const BinaryTreePtr& node : children) {
ItemTypePtr itemType(new ItemType);
itemType->unserialize(node);
addItemType(itemType);
uint16 clientId = itemType->getClientId();
if (unlikely(clientId >= m_reverseItemTypes.size()))
m_reverseItemTypes.resize(clientId + 1);
m_reverseItemTypes[clientId] = itemType;
}
m_otbLoaded = true;
g_lua.callGlobalField("g_things", "onLoadOtb", file);
} catch (std::exception& e) {
g_logger.error(stdext::format("Failed to load '%s' (OTB file): %s", file, e.what()));
}
}
void ThingTypeManager::loadXml(const std::string& file)
{
try {
if(!isOtbLoaded())
stdext::throw_exception("OTB must be loaded before XML");
TiXmlDocument doc;
doc.Parse(g_resources.readFileContents(file).c_str());
if(doc.Error())
stdext::throw_exception(stdext::format("failed to parse '%s': '%s'", file, doc.ErrorDesc()));
TiXmlElement* root = doc.FirstChildElement();
if(!root || root->ValueTStr() != "items")
stdext::throw_exception("invalid root tag name");
for(TiXmlElement *element = root->FirstChildElement(); element; element = element->NextSiblingElement()) {
if(unlikely(element->ValueTStr() != "item"))
continue;
uint16 id = element->readType<uint16>("id");
if(id != 0) {
std::vector<std::string> s_ids = stdext::split(element->Attribute("id"), ";");
for(const std::string& s : s_ids) {
std::vector<int32> ids = stdext::split<int32>(s, "-");
if(ids.size() > 1) {
int32 i = ids[0];
while(i <= ids[1])
parseItemType(i++, element);
} else
parseItemType(atoi(s.c_str()), element);
}
} else {
std::vector<int32> begin = stdext::split<int32>(element->Attribute("fromid"), ";");
std::vector<int32> end = stdext::split<int32>(element->Attribute("toid"), ";");
if(begin[0] && begin.size() == end.size()) {
size_t size = begin.size();
for(size_t i = 0; i < size; ++i)
while(begin[i] <= end[i])
parseItemType(begin[i]++, element);
}
}
}
doc.Clear();
m_xmlLoaded = true;
g_logger.debug("items.xml read successfully.");
} catch(std::exception& e) {
g_logger.error(stdext::format("Failed to load '%s' (XML file): %s", file, e.what()));
}
}
void ThingTypeManager::parseItemType(uint16 serverId, TiXmlElement* elem)
{
ItemTypePtr itemType = nullptr;
bool s;
int d;
if(g_game.getClientVersion() < 960) {
s = serverId > 20000 && serverId < 20100;
d = 20000;
} else {
s = serverId > 30000 && serverId < 30100;
d = 30000;
}
if(s) {
serverId -= d;
itemType = ItemTypePtr(new ItemType);
itemType->setServerId(serverId);
addItemType(itemType);
} else
itemType = getItemType(serverId);
itemType->setName(elem->Attribute("name"));
for(TiXmlElement* attrib = elem->FirstChildElement(); attrib; attrib = attrib->NextSiblingElement()) {
std::string key = attrib->Attribute("key");
if(key.empty())
continue;
stdext::tolower(key);
if(key == "description")
itemType->setDesc(attrib->Attribute("value"));
else if(key == "weapontype")
itemType->setCategory(ItemCategoryWeapon);
else if(key == "ammotype")
itemType->setCategory(ItemCategoryAmmunition);
else if(key == "armor")
itemType->setCategory(ItemCategoryArmor);
else if(key == "charges")
itemType->setCategory(ItemCategoryCharges);
else if(key == "type") {
std::string value = attrib->Attribute("value");
stdext::tolower(value);
if(value == "key")
itemType->setCategory(ItemCategoryKey);
else if(value == "magicfield")
itemType->setCategory(ItemCategoryMagicField);
else if(value == "teleport")
itemType->setCategory(ItemCategoryTeleport);
else if(value == "door")
itemType->setCategory(ItemCategoryDoor);
}
}
}
void ThingTypeManager::addItemType(const ItemTypePtr& itemType)
{
uint16 id = itemType->getServerId();
if(unlikely(id >= m_itemTypes.size()))
m_itemTypes.resize(id + 1, m_nullItemType);
m_itemTypes[id] = itemType;
}
const ItemTypePtr& ThingTypeManager::findItemTypeByClientId(uint16 id)
{
if(id == 0 || id >= m_reverseItemTypes.size())
return m_nullItemType;
if(m_reverseItemTypes[id])
return m_reverseItemTypes[id];
else
return m_nullItemType;
}
const ItemTypePtr& ThingTypeManager::findItemTypeByName(std::string name)
{
for(const ItemTypePtr& it : m_itemTypes)
if(it->getName() == name)
return it;
return m_nullItemType;
}
ItemTypeList ThingTypeManager::findItemTypesByName(std::string name)
{
ItemTypeList ret;
for(const ItemTypePtr& it : m_itemTypes)
if(it->getName() == name)
ret.push_back(it);
return ret;
}
ItemTypeList ThingTypeManager::findItemTypesByString(std::string name)
{
ItemTypeList ret;
for(const ItemTypePtr& it : m_itemTypes)
if(it->getName().find(name) != std::string::npos)
ret.push_back(it);
return ret;
}
const ThingTypePtr& ThingTypeManager::getThingType(uint16 id, ThingCategory category)
{
if(category >= ThingLastCategory || id >= m_thingTypes[category].size()) {
g_logger.error(stdext::format("invalid thing type client id %d in category %d", id, category));
return m_nullThingType;
}
return m_thingTypes[category][id];
}
const ItemTypePtr& ThingTypeManager::getItemType(uint16 id)
{
if(id >= m_itemTypes.size() || m_itemTypes[id] == m_nullItemType) {
g_logger.error(stdext::format("invalid thing type, server id: %d", id));
return m_nullItemType;
}
return m_itemTypes[id];
}
ThingTypeList ThingTypeManager::findThingTypeByAttr(ThingAttr attr, ThingCategory category)
{
ThingTypeList ret;
for(const ThingTypePtr& type : m_thingTypes[category])
if(type->hasAttr(attr))
ret.push_back(type);
return ret;
}
ItemTypeList ThingTypeManager::findItemTypeByCategory(ItemCategory category)
{
ItemTypeList ret;
for(const ItemTypePtr& type : m_itemTypes)
if(type->getCategory() == category)
ret.push_back(type);
return ret;
}
const ThingTypeList& ThingTypeManager::getThingTypes(ThingCategory category)
{
ThingTypeList ret;
if(category >= ThingLastCategory)
stdext::throw_exception(stdext::format("invalid thing type category %d", category));
return m_thingTypes[category];
}
/* vim: set ts=4 sw=4 et: */

View File

@ -1,119 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef THINGTYPEMANAGER_H
#define THINGTYPEMANAGER_H
#include <framework/global.h>
#include <framework/core/declarations.h>
#include <framework/core/eventdispatcher.h>
#include "thingtype.h"
#include "itemtype.h"
class ThingTypeManager
{
public:
void init();
void terminate();
void check();
bool loadDat(std::string file);
bool loadOtml(std::string file);
void loadOtb(const std::string& file);
void loadXml(const std::string& file);
void parseItemType(uint16 id, TiXmlElement *elem);
#ifdef WITH_ENCRYPTION
void saveDat(std::string fileName);
void dumpTextures(std::string dir);
void replaceTextures(std::string dir);
#endif
void addItemType(const ItemTypePtr& itemType);
const ItemTypePtr& findItemTypeByClientId(uint16 id);
const ItemTypePtr& findItemTypeByName(std::string name);
ItemTypeList findItemTypesByName(std::string name);
ItemTypeList findItemTypesByString(std::string str);
std::set<int> getMarketCategories()
{
return m_marketCategories;
}
const ThingTypePtr& getNullThingType() { return m_nullThingType; }
const ItemTypePtr& getNullItemType() { return m_nullItemType; }
const ThingTypePtr& getThingType(uint16 id, ThingCategory category);
const ItemTypePtr& getItemType(uint16 id);
ThingType* rawGetThingType(uint16 id, ThingCategory category) {
VALIDATE(id < m_thingTypes[category].size());
return m_thingTypes[category][id].get();
}
ItemType* rawGetItemType(uint16 id) {
VALIDATE(id < m_itemTypes.size());
return m_itemTypes[id].get();
}
ThingTypeList findThingTypeByAttr(ThingAttr attr, ThingCategory category);
ItemTypeList findItemTypeByCategory(ItemCategory category);
const ThingTypeList& getThingTypes(ThingCategory category);
const ItemTypeList& getItemTypes() { return m_itemTypes; }
uint32 getDatSignature() { return m_datSignature; }
uint32 getOtbMajorVersion() { return m_otbMajorVersion; }
uint32 getOtbMinorVersion() { return m_otbMinorVersion; }
uint16 getContentRevision() { return m_contentRevision; }
bool isDatLoaded() { return m_datLoaded; }
bool isXmlLoaded() { return m_xmlLoaded; }
bool isOtbLoaded() { return m_otbLoaded; }
bool isValidDatId(uint16 id, ThingCategory category) { return id >= 1 && id < m_thingTypes[category].size(); }
bool isValidOtbId(uint16 id) { return id >= 1 && id < m_itemTypes.size(); }
private:
ThingTypeList m_thingTypes[ThingLastCategory];
ItemTypeList m_reverseItemTypes;
ItemTypeList m_itemTypes;
std::set<int> m_marketCategories;
ThingTypePtr m_nullThingType;
ItemTypePtr m_nullItemType;
bool m_datLoaded;
bool m_xmlLoaded;
bool m_otbLoaded;
uint32 m_otbMinorVersion;
uint32 m_otbMajorVersion;
uint32 m_datSignature;
uint16 m_contentRevision;
ScheduledEventPtr m_checkEvent;
size_t m_checkIndex[ThingLastCategory];
};
extern ThingTypeManager g_things;
#endif

View File

@ -1,792 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "tile.h"
#include "item.h"
#include "thingtypemanager.h"
#include "map.h"
#include "game.h"
#include "localplayer.h"
#include "effect.h"
#include "protocolgame.h"
#include "lightview.h"
#include "spritemanager.h"
#include <framework/graphics/fontmanager.h>
#include <framework/util/extras.h>
#include <framework/core/adaptiverenderer.h>
Tile::Tile(const Position& position) :
m_position(position),
m_drawElevation(0),
m_minimapColor(0),
m_flags(0)
{
}
void Tile::drawBottom(const Point& dest, LightView* lightView)
{
m_topDraws = 0;
m_drawElevation = 0;
if (m_fill != Color::alpha) {
g_drawQueue->addFilledRect(Rect(dest, Otc::TILE_PIXELS, Otc::TILE_PIXELS), m_fill);
return;
}
// bottom things
for (const ThingPtr& thing : m_things) {
if (!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom())
break;
if (thing->isHidden())
continue;
thing->draw(dest - m_drawElevation, true, lightView);
m_drawElevation = std::min<uint8_t>(m_drawElevation + thing->getElevation(), Otc::MAX_ELEVATION);
}
// common items, reverse order
int redrawPreviousTopW = 0, redrawPreviousTopH = 0;
for (auto it = m_things.rbegin(); it != m_things.rend(); ++it) {
const ThingPtr& thing = *it;
if (thing->isOnTop() || thing->isOnBottom() || thing->isGroundBorder() || thing->isGround() || thing->isCreature())
break;
if (thing->isHidden())
continue;
thing->draw(dest - m_drawElevation, true, lightView);
m_drawElevation = std::min<uint8_t>(m_drawElevation + thing->getElevation(), Otc::MAX_ELEVATION);
if (thing->isLyingCorpse()) {
redrawPreviousTopW = std::max<int>(thing->getWidth() - 1, redrawPreviousTopW);
redrawPreviousTopH = std::max<int>(thing->getHeight() - 1, redrawPreviousTopH);
}
}
for (int x = -redrawPreviousTopW; x <= 0; ++x) {
for (int y = -redrawPreviousTopH; y <= 0; ++y) {
if (x == 0 && y == 0)
continue;
if(const TilePtr& tile = g_map.getTile(m_position.translated(x, y)))
tile->drawTop(dest + Point(x * Otc::TILE_PIXELS, y * Otc::TILE_PIXELS), lightView);
}
}
if (lightView && hasTranslucentLight()) {
lightView->addLight(dest + Point(16, 16), 215, 1);
}
}
void Tile::drawTop(const Point& dest, LightView* lightView)
{
if (m_fill != Color::alpha)
return;
if (m_topDraws++ < m_topCorrection)
return;
// walking creatures
for (const CreaturePtr& creature : m_walkingCreatures) {
if (creature->isHidden())
continue;
Point creatureDest(dest.x + ((creature->getPrewalkingPosition().x - m_position.x) * Otc::TILE_PIXELS - m_drawElevation),
dest.y + ((creature->getPrewalkingPosition().y - m_position.y) * Otc::TILE_PIXELS - m_drawElevation));
creature->draw(creatureDest, true, lightView);
}
// creatures
std::vector<CreaturePtr> creaturesToDraw;
int limit = g_adaptiveRenderer.creaturesLimit();
for (auto& thing : m_things) {
if (!thing->isCreature() || thing->isHidden())
continue;
if (limit-- <= 0)
break;
CreaturePtr creature = thing->static_self_cast<Creature>();
if (!creature || creature->isWalking())
continue;
creature->draw(dest - m_drawElevation, true, lightView);
}
// effects
limit = std::min<int>((int)m_effects.size() - 1, g_adaptiveRenderer.effetsLimit());
for (int i = limit; i >= 0; --i) {
if (m_effects[i]->isHidden())
continue;
m_effects[i]->draw(dest - m_drawElevation, m_position.x - g_map.getCentralPosition().x, m_position.y - g_map.getCentralPosition().y, true, lightView);
}
// top
for (const ThingPtr& thing : m_things) {
if (!thing->isOnTop() || thing->isHidden())
continue;
thing->draw(dest - m_drawElevation, true, lightView);
m_drawElevation = std::min<uint8_t>(m_drawElevation + thing->getElevation(), Otc::MAX_ELEVATION);
}
}
void Tile::calculateCorpseCorrection() {
m_topCorrection = 0;
int redrawPreviousTopW = 0, redrawPreviousTopH = 0;
for(auto it = m_things.rbegin(); it != m_things.rend(); ++it) {
const ThingPtr& thing = *it;
if(!thing->isLyingCorpse()) {
continue;
}
if (thing->isHidden())
continue;
redrawPreviousTopW = std::max<int>(thing->getWidth() - 1, redrawPreviousTopW);
redrawPreviousTopH = std::max<int>(thing->getHeight() - 1, redrawPreviousTopH);
}
for (int x = -redrawPreviousTopW; x <= 0; ++x) {
for (int y = -redrawPreviousTopH; y <= 0; ++y) {
if (x == 0 && y == 0)
continue;
if (const TilePtr& tile = g_map.getTile(m_position.translated(x, y)))
tile->m_topCorrection += 1;
}
}
}
void Tile::drawTexts(Point dest)
{
if (m_timerText && g_clock.millis() < m_timer) {
if (m_text && m_text->hasText())
dest.y -= 8;
m_timerText->setText(stdext::format("%.01f", (m_timer - g_clock.millis()) / 1000.));
m_timerText->drawText(dest, Rect(dest.x - 64, dest.y - 64, 128, 128));
dest.y += 16;
}
if (m_text && m_text->hasText()) {
m_text->drawText(dest, Rect(dest.x - 64, dest.y - 64, 128, 128));
}
}
void Tile::clean()
{
while(!m_things.empty())
removeThing(m_things.front());
}
void Tile::addWalkingCreature(const CreaturePtr& creature)
{
m_walkingCreatures.push_back(creature);
}
void Tile::removeWalkingCreature(const CreaturePtr& creature)
{
auto it = std::find(m_walkingCreatures.begin(), m_walkingCreatures.end(), creature);
if(it != m_walkingCreatures.end())
m_walkingCreatures.erase(it);
}
void Tile::addThing(const ThingPtr& thing, int stackPos)
{
if(!thing)
return;
if(thing->isEffect()) {
if(thing->isTopEffect())
m_effects.insert(m_effects.begin(), thing->static_self_cast<Effect>());
else
m_effects.push_back(thing->static_self_cast<Effect>());
} else {
// priority 854
// 0 - ground, --> -->
// 1 - ground borders --> -->
// 2 - bottom (walls), --> -->
// 3 - on top (doors) --> -->
// 4 - creatures, from top to bottom <-- -->
// 5 - items, from top to bottom <-- <--
if(stackPos < 0 || stackPos == 255) {
int priority = thing->getStackPriority();
// -1 or 255 => auto detect position
// -2 => append
bool append;
if(stackPos == -2)
append = true;
else {
append = (priority <= 3);
// newer protocols does not store creatures in reverse order
if(g_game.getClientVersion() >= 854 && priority == 4)
append = !append;
}
for(stackPos = 0; stackPos < (int)m_things.size(); ++stackPos) {
int otherPriority = m_things[stackPos]->getStackPriority();
if((append && otherPriority > priority) || (!append && otherPriority >= priority))
break;
}
} else if(stackPos > (int)m_things.size())
stackPos = m_things.size();
m_things.insert(m_things.begin() + stackPos, thing);
if(m_things.size() > MAX_THINGS)
removeThing(m_things[MAX_THINGS]);
/*
// check stack priorities
// this code exists to find stackpos bugs faster
int lastPriority = 0;
for(const ThingPtr& thing : m_things) {
int priority = thing->getStackPriority();
VALIDATE(lastPriority <= priority);
lastPriority = priority;
}
*/
}
thing->setPosition(m_position);
thing->onAppear();
if(thing->isTranslucent())
checkTranslucentLight();
if(g_game.isTileThingLuaCallbackEnabled())
callLuaField("onAddThing", thing);
}
bool Tile::removeThing(ThingPtr thing)
{
if(!thing)
return false;
bool removed = false;
if(thing->isEffect()) {
EffectPtr effect = thing->static_self_cast<Effect>();
auto it = std::find(m_effects.begin(), m_effects.end(), effect);
if(it != m_effects.end()) {
m_effects.erase(it);
removed = true;
}
} else {
auto it = std::find(m_things.begin(), m_things.end(), thing);
if(it != m_things.end()) {
m_things.erase(it);
removed = true;
}
}
if (thing->isCreature()) {
m_lastCreature = thing->getId();
}
thing->onDisappear();
if(thing->isTranslucent())
checkTranslucentLight();
if (g_game.isTileThingLuaCallbackEnabled() && removed) {
callLuaField("onRemoveThing", thing);
}
return removed;
}
ThingPtr Tile::getThing(int stackPos)
{
if(stackPos >= 0 && stackPos < (int)m_things.size())
return m_things[stackPos];
return nullptr;
}
EffectPtr Tile::getEffect(uint16 id)
{
for(const EffectPtr& effect : m_effects)
if(effect->getId() == id)
return effect;
return nullptr;
}
bool Tile::hasThing(const ThingPtr& thing)
{
return std::find(m_things.begin(), m_things.end(), thing) != m_things.end();
}
int Tile::getThingStackPos(const ThingPtr& thing)
{
for(uint stackpos = 0; stackpos < m_things.size(); ++stackpos)
if(thing == m_things[stackpos])
return stackpos;
return -1;
}
ThingPtr Tile::getTopThing()
{
if(isEmpty())
return nullptr;
for(const ThingPtr& thing : m_things)
if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop() && !thing->isCreature())
return thing;
return m_things[m_things.size() - 1];
}
std::vector<ItemPtr> Tile::getItems()
{
std::vector<ItemPtr> items;
for(const ThingPtr& thing : m_things) {
if(!thing->isItem())
continue;
ItemPtr item = thing->static_self_cast<Item>();
items.push_back(item);
}
return items;
}
std::vector<CreaturePtr> Tile::getCreatures()
{
std::vector<CreaturePtr> creatures;
for(const ThingPtr& thing : m_things) {
if(thing->isCreature())
creatures.push_back(thing->static_self_cast<Creature>());
}
return creatures;
}
ItemPtr Tile::getGround()
{
ThingPtr firstObject = getThing(0);
if(!firstObject)
return nullptr;
if(firstObject->isGround() && firstObject->isItem())
return firstObject->static_self_cast<Item>();
return nullptr;
}
int Tile::getGroundSpeed()
{
if (m_speed)
return m_speed;
int groundSpeed = 100;
if(ItemPtr ground = getGround())
groundSpeed = ground->getGroundSpeed();
return groundSpeed;
}
uint8 Tile::getMinimapColorByte()
{
uint8 color = 255; // alpha
if(m_minimapColor != 0)
return m_minimapColor;
for(const ThingPtr& thing : m_things) {
if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop())
break;
uint8 c = thing->getMinimapColor();
if(c != 0)
color = c;
}
return color;
}
ThingPtr Tile::getTopLookThing()
{
if(isEmpty())
return nullptr;
for(uint i = 0; i < m_things.size(); ++i) {
ThingPtr thing = m_things[i];
if(!thing->isIgnoreLook() && (!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop()))
return thing;
}
return m_things[0];
}
ThingPtr Tile::getTopLookThingEx(Point offset)
{
auto creature = getTopCreatureEx(offset);
if (creature)
return creature;
if (isEmpty())
return nullptr;
for (uint i = 0; i < m_things.size(); ++i) {
ThingPtr thing = m_things[i];
if (!thing->isIgnoreLook() && (!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop() && !thing->isCreature()))
return thing;
}
return m_things[0];
}
ThingPtr Tile::getTopUseThing()
{
if(isEmpty())
return nullptr;
for(uint i = 0; i < m_things.size(); ++i) {
ThingPtr thing = m_things[i];
if (thing->isForceUse() || (!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop() && !thing->isCreature() && !thing->isSplash()))
return thing;
}
for (uint i = m_things.size() - 1; i > 0; --i) {
ThingPtr thing = m_things[i];
if (!thing->isSplash() && !thing->isCreature())
return thing;
}
return m_things[0];
}
CreaturePtr Tile::getTopCreature()
{
CreaturePtr creature;
for(uint i = 0; i < m_things.size(); ++i) {
ThingPtr thing = m_things[i];
if(thing->isLocalPlayer()) // return local player if there is no other creature
creature = thing->static_self_cast<Creature>();
else if(thing->isCreature() && !thing->isLocalPlayer())
return thing->static_self_cast<Creature>();
}
if(!creature && !m_walkingCreatures.empty())
creature = m_walkingCreatures.back();
// check for walking creatures in tiles around
if(!creature) {
for(int xi=-1;xi<=1;++xi) {
for(int yi=-1;yi<=1;++yi) {
Position pos = m_position.translated(xi, yi);
if(pos == m_position)
continue;
const TilePtr& tile = g_map.getTile(pos);
if(tile) {
for(const CreaturePtr& c : tile->getCreatures()) {
if(c->isWalking() && c->getLastStepFromPosition() == m_position && c->getStepProgress() < 0.75f) {
creature = c;
}
}
}
}
}
}
return creature;
}
CreaturePtr Tile::getTopCreatureEx(Point offset)
{
// hidden
return nullptr;
}
ThingPtr Tile::getTopMoveThing()
{
if(isEmpty())
return nullptr;
for(uint i = 0; i < m_things.size(); ++i) {
ThingPtr thing = m_things[i];
if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop() && !thing->isCreature()) {
if(i > 0 && thing->isNotMoveable())
return m_things[i-1];
return thing;
}
}
for(const ThingPtr& thing : m_things) {
if(thing->isCreature())
return thing;
}
return m_things[0];
}
ThingPtr Tile::getTopMultiUseThing()
{
if (isEmpty())
return nullptr;
if (CreaturePtr topCreature = getTopCreature())
return topCreature;
for (uint i = 0; i < m_things.size(); ++i) {
ThingPtr thing = m_things[i];
if (thing->isForceUse())
return thing;
}
for (uint i = 0; i < m_things.size(); ++i) {
ThingPtr thing = m_things[i];
if (!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop()) {
if (i > 0 && thing->isSplash())
return m_things[i - 1];
return thing;
}
}
return m_things.back();
}
ThingPtr Tile::getTopMultiUseThingEx(Point offset)
{
if (CreaturePtr topCreature = getTopCreatureEx(offset))
return topCreature;
if (isEmpty())
return nullptr;
for (uint i = 0; i < m_things.size(); ++i) {
ThingPtr thing = m_things[i];
if (thing->isForceUse() && !thing->isCreature())
return thing;
}
for (uint i = 0; i < m_things.size(); ++i) {
ThingPtr thing = m_things[i];
if (!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop() && !thing->isCreature()) {
if (i > 0 && thing->isSplash())
return m_things[i - 1];
return thing;
}
}
for (uint i = m_things.size() - 1; i > 0; --i) {
ThingPtr thing = m_things[i];
if (!thing->isCreature())
return thing;
}
return m_things[0];
}
bool Tile::isWalkable(bool ignoreCreatures)
{
if(!getGround())
return false;
for(const ThingPtr& thing : m_things) {
if(thing->isNotWalkable())
return false;
if(!ignoreCreatures) {
if(thing->isCreature()) {
CreaturePtr creature = thing->static_self_cast<Creature>();
if(!creature->isPassable() && creature->canBeSeen() && !creature->isLocalPlayer())
return false;
}
}
}
return true;
}
bool Tile::isPathable()
{
for(const ThingPtr& thing : m_things)
if(thing->isNotPathable())
return false;
return true;
}
bool Tile::isFullGround()
{
ItemPtr ground = getGround();
if(ground && ground->isFullGround())
return true;
return false;
}
bool Tile::isFullyOpaque()
{
ThingPtr firstObject = getThing(0);
return firstObject && firstObject->isFullGround();
}
bool Tile::isSingleDimension()
{
if(!m_walkingCreatures.empty())
return false;
for(const ThingPtr& thing : m_things)
if(thing->getHeight() != 1 || thing->getWidth() != 1)
return false;
return true;
}
bool Tile::isLookPossible()
{
for(const ThingPtr& thing : m_things)
if(thing->blockProjectile())
return false;
return true;
}
bool Tile::isClickable()
{
bool hasGround = false;
bool hasOnBottom = false;
bool hasIgnoreLook = false;
for(const ThingPtr& thing : m_things) {
if(thing->isGround())
hasGround = true;
if(thing->isOnBottom())
hasOnBottom = true;
if((hasGround || hasOnBottom) && !hasIgnoreLook)
return true;
}
return false;
}
bool Tile::isEmpty()
{
return m_things.size() == 0;
}
bool Tile::isDrawable()
{
return !m_things.empty() || !m_walkingCreatures.empty() || !m_effects.empty();
}
bool Tile::mustHookEast()
{
for(const ThingPtr& thing : m_things)
if(thing->isHookEast())
return true;
return false;
}
bool Tile::mustHookSouth()
{
for(const ThingPtr& thing : m_things)
if(thing->isHookSouth())
return true;
return false;
}
bool Tile::hasCreature()
{
for(const ThingPtr& thing : m_things)
if(thing->isCreature())
return true;
return false;
}
bool Tile::hasBlockingCreature()
{
for (const ThingPtr& thing : m_things)
if (thing->isCreature() && !thing->static_self_cast<Creature>()->isPassable() && !thing->isLocalPlayer())
return true;
return false;
}
bool Tile::limitsFloorsView(bool isFreeView)
{
// ground and walls limits the view
ThingPtr firstThing = getThing(0);
if(isFreeView) {
if(firstThing && !firstThing->isDontHide() && (firstThing->isGround() || firstThing->isOnBottom()))
return true;
} else if(firstThing && !firstThing->isDontHide() && (firstThing->isGround() || (firstThing->isOnBottom() && firstThing->blockProjectile())))
return true;
return false;
}
bool Tile::canErase()
{
return m_walkingCreatures.empty() && m_effects.empty() && m_things.empty() && m_flags == 0 && m_minimapColor == 0;
}
int Tile::getElevation()
{
int elevation = 0;
for(const ThingPtr& thing : m_things)
if(thing->getElevation() > 0)
elevation++;
return elevation;
}
bool Tile::hasElevation(int elevation)
{
return getElevation() >= elevation;
}
void Tile::checkTranslucentLight()
{
if(m_position.z != Otc::SEA_FLOOR)
return;
Position downPos = m_position;
if(!downPos.down())
return;
TilePtr tile = g_map.getOrCreateTile(downPos);
if(!tile)
return;
bool translucent = false;
for(const ThingPtr& thing : m_things) {
if(thing->isTranslucent() || thing->hasLensHelp()) {
translucent = true;
break;
}
}
if(translucent)
tile->m_flags |= TILESTATE_TRANSLUECENT_LIGHT;
else
tile->m_flags &= ~TILESTATE_TRANSLUECENT_LIGHT;
}
void Tile::setText(const std::string& text, Color color)
{
if (!m_text) {
m_text = StaticTextPtr(new StaticText());
}
m_text->setText(text);
m_text->setColor(color);
}
std::string Tile::getText()
{
return m_text ? m_text->getCachedText().getText() : "";
}
void Tile::setTimer(int time, Color color)
{
if (time > 60000) {
g_logger.warning("Max tile timer value is 300000 (300s)!");
return;
}
m_timer = time + g_clock.millis();
if (!m_timerText) {
m_timerText = StaticTextPtr(new StaticText());
}
m_timerText->setColor(color);
}
int Tile::getTimer()
{
return m_timerText ? std::max<int>(0, m_timer - g_clock.millis()) : 0;
}
void Tile::setFill(Color color)
{
m_fill = color;
}

View File

@ -1,180 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef TILE_H
#define TILE_H
#include "declarations.h"
#include "mapview.h"
#include "effect.h"
#include "creature.h"
#include "item.h"
#include <framework/luaengine/luaobject.h>
#include <framework/stdext/time.h>
enum tileflags_t
{
TILESTATE_NONE = 0,
TILESTATE_PROTECTIONZONE = 1 << 0,
TILESTATE_TRASHED = 1 << 1,
TILESTATE_OPTIONALZONE = 1 << 2,
TILESTATE_NOLOGOUT = 1 << 3,
TILESTATE_HARDCOREZONE = 1 << 4,
TILESTATE_REFRESH = 1 << 5,
// internal usage
TILESTATE_HOUSE = 1 << 6,
TILESTATE_TELEPORT = 1 << 17,
TILESTATE_MAGICFIELD = 1 << 18,
TILESTATE_MAILBOX = 1 << 19,
TILESTATE_TRASHHOLDER = 1 << 20,
TILESTATE_BED = 1 << 21,
TILESTATE_DEPOT = 1 << 22,
TILESTATE_TRANSLUECENT_LIGHT = 1 << 23,
TILESTATE_LAST = 1 << 24
};
class Tile : public LuaObject
{
public:
enum {
MAX_THINGS = 10
};
Tile(const Position& position);
void calculateCorpseCorrection();
void drawBottom(const Point& dest, LightView* lightView = nullptr);
void drawTop(const Point& dest, LightView* lightView = nullptr);
void drawTexts(Point dest);
public:
void clean();
void addWalkingCreature(const CreaturePtr& creature);
void removeWalkingCreature(const CreaturePtr& creature);
void addThing(const ThingPtr& thing, int stackPos);
bool removeThing(ThingPtr thing);
ThingPtr getThing(int stackPos);
EffectPtr getEffect(uint16 id);
bool hasThing(const ThingPtr& thing);
int getThingStackPos(const ThingPtr& thing);
ThingPtr getTopThing();
ThingPtr getTopLookThing();
ThingPtr getTopLookThingEx(Point offset);
ThingPtr getTopUseThing();
CreaturePtr getTopCreature();
CreaturePtr getTopCreatureEx(Point offset);
ThingPtr getTopMoveThing();
ThingPtr getTopMultiUseThing();
ThingPtr getTopMultiUseThingEx(Point offset);
const Position& getPosition() { return m_position; }
int getDrawElevation() { return m_drawElevation; }
std::vector<ItemPtr> getItems();
std::vector<CreaturePtr> getCreatures();
std::vector<CreaturePtr> getWalkingCreatures() { return m_walkingCreatures; }
std::vector<ThingPtr> getThings() { return m_things; }
std::vector<EffectPtr> getEffects() { return m_effects; }
ItemPtr getGround();
int getGroundSpeed();
bool isBlocking() { return m_blocking != 0; }
uint8 getMinimapColorByte();
int getThingCount() { return m_things.size() + m_effects.size(); }
bool isPathable();
bool isWalkable(bool ignoreCreatures = false);
bool isFullGround();
bool isFullyOpaque();
bool isSingleDimension();
bool isLookPossible();
bool isClickable();
bool isEmpty();
bool isDrawable();
bool hasTranslucentLight() { return m_flags & TILESTATE_TRANSLUECENT_LIGHT; }
bool mustHookSouth();
bool mustHookEast();
bool hasCreature();
bool hasBlockingCreature();
bool limitsFloorsView(bool isFreeView = false);
bool canErase();
int getElevation();
bool hasElevation(int elevation = 1);
void overwriteMinimapColor(uint8 color) { m_minimapColor = color; }
void remFlag(uint32 flag) { m_flags &= ~flag; }
void setFlag(uint32 flag) { m_flags |= flag; }
void setFlags(uint32 flags) { m_flags = flags; }
bool hasFlag(uint32 flag) { return (m_flags & flag) == flag; }
uint32 getFlags() { return m_flags; }
void setHouseId(uint32 hid) { m_houseId = hid; }
uint32 getHouseId() { return m_houseId; }
bool isHouseTile() { return m_houseId != 0 && (m_flags & TILESTATE_HOUSE) == TILESTATE_HOUSE; }
void select() { m_selected = true; }
void unselect() { m_selected = false; }
bool isSelected() { return m_selected; }
TilePtr asTile() { return static_self_cast<Tile>(); }
void setSpeed(uint16_t speed, uint8_t blocking) {
m_speed = speed;
m_blocking = blocking;
}
void setText(const std::string& text, Color color);
std::string getText();
void setTimer(int time, Color color);
int getTimer();
void setFill(Color color);
void resetFill() { m_fill = Color::alpha; }
private:
void checkTranslucentLight();
std::vector<CreaturePtr> m_walkingCreatures;
std::vector<EffectPtr> m_effects; // leave this outside m_things because it has no stackpos.
std::vector<ThingPtr> m_things;
Position m_position;
uint8 m_drawElevation;
uint8 m_minimapColor;
uint32 m_flags, m_houseId;
uint16 m_speed = 0;
uint8 m_blocking = 0;
uint32_t m_lastCreature = 0;
int m_topCorrection = 0;
int m_topDraws = 0;
stdext::boolean<false> m_selected;
ticks_t m_timer = 0;
StaticTextPtr m_timerText;
StaticTextPtr m_text;
Color m_fill = Color::alpha;
};
#endif

View File

@ -1,80 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "towns.h"
TownManager g_towns;
Town::Town(uint32 tid, const std::string& name, const Position& pos)
: m_id(tid), m_name(name)
{
if(pos.isValid())
m_pos = pos;
}
TownManager::TownManager()
{
m_nullTown = TownPtr(new Town);
}
void TownManager::addTown(const TownPtr &town)
{
if(findTown(town->getId()) == m_towns.end())
m_towns.push_back(town);
}
void TownManager::removeTown(uint32 townId)
{
auto it = findTown(townId);
if(it != m_towns.end())
m_towns.erase(it);
}
const TownPtr& TownManager::getTown(uint32 townId)
{
auto it = std::find_if(m_towns.begin(), m_towns.end(),
[=] (const TownPtr& town) -> bool { return town->getId() == townId; });
if(it != m_towns.end())
return *it;
return m_nullTown;
}
const TownPtr& TownManager::getTownByName(std::string name)
{
auto it = std::find_if(m_towns.begin(), m_towns.end(),
[=] (const TownPtr& town) -> bool { return town->getName() == name; } );
if(it != m_towns.end())
return *it;
return m_nullTown;
}
TownList::iterator TownManager::findTown(uint32 townId)
{
return std::find_if(m_towns.begin(), m_towns.end(),
[=] (const TownPtr& town) -> bool { return town->getId() == townId; });
}
void TownManager::sort()
{
m_towns.sort([] (const TownPtr& lhs, const TownPtr& rhs) { return lhs->getName() < rhs->getName(); });
}

View File

@ -1,73 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef TOWNS_H
#define TOWNS_H
#include "declarations.h"
#include <framework/luaengine/luaobject.h>
class Town : public LuaObject
{
public:
Town() { }
Town(uint32 tid, const std::string& name, const Position& pos=Position());
void setId(uint32 tid) { m_id = tid; }
void setName(const std::string& name) { m_name = name; }
void setPos(const Position& pos) { m_pos = pos; }
uint32 getId() { return m_id; }
std::string getName() { return m_name; }
Position getPos() { return m_pos; }
private:
uint32 m_id;
std::string m_name;
Position m_pos; // temple pos
};
class TownManager
{
public:
TownManager();
void addTown(const TownPtr& town);
void removeTown(uint32 townId);
const TownPtr& getTown(uint32 townId);
const TownPtr& getTownByName(std::string name);
void sort();
TownList getTowns() { return m_towns; }
void clear() { m_towns.clear(); m_nullTown = nullptr; }
private:
TownList m_towns;
TownPtr m_nullTown;
protected:
TownList::iterator findTown(uint32 townId);
};
extern TownManager g_towns;
#endif

View File

@ -1,123 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "uicreature.h"
#include <framework/otml/otml.h>
#include <framework/graphics/drawqueue.h>
void UICreature::drawSelf(Fw::DrawPane drawPane)
{
if(drawPane != Fw::ForegroundPane)
return;
UIWidget::drawSelf(drawPane);
if(m_creature) {
if (m_autoRotating) {
auto ticks = (g_clock.millis() % 4000) / 4;
Otc::Direction new_dir;
if (ticks < 250)
{
new_dir = Otc::South;
}
else if (ticks < 500)
{
new_dir = Otc::East;
}
else if (ticks < 750)
{
new_dir = Otc::North;
}
else
{
new_dir = Otc::West;
}
if (new_dir != m_direction) {
m_direction = new_dir;
m_redraw = true;
}
}
if (m_creature->getOutfitNumber() != m_outfitNumber) {
m_outfitNumber = m_creature->getOutfitNumber();
m_redraw = true;
}
m_creature->drawOutfit(getPaddingRect(), m_direction, m_imageColor);
}
}
void UICreature::setOutfit(const Outfit& outfit)
{
if(!m_creature)
m_creature = CreaturePtr(new Creature);
m_direction = Otc::South;
m_creature->setOutfit(outfit);
m_redraw = true;
}
void UICreature::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
{
UIWidget::onStyleApply(styleName, styleNode);
for(const OTMLNodePtr& node : styleNode->children()) {
if(node->tag() == "fixed-creature-size")
setFixedCreatureSize(node->value<bool>());
else if(node->tag() == "outfit-id") {
Outfit outfit = (m_creature ? m_creature->getOutfit() : Outfit());
outfit.setId(node->value<int>());
setOutfit(outfit);
}
else if(node->tag() == "outfit-head") {
Outfit outfit = (m_creature ? m_creature->getOutfit() : Outfit());
outfit.setHead(node->value<int>());
setOutfit(outfit);
}
else if(node->tag() == "outfit-body") {
Outfit outfit = (m_creature ? m_creature->getOutfit() : Outfit());
outfit.setBody(node->value<int>());
setOutfit(outfit);
}
else if(node->tag() == "outfit-legs") {
Outfit outfit = (m_creature ? m_creature->getOutfit() : Outfit());
outfit.setLegs(node->value<int>());
setOutfit(outfit);
}
else if(node->tag() == "outfit-feet") {
Outfit outfit = (m_creature ? m_creature->getOutfit() : Outfit());
outfit.setFeet(node->value<int>());
setOutfit(outfit);
}
else if (node->tag() == "scale") {
setScale(node->value<float>());
}
else if (node->tag() == "optimized") {
setOptimized(node->value<bool>());
}
}
}
void UICreature::onGeometryChange(const Rect& oldRect, const Rect& newRect)
{
UIWidget::onGeometryChange(oldRect, newRect);
m_redraw = true;
}

View File

@ -1,63 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef UICREATURE_H
#define UICREATURE_H
#include "declarations.h"
#include <framework/ui/uiwidget.h>
#include "creature.h"
class UICreature : public UIWidget
{
public:
void drawSelf(Fw::DrawPane drawPane);
void setCreature(const CreaturePtr& creature) { m_creature = creature; m_redraw = true; }
void setFixedCreatureSize(bool fixed) { m_scale = fixed ? 1.0 : 0; m_redraw = true; }
void setOutfit(const Outfit& outfit);
CreaturePtr getCreature() { return m_creature; }
bool isFixedCreatureSize() { return m_scale > 0; }
void setAutoRotating(bool value) { m_autoRotating = value; }
void setDirection(Otc::Direction direction) { m_direction = direction; m_redraw = true; }
void setScale(float scale) { m_scale = scale; m_redraw = true; }
float getScale() { return m_scale; }
void setOptimized(bool value) { m_optimized = value; m_redraw = true; }
protected:
void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
void onGeometryChange(const Rect& oldRect, const Rect& newRect) override;
CreaturePtr m_creature;
stdext::boolean<false> m_autoRotating;
stdext::boolean<false> m_redraw;
int m_outfitNumber = 0;
Otc::Direction m_direction = Otc::South;
float m_scale = 1.0;
bool m_optimized = false;
};
#endif

View File

@ -1,120 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "uiitem.h"
#include <framework/otml/otml.h>
#include <framework/graphics/graphics.h>
#include <framework/graphics/fontmanager.h>
UIItem::UIItem()
{
m_draggable = true;
}
void UIItem::drawSelf(Fw::DrawPane drawPane)
{
if(drawPane != Fw::ForegroundPane)
return;
// draw style components in order
if(m_backgroundColor.aF() > Fw::MIN_ALPHA) {
Rect backgroundDestRect = m_rect;
backgroundDestRect.expand(-m_borderWidth.top, -m_borderWidth.right, -m_borderWidth.bottom, -m_borderWidth.left);
drawBackground(m_rect);
}
drawImage(m_rect);
if(m_itemVisible && m_item) {
Rect drawRect = getPaddingRect();
int exactSize = std::max<int>(32, m_item->getExactSize());
if(exactSize == 0)
return;
m_item->setColor(m_color);
m_item->draw(drawRect);
if(m_font && m_showCount && (m_item->isStackable() || m_item->isChargeable()) && m_item->getCountOrSubType() > 1) {
g_drawQueue->addText(m_font, std::to_string(m_item->getCountOrSubType()), Rect(m_rect.topLeft(), m_rect.bottomRight() - Point(3, 0)), Fw::AlignBottomRight, Color(231, 231, 231));
}
if (m_showId) {
g_drawQueue->addText(m_font, std::to_string(m_item->getServerId()), m_rect, Fw::AlignBottomRight, Color(231, 231, 231));
}
}
drawBorder(m_rect);
drawIcon(m_rect);
drawText(m_rect);
}
void UIItem::setItemId(int id)
{
if (!m_item && id != 0)
m_item = Item::create(id);
else {
// remove item
if (id == 0)
m_item = nullptr;
else
m_item->setId(id);
}
callLuaField("onItemChange");
}
void UIItem::setItemCount(int count)
{
if (m_item)
m_item->setCount(count);
callLuaField("onItemChange");
}
void UIItem::setItemSubType(int subType)
{
if (m_item)
m_item->setSubType(subType);
callLuaField("onItemChange");
}
void UIItem::setItem(const ItemPtr& item)
{
m_item = item;
callLuaField("onItemChange");
}
void UIItem::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
{
UIWidget::onStyleApply(styleName, styleNode);
for(const OTMLNodePtr& node : styleNode->children()) {
if(node->tag() == "item-id")
setItemId(node->value<int>());
else if(node->tag() == "item-count")
setItemCount(node->value<int>());
else if(node->tag() == "item-visible")
setItemVisible(node->value<bool>());
else if(node->tag() == "virtual")
setVirtual(node->value<bool>());
else if(node->tag() == "show-id")
m_showId = node->value<bool>();
}
}

View File

@ -1,63 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef UIITEM_H
#define UIITEM_H
#include "declarations.h"
#include <framework/ui/uiwidget.h>
#include "item.h"
class UIItem : public UIWidget
{
public:
UIItem();
void drawSelf(Fw::DrawPane drawPane);
void setItemId(int id);
void setItemCount(int count);
void setItemSubType(int subType);
void setItemVisible(bool visible) { m_itemVisible = visible; }
void setItem(const ItemPtr& item);
void setVirtual(bool virt) { m_virtual = virt; }
void clearItem() { setItemId(0); }
void setShowCount(bool value) { m_showCount = value; }
int getItemId() { return m_item ? m_item->getId() : 0; }
int getItemCount() { return m_item ? m_item->getCount() : 0; }
int getItemSubType() { return m_item ? m_item->getSubType() : 0; }
int getItemCountOrSubType() { return m_item ? m_item->getCountOrSubType() : 0; }
ItemPtr getItem() { return m_item; }
bool isVirtual() { return m_virtual; }
bool isItemVisible() { return m_itemVisible; }
protected:
void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
ItemPtr m_item;
stdext::boolean<false> m_virtual;
stdext::boolean<true> m_itemVisible;
stdext::boolean<false> m_showId;
stdext::boolean<true> m_showCount;
};
#endif

View File

@ -1,231 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "uimap.h"
#include "game.h"
#include "map.h"
#include "mapview.h"
#include <framework/otml/otml.h>
#include <framework/graphics/graphics.h>
#include <framework/util/extras.h>
#include "localplayer.h"
UIMap::UIMap()
{
m_draggable = true;
m_mapView = MapViewPtr(new MapView);
m_zoom = m_mapView->getVisibleDimension().height();
m_keepAspectRatio = true;
m_limitVisibleRange = false;
m_aspectRatio = m_mapView->getVisibleDimension().ratio();
m_maxZoomIn = 3;
m_maxZoomOut = 513;
m_mapRect.resize(1,1);
g_map.addMapView(m_mapView);
}
UIMap::~UIMap()
{
g_map.removeMapView(m_mapView);
}
bool UIMap::onMouseMove(const Point& mousePos, const Point& mouseMoved)
{
m_mousePosition = mousePos;
return UIWidget::onMouseMove(mousePos, mouseMoved);
}
void UIMap::drawSelf(Fw::DrawPane drawPane)
{
UIWidget::drawSelf(drawPane);
if(drawPane == Fw::ForegroundPane) {
g_drawQueue->addBoundingRect(m_mapRect.expanded(1), 1, Color::black);
g_drawQueue->markMapPosition();
} else if(drawPane == Fw::MapBackgroundPane) {
m_mapView->drawBackground(m_mapRect, getTile(m_mousePosition));
} else if (drawPane == Fw::MapForegroundPane) {
m_mapView->drawForeground(m_mapRect);
}
}
void UIMap::movePixels(int x, int y)
{
m_mapView->move(x, y);
}
bool UIMap::setZoom(int zoom)
{
m_zoom = stdext::clamp<int>(zoom, m_maxZoomIn, m_maxZoomOut);
updateVisibleDimension();
return false;
}
bool UIMap::zoomIn()
{
int delta = 2;
if(m_zoom - delta < m_maxZoomIn)
delta--;
if(m_zoom - delta < m_maxZoomIn)
return false;
m_zoom -= delta;
updateVisibleDimension();
return true;
}
bool UIMap::zoomOut()
{
int delta = 2;
if(m_zoom + delta > m_maxZoomOut)
delta--;
if(m_zoom + delta > m_maxZoomOut)
return false;
m_zoom += 2;
updateVisibleDimension();
return true;
}
void UIMap::setVisibleDimension(const Size& visibleDimension)
{
m_mapView->setVisibleDimension(visibleDimension);
m_aspectRatio = visibleDimension.ratio();
if(m_keepAspectRatio)
updateMapSize();
}
void UIMap::setKeepAspectRatio(bool enable)
{
m_keepAspectRatio = enable;
if(enable)
m_aspectRatio = getVisibleDimension().ratio();
updateMapSize();
}
Position UIMap::getPosition(const Point& mousePos)
{
if (!m_mapRect.contains(mousePos))
return Position();
Point relativeMousePos = mousePos - m_mapRect.topLeft();
return m_mapView->getPosition(relativeMousePos, m_mapRect.size());
}
Point UIMap::getPositionOffset(const Point& mousePos)
{
if (!m_mapRect.contains(mousePos))
return Point(0, 0);
Point relativeMousePos = mousePos - m_mapRect.topLeft();
return m_mapView->getPositionOffset(relativeMousePos, m_mapRect.size());
}
TilePtr UIMap::getTile(const Point& mousePos)
{
Position tilePos = getPosition(mousePos);
if(!tilePos.isValid())
return nullptr;
// we must check every floor, from top to bottom to check for a clickable tile
TilePtr tile;
tilePos.coveredUp(tilePos.z - m_mapView->getCachedFirstVisibleFloor());
for(int i = m_mapView->getCachedFirstVisibleFloor(); i <= m_mapView->getCachedLastVisibleFloor(); i++) {
tile = g_map.getTile(tilePos);
if(tile && tile->isClickable())
break;
tilePos.coveredDown();
}
if(!tile || !tile->isClickable())
return nullptr;
return tile;
}
void UIMap::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
{
UIWidget::onStyleApply(styleName, styleNode);
for(const OTMLNodePtr& node : styleNode->children()) {
if(node->tag() == "multifloor")
setMultifloor(node->value<bool>());
else if(node->tag() == "draw-texts")
setDrawTexts(node->value<bool>());
else if(node->tag() == "draw-lights")
setDrawLights(node->value<bool>());
else if(node->tag() == "animated")
setAnimated(node->value<bool>());
}
}
void UIMap::onGeometryChange(const Rect& oldRect, const Rect& newRect)
{
UIWidget::onGeometryChange(oldRect, newRect);
updateMapSize();
}
void UIMap::updateVisibleDimension()
{
int dimensionHeight = m_zoom;
float ratio = m_aspectRatio;
if(!m_limitVisibleRange && !m_mapRect.isEmpty() && !m_keepAspectRatio)
ratio = m_mapRect.size().ratio();
if(dimensionHeight % 2 == 0)
dimensionHeight += 1;
int dimensionWidth = m_zoom * ratio;
if(dimensionWidth % 2 == 0)
dimensionWidth += 1;
m_mapView->setVisibleDimension(Size(dimensionWidth, dimensionHeight));
if(m_keepAspectRatio)
updateMapSize();
callLuaField("onVisibleDimensionChange", dimensionWidth, dimensionHeight);
}
void UIMap::updateMapSize()
{
Rect clippingRect = getPaddingRect();
Size mapSize;
if(m_keepAspectRatio) {
Rect mapRect = clippingRect.expanded(-1);
mapSize = Size(m_aspectRatio*m_zoom, m_zoom);
mapSize.scale(mapRect.size(), Fw::KeepAspectRatio);
} else {
mapSize = clippingRect.expanded(-1).size();
}
m_mapRect.resize(mapSize);
m_mapRect.moveCenter(clippingRect.center());
m_mapView->optimizeForSize(mapSize);
if(!m_keepAspectRatio)
updateVisibleDimension();
}
/* vim: set ts=4 sw=4 et: */

View File

@ -1,111 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef UIMAP_H
#define UIMAP_H
#include "declarations.h"
#include <framework/ui/uiwidget.h>
#include "tile.h"
#include "mapview.h"
class UIMap : public UIWidget
{
public:
UIMap();
~UIMap();
bool onMouseMove(const Point& mousePos, const Point& mouseMoved);
void drawSelf(Fw::DrawPane drawPane);
void movePixels(int x, int y);
bool setZoom(int zoom);
bool zoomIn();
bool zoomOut();
void followCreature(const CreaturePtr& creature) { m_mapView->followCreature(creature); }
void setCameraPosition(const Position& pos) { m_mapView->setCameraPosition(pos); }
void setMaxZoomIn(int maxZoomIn) { m_maxZoomIn = maxZoomIn; }
void setMaxZoomOut(int maxZoomOut) { m_maxZoomOut = maxZoomOut; }
void setMultifloor(bool enable) { m_mapView->setMultifloor(enable); }
void lockVisibleFloor(int floor) { m_mapView->lockFirstVisibleFloor(floor); }
void unlockVisibleFloor() { m_mapView->unlockFirstVisibleFloor(); }
void setVisibleDimension(const Size& visibleDimension);
void setDrawFlags(Otc::DrawFlags drawFlags) { m_mapView->setDrawFlags(drawFlags); }
void setDrawTexts(bool enable) { m_mapView->setDrawTexts(enable); }
void setDrawNames(bool enable) { m_mapView->setDrawNames(enable); }
void setDrawHealthBars(bool enable) { m_mapView->setDrawHealthBars(enable); }
void setDrawHealthBarsOnTop(bool enable) { m_mapView->setDrawHealthBarsOnTop(enable); }
void setDrawLights(bool enable) { m_mapView->setDrawLights(enable); }
void setDrawManaBar(bool enable) { m_mapView->setDrawManaBar(enable); }
void setDrawPlayerBars(bool enable) { m_mapView->setDrawPlayerBars(enable); }
void setAnimated(bool enable) { m_mapView->setAnimated(enable); }
void setKeepAspectRatio(bool enable);
void setMinimumAmbientLight(float intensity) { m_mapView->setMinimumAmbientLight(intensity); }
void setLimitVisibleRange(bool limitVisibleRange) { m_limitVisibleRange = limitVisibleRange; updateVisibleDimension(); }
void setFloorFading(int value) { m_mapView->setFloorFading(value); }
void setCrosshair(const std::string& type) { m_mapView->setCrosshair(type); }
bool isMultifloor() { return m_mapView->isMultifloor(); }
bool isDrawingTexts() { return m_mapView->isDrawingTexts(); }
bool isDrawingNames() { return m_mapView->isDrawingNames(); }
bool isDrawingHealthBars() { return m_mapView->isDrawingHealthBars(); }
bool isDrawingHealthBarsOnTop() { return m_mapView->isDrawingHealthBarsOnTop(); }
bool isDrawingLights() { return m_mapView->isDrawingLights(); }
bool isDrawingManaBar() { return m_mapView->isDrawingManaBar(); }
bool isAnimating() { return m_mapView->isAnimating(); }
bool isKeepAspectRatioEnabled() { return m_keepAspectRatio; }
bool isLimitVisibleRangeEnabled() { return m_limitVisibleRange; }
Size getVisibleDimension() { return m_mapView->getVisibleDimension(); }
CreaturePtr getFollowingCreature() { return m_mapView->getFollowingCreature(); }
Otc::DrawFlags getDrawFlags() { return m_mapView->getDrawFlags(); }
Position getCameraPosition() { return m_mapView->getCameraPosition(); }
Position getPosition(const Point& mousePos);
Point getPositionOffset(const Point& mousePos);
TilePtr getTile(const Point& mousePos);
int getMaxZoomIn() { return m_maxZoomIn; }
int getMaxZoomOut() { return m_maxZoomOut; }
int getZoom() { return m_zoom; }
float getMinimumAmbientLight() { return m_mapView->getMinimumAmbientLight(); }
protected:
virtual void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
virtual void onGeometryChange(const Rect& oldRect, const Rect& newRect);
private:
void updateVisibleDimension();
void updateMapSize();
int m_zoom;
MapViewPtr m_mapView;
Rect m_mapRect;
Point m_mousePosition;
float m_aspectRatio;
bool m_keepAspectRatio;
bool m_limitVisibleRange;
int m_maxZoomIn;
int m_maxZoomOut;
};
#endif

View File

@ -1,92 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "declarations.h"
#include "uimapanchorlayout.h"
#include "uiminimap.h"
#include <framework/ui/uiwidget.h>
int UIPositionAnchor::getHookedPoint(const UIWidgetPtr& hookedWidget, const UIWidgetPtr& parentWidget)
{
UIMinimapPtr minimap = hookedWidget->static_self_cast<UIMinimap>();
Rect hookedRect = minimap->getTileRect(m_hookedPosition);
int point = 0;
if(hookedRect.isValid()) {
switch(m_hookedEdge) {
case Fw::AnchorLeft:
point = hookedRect.left();
break;
case Fw::AnchorRight:
point = hookedRect.right();
break;
case Fw::AnchorTop:
point = hookedRect.top();
break;
case Fw::AnchorBottom:
point = hookedRect.bottom();
break;
case Fw::AnchorHorizontalCenter:
point = hookedRect.horizontalCenter();
break;
case Fw::AnchorVerticalCenter:
point = hookedRect.verticalCenter();
break;
default:
// must never happens
VALIDATE(false);
break;
}
}
return point;
}
void UIMapAnchorLayout::addPositionAnchor(const UIWidgetPtr& anchoredWidget, Fw::AnchorEdge anchoredEdge, const Position& hookedPosition, Fw::AnchorEdge hookedEdge)
{
if(!anchoredWidget)
return;
VALIDATE(anchoredWidget != getParentWidget());
UIPositionAnchorPtr anchor(new UIPositionAnchor(anchoredEdge, hookedPosition, hookedEdge));
UIAnchorGroupPtr& anchorGroup = m_anchorsGroups[anchoredWidget];
if(!anchorGroup)
anchorGroup = UIAnchorGroupPtr(new UIAnchorGroup);
anchorGroup->addAnchor(anchor);
// layout must be updated because a new anchor got in
update();
}
void UIMapAnchorLayout::centerInPosition(const UIWidgetPtr& anchoredWidget, const Position& hookedPosition)
{
addPositionAnchor(anchoredWidget, Fw::AnchorHorizontalCenter, hookedPosition, Fw::AnchorHorizontalCenter);
addPositionAnchor(anchoredWidget, Fw::AnchorVerticalCenter, hookedPosition, Fw::AnchorVerticalCenter);
}
void UIMapAnchorLayout::fillPosition(const UIWidgetPtr& anchoredWidget, const Position& hookedPosition)
{
addPositionAnchor(anchoredWidget, Fw::AnchorLeft, hookedPosition, Fw::AnchorLeft);
addPositionAnchor(anchoredWidget, Fw::AnchorRight, hookedPosition, Fw::AnchorRight);
addPositionAnchor(anchoredWidget, Fw::AnchorTop, hookedPosition, Fw::AnchorTop);
addPositionAnchor(anchoredWidget, Fw::AnchorBottom, hookedPosition, Fw::AnchorBottom);
}

View File

@ -1,55 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef UIMAPANCHORLAYOUT_H
#define UIMAPANCHORLAYOUT_H
#include "declarations.h"
#include <framework/ui/uianchorlayout.h>
class UIPositionAnchor : public UIAnchor
{
public:
UIPositionAnchor(Fw::AnchorEdge anchoredEdge, const Position& hookedPosition, Fw::AnchorEdge hookedEdge) :
UIAnchor(anchoredEdge, std::string(), hookedEdge), m_hookedPosition(hookedPosition) { }
UIWidgetPtr getHookedWidget(const UIWidgetPtr& widget, const UIWidgetPtr& parentWidget) { return parentWidget; }
int getHookedPoint(const UIWidgetPtr& hookedWidget, const UIWidgetPtr& parentWidget);
private:
Position m_hookedPosition;
};
class UIMapAnchorLayout : public UIAnchorLayout
{
public:
UIMapAnchorLayout(UIWidgetPtr parentWidget) : UIAnchorLayout(parentWidget) { }
void addPositionAnchor(const UIWidgetPtr& anchoredWidget, Fw::AnchorEdge anchoredEdge,
const Position& hookedPosition, Fw::AnchorEdge hookedEdge);
void centerInPosition(const UIWidgetPtr& anchoredWidget, const Position& hookedPosition);
void fillPosition(const UIWidgetPtr& anchoredWidget, const Position& hookedPosition);
protected:
};
#endif

View File

@ -1,157 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "uiminimap.h"
#include "minimap.h"
#include "game.h"
#include "uimapanchorlayout.h"
#include "luavaluecasts_client.h"
#include <framework/graphics/painter.h>
#include "uimapanchorlayout.h"
UIMinimap::UIMinimap()
{
m_zoom = 0;
m_scale = 1.0f;
m_minZoom = -5;
m_maxZoom = 5;
m_layout = UIMapAnchorLayoutPtr(new UIMapAnchorLayout(static_self_cast<UIWidget>()));
}
void UIMinimap::drawSelf(Fw::DrawPane drawPane)
{
UIWidget::drawSelf(drawPane);
if(drawPane != Fw::ForegroundPane)
return;
g_minimap.draw(getPaddingRect(), getCameraPosition(), m_scale, m_color);
}
bool UIMinimap::setZoom(int zoom)
{
if(zoom == m_zoom)
return true;
if(zoom < m_minZoom || zoom > m_maxZoom)
return false;
int oldZoom = m_zoom;
m_zoom = zoom;
if(m_zoom < 0)
m_scale = 1.0f / (1 << std::abs(zoom));
else if(m_zoom > 0)
m_scale = 1.0f * (1 << std::abs(zoom));
else
m_scale = 1;
m_layout->update();
onZoomChange(zoom, oldZoom);
return true;
}
void UIMinimap::setCameraPosition(const Position& pos)
{
Position oldPos = m_cameraPosition;
m_cameraPosition = pos;
m_layout->update();
onCameraPositionChange(pos, oldPos);
}
bool UIMinimap::floorUp()
{
Position pos = getCameraPosition();
if(!pos.up())
return false;
setCameraPosition(pos);
return true;
}
bool UIMinimap::floorDown()
{
Position pos = getCameraPosition();
if(!pos.down())
return false;
setCameraPosition(pos);
return true;
}
Point UIMinimap::getTilePoint(const Position& pos)
{
return g_minimap.getTilePoint(pos, getPaddingRect(), getCameraPosition(), m_scale);
}
Rect UIMinimap::getTileRect(const Position& pos)
{
return g_minimap.getTileRect(pos, getPaddingRect(), getCameraPosition(), m_scale);
}
Position UIMinimap::getTilePosition(const Point& mousePos)
{
return g_minimap.getTilePosition(mousePos, getPaddingRect(), getCameraPosition(), m_scale);
}
void UIMinimap::anchorPosition(const UIWidgetPtr& anchoredWidget, Fw::AnchorEdge anchoredEdge, const Position& hookedPosition, Fw::AnchorEdge hookedEdge)
{
UIMapAnchorLayoutPtr layout = m_layout->static_self_cast<UIMapAnchorLayout>();
VALIDATE(layout);
layout->addPositionAnchor(anchoredWidget, anchoredEdge, hookedPosition, hookedEdge);
}
void UIMinimap::fillPosition(const UIWidgetPtr& anchoredWidget, const Position& hookedPosition)
{
UIMapAnchorLayoutPtr layout = m_layout->static_self_cast<UIMapAnchorLayout>();
VALIDATE(layout);
layout->fillPosition(anchoredWidget, hookedPosition);
}
void UIMinimap::centerInPosition(const UIWidgetPtr& anchoredWidget, const Position& hookedPosition)
{
UIMapAnchorLayoutPtr layout = m_layout->static_self_cast<UIMapAnchorLayout>();
VALIDATE(layout);
layout->centerInPosition(anchoredWidget, hookedPosition);
}
void UIMinimap::onZoomChange(int zoom, int oldZoom)
{
callLuaField("onZoomChange", zoom, oldZoom);
}
void UIMinimap::onCameraPositionChange(const Position& position, const Position& oldPosition)
{
callLuaField("onCameraPositionChange", position, oldPosition);
}
void UIMinimap::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
{
UIWidget::onStyleApply(styleName, styleNode);
for(const OTMLNodePtr& node : styleNode->children()) {
if(node->tag() == "zoom")
setZoom(node->value<int>());
else if(node->tag() == "max-zoom")
setMaxZoom(node->value<int>());
else if(node->tag() == "min-zoom")
setMinZoom(node->value<int>());
}
}

View File

@ -1,76 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef UIMINIMAP_H
#define UIMINIMAP_H
#include "declarations.h"
#include <framework/ui/uiwidget.h>
class UIMinimap : public UIWidget
{
public:
UIMinimap();
void drawSelf(Fw::DrawPane drawPane);
bool zoomIn() { return setZoom(m_zoom+1); }
bool zoomOut() { return setZoom(m_zoom-1); }
bool setZoom(int zoom);
void setMinZoom(int minZoom) { m_minZoom = minZoom; }
void setMaxZoom(int maxZoom) { m_maxZoom = maxZoom; }
void setCameraPosition(const Position& pos);
bool floorUp();
bool floorDown();
Point getTilePoint(const Position& pos);
Rect getTileRect(const Position& pos);
Position getTilePosition(const Point& mousePos);
Position getCameraPosition() { return m_cameraPosition; }
int getMinZoom() { return m_minZoom; }
int getMaxZoom() { return m_maxZoom; }
int getZoom() { return m_zoom; }
float getScale() { return m_scale; }
void anchorPosition(const UIWidgetPtr& anchoredWidget, Fw::AnchorEdge anchoredEdge, const Position& hookedPosition, Fw::AnchorEdge hookedEdge);
void fillPosition(const UIWidgetPtr& anchoredWidget, const Position& hookedPosition);
void centerInPosition(const UIWidgetPtr& anchoredWidget, const Position& hookedPosition);
protected:
virtual void onZoomChange(int zoom, int oldZoom);
virtual void onCameraPositionChange(const Position& position, const Position& oldPosition);
virtual void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
private:
void update();
Rect m_mapArea;
Position m_cameraPosition;
float m_scale;
int m_zoom;
int m_minZoom;
int m_maxZoom;
};
#endif

View File

@ -1,96 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "uiprogressrect.h"
#include <framework/otml/otml.h>
#include <framework/graphics/graphics.h>
#include <framework/graphics/fontmanager.h>
UIProgressRect::UIProgressRect()
{
m_percent = 0;
}
void UIProgressRect::drawSelf(Fw::DrawPane drawPane)
{
if(drawPane != Fw::ForegroundPane)
return;
// todo: check +1 to right/bottom
// todo: add smooth
Rect drawRect = getPaddingRect();
// 0% - 12.5% (12.5)
// triangle from top center, to top right (var x)
if(m_percent < 12.5) {
Point var = Point(std::max<int>(m_percent - 0.0, 0.0) * (drawRect.right() - drawRect.horizontalCenter()) / 12.5, 0);
g_drawQueue->addFilledTriangle(drawRect.center(), drawRect.topRight() + Point(1,0), drawRect.topCenter() + var, m_backgroundColor);
}
// 12.5% - 37.5% (25)
// triangle from top right to bottom right (var y)
if(m_percent < 37.5) {
Point var = Point(0, std::max<int>(m_percent - 12.5, 0.0) * (drawRect.bottom() - drawRect.top()) / 25.0);
g_drawQueue->addFilledTriangle(drawRect.center(), drawRect.bottomRight() + Point(1,1), drawRect.topRight() + var + Point(1,0), m_backgroundColor);
}
// 37.5% - 62.5% (25)
// triangle from bottom right to bottom left (var x)
if(m_percent < 62.5) {
Point var = Point(std::max<int>(m_percent - 37.5, 0.0) * (drawRect.right() - drawRect.left()) / 25.0, 0);
g_drawQueue->addFilledTriangle(drawRect.center(), drawRect.bottomLeft() + Point(0,1), drawRect.bottomRight() - var + Point(1,1), m_backgroundColor);
}
// 62.5% - 87.5% (25)
// triangle from bottom left to top left
if(m_percent < 87.5) {
Point var = Point(0, std::max<int>(m_percent - 62.5, 0.0) * (drawRect.bottom() - drawRect.top()) / 25.0);
g_drawQueue->addFilledTriangle(drawRect.center(), drawRect.topLeft(), drawRect.bottomLeft() - var + Point(0,1), m_backgroundColor);
}
// 87.5% - 100% (12.5)
// triangle from top left to top center
if(m_percent < 100) {
Point var = Point(std::max<int>(m_percent - 87.5, 0.0) * (drawRect.horizontalCenter() - drawRect.left()) / 12.5, 0);
g_drawQueue->addFilledTriangle(drawRect.center(), drawRect.topCenter(), drawRect.topLeft() + var, m_backgroundColor);
}
drawImage(m_rect);
drawBorder(m_rect);
drawIcon(m_rect);
drawText(m_rect);
}
void UIProgressRect::setPercent(float percent)
{
m_percent = stdext::clamp<float>((double)percent, 0.0, 100.0);
}
void UIProgressRect::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
{
UIWidget::onStyleApply(styleName, styleNode);
for(const OTMLNodePtr& node : styleNode->children()) {
if(node->tag() == "percent")
setPercent(node->value<float>());
}
}

View File

@ -1,45 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef UIPROGRESSRECT_H
#define UIPROGRESSRECT_H
#include "declarations.h"
#include <framework/ui/uiwidget.h>
#include "item.h"
class UIProgressRect : public UIWidget
{
public:
UIProgressRect();
void drawSelf(Fw::DrawPane drawPane);
void setPercent(float percent);
float getPercent() { return m_percent; }
protected:
void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
float m_percent;
};
#endif

View File

@ -1,86 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "uisprite.h"
#include <framework/otml/otml.h>
#include <framework/graphics/graphics.h>
#include <framework/graphics/texturemanager.h>
#include <client/spritemanager.h>
UISprite::UISprite() :
m_spriteId(0),
m_spriteColor(Color::white)
{ }
void UISprite::drawSelf(Fw::DrawPane drawPane)
{
if(drawPane != Fw::ForegroundPane)
return;
// draw style components in order
if(m_backgroundColor.aF() > Fw::MIN_ALPHA) {
Rect backgroundDestRect = m_rect;
backgroundDestRect.expand(-m_borderWidth.top, -m_borderWidth.right, -m_borderWidth.bottom, -m_borderWidth.left);
drawBackground(m_rect);
}
drawImage(m_rect);
if(m_spriteVisible && m_sprite) {
g_drawQueue->addTexturedRect(getPaddingRect(), m_sprite, Rect(Point(0, 0), m_sprite->getSize()), m_spriteColor);
}
drawBorder(m_rect);
drawIcon(m_rect);
drawText(m_rect);
}
void UISprite::setSpriteId(int id)
{
if(!g_sprites.isLoaded())
return;
m_spriteId = id;
if(id == 0)
m_sprite = nullptr;
else {
ImagePtr image = g_sprites.getSpriteImage(id);
if(image)
m_sprite = new Texture(image);
else
m_sprite = nullptr;
}
}
void UISprite::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
{
UIWidget::onStyleApply(styleName, styleNode);
for(const OTMLNodePtr& node : styleNode->children()) {
if(node->tag() == "sprite-id")
setSpriteId(node->value<int>());
else if(node->tag() == "sprite-visible")
setSpriteVisible(node->value<bool>());
else if(node->tag() == "sprite-color")
setSpriteColor(node->value<Color>());
}
}

View File

@ -1,56 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef UISPRITE_H
#define UISPRITE_H
#include "declarations.h"
#include <framework/ui/uiwidget.h>
class UISprite : public UIWidget
{
public:
UISprite();
void drawSelf(Fw::DrawPane drawPane);
void setSpriteId(int id);
int getSpriteId() { return m_spriteId; }
void clearSprite() { setSpriteId(0); }
void setSpriteColor(Color color) { m_spriteColor = color; }
bool isSpriteVisible() { return m_spriteVisible; }
void setSpriteVisible(bool visible) { m_spriteVisible = visible; }
bool hasSprite() { return m_sprite != nullptr; }
protected:
void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
TexturePtr m_sprite;
uint16 m_spriteId;
Color m_spriteColor;
stdext::boolean<true> m_spriteVisible;
};
#endif

View File

@ -1,301 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef FRAMEWORK_CONST_H
#define FRAMEWORK_CONST_H
#include "stdext/compiler.h"
#define DEG_TO_RAD (acos(-1)/180.0)
#define RAD_TO_DEC (180.0/acos(-1))
#ifndef BUILD_COMMIT
#define BUILD_COMMIT "devel"
#endif
#ifndef BUILD_REVISION
#define BUILD_REVISION "0"
#endif
#ifndef BUILD_TYPE
#define BUILD_TYPE "unknown"
#endif
#ifndef BUILD_ARCH
#if defined(__amd64) || defined(_M_X64)
#define BUILD_ARCH "x64"
#elif defined(__i386) || defined(_M_IX86) || defined(_X86_)
#define BUILD_ARCH "x86"
#else
#define BUILD_ARCH "unknown"
#endif
#endif
namespace Fw
{
static const float pi = 3.14159265;
static const float MIN_ALPHA = 0.003f;
enum Key : unsigned char {
KeyUnknown = 0,
KeyEscape = 1,
KeyTab = 2,
KeyBackspace = 3,
//KeyReturn = 4,
KeyEnter = 5,
KeyInsert = 6,
KeyDelete = 7,
KeyPause = 8,
KeyPrintScreen = 9,
KeyHome = 10,
KeyEnd = 11,
KeyPageUp = 12,
KeyPageDown = 13,
KeyUp = 14,
KeyDown = 15,
KeyLeft = 16,
KeyRight = 17,
KeyNumLock = 18,
KeyScrollLock = 19,
KeyCapsLock = 20,
KeyCtrl = 21,
KeyShift = 22,
KeyAlt = 23,
//KeyAltGr = 24,
KeyMeta = 25,
KeyMenu = 26,
KeySpace = 32, // ' '
KeyExclamation = 33, // !
KeyQuote = 34, // "
KeyNumberSign = 35, // #
KeyDollar = 36, // $
KeyPercent = 37, // %
KeyAmpersand = 38, // &
KeyApostrophe = 39, // '
KeyLeftParen = 40, // (
KeyRightParen = 41, // )
KeyAsterisk = 42, // *
KeyPlus = 43, // +
KeyComma = 44, // ,
KeyMinus = 45, // -
KeyPeriod = 46, // .
KeySlash = 47, // /
Key0 = 48, // 0
Key1 = 49, // 1
Key2 = 50, // 2
Key3 = 51, // 3
Key4 = 52, // 4
Key5 = 53, // 5
Key6 = 54, // 6
Key7 = 55, // 7
Key8 = 56, // 8
Key9 = 57, // 9
KeyColon = 58, // :
KeySemicolon = 59, // ;
KeyLess = 60, // <
KeyEqual = 61, // =
KeyGreater = 62, // >
KeyQuestion = 63, // ?
KeyAtSign = 64, // @
KeyA = 65, // a
KeyB = 66, // b
KeyC = 67, // c
KeyD = 68, // d
KeyE = 69, // e
KeyF = 70, // f
KeyG = 71, // g
KeyH = 72, // h
KeyI = 73, // i
KeyJ = 74, // j
KeyK = 75, // k
KeyL = 76, // l
KeyM = 77, // m
KeyN = 78, // n
KeyO = 79, // o
KeyP = 80, // p
KeyQ = 81, // q
KeyR = 82, // r
KeyS = 83, // s
KeyT = 84, // t
KeyU = 85, // u
KeyV = 86, // v
KeyW = 87, // w
KeyX = 88, // x
KeyY = 89, // y
KeyZ = 90, // z
KeyLeftBracket = 91, // [
KeyBackslash = 92, // '\'
KeyRightBracket = 93, // ]
KeyCaret = 94, // ^
KeyUnderscore = 95, // _
KeyGrave = 96, // `
KeyLeftCurly = 123, // {
KeyBar = 124, // |
KeyRightCurly = 125, // }
KeyTilde = 126, // ~
KeyF1 = 128,
KeyF2 = 129,
KeyF3 = 130,
KeyF4 = 131,
KeyF5 = 132,
KeyF6 = 134,
KeyF7 = 135,
KeyF8 = 136,
KeyF9 = 137,
KeyF10 = 138,
KeyF11 = 139,
KeyF12 = 140,
KeyNumpad0 = 141,
KeyNumpad1 = 142,
KeyNumpad2 = 143,
KeyNumpad3 = 144,
KeyNumpad4 = 145,
KeyNumpad5 = 146,
KeyNumpad6 = 147,
KeyNumpad7 = 148,
KeyNumpad8 = 149,
KeyNumpad9 = 150
};
enum LogLevel {
LogDebug = 0,
LogInfo,
LogWarning,
LogError,
LogFatal
};
enum AspectRatioMode {
IgnoreAspectRatio,
KeepAspectRatio,
KeepAspectRatioByExpanding
};
enum AlignmentFlag {
AlignNone = 0,
AlignLeft = 1,
AlignRight = 2,
AlignTop = 4,
AlignBottom = 8,
AlignHorizontalCenter = 16,
AlignVerticalCenter = 32,
AlignTopLeft = AlignTop | AlignLeft, // 5
AlignTopRight = AlignTop | AlignRight, // 6
AlignBottomLeft = AlignBottom | AlignLeft, // 9
AlignBottomRight = AlignBottom | AlignRight, // 10
AlignLeftCenter = AlignLeft | AlignVerticalCenter, // 33
AlignRightCenter = AlignRight | AlignVerticalCenter, // 34
AlignTopCenter = AlignTop | AlignHorizontalCenter, // 20
AlignBottomCenter = AlignBottom | AlignHorizontalCenter, // 24
AlignCenter = AlignVerticalCenter | AlignHorizontalCenter // 48
};
enum AnchorEdge {
AnchorNone = 0,
AnchorTop,
AnchorBottom,
AnchorLeft,
AnchorRight,
AnchorVerticalCenter,
AnchorHorizontalCenter
};
enum FocusReason {
MouseFocusReason = 0,
KeyboardFocusReason,
ActiveFocusReason,
OtherFocusReason
};
enum AutoFocusPolicy {
AutoFocusNone = 0,
AutoFocusFirst,
AutoFocusLast
};
enum InputEventType {
NoInputEvent = 0,
KeyTextInputEvent,
KeyDownInputEvent,
KeyPressInputEvent,
KeyUpInputEvent,
MousePressInputEvent,
MouseReleaseInputEvent,
MouseMoveInputEvent,
MouseWheelInputEvent
};
enum MouseButton {
MouseNoButton = 0,
MouseLeftButton,
MouseRightButton,
MouseMidButton,
MouseTouch
};
enum MouseWheelDirection {
MouseNoWheel = 0,
MouseWheelUp,
MouseWheelDown
};
enum KeyboardModifier {
KeyboardNoModifier = 0,
KeyboardCtrlModifier = 1,
KeyboardAltModifier = 2,
KeyboardShiftModifier = 4
};
enum WidgetState {
InvalidState = -1,
DefaultState = 0,
ActiveState = 1,
FocusState = 2,
HoverState = 4,
PressedState = 8,
DisabledState = 16,
CheckedState = 32,
OnState = 64,
FirstState = 128,
MiddleState = 256,
LastState = 512,
AlternateState = 1024,
DraggingState = 2048,
HiddenState = 4096,
MobileState = 8192,
LastWidgetState = 16384
};
enum DrawPane {
ForegroundPane = 1,
MapBackgroundPane = 2,
MapForegroundPane = 3,
};
#ifdef FW_SQL
enum DatabaseEngine {
DatabaseNone = 0,
DatabaseMySQL
};
#endif
}
#endif

View File

@ -1,91 +0,0 @@
#include <framework/core/logger.h>
#include <framework/core/graphicalapplication.h>
#include <framework/stdext/format.h>
#include <framework/util/extras.h>
#include "adaptiverenderer.h"
AdaptiveRenderer g_adaptiveRenderer;
void AdaptiveRenderer::newFrame() {
auto now = stdext::millis();
m_frames.push_back(now);
while (m_frames.front() + 5000 < now) {
m_frames.pop_front();
}
if (m_forcedSpeed >= 0 && m_forcedSpeed <= 4) {
m_speed = m_forcedSpeed;
return;
}
if (m_update + 5000 > now)
return;
m_update = stdext::millis();
if (m_speed < 1)
m_speed = 1;
int maxFps = std::min<int>(100, std::max<int>(10, g_app.getMaxFps() < 10 ? 100 : g_app.getMaxFps()));
if (m_speed >= 2 && maxFps > 60) { // fix for forced vsync
maxFps = 60;
}
if (m_frames.size() < maxFps * (4.0f - m_speed * 0.3f) && m_speed != RenderSpeeds - 1) {
m_speed += 1;
}
if (m_frames.size() > maxFps * (4.5f - m_speed * 0.1f) && m_speed > 1) {
m_speed -= 1;
}
}
void AdaptiveRenderer::refresh() {
m_update = stdext::millis();
}
int AdaptiveRenderer::effetsLimit() {
static int limits[RenderSpeeds] = { 20, 10, 7, 4, 2 };
return limits[m_speed];
}
int AdaptiveRenderer::creaturesLimit() {
static int limits[RenderSpeeds] = { 20, 10, 7, 5, 3 };
return limits[m_speed];
}
int AdaptiveRenderer::itemsLimit() {
static int limits[RenderSpeeds] = { 20, 10, 7, 5, 3 };
return limits[m_speed];
}
int AdaptiveRenderer::mapRenderInterval() {
static int limits[RenderSpeeds] = { 0, 10, 20, 50, 100 };
return limits[m_speed];
}
int AdaptiveRenderer::textsLimit() {
static int limits[RenderSpeeds] = { 1000, 50, 30, 15, 5 };
return limits[m_speed];
}
int AdaptiveRenderer::creaturesRenderInterval() {
// not working yet
static int limits[RenderSpeeds] = { 0, 0, 10, 15, 20 };
return limits[m_speed];
}
bool AdaptiveRenderer::allowFading() {
return m_speed <= 2;
}
int AdaptiveRenderer::foregroundUpdateInterval() {
static int limits[RenderSpeeds] = { 0, 20, 40, 50, 60 };
return limits[m_speed];
}
std::string AdaptiveRenderer::getDebugInfo() {
std::stringstream ss;
ss << "Frames: " << m_frames.size() << "|" << m_speed << "|" << m_forcedSpeed;
return ss.str();
}

View File

@ -1,50 +0,0 @@
#ifndef ADAPTIVERENDERER_H
#define ADAPTIVERENDERER_H
#include <list>
constexpr int RenderSpeeds = 5;
class AdaptiveRenderer {
public:
void newFrame();
void refresh();
int effetsLimit();
int creaturesLimit();
int itemsLimit();
int textsLimit();
int mapRenderInterval();
int creaturesRenderInterval();
bool allowFading();
int getLevel() {
return m_speed;
}
int foregroundUpdateInterval();
std::string getDebugInfo();
void setForcedLevel(int value) {
m_forcedSpeed = value;
}
private:
int m_forcedSpeed = -1;
int m_speed = 0;
time_t m_update = 0;
std::list<time_t> m_frames;
};
extern AdaptiveRenderer g_adaptiveRenderer;
#endif

View File

@ -1,223 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "application.h"
#include <csignal>
#include <framework/core/clock.h>
#include <framework/core/resourcemanager.h>
#include <framework/core/modulemanager.h>
#include <framework/core/eventdispatcher.h>
#include <framework/core/configmanager.h>
#include "asyncdispatcher.h"
#include <framework/luaengine/luainterface.h>
#include <framework/platform/crashhandler.h>
#include <framework/platform/platform.h>
#include <framework/http/http.h>
#include <boost/process.hpp>
#include <locale>
#ifdef FW_NET
#include <framework/net/connection.h>
#ifdef FW_PROXY
#include <extras/proxy/proxy.h>
#endif
#endif
void exitSignalHandler(int sig)
{
static bool signaled = false;
switch(sig) {
case SIGTERM:
case SIGINT:
if(!signaled && !g_app.isStopping() && !g_app.isTerminated()) {
signaled = true;
g_dispatcher.addEvent(std::bind(&Application::close, &g_app));
}
break;
}
}
Application::Application()
{
m_appName = "application";
m_appCompactName = "app";
m_appVersion = "none";
m_charset = "cp1252";
m_stopping = false;
#ifdef ANDROID
m_mobile = true;
#endif
}
void Application::init(std::vector<std::string>& args)
{
// capture exit signals
signal(SIGTERM, exitSignalHandler);
signal(SIGINT, exitSignalHandler);
// setup locale
std::locale::global(std::locale());
// process args encoding
g_platform.processArgs(args);
g_asyncDispatcher.init();
std::string startupOptions;
for(uint i=1;i<args.size();++i) {
const std::string& arg = args[i];
startupOptions += " ";
startupOptions += arg;
}
if(startupOptions.length() > 0)
g_logger.info(stdext::format("Startup options: %s", startupOptions));
m_startupOptions = startupOptions;
// mobile testing
if (startupOptions.find("-mobile") != std::string::npos)
m_mobile = true;
// initialize configs
g_configs.init();
// initialize lua
g_lua.init();
registerLuaFunctions();
#ifdef FW_PROXY
// initalize proxy
g_proxy.init();
#endif
}
void Application::deinit()
{
g_lua.callGlobalField("g_app", "onTerminate");
// run modules unload events
g_modules.unloadModules();
g_modules.clear();
// release remaining lua object references
g_lua.collectGarbage();
// poll remaining events
poll();
// disable dispatcher events
g_dispatcher.shutdown();
}
void Application::terminate()
{
#ifdef FW_NET
// terminate network
Connection::terminate();
#endif
// release configs
g_configs.terminate();
// release resources
g_resources.terminate();
// terminate script environment
g_lua.terminate();
#ifdef FW_PROXY
// terminate proxy
g_proxy.terminate();
#endif
m_terminated = true;
signal(SIGTERM, SIG_DFL);
signal(SIGINT, SIG_DFL);
}
void Application::poll()
{
#ifdef FW_NET
Connection::poll();
#endif
g_dispatcher.poll();
// poll connection again to flush pending write
#ifdef FW_NET
Connection::poll();
#endif
}
void Application::exit()
{
g_lua.callGlobalField<bool>("g_app", "onExit");
m_stopping = true;
}
void Application::quick_exit()
{
#ifdef _MSC_VER
::quick_exit(0);
#else
::exit(0);
#endif
}
void Application::close()
{
if(!g_lua.callGlobalField<bool>("g_app", "onClose"))
exit();
}
void Application::restart()
{
#ifndef ANDROID
boost::process::child c(g_resources.getBinaryName());
std::error_code ec2;
if (c.wait_for(std::chrono::seconds(1), ec2)) {
g_logger.fatal("Updater restart error. Please restart application");
}
c.detach();
quick_exit();
#else
exit();
#endif
}
std::string Application::getOs()
{
#if defined(ANDROID)
return "android";
#elif defined(WIN32)
return "windows";
#elif defined(__APPLE__)
return "mac";
#elif __linux
return "linux";
#else
return "unknown";
#endif
}

View File

@ -1,92 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef APPLICATION_H
#define APPLICATION_H
#include <framework/global.h>
//@bindsingleton g_app
class Application
{
public:
Application();
virtual ~Application() {}
virtual void init(std::vector<std::string>& args);
virtual void deinit();
virtual void terminate();
virtual void run() = 0;
virtual void poll();
virtual void exit();
virtual void quick_exit();
virtual void close();
void restart();
void setName(const std::string& name) { m_appName = name; }
void setCompactName(const std::string& compactName) { m_appCompactName = compactName; }
void setVersion(const std::string& version) { m_appVersion = version; }
bool isRunning() { return m_running; }
bool isStopping() { return m_stopping; }
bool isTerminated() { return m_terminated; }
const std::string& getName() { return m_appName; }
const std::string& getCompactName() { return m_appCompactName; }
const std::string& getVersion() { return m_appVersion; }
std::string getCharset() { return m_charset; }
std::string getBuildCompiler() { return BUILD_COMPILER; }
std::string getBuildDate() { return std::string(__DATE__); }
std::string getBuildRevision() { return BUILD_REVISION; }
std::string getBuildCommit() { return BUILD_COMMIT; }
std::string getBuildType() { return BUILD_TYPE; }
std::string getBuildArch() { return BUILD_ARCH; }
std::string getAuthor() { return "otclient.ovh"; }
std::string getOs();
std::string getStartupOptions() { return m_startupOptions; }
bool isMobile()
{
return m_mobile;
}
protected:
void registerLuaFunctions();
std::string m_charset;
std::string m_appName;
std::string m_appCompactName;
std::string m_appVersion;
std::string m_startupOptions;
stdext::boolean<false> m_running;
stdext::boolean<false> m_stopping;
stdext::boolean<false> m_terminated;
stdext::boolean<false> m_mobile;
};
#ifdef FW_GRAPHICS
#include "graphicalapplication.h"
#else
#include "consoleapplication.h"
#endif
#endif

View File

@ -1,71 +0,0 @@
/*
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "asyncdispatcher.h"
AsyncDispatcher g_asyncDispatcher;
void AsyncDispatcher::init()
{
spawn_thread();
}
void AsyncDispatcher::terminate()
{
stop();
m_tasks.clear();
}
void AsyncDispatcher::spawn_thread()
{
m_running = true;
m_threads.push_back(std::thread(std::bind(&AsyncDispatcher::exec_loop, this)));
}
void AsyncDispatcher::stop()
{
m_mutex.lock();
m_running = false;
m_condition.notify_all();
m_mutex.unlock();
for(std::thread& thread : m_threads)
thread.join();
m_threads.clear();
};
void AsyncDispatcher::exec_loop() {
std::unique_lock<std::mutex> lock(m_mutex);
while(true) {
while(m_tasks.size() == 0 && m_running)
m_condition.wait(lock);
if(!m_running)
return;
std::function<void()> task = m_tasks.front();
m_tasks.pop_front();
lock.unlock();
task();
lock.lock();
}
}

Some files were not shown because too many files have changed in this diff Show More