Version 2.6.1

This commit is contained in:
OTCv8 2021-01-18 00:46:05 +01:00
parent 8fa45f387d
commit b938520faf
100 changed files with 1812 additions and 4267 deletions

View File

@ -1,278 +1,278 @@
HTTP = {
timeout=5,
websocketTimeout=15,
agent="Mozilla/5.0",
imageId=1000,
images={},
operations={},
}
function HTTP.get(url, callback)
if not g_http or not g_http.get then
return error("HTTP.get is not supported")
end
local operation = g_http.get(url, HTTP.timeout)
HTTP.operations[operation] = {type="get", url=url, callback=callback}
return operation
end
function HTTP.getJSON(url, callback)
if not g_http or not g_http.get then
return error("HTTP.getJSON is not supported")
end
local operation = g_http.get(url, HTTP.timeout)
HTTP.operations[operation] = {type="get", json=true, url=url, callback=callback}
return operation
end
function HTTP.post(url, data, callback)
if not g_http or not g_http.post then
return error("HTTP.post is not supported")
end
if type(data) == "table" then
data = json.encode(data)
end
local operation = g_http.post(url, data, HTTP.timeout)
HTTP.operations[operation] = {type="post", url=url, callback=callback}
return operation
end
function HTTP.postJSON(url, data, callback)
if not g_http or not g_http.post then
return error("HTTP.postJSON is not supported")
end
if type(data) == "table" then
data = json.encode(data)
end
local operation = g_http.post(url, data, HTTP.timeout)
HTTP.operations[operation] = {type="post", json=true, url=url, callback=callback}
return operation
end
function HTTP.download(url, file, callback, progressCallback)
if not g_http or not g_http.download then
return error("HTTP.download is not supported")
end
local operation = g_http.download(url, file, HTTP.timeout)
HTTP.operations[operation] = {type="download", url=url, file=file, callback=callback, progressCallback=progressCallback}
return operation
end
function HTTP.downloadImage(url, callback)
if not g_http or not g_http.download then
return error("HTTP.downloadImage is not supported")
end
if HTTP.images[url] ~= nil then
if callback then
callback('/downloads/' .. HTTP.images[url], nil)
end
return
end
local file = "autoimage_" .. HTTP.imageId .. ".png"
HTTP.imageId = HTTP.imageId + 1
local operation = g_http.download(url, file, HTTP.timeout)
HTTP.operations[operation] = {type="image", url=url, file=file, callback=callback}
return operation
end
function HTTP.webSocket(url, callbacks, timeout, jsonWebsocket)
if not g_http or not g_http.ws then
return error("WebSocket is not supported")
end
if not timeout or timeout < 1 then
timeout = HTTP.websocketTimeout
end
local operation = g_http.ws(url, timeout)
HTTP.operations[operation] = {type="ws", json=jsonWebsocket, url=url, callbacks=callbacks}
return {
id = operation,
url = url,
close = function()
g_http.wsClose(operation)
end,
send = function(message)
if type(message) == "table" then
message = json.encode(message)
end
g_http.wsSend(operation, message)
end
}
end
HTTP.WebSocket = HTTP.webSocket
function HTTP.webSocketJSON(url, callbacks, timeout)
return HTTP.webSocket(url, callbacks, timeout, true)
end
HTTP.WebSocketJSON = HTTP.webSocketJSON
function HTTP.cancel(operationId)
if not g_http or not g_http.cancel then
return
end
HTTP.operations[operationId] = nil
return g_http.cancel(operationId)
end
function HTTP.onGet(operationId, url, err, data)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if err and err:len() == 0 then
err = nil
end
if not err and operation.json then
local status, result = pcall(function() return json.decode(data) end)
if not status then
err = "JSON ERROR: " .. result
if data and data:len() > 0 then
err = err .. " (" .. data:sub(1, 100) .. ")"
end
end
data = result
end
if operation.callback then
operation.callback(data, err)
end
end
function HTTP.onGetProgress(operationId, url, progress)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
end
function HTTP.onPost(operationId, url, err, data)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if err and err:len() == 0 then
err = nil
end
if not err and operation.json then
local status, result = pcall(function() return json.decode(data) end)
if not status then
err = "JSON ERROR: " .. result
if data and data:len() > 0 then
err = err .. " (" .. data:sub(1, 100) .. ")"
end
end
data = result
end
if operation.callback then
operation.callback(data, err)
end
end
function HTTP.onPostProgress(operationId, url, progress)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
end
function HTTP.onDownload(operationId, url, err, path, checksum)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if err and err:len() == 0 then
err = nil
end
if operation.callback then
if operation["type"] == "image" then
if not err then
HTTP.images[url] = path
end
operation.callback('/downloads/' .. path, err)
else
operation.callback(path, checksum, err)
end
end
end
function HTTP.onDownloadProgress(operationId, url, progress, speed)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if operation.progressCallback then
operation.progressCallback(progress, speed)
end
end
function HTTP.onWsOpen(operationId, message)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if operation.callbacks.onOpen then
operation.callbacks.onOpen(message, operationId)
end
end
function HTTP.onWsMessage(operationId, message)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if operation.callbacks.onMessage then
if operation.json then
local status, result = pcall(function() return json.decode(message) end)
local err = nil
if not status then
err = "JSON ERROR: " .. result
if message and message:len() > 0 then
err = err .. " (" .. message:sub(1, 100) .. ")"
end
end
if err then
if operation.callbacks.onError then
operation.callbacks.onError(err, operationId)
end
else
operation.callbacks.onMessage(result, operationId)
end
else
operation.callbacks.onMessage(message, operationId)
end
end
end
function HTTP.onWsClose(operationId, message)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if operation.callbacks.onClose then
operation.callbacks.onClose(message, operationId)
end
end
function HTTP.onWsError(operationId, message)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if operation.callbacks.onError then
operation.callbacks.onError(message, operationId)
end
end
connect(g_http,
{
onGet = HTTP.onGet,
onGetProgress = HTTP.onGetProgress,
onPost = HTTP.onPost,
onPostProgress = HTTP.onPostProgress,
onDownload = HTTP.onDownload,
onDownloadProgress = HTTP.onDownloadProgress,
onWsOpen = HTTP.onWsOpen,
onWsMessage = HTTP.onWsMessage,
onWsClose = HTTP.onWsClose,
onWsError = HTTP.onWsError,
})
g_http.setUserAgent(HTTP.agent)
HTTP = {
timeout=5,
websocketTimeout=15,
agent="Mozilla/5.0",
imageId=1000,
images={},
operations={},
}
function HTTP.get(url, callback)
if not g_http or not g_http.get then
return error("HTTP.get is not supported")
end
local operation = g_http.get(url, HTTP.timeout)
HTTP.operations[operation] = {type="get", url=url, callback=callback}
return operation
end
function HTTP.getJSON(url, callback)
if not g_http or not g_http.get then
return error("HTTP.getJSON is not supported")
end
local operation = g_http.get(url, HTTP.timeout)
HTTP.operations[operation] = {type="get", json=true, url=url, callback=callback}
return operation
end
function HTTP.post(url, data, callback)
if not g_http or not g_http.post then
return error("HTTP.post is not supported")
end
if type(data) == "table" then
data = json.encode(data)
end
local operation = g_http.post(url, data, HTTP.timeout)
HTTP.operations[operation] = {type="post", url=url, callback=callback}
return operation
end
function HTTP.postJSON(url, data, callback)
if not g_http or not g_http.post then
return error("HTTP.postJSON is not supported")
end
if type(data) == "table" then
data = json.encode(data)
end
local operation = g_http.post(url, data, HTTP.timeout)
HTTP.operations[operation] = {type="post", json=true, url=url, callback=callback}
return operation
end
function HTTP.download(url, file, callback, progressCallback)
if not g_http or not g_http.download then
return error("HTTP.download is not supported")
end
local operation = g_http.download(url, file, HTTP.timeout)
HTTP.operations[operation] = {type="download", url=url, file=file, callback=callback, progressCallback=progressCallback}
return operation
end
function HTTP.downloadImage(url, callback)
if not g_http or not g_http.download then
return error("HTTP.downloadImage is not supported")
end
if HTTP.images[url] ~= nil then
if callback then
callback('/downloads/' .. HTTP.images[url], nil)
end
return
end
local file = "autoimage_" .. HTTP.imageId .. ".png"
HTTP.imageId = HTTP.imageId + 1
local operation = g_http.download(url, file, HTTP.timeout)
HTTP.operations[operation] = {type="image", url=url, file=file, callback=callback}
return operation
end
function HTTP.webSocket(url, callbacks, timeout, jsonWebsocket)
if not g_http or not g_http.ws then
return error("WebSocket is not supported")
end
if not timeout or timeout < 1 then
timeout = HTTP.websocketTimeout
end
local operation = g_http.ws(url, timeout)
HTTP.operations[operation] = {type="ws", json=jsonWebsocket, url=url, callbacks=callbacks}
return {
id = operation,
url = url,
close = function()
g_http.wsClose(operation)
end,
send = function(message)
if type(message) == "table" then
message = json.encode(message)
end
g_http.wsSend(operation, message)
end
}
end
HTTP.WebSocket = HTTP.webSocket
function HTTP.webSocketJSON(url, callbacks, timeout)
return HTTP.webSocket(url, callbacks, timeout, true)
end
HTTP.WebSocketJSON = HTTP.webSocketJSON
function HTTP.cancel(operationId)
if not g_http or not g_http.cancel then
return
end
HTTP.operations[operationId] = nil
return g_http.cancel(operationId)
end
function HTTP.onGet(operationId, url, err, data)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if err and err:len() == 0 then
err = nil
end
if not err and operation.json then
local status, result = pcall(function() return json.decode(data) end)
if not status then
err = "JSON ERROR: " .. result
if data and data:len() > 0 then
err = err .. " (" .. data:sub(1, 100) .. ")"
end
end
data = result
end
if operation.callback then
operation.callback(data, err)
end
end
function HTTP.onGetProgress(operationId, url, progress)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
end
function HTTP.onPost(operationId, url, err, data)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if err and err:len() == 0 then
err = nil
end
if not err and operation.json then
local status, result = pcall(function() return json.decode(data) end)
if not status then
err = "JSON ERROR: " .. result
if data and data:len() > 0 then
err = err .. " (" .. data:sub(1, 100) .. ")"
end
end
data = result
end
if operation.callback then
operation.callback(data, err)
end
end
function HTTP.onPostProgress(operationId, url, progress)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
end
function HTTP.onDownload(operationId, url, err, path, checksum)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if err and err:len() == 0 then
err = nil
end
if operation.callback then
if operation["type"] == "image" then
if not err then
HTTP.images[url] = path
end
operation.callback('/downloads/' .. path, err)
else
operation.callback(path, checksum, err)
end
end
end
function HTTP.onDownloadProgress(operationId, url, progress, speed)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if operation.progressCallback then
operation.progressCallback(progress, speed)
end
end
function HTTP.onWsOpen(operationId, message)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if operation.callbacks.onOpen then
operation.callbacks.onOpen(message, operationId)
end
end
function HTTP.onWsMessage(operationId, message)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if operation.callbacks.onMessage then
if operation.json then
local status, result = pcall(function() return json.decode(message) end)
local err = nil
if not status then
err = "JSON ERROR: " .. result
if message and message:len() > 0 then
err = err .. " (" .. message:sub(1, 100) .. ")"
end
end
if err then
if operation.callbacks.onError then
operation.callbacks.onError(err, operationId)
end
else
operation.callbacks.onMessage(result, operationId)
end
else
operation.callbacks.onMessage(message, operationId)
end
end
end
function HTTP.onWsClose(operationId, message)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if operation.callbacks.onClose then
operation.callbacks.onClose(message, operationId)
end
end
function HTTP.onWsError(operationId, message)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if operation.callbacks.onError then
operation.callbacks.onError(message, operationId)
end
end
connect(g_http,
{
onGet = HTTP.onGet,
onGetProgress = HTTP.onGetProgress,
onPost = HTTP.onPost,
onPostProgress = HTTP.onPostProgress,
onDownload = HTTP.onDownload,
onDownloadProgress = HTTP.onDownloadProgress,
onWsOpen = HTTP.onWsOpen,
onWsMessage = HTTP.onWsMessage,
onWsClose = HTTP.onWsClose,
onWsError = HTTP.onWsError,
})
g_http.setUserAgent(HTTP.agent)

View File

@ -1,419 +1,419 @@
--
-- json.lua
--
-- Copyright (c) 2019 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 make_indent(state)
return string.rep(" ", state.currentIndentLevel * state.indent)
end
local function escape_char(c)
return escape_char_map[c] or string.format("\\u%04x", c:byte())
end
local function encode_nil()
return "null"
end
local function encode_table(val, state)
local res = {}
local stack = state.stack
local pretty = state.indent > 0
local close_indent = make_indent(state)
local comma = pretty and ",\n" or ","
local colon = pretty and ": " or ":"
local open_brace = pretty and "{\n" or "{"
local close_brace = pretty and ("\n" .. close_indent .. "}") or "}"
local open_bracket = pretty and "[\n" or "["
local close_bracket = pretty and ("\n" .. close_indent .. "]") or "]"
-- Circular reference?
if stack[val] then error("circular reference") end
stack[val] = true
if rawget(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 _, v in ipairs(val) do
state.currentIndentLevel = state.currentIndentLevel + 1
table.insert(res, make_indent(state) .. encode(v, state))
state.currentIndentLevel = state.currentIndentLevel - 1
end
stack[val] = nil
return open_bracket .. table.concat(res, comma) .. close_bracket
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
state.currentIndentLevel = state.currentIndentLevel + 1
table.insert(res, make_indent(state) .. encode(k, state) .. colon .. encode(v, state))
state.currentIndentLevel = state.currentIndentLevel - 1
end
stack[val] = nil
return open_brace .. table.concat(res, comma) .. close_brace
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, state)
local t = type(val)
local f = type_func_map[t]
if f then
return f(val, state)
end
error("unexpected type '" .. t .. "'")
end
function json.encode(val, indent)
local state = {
indent = indent or 0,
currentIndentLevel = 0,
stack = {}
}
return encode(val, state)
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
--
-- json.lua
--
-- Copyright (c) 2019 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 make_indent(state)
return string.rep(" ", state.currentIndentLevel * state.indent)
end
local function escape_char(c)
return escape_char_map[c] or string.format("\\u%04x", c:byte())
end
local function encode_nil()
return "null"
end
local function encode_table(val, state)
local res = {}
local stack = state.stack
local pretty = state.indent > 0
local close_indent = make_indent(state)
local comma = pretty and ",\n" or ","
local colon = pretty and ": " or ":"
local open_brace = pretty and "{\n" or "{"
local close_brace = pretty and ("\n" .. close_indent .. "}") or "}"
local open_bracket = pretty and "[\n" or "["
local close_bracket = pretty and ("\n" .. close_indent .. "]") or "]"
-- Circular reference?
if stack[val] then error("circular reference") end
stack[val] = true
if rawget(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 _, v in ipairs(val) do
state.currentIndentLevel = state.currentIndentLevel + 1
table.insert(res, make_indent(state) .. encode(v, state))
state.currentIndentLevel = state.currentIndentLevel - 1
end
stack[val] = nil
return open_bracket .. table.concat(res, comma) .. close_bracket
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
state.currentIndentLevel = state.currentIndentLevel + 1
table.insert(res, make_indent(state) .. encode(k, state) .. colon .. encode(v, state))
state.currentIndentLevel = state.currentIndentLevel - 1
end
stack[val] = nil
return open_brace .. table.concat(res, comma) .. close_brace
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, state)
local t = type(val)
local f = type_func_map[t]
if f then
return f(val, state)
end
error("unexpected type '" .. t .. "'")
end
function json.encode(val, indent)
local state = {
indent = indent or 0,
currentIndentLevel = 0,
stack = {}
}
return encode(val, state)
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,43 +1,43 @@
function __genOrderedIndex( t )
local orderedIndex = {}
for key in pairs(t) do
table.insert( orderedIndex, key )
end
table.sort( orderedIndex )
return orderedIndex
end
function orderedNext(t, state)
-- Equivalent of the next function, but returns the keys in the alphabetic
-- order. We use a temporary ordered key table that is stored in the
-- table being iterated.
local key = nil
--print("orderedNext: state = "..tostring(state) )
if state == nil then
-- the first time, generate the index
t.__orderedIndex = __genOrderedIndex( t )
key = t.__orderedIndex[1]
else
-- fetch the next value
for i = 1,table.getn(t.__orderedIndex) do
if t.__orderedIndex[i] == state then
key = t.__orderedIndex[i+1]
end
end
end
if key then
return key, t[key]
end
-- no more value to return, cleanup
t.__orderedIndex = nil
return
end
function orderedPairs(t)
-- Equivalent of the pairs() function on tables. Allows to iterate
-- in order
return orderedNext, t, nil
function __genOrderedIndex( t )
local orderedIndex = {}
for key in pairs(t) do
table.insert( orderedIndex, key )
end
table.sort( orderedIndex )
return orderedIndex
end
function orderedNext(t, state)
-- Equivalent of the next function, but returns the keys in the alphabetic
-- order. We use a temporary ordered key table that is stored in the
-- table being iterated.
local key = nil
--print("orderedNext: state = "..tostring(state) )
if state == nil then
-- the first time, generate the index
t.__orderedIndex = __genOrderedIndex( t )
key = t.__orderedIndex[1]
else
-- fetch the next value
for i = 1,table.getn(t.__orderedIndex) do
if t.__orderedIndex[i] == state then
key = t.__orderedIndex[i+1]
end
end
end
if key then
return key, t[key]
end
-- no more value to return, cleanup
t.__orderedIndex = nil
return
end
function orderedPairs(t)
-- Equivalent of the pairs() function on tables. Allows to iterate
-- in order
return orderedNext, t, nil
end

