mirror of
https://github.com/OTCv8/otclientv8.git
synced 2025-04-29 18:59:20 +02:00
Version 2.6.1
This commit is contained in:
parent
8fa45f387d
commit
b938520faf
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -1,7 +0,0 @@
|
||||
-- main tab
|
||||
UI.Label("Vithrax CFG v1.2 \n \n Scripting Service: \n Vithrax#5814")
|
||||
|
||||
UI.Separator()
|
||||
|
||||
|
||||
|
@ -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
|
||||
]]
|
@ -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)
|
@ -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
|
@ -1,3 +0,0 @@
|
||||
macro(60000, function()
|
||||
turn(math.random(0,3))
|
||||
end)
|
@ -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
|
@ -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
@ -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
|
@ -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
|
@ -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
|
@ -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)
|
@ -0,0 +1,7 @@
|
||||
-- main tab
|
||||
UI.Label("Vithrax CFG v1.3 \n \n Scripting Service: \n Vithrax#5814")
|
||||
|
||||
UI.Separator()
|
||||
|
||||
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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)
|
@ -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)
|
634
modules/game_bot/default_configs/vithrax_1.3/_vlib.lua
Normal file
634
modules/game_bot/default_configs/vithrax_1.3/_vlib.lua
Normal 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
|
||||
]]
|
@ -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)
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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!")
|
@ -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
|
36
modules/game_bot/default_configs/vithrax_1.3/equip.lua
Normal file
36
modules/game_bot/default_configs/vithrax_1.3/equip.lua
Normal 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)
|
@ -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
|
@ -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
|
@ -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"))
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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'
|
||||
|
BIN
otclient_dx.exe
BIN
otclient_dx.exe
Binary file not shown.
BIN
otclient_gl.exe
BIN
otclient_gl.exe
Binary file not shown.
BIN
otclientv8.apk
BIN
otclientv8.apk
Binary file not shown.
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user