mirror of
https://github.com/OTCv8/otclientv8.git
synced 2025-10-19 06:03:27 +02:00
Version 0.999 BETA - a lot of bug fixes, improvments and more advanced bot
This commit is contained in:
@@ -9,6 +9,7 @@ local render = nil
|
||||
local atlas = nil
|
||||
local adaptiveRender = nil
|
||||
local slowMain = nil
|
||||
local widgetsInfo = nil
|
||||
|
||||
local updateEvent = nil
|
||||
local monitorEvent = nil
|
||||
@@ -36,6 +37,7 @@ function init()
|
||||
atlas = statsWindow:recursiveGetChildById('atlas')
|
||||
adaptiveRender = statsWindow:recursiveGetChildById('adaptiveRender')
|
||||
slowMain = statsWindow:recursiveGetChildById('slowMain')
|
||||
widgetsInfo = statsWindow:recursiveGetChildById('widgetsInfo')
|
||||
|
||||
lastSend = os.time()
|
||||
g_stats.resetSleepTime()
|
||||
@@ -143,6 +145,7 @@ function sendStats()
|
||||
g_stats.clear(i - 1)
|
||||
g_stats.clearSlow(i - 1)
|
||||
end
|
||||
data.widgets = g_stats.getWidgetsInfo(10, false)
|
||||
data = json.encode(data)
|
||||
if Services.stats ~= nil and Services.stats:len() > 3 then
|
||||
g_http.post(Services.stats, data)
|
||||
@@ -171,7 +174,8 @@ function update()
|
||||
dispatcherStats:setText(g_stats.get(3, 5, true))
|
||||
luaStats:setText(g_stats.get(4, 5, true))
|
||||
luaCallback:setText(g_stats.get(5, 5, true))
|
||||
slowMain:setText(g_stats.getSlow(3, 10, 10, true) .. "\n\n\n" .. g_stats.getSlow(1, 20, 20, true))
|
||||
slowMain:setText(g_stats.getSlow(3, 10, 10, true) .. "\n\n\n" .. g_stats.getSlow(1, 20, 20, true))
|
||||
widgetsInfo:setText(g_stats.getWidgetsInfo(10, true))
|
||||
|
||||
if g_proxy then
|
||||
local text = ""
|
||||
|
@@ -87,6 +87,13 @@ MainWindow
|
||||
DebugText
|
||||
id: luaCallback
|
||||
text: -
|
||||
|
||||
DebugLabel
|
||||
!text: tr('Widgets')
|
||||
|
||||
DebugText
|
||||
id: widgetsInfo
|
||||
text: -
|
||||
|
||||
DebugLabel
|
||||
!text: tr('Slow main functions')
|
||||
|
@@ -317,6 +317,12 @@ function UIMoveableTabBar:onStyleApply(styleName, styleNode)
|
||||
end
|
||||
end
|
||||
|
||||
function UIMoveableTabBar:clearTabs()
|
||||
while #self.tabs > 0 do
|
||||
self:removeTab(self.tabs[#self.tabs])
|
||||
end
|
||||
end
|
||||
|
||||
function UIMoveableTabBar:removeTab(tab)
|
||||
local tabTables = {self.tabs, self.preTabs, self.postTabs}
|
||||
local index = nil
|
||||
|
@@ -80,8 +80,10 @@ end
|
||||
function UISpinBox:onStyleApply(styleName, styleNode)
|
||||
for name, value in pairs(styleNode) do
|
||||
if name == 'maximum' then
|
||||
self.maximum = value
|
||||
addEvent(function() self:setMaximum(value) end)
|
||||
elseif name == 'minimum' then
|
||||
self.minimum = value
|
||||
addEvent(function() self:setMinimum(value) end)
|
||||
elseif name == 'mouse-scroll' then
|
||||
addEvent(function() self:setMouseScroll(value) end)
|
||||
@@ -118,6 +120,9 @@ function UISpinBox:down()
|
||||
end
|
||||
|
||||
function UISpinBox:setValue(value, dontSignal)
|
||||
if type(value) == "string" then
|
||||
value = tonumber(value)
|
||||
end
|
||||
value = value or 0
|
||||
value = math.max(math.min(self.maximum, value), self.minimum)
|
||||
|
||||
|
@@ -6,6 +6,7 @@ contentsPanel = nil
|
||||
configWindow = nil
|
||||
configEditorText = nil
|
||||
configList = nil
|
||||
botTabs = nil
|
||||
botPanel = nil
|
||||
local botMessages = nil
|
||||
local configCopy = ""
|
||||
@@ -32,6 +33,17 @@ function init()
|
||||
onKeyPress = botKeyPress })
|
||||
|
||||
connect(Tile, { onAddThing = botAddThing, onRemoveThing = botRemoveThing })
|
||||
|
||||
connect(Creature, {
|
||||
onAppear = botCreatureAppear,
|
||||
onDisappear =botCreatureDisappear,
|
||||
onPositionChange = botCreaturePositionChange,
|
||||
onHealthPercentChange = botCraetureHealthPercentChange
|
||||
})
|
||||
connect(LocalPlayer, {
|
||||
onPositionChange = botCreaturePositionChange,
|
||||
onHealthPercentChange = botCraetureHealthPercentChange
|
||||
})
|
||||
|
||||
botConfigFile = g_configs.create("/bot.otml")
|
||||
local config = botConfigFile:get("config")
|
||||
@@ -53,18 +65,20 @@ function init()
|
||||
botWindow = g_ui.loadUI('bot', modules.game_interface.getRightPanel())
|
||||
botWindow:setup()
|
||||
|
||||
contentsPanel = botWindow:getChildById('contentsPanel')
|
||||
configList = contentsPanel:getChildById('config')
|
||||
enableButton = contentsPanel:getChildById('enableButton')
|
||||
statusLabel = contentsPanel:getChildById('statusLabel')
|
||||
botMessages = contentsPanel:getChildById('messages')
|
||||
botPanel = contentsPanel:getChildById('botPanel')
|
||||
|
||||
contentsPanel = botWindow.contentsPanel
|
||||
configList = contentsPanel.config
|
||||
enableButton = contentsPanel.enableButton
|
||||
statusLabel = contentsPanel.statusLabel
|
||||
botMessages = contentsPanel.messages
|
||||
botTabs = contentsPanel.botTabs
|
||||
botPanel = contentsPanel.botPanel
|
||||
botTabs:setContentWidget(botPanel)
|
||||
|
||||
configWindow = g_ui.displayUI('config')
|
||||
configWindow:hide()
|
||||
|
||||
configEditorText = configWindow:getChildById('text')
|
||||
configTab = configWindow:getChildById('configTab')
|
||||
configEditorText = configWindow.text
|
||||
configTab = configWindow.configTab
|
||||
|
||||
configTab.onTabChange = editorTabChanged
|
||||
|
||||
@@ -91,8 +105,27 @@ function init()
|
||||
end
|
||||
|
||||
function saveConfig()
|
||||
botConfigFile:set("config", json.encode(botConfig))
|
||||
botConfigFile:save()
|
||||
local status, result = pcall(function()
|
||||
botConfigFile:set("config", json.encode(botConfig))
|
||||
botConfigFile:save()
|
||||
end)
|
||||
if not status then
|
||||
errorOccured = true
|
||||
-- try to fix it
|
||||
local extraInfo = ""
|
||||
for i = 1, #botConfig.configs do
|
||||
if botConfig.configs[i].storage then
|
||||
local status, result = pcall(function() json.encode(botConfig.configs[i].storage) end)
|
||||
if not status then
|
||||
botConfig.configs[i].storage = nil
|
||||
extraInfo = extraInfo .. "\nLocal storage of config " .. i .. " has been erased due to invalid data"
|
||||
end
|
||||
end
|
||||
end
|
||||
statusLabel:setText("Error while saving config and user storage:\n" .. result .. extraInfo .. "\n\n" .. "Try to restart bot")
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function terminate()
|
||||
@@ -107,6 +140,17 @@ function terminate()
|
||||
|
||||
disconnect(Tile, { onAddThing = botAddThing, onRemoveThing = botRemoveThing })
|
||||
|
||||
disconnect(Creature, {
|
||||
onAppear = botCreatureAppear,
|
||||
onDisappear =botCreatureDisappear,
|
||||
onPositionChange = botCreaturePositionChange,
|
||||
onHealthPercentChange = botCraetureHealthPercentChange
|
||||
})
|
||||
disconnect(LocalPlayer, {
|
||||
onPositionChange = botCreaturePositionChange,
|
||||
onHealthPercentChange = botCraetureHealthPercentChange
|
||||
})
|
||||
|
||||
removeEvent(executeEvent)
|
||||
removeEvent(checkMsgsEvent)
|
||||
|
||||
@@ -259,13 +303,15 @@ end
|
||||
|
||||
function clearConfig()
|
||||
compiledConfig = nil
|
||||
botPanel:destroyChildren()
|
||||
|
||||
botTabs:clearTabs()
|
||||
botTabs:setOn(false)
|
||||
|
||||
botMessages:destroyChildren()
|
||||
botMessages:updateLayout()
|
||||
end
|
||||
|
||||
function refreshConfig()
|
||||
clearConfig()
|
||||
configWindow:hide()
|
||||
|
||||
botConfig.selectedConfig = configList.currentIndex
|
||||
@@ -273,8 +319,13 @@ function refreshConfig()
|
||||
return
|
||||
end
|
||||
|
||||
saveConfig()
|
||||
if not saveConfig() then
|
||||
clearConfig()
|
||||
return
|
||||
end
|
||||
|
||||
clearConfig()
|
||||
|
||||
local config = botConfig.configs[configList.currentIndex]
|
||||
if not config.storage then
|
||||
config.storage = {}
|
||||
@@ -286,7 +337,7 @@ function refreshConfig()
|
||||
end
|
||||
errorOccured = false
|
||||
g_game.enableTileThingLuaCallback(false)
|
||||
local status, result = pcall(function() return executeBot(config.script, config.storage, botPanel, botMsgCallback) end)
|
||||
local status, result = pcall(function() return executeBot(config.script, config.storage, botTabs, botMsgCallback) end)
|
||||
if not status then
|
||||
errorOccured = true
|
||||
statusLabel:setText("Error: " .. tostring(result))
|
||||
@@ -342,9 +393,8 @@ function checkMsgs()
|
||||
end
|
||||
end
|
||||
|
||||
function botKeyDown(widget, keyCode, keyboardModifiers)
|
||||
if keyCode == KeyUnknown or compiledConfig == nil then return false end
|
||||
local status, result = pcall(function() compiledConfig.callbacks.onKeyDown(keyCode, keyboardModifiers) end)
|
||||
function safeBotCall(func)
|
||||
local status, result = pcall(func)
|
||||
if not status then
|
||||
errorOccured = true
|
||||
statusLabel:setText("Error: " .. result)
|
||||
@@ -352,52 +402,55 @@ function botKeyDown(widget, keyCode, keyboardModifiers)
|
||||
return false
|
||||
end
|
||||
|
||||
function botKeyDown(widget, keyCode, keyboardModifiers)
|
||||
if compiledConfig == nil then return false end
|
||||
if keyCode == KeyUnknown then return end
|
||||
safeBotCall(function() compiledConfig.callbacks.onKeyDown(keyCode, keyboardModifiers) end)
|
||||
end
|
||||
|
||||
function botKeyUp(widget, keyCode, keyboardModifiers)
|
||||
if keyCode == KeyUnknown or compiledConfig == nil then return false end
|
||||
local status, result = pcall(function() compiledConfig.callbacks.onKeyUp(keyCode, keyboardModifiers) end)
|
||||
if not status then
|
||||
errorOccured = true
|
||||
statusLabel:setText("Error: " .. result)
|
||||
end
|
||||
return false
|
||||
if compiledConfig == nil then return false end
|
||||
if keyCode == KeyUnknown then return end
|
||||
safeBotCall(function() compiledConfig.callbacks.onKeyUp(keyCode, keyboardModifiers) end)
|
||||
end
|
||||
|
||||
function botKeyPress(widget, keyCode, keyboardModifiers, autoRepeatTicks)
|
||||
if keyCode == KeyUnknown or compiledConfig == nil then return false end
|
||||
local status, result = pcall(function() compiledConfig.callbacks.onKeyPress(keyCode, keyboardModifiers, autoRepeatTicks) end)
|
||||
if not status then
|
||||
errorOccured = true
|
||||
statusLabel:setText("Error: " .. result)
|
||||
end
|
||||
return false
|
||||
if compiledConfig == nil then return false end
|
||||
if keyCode == KeyUnknown then return end
|
||||
safeBotCall(function() compiledConfig.callbacks.onKeyPress(keyCode, keyboardModifiers, autoRepeatTicks) end)
|
||||
end
|
||||
|
||||
function botOnTalk(name, level, mode, text, channelId, pos)
|
||||
if compiledConfig == nil then return false end
|
||||
local status, result = pcall(function() compiledConfig.callbacks.onTalk(name, level, mode, text, channelId, pos) end)
|
||||
if not status then
|
||||
errorOccured = true
|
||||
statusLabel:setText("Error: " .. result)
|
||||
end
|
||||
return false
|
||||
safeBotCall(function() compiledConfig.callbacks.onTalk(name, level, mode, text, channelId, pos) end)
|
||||
end
|
||||
|
||||
function botAddThing(tile, thing, asd)
|
||||
function botAddThing(tile, thing)
|
||||
if compiledConfig == nil then return false end
|
||||
local status, result = pcall(function() compiledConfig.callbacks.onAddThing(tile, thing) end)
|
||||
if not status then
|
||||
errorOccured = true
|
||||
statusLabel:setText("Error: " .. result)
|
||||
end
|
||||
return false
|
||||
safeBotCall(function() compiledConfig.callbacks.onAddThing(tile, thing) end)
|
||||
end
|
||||
|
||||
function botRemoveThing(tile, thing)
|
||||
if compiledConfig == nil then return false end
|
||||
local status, result = pcall(function() compiledConfig.callbacks.onRemoveThing(tile, thing) end)
|
||||
if not status then
|
||||
errorOccured = true
|
||||
statusLabel:setText("Error: " .. result)
|
||||
end
|
||||
return false
|
||||
end
|
||||
safeBotCall(function() compiledConfig.callbacks.onRemoveThing(tile, thing) end)
|
||||
end
|
||||
|
||||
function botCreatureAppear(creature)
|
||||
if compiledConfig == nil then return false end
|
||||
safeBotCall(function() compiledConfig.callbacks.onCreatureAppear(creature) end)
|
||||
end
|
||||
|
||||
function botCreatureDisappear(creature)
|
||||
if compiledConfig == nil then return false end
|
||||
safeBotCall(function() compiledConfig.callbacks.onCreatureDisappear(creature) end)
|
||||
end
|
||||
|
||||
function botCreaturePositionChange(creature, newPos, oldPos)
|
||||
if compiledConfig == nil then return false end
|
||||
safeBotCall(function() compiledConfig.callbacks.onCreaturePositionChange(creature, newPos, oldPos) end)
|
||||
end
|
||||
|
||||
function botCraetureHealthPercentChange(creature, healthPercent)
|
||||
if compiledConfig == nil then return false end
|
||||
safeBotCall(function() compiledConfig.callbacks.onCreatureHealthPercentChange(creature, healthPercent) end)
|
||||
end
|
||||
|
@@ -3,12 +3,14 @@ BotButton < Button
|
||||
|
||||
BotSwitch < Button
|
||||
margin-top: 2
|
||||
height: 20
|
||||
image-color: green
|
||||
$!on:
|
||||
image-color: red
|
||||
|
||||
BotLabel < Label
|
||||
margin-top: 2
|
||||
height: 20
|
||||
text-auto-resize: true
|
||||
text-align: center
|
||||
text-wrap: true
|
||||
@@ -18,17 +20,20 @@ BotItem < UIItem
|
||||
size: 32 32
|
||||
border: 1 black
|
||||
&selectable: true
|
||||
|
||||
BotTextEdit < TextEdit
|
||||
@onClick: modules.game_textedit.show(self)
|
||||
text-align: center
|
||||
multiline: false
|
||||
|
||||
BotSeparator < HorizontalSeparator
|
||||
margin-top: 5
|
||||
margin-bottom: 3
|
||||
|
||||
|
||||
BotPanel < Panel
|
||||
margin-top: 2
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
|
||||
MiniWindow
|
||||
id: botWindow
|
||||
!text: tr('Bot')
|
||||
@@ -99,12 +104,28 @@ MiniWindow
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
|
||||
MoveableTabBar
|
||||
id: botTabs
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
tab-spacing: 2
|
||||
height: 20
|
||||
movable: false
|
||||
|
||||
$on:
|
||||
visible: true
|
||||
margin-top: 2
|
||||
|
||||
$!on:
|
||||
visible: false
|
||||
margin-top: -20
|
||||
|
||||
Panel
|
||||
id: botPanel
|
||||
margin-top: 2
|
||||
anchors.top: prev.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
id: botPanel
|
||||
layout:
|
||||
type: verticalBox
|
@@ -1,82 +1,52 @@
|
||||
botDefaultConfig = {
|
||||
configs = {
|
||||
{name = "Example", script = [=[
|
||||
--#Example
|
||||
info("Tested on 10.99")
|
||||
--Example
|
||||
|
||||
--#main
|
||||
local widget = setupUI([[
|
||||
Panel
|
||||
id: redPanel
|
||||
background: red
|
||||
margin-top: 10
|
||||
margin-bottom: 10
|
||||
height: 100
|
||||
|
||||
Label
|
||||
anchors.fill: parent
|
||||
text: custom ui, otml based
|
||||
text-align: center
|
||||
]])
|
||||
|
||||
Panels.Haste()
|
||||
Panels.ManaShield()
|
||||
Panels.Health()
|
||||
Panels.HealthItem()
|
||||
Panels.ManaItem()
|
||||
Panels.ManaItem()
|
||||
Panels.AntiParalyze()
|
||||
|
||||
local tab2 = addTab("Another Tab")
|
||||
addButton("button1", "test button on 2nd tab", nil, tab2)
|
||||
|
||||
local tab3 = addTab("3th tab")
|
||||
addLabel("label1", "Label on 3th tab", tab3)
|
||||
Panels.Turning(tab3)
|
||||
|
||||
--#macros
|
||||
macro(5000, "macro send link", "f5", function()
|
||||
g_game.talk("macro test - https://github.com/OTCv8/otclient_bot")
|
||||
g_game.talk("bot is hiding 50% of effects as example, say exevo gran mas vis")
|
||||
end)
|
||||
|
||||
macro(1000, "flag tiles", function()
|
||||
player:getTile():setText("Hello =)", "red")
|
||||
end)
|
||||
|
||||
macro(25, "auto healing", function()
|
||||
if hppercent() < 80 then
|
||||
say("exura")
|
||||
delay(1000) -- not calling this macro for next 1s
|
||||
end
|
||||
end)
|
||||
|
||||
addSeparator("spe0")
|
||||
local helloLabel = addLabel("helloLabel", "", tab2)
|
||||
|
||||
macro(1000, "example macro (time)", nil, function()
|
||||
helloLabel:setText("Time from start: " .. now)
|
||||
end, tab2)
|
||||
--#hotkeys
|
||||
hotkey('y', 'test hotkey', function() g_game.talk('hotkey elo') end)
|
||||
singlehotkey('x', 'single hotkey', function() g_game.talk('single hotkey') end)
|
||||
|
||||
singlehotkey('=', "Zoom in map", function () zoomIn() end)
|
||||
singlehotkey('-', "Zoom out map", function () zoomOut() end)
|
||||
|
||||
--#callbacks
|
||||
onAddThing(function(tile, thing)
|
||||
if thing:isItem() and thing:getId() == 2129 then
|
||||
local pos = tile:getPosition().x .. "," .. tile:getPosition().y .. "," .. tile:getPosition().z
|
||||
if not storage[pos] or storage[pos] < now then
|
||||
storage[pos] = now + 20000
|
||||
end
|
||||
tile:setTimer(storage[pos] - now)
|
||||
end
|
||||
hotkey("f5", "example hotkey", function()
|
||||
info("Wow, you clicked f5 hotkey")
|
||||
end)
|
||||
|
||||
-- hide 50% of effects
|
||||
onAddThing(function(tile, thing)
|
||||
if thing:isEffect() and math.random(1, 2) == 1 then
|
||||
thing:hide()
|
||||
end
|
||||
singlehotkey("f6", "example hotkey2", function()
|
||||
info("Wow, you clicked f6 singlehotkey")
|
||||
end)
|
||||
--#callbacks
|
||||
|
||||
local positionLabel = addLabel("positionLabel", "")
|
||||
onPlayerPositionChange(function()
|
||||
positionLabel:setText("Pos: " .. posx() .. "," .. posy() .. "," .. posz())
|
||||
end)
|
||||
|
||||
listen(player:getName(), function(text)
|
||||
info("you said: " .. text)
|
||||
end)
|
||||
|
||||
--#other
|
||||
addLabel("label1", "Test label 1")
|
||||
addSeparator("sep1")
|
||||
addLabel("label2", "Test label 2")
|
||||
|
||||
storage.clicks = 0
|
||||
addButton("button1", "Click me", function()
|
||||
storage.clicks = storage.clicks + 1
|
||||
ui.button1:setText("Clicks: " .. storage.clicks)
|
||||
end)
|
||||
|
||||
HTTP.getJSON("https://api.ipify.org/?format=json", function(data, err)
|
||||
if err then
|
||||
@@ -85,6 +55,7 @@ HTTP.getJSON("https://api.ipify.org/?format=json", function(data, err)
|
||||
end
|
||||
info("HTTP: My IP is: " .. tostring(data['ip']))
|
||||
end)
|
||||
|
||||
|
||||
|
||||
]=]},
|
||||
|
@@ -1,6 +1,8 @@
|
||||
function executeBot(config, storage, panel, msgCallback)
|
||||
function executeBot(config, storage, tabs, msgCallback)
|
||||
local context = {}
|
||||
context.panel = panel
|
||||
context.tabs = tabs
|
||||
context.panel = context.tabs:addTab("Main", g_ui.createWidget('BotPanel')).tabPanel
|
||||
|
||||
context.storage = storage
|
||||
if context.storage._macros == nil then
|
||||
context.storage._macros = {} -- active macros
|
||||
@@ -16,9 +18,12 @@ function executeBot(config, storage, panel, msgCallback)
|
||||
onKeyPress = {},
|
||||
onTalk = {},
|
||||
onAddThing = {},
|
||||
onRemoveThing = {}
|
||||
onRemoveThing = {},
|
||||
onCreatureAppear = {},
|
||||
onCreatureDisappear = {},
|
||||
onCreaturePositionChange = {},
|
||||
onCreatureHealthPercentChange = {}
|
||||
}
|
||||
context.ui = {}
|
||||
|
||||
-- basic functions & classes
|
||||
context.print = print
|
||||
@@ -44,265 +49,20 @@ function executeBot(config, storage, panel, msgCallback)
|
||||
context.info = function(text) return msgCallback("info", tostring(text)) end
|
||||
context.warn = function(text) return msgCallback("warn", tostring(text)) end
|
||||
context.error = function(text) return msgCallback("error", tostring(text)) end
|
||||
context.warning = context.warn
|
||||
|
||||
-- UI
|
||||
context.setupUI = function(otml, parent)
|
||||
if parent == nil then
|
||||
parent = context.panel
|
||||
end
|
||||
local widget = g_ui.loadUIFromString(otml, parent)
|
||||
if parent == context.panel and widget:getId() then
|
||||
context.ui[widget:getId()] = widget
|
||||
end
|
||||
return widget
|
||||
end
|
||||
|
||||
context.addSwitch = function(id, text, onClickCallback)
|
||||
local switch = g_ui.createWidget('BotSwitch', context.panel)
|
||||
switch:setId(id)
|
||||
switch:setText(text)
|
||||
switch.onClick = onClickCallback
|
||||
context.ui[id] = switch
|
||||
return switch
|
||||
end
|
||||
|
||||
context.addButton = function(id, text, onClickCallback)
|
||||
local button = g_ui.createWidget('BotButton', context.panel)
|
||||
button:setId(id)
|
||||
button:setText(text)
|
||||
button.onClick = onClickCallback
|
||||
context.ui[id] = button
|
||||
return button
|
||||
end
|
||||
|
||||
context.addLabel = function(id, text)
|
||||
local label = g_ui.createWidget('BotLabel', context.panel)
|
||||
label:setId(id)
|
||||
label:setText(text)
|
||||
context.ui[id] = label
|
||||
return label
|
||||
end
|
||||
|
||||
context.addSeparator = function(id)
|
||||
local separator = g_ui.createWidget('BotSeparator', context.panel)
|
||||
separator:setId(id)
|
||||
context.ui[id] = separator
|
||||
return separator
|
||||
end
|
||||
|
||||
context._addMacroSwitch = function(name, keys)
|
||||
local text = name
|
||||
if keys:len() > 0 then
|
||||
text = name .. " [" .. keys .. "]"
|
||||
end
|
||||
local switch = context.addSwitch("macro_" .. #context._macros, text, function(widget)
|
||||
context.storage._macros[name] = not context.storage._macros[name]
|
||||
widget:setOn(context.storage._macros[name])
|
||||
end)
|
||||
switch:setOn(context.storage._macros[name])
|
||||
return switch
|
||||
end
|
||||
|
||||
context._addHotkeySwitch = function(name, keys)
|
||||
local text = name
|
||||
if keys:len() > 0 then
|
||||
text = name .. " [" .. keys .. "]"
|
||||
end
|
||||
local switch = context.addSwitch("hotkey_" .. #context._hotkeys, text, nil)
|
||||
switch:setOn(false)
|
||||
return switch
|
||||
end
|
||||
|
||||
-- MAIN BOT FUNCTION
|
||||
-- macro(timeout, callback)
|
||||
-- macro(timeout, name, callback)
|
||||
-- macro(timeout, name, hotkey, callback)
|
||||
context.macro = function(timeout, name, hotkey, callback)
|
||||
if type(timeout) ~= 'number' or timeout < 1 then
|
||||
error("Invalid timeout for macro: " .. tostring(timeout))
|
||||
end
|
||||
if type(name) == 'function' then
|
||||
callback = name
|
||||
name = ""
|
||||
hotkey = ""
|
||||
elseif type(hotkey) == 'function' then
|
||||
callback = hotkey
|
||||
hotkey = ""
|
||||
elseif type(callback) ~= 'function' then
|
||||
error("Invalid callback for macro: " .. tostring(callback))
|
||||
end
|
||||
if type(name) ~= 'string' or type(hotkey) ~= 'string' then
|
||||
error("Invalid name or hotkey for macro")
|
||||
end
|
||||
if hotkey:len() > 0 then
|
||||
hotkey = retranslateKeyComboDesc(hotkey)
|
||||
end
|
||||
|
||||
local switch = nil
|
||||
if name:len() > 0 then
|
||||
if context.storage._macros[name] == nil then
|
||||
context.storage._macros[name] = true
|
||||
end
|
||||
switch = context._addMacroSwitch(name, hotkey)
|
||||
end
|
||||
|
||||
table.insert(context._macros, {
|
||||
timeout = timeout,
|
||||
name = name,
|
||||
callback = callback,
|
||||
lastExecution = context.now,
|
||||
hotkey = hotkey,
|
||||
switch = switch
|
||||
})
|
||||
return context._macros[#context._macros]
|
||||
end
|
||||
|
||||
-- hotkey(keys, callback)
|
||||
-- hotkey(keys, name, callback)
|
||||
context.hotkey = function(keys, name, callback)
|
||||
if type(name) == 'function' then
|
||||
callback = name
|
||||
name = ""
|
||||
end
|
||||
keys = retranslateKeyComboDesc(keys)
|
||||
if not keys or #keys == 0 then
|
||||
return context.error("Invalid hotkey keys " .. tostring(name))
|
||||
end
|
||||
if context._hotkeys[keys] then
|
||||
return context.error("Duplicated hotkey: " .. keys)
|
||||
end
|
||||
|
||||
local switch = nil
|
||||
if name:len() > 0 then
|
||||
switch = context._addHotkeySwitch(name, keys)
|
||||
end
|
||||
|
||||
context._hotkeys[keys] = {
|
||||
name = name,
|
||||
callback = callback,
|
||||
lastExecution = context.now,
|
||||
switch = switch,
|
||||
single = false
|
||||
}
|
||||
return context._hotkeys[keys]
|
||||
end
|
||||
|
||||
-- singlehotkey(keys, callback)
|
||||
-- singlehotkey(keys, name, callback)
|
||||
context.singlehotkey = function(keys, name, callback)
|
||||
if type(name) == 'function' then
|
||||
callback = name
|
||||
name = ""
|
||||
end
|
||||
keys = retranslateKeyComboDesc(keys)
|
||||
if not keys or #keys == 0 then
|
||||
return context.error("Invalid hotkey keys " .. tostring(name))
|
||||
end
|
||||
if context._hotkeys[keys] then
|
||||
return context.error("Duplicated hotkey: " .. keys)
|
||||
end
|
||||
|
||||
local switch = nil
|
||||
if name:len() > 0 then
|
||||
switch = context._addHotkeySwitch(name, keys)
|
||||
end
|
||||
|
||||
context._hotkeys[keys] = {
|
||||
name = name,
|
||||
callback = callback,
|
||||
lastExecution = context.now,
|
||||
switch = switch,
|
||||
single = true
|
||||
}
|
||||
return context._hotkeys[keys]
|
||||
end
|
||||
|
||||
-- schedule(timeout, callback)
|
||||
context.schedule = function(timeout, callback)
|
||||
local extecute_time = g_clock.millis() + timeout
|
||||
table.insert(context._scheduler, {
|
||||
execution = extecute_time,
|
||||
callback = callback
|
||||
})
|
||||
table.sort(context._scheduler, function(a, b) return a.execution < b.execution end)
|
||||
end
|
||||
|
||||
-- callback(callbackType, callback)
|
||||
context.callback = function(callbackType, callback)
|
||||
if not context._callbacks[callbackType] then
|
||||
return error("Wrong callback type: " .. callbackType)
|
||||
end
|
||||
if callbackType == "onAddThing" or callbackType == "onRemoveThing" then
|
||||
g_game.enableTileThingLuaCallback(true)
|
||||
end
|
||||
local callbackData = {}
|
||||
table.insert(context._callbacks[callbackType], function(...)
|
||||
if not callbackData.delay or callbackData.delay < context.now then
|
||||
context._currentExecution = callbackData
|
||||
callback(...)
|
||||
context._currentExecution = nil
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- onKeyDown(callback) -- callback = function(keys)
|
||||
context.onKeyDown = function(callback)
|
||||
return context.callback("onKeyDown", callback)
|
||||
end
|
||||
|
||||
-- onKeyPress(callback) -- callback = function(keys)
|
||||
context.onKeyPress = function(callback)
|
||||
return context.callback("onKeyPress", callback)
|
||||
end
|
||||
|
||||
-- onKeyUp(callback) -- callback = function(keys)
|
||||
context.onKeyUp = function(callback)
|
||||
return context.callback("onKeyUp", callback)
|
||||
end
|
||||
|
||||
-- onTalk(callback) -- callback = function(name, level, mode, text, channelId, pos)
|
||||
context.onTalk = function(callback)
|
||||
return context.callback("onTalk", callback)
|
||||
end
|
||||
|
||||
-- onAddThing(callback) -- callback = function(tile, thing)
|
||||
context.onAddThing = function(callback)
|
||||
return context.callback("onAddThing", callback)
|
||||
end
|
||||
|
||||
-- onRemoveThing(callback) -- callback = function(tile, thing)
|
||||
context.onRemoveThing = function(callback)
|
||||
return context.callback("onRemoveThing", callback)
|
||||
end
|
||||
|
||||
-- listen(name, callback) -- callback = function(text, channelId, pos)
|
||||
context.listen = function(name, callback)
|
||||
if not name then return context.error("listen: invalid name") end
|
||||
name = name:lower()
|
||||
context.onTalk(function(name2, level, mode, text, channelId, pos)
|
||||
if name == name2:lower() then
|
||||
callback(text, channelId, pos)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- delay(duration) -- block execution of current macro/hotkey/callback for x milliseconds
|
||||
context.delay = function(duration)
|
||||
if not context._currentExecution then
|
||||
return context.error("Invalid usage of delay function, it should be used inside callbacks")
|
||||
end
|
||||
context._currentExecution.delay = context.now + duration
|
||||
end
|
||||
context.warning = context.warn
|
||||
|
||||
-- init context
|
||||
context.now = g_clock.millis()
|
||||
context.time = g_clock.millis()
|
||||
context.player = g_game.getLocalPlayer()
|
||||
|
||||
require("functions.lua")
|
||||
setupFunctions(context)
|
||||
|
||||
-- init functions
|
||||
G.botContext = context
|
||||
dofiles("functions")
|
||||
context.Panels = {}
|
||||
dofiles("panels")
|
||||
G.botContext = nil
|
||||
|
||||
-- run script
|
||||
assert(load(config, nil, nil, context))()
|
||||
|
||||
@@ -313,11 +73,8 @@ function executeBot(config, storage, panel, msgCallback)
|
||||
|
||||
for i, macro in ipairs(context._macros) do
|
||||
if macro.lastExecution + macro.timeout <= context.now and (macro.name == nil or macro.name:len() < 1 or context.storage._macros[macro.name]) then
|
||||
if not macro.delay or macro.delay < context.now then
|
||||
macro.lastExecution = context.now
|
||||
context._currentExecution = context._macros[i]
|
||||
macro.callback()
|
||||
context._currentExecution = nil
|
||||
if macro.callback() then
|
||||
macro.lastExecution = context.now
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -338,11 +95,8 @@ function executeBot(config, storage, panel, msgCallback)
|
||||
local hotkey = context._hotkeys[keyDesc]
|
||||
if hotkey then
|
||||
if hotkey.single then
|
||||
if not hotkey.delay or hotkey.delay < context.now then
|
||||
hotkey.lastExecution = context.now
|
||||
context._currentExecution = hotkey
|
||||
hotkey.callback()
|
||||
context._currentExecution = nil
|
||||
if hotkey.callback() then
|
||||
hotkey.lastExecution = context.now
|
||||
end
|
||||
end
|
||||
if hotkey.switch then
|
||||
@@ -369,11 +123,8 @@ function executeBot(config, storage, panel, msgCallback)
|
||||
local keyDesc = determineKeyComboDesc(keyCode, keyboardModifiers)
|
||||
local hotkey = context._hotkeys[keyDesc]
|
||||
if hotkey and not hotkey.single then
|
||||
if not hotkey.delay or hotkey.delay < context.now then
|
||||
hotkey.lastExecution = context.now
|
||||
context._currentExecution = hotkey
|
||||
hotkey.callback()
|
||||
context._currentExecution = nil
|
||||
if hotkey.callback() then
|
||||
hotkey.lastExecution = context.now
|
||||
end
|
||||
end
|
||||
for i, callback in ipairs(context._callbacks.onKeyPress) do
|
||||
@@ -394,6 +145,26 @@ function executeBot(config, storage, panel, msgCallback)
|
||||
for i, callback in ipairs(context._callbacks.onRemoveThing) do
|
||||
callback(tile, thing)
|
||||
end
|
||||
end,
|
||||
onCreatureAppear = function(creature)
|
||||
for i, callback in ipairs(context._callbacks.onCreatureAppear) do
|
||||
callback(creature)
|
||||
end
|
||||
end,
|
||||
onCreatureDisappear = function(creature)
|
||||
for i, callback in ipairs(context._callbacks.onCreatureDisappear) do
|
||||
callback(creature)
|
||||
end
|
||||
end,
|
||||
onCreaturePositionChange = function(creature, newPos, oldPos)
|
||||
for i, callback in ipairs(context._callbacks.onCreaturePositionChange) do
|
||||
callback(creature, newPos, oldPos)
|
||||
end
|
||||
end,
|
||||
onCreatureHealthPercentChange = function(creature, healthPercent)
|
||||
for i, callback in ipairs(context._callbacks.onCreatureHealthPercentChange) do
|
||||
callback(creature, healthPercent)
|
||||
end
|
||||
end
|
||||
}
|
||||
}
|
||||
|
101
modules/game_bot/functions/callbacks.lua
Normal file
101
modules/game_bot/functions/callbacks.lua
Normal file
@@ -0,0 +1,101 @@
|
||||
local context = G.botContext
|
||||
|
||||
-- callback(callbackType, callback)
|
||||
context.callback = function(callbackType, callback)
|
||||
if not context._callbacks[callbackType] then
|
||||
return error("Wrong callback type: " .. callbackType)
|
||||
end
|
||||
if callbackType == "onAddThing" or callbackType == "onRemoveThing" then
|
||||
g_game.enableTileThingLuaCallback(true)
|
||||
end
|
||||
local callbackData = {}
|
||||
table.insert(context._callbacks[callbackType], function(...)
|
||||
if not callbackData.delay or callbackData.delay < context.now then
|
||||
context._currentExecution = callbackData
|
||||
callback(...)
|
||||
context._currentExecution = nil
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- onKeyDown(callback) -- callback = function(keys)
|
||||
context.onKeyDown = function(callback)
|
||||
return context.callback("onKeyDown", callback)
|
||||
end
|
||||
|
||||
-- onKeyPress(callback) -- callback = function(keys)
|
||||
context.onKeyPress = function(callback)
|
||||
return context.callback("onKeyPress", callback)
|
||||
end
|
||||
|
||||
-- onKeyUp(callback) -- callback = function(keys)
|
||||
context.onKeyUp = function(callback)
|
||||
return context.callback("onKeyUp", callback)
|
||||
end
|
||||
|
||||
-- onTalk(callback) -- callback = function(name, level, mode, text, channelId, pos)
|
||||
context.onTalk = function(callback)
|
||||
return context.callback("onTalk", callback)
|
||||
end
|
||||
|
||||
-- onAddThing(callback) -- callback = function(tile, thing)
|
||||
context.onAddThing = function(callback)
|
||||
return context.callback("onAddThing", callback)
|
||||
end
|
||||
|
||||
-- onRemoveThing(callback) -- callback = function(tile, thing)
|
||||
context.onRemoveThing = function(callback)
|
||||
return context.callback("onRemoveThing", callback)
|
||||
end
|
||||
|
||||
-- onCreatureAppear(callback) -- callback = function(creature)
|
||||
context.onCreatureAppear = function(callback)
|
||||
return context.callback("onCreatureAppear", callback)
|
||||
end
|
||||
|
||||
-- onCreatureDisappear(callback) -- callback = function(creature)
|
||||
context.onCreatureDisappear = function(callback)
|
||||
return context.callback("onCreatureDisappear", callback)
|
||||
end
|
||||
|
||||
-- onCreaturePositionChange(callback) -- callback = function(creature, newPos, oldPos)
|
||||
context.onCreaturePositionChange = function(callback)
|
||||
return context.callback("onCreaturePositionChange", callback)
|
||||
end
|
||||
|
||||
-- onCreatureHealthPercentChange(callback) -- callback = function(creature, healthPercent)
|
||||
context.onCreatureHealthPercentChange = function(callback)
|
||||
return context.callback("onCreatureHealthPercentChange", callback)
|
||||
end
|
||||
|
||||
|
||||
-- custom callbacks
|
||||
|
||||
-- listen(name, callback) -- callback = function(text, channelId, pos)
|
||||
context.listen = function(name, callback)
|
||||
if not name then return context.error("listen: invalid name") end
|
||||
name = name:lower()
|
||||
context.onTalk(function(name2, level, mode, text, channelId, pos)
|
||||
if name == name2:lower() then
|
||||
callback(text, channelId, pos)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- onPlayerPositionChange(callback) -- callback = function(newPos, oldPos)
|
||||
context.onPlayerPositionChange = function(callback)
|
||||
context.onCreaturePositionChange(function(creature, newPos, oldPos)
|
||||
if creature == context.player then
|
||||
callback(newPos, oldPos)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- onPlayerHealthChange(callback) -- callback = function(healthPercent)
|
||||
context.onPlayerHealthChange = function(callback)
|
||||
context.onCreatureHealthPercentChange(function(creature, healthPercent)
|
||||
if creature == context.player then
|
||||
callback(healthPercent)
|
||||
end
|
||||
end)
|
||||
end
|
136
modules/game_bot/functions/main.lua
Normal file
136
modules/game_bot/functions/main.lua
Normal file
@@ -0,0 +1,136 @@
|
||||
local context = G.botContext
|
||||
|
||||
-- MAIN BOT FUNCTION
|
||||
-- macro(timeout, callback)
|
||||
-- macro(timeout, name, callback)
|
||||
-- macro(timeout, name, hotkey, callback)
|
||||
-- macro(timeout, name, hotkey, callback, parent)
|
||||
context.macro = function(timeout, name, hotkey, callback, parent)
|
||||
if not parent then
|
||||
parent = context.panel
|
||||
end
|
||||
|
||||
if type(timeout) ~= 'number' or timeout < 1 then
|
||||
error("Invalid timeout for macro: " .. tostring(timeout))
|
||||
end
|
||||
if type(name) == 'function' then
|
||||
callback = name
|
||||
name = ""
|
||||
hotkey = ""
|
||||
elseif type(hotkey) == 'function' then
|
||||
callback = hotkey
|
||||
hotkey = ""
|
||||
elseif type(callback) ~= 'function' then
|
||||
error("Invalid callback for macro: " .. tostring(callback))
|
||||
end
|
||||
if hotkey == nil then
|
||||
hotkey = ""
|
||||
end
|
||||
if type(name) ~= 'string' or type(hotkey) ~= 'string' then
|
||||
error("Invalid name or hotkey for macro")
|
||||
end
|
||||
if hotkey:len() > 0 then
|
||||
hotkey = retranslateKeyComboDesc(hotkey)
|
||||
end
|
||||
|
||||
local switch = nil
|
||||
if name:len() > 0 then
|
||||
if context.storage._macros[name] == nil then
|
||||
context.storage._macros[name] = true
|
||||
end
|
||||
switch = context._addMacroSwitch(name, hotkey, parent)
|
||||
end
|
||||
|
||||
table.insert(context._macros, {
|
||||
timeout = timeout,
|
||||
name = name,
|
||||
lastExecution = context.now,
|
||||
hotkey = hotkey,
|
||||
switch = switch
|
||||
})
|
||||
|
||||
local macroData = context._macros[#context._macros]
|
||||
macroData.callback = function()
|
||||
if not macroData.delay or macroData.delay < context.now then
|
||||
context._currentExecution = macroData
|
||||
callback()
|
||||
context._currentExecution = nil
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return macroData
|
||||
end
|
||||
|
||||
-- hotkey(keys, callback)
|
||||
-- hotkey(keys, name, callback)
|
||||
-- hotkey(keys, name, callback, parent)
|
||||
context.hotkey = function(keys, name, callback, single, parent)
|
||||
if not parent then
|
||||
parent = context.panel
|
||||
end
|
||||
if type(name) == 'function' then
|
||||
callback = name
|
||||
name = ""
|
||||
end
|
||||
keys = retranslateKeyComboDesc(keys)
|
||||
if not keys or #keys == 0 then
|
||||
return context.error("Invalid hotkey keys " .. tostring(name))
|
||||
end
|
||||
if context._hotkeys[keys] then
|
||||
return context.error("Duplicated hotkey: " .. keys)
|
||||
end
|
||||
|
||||
local switch = nil
|
||||
if name:len() > 0 then
|
||||
switch = context._addHotkeySwitch(name, keys, parent)
|
||||
end
|
||||
|
||||
context._hotkeys[keys] = {
|
||||
name = name,
|
||||
lastExecution = context.now,
|
||||
switch = switch,
|
||||
single = single
|
||||
}
|
||||
|
||||
local hotkeyData = context._hotkeys[keys]
|
||||
hotkeyData.callback = function()
|
||||
if not hotkeyData.delay or hotkeyData.delay < context.now then
|
||||
context._currentExecution = hotkeyData
|
||||
callback()
|
||||
context._currentExecution = nil
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return hotkeyData
|
||||
end
|
||||
|
||||
-- singlehotkey(keys, callback)
|
||||
-- singlehotkey(keys, name, callback)
|
||||
-- singlehotkey(keys, name, callback, parent)
|
||||
context.singlehotkey = function(keys, name, callback, parent)
|
||||
if type(name) == 'function' then
|
||||
callback = name
|
||||
name = ""
|
||||
end
|
||||
return context.hotkey(keys, name, callback, true, parent)
|
||||
end
|
||||
|
||||
-- schedule(timeout, callback)
|
||||
context.schedule = function(timeout, callback)
|
||||
local extecute_time = g_clock.millis() + timeout
|
||||
table.insert(context._scheduler, {
|
||||
execution = extecute_time,
|
||||
callback = callback
|
||||
})
|
||||
table.sort(context._scheduler, function(a, b) return a.execution < b.execution end)
|
||||
end
|
||||
|
||||
-- delay(duration) -- block execution of current macro/hotkey/callback for x milliseconds
|
||||
context.delay = function(duration)
|
||||
if not context._currentExecution then
|
||||
return context.error("Invalid usage of delay function, it should be used inside callbacks")
|
||||
end
|
||||
context._currentExecution.delay = context.now + duration
|
||||
end
|
39
modules/game_bot/functions/map.lua
Normal file
39
modules/game_bot/functions/map.lua
Normal file
@@ -0,0 +1,39 @@
|
||||
local context = G.botContext
|
||||
|
||||
context.zoomIn = function() modules.game_interface.getMapPanel():zoomIn() end
|
||||
context.zoomOut = function() modules.game_interface.getMapPanel():zoomOut() end
|
||||
|
||||
context.getSpectators = function(multifloor)
|
||||
if multifloor ~= true then
|
||||
multifloor = false
|
||||
end
|
||||
return g_map.getSpectators(context.player:getPosition(), multifloor)
|
||||
end
|
||||
|
||||
context.getCreatureByName = function(name, multifloor)
|
||||
if not name then return nil end
|
||||
name = name:lower()
|
||||
if multifloor ~= true then
|
||||
multifloor = false
|
||||
end
|
||||
for i, spec in ipairs(g_map.getSpectators(context.player:getPosition(), multifloor)) do
|
||||
if spec:getName():lower() == name then
|
||||
return spec
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
context.getPlayerByName = function(name, multifloor)
|
||||
if not name then return nil end
|
||||
name = name:lower()
|
||||
if multifloor ~= true then
|
||||
multifloor = false
|
||||
end
|
||||
for i, spec in ipairs(g_map.getSpectators(context.player:getPosition(), multifloor)) do
|
||||
if spec:isPlayer() and spec:getName():lower() == name then
|
||||
return spec
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
98
modules/game_bot/functions/player.lua
Normal file
98
modules/game_bot/functions/player.lua
Normal file
@@ -0,0 +1,98 @@
|
||||
local context = G.botContext
|
||||
|
||||
context.name = function() return context.player:getName() end
|
||||
|
||||
context.hp = function() return context.player:getHealth() end
|
||||
context.mana = function() return context.player:getMana() end
|
||||
context.hppercent = function() return context.player:getHealthPercent() end
|
||||
context.manapercent = function() if context.player:getMaxMana() <= 1 then return 100 else return math.floor(context.player:getMana() * 100 / context.player:getMaxMana()) end end
|
||||
context.maxhp = function() return context.player:getMaxHealth() end
|
||||
context.maxmana = function() return context.player:getMaxMana() end
|
||||
context.hpmax = function() return context.player:getMaxHealth() end
|
||||
context.manamax = function() return context.player:getMaxMana() end
|
||||
|
||||
context.cap = function() return context.player:getCapacity() end
|
||||
context.freecap = function() return context.player:getFreeCapacity() end
|
||||
context.maxcap = function() return context.player:getTotalCapacity() end
|
||||
context.capmax = function() return context.player:getTotalCapacity() end
|
||||
|
||||
context.exp = function() return context.player:getExperience() end
|
||||
context.lvl = function() return context.player:getLevel() end
|
||||
context.level = function() return context.player:getLevel() end
|
||||
|
||||
context.mlev = function() return context.player:getMagicLevel() end
|
||||
context.magic = function() return context.player:getMagicLevel() end
|
||||
context.mlevel = function() return context.player:getMagicLevel() end
|
||||
|
||||
context.soul = function() return context.player:getSoul() end
|
||||
context.stamina = function() return context.player:getStamina() end
|
||||
context.voc = function() return context.player:getVocation() end
|
||||
context.vocation = function() return context.player:getVocation() end
|
||||
|
||||
context.bless = function() return context.player:getBlessings() end
|
||||
context.blesses = function() return context.player:getBlessings() end
|
||||
context.blessings = function() return context.player:getBlessings() end
|
||||
|
||||
|
||||
context.pos = function() return context.player:getPosition() end
|
||||
context.posx = function() return context.player:getPosition().x end
|
||||
context.posy = function() return context.player:getPosition().y end
|
||||
context.posz = function() return context.player:getPosition().z end
|
||||
|
||||
context.direction = function() return context.player:getDirection() end
|
||||
context.speed = function() return context.player:getSpeed() end
|
||||
context.skull = function() return context.player:getSkull() end
|
||||
context.outfit = function() return context.player:getOutfit() end
|
||||
|
||||
context.setOutfit = function(outfit)
|
||||
modules.game_outfit.ignoreNextOutfitWindow = g_clock.millis()
|
||||
g_game.requestOutfit()
|
||||
context.schedule(100, function()
|
||||
g_game.changeOutfit(outfit)
|
||||
end)
|
||||
end
|
||||
context.changeOutfit = context.setOutfit
|
||||
context.setSpeed = function(value) context.player:setSpeed(value) end
|
||||
|
||||
context.autoWalk = function(destination) return context.player:autoWalk(destination) end
|
||||
context.walk = function(dir) return modules.game_walking.walk(dir) end
|
||||
context.turn = function(dir) return g_game.turn(dir) end
|
||||
|
||||
-- game releated
|
||||
context.say = g_game.talk
|
||||
context.talk = g_game.talk
|
||||
|
||||
context.saySpell = function(text, lastSpellTimeout)
|
||||
if context.lastSpell == nil then
|
||||
context.lastSpell = 0
|
||||
end
|
||||
if not lastSpellTimeout then
|
||||
lastSpellTimeout = 1000
|
||||
end
|
||||
if context.lastSpell + lastSpellTimeout > context.now then
|
||||
return false
|
||||
end
|
||||
context.say(text)
|
||||
context.lastSpell = context.now
|
||||
return true
|
||||
end
|
||||
|
||||
context.setSpellTimeout = function()
|
||||
context.lastSpell = context.now
|
||||
end
|
||||
|
||||
context.talkPrivate = g_game.talkPrivate
|
||||
context.sayPrivate = g_game.talkPrivate
|
||||
context.use = g_game.useInventoryItem
|
||||
context.usewith = g_game.useInventoryItemWith
|
||||
context.useWith = g_game.useInventoryItemWith
|
||||
context.findItem = g_game.findItemInContainers
|
||||
|
||||
context.attack = g_game.attack
|
||||
context.cancelAttack = g_game.cancelAttack
|
||||
context.follow = g_game.follow
|
||||
context.cancelFollow = g_game.cancelFollow
|
||||
context.cancelAttackAndFollow = g_game.cancelAttackAndFollow
|
||||
|
||||
context.logout = g_game.forceLogout
|
||||
context.ping = g_game.getPing
|
32
modules/game_bot/functions/player_conditions.lua
Normal file
32
modules/game_bot/functions/player_conditions.lua
Normal file
@@ -0,0 +1,32 @@
|
||||
local context = G.botContext
|
||||
|
||||
for i, state in ipairs(PlayerStates) do
|
||||
context[state] = state
|
||||
end
|
||||
|
||||
context.hasCondition = function(condition) return bit.band(context.player:getStates(), condition) > 0 end
|
||||
|
||||
context.isPoisioned = function() return context.hasCondition(PlayerStates.Poison) end
|
||||
context.isBurnining = function() return context.hasCondition(PlayerStates.Burn) end
|
||||
context.isEnergized = function() return context.hasCondition(PlayerStates.Energy) end
|
||||
context.isDrunk = function() return context.hasCondition(PlayerStates.Drunk) end
|
||||
context.hasManaShield = function() return context.hasCondition(PlayerStates.ManaShield) end
|
||||
context.isParalyzed = function() return context.hasCondition(PlayerStates.Paralyze) end
|
||||
context.hasHaste = function() return context.hasCondition(PlayerStates.Haste) end
|
||||
context.hasSwords = function() return context.hasCondition(PlayerStates.Swords) end
|
||||
context.isInFight = function() return context.hasCondition(PlayerStates.Swords) end
|
||||
context.canLogout = function() return not context.hasCondition(PlayerStates.Swords) end
|
||||
context.isDrowning = function() return context.hasCondition(PlayerStates.Drowning) end
|
||||
context.isFreezing = function() return context.hasCondition(PlayerStates.Freezing) end
|
||||
context.isDazzled = function() return context.hasCondition(PlayerStates.Dazzled) end
|
||||
context.isCursed = function() return context.hasCondition(PlayerStates.Cursed) end
|
||||
context.hasPartyBuff = function() return context.hasCondition(PlayerStates.PartyBuff) end
|
||||
context.hasPzLock = function() return context.hasCondition(PlayerStates.PzBlock) end
|
||||
context.hasPzBlock = function() return context.hasCondition(PlayerStates.PzBlock) end
|
||||
context.isPzLocked = function() return context.hasCondition(PlayerStates.PzBlock) end
|
||||
context.isPzBlocked = function() return context.hasCondition(PlayerStates.PzBlock) end
|
||||
context.isInProtectionZone = function() return context.hasCondition(PlayerStates.Pz) end
|
||||
context.hasPz = function() return context.hasCondition(PlayerStates.Pz) end
|
||||
context.isInPz = function() return context.hasCondition(PlayerStates.Pz) end
|
||||
context.isBleeding = function() return context.hasCondition(PlayerStates.Bleeding) end
|
||||
context.isHungry = function() return context.hasCondition(PlayerStates.Hungry) end
|
33
modules/game_bot/functions/player_inventory.lua
Normal file
33
modules/game_bot/functions/player_inventory.lua
Normal file
@@ -0,0 +1,33 @@
|
||||
local context = G.botContext
|
||||
|
||||
context.SlotOther = InventorySlotOther
|
||||
context.SlotHead = InventorySlotHead
|
||||
context.SlotNeck = InventorySlotNeck
|
||||
context.SlotBack = InventorySlotBack
|
||||
context.SlotBody = InventorySlotBody
|
||||
context.SlotRight = InventorySlotRight
|
||||
context.SlotLeft = InventorySlotLeft
|
||||
context.SlotLeg = InventorySlotLeg
|
||||
context.SlotFeet = InventorySlotFeet
|
||||
context.SlotFinger = InventorySlotFinger
|
||||
context.SlotAmmo = InventorySlotAmmo
|
||||
context.SlotPurse = InventorySlotPurse
|
||||
|
||||
context.getInventoryItem = function(slot) return context.player:getInventoryItem(slot) end
|
||||
context.getSlot = context.getInventoryItem
|
||||
|
||||
context.getHead = function() return context.getInventoryItem(context.SlotHead) end
|
||||
context.getNeck = function() return context.getInventoryItem(context.SlotNeck) end
|
||||
context.getBack = function() return context.getInventoryItem(context.SlotBack) end
|
||||
context.getBody = function() return context.getInventoryItem(context.SlotBody) end
|
||||
context.getRight = function() return context.getInventoryItem(context.SlotRight) end
|
||||
context.getLeft = function() return context.getInventoryItem(context.SlotLeft) end
|
||||
context.getLeg = function() return context.getInventoryItem(context.SlotLeg) end
|
||||
context.getFeet = function() return context.getInventoryItem(context.SlotFeet) end
|
||||
context.getFinger = function() return context.getInventoryItem(context.SlotFinger) end
|
||||
context.getAmmo = function() return context.getInventoryItem(context.SlotAmmo) end
|
||||
context.getPurse = function() return context.getInventoryItem(context.SlotPurse) end
|
||||
|
||||
|
||||
context.getContainers = function() return g_game.getContainers() end
|
||||
context.getContainer = function(index) return g_game.getContainer(index) end
|
3
modules/game_bot/functions/test.lua
Normal file
3
modules/game_bot/functions/test.lua
Normal file
@@ -0,0 +1,3 @@
|
||||
local context = G.botContext
|
||||
|
||||
context.test = function() return context.info("test") end
|
4
modules/game_bot/functions/tools.lua
Normal file
4
modules/game_bot/functions/tools.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
local context = G.botContext
|
||||
|
||||
context.encode = function(data) return json.encode(data) end
|
||||
context.decode = function(text) local status, result = pcall(function() return json.decode(text) end) if status then return result end return {} end
|
95
modules/game_bot/functions/ui.lua
Normal file
95
modules/game_bot/functions/ui.lua
Normal file
@@ -0,0 +1,95 @@
|
||||
local context = G.botContext
|
||||
|
||||
context.setupUI = function(otml, parent)
|
||||
if parent == nil then
|
||||
parent = context.panel
|
||||
end
|
||||
local widget = g_ui.loadUIFromString(otml, parent)
|
||||
return widget
|
||||
end
|
||||
|
||||
context.addTab = function(name)
|
||||
context.tabs:setOn(true)
|
||||
return context.tabs:addTab(name, g_ui.createWidget('BotPanel')).tabPanel
|
||||
end
|
||||
|
||||
context.addSwitch = function(id, text, onClickCallback, parent)
|
||||
if not parent then
|
||||
parent = context.panel
|
||||
end
|
||||
local switch = g_ui.createWidget('BotSwitch', parent)
|
||||
switch:setId(id)
|
||||
switch:setText(text)
|
||||
switch.onClick = onClickCallback
|
||||
return switch
|
||||
end
|
||||
|
||||
context.addButton = function(id, text, onClickCallback, parent)
|
||||
if not parent then
|
||||
parent = context.panel
|
||||
end
|
||||
local button = g_ui.createWidget('BotButton', parent)
|
||||
button:setId(id)
|
||||
button:setText(text)
|
||||
button.onClick = onClickCallback
|
||||
return button
|
||||
end
|
||||
|
||||
context.addLabel = function(id, text, parent)
|
||||
if not parent then
|
||||
parent = context.panel
|
||||
end
|
||||
local label = g_ui.createWidget('BotLabel', parent)
|
||||
label:setId(id)
|
||||
label:setText(text)
|
||||
return label
|
||||
end
|
||||
|
||||
context.addTextEdit = function(id, text, onTextChangeCallback, parent)
|
||||
if not parent then
|
||||
parent = context.panel
|
||||
end
|
||||
local widget = g_ui.createWidget('BotTextEdit', parent)
|
||||
widget:setId(id)
|
||||
widget.onTextChange = onTextChangeCallback
|
||||
widget:setText(text)
|
||||
return widget
|
||||
end
|
||||
|
||||
context.addSeparator = function(id, parent)
|
||||
if not parent then
|
||||
parent = context.panel
|
||||
end
|
||||
local separator = g_ui.createWidget('BotSeparator', parent)
|
||||
separator:setId(id)
|
||||
return separator
|
||||
end
|
||||
|
||||
context._addMacroSwitch = function(name, keys, parent)
|
||||
if not parent then
|
||||
parent = context.panel
|
||||
end
|
||||
local text = name
|
||||
if keys:len() > 0 then
|
||||
text = name .. " [" .. keys .. "]"
|
||||
end
|
||||
local switch = context.addSwitch("macro_" .. #context._macros, text, function(widget)
|
||||
context.storage._macros[name] = not context.storage._macros[name]
|
||||
widget:setOn(context.storage._macros[name])
|
||||
end, parent)
|
||||
switch:setOn(context.storage._macros[name])
|
||||
return switch
|
||||
end
|
||||
|
||||
context._addHotkeySwitch = function(name, keys, parent)
|
||||
if not parent then
|
||||
parent = context.panel
|
||||
end
|
||||
local text = name
|
||||
if keys:len() > 0 then
|
||||
text = name .. " [" .. keys .. "]"
|
||||
end
|
||||
local switch = context.addSwitch("hotkey_" .. #context._hotkeys, text, nil, parent)
|
||||
switch:setOn(false)
|
||||
return switch
|
||||
end
|
326
modules/game_bot/panels/basic.lua
Normal file
326
modules/game_bot/panels/basic.lua
Normal file
@@ -0,0 +1,326 @@
|
||||
local context = G.botContext
|
||||
local Panels = context.Panels
|
||||
|
||||
Panels.Haste = function(parent)
|
||||
context.macro(500, "Auto Haste", nil, function()
|
||||
if not context.hasHaste() and context.storage.autoHasteText:len() > 0 then
|
||||
if context.saySpell(context.storage.autoHasteText, 2500) then
|
||||
context.delay(5000)
|
||||
end
|
||||
end
|
||||
end, parent)
|
||||
context.addTextEdit("autoHasteText", context.storage.autoHasteText or "utani hur", function(widget, text)
|
||||
context.storage.autoHasteText = text
|
||||
end, parent)
|
||||
end
|
||||
|
||||
Panels.ManaShield = function(parent)
|
||||
context.macro(500, "Auto ManaShield", nil, function()
|
||||
if not context.hasManaShield() then
|
||||
if context.saySpell("utamo vita", 1000) then
|
||||
context.delay(5000)
|
||||
end
|
||||
end
|
||||
end, parent)
|
||||
end
|
||||
|
||||
Panels.AntiParalyze = function(parent)
|
||||
context.macro(500, "Anti Paralyze", nil, function()
|
||||
if not context.isParalyzed() and context.storage.autoHasteText:len() > 0 then
|
||||
if context.saySpell(context.storage.autoAntiParalyzeText, 2500) then
|
||||
context.delay(5000)
|
||||
end
|
||||
end
|
||||
end, parent)
|
||||
context.addTextEdit("autoHasteText", context.storage.autoAntiParalyzeText or "utani hur", function(widget, text)
|
||||
context.storage.autoAntiParalyzeText = text
|
||||
end, parent)
|
||||
end
|
||||
|
||||
|
||||
Panels.Health = function(parent)
|
||||
if not parent then
|
||||
parent = context.panel
|
||||
end
|
||||
|
||||
local panelName = "autoHealthPanel"
|
||||
local panelId = 1
|
||||
while parent:getChildById(panelName .. panelId) do
|
||||
panelId = panelId + 1
|
||||
end
|
||||
panelName = panelName .. panelId
|
||||
|
||||
local ui = context.setupUI([[
|
||||
Panel
|
||||
height: 70
|
||||
margin-top: 2
|
||||
|
||||
Label
|
||||
id: info
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text: Auto Healing
|
||||
text-align: center
|
||||
|
||||
Label
|
||||
id: label
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin: 0 5 0 5
|
||||
text-align: center
|
||||
|
||||
HorizontalScrollBar
|
||||
id: scroll1
|
||||
anchors.left: label.left
|
||||
anchors.right: label.horizontalCenter
|
||||
anchors.top: label.bottom
|
||||
margin-top: 5
|
||||
margin-right: 2
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
step: 1
|
||||
|
||||
HorizontalScrollBar
|
||||
id: scroll2
|
||||
anchors.left: label.horizontalCenter
|
||||
anchors.right: label.right
|
||||
anchors.top: label.bottom
|
||||
margin-top: 5
|
||||
margin-left: 2
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
step: 1
|
||||
|
||||
BotTextEdit
|
||||
id: text
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: scroll1.bottom
|
||||
]], parent)
|
||||
ui:setId(panelName)
|
||||
|
||||
ui.text.onTextChange = function(widget, text)
|
||||
context.storage["healthText" .. panelId] = text
|
||||
end
|
||||
ui.text:setText(context.storage["healthText" .. panelId] or "exura")
|
||||
|
||||
local updateText = function()
|
||||
ui.label:setText("" .. (context.storage["healthPercentMin" .. panelId] or "") .. "% <= hp <= " .. (context.storage["healthPercentMax" .. panelId] or "") .. "%")
|
||||
end
|
||||
|
||||
ui.scroll1.onValueChange = function(scroll, value)
|
||||
context.storage["healthPercentMin" .. panelId] = value
|
||||
updateText()
|
||||
end
|
||||
ui.scroll2.onValueChange = function(scroll, value)
|
||||
context.storage["healthPercentMax" .. panelId] = value
|
||||
updateText()
|
||||
end
|
||||
|
||||
ui.scroll1:setValue(context.storage["healthPercentMin" .. panelId] or 20)
|
||||
ui.scroll2:setValue(context.storage["healthPercentMax" .. panelId] or 60)
|
||||
|
||||
context.macro(25, function()
|
||||
if context.storage["healthText" .. panelId]:len() > 0 and context.storage["healthPercentMin" .. panelId] <= context.hppercent() and context.hppercent() <= context.storage["healthPercentMax" .. panelId] then
|
||||
if context.saySpell(context.storage["healthText" .. panelId], 500) then
|
||||
context.delay(200)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
Panels.HealthItem = function(parent)
|
||||
if not parent then
|
||||
parent = context.panel
|
||||
end
|
||||
|
||||
local panelName = "autoHealthItemPanel"
|
||||
local panelId = 1
|
||||
while parent:getChildById(panelName .. panelId) do
|
||||
panelId = panelId + 1
|
||||
end
|
||||
panelName = panelName .. panelId
|
||||
|
||||
local ui = context.setupUI([[
|
||||
Panel
|
||||
height: 55
|
||||
margin-top: 2
|
||||
|
||||
Label
|
||||
id: info
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text: Auto Healing
|
||||
text-align: center
|
||||
|
||||
BotItem
|
||||
id: item
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: label
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.top
|
||||
margin: 0 5 0 5
|
||||
text-align: center
|
||||
|
||||
HorizontalScrollBar
|
||||
id: scroll1
|
||||
anchors.left: label.left
|
||||
anchors.right: label.horizontalCenter
|
||||
anchors.top: label.bottom
|
||||
margin-top: 5
|
||||
margin-right: 2
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
step: 1
|
||||
|
||||
HorizontalScrollBar
|
||||
id: scroll2
|
||||
anchors.left: label.horizontalCenter
|
||||
anchors.right: label.right
|
||||
anchors.top: label.bottom
|
||||
margin-top: 5
|
||||
margin-left: 2
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
step: 1
|
||||
]], parent)
|
||||
ui:setId(panelName)
|
||||
|
||||
ui.item.onItemChange = function(widget)
|
||||
cp("item change")
|
||||
context.storage["healthItem" .. panelId] = widget:getItemId()
|
||||
end
|
||||
ui.item:setItemId(context.storage["healthItem" .. panelId] or 266)
|
||||
|
||||
local updateText = function()
|
||||
ui.label:setText("" .. (context.storage["healthItemPercentMin" .. panelId] or "") .. "% <= hp <= " .. (context.storage["healthItemPercentMax" .. panelId] or "") .. "%")
|
||||
end
|
||||
|
||||
ui.scroll1.onValueChange = function(scroll, value)
|
||||
context.storage["healthItemPercentMin" .. panelId] = value
|
||||
updateText()
|
||||
end
|
||||
ui.scroll2.onValueChange = function(scroll, value)
|
||||
context.storage["healthItemPercentMax" .. panelId] = value
|
||||
updateText()
|
||||
end
|
||||
|
||||
ui.scroll1:setValue(context.storage["healthItemPercentMin" .. panelId] or 20)
|
||||
ui.scroll2:setValue(context.storage["healthItemPercentMax" .. panelId] or 60)
|
||||
|
||||
context.macro(25, function()
|
||||
if context.storage["healthItem" .. panelId] > 0 and context.storage["healthItemPercentMin" .. panelId] <= context.hppercent() and context.hppercent() <= context.storage["healthItemPercentMax" .. panelId] then
|
||||
context.useWith(context.storage["healthItem" .. panelId], context.player)
|
||||
context.delay(300)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
Panels.Mana = function(parent)
|
||||
if not parent then
|
||||
parent = context.panel
|
||||
end
|
||||
|
||||
local panelName = "autoManaItemPanel"
|
||||
local panelId = 1
|
||||
while parent:getChildById(panelName .. panelId) do
|
||||
panelId = panelId + 1
|
||||
end
|
||||
panelName = panelName .. panelId
|
||||
|
||||
local ui = context.setupUI([[
|
||||
Panel
|
||||
height: 55
|
||||
margin-top: 2
|
||||
|
||||
Label
|
||||
id: info
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text: Auto Mana
|
||||
text-align: center
|
||||
|
||||
BotItem
|
||||
id: item
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: label
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.top
|
||||
margin: 0 5 0 5
|
||||
text-align: center
|
||||
|
||||
HorizontalScrollBar
|
||||
id: scroll1
|
||||
anchors.left: label.left
|
||||
anchors.right: label.horizontalCenter
|
||||
anchors.top: label.bottom
|
||||
margin-top: 5
|
||||
margin-right: 2
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
step: 1
|
||||
|
||||
HorizontalScrollBar
|
||||
id: scroll2
|
||||
anchors.left: label.horizontalCenter
|
||||
anchors.right: label.right
|
||||
anchors.top: label.bottom
|
||||
margin-top: 5
|
||||
margin-left: 2
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
step: 1
|
||||
]], parent)
|
||||
ui:setId(panelName)
|
||||
|
||||
ui.item.onItemChange = function(widget)
|
||||
context.storage["manaItem" .. panelId] = widget:getItemId()
|
||||
end
|
||||
ui.item:setItemId(context.storage["manaItem" .. panelId] or 268)
|
||||
|
||||
local updateText = function()
|
||||
ui.label:setText("" .. (context.storage["manaItemPercentMin" .. panelId] or "") .. "% <= mana <= " .. (context.storage["manaItemPercentMax" .. panelId] or "") .. "%")
|
||||
end
|
||||
|
||||
ui.scroll1.onValueChange = function(scroll, value)
|
||||
context.storage["manaItemPercentMin" .. panelId] = value
|
||||
updateText()
|
||||
end
|
||||
ui.scroll2.onValueChange = function(scroll, value)
|
||||
context.storage["manaItemPercentMax" .. panelId] = value
|
||||
updateText()
|
||||
end
|
||||
|
||||
ui.scroll1:setValue(context.storage["manaItemPercentMin" .. panelId] or 20)
|
||||
ui.scroll2:setValue(context.storage["manaItemPercentMax" .. panelId] or 60)
|
||||
|
||||
context.macro(25, function()
|
||||
if context.storage["manaItem" .. panelId] > 0 and context.storage["manaItemPercentMin" .. panelId] <= context.manapercent() and context.manapercent() <= context.storage["manaItemPercentMax" .. panelId] then
|
||||
context.useWith(context.storage["manaItem" .. panelId], context.player)
|
||||
context.delay(300)
|
||||
end
|
||||
end)
|
||||
end
|
||||
Panels.ManaItem = Panels.Mana
|
||||
|
||||
Panels.Turning = function(parent)
|
||||
context.macro(1000, "Turning / AntiIdle", nil, function()
|
||||
context.turn(math.random(1, 4))
|
||||
end, parent)
|
||||
end
|
||||
Panels.AntiIdle = Panels.Turning
|
||||
|
@@ -619,22 +619,36 @@ function addTabText(text, speaktype, tab, creatureName)
|
||||
|
||||
local panel = consoleTabBar:getTabPanel(tab)
|
||||
local consoleBuffer = panel:getChildById('consoleBuffer')
|
||||
local label = g_ui.createWidget('ConsoleLabel', consoleBuffer)
|
||||
|
||||
local label = nil
|
||||
if consoleBuffer:getChildCount() > MAX_LINES then
|
||||
label = consoleBuffer:getFirstChild()
|
||||
consoleBuffer:moveChildToIndex(label, consoleBuffer:getChildCount())
|
||||
end
|
||||
|
||||
if not label then
|
||||
label = g_ui.createWidget('ConsoleLabel', consoleBuffer)
|
||||
end
|
||||
label:setId('consoleLabel' .. consoleBuffer:getChildCount())
|
||||
label:setText(text)
|
||||
label:setColor(speaktype.color)
|
||||
consoleTabBar:blinkTab(tab)
|
||||
|
||||
-- Overlay for consoleBuffer which shows highlighted words only
|
||||
-- Overlay for consoleBuffer which shows highlighted words only
|
||||
local labelHighlight = label:getChildById("consoleLabelHighlight")
|
||||
if labelHighlight then
|
||||
labelHighlight:setText("")
|
||||
end
|
||||
|
||||
if speaktype.npcChat and (g_game.getCharacterName() ~= creatureName or g_game.getCharacterName() == 'Account Manager') then
|
||||
local highlightData = getHighlightedText(text)
|
||||
if #highlightData > 0 then
|
||||
local labelHighlight = g_ui.createWidget('ConsolePhantomLabel', label)
|
||||
labelHighlight:fill('parent')
|
||||
|
||||
labelHighlight:setId('consoleLabelHighlight' .. consoleBuffer:getChildCount())
|
||||
labelHighlight:setColor("#1f9ffe")
|
||||
if not labelHighlight then
|
||||
labelHighlight = g_ui.createWidget('ConsolePhantomLabel', label)
|
||||
labelHighlight:fill('parent')
|
||||
labelHighlight:setId('consoleLabelHighlight')
|
||||
labelHighlight:setColor("#1f9ffe")
|
||||
end
|
||||
|
||||
-- Remove the curly braces
|
||||
for i = 1, #highlightData / 3 do
|
||||
@@ -768,12 +782,6 @@ function addTabText(text, speaktype, tab, creatureName)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
if consoleBuffer:getChildCount() > MAX_LINES then
|
||||
local child = consoleBuffer:getFirstChild()
|
||||
clearSelection(consoleBuffer)
|
||||
child:destroy()
|
||||
end
|
||||
end
|
||||
|
||||
function removeTabLabelByName(tab, name)
|
||||
@@ -1499,6 +1507,12 @@ function online()
|
||||
defaultTab = addTab(tr('Default'), true)
|
||||
serverTab = addTab(tr('Server Log'), false)
|
||||
|
||||
|
||||
if g_game.getClientVersion() >= 820 then
|
||||
local tab = addTab("NPCs", false)
|
||||
tab.npcChat = true
|
||||
end
|
||||
|
||||
if g_game.getClientVersion() < 862 then
|
||||
local gameRootPanel = modules.game_interface.getRootPanel()
|
||||
g_keyboard.bindKeyDown('Ctrl+R', openPlayerReportRuleViolationWindow, gameRootPanel)
|
||||
|
@@ -12,6 +12,7 @@ function updateFeatures(version)
|
||||
-- you can add custom features here, list of them in modules\gamelib\const.lua
|
||||
g_game.enableFeature(GameBot)
|
||||
--g_game.enableFeature(GameMinimapLimitedToSingleFloor)
|
||||
--g_game.enableFeature(GameSpritesAlphaChannel)
|
||||
|
||||
if(version >= 770) then
|
||||
g_game.enableFeature(GameLooktypeU16);
|
||||
|
@@ -402,7 +402,7 @@ end
|
||||
|
||||
function prepareKeyCombo(keyCombo, repeated)
|
||||
local hotKey = hotkeyList[keyCombo]
|
||||
if keyCombo:lower():find("ctrl") or not hotKey or (hotKey.itemId == nil and (not hotKey.value or #hotKey.value == 0)) then
|
||||
if (keyCombo:lower():find("ctrl") and not hotKey) or (hotKey and hotKey.itemId == nil and (not hotKey.value or #hotKey.value == 0)) then
|
||||
keyCombo = keyCombo:gsub("Ctrl%+", "")
|
||||
keyCombo = keyCombo:gsub("ctrl%+", "")
|
||||
hotKey = hotkeyList[keyCombo]
|
||||
|
@@ -531,9 +531,13 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
||||
end
|
||||
end
|
||||
|
||||
if g_game.getFeature(GameBot) and useThing then
|
||||
if g_game.getFeature(GameBot) and useThing and useThing:isItem() then
|
||||
menu:addSeparator()
|
||||
menu:addOption("ID: " .. useThing:getId())
|
||||
if useThing:getSubType() > 1 then
|
||||
menu:addOption("ID: " .. useThing:getId() .. " SubType: " .. useThing:getSubType())
|
||||
else
|
||||
menu:addOption("ID: " .. useThing:getId())
|
||||
end
|
||||
end
|
||||
|
||||
menu:display(menuPosition)
|
||||
|
@@ -4,7 +4,7 @@ Module
|
||||
author: OTClient team
|
||||
website: https://github.com/edubart/otclient
|
||||
sandboxed: true
|
||||
scripts: [ widgets/uigamemap, widgets/uiitem, gameinterface ]
|
||||
scripts: [ widgets/uigamemap, gameinterface ]
|
||||
load-later:
|
||||
- game_hotkeys
|
||||
- game_questlog
|
||||
@@ -32,6 +32,8 @@ Module
|
||||
- game_unjustifiedpoints
|
||||
- game_walking
|
||||
- game_shop
|
||||
- game_itemselector
|
||||
- game_textedit
|
||||
- game_bot
|
||||
@onLoad: init()
|
||||
@onUnload: terminate()
|
||||
|
@@ -200,6 +200,7 @@ function refresh()
|
||||
if player then
|
||||
onSoulChange(player, player:getSoul())
|
||||
onFreeCapacityChange(player, player:getFreeCapacity())
|
||||
onStatesChange(player, player:getStates(), 0)
|
||||
end
|
||||
|
||||
--purseButton:setVisible(g_game.getFeature(GamePurseSlot))
|
||||
|
73
modules/game_itemselector/itemselector.lua
Normal file
73
modules/game_itemselector/itemselector.lua
Normal file
@@ -0,0 +1,73 @@
|
||||
local activeWindow
|
||||
|
||||
function init()
|
||||
g_ui.importStyle('itemselector')
|
||||
|
||||
connect(g_game, { onGameEnd = destroyWindow })
|
||||
end
|
||||
|
||||
function terminate()
|
||||
disconnect(g_game, { onGameEnd = destroyWindow })
|
||||
|
||||
destroyWindow()
|
||||
end
|
||||
|
||||
function destroyWindow()
|
||||
if activeWindow then
|
||||
activeWindow:destroy()
|
||||
activeWindow = nil
|
||||
end
|
||||
end
|
||||
|
||||
function show(itemWidget)
|
||||
if not itemWidget then
|
||||
return
|
||||
end
|
||||
if activeWindow then
|
||||
destroyWindow()
|
||||
end
|
||||
local window = g_ui.createWidget('ItemSelectorWindow', rootWidget)
|
||||
|
||||
local destroy = function()
|
||||
window:destroy()
|
||||
if window == activeWindow then
|
||||
activeWindow = nil
|
||||
end
|
||||
end
|
||||
local doneFunc = function()
|
||||
itemWidget:setItemId(window.item:getItemId())
|
||||
itemWidget:setItemCount(window.item:getItemCount())
|
||||
if itemWidget.onItemChange then
|
||||
itemWidget:onItemChange()
|
||||
end
|
||||
destroy()
|
||||
end
|
||||
|
||||
window.okButton.onClick = doneFunc
|
||||
window.cancelButton.onClick = destroy
|
||||
window.onEnter = doneFunc
|
||||
window.onEscape = destroy
|
||||
|
||||
window.item:setItemId(itemWidget:getItemId())
|
||||
window.item:setItemCount(itemWidget:getItemCount())
|
||||
|
||||
window.itemId:setValue(itemWidget:getItemId())
|
||||
if itemWidget:getItemCount() > 1 then
|
||||
window.itemCount:setValue(itemWidget:getItemCount())
|
||||
end
|
||||
|
||||
window.itemId.onValueChange = function(widget, value)
|
||||
window.item:setItemId(value)
|
||||
end
|
||||
window.itemCount.onValueChange = function(widget, value)
|
||||
window.item:setItemCount(value)
|
||||
end
|
||||
|
||||
activeWindow = window
|
||||
activeWindow:raise()
|
||||
activeWindow:focus()
|
||||
end
|
||||
|
||||
function hide()
|
||||
destroyWindow()
|
||||
end
|
10
modules/game_itemselector/itemselector.otmod
Normal file
10
modules/game_itemselector/itemselector.otmod
Normal file
@@ -0,0 +1,10 @@
|
||||
Module
|
||||
name: game_itemselector
|
||||
description: Allow to select item
|
||||
author: OTClientV8
|
||||
website: https://github.com/OTCv8/otclientv8
|
||||
sandboxed: true
|
||||
dependencies: [ game_interface ]
|
||||
scripts: [ itemselector ]
|
||||
@onLoad: init()
|
||||
@onUnload: terminate()
|
65
modules/game_itemselector/itemselector.otui
Normal file
65
modules/game_itemselector/itemselector.otui
Normal file
@@ -0,0 +1,65 @@
|
||||
ItemSelectorWindow < MainWindow
|
||||
id: itemSelector
|
||||
size: 260 120
|
||||
!text: tr("Select item")
|
||||
|
||||
Item
|
||||
id: item
|
||||
virtual: true
|
||||
size: 32 32
|
||||
margin-top: 10
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
||||
SpinBox
|
||||
id: itemId
|
||||
anchors.top: parent.top
|
||||
anchors.left: prev.right
|
||||
margin-top: 15
|
||||
margin-left: 5
|
||||
padding-left: 5
|
||||
width: 70
|
||||
minimum: 1
|
||||
maximum: 999999999
|
||||
focusable: true
|
||||
|
||||
Label
|
||||
anchors.top: parent.top
|
||||
anchors.left: prev.left
|
||||
anchors.right: prev.right
|
||||
text-align: center
|
||||
!text: tr("Item ID")
|
||||
|
||||
SpinBox
|
||||
id: itemCount
|
||||
anchors.top: parent.top
|
||||
anchors.left: prev.right
|
||||
margin-top: 15
|
||||
margin-left: 5
|
||||
padding-left: 5
|
||||
width: 120
|
||||
minimum: 1
|
||||
maximum: 100
|
||||
focusable: true
|
||||
|
||||
Label
|
||||
anchors.top: parent.top
|
||||
anchors.left: prev.left
|
||||
anchors.right: prev.right
|
||||
text-align: center
|
||||
!text: tr("Count / SubType")
|
||||
|
||||
Button
|
||||
id: okButton
|
||||
!text: tr('Ok')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: next.left
|
||||
margin-right: 10
|
||||
width: 60
|
||||
|
||||
Button
|
||||
id: cancelButton
|
||||
!text: tr('Cancel')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
width: 60
|
56
modules/game_textedit/textedit.lua
Normal file
56
modules/game_textedit/textedit.lua
Normal file
@@ -0,0 +1,56 @@
|
||||
local activeWindow
|
||||
|
||||
function init()
|
||||
g_ui.importStyle('textedit')
|
||||
|
||||
connect(g_game, { onGameEnd = destroyWindow })
|
||||
end
|
||||
|
||||
function terminate()
|
||||
disconnect(g_game, { onGameEnd = destroyWindow })
|
||||
|
||||
destroyWindow()
|
||||
end
|
||||
|
||||
function destroyWindow()
|
||||
if activeWindow then
|
||||
activeWindow:destroy()
|
||||
activeWindow = nil
|
||||
end
|
||||
end
|
||||
|
||||
function show(widget)
|
||||
if not widget then
|
||||
return
|
||||
end
|
||||
if activeWindow then
|
||||
destroyWindow()
|
||||
end
|
||||
local window = g_ui.createWidget('TextEditWindow', rootWidget)
|
||||
|
||||
local destroy = function()
|
||||
window:destroy()
|
||||
if window == activeWindow then
|
||||
activeWindow = nil
|
||||
end
|
||||
end
|
||||
local doneFunc = function()
|
||||
widget:setText(window.text:getText())
|
||||
destroy()
|
||||
end
|
||||
|
||||
window.okButton.onClick = doneFunc
|
||||
window.cancelButton.onClick = destroy
|
||||
window.onEnter = doneFunc
|
||||
window.onEscape = destroy
|
||||
|
||||
window.text:setText(widget:getText())
|
||||
|
||||
activeWindow = window
|
||||
activeWindow:raise()
|
||||
activeWindow:focus()
|
||||
end
|
||||
|
||||
function hide()
|
||||
destroyWindow()
|
||||
end
|
10
modules/game_textedit/textedit.otmod
Normal file
10
modules/game_textedit/textedit.otmod
Normal file
@@ -0,0 +1,10 @@
|
||||
Module
|
||||
name: game_textedit
|
||||
description: Allow to edit text
|
||||
author: OTClientV8
|
||||
website: https://github.com/OTCv8/otclientv8
|
||||
sandboxed: true
|
||||
dependencies: [ game_interface ]
|
||||
scripts: [ textedit ]
|
||||
@onLoad: init()
|
||||
@onUnload: terminate()
|
25
modules/game_textedit/textedit.otui
Normal file
25
modules/game_textedit/textedit.otui
Normal file
@@ -0,0 +1,25 @@
|
||||
TextEditWindow < MainWindow
|
||||
id: textedit
|
||||
size: 260 105
|
||||
!text: tr("Edit text")
|
||||
|
||||
TextEdit
|
||||
id: text
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Button
|
||||
id: okButton
|
||||
!text: tr('Ok')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: next.left
|
||||
margin-right: 10
|
||||
width: 60
|
||||
|
||||
Button
|
||||
id: cancelButton
|
||||
!text: tr('Cancel')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
width: 60
|
133
modules/gamelib/ui/uiitem.lua
Normal file
133
modules/gamelib/ui/uiitem.lua
Normal file
@@ -0,0 +1,133 @@
|
||||
function UIItem:onDragEnter(mousePos)
|
||||
if self:isVirtual() then return false end
|
||||
|
||||
local item = self:getItem()
|
||||
if not item then return false end
|
||||
|
||||
self:setBorderWidth(1)
|
||||
self.currentDragThing = item
|
||||
g_mouse.pushCursor('target')
|
||||
return true
|
||||
end
|
||||
|
||||
function UIItem:onDragLeave(droppedWidget, mousePos)
|
||||
if self:isVirtual() then return false end
|
||||
self.currentDragThing = nil
|
||||
g_mouse.popCursor('target')
|
||||
self:setBorderWidth(0)
|
||||
self.hoveredWho = nil
|
||||
return true
|
||||
end
|
||||
|
||||
function UIItem:onDrop(widget, mousePos, forced)
|
||||
if not self:canAcceptDrop(widget, mousePos) and not forced then return false end
|
||||
|
||||
local item = widget.currentDragThing
|
||||
if not item or not item:isItem() then return false end
|
||||
|
||||
if self.selectable then
|
||||
self:setItemId(item:getId())
|
||||
self:setItemCount(item:getCount())
|
||||
if item:getSubType() > 1 then
|
||||
self:setItemSubType(item:getSubType())
|
||||
end
|
||||
if self.onItemChange then
|
||||
self:onItemChange()
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local toPos = self.position
|
||||
|
||||
local itemPos = item:getPosition()
|
||||
if itemPos.x == toPos.x and itemPos.y == toPos.y and itemPos.z == toPos.z then return false end
|
||||
|
||||
if item:getCount() > 1 then
|
||||
modules.game_interface.moveStackableItem(item, toPos)
|
||||
else
|
||||
g_game.move(item, toPos, 1)
|
||||
end
|
||||
|
||||
self:setBorderWidth(0)
|
||||
return true
|
||||
end
|
||||
|
||||
function UIItem:onDestroy()
|
||||
if self == g_ui.getDraggingWidget() and self.hoveredWho then
|
||||
self.hoveredWho:setBorderWidth(0)
|
||||
end
|
||||
|
||||
if self.hoveredWho then
|
||||
self.hoveredWho = nil
|
||||
end
|
||||
end
|
||||
|
||||
function UIItem:onHoverChange(hovered)
|
||||
UIWidget.onHoverChange(self, hovered)
|
||||
|
||||
if self:isVirtual() or not self:isDraggable() then return end
|
||||
|
||||
local draggingWidget = g_ui.getDraggingWidget()
|
||||
if draggingWidget and self ~= draggingWidget then
|
||||
local gotMap = draggingWidget:getClassName() == 'UIGameMap'
|
||||
local gotItem = draggingWidget:getClassName() == 'UIItem' and not draggingWidget:isVirtual()
|
||||
if hovered and (gotItem or gotMap) then
|
||||
self:setBorderWidth(1)
|
||||
draggingWidget.hoveredWho = self
|
||||
else
|
||||
self:setBorderWidth(0)
|
||||
draggingWidget.hoveredWho = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function UIItem:onMouseRelease(mousePosition, mouseButton)
|
||||
if self.cancelNextRelease then
|
||||
self.cancelNextRelease = false
|
||||
return true
|
||||
end
|
||||
|
||||
if self:isVirtual() then return false end
|
||||
|
||||
local item = self:getItem()
|
||||
if not item or not self:containsPoint(mousePosition) then return false end
|
||||
|
||||
if modules.client_options.getOption('classicControl') and
|
||||
((g_mouse.isPressed(MouseLeftButton) and mouseButton == MouseRightButton) or
|
||||
(g_mouse.isPressed(MouseRightButton) and mouseButton == MouseLeftButton)) then
|
||||
g_game.look(item)
|
||||
self.cancelNextRelease = true
|
||||
return true
|
||||
elseif modules.game_interface.processMouseAction(mousePosition, mouseButton, nil, item, item, nil, nil) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function UIItem:canAcceptDrop(widget, mousePos)
|
||||
if not self.selectable and (self:isVirtual() or not self:isDraggable()) then return false end
|
||||
if not widget or not widget.currentDragThing then return false end
|
||||
|
||||
local children = rootWidget:recursiveGetChildrenByPos(mousePos)
|
||||
for i=1,#children do
|
||||
local child = children[i]
|
||||
if child == self then
|
||||
return true
|
||||
elseif not child:isPhantom() then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
error('Widget ' .. self:getId() .. ' not in drop list.')
|
||||
return false
|
||||
end
|
||||
|
||||
function UIItem:onClick(mousePos)
|
||||
if not self.selectable then
|
||||
return
|
||||
end
|
||||
|
||||
if modules.game_itemselector then
|
||||
modules.game_itemselector.show(self)
|
||||
end
|
||||
end
|
Reference in New Issue
Block a user