View File

@ -139,7 +139,12 @@ function UIMiniWindow:setup()
local oldParent = self:getParent()
local settings = g_settings.getNode('MiniWindows')
local settings = {}
if g_settings.getNodeSize('MiniWindows') < 100 then
settings = g_settings.getNode('MiniWindows')
end
if settings then
local selfSettings = settings[self:getId()]
if selfSettings then
@ -184,7 +189,7 @@ function UIMiniWindow:setup()
self.miniLoaded = true
if self.save then
if oldParent and oldParent:getClassName() == 'UIMiniWindowContainer' then
if oldParent and oldParent:getClassName() == 'UIMiniWindowContainer' and not self.containerWindow then
addEvent(function() oldParent:order() end)
end
if newParent and newParent:getClassName() == 'UIMiniWindowContainer' and newParent ~= oldParent then

View File

@ -1,7 +0,0 @@
-- main tab
UI.Label("Vithrax CFG v1.2 \n \n Scripting Service: \n Vithrax#5814")
UI.Separator()

View File

@ -1,875 +0,0 @@
-- lib ver 1.41
-- Author: Vithrax
-- contains mostly basic function shortcuts and code shorteners
function isBuffed()
local var = false
for i=1,4 do
if (player:getSkillLevel(i) - player:getSkillBaseLevel(i)) > 5 and (4*(player:getSkillLevel(i) - player:getSkillBaseLevel(i))) < player:getSkillLevel(i) then
var = true
end
end
return var
end
function killsToRs()
return math.min(g_game.getUnjustifiedPoints().killsDayRemaining, g_game.getUnjustifiedPoints().killsWeekRemaining, g_game.getUnjustifiedPoints().killsMonthRemaining)
end
function canCast(spell)
if not spell then return end
if not getSpellData(spell) then return true end
if not getSpellCoolDown(spell) and mana() >= getSpellData(spell).manaCost and level() >= getSpellData(spell).level then
return true
else
return false
end
end
function getSpellData(spell)
if not spell then return false end
if Spells[spell] then
return Spells[spell]
else
return false
end
end
Spells = {
["adana ani"] = {level = 54, manaCost = 1400},
["adana mort"] = {level = 27, manaCost = 600},
["adana pox"] = {level = 15, manaCost = 200},
["adeta sio"] = {level = 16, manaCost = 200},
["adevo grav flam"] = {level = 15, manaCost = 240},
["adevo grav pox"] = {level = 14, manaCost = 200},
["adevo grav tera"] = {level = 32, manaCost = 750},
["adevo grav vis"] = {level = 18, manaCost = 320},
["adevo grav vita"] = {level = 27, manaCost = 600},
["adevo ina"] = {level = 27, manaCost = 600},
["adevo mas flam"] = {level = 27, manaCost = 600},
["adevo mas grav flam"] = {level = 33, manaCost = 780},
["adevo mas grav pox"] = {level = 29, manaCost = 640},
["adevo mas grav vis"] = {level = 41, manaCost = 1000},
["adevo mas hur"] = {level = 31, manaCost = 570},
["adevo mas pox"] = {level = 25, manaCost = 520},
["adevo mas vis"] = {level = 37, manaCost = 880},
["adevo res flam"] = {level = 27, manaCost = 420},
["adito grav"] = {level = 17, manaCost = 120},
["adito tera"] = {level = 21, manaCost = 200},
["adori dis min vis"] = {level = 1, manaCost = 5},
["adori flam"] = {level = 27, manaCost = 460},
["adori frigo"] = {level = 28, manaCost = 460},
["adori gran mort"] = {level = 45, manaCost = 985},
["adori mas flam"] = {level = 30, manaCost = 530},
["adori mas frigo"] = {level = 30, manaCost = 530},
["adori mas tera"] = {level = 28, manaCost = 430},
["adori mas vis"] = {level = 28, manaCost = 430},
["adori min vis"] = {level = 15, manaCost = 120},
["adori san"] = {level = 27, manaCost = 300},
["adori tera"] = {level = 24, manaCost = 350},
["adori vis"] = {level = 25, manaCost = 350},
["adura gran"] = {level = 15, manaCost = 120},
["adura vita"] = {level = 24, manaCost = 400},
["exana flam"] = {level = 30, manaCost = 30},
["exana ina"] = {level = 26, manaCost = 200},
["exana kor"] = {level = 45, manaCost = 30},
["exana mort"] = {level = 80, manaCost = 40},
["exana pox"] = {level = 10, manaCost = 30},
["exana vis"] = {level = 22, manaCost = 30},
["exani tera"] = {level = 9, manaCost = 20},
["exeta con"] = {level = 45, manaCost = 350},
["exeta res"] = {level = 20, manaCost = 40},
["exevo con"] = {level = 13, manaCost = 100},
["exevo con flam"] = {level = 25, manaCost = 290},
["exevo dis flam hur"] = {level = 1, manaCost = 5},
["exevo flam hur"] = {level = 18, manaCost = 25},
["exevo frigo hur"] = {level = 18, manaCost = 25},
["exevo gran con hur"] = {level = 150, manaCost = 1000},
["exevo gran con vis"] = {level = 150, manaCost = 1000},
["exevo gran frigo hur"] = {level = 40, manaCost = 170},
["exevo gran mas flam"] = {level = 60, manaCost = 1100},
["exevo gran mas frigo"] = {level = 60, manaCost = 1050},
["exevo gran mas tera"] = {level = 55, manaCost = 700},
["exevo gran mas vis"] = {level = 55, manaCost = 600},
["exevo gran mort"] = {level = 41, manaCost = 250},
["exevo gran vis lux"] = {level = 29, manaCost = 110},
["exevo infir con"] = {level = 1, manaCost = 10},
["exevo infir flam hur"] = {level = 1, manaCost = 8},
["exevo infir frigo hur"] = {level = 1, manaCost = 8},
["exevo mas san"] = {level = 50, manaCost = 160},
["exevo pan"] = {level = 14, manaCost = 120},
["exevo tera hur"] = {level = 38, manaCost = 210},
["exevo vis hur"] = {level = 38, manaCost = 170},
["exevo vis lux"] = {level = 23, manaCost = 40},
["exori"] = {level = 35, manaCost = 115},
["exori amp vis"] = {level = 55, manaCost = 60},
["exori con"] = {level = 23, manaCost = 25},
["exori flam"] = {level = 14, manaCost = 20},
["exori frigo"] = {level = 15, manaCost = 20},
["exori gran"] = {level = 90, manaCost = 340},
["exori gran con"] = {level = 90, manaCost = 55},
["exori gran flam"] = {level = 70, manaCost = 60},
["exori gran frigo"] = {level = 80, manaCost = 60},
["exori gran ico"] = {level = 110, manaCost = 300},
["exori gran tera"] = {level = 70, manaCost = 60},
["exori gran vis"] = {level = 80, manaCost = 60},
["exori hur"] = {level = 28, manaCost = 40},
["exori ico"] = {level = 16, manaCost = 30},
["exori infir tera"] = {level = 1, manaCost = 6},
["exori infir vis"] = {level = 1, manaCost = 6},
["exori mas"] = {level = 33, manaCost = 160},
["exori max flam"] = {level = 90, manaCost = 100},
["exori max frigo"] = {level = 100, manaCost = 100},
["exori max tera"] = {level = 90, manaCost = 100},
["exori max vis"] = {level = 100, manaCost = 100},
["exori min"] = {level = 70, manaCost = 200},
["exori min flam"] = {level = 8, manaCost = 6},
["exori moe ico"] = {level = 16, manaCost = 20},
["exori mort"] = {level = 16, manaCost = 20},
["exori san"] = {level = 40, manaCost = 20},
["exori tera"] = {level = 13, manaCost = 20},
["exori vis"] = {level = 12, manaCost = 20},
["exura"] = {level = 8, manaCost = 20},
["exura dis"] = {level = 1, manaCost = 5},
["exura gran"] = {level = 20, manaCost = 70},
["exura gran ico"] = {level = 80, manaCost = 200},
["exura gran mas res"] = {level = 36, manaCost = 150},
["exura gran san"] = {level = 60, manaCost = 210},
["exura ico"] = {level = 8, manaCost = 40},
["exura infir"] = {level = 1, manaCost = 6},
["exura infir ico"] = {level = 1, manaCost = 10},
["exura san"] = {level = 35, manaCost = 160},
["exura vita"] = {level = 30, manaCost = 160},
["utamo mas sio"] = {level = 32, manaCost = 0},
["utamo tempo"] = {level = 55, manaCost = 200},
["utamo tempo san"] = {level = 55, manaCost = 400},
["utamo vita"] = {level = 14, manaCost = 50},
["utana vid"] = {level = 35, manaCost = 440},
["utani gran hur"] = {level = 20, manaCost = 100},
["utani hur"] = {level = 14, manaCost = 60},
["utani tempo hur"] = {level = 25, manaCost = 100},
["utevo gran lux"] = {level = 13, manaCost = 60},
["utevo gran res dru"] = {level = 200, manaCost = 3000},
["utevo gran res eq"] = {level = 200, manaCost = 1000},
["utevo gran res sac"] = {level = 200, manaCost = 2000},
["utevo gran res ven"] = {level = 200, manaCost = 3000},
["utevo lux"] = {level = 8, manaCost = 20},
["utevo vis lux"] = {level = 26, manaCost = 140},
["utito mas sio"] = {level = 32, manaCost = 0},
["utito tempo"] = {level = 60, manaCost = 290},
["utito tempo san"] = {level = 60, manaCost = 450},
["utori flam"] = {level = 26, manaCost = 30},
["utori kor"] = {level = 40, manaCost = 30},
["utori mas sio"] = {level = 32, manaCost = 0},
["utori mort"] = {level = 75, manaCost = 30},
["utori pox"] = {level = 50, manaCost = 30},
["utori san"] = {level = 70, manaCost = 30},
["utori vis"] = {level = 34, manaCost = 30},
["utura"] = {level = 50, manaCost = 75},
["utura gran"] = {level = 100, manaCost = 165},
["utura mas sio"] = {level = 32, manaCost = 0}
}
function getSpellCoolDown(text)
if not text then return false end
if text:lower() == "exura" then
return modules.game_cooldown.isCooldownIconActive(1)
elseif text:lower() == "exura gran" then
return modules.game_cooldown.isCooldownIconActive(2)
elseif text:lower() == "exura vita" then
return modules.game_cooldown.isCooldownIconActive(3)
elseif text:lower() == "exura gran mas res" then
return modules.game_cooldown.isCooldownIconActive(82)
elseif string.find(text:lower(), "exura sio") then
return modules.game_cooldown.isCooldownIconActive(84)
elseif string.find(text:lower(), "exiva") then
return modules.game_cooldown.isCooldownIconActive(20)
elseif string.find(text:lower(), "exani hur") then
return modules.game_cooldown.isCooldownIconActive(81)
elseif string.find(text:lower(), "utevo res ina") then
return modules.game_cooldown.isCooldownIconActive(38)
elseif string.find(text:lower(), 'utevo res "' ) then
return modules.game_cooldown.isCooldownIconActive(9)
elseif text:lower() == "exana pox" then
return modules.game_cooldown.isCooldownIconActive(29)
elseif text:lower() == "utevo lux" then
return modules.game_cooldown.isCooldownIconActive(10)
elseif text:lower() == "exani tera" then
return modules.game_cooldown.isCooldownIconActive(76)
elseif text:lower() == "exori vis" then
return modules.game_cooldown.isCooldownIconActive(88)
elseif text:lower() == "utevo gran lux" then
return modules.game_cooldown.isCooldownIconActive(11)
elseif text:lower() == "utani hur" then
return modules.game_cooldown.isCooldownIconActive(6)
elseif text:lower() == "exori tera" then
return modules.game_cooldown.isCooldownIconActive(113)
elseif text:lower() == "exevo pan" then
return modules.game_cooldown.isCooldownIconActive(42)
elseif text:lower() == "utamo vita" then
return modules.game_cooldown.isCooldownIconActive(44)
elseif text:lower() == "exori flam" then
return modules.game_cooldown.isCooldownIconActive(89)
elseif text:lower() == "exori frigo" then
return modules.game_cooldown.isCooldownIconActive(112)
elseif text:lower() == "exori moe ico" then
return modules.game_cooldown.isCooldownIconActive(148)
elseif text:lower() == "exevo frigo hur" then
return modules.game_cooldown.isCooldownIconActive(121)
elseif text:lower() == "utani gran hur" then
return modules.game_cooldown.isCooldownIconActive(39)
elseif text:lower() == "exana vis" then
return modules.game_cooldown.isCooldownIconActive(146)
elseif text:lower() == "utevo vis lux" then
return modules.game_cooldown.isCooldownIconActive(75)
elseif text:lower() == "exana flam" then
return modules.game_cooldown.isCooldownIconActive(145)
elseif text:lower() == "utana vid" then
return modules.game_cooldown.isCooldownIconActive(45)
elseif text:lower() == "exevo tera hur" then
return modules.game_cooldown.isCooldownIconActive(120)
elseif text:lower() == "exevo gran frigo hur" then
return modules.game_cooldown.isCooldownIconActive(43)
elseif text:lower() == "exana kor" then
return modules.game_cooldown.isCooldownIconActive(144)
elseif text:lower() == "utori pox" then
return modules.game_cooldown.isCooldownIconActive(142)
elseif text:lower() == "exevo gran mas tera" then
return modules.game_cooldown.isCooldownIconActive(56)
elseif text:lower() == "exevo gran mas frigo" then
return modules.game_cooldown.isCooldownIconActive(118)
elseif text:lower() == "exevo gran mas tera" then
return modules.game_cooldown.isCooldownIconActive(56)
elseif text:lower() == "exori gran tera" then
return modules.game_cooldown.isCooldownIconActive(153)
elseif text:lower() == "exori max tera" then
return modules.game_cooldown.isCooldownIconActive(157)
elseif text:lower() == "exori gran frigo" then
return modules.game_cooldown.isCooldownIconActive(152)
elseif text:lower() == "exori max frigo" then
return modules.game_cooldown.isCooldownIconActive(156)
elseif text:lower() == "exori max tera" then
return modules.game_cooldown.isCooldownIconActive(157)
elseif text:lower() == "exori con" then
return modules.game_cooldown.isCooldownIconActive(111)
elseif text:lower() == "exura san" then
return modules.game_cooldown.isCooldownIconActive(125)
elseif text:lower() == "exevo mas san" then
return modules.game_cooldown.isCooldownIconActive(124)
elseif text:lower() == "utura" then
return modules.game_cooldown.isCooldownIconActive(159)
elseif text:lower() == "utura gran" then
return modules.game_cooldown.isCooldownIconActive(160)
elseif text:lower() == "utamo tempo san" then
return modules.game_cooldown.isCooldownIconActive(134)
elseif text:lower() == "utito tempo san" then
return modules.game_cooldown.isCooldownIconActive(135)
elseif text:lower() == "exura gran san" then
return modules.game_cooldown.isCooldownIconActive(36)
elseif text:lower() == "utori san" then
return modules.game_cooldown.isCooldownIconActive(143)
elseif text:lower() == "exana mort" then
return modules.game_cooldown.isCooldownIconActive(147)
elseif text:lower() == "exori gran con" then
return modules.game_cooldown.isCooldownIconActive(57)
elseif text:lower() == "exura ico" then
return modules.game_cooldown.isCooldownIconActive(123)
elseif text:lower() == "exeta res" then
return modules.game_cooldown.isCooldownIconActive(93)
elseif text:lower() == "utani tempo hur" then
return modules.game_cooldown.isCooldownIconActive(131)
elseif text:lower() == "utamo tempo" then
return modules.game_cooldown.isCooldownIconActive(132)
elseif text:lower() == "utito tempo" then
return modules.game_cooldown.isCooldownIconActive(133)
elseif text:lower() == "exura gran ico" then
return modules.game_cooldown.isCooldownIconActive(158)
elseif text:lower() == "exori hur" then
return modules.game_cooldown.isCooldownIconActive(107)
elseif text:lower() == "exori ico" then
return modules.game_cooldown.isCooldownIconActive(61)
elseif text:lower() == "exori" then
return modules.game_cooldown.isCooldownIconActive(80)
elseif text:lower() == "exori mas" then
return modules.game_cooldown.isCooldownIconActive(106)
elseif text:lower() == "exori gran" then
return modules.game_cooldown.isCooldownIconActive(105)
elseif text:lower() == "exori gran ico" then
return modules.game_cooldown.isCooldownIconActive(62)
elseif text:lower() == "exori min" then
return modules.game_cooldown.isCooldownIconActive(59)
elseif text:lower() == "exevo gran mas flam" then
return modules.game_cooldown.isCooldownIconActive(24)
elseif text:lower() == "exevo gran mas vis" then
return modules.game_cooldown.isCooldownIconActive(119)
elseif text:lower() == "exevo vis hur" then
return modules.game_cooldown.isCooldownIconActive(13)
elseif text:lower() == "exevo vis lux" then
return modules.game_cooldown.isCooldownIconActive(22)
elseif text:lower() == "exevo gran vis lux" then
return modules.game_cooldown.isCooldownIconActive(23)
elseif text:lower() == "exori amp vis" then
return modules.game_cooldown.isCooldownIconActive(149)
elseif text:lower() == "exori gran vis" then
return modules.game_cooldown.isCooldownIconActive(151)
elseif text:lower() == "exori gran flam" then
return modules.game_cooldown.isCooldownIconActive(150)
elseif text:lower() == "exori max vis" then
return modules.game_cooldown.isCooldownIconActive(155)
elseif text:lower() == "exori max flam" then
return modules.game_cooldown.isCooldownIconActive(154)
elseif text:lower() == "exevo gran flam hur" then
return modules.game_cooldown.isCooldownIconActive(150)
else
return false
end
end
storage.isUsing = false
onUse(function(pos, itemId, stackPos, subType)
if pos.x < 65000 then
storage.isUsing = true
end
schedule(1500, function() storage.isUsing = false end)
end)
function string.starts(String,Start)
return string.sub(String,1,string.len(Start))==Start
end
function isFriend(name)
if not name then return false end
if getCreatureByName(name, true):isPlayer() and not getCreatureByName(name, true):isLocalPlayer() and table.find(storage.playerList.friendList, name) or string.find(storage.serverMembers, name) or table.find(storage.playerList.friendList, name:lower()) or (storage.playerList.groupMembers and ((getCreatureByName(name, true):getShield() >= 3 and getCreatureByName(name, true):getShield() <= 10) or getCreatureByName(name, true):getEmblem() == 2)) then
return true
else
return false
end
end
function isEnemy(name)
if not name then return false end
if getCreatureByName(name, true):isPlayer() and not getCreatureByName(name, true):isLocalPlayer() and table.find(storage.playerList.enemyList, name) or table.find(storage.playerList.enemyList, name:lower()) or (storage.playerList.marks and not isFriend(name)) then
return true
else
return false
end
end
function isAttSpell(expr)
if string.starts(expr, "exori") or string.starts(expr, "exevo") then
return true
else
return false
end
end
function getPlayerByName(name)
if not name then
return false
end
local creature
for i, spec in pairs(getSpectators()) do
if spec:isPlayer() and spec:getName():lower() == name:lower() then
creature = spec
end
end
if creature then
return creature
end
end
function getActiveItemId(id)
if not id then
return false
end
if id == 3049 then
return 3086
elseif id == 3050 then
return 3087
elseif id == 3051 then
return 3088
elseif id == 3052 then
return 3089
elseif id == 3053 then
return 3090
elseif id == 3091 then
return 3094
elseif id == 3092 then
return 3095
elseif id == 3093 then
return 3096
elseif id == 3097 then
return 3099
elseif id == 3098 then
return 3100
elseif id == 16114 then
return 16264
elseif id == 23531 then
return 23532
elseif id == 23533 then
return 23534
elseif id == 23529 then
return 23530
else
return id
end
end
function getInactiveItemId(id)
if not id then
return false
end
if id == 3086 then
return 3049
elseif id == 3087 then
return 3050
elseif id == 3088 then
return 3051
elseif id == 3089 then
return 3052
elseif id == 3090 then
return 3053
elseif id == 3094 then
return 3091
elseif id == 3095 then
return 3092
elseif id == 3096 then
return 3093
elseif id == 3099 then
return 3097
elseif id == 3100 then
return 3098
elseif id == 16264 then
return 16114
elseif id == 23532 then
return 23531
elseif id == 23534 then
return 23533
elseif id == 23530 then
return 23529
else
return id
end
end
function getMonstersInRange(pos, range)
if not pos or not range then
return false
end
local monsters = 0
for i, spec in pairs(getSpectators()) do
if spec:isMonster() and spec:getType() ~= 3 and getDistanceBetween(pos, spec:getPosition()) < range then
monsters = monsters + 1
end
end
return monsters
end
function distanceFromPlayer(coords)
if not coords then
return false
end
return getDistanceBetween(pos(), coords)
end
function getMonsters(range, multifloor)
if not range then
range = 10
end
local mobs = 0;
for _, spec in pairs(getSpectators(multifloor)) do
mobs = spec:getType() ~= 3 and spec:isMonster() and distanceFromPlayer(spec:getPosition()) <= range and mobs + 1 or mobs;
end
return mobs;
end
function getPlayers(range, multifloor)
if not range then
range = 10
end
local specs = 0;
for _, spec in pairs(getSpectators(multifloor)) do
specs = not spec:isLocalPlayer() and spec:isPlayer() and distanceFromPlayer(spec:getPosition()) <= range and not ((spec:getShield() >= 3 and spec:getShield() <= 10) or spec:getEmblem() == 1) and specs + 1 or specs;
end
return specs;
end
function isSafe(range, multifloor, padding)
local onSame = 0
local onAnother = 0
if not multifloor and padding then
multifloor = false
padding = false
end
for _, spec in pairs(getSpectators(multifloor)) do
if spec:isPlayer() and not spec:isLocalPlayer() and not isFriend(spec:getName()) then
if spec:getPosition().z == posz() and distanceFromPlayer(spec:getPosition()) <= range then
onSame = onSame + 1
end
if multifloor and padding and spec:getPosition().z ~= posz() and distanceFromPlayer(spec:getPosition()) <= (range + padding) then
onAnother = onAnother + 1
end
end
end
if onSame + onAnother > 0 then
return false
else
return true
end
end
function getAllPlayers(range, multifloor)
if not range then
range = 10
end
local specs = 0;
for _, spec in pairs(g_map.getSpectators(multifloor)) do
specs = not spec:isLocalPlayer() and spec:isPlayer() and distanceFromPlayer(spec:getPosition()) <= range and specs + 1 or specs;
end
return specs;
end
function getNpcs(range, multifloor)
if not range then
range = 10
end
local npcs = 0;
for _, spec in pairs(g_map.getSpectators(multifloor)) do
npcs = spec:isNpc() and distanceFromPlayer(spec:getPosition()) <= range and npcs + 1 or npcs;
end
return npcs;
end
function itemAmount(id)
local totalItemCount = 0
for _, container in pairs(getContainers()) do
for _, item in ipairs(container:getItems()) do
totalItemCount = item:getId() == id and totalItemCount + item:getCount() or totalItemCount
end
end
if getHead() and getHead():getId() == id then
totalItemCount = totalItemCount + getHead():getCount()
end
if getNeck() and getNeck():getId() == id then
totalItemCount = totalItemCount + getNeck():getCount()
end
if getBack() and getBack():getId() == id then
totalItemCount = totalItemCount + getBack():getCount()
end
if getBody() and getBody():getId() == id then
totalItemCount = totalItemCount + getBody():getCount()
end
if getRight() and getRight():getId() == id then
totalItemCount = totalItemCount + getRight():getCount()
end
if getLeft() and getLeft():getId() == id then
totalItemCount = totalItemCount + getLeft():getCount()
end
if getLeg() and getLeg():getId() == id then
totalItemCount = totalItemCount + getLeg():getCount()
end
if getFeet() and getFeet():getId() == id then
totalItemCount = totalItemCount + getFeet():getCount()
end
if getFinger() and getFinger():getId() == id then
totalItemCount = totalItemCount + getFinger():getCount()
end
if getAmmo() and getAmmo():getId() == id then
totalItemCount = totalItemCount + getAmmo():getCount()
end
return totalItemCount
end
function cordsToPos(x, y, z)
if not x or not y or not z then
return false
end
local tilePos = pos()
tilePos.x = x
tilePos.y = y
tilePos.z = z
return tilePos
end
function reachGroundItem(id)
local targetTile
for _, tile in ipairs(g_map.getTiles(posz())) do
if tile:getTopUseThing():getId() == id then
targetTile = tile:getPosition()
end
end
if distanceFromPlayer(targetTile) > 1 then
if CaveBot.walkTo(targetTile, 10, {ignoreNonPathable = true, precision=1}) then
delay(200)
end
else
return true
end
end
function useGroundItem(id)
if not id then
return false
end
local targetTile = nil
for _, tile in ipairs(g_map.getTiles(posz())) do
if tile:getTopUseThing():getId() == id then
targetTile = tile:getPosition()
end
end
if targetTile then
if distanceFromPlayer(targetTile) > 1 then
if CaveBot.walkTo(targetTile, 20, {ignoreNonWalkable = true, ignoreNonPathable = true, precision=1}) then
delay(200)
end
else
g_game.use(g_map.getTile(targetTile):getTopUseThing())
return true
end
else
return "retry"
end
end
function target()
if not g_game.isAttacking() then
return
else
return g_game.getAttackingCreature()
end
end
function getTarget()
return target()
end
function targetPos(dist)
if not g_game.isAttacking() then
return
end
if dist then
return distanceFromPlayer(target():getPosition())
else
return target():getPosition()
end
end
-- for gunzodus
function reopenPurse()
schedule(100, function() g_game.open(findItem(23721)) return true end)
schedule(1400, function() g_game.open(findItem(23721)) return true end)
CaveBot.delay(1500)
return true
end
-- getSpectator patterns
function getCreaturesInArea(param1, param2, param3)
-- param1 - pos/creature
-- param2 - pattern
-- param3 - type of return
-- 1 - everyone, 2 - monsters, 3 - players
local specs = 0
local monsters = 0
local players = 0
for i, spec in pairs(getSpectators(param1, param2)) do
if spec ~= player then
specs = specs + 1
if spec:isMonster() then
monsters = monsters + 1
elseif spec:isPlayer() and not isFriend(spec:getName()) then
players = players +1
end
end
end
if param3 == 1 then
return specs
elseif param3 == 2 then
return monsters
else
return players
end
end
function getBestTileByPatern(pattern, specType, maxDist, safe)
if not pattern or not specType then return end
if not maxDist then maxDist = 4 end
if not safe then safe = false end
local fieldList = {}
local bestTile = nil
-- best area tile to use
for _, tile in pairs(g_map.getTiles(posz())) do
if tile:canShoot() and distanceFromPlayer(tile:getPosition()) <= maxDist and tile:isWalkable() and getCreaturesInArea(tile:getPosition(), pattern, specType) > 0 and (not safe or getCreaturesInArea(tile:getPosition(), pattern, 3) == 0) then
table.insert(fieldList, {pos = tile, count = getCreaturesInArea(tile:getPosition(), pattern, specType)})
end
end
table.sort(fieldList, function(a,b) return a.count > b.count end)
bestTile = fieldList[1]
if bestTile then
return bestTile
else
return false
end
end
LargeUeArea = [[
0000001000000
0000011100000
0000111110000
0001111111000
0011111111100
0111111111110
1111111111111
0111111111110
0011111111100
0001111111000
0000111110000
0000011100000
0000001000000
]]
NormalUeAreaMs = [[
00000100000
00011111000
00111111100
01111111110
01111111110
11111111111
01111111110
01111111110
00111111100
00001110000
00000100000
]]
NormalUeAreaEd = [[
00000100000
00001110000
00011111000
00111111100
01111111110
11111111111
01111111110
00111111100
00011111000
00001110000
00000100000
]]
smallUeArea = [[
0011100
0111110
1111111
1111111
1111111
0111110
0011100
]]
largeRuneArea = [[
0011100
0111110
1111111
1111111
1111111
0111110
0011100
]]
adjacentArea = [[
111
101
111
]]
longBeamArea = [[
0000000N0000000
0000000N0000000
0000000N0000000
0000000N0000000
0000000N0000000
0000000N0000000
0000000N0000000
WWWWWWW0EEEEEEE
0000000S0000000
0000000S0000000
0000000S0000000
0000000S0000000
0000000S0000000
0000000S0000000
0000000S0000000
]]
shortBeamArea = [[
00000100000
00000100000
00000100000
00000100000
00000100000
EEEEE0WWWWW
00000S00000
00000S00000
00000S00000
00000S00000
00000S00000
]]
newWaveArea = [[
000NNNNN000
000NNNNN000
0000NNN0000
WW00NNN00EE
WWWW0N0EEEE
WWWWW0EEEEE
WWWW0S0EEEE
WW00SSS00EE
0000SSS0000
000SSSSS000
000SSSSS000
]]
bigWaveArea = [[
0000NNN0000
0000NNN0000
0000NNN0000
00000N00000
WWW00N00EEE
WWWWW0EEEEE
WWW00S00EEE
00000S00000
0000SSS0000
0000SSS0000
0000SSS0000
]]
smallWaveArea = [[
00NNN00
00NNN00
WW0N0EE
WWW0EEE
WW0S0EE
00SSS00
00SSS00
]]
diamondArrowArea = [[
01110
11111
11111
11111
01110
]]

