diff --git a/modules/game_bot/bot.otmod b/modules/game_bot/bot.otmod index 382c1e1..05634ea 100644 --- a/modules/game_bot/bot.otmod +++ b/modules/game_bot/bot.otmod @@ -1,8 +1,8 @@ -Module - name: game_bot - description: Bot - author: otclient@otclient.ovh - sandboxed: true - scripts: [ bot ] - @onLoad: init() - @onUnload: terminate() +Module + name: game_bot + description: Bot + author: otclient@otclient.ovh + sandboxed: true + scripts: [ bot ] + @onLoad: init() + @onUnload: terminate() diff --git a/modules/game_bot/defaultconfig.lua b/modules/game_bot/defaultconfig.lua index 0ddbde6..663b628 100644 --- a/modules/game_bot/defaultconfig.lua +++ b/modules/game_bot/defaultconfig.lua @@ -1,62 +1,62 @@ -botDefaultConfig = { - configs = { - {name = "Example", script = [[ ---#Example config - ---#macros -macro(5000, "macro send link", "f5", function() - g_game.talk("macro test - https://github.com/OTCv8/otclient_bot") -end) - -macro(1000, "flag tiles", function() - local staticText = StaticText.create() - staticText:addMessage("t", 9, "xDDD") - local tile = player:getTile() - tile:clearTexts() - tile:addText(staticText) - for i = 1, 10 do - schedule(1000 * i, function() - staticText:setText(i) - end) - end - schedule(11000, function() - tile:clearTexts() - end) -end) - - -addSeparator("spe0") - ---#hotkeys -hotkey('y', 'test hotkey', function() g_game.talk('hotkey elo') end) - ---#callbacks - ---#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 - warn("Whoops! Error occured: " .. err) - return - end - info("HTTP: My IP is: " .. tostring(data['ip'])) -end) - -info("Bot started") - - -]]}, - {}, {}, {}, {} - }, - enabled = false, - selectedConfig = 1 +botDefaultConfig = { + configs = { + {name = "Example", script = [[ +--#Example config + +--#macros +macro(5000, "macro send link", "f5", function() + g_game.talk("macro test - https://github.com/OTCv8/otclient_bot") +end) + +macro(1000, "flag tiles", function() + local staticText = StaticText.create() + staticText:addMessage("t", 9, "xDDD") + local tile = player:getTile() + tile:clearTexts() + tile:addText(staticText) + for i = 1, 10 do + schedule(1000 * i, function() + staticText:setText(i) + end) + end + schedule(11000, function() + tile:clearTexts() + end) +end) + + +addSeparator("spe0") + +--#hotkeys +hotkey('y', 'test hotkey', function() g_game.talk('hotkey elo') end) + +--#callbacks + +--#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 + warn("Whoops! Error occured: " .. err) + return + end + info("HTTP: My IP is: " .. tostring(data['ip'])) +end) + +info("Bot started") + + +]]}, + {}, {}, {}, {} + }, + enabled = false, + selectedConfig = 1 } \ No newline at end of file diff --git a/modules/game_bot/executor.lua b/modules/game_bot/executor.lua index 89e95e8..3a53a64 100644 --- a/modules/game_bot/executor.lua +++ b/modules/game_bot/executor.lua @@ -1,247 +1,247 @@ -function executeBot(config, storage, panel, msg) - local context = {} - context.panel = panel - context.storage = storage - if context.storage.macros == nil then - context.storage.macros = {} -- active macros - end - - -- - context.macros = {} - context.hotkeys = {} - context.scheduler = {} - context.callbacks = { - onKeyDown = {}, - onKeyUp = {}, - onKeyPress = {}, - onTalk = {}, - } - context.ui = {} - - -- basic functions - context.print = print - context.pairs = pairs - context.ipairs = ipairs - context.tostring = tostring - context.math = math - context.table = table - context.string = string - context.tr = tr - context.json = json - context.regexMatch = regexMatch - - -- game functions - context.say = g_game.talk - context.talk = g_game.talk - context.talkPrivate = context.talkPrivate - context.sayPrivate = context.talkPrivate - context.use = g_game.useInventoryItem - context.usewith = g_game.useInventoryItemWith - context.useWith = g_game.useInventoryItemWith - context.findItem = g_game.findItemInContainers - - -- classes - context.g_game = g_game - context.g_map = g_map - context.StaticText = StaticText - context.HTTP = HTTP - - -- log functions - context.info = function(text) return msg("info", text) end - context.warn = function(text) return msg("warn", text) end - context.error = function(text) return msg("error", text) end - context.warning = context.warn - - -- UI - 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 - }) - 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) - 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 - } - 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 - - -- init context - context.now = g_clock.millis() - context.time = g_clock.millis() - context.player = g_game.getLocalPlayer() - - -- run script - assert(load(config, nil, nil, context))() - - return { - script = function() - context.now = g_clock.millis() - context.time = g_clock.millis() - - 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 - macro.lastExecution = context.now - macro.callback() - end - end - - while #context.scheduler > 0 and context.scheduler[1].execution <= g_clock.millis() do - context.scheduler[1].callback() - table.remove(context.scheduler, 1) - end - end, - callbacks = { - onKeyDown = function(keyCode, keyboardModifiers) - local keyDesc = determineKeyComboDesc(keyCode, keyboardModifiers) - for i, macro in ipairs(context.macros) do - if macro.switch and macro.hotkey == keyDesc then - macro.switch:onClick() - end - end - local hotkey = context.hotkeys[keyDesc] - if hotkey and hotkey.switch then - hotkey.switch:setOn(true) - end - - end, - onKeyUp = function(keyCode, keyboardModifiers) - local keyDesc = determineKeyComboDesc(keyCode, keyboardModifiers) - local hotkey = context.hotkeys[keyDesc] - if hotkey and hotkey.switch then - hotkey.switch:setOn(false) - end - - end, - onKeyPress = function(keyCode, keyboardModifiers, autoRepeatTicks) - local keyDesc = determineKeyComboDesc(keyCode, keyboardModifiers) - local hotkey = context.hotkeys[keyDesc] - if hotkey then - hotkey.lastExecution = context.now - hotkey.callback() - end - - end, - onTalk = function(name, level, mode, text, channelId, pos) - - end - } - } +function executeBot(config, storage, panel, msg) + local context = {} + context.panel = panel + context.storage = storage + if context.storage.macros == nil then + context.storage.macros = {} -- active macros + end + + -- + context.macros = {} + context.hotkeys = {} + context.scheduler = {} + context.callbacks = { + onKeyDown = {}, + onKeyUp = {}, + onKeyPress = {}, + onTalk = {}, + } + context.ui = {} + + -- basic functions + context.print = print + context.pairs = pairs + context.ipairs = ipairs + context.tostring = tostring + context.math = math + context.table = table + context.string = string + context.tr = tr + context.json = json + context.regexMatch = regexMatch + + -- game functions + context.say = g_game.talk + context.talk = g_game.talk + context.talkPrivate = context.talkPrivate + context.sayPrivate = context.talkPrivate + context.use = g_game.useInventoryItem + context.usewith = g_game.useInventoryItemWith + context.useWith = g_game.useInventoryItemWith + context.findItem = g_game.findItemInContainers + + -- classes + context.g_game = g_game + context.g_map = g_map + context.StaticText = StaticText + context.HTTP = HTTP + + -- log functions + context.info = function(text) return msg("info", text) end + context.warn = function(text) return msg("warn", text) end + context.error = function(text) return msg("error", text) end + context.warning = context.warn + + -- UI + 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 + }) + 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) + 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 + } + 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 + + -- init context + context.now = g_clock.millis() + context.time = g_clock.millis() + context.player = g_game.getLocalPlayer() + + -- run script + assert(load(config, nil, nil, context))() + + return { + script = function() + context.now = g_clock.millis() + context.time = g_clock.millis() + + 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 + macro.lastExecution = context.now + macro.callback() + end + end + + while #context.scheduler > 0 and context.scheduler[1].execution <= g_clock.millis() do + context.scheduler[1].callback() + table.remove(context.scheduler, 1) + end + end, + callbacks = { + onKeyDown = function(keyCode, keyboardModifiers) + local keyDesc = determineKeyComboDesc(keyCode, keyboardModifiers) + for i, macro in ipairs(context.macros) do + if macro.switch and macro.hotkey == keyDesc then + macro.switch:onClick() + end + end + local hotkey = context.hotkeys[keyDesc] + if hotkey and hotkey.switch then + hotkey.switch:setOn(true) + end + + end, + onKeyUp = function(keyCode, keyboardModifiers) + local keyDesc = determineKeyComboDesc(keyCode, keyboardModifiers) + local hotkey = context.hotkeys[keyDesc] + if hotkey and hotkey.switch then + hotkey.switch:setOn(false) + end + + end, + onKeyPress = function(keyCode, keyboardModifiers, autoRepeatTicks) + local keyDesc = determineKeyComboDesc(keyCode, keyboardModifiers) + local hotkey = context.hotkeys[keyDesc] + if hotkey then + hotkey.lastExecution = context.now + hotkey.callback() + end + + end, + onTalk = function(name, level, mode, text, channelId, pos) + + end + } + } end \ No newline at end of file diff --git a/modules/game_hotkeys/hotkeys_manager.lua b/modules/game_hotkeys/hotkeys_manager.lua index 08ddac8..262703e 100644 --- a/modules/game_hotkeys/hotkeys_manager.lua +++ b/modules/game_hotkeys/hotkeys_manager.lua @@ -402,7 +402,7 @@ end function prepareKeyCombo(keyCombo) local hotKey = hotkeyList[keyCombo] - if keyCombo:lower():find("ctrl") and not hotKey or (hotKey.itemId == nil and (not hotKey.value or #hotKey.value == 0)) then + if keyCombo:lower():find("ctrl") or not hotKey or (hotKey.itemId == nil and (not hotKey.value or #hotKey.value == 0)) then keyCombo = keyCombo:gsub("Ctrl%+", "") keyCombo = keyCombo:gsub("ctrl%+", "") hotKey = hotkeyList[keyCombo] diff --git a/modules/game_viplist/viplist.lua b/modules/game_viplist/viplist.lua index ad4d28d..24e3625 100644 --- a/modules/game_viplist/viplist.lua +++ b/modules/game_viplist/viplist.lua @@ -334,6 +334,9 @@ end function onVipStateChange(id, state) local vipList = vipWindow:getChildById('contentsPanel') local label = vipList:getChildById('vip' .. id) + if not label then + return + end local name = label:getText() local description = label:getTooltip() local iconId = label.iconId diff --git a/otclient_dx.exe b/otclient_dx.exe index d389a0e..38fbb92 100644 Binary files a/otclient_dx.exe and b/otclient_dx.exe differ diff --git a/otclient_gl.exe b/otclient_gl.exe index 2c9557f..95e4af2 100644 Binary files a/otclient_gl.exe and b/otclient_gl.exe differ diff --git a/pdb/otclient_dx.pdb b/pdb/otclient_dx.pdb index e3b740c..e3da30f 100644 Binary files a/pdb/otclient_dx.pdb and b/pdb/otclient_dx.pdb differ diff --git a/pdb/otclient_gl.pdb b/pdb/otclient_gl.pdb index 864d938..7708130 100644 Binary files a/pdb/otclient_gl.pdb and b/pdb/otclient_gl.pdb differ