View File

@ -1,375 +0,0 @@
local analyserPanelName = "AnalysersPanel"
local ui = setupUI([[
Panel
height: 18
Button
id: analyzersMain
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
height: 18
text: Hunt Analysers
]], parent)
ui:setId(analyserPanelName)
if not storage[analyserPanelName] then
storage[analyserPanelName] = {
bestHit = 0,
bestHeal = 0,
lootItems = {}
}
end
analyzersWindow = g_ui.createWidget('MainAnalyzer', modules.game_interface.getRightPanel())
huntWindow = g_ui.createWidget('HuntAnalyser', modules.game_interface.getRightPanel())
impactWindow = g_ui.createWidget('ImpactAnalyser', modules.game_interface.getRightPanel())
lootWindow = g_ui.createWidget('LootAnalyser', modules.game_interface.getRightPanel())
xpWindow = g_ui.createWidget('XpAnalyser', modules.game_interface.getRightPanel())
analyzersWindow:setup()
huntWindow:setup()
impactWindow:setup()
lootWindow:setup()
xpWindow:setup()
rootWidget = g_ui.getRootWidget()
lootListWindow = g_ui.createWidget('LootWindow', rootWidget)
lootListWindow:hide()
function refresh()
analyzersWindow:setContentMinimumHeight(105)
analyzersWindow:setContentMaximumHeight(105)
huntWindow:setContentMinimumHeight(30)
impactWindow:setContentMinimumHeight(30)
impactWindow:setContentMaximumHeight(185)
lootWindow:setContentMinimumHeight(30)
xpWindow:setContentMinimumHeight(30)
xpWindow:setContentMaximumHeight(65)
end
refresh()
function huntWindowToggle()
if huntWindow:isVisible() then
huntWindow:close()
else
huntWindow:open()
end
end
function impactWindowToggle()
if impactWindow:isVisible() then
impactWindow:close()
else
impactWindow:open()
end
end
function lootWindowToggle()
if lootWindow:isVisible() then
lootWindow:close()
else
lootWindow:open()
end
end
function xpWindowToggle()
if xpWindow:isVisible() then
xpWindow:close()
else
xpWindow:open()
end
end
ui.analyzersMain.onClick = function(widget)
if analyzersWindow:isVisible() then
analyzersWindow:close()
else
analyzersWindow:open()
end
end
lootWindow.contentsPanel.LootEdit.onClick = function(widget)
lootListWindow:show()
lootListWindow:raise()
lootListWindow:focus()
end
if storage[analyserPanelName].lootItems and #storage[analyserPanelName].lootItems > 0 then
for _, name in ipairs(storage[analyserPanelName].lootItems) do
local label = g_ui.createWidget("LootItemName", lootListWindow.LootList)
label.remove.onClick = function(widget)
table.removevalue(storage[analyserPanelName].lootItems, label:getText())
label:destroy()
end
label:setText(name)
end
end
lootListWindow.AddLoot.onClick = function(widget)
local lootName = lootListWindow.LootName:getText():lower()
if lootName:len() > 0 and not table.contains(storage[analyserPanelName].lootItems, lootName, true) then
table.insert(storage[analyserPanelName].lootItems, lootName)
local label = g_ui.createWidget("LootItemName", lootListWindow.LootList)
label.remove.onClick = function(widget)
table.removevalue(storage[analyserPanelName].lootItems, label:getText())
label:destroy()
end
label:setText(lootName)
lootListWindow.LootName:setText('')
end
end
lootListWindow.closeButton.onClick = function(widget)
lootListWindow:hide()
end
analyzersWindow.contentsPanel.HuntButton.onClick = function(widget)
huntWindowToggle()
end
analyzersWindow.contentsPanel.lootSupplyButton.onClick = function(widget)
lootWindowToggle()
end
analyzersWindow.contentsPanel.impactButton.onClick = function(widget)
impactWindowToggle()
end
analyzersWindow.contentsPanel.xpButton.onClick = function(widget)
xpWindowToggle()
end
local uptime
local launchTime = now
local startTime = now
function sessionTime()
uptime = math.floor((now - launchTime)/1000)
local hours = string.format("%02.f", math.floor(uptime/3600))
local mins = string.format("%02.f", math.floor(uptime/60 - (hours*60)))
return hours .. ":" .. mins .. "h"
end
local startExp = exp()
function expGained()
return exp() - startExp
end
function expForLevel(level)
return math.floor((50*level*level*level)/3 - 100*level*level + (850*level)/3 - 200)
end
function expH()
return (expGained() / (now - startTime))
end
function format_thousand(v)
if not v then return 0 end
local s = string.format("%d", math.floor(v))
local pos = string.len(s) % 3
if pos == 0 then pos = 3 end
return string.sub(s, 1, pos)
.. string.gsub(string.sub(s, pos+1), "(...)", ".%1")
end
function checkExpSpeed()
local player = g_game.getLocalPlayer()
if not player then return end
local currentExp = player:getExperience()
local currentTime = now/1000
if player.lastExps ~= nil then
player.expSpeed = (currentExp - player.lastExps[1][1])/(currentTime - player.lastExps[1][2])
else
player.lastExps = {}
end
table.insert(player.lastExps, {currentExp, currentTime})
if #player.lastExps > 30 then
table.remove(player.lastExps, 1)
end
return player.expSpeed
end
function nextLevelData(time)
if checkExpSpeed() ~= nil then
expPerHour = math.floor(checkExpSpeed() * 3600)
if expPerHour > 0 then
nextLevelExp = expForLevel(player:getLevel()+1)
hoursLeft = (nextLevelExp - player:getExperience()) / expPerHour
minutesLeft = math.floor((hoursLeft - math.floor(hoursLeft))*60)
hoursLeft = math.floor(hoursLeft)
timeLeft = tostring(hoursLeft .. ":" .. minutesLeft .. "h")
end
end
if time then
return expPerHour
else
return timeLeft
end
end
function sum(t)
local sum = 0
for k,v in pairs(t) do
sum = sum + v
end
return sum
end
local cumulatedDamage = 0
local cumulatedHealing = 0
local allHits = {}
local allHeals = {}
local dps
local hps
local kills = {}
local droppedItems = {}
onTextMessage(function(mode, text)
-- [[ kill counter ]] --
if string.find(text, "Loot of") then
local split = string.split(text, ":")
local mobName = string.split(split[1], "of ")[2]:trim()
table.insert(kills, mobName)
local killCount = {}
for i, entry in pairs(kills) do
if killCount[entry] then
killCount[entry] = killCount[entry] + 1
else
killCount[entry] = 1
end
end
for i, child in pairs(huntWindow.contentsPanel.MessagePanel:getChildren()) do
child:destroy()
end
for k,v in pairs(killCount) do
local label = g_ui.createWidget("MonsterLabel", huntWindow.contentsPanel.MessagePanel)
label:setText(v .. "x " .. k)
end
-- [[ loot counter ]] --
local monsterDrop = string.split(split[2], ",")
if #monsterDrop > 0 then
for i=1,#monsterDrop do
local drop = monsterDrop[i]:trim()
for i, entry in pairs(storage[analyserPanelName].lootItems) do
if string.match(drop, entry) then
local entryCount
if tonumber(string.match(drop, "%d+")) then
entryCount = tonumber(string.match(drop, "%d+"))
else
entryCount = 1
end
if droppedItems[entry] then
droppedItems[entry] = droppedItems[entry] + entryCount
else
droppedItems[entry] = entryCount
end
end
end
end
end
for i, child in pairs(lootWindow.contentsPanel.MessagePanel:getChildren()) do
child:destroy()
end
for k,v in pairs(droppedItems) do
local label = g_ui.createWidget("MonsterLabel", lootWindow.contentsPanel.MessagePanel)
label:setText(v .. "x " .. k)
end
end
-- damage
if string.find(text, "hitpoints due to your attack") then
table.insert(allHits, tonumber(string.match(text, "%d+")))
if dps then
if now - startTime > 1000 then
local dmgSum = sum(allHits)
dps = dmgSum
allHits = {}
startTime = now
end
else
dps = 0
end
local dmgValue = tonumber(string.match(text, "%d+"))
cumulatedDamage = cumulatedDamage + dmgValue
if storage[analyserPanelName].bestHit < dmgValue then
storage[analyserPanelName].bestHit = dmgValue
end
end
-- healing
if string.find(text, "You heal") then
table.insert(allHeals, tonumber(string.match(text, "%d+")))
if hps then
if now - startTime > 1000 then
local healSum = sum(allHeals)
hps = healSum
allHeals = {}
startTime = now
end
else
hps = 0
end
local healValue = tonumber(string.match(text, "%d+"))
cumulatedHealing = cumulatedHealing + healValue
if storage[analyserPanelName].bestHeal < healValue then
storage[analyserPanelName].bestHeal = healValue
end
end
-- [[ waste]] --
if string.find(text, "Using one of") then
local splitTwo = string.split(text, "Using one of")
if #splitTwo == 1 then
local itemAmount = string.match(splitTwo[1], "%d+")
end
end
end)
function hourVal(v)
if not v then return end
return (v/uptime)*3600
end
function expH()
return (expGained()/uptime)*3600
end
local lootWorth
macro(1000, function()
-- [[ profit ]] --
lootWorth = 0
for k, v in pairs(droppedItems) do
if lootitems[k] then
lootWorth = lootWorth + (lootitems[k]*v)
end
end
-- [[ Hunt Window ]] --
huntWindow.contentsPanel.sessionValue:setText(sessionTime())
huntWindow.contentsPanel.xpGainValue:setText(format_thousand(expGained()))
huntWindow.contentsPanel.xpHourValue:setText(format_thousand(expH()))
if cumulatedDamage then huntWindow.contentsPanel.damageValue:setText(format_thousand(cumulatedDamage)) end
if cumulatedHealing then huntWindow.contentsPanel.healingValue:setText(format_thousand(cumulatedHealing)) end
huntWindow.contentsPanel.damageHourValue:setText(format_thousand(hourVal(cumulatedDamage)))
huntWindow.contentsPanel.healingHourValue:setText(format_thousand(hourVal(cumulatedHealing)))
huntWindow.contentsPanel.lootValue:setText(format_thousand(lootWorth))
-- [[ XP Window ]] --
xpWindow.contentsPanel.xpValue:setText(format_thousand(expGained()))
xpWindow.contentsPanel.hourValue:setText(format_thousand(expH()))
if not nextLevelData() then xpWindow.contentsPanel.ttnlValue:setText("-") else xpWindow.contentsPanel.ttnlValue:setText(nextLevelData()) end
-- [[ Impact Window ]] --
if cumulatedDamage then impactWindow.contentsPanel.damageValue:setText(format_thousand(cumulatedDamage)) end
if dps then impactWindow.contentsPanel.maxDpsValue:setText(format_thousand(dps)) end
impactWindow.contentsPanel.allTimeHighValue:setText(format_thousand(storage[analyserPanelName].bestHit))
if cumulatedHealing then impactWindow.contentsPanel.healingValue:setText(format_thousand(cumulatedHealing)) end
if hps then impactWindow.contentsPanel.maxHpsValue:setText(format_thousand(hps)) end
impactWindow.contentsPanel.allTimeHighHealValue:setText(format_thousand(storage[analyserPanelName].bestHeal))
-- [[ Loot Window ]] --
lootWindow.contentsPanel.lootValue:setText(format_thousand(lootWorth))
lootWindow.contentsPanel.lootHourValue:setText(format_thousand(hourVal(lootWorth)))
end)

View File

@ -1,47 +0,0 @@
MainAnalyzer < MiniWindow
!text: tr('Analytics Selector')
height: 125
icon: /images/topbuttons/analyzers
&autoOpen: false
MiniWindowContents
Button
id: HuntButton
!text: tr('Hunting Session Analyser')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
margin-top: 3
margin-left: 3
margin-right: 3
Button
id: lootSupplyButton
!text: tr('Loot & Supplies Analyser')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
margin-right: 3
Button
id: impactButton
!text: tr('Impact Analyser')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
margin-right: 3
Button
id: xpButton
!text: tr('XP Analyser')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
margin-right: 3

View File

@ -1,3 +0,0 @@
macro(60000, function()
turn(math.random(0,3))
end)

View File

@ -1,296 +0,0 @@
MonsterLabel < Label
opacity: 0.87
text-offset: 2 0
focusable: false
height: 16
HuntAnalyser < MiniWindow
!text: tr('Hunt Analyser')
height: 222
icon: /images/topbuttons/analyzers
&save: true
&autoOpen: false
MiniWindowContents
Label
id: session
!text: tr('Session:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
margin-top: 3
margin-left: 3
margin-right: 3
BotLabel
id: sessionValue
!text: tr('00:00h')
anchors.right: parent.right
anchors.verticalCenter: session.verticalCenter
margin-left: 3
margin-right: 3
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: xpGain
!text: tr('XP Gain:')
anchors.left: parent.left
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
Label
id: xpGainValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: xpGain.verticalCenter
margin-right: 3
width: 110
text-align: right
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: xpHour
!text: tr('XP/h:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
margin-right: 3
Label
id: xpHourValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: xpHour.verticalCenter
margin-left: 3
width: 100
text-align: right
margin-right: 3
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: loot
!text: tr('Loot:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
margin-right: 3
Label
id: lootValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: loot.verticalCenter
margin-left: 3
margin-right: 3
width: 100
text-align: right
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: supplies
!text: tr('Supplies:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
margin-right: 3
Label
id: suppliesValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: supplies.verticalCenter
margin-left: 3
margin-right: 3
width: 110
text-align: right
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: balance
!text: tr('Balance:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
margin-right: 3
Label
id: balanceValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: balance.verticalCenter
margin-left: 3
margin-right: 3
width: 110
text-align: right
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: damage
!text: tr('Damage:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
margin-right: 3
Label
id: damageValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: damage.verticalCenter
margin-left: 3
margin-right: 3
width: 100
text-align: right
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: damageHour
!text: tr('Damage/h:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
margin-right: 3
Label
id: damageHourValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: damageHour.verticalCenter
margin-left: 3
margin-right: 3
width: 100
text-align: right
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: healing
!text: tr('Healing:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
margin-right: 3
Label
id: healingValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: healing.verticalCenter
margin-left: 3
margin-right: 3
width: 100
text-align: right
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: healingHour
!text: tr('Healing/h:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
margin-right: 3
Label
id: healingHourValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: healingHour.verticalCenter
margin-left: 3
margin-right: 3
width: 100
text-align: right
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: Label
anchors.top: prev.bottom
anchors.left: parent.left
margin-top: 10
margin-left: 3
!text: tr('Monsters Killed:')
TextList
id: MessagePanel
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 3
margin-left: 3
margin-right: 3
height: 400

View File

@ -1,195 +0,0 @@
ImpactAnalyser < MiniWindow
!text: tr('Impact Analyser')
height: 205
icon: /images/topbuttons/analyzers
&save: true
&autoOpen: false
MiniWindowContents
Label
id: damageCategory
!text: tr('Damage')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
margin-top: 5
height: 20
font: sans-bold-16px
text-align: center
margin-left: 3
margin-right: 3
Label
id: damageTotal
!text: tr('Total:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
margin-left: 3
margin-right: 3
Label
id: damageValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: damageTotal.verticalCenter
margin-left: 3
margin-right: 3
width: 100
text-align: right
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: maxDps
!text: tr('DPS:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
margin-right: 3
Label
id: maxDpsValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: maxDps.verticalCenter
margin-left: 3
margin-right: 3
width: 100
text-align: right
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: allTimeHigh
!text: tr('All-Time High:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
margin-right: 3
Label
id: allTimeHighValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: allTimeHigh.verticalCenter
margin-left: 3
margin-right: 3
width: 100
text-align: right
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: healingCategory
!text: tr('Healing')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 15
height: 20
font: sans-bold-16px
text-align: center
margin-left: 3
margin-right: 3
Label
id: healingTotal
!text: tr('Total:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
margin-left: 3
margin-right: 3
Label
id: healingValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: healingTotal.verticalCenter
margin-left: 3
margin-right: 3
width: 100
text-align: right
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: maxHps
!text: tr('HPS:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
margin-right: 3
Label
id: maxHpsValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: maxHps.verticalCenter
margin-left: 3
margin-right: 3
width: 100
text-align: right
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: allTimeHighHeal
!text: tr('All-Time High:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
margin-right: 3
Label
id: allTimeHighHealValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: allTimeHighHeal.verticalCenter
margin-left: 3
margin-right: 3
width: 100
text-align: right
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3

File diff suppressed because it is too large Load Diff

View File

@ -1,150 +0,0 @@
lootg=Label < Label
opacity: 0.87
text-offset: 2 0
focusable: false
height: 16
LootAnalyser < MiniWindow
!text: tr('Loot & Supplies')
height: 100
icon: /images/topbuttons/analyzers
&save: true
&autoOpen: false
MiniWindowContents
Button
id: LootEdit
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
margin-left: 10
margin-right: 10
margin-top: 5
height: 15
!text: tr('Edit Loot List')
Label
id: supply
!text: tr('Supplies:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
margin-left: 3
margin-right: 3
Label
id: supplyValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: supply.verticalCenter
margin-left: 3
margin-right: 3
width: 100
text-align: right
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: supplyHour
!text: tr('Supplies/h:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
margin-right: 3
Label
id: supplyHourValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: supplyHour.verticalCenter
margin-left: 3
margin-right: 3
width: 100
text-align: right
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: loot
!text: tr('Loot:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
margin-right: 3
Label
id: lootValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: loot.verticalCenter
margin-left: 3
margin-right: 3
width: 100
text-align: right
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: lootHour
!text: tr('Loot/h:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-left: 3
margin-right: 3
Label
id: lootHourValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: lootHour.verticalCenter
margin-left: 3
margin-right: 3
width: 100
text-align: right
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: Label
anchors.top: prev.bottom
anchors.left: parent.left
margin-left: 3
margin-top: 10
!text: tr('Items Looted:')
TextList
id: MessagePanel
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 3
margin-left: 3
margin-right: 3
height: 400

View File

@ -1,72 +0,0 @@
LootItemName < Label
background-color: alpha
text-offset: 2 0
focusable: true
height: 16
$focus:
background-color: #00000055
Button
id: remove
!text: tr('x')
anchors.right: parent.right
margin-right: 15
width: 15
height: 15
LootWindow < MainWindow
!text: tr('Loot List')
size: 250 340
@onEscape: self:hide()
TextList
id: LootList
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
margin-bottom: 5
padding: 1
width: 200
height: 200
vertical-scrollbar: LootListScrollBar
VerticalScrollBar
id: LootListScrollBar
anchors.top: LootList.top
anchors.bottom: LootList.bottom
anchors.right: LootList.right
step: 14
pixels-scroll: true
TextEdit
id: LootName
anchors.right: parent.right
anchors.left: parent.left
anchors.top: LootList.bottom
margin-top: 5
Button
id: AddLoot
!text: tr('Add Loot')
anchors.right: parent.right
anchors.left: parent.left
anchors.top: prev.bottom
margin-top: 3
HorizontalSeparator
id: separator
anchors.right: parent.right
anchors.left: parent.left
anchors.bottom: closeButton.top
margin-bottom: 8
Button
id: closeButton
!text: tr('Close')
font: cipsoftFont
anchors.right: parent.right
anchors.bottom: parent.bottom
size: 45 21
margin-top: 15
margin-right: 5

View File

@ -1,80 +0,0 @@
XpAnalyser < MiniWindow
!text: tr('XP Analyser')
height: 85
icon: /images/topbuttons/analyzers
&save: true
&autoOpen: false
MiniWindowContents
Label
id: xpGain
!text: tr('XP Gain:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
margin-left: 3
margin-right: 3
Label
id: xpValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: xpGain.verticalCenter
margin-left: 3
margin-right: 3
width: 100
text-align: right
HorizontalSeparator
id: separatorOne
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: xpHour
!text: tr('XP/h:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: xpGain.bottom
margin-top: 10
margin-left: 3
margin-right: 3
Label
id: hourValue
!text: tr('0')
anchors.right: parent.right
anchors.verticalCenter: xpHour.verticalCenter
margin-left: 3
margin-right: 3
width: 100
text-align: right
HorizontalSeparator
id: separatorTwo
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
Label
id: ttnl
!text: tr('Next Level:')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: xpHour.bottom
margin-top: 10
margin-left: 3
margin-right: 3
Label
id: ttnlValue
!text: tr('-')
anchors.right: parent.right
anchors.verticalCenter: ttnl.verticalCenter
margin-left: 3
margin-right: 3
width: 100
text-align: right

View File

@ -1,87 +0,0 @@
setDefaultTab("Cave")
UI.Separator()
function containerIsFull(c)
if not c then return false end
if c:getCapacity() > #c:getItems() then
return false
else
return true
end
end
-- config
local ammoBp = "crystal backpack"
local potionBp = "camouflage backpack"
local runeBp = "red backpack"
-- script
local potions = {268, 237, 238, 23373, 266, 236, 239, 7643, 23375, 7642, 23374}
local runes = {3725, 3203, 3161, 3147, 3178, 3177, 3153, 3148, 3197, 3149, 3164, 3166, 3200, 3192, 3188, 3190, 3189, 3191, 3198, 3182, 3158, 3152, 3174, 3180, 3165, 3173, 3172, 3176, 3195, 3179, 3175, 3155, 3202, 3160, 3156}
local ammo = {3446, 16142, 6528, 7363, 3450, 16141, 25785, 14252, 3447, 3449, 15793, 25757, 774, 16143, 763, 761, 7365, 3448, 762, 21470, 7364, 14251, 7368, 25759, 3287, 7366, 3298, 25758}
local potionsContainer = nil
local runesContainer = nil
local ammoContainer = nil
macro(500, "Supply Sorter", function()
-- set the containers
if not potionsContainer or not runesContainer or not ammoContainer then
for i, container in pairs(getContainers()) do
if container:getName():lower() == potionBp:lower() then
potionsContainer = container
elseif container:getName():lower() == runeBp:lower() then
runesContainer = container
elseif container:getName():lower() == ammoBp:lower() then
ammoContainer = container
end
end
end
-- potions
if potionsContainer then
for i, container in pairs(getContainers()) do
if (container:getName():lower() ~= potionBp:lower() and (string.find(container:getName(), "backpack") or string.find(container:getName(), "bag") or string.find(container:getName(), "chess"))) and not string.find(container:getName():lower(), "loot") then
for j, item in pairs(container:getItems()) do
if table.find(potions, item:getId()) and not containerIsFull(potionsContainer) then
g_game.move(item, potionsContainer:getSlotPosition(potionsContainer:getItemsCount()), item:getCount())
end
end
end
end
end
-- runes
if runesContainer then
for i, container in pairs(getContainers()) do
if (container:getName():lower() ~= runeBp:lower() and (string.find(container:getName(), "backpack") or string.find(container:getName(), "bag") or string.find(container:getName(), "chess"))) and not string.find(container:getName():lower(), "loot") then
for j, item in pairs(container:getItems()) do
if table.find(runes, item:getId()) and not containerIsFull(runesContainer) then
g_game.move(item, runesContainer:getSlotPosition(runesContainer:getItemsCount()), item:getCount())
end
end
end
end
end
-- ammo
if ammoContainer then
for i, container in pairs(getContainers()) do
if (container:getName():lower() ~= ammoBp:lower() and (string.find(container:getName(), "backpack") or string.find(container:getName(), "bag") or string.find(container:getName(), "chess"))) and not string.find(container:getName():lower(), "loot") then
for j, item in pairs(container:getItems()) do
if table.find(ammo, item:getId()) and not containerIsFull(ammoContainer) then
g_game.move(item, ammoContainer:getSlotPosition(ammoContainer:getItemsCount()), item:getCount())
end
end
end
end
end
end)

View File

@ -0,0 +1,7 @@
-- main tab
UI.Label("Vithrax CFG v1.3 \n \n Scripting Service: \n Vithrax#5814")
UI.Separator()

View File

@ -96,10 +96,13 @@ macro(10, function()
local tile = g_map.getTile(target:getPosition())
targetOldPos = tile:getPosition()
if tile then
if tile:getTopUseThing():isPickupable() or not tile:getTopUseThing():isNotMoveable() then
useWith(tonumber(storage[pushPanelName].pushMaxRuneId), target)
delay(10)
end
if targetTile:getTopThing():getId() == 2129 or targetTile:getTopThing():getId() == 2130 or targetTile:getTopThing():getId() == tonumber(storage[pushPanelName].mwallBlockId) then
if targetTile:getTimer() <= tonumber(storage[pushPanelName].pushDelay) then
useWith(tonumber(storage[pushPanelName].pushMaxRuneId), target) -- 3197 desintigrate rune / 3188 firebomb rune
delay(10)
info("now")
g_game.move(target, targetTile:getPosition())
tile:setText("")
targetTile:setText("")
@ -107,15 +110,8 @@ macro(10, function()
targetTile = nil
end
else
if tile:getTopUseThing():isPickupable() or not tile:getTopUseThing():isNotMoveable() then
useWith(tonumber(storage[pushPanelName].pushMaxRuneId), target)
delay(10)
g_game.move(target, targetTile:getPosition())
delay(1250)
else
g_game.move(target, targetTile:getPosition())
delay(1250)
end
g_game.move(target, targetTile:getPosition())
delay(1250)
end
end
else

View File

@ -1,4 +1,5 @@
setDefaultTab("HP")
storage.lootStatus = ""
healPanelName = "healbot"
local ui = setupUI([[
Panel
@ -63,6 +64,7 @@ if rootWidget then
end
label.remove.onClick = function(widget)
table.removevalue(storage[healPanelName].spellTable, entry)
reindexTable(storage[healPanelName].spellTable)
label:destroy()
end
label:setText("(MP>" .. entry.cost .. ") " .. entry.origin .. entry.sign .. entry.value .. ":" .. entry.spell)
@ -85,6 +87,7 @@ if rootWidget then
end
label.remove.onClick = function(widget)
table.removevalue(storage[healPanelName].itemTable, entry)
reindexTable(storage[healPanelName].itemTable)
label:destroy()
end
label:setText(entry.origin .. entry.sign .. entry.value .. ":" .. entry.item)
@ -301,7 +304,7 @@ macro(100, function()
if not storage[healPanelName].enabled or modules.game_cooldown.isGroupCooldownIconActive(2) or #storage[healPanelName].spellTable == 0 then return end
for _, entry in pairs(storage[healPanelName].spellTable) do
if mana() >= tonumber(entry.cost) and not getSpellCoolDown(entry.spell) and entry.enabled then
if canCast(entry.spell) and entry.enabled then
if entry.origin == "HP%" then
if entry.sign == "=" and hppercent() == entry.value then
say(entry.spell)
@ -353,8 +356,12 @@ end)
-- items
macro(500, function()
if TargetBot.isOff() then storage.lootStatus = "" end
if not storage[healPanelName].enabled or storage.isUsing or #storage[healPanelName].itemTable == 0 then return end
if storage.lootStatus:len() > 0 then
delay(500)
end
for _, entry in pairs(storage[healPanelName].itemTable) do
local item = findItem(entry.item)
if item and entry.enabled then

View File

@ -105,14 +105,17 @@ Panel
macro(200, function()
if storage[panelName].enabled and storage[panelName].spellName:len() > 0 and manapercent() > storage[panelName].minMana then
for _, spec in ipairs(getSpectators()) do
if spec:isPlayer() and storage[panelName].minFriendHp >= spec:getHealthPercent() and isFriend(spec:getName()) then
if storage[panelName].spellHeal then
saySpell(storage[panelName].spellName .. ' "' .. spec:getName(), 100)
end
healItem = findItem(storage[panelName].id)
if storage[panelName].itemHeal and distanceFromPlayer(spec:getPosition()) <= storage[panelName].distance and healItem then
useWith(storage[panelName].id, spec)
delay(300)
if not spec:isLocalPlayer() then
if spec:isPlayer() and storage[panelName].minFriendHp >= spec:getHealthPercent() and isFriend(spec:getName()) then
if storage[panelName].spellHeal then
saySpell(storage[panelName].spellName .. ' "' .. spec:getName(), 100)
return
end
healItem = findItem(storage[panelName].id)
if storage[panelName].itemHeal and distanceFromPlayer(spec:getPosition()) <= storage[panelName].distance and healItem then
useWith(storage[panelName].id, spec)
return
end
end
end
end

View File

@ -52,14 +52,13 @@ local k = 1
local pvpDedicated = false
local item = false
UI.Separator()
if not storage[attackPanelName] or not storage[attackPanelName].attackTable then
storage[attackPanelName] = {
pvpMode = false,
pvpSafe = true,
enabled = false,
attackTable = {}
attackTable = {},
ignoreMana = true
}
end
@ -183,6 +182,11 @@ if rootWidget then
pvpDedicated = not pvpDedicated
attackWindow.pvpSpell:setChecked(pvpDedicated)
end
attackWindow.IgnoreMana:setChecked(storage[attackPanelName].ignoreMana)
attackWindow.IgnoreMana.onClick = function(widget)
storage[attackPanelName].ignoreMana = not storage[attackPanelName].ignoreMana
attackWindow.IgnoreMana:setChecked(storage[attackPanelName].ignoreMana)
end
--buttons
attackWindow.CloseButton.onClick = function(widget)
@ -307,6 +311,7 @@ if rootWidget then
end
label.remove.onClick = function(widget)
table.removevalue(storage[attackPanelName].attackTable, entry)
reindexTable(storage[attackPanelName].attackTable)
label:destroy()
end
if entry.pvp then
@ -629,7 +634,8 @@ local posW = [[
100
]]
macro(1000, function()
local bestTile
macro(100, function()
if not storage[attackPanelName].enabled then return end
if #storage[attackPanelName].attackTable == 0 or isInPz() or not target() or modules.game_cooldown.isGroupCooldownIconActive(1) then return end
@ -641,7 +647,7 @@ macro(1000, function()
monstersN = getCreaturesInArea(pos(), posN, 2)
monstersE = getCreaturesInArea(pos(), posE, 2)
monstersS = getCreaturesInArea(pos(), posS, 2)
monstersW = getCreaturesInArea(pos(), posN, 2)
monstersW = getCreaturesInArea(pos(), posW, 2)
local posTable = {monstersE, monstersN, monstersS, monstersW}
local bestSide = 0
@ -661,13 +667,13 @@ macro(1000, function()
elseif monstersW == bestSide then bestDir = 3
end
if player:getDirection() ~= bestDir and bestSide > 0 and CaveBot.isOn() then
if player:getDirection() ~= bestDir and bestSide > 0 then
turn(bestDir)
end
for _, entry in pairs(storage[attackPanelName].attackTable) do
if entry.enabled then
if (type(entry.attack) == "string" and canCast(entry.attack)) or (type(entry.attack) == "number" and findItem(entry.attack)) then
if (type(entry.attack) == "string" and canCast(entry.attack, not storage[attackPanelName].ignoreMana)) or (type(entry.attack) == "number" and findItem(entry.attack)) then
if manapercent() >= entry.manaCost and distanceFromPlayer(target():getPosition()) <= entry.dist then
if storage[attackPanelName].pvpMode then
if entry.pvp then
@ -696,6 +702,9 @@ macro(1000, function()
end
else
if killsToRs() > 2 then
if entry.category == 8 then
bestTile = getBestTileByPatern(patterns[5], 2, entry.dist, storage[attackPanelName].pvpSafe)
end
if entry.category == 4 and (not storage[attackPanelName].pvpSafe or isSafe(2, false)) and bestSide >= entry.minMonsters then
say(entry.attack)
return
@ -708,9 +717,9 @@ macro(1000, function()
elseif entry.category == 2 and getCreaturesInArea(pos(), patterns[entry.model], 2) >= entry.minMonsters and (not storage[attackPanelName].pvpSafe or getCreaturesInArea(pos(), safePatterns[entry.model], 3) == 0) then
say(entry.attack)
return
elseif entry.category == 8 and getBestTileByPatern(patterns[5], 2, entry.dist, storage[attackPanelName].pvpSafe) and getBestTileByPatern(patterns[5], 2, entry.dist, storage[attackPanelName].pvpSafe).count >= entry.minMonsters then
elseif entry.category == 8 and bestTile and bestTile.count >= entry.minMonsters then
if not storage.isUsing then
useWith(entry.attack, getBestTileByPatern(patterns[5], 2, entry.dist, storage[attackPanelName].pvpSafe).pos:getTopUseThing())
useWith(entry.attack, bestTile.pos:getTopUseThing())
end
return
elseif entry.category == 9 and not isBuffed() and getMonsters(entry.dist) >= entry.minMonsters then

View File

@ -216,6 +216,14 @@ AttackWindow < MainWindow
text-align: center
margin-bottom: 2
CheckBox
id: IgnoreMana
anchors.verticalCenter: CloseButton.verticalCenter
anchors.left: parent.left
margin-left: 5
width: 250
text: Check RL Tibia mana cost
HorizontalSeparator
id: BottomSeparator
anchors.right: parent.right

View File

@ -10,7 +10,7 @@ CureConditions < Panel
image-source: /images/ui/panel_flat
image-border: 6
padding: 3
size: 200 180
size: 200 190
Label
id: label1
@ -201,7 +201,7 @@ HoldConditions < Panel
image-source: /images/ui/panel_flat
image-border: 6
padding: 3
size: 200 180
size: 200 190
Label
id: label1
@ -350,20 +350,33 @@ HoldConditions < Panel
id: IgnoreInPz
anchors.left: label5.left
anchors.top: label6.bottom
margin-top: 15
margin-top: 12
Label
id: label
anchors.verticalCenter: IgnoreInPz.verticalCenter
anchors.left: prev.right
margin-top: 3
margin-left: 5
text: Don't Cast in Protection Zones
font: cipsoftFont
font: cipsoftFont
CheckBox
id: StopHaste
anchors.horizontalCenter: IgnoreInPz.horizontalCenter
anchors.top: IgnoreInPz.bottom
margin-top: 8
Label
anchors.verticalCenter: prev.verticalCenter
anchors.left: prev.right
margin-top: 3
margin-left: 5
text: Stop Haste if TargetBot Is Active
font: cipsoftFont
ConditionsWindow < MainWindow
!text: tr('Condition Manager')
size: 445 270
size: 445 280
@onEscape: self:hide()
CureConditions

View File

@ -1,16 +1,16 @@
local vocation = player:getVocation()
local vocText = nil
local vocText = ""
if vocation == 1 or vocation == 11 then
vocText = "EK"
vocText = "- EK"
elseif vocation == 2 or vocation == 12 then
vocText = "RP"
vocText = "- RP"
elseif vocation == 3 or vocation == 13 then
vocText = "MS"
vocText = "- MS"
elseif vocation == 4 or vocation == 14 then
vocText = "ED"
vocText = "- ED"
end
macro(10000, function()
g_window.setTitle("Tibia - " .. player:getName() .. " - " .. lvl() .. "lvl - " .. vocText)
g_window.setTitle("Tibia - " .. player:getName() .. " - " .. lvl() .. "lvl " .. vocText)
end, batTab)

View File

@ -50,7 +50,8 @@ Panel
holdUtura = false,
uturaType = "",
uturaCost = 100,
ignoreInPz = true
ignoreInPz = true,
stopHaste = false
}
end
@ -207,6 +208,12 @@ Panel
widget:setChecked(storage[conditionPanelName].ignoreInPz)
end
conditionsWindow.Hold.StopHaste:setChecked(storage[conditionPanelName].stopHaste)
conditionsWindow.Hold.StopHaste.onClick = function(widget)
storage[conditionPanelName].stopHaste = not storage[conditionPanelName].stopHaste
widget:setChecked(storage[conditionPanelName].stopHaste)
end
-- buttons
conditionsWindow.closeButton.onClick = function(widget)
conditionsWindow:hide()
@ -229,7 +236,7 @@ Panel
macro(50, function()
if not storage[conditionPanelName].enabled then return end
if (not storage[conditionPanelName].ignoreInPz or not isInPz()) and storage[conditionPanelName].holdUtamo and mana() >= storage[conditionPanelName].utamoCost and not hasManaShield() then say("utamo vita")
elseif (not storage[conditionPanelName].ignoreInPz or not isInPz()) and storage[conditionPanelName].holdHaste and mana() >= storage[conditionPanelName].hasteCost and not hasHaste() and not getSpellCoolDown(storage[conditionPanelName].hasteSpell) then say(storage[conditionPanelName].hasteSpell)
elseif (not storage[conditionPanelName].ignoreInPz or not isInPz()) and storage[conditionPanelName].holdHaste and mana() >= storage[conditionPanelName].hasteCost and not hasHaste() and not getSpellCoolDown(storage[conditionPanelName].hasteSpell) and (not target() or not storage[conditionPanelName].stopHaste or TargetBot.isCaveBotActionAllowed()) then say(storage[conditionPanelName].hasteSpell)
elseif storage[conditionPanelName].cureParalyse and mana() >= storage[conditionPanelName].paralyseCost and isParalyzed() and not getSpellCoolDown(storage[conditionPanelName].paralyseSpell) then say(storage[conditionPanelName].paralyseSpell)
end
end)

View File

@ -0,0 +1,634 @@
-- Author: Vithrax
-- contains mostly basic function shortcuts and code shorteners
function containerIsFull(c)
if not c then return false end
if c:getCapacity() > #c:getItems() then
return false
else
return true
end
end
function isBuffed()
local var = false
for i=1,4 do
local premium = (player:getSkillLevel(i) - player:getSkillBaseLevel(i))
local base = player:getSkillBaseLevel(i)
if hasPartyBuff() and (premium/100)*305 > base then
var = true
end
end
return var
end
function reindexTable(t)
if not t or type(t) ~= "table" then return end
local i = 0
for _, e in pairs(t) do
i = i + 1
e.index = i
end
end
function killsToRs()
return math.min(g_game.getUnjustifiedPoints().killsDayRemaining, g_game.getUnjustifiedPoints().killsWeekRemaining, g_game.getUnjustifiedPoints().killsMonthRemaining)
end
local Spells = modules.gamelib.SpellInfo['Default']
function canCast(spell, ignoreMana)
if type(spell) ~= "string" then return end
if not getSpellData(spell) then return true end
if not getSpellCoolDown(spell) and level() >= getSpellData(spell).level and (ignoreMana or mana() >= getSpellData(spell).mana) then
return true
else
return false
end
end
function getSpellData(spell)
if not spell then return false end
local t = nil
for k,v in pairs(Spells) do
if v.words == spell then
t = k
break
end
end
if t then
return Spells[t]
else
return false
end
end
function getSpellCoolDown(text)
if not text then return false end
if not getSpellData(text) then return false end
for i,v in pairs(Spells) do
if v.words == text then
return modules.game_cooldown.isCooldownIconActive(v.id)
end
end
end
storage.isUsing = false
onUse(function(pos, itemId, stackPos, subType)
if pos.x < 65000 then
storage.isUsing = true
end
schedule(1500, function() storage.isUsing = false end)
end)
function string.starts(String,Start)
return string.sub(String,1,string.len(Start))==Start
end
function isFriend(name)
if not name then return false end
if table.find(storage.playerList.friendList, name) then
return true
elseif string.find(storage.serverMembers, name) then
return true
elseif storage.playerList.groupMembers then
local p = getCreatureByName(name, true)
if p:isLocalPlayer() then return true end
if p:isPlayer() then
if ((p:getShield() >= 3 and p:getShield() <= 10) or p:getEmblem() == 2) then
return true
else
return false
end
end
else
return false
end
end
function isEnemy(name)
if not name then return false end
local p = getCreatureByName(name, true)
if p:isLocalPlayer() then return end
if p:isPlayer() and table.find(storage.playerList.enemyList, name) or (storage.playerList.marks and not isFriend(name)) then
return true
else
return false
end
end
function isAttSpell(expr)
if string.starts(expr, "exori") or string.starts(expr, "exevo") then
return true
else
return false
end
end
function getActiveItemId(id)
if not id then
return false
end
if id == 3049 then
return 3086
elseif id == 3050 then
return 3087
elseif id == 3051 then
return 3088
elseif id == 3052 then
return 3089
elseif id == 3053 then
return 3090
elseif id == 3091 then
return 3094
elseif id == 3092 then
return 3095
elseif id == 3093 then
return 3096
elseif id == 3097 then
return 3099
elseif id == 3098 then
return 3100
elseif id == 16114 then
return 16264
elseif id == 23531 then
return 23532
elseif id == 23533 then
return 23534
elseif id == 23529 then
return 23530
else
return id
end
end
function getInactiveItemId(id)
if not id then
return false
end
if id == 3086 then
return 3049
elseif id == 3087 then
return 3050
elseif id == 3088 then
return 3051
elseif id == 3089 then
return 3052
elseif id == 3090 then
return 3053
elseif id == 3094 then
return 3091
elseif id == 3095 then
return 3092
elseif id == 3096 then
return 3093
elseif id == 3099 then
return 3097
elseif id == 3100 then
return 3098
elseif id == 16264 then
return 16114
elseif id == 23532 then
return 23531
elseif id == 23534 then
return 23533
elseif id == 23530 then
return 23529
else
return id
end
end
function getMonstersInRange(pos, range)
if not pos or not range then
return false
end
local monsters = 0
for i, spec in pairs(getSpectators()) do
if spec:isMonster() and spec:getType() ~= 3 and getDistanceBetween(pos, spec:getPosition()) < range then
monsters = monsters + 1
end
end
return monsters
end
function distanceFromPlayer(coords)
if not coords then
return false
end
return getDistanceBetween(pos(), coords)
end
function getMonsters(range, multifloor)
if not range then
range = 10
end
local mobs = 0;
for _, spec in pairs(getSpectators(multifloor)) do
mobs = spec:getType() ~= 3 and spec:isMonster() and distanceFromPlayer(spec:getPosition()) <= range and mobs + 1 or mobs;
end
return mobs;
end
function getPlayers(range, multifloor)
if not range then
range = 10
end
local specs = 0;
for _, spec in pairs(getSpectators(multifloor)) do
specs = not spec:isLocalPlayer() and spec:isPlayer() and distanceFromPlayer(spec:getPosition()) <= range and not ((spec:getShield() >= 3 and spec:getShield() <= 10) or spec:getEmblem() == 1) and specs + 1 or specs;
end
return specs;
end
function isSafe(range, multifloor, padding)
local onSame = 0
local onAnother = 0
if not multifloor and padding then
multifloor = false
padding = false
end
for _, spec in pairs(getSpectators(multifloor)) do
if spec:isPlayer() and not spec:isLocalPlayer() and not isFriend(spec:getName()) then
if spec:getPosition().z == posz() and distanceFromPlayer(spec:getPosition()) <= range then
onSame = onSame + 1
end
if multifloor and padding and spec:getPosition().z ~= posz() and distanceFromPlayer(spec:getPosition()) <= (range + padding) then
onAnother = onAnother + 1
end
end
end
if onSame + onAnother > 0 then
return false
else
return true
end
end
function getAllPlayers(range, multifloor)
if not range then
range = 10
end
local specs = 0;
for _, spec in pairs(g_map.getSpectators(multifloor)) do
specs = not spec:isLocalPlayer() and spec:isPlayer() and distanceFromPlayer(spec:getPosition()) <= range and specs + 1 or specs;
end
return specs;
end
function getNpcs(range, multifloor)
if not range then
range = 10
end
local npcs = 0;
for _, spec in pairs(g_map.getSpectators(multifloor)) do
npcs = spec:isNpc() and distanceFromPlayer(spec:getPosition()) <= range and npcs + 1 or npcs;
end
return npcs;
end
function itemAmount(id)
local totalItemCount = 0
for _, container in pairs(getContainers()) do
for _, item in ipairs(container:getItems()) do
totalItemCount = item:getId() == id and totalItemCount + item:getCount() or totalItemCount
end
end
if getHead() and getHead():getId() == id then
totalItemCount = totalItemCount + getHead():getCount()
end
if getNeck() and getNeck():getId() == id then
totalItemCount = totalItemCount + getNeck():getCount()
end
if getBack() and getBack():getId() == id then
totalItemCount = totalItemCount + getBack():getCount()
end
if getBody() and getBody():getId() == id then
totalItemCount = totalItemCount + getBody():getCount()
end
if getRight() and getRight():getId() == id then
totalItemCount = totalItemCount + getRight():getCount()
end
if getLeft() and getLeft():getId() == id then
totalItemCount = totalItemCount + getLeft():getCount()
end
if getLeg() and getLeg():getId() == id then
totalItemCount = totalItemCount + getLeg():getCount()
end
if getFeet() and getFeet():getId() == id then
totalItemCount = totalItemCount + getFeet():getCount()
end
if getFinger() and getFinger():getId() == id then
totalItemCount = totalItemCount + getFinger():getCount()
end
if getAmmo() and getAmmo():getId() == id then
totalItemCount = totalItemCount + getAmmo():getCount()
end
return totalItemCount
end
function cordsToPos(x, y, z)
if not x or not y or not z then
return false
end
local tilePos = pos()
tilePos.x = x
tilePos.y = y
tilePos.z = z
return tilePos
end
function reachGroundItem(id)
local targetTile
for _, tile in ipairs(g_map.getTiles(posz())) do
if tile:getTopUseThing():getId() == id then
targetTile = tile:getPosition()
end
end
if distanceFromPlayer(targetTile) > 1 then
if CaveBot.walkTo(targetTile, 10, {ignoreNonPathable = true, precision=1}) then
delay(200)
end
else
return true
end
end
function useGroundItem(id)
if not id then
return false
end
local targetTile = nil
for _, tile in ipairs(g_map.getTiles(posz())) do
if tile:getTopUseThing():getId() == id then
targetTile = tile:getPosition()
end
end
if targetTile then
if distanceFromPlayer(targetTile) > 1 then
if CaveBot.walkTo(targetTile, 20, {ignoreNonWalkable = true, ignoreNonPathable = true, precision=1}) then
delay(200)
end
else
g_game.use(g_map.getTile(targetTile):getTopUseThing())
return true
end
else
return "retry"
end
end
function target()
if not g_game.isAttacking() then
return
else
return g_game.getAttackingCreature()
end
end
function getTarget()
return target()
end
function targetPos(dist)
if not g_game.isAttacking() then
return
end
if dist then
return distanceFromPlayer(target():getPosition())
else
return target():getPosition()
end
end
-- for gunzodus
function reopenPurse()
schedule(100, function() g_game.open(findItem(23721)) return true end)
schedule(1400, function() g_game.open(findItem(23721)) return true end)
CaveBot.delay(1500)
return true
end
-- getSpectator patterns
function getCreaturesInArea(param1, param2, param3)
-- param1 - pos/creature
-- param2 - pattern
-- param3 - type of return
-- 1 - everyone, 2 - monsters, 3 - players
local specs = 0
local monsters = 0
local players = 0
for i, spec in pairs(getSpectators(param1, param2)) do
if spec ~= player then
specs = specs + 1
if spec:isMonster() and spec:getType() ~= 3 then
monsters = monsters + 1
elseif spec:isPlayer() and not isFriend(spec:getName()) then
players = players +1
end
end
end
if param3 == 1 then
return specs
elseif param3 == 2 then
return monsters
else
return players
end
end
function getBestTileByPatern(pattern, specType, maxDist, safe)
if not pattern or not specType then return end
if not maxDist then maxDist = 4 end
if not safe then safe = false end
local bestTile = nil
local best = nil
-- best area tile to use
for _, tile in pairs(g_map.getTiles(posz())) do
if distanceFromPlayer(tile:getPosition()) <= maxDist then
local minimapColor = g_map.getMinimapColor(tile:getPosition())
local stairs = (minimapColor >= 210 and minimapColor <= 213)
if tile:canShoot() and tile:isWalkable() and not stairs then
if getCreaturesInArea(tile:getPosition(), pattern, specType) > 0 then
if (not safe or getCreaturesInArea(tile:getPosition(), pattern, 3) == 0) then
local candidate = {pos = tile, count = getCreaturesInArea(tile:getPosition(), pattern, specType)}
if not best or best.count <= candidate.count then
best = candidate
end
end
end
end
end
end
bestTile = best
if bestTile then
return bestTile
else
return false
end
end
LargeUeArea = [[
0000001000000
0000011100000
0000111110000
0001111111000
0011111111100
0111111111110
1111111111111
0111111111110
0011111111100
0001111111000
0000111110000
0000011100000
0000001000000
]]
NormalUeAreaMs = [[
00000100000
00011111000
00111111100
01111111110
01111111110
11111111111
01111111110
01111111110
00111111100
00001110000
00000100000
]]
NormalUeAreaEd = [[
00000100000
00001110000
00011111000
00111111100
01111111110
11111111111
01111111110
00111111100
00011111000
00001110000
00000100000
]]
smallUeArea = [[
0011100
0111110
1111111
1111111
1111111
0111110
0011100
]]
largeRuneArea = [[
0011100
0111110
1111111
1111111
1111111
0111110
0011100
]]
adjacentArea = [[
111
101
111
]]
longBeamArea = [[
0000000N0000000
0000000N0000000
0000000N0000000
0000000N0000000
0000000N0000000
0000000N0000000
0000000N0000000
WWWWWWW0EEEEEEE
0000000S0000000
0000000S0000000
0000000S0000000
0000000S0000000
0000000S0000000
0000000S0000000
0000000S0000000
]]
shortBeamArea = [[
00000100000
00000100000
00000100000
00000100000
00000100000
EEEEE0WWWWW
00000S00000
00000S00000
00000S00000
00000S00000
00000S00000
]]
newWaveArea = [[
000NNNNN000
000NNNNN000
0000NNN0000
WW00NNN00EE
WWWW0N0EEEE
WWWWW0EEEEE
WWWW0S0EEEE
WW00SSS00EE
0000SSS0000
000SSSSS000
000SSSSS000
]]
bigWaveArea = [[
0000NNN0000
0000NNN0000
0000NNN0000
00000N00000
WWW00N00EEE
WWWWW0EEEEE
WWW00S00EEE
00000S00000
0000SSS0000
0000SSS0000
0000SSS0000
]]
smallWaveArea = [[
00NNN00
00NNN00
WW0N0EE
WWW0EEE
WW0S0EE
00SSS00
00SSS00
]]
diamondArrowArea = [[
01110
11111
11111
11111
01110
]]

View File

@ -0,0 +1,7 @@
local lastMove = now
onPlayerPositionChange(function(newPos, oldPos)
if now - lastMove > 13*60*1000 then
turn(math.random(0,3))
lastMove = now
end
end)

View File

@ -155,7 +155,7 @@ CaveBot.registerAction("goto", "green", function(value, retries, prev)
if not path2 then
local monsters = {}
for i, spec in pairs(getSpectators()) do
if spec:isMonster() and spec:canShoot() and findPath(playerPos, spec:getPosition(), 20, {ignoreNonPathable = true, precision = 1}) then
if spec:isMonster() and spec:getType() ~= 3 and spec:canShoot() and findPath(playerPos, spec:getPosition(), 20, {ignoreNonPathable = true, precision = 1}) then
table.insert(monsters, {mob = spec, dist = getDistanceBetween(pos, spec:getPosition())})
end
end

View File

@ -30,7 +30,7 @@ CaveBot.Extensions.BuySupplies.setup = function()
delay(waitVal)
end
if retries > 30 then
if retries > 40 then
print("CaveBot[BuySupplies]: Too many tries, can't buy")
return false
end

View File

@ -5,6 +5,7 @@ comparePosition = function(pPos, tPos)
end
local depotIDs = {3497, 3498, 3499, 3500}
local depotContainers = {22797, 22798, 22799, 22800, 22801, 22802, 22803, 22804, 22805, 22806, 22807, 22808, 22809, 22810, 22811, 22812, 22813}
storage.stopSearch = false
storage.lootContainerOpen = false
local i = 1
@ -12,18 +13,26 @@ local i = 1
CaveBot.Extensions.DWithdraw.setup = function()
CaveBot.registerAction("dpwithdraw", "#00FFFF", function(value, retries)
if freecap() < 200 then
print("CaveBot[DepotWithdraw]: cap limit reached, proceeding")
return true
end
local capLimit = nil
if retries > 600 then
print("CaveBot[DepotWithdraw]: actions limit reached, proceeding")
return true
end
delay(50)
if not value or #string.split(value, ",") ~= 2 then return end
local destName = string.split(value, ",")[1]:trim()
local destId = tonumber(string.split(value, ",")[2]:trim())
if not value or #string.split(value, ",") ~= 3 and #string.split(value, ",") ~= 4 then
warn("CaveBot[DepotWithdraw]: incorrect value!")
return false
end
local indexDp = tonumber(string.split(value, ",")[1]:trim())
local destName = string.split(value, ",")[2]:trim()
local destId = tonumber(string.split(value, ",")[3]:trim())
if #string.split(value, ",") == 4 then
capLimit = tonumber(string.split(value, ",")[4]:trim())
end
if freecap() < (capLimit or 200) then
print("CaveBot[DepotWithdraw]: cap limit reached, proceeding")
return true
end
local destContainer
for i, container in pairs(getContainers()) do
@ -138,7 +147,7 @@ CaveBot.Extensions.DWithdraw.setup = function()
if container:getName():lower() == "depot chest" then
for _, item in ipairs(container:getItems()) do
if item:isContainer() and table.find({22797, 22798}, item:getId()) then
g_game.open(findItem(22797), container)
g_game.open(findItem(depotContainers[indexDp]), container)
delay(500)
for _, cont in pairs(g_game.getContainers()) do
if string.find(cont:getName():lower(), "depot box") then
@ -167,9 +176,9 @@ CaveBot.Extensions.DWithdraw.setup = function()
end)
CaveBot.Editor.registerAction("dpwithdraw", "dpwithdraw", {
value="shopping bag, 21411",
value="1, shopping bag, 21411",
title="Loot Withdraw",
description="insert destination container name and it's ID",
description="index Depot, destination container name and it's ID",
})
end

View File

@ -3,10 +3,10 @@ CaveBot.Extensions.Lure = {}
CaveBot.Extensions.Lure.setup = function()
CaveBot.registerAction("lure", "#00FFFF", function(value, retries)
if value == "start" then
TargetBot.enableLuring()
TargetBot.setOff()
return true
elseif value == "stop" then
TargetBot.disableLuring()
TargetBot.setOn()
return true
else
warn("incorrect lure value!")

View File

@ -9,6 +9,7 @@ CaveBot.Extensions.SupplyCheck.setup = function()
local totalItem3 = itemAmount(storage[suppliesPanelName].item3)
local totalItem4 = itemAmount(storage[suppliesPanelName].item4)
local totalItem5 = itemAmount(storage[suppliesPanelName].item5)
local totalItem6 = itemAmount(storage[suppliesPanelName].item6)
if storage.supplyRetries > 50 then
print("CaveBot[SupplyCheck]: Round limit reached, going back on refill.")
@ -46,6 +47,10 @@ CaveBot.Extensions.SupplyCheck.setup = function()
print("CaveBot[SupplyCheck]: Not enough item: " .. storage[suppliesPanelName].item5 .. "(only " .. totalItem5 .. " left). Going on refill.")
storage.supplyRetries = 0
return false
elseif (totalItem6 < tonumber(storage[suppliesPanelName].item6Min) and storage[suppliesPanelName].item6 > 100) then
print("CaveBot[SupplyCheck]: Not enough item: " .. storage[suppliesPanelName].item6 .. "(only " .. totalItem6 .. " left). Going on refill.")
storage.supplyRetries = 0
return false
elseif (freecap() < tonumber(storage[suppliesPanelName].capValue) and storage[suppliesPanelName].capSwitch) then
print("CaveBot[SupplyCheck]: Not enough capacity. Going on refill.")
storage.supplyRetries = 0

View File

@ -0,0 +1,36 @@
-- config
setDefaultTab("HP")
local scripts = 2 -- if you want more auto equip panels you can change 2 to higher value
-- script by kondrah, don't edit below unless you know what you are doing
UI.Label("Auto equip")
if type(storage.autoEquip) ~= "table" then
storage.autoEquip = {}
end
for i=1,scripts do
if not storage.autoEquip[i] then
storage.autoEquip[i] = {on=false, title="Auto Equip", item1=i == 1 and 3052 or 0, item2=i == 1 and 3089 or 0, slot=i == 1 and 9 or 0}
end
UI.TwoItemsAndSlotPanel(storage.autoEquip[i], function(widget, newParams)
storage.autoEquip[i] = newParams
end)
end
macro(250, function()
local containers = g_game.getContainers()
for index, autoEquip in ipairs(storage.autoEquip) do
if autoEquip.on then
local slotItem = getSlot(autoEquip.slot)
if not slotItem or (slotItem:getId() ~= autoEquip.item1 and slotItem:getId() ~= autoEquip.item2) then
for _, container in pairs(containers) do
for __, item in ipairs(container:getItems()) do
if item:getId() == autoEquip.item1 or item:getId() == autoEquip.item2 then
g_game.move(item, {x=65535, y=autoEquip.slot, z=0}, item:getCount())
delay(1000) -- don't call it too often
return
end
end
end
end
end
end
end)

View File

@ -235,9 +235,6 @@ Panel
local defaultRing
local defaultAmmy
local ringToEquip
local ammyToEquip
-- basic ring check
function defaultRingFind()
@ -268,47 +265,60 @@ Panel
defaultAmmyFind()
end
local lastAction = now
macro(20, function()
ammyToEquip = findItem(storage[panelName].ammyId)
ringToEquip = findItem(storage[panelName].ringId)
-- basic conditions to met
if now - lastAction < 100 then return end
if not storage[panelName].ringEnabled and not storage[panelName].ammyEnabled then return end
if not storage[panelName].ringEnabled and storage[panelName].ammyEnabled and not ammyToEquip and (not getNeck() or (getNeck():getId() ~= storage[panelName].ammyId and getNeck():getId() ~= getActiveItemId(storage[panelName].ammyId))) then return end
if storage[panelName].ringEnabled and not storage[panelName].ammyEnabled and not ringToEquip and (not getFinger() or (getFinger():getId() ~= storage[panelName].ringId and getFinger():getId() ~= getActiveItemId(storage[panelName].ringId))) then return end
-- ring unequip conditions
if storage[panelName].ringEnabled and getFinger() and getFinger():getId() == getActiveItemId(storage[panelName].ringId) and ((storage[panelName].pzCheck and isInPz()) or (not storage[panelName].valueRing and hppercent() >= storage[panelName].ringMax) or (storage[panelName].valueRing and manapercent() >= storage[panelName].ringMax)) then
if defaultRing then
moveToSlot(findItem(defaultRing), SlotFinger, 1)
else
for _,container in pairs(getContainers()) do
g_game.move(getFinger(), container:getSlotPosition(container:getItemsCount()))
-- [[ condition list ]] --
local ringEnabled = storage[panelName].ringEnabled
local ringEquipped = getFinger() and (getFinger():getId() == storage[panelName].ringId or getFinger():getId() == getActiveItemId(storage[panelName].ringId))
local shouldEquipRing = not storage[panelName].valueRing and hppercent() <= storage[panelName].ringMin or storage[panelName].valueRing and manapercent() <= storage[panelName].ringMin
local shouldUnequipRing = not storage[panelName].valueRing and hppercent() >= storage[panelName].ringMax or storage[panelName].valueRing and manapercent() >= storage[panelName].ringMax
local hasDefaultRing = defaultRing and findItem(defaultRing)
local ammyEnabled = storage[panelName].ammyEnabled
local ammyEquipped = getNeck() and (getNeck():getId() == storage[panelName].ammyId or getNeck():getId() == getActiveItemId(storage[panelName].ammyId))
local shouldEquipAmmy = not storage[panelName].valueAmmy and hppercent() <= storage[panelName].ammyMin or storage[panelName].valueAmmy and manapercent() <= storage[panelName].ammyMin
local shouldUnequipAmmy = not storage[panelName].valueAmmy and hppercent() >= storage[panelName].ammyMax or storage[panelName].valueAmmy and manapercent() >= storage[panelName].ammyMax
local hasDefaultAmmy = defaultAmmy and findItem(defaultAmmy)
local pzOk = not storage[panelName].pzCheck or not isInPz()
-- [[ ring ]] --
if ringEnabled then
if not ringEquipped and shouldEquipRing and pzOk then
g_game.equipItemId(storage[panelName].ringId)
lastAction = now
return
elseif ringEquipped and (shouldUnequipRing or not pzOk) then
if hasDefaultRing then
g_game.equipItemId(defaultRing)
lastAction = now
return
else
g_game.equipItemId(storage[panelName].ringId)
lastAction = now
return
end
end
end
end
-- amulet unequip conditions
if storage[panelName].ammyEnabled and getNeck() and getNeck():getId() == getActiveItemId(storage[panelName].ammyId) and ((storage[panelName].pzCheck and isInPz()) or (not storage[panelName].valueAmmy and hppercent() >= storage[panelName].ammyMax) or (not storage[panelName].valueAmmy and manapercent() >= storage[panelName].ammyMax)) then
if defaultAmmy then
moveToSlot(findItem(defaultAmmy), SlotNeck, 1)
else
for _,container in pairs(getContainers()) do
g_game.move(getNeck(), container:getSlotPosition(container:getItemsCount()))
end
-- [[ amulet ]] --
if ammyEnabled then
if not ammyEquipped and shouldEquipAmmy and pzOk then
g_game.equipItemId(storage[panelName].ammyId)
lastAction = now
return
elseif ammyEquipped and (shouldUnequipAmmy or not pzOk) then
if hasDefaultAmmy then
g_game.equipItemId(defaultAmmy)
lastAction = now
return
else
g_game.equipItemId(storage[panelName].ammyId)
lastAction = now
return
end
end
end
end
-- ring equip conditions
if storage[panelName].ringEnabled and (not getFinger() or getFinger():getId() ~= getActiveItemId(storage[panelName].ringId)) and (not storage[panelName].pzCheck or not isInPz()) and ((not storage[panelName].valueRing and hppercent() <= storage[panelName].ringMin) or (storage[panelName].valueRing and manapercent() <= storage[panelName].ringMin)) then
moveToSlot(ringToEquip, SlotFinger, 1)
end
-- amulet equip conditions
if storage[panelName].ammyEnabled and (not getNeck() or getNeck():getId() ~= getActiveItemId(storage[panelName].ammyId)) and (not storage[panelName].pzCheck or not isInPz()) and ((not storage[panelName].valueAmmy and hppercent() <= storage[panelName].ammyMin) or (storage[panelName].valueAmmy and manapercent() <= storage[panelName].ammyMin)) then
moveToSlot(ammyToEquip, SlotNeck, 1)
end
end
end)
-- end of function
end

View File

@ -16,8 +16,8 @@ PushMaxWindow < MainWindow
anchors.right: delayText.right
anchors.top: delayText.bottom
margin-top: 5
minimum: 1000
maximum: 1500
minimum: 800
maximum: 2000
step: 10
Label

View File

@ -25,6 +25,7 @@ storage[suppliesPanelName] = {
item3 = 0,
item4 = 0,
item5 = 0,
item6 = 0,
capValue = 0,
capSwitch = false,
SoftBoots = false,
@ -41,6 +42,12 @@ storage[suppliesPanelName] = {
item4Max = 0,
item5Min = 0,
item5Max = 0,
item6Min = 0,
item6Max = 0,
sortSupplies = false,
potionBp = 0,
runeBp = 0,
ammoBp = 0
}
end
@ -73,6 +80,12 @@ if rootWidget then
widget:setOn(storage[suppliesPanelName].staminaSwitch)
end
SuppliesWindow.SortSupplies:setOn(storage[suppliesPanelName].sortSupplies)
SuppliesWindow.SortSupplies.onClick = function(widget)
storage[suppliesPanelName].sortSupplies = not storage[suppliesPanelName].sortSupplies
widget:setOn(storage[suppliesPanelName].sortSupplies)
end
-- bot items
SuppliesWindow.item1:setItemId(storage[suppliesPanelName].item1)
@ -100,6 +113,26 @@ if rootWidget then
storage[suppliesPanelName].item5 = widget:getItemId()
end
SuppliesWindow.item6:setItemId(storage[suppliesPanelName].item6)
SuppliesWindow.item6.onItemChange = function(widget)
storage[suppliesPanelName].item6 = widget:getItemId()
end
SuppliesWindow.PotionBp:setItemId(storage[suppliesPanelName].potionBp)
SuppliesWindow.PotionBp.onItemChange = function(widget)
storage[suppliesPanelName].potionBp = widget:getItemId()
end
SuppliesWindow.RuneBp:setItemId(storage[suppliesPanelName].runeBp)
SuppliesWindow.RuneBp.onItemChange = function(widget)
storage[suppliesPanelName].runeBp = widget:getItemId()
end
SuppliesWindow.AmmoBp:setItemId(storage[suppliesPanelName].ammoBp)
SuppliesWindow.AmmoBp.onItemChange = function(widget)
storage[suppliesPanelName].ammoBp = widget:getItemId()
end
-- text windows
SuppliesWindow.capValue:setText(storage[suppliesPanelName].capValue)
SuppliesWindow.capValue.onTextChange = function(widget, text)
@ -177,7 +210,7 @@ SuppliesWindow.staminaValue:setText(storage[suppliesPanelName].staminaValue)
SuppliesWindow.staminaValue.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.staminaValue:getText())
if not value then
SuppliesWindow.staminaValue:setText("")
SuppliesWindow.staminaValue:setText(0)
end
storage[suppliesPanelName].staminaValue = text
end
@ -209,6 +242,24 @@ end
storage[suppliesPanelName].item5Max = text
end
SuppliesWindow.item6Min:setText(storage[suppliesPanelName].item6Min)
SuppliesWindow.item6Min.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item6Min:getText())
if not value then
SuppliesWindow.item6Min:setText(0)
end
storage[suppliesPanelName].item6Min = text
end
SuppliesWindow.item6Max:setText(storage[suppliesPanelName].item6Max)
SuppliesWindow.item6Max.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item6Max:getText())
if not value then
SuppliesWindow.item6Max:setText(0)
end
storage[suppliesPanelName].item6Max = text
end
end
ui.supplies.onClick = function(widget)
@ -222,5 +273,74 @@ SuppliesWindow.close.onClick = function(widget)
end
end
local potions = {268, 237, 238, 23373, 266, 236, 239, 7643, 23375, 7642, 23374}
local runes = {3725, 3203, 3161, 3147, 3178, 3177, 3153, 3148, 3197, 3149, 3164, 3166, 3200, 3192, 3188, 3190, 3189, 3191, 3198, 3182, 3158, 3152, 3174, 3180, 3165, 3173, 3172, 3176, 3195, 3179, 3175, 3155, 3202, 3160, 3156}
local ammo = {3446, 16142, 6528, 7363, 3450, 16141, 25785, 14252, 3447, 3449, 15793, 25757, 774, 16143, 763, 761, 7365, 3448, 762, 21470, 7364, 14251, 7368, 25759, 3287, 7366, 3298, 25758}
macro(250, function()
if not storage[suppliesPanelName].sortSupplies then return end
local sortPotions = storage[suppliesPanelName].potionBp > 100
local sortRunes = storage[suppliesPanelName].runeBp > 100
local sortAmmo = storage[suppliesPanelName].ammoBp > 100
local potionsContainer = nil
local runesContainer = nil
local ammoContainer = nil
-- set the containers
if not potionsContainer or not runesContainer or not ammoContainer then
for i, container in pairs(getContainers()) do
if not containerIsFull(container) then
if sortPotions and container:getContainerItem():getId() == storage[suppliesPanelName].potionBp then
potionsContainer = container
elseif sortRunes and container:getContainerItem():getId() == storage[suppliesPanelName].runeBp then
runesContainer = container
elseif sortAmmo and container:getContainerItem():getId() == storage[suppliesPanelName].ammoBp then
ammoContainer = container
end
end
end
end
-- potions
if potionsContainer then
for i, container in pairs(getContainers()) do
if (container:getContainerItem():getId() ~= storage[suppliesPanelName].potionBp and (string.find(container:getName(), "backpack") or string.find(container:getName(), "bag") or string.find(container:getName(), "chess"))) and not string.find(container:getName():lower(), "loot") then
for j, item in pairs(container:getItems()) do
if table.find(potions, item:getId()) then
return g_game.move(item, potionsContainer:getSlotPosition(potionsContainer:getItemsCount()), item:getCount())
end
end
end
end
end
-- runes
if runesContainer then
for i, container in pairs(getContainers()) do
if (container:getContainerItem():getId() ~= storage[suppliesPanelName].runeBp and (string.find(container:getName(), "backpack") or string.find(container:getName(), "bag") or string.find(container:getName(), "chess"))) and not string.find(container:getName():lower(), "loot") then
for j, item in pairs(container:getItems()) do
if table.find(runes, item:getId()) then
return g_game.move(item, runesContainer:getSlotPosition(runesContainer:getItemsCount()), item:getCount())
end
end
end
end
end
-- ammo
if ammoContainer then
for i, container in pairs(getContainers()) do
if (container:getContainerItem():getId() ~= storage[suppliesPanelName].ammoBp and (string.find(container:getName(), "backpack") or string.find(container:getName(), "bag") or string.find(container:getName(), "chess"))) and not string.find(container:getName():lower(), "loot") then
for j, item in pairs(container:getItems()) do
if table.find(ammo, item:getId()) then
return g_game.move(item, ammoContainer:getSlotPosition(ammoContainer:getItemsCount()), item:getCount())
end
end
end
end
end
end)
UI.Separator()
SuppliesPanel(setDefaultTab("Cave"))

View File

@ -1,6 +1,6 @@
SuppliesWindow < MainWindow
!text: tr('Supplies')
size: 430 280
size: 430 310
@onEscape: self:hide()
VerticalSeparator
@ -81,7 +81,57 @@ SuppliesWindow < MainWindow
anchors.right: parent.right
margin-top: 5
margin-left: 10
text: No Imbues
text: No Imbues
HorizontalSeparator
anchors.top: prev.bottom
anchors.left: prev.left
anchors.right: prev.right
margin-top: 5
BotSwitch
id: SortSupplies
anchors.top: prev.bottom
anchors.left: prev.left
anchors.right: prev.right
margin-top: 5
text: Sort Supplies
BotItem
id: PotionBp
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 3
Label
anchors.verticalCenter: prev.verticalCenter
anchors.left: prev.right
margin-left: 5
text: Potions
BotItem
id: RuneBp
anchors.top: PotionBp.bottom
anchors.left: PotionBp.left
margin-top: 3
Label
anchors.verticalCenter: prev.verticalCenter
anchors.left: prev.right
margin-left: 5
text: Runes
BotItem
id: AmmoBp
anchors.top: RuneBp.bottom
anchors.left: RuneBp.left
margin-top: 3
Label
anchors.verticalCenter: prev.verticalCenter
anchors.left: prev.right
margin-left: 5
text: Ammo
BotItem
id: item1
@ -266,6 +316,43 @@ SuppliesWindow < MainWindow
anchors.left: prev.right
anchors.top: prev.top
margin-left: 5
text-align: center
BotItem
id: item6
anchors.left: parent.left
anchors.top: prev.top
margin-top: 30
Label
id: MinLabel
!text: tr('Min Amount')
anchors.left: prev.right
anchors.top: prev.top
margin-left: 18
Label
id: MaxLabel
!text: tr('Max Amount')
anchors.left: prev.right
anchors.top: prev.top
margin-left: 35
TextEdit
id: item6Min
size: 100 20
anchors.left: parent.left
anchors.top: prev.top
margin-top: 15
margin-left: 40
text-align: center
TextEdit
id: item6Max
size: 100 20
anchors.left: prev.right
anchors.top: prev.top
margin-left: 5
text-align: center
Button

View File

@ -31,6 +31,8 @@ ui.editor.debug.onClick = function()
end
end
local oldTibia = g_game.getClientVersion() < 960
-- main loop, controlled by config
targetbotMacro = macro(100, function()
local pos = player:getPosition()
@ -44,7 +46,7 @@ targetbotMacro = macro(100, function()
local highestPriorityParams = nil
for i, creature in ipairs(creatures) do
local path = findPath(player:getPosition(), creature:getPosition(), 7, {ignoreLastCreature=true, ignoreNonPathable=true, ignoreCost=true})
if creature:isMonster() and creature:getType() < 3 and path then
if creature:isMonster() and (oldTibia or creature:getType() < 3) and path then
local params = TargetBot.Creature.calculateParams(creature, path) -- return {craeture, config, danger, priority}
dangerLevel = dangerLevel + params.danger
if params.priority > 0 then
@ -66,6 +68,7 @@ targetbotMacro = macro(100, function()
-- looting
local looting = TargetBot.Looting.process(targets, dangerLevel)
local lootingStatus = TargetBot.Looting.getStatus()
storage.lootStatus = TargetBot.Looting.getStatus()
ui.danger.right:setText(dangerLevel)
if highestPriorityParams and not isInPz() then

View File

@ -106,7 +106,7 @@ function onContainerOpen(container, previousContainer)
containerWindow = g_ui.createWidget('ContainerWindow', modules.game_interface.getContainerPanel())
end
containerWindow:setId('container' .. container:getId() .. '_' .. container:getName())
containerWindow:setId('container' .. container:getId())
if gameStart + 1000 < g_clock.millis() then
containerWindow:clearSettings()
end
@ -167,8 +167,7 @@ function onContainerOpen(container, previousContainer)
containerWindow:setContentMinimumHeight(cellSize.height)
containerWindow:setContentMaximumHeight(cellSize.height*layout:getNumLines())
local hasHeightInSettings = containerWindow:getSettings("height")
if not previousContainer and not hasHeightInSettings then
if not previousContainer then
local filledLines = math.max(math.ceil(container:getItemsCount() / layout:getNumColumns()), 1)
containerWindow:setContentHeight(filledLines*cellSize.height)
end

View File

@ -182,6 +182,7 @@ GameForceLight = 97
GameNoDebug = 98
GameBotProtection = 99
GameCreatureDirectionPassable = 100
GameFasterAnimations = 101
GameCenteredOutfits = 102
GameSendIdentifiers = 103
@ -195,7 +196,7 @@ GameDrawAuraOnTop = 109
GamePacketSizeU32 = 110
GamePacketCompression = 111
LastGameFeature = 120
LastGameFeature = 130
TextColors = {
red = '#f55e5e', --'#c83200'

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -3494,7 +3494,7 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
}
}
if (g_game.getClientVersion() >= 953) {
if (g_game.getClientVersion() >= 953 || g_game.getFeature(Otc::GameCreatureDirectionPassable)) {
bool unpass = msg->getU8();
if (creature)