mirror of
				https://github.com/OTCv8/otclientv8.git
				synced 2025-10-31 10:56:24 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			423 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			423 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| function executeBot(config, storage, tabs, msgCallback, saveConfigCallback, reloadCallback, websockets)
 | |
|   -- load lua and otui files
 | |
|   local configFiles = g_resources.listDirectoryFiles("/bot/" .. config, true, false)  
 | |
|   local luaFiles = {}
 | |
|   local uiFiles = {}
 | |
|   for i, file in ipairs(configFiles) do
 | |
|     local ext = file:split(".")
 | |
|     if ext[#ext]:lower() == "lua" then
 | |
|       table.insert(luaFiles, file)
 | |
|     end
 | |
|     if ext[#ext]:lower() == "ui" or ext[#ext]:lower() == "otui" then
 | |
|       table.insert(uiFiles, file)
 | |
|     end
 | |
|   end
 | |
|   
 | |
|   if #luaFiles == 0 then
 | |
|     return error("Config (/bot/" .. config .. ") doesn't have lua files")
 | |
|   end
 | |
|   
 | |
|   -- init bot variables
 | |
|   local context = {}
 | |
|   context.configDir = "/bot/".. config
 | |
|   context.tabs = tabs
 | |
|   context.mainTab = context.tabs:addTab("Main", g_ui.createWidget('BotPanel')).tabPanel.content
 | |
|   context.panel = context.mainTab
 | |
|   context.saveConfig = saveConfigCallback
 | |
|   context.reload = reloadCallback
 | |
|   
 | |
|   context.storage = storage
 | |
|   if context.storage._macros == nil then
 | |
|     context.storage._macros = {} -- active macros
 | |
|   end
 | |
| 
 | |
|   -- websockets, macros, hotkeys, scheduler, icons, callbacks
 | |
|   context._websockets = websockets
 | |
|   context._macros = {}
 | |
|   context._hotkeys = {}
 | |
|   context._scheduler = {}
 | |
|   context._callbacks = {
 | |
|     onKeyDown = {},
 | |
|     onKeyUp = {},
 | |
|     onKeyPress = {},
 | |
|     onTalk = {},
 | |
|     onTextMessage = {},
 | |
|     onLoginAdvice = {},
 | |
|     onAddThing = {},
 | |
|     onRemoveThing = {},
 | |
|     onCreatureAppear = {},
 | |
|     onCreatureDisappear = {},
 | |
|     onCreaturePositionChange = {},
 | |
|     onCreatureHealthPercentChange = {},
 | |
|     onUse = {},
 | |
|     onUseWith = {},
 | |
|     onContainerOpen = {},
 | |
|     onContainerClose = {},
 | |
|     onContainerUpdateItem = {},
 | |
|     onMissle = {},
 | |
|     onAnimatedText = {},
 | |
|     onStaticText = {},
 | |
|     onChannelList = {},
 | |
|     onOpenChannel = {},
 | |
|     onCloseChannel = {},
 | |
|     onChannelEvent = {},
 | |
|     onTurn = {},
 | |
|     onWalk = {},
 | |
|     onImbuementWindow = {},
 | |
|     onModalDialog = {},
 | |
|     onAttackingCreatureChange = {},
 | |
|     onManaChange = {},
 | |
|     onStatesChange = {},
 | |
|     onAddItem = {},
 | |
|     onGameEditText = {},
 | |
|     onGroupSpellCooldown = {},
 | |
|     onSpellCooldown = {},
 | |
|     onRemoveItem = {},
 | |
|     onInventoryChange = {}
 | |
|   }
 | |
|   
 | |
|   -- basic functions & classes
 | |
|   context.print = print
 | |
|   context.bit32 = bit32
 | |
|   context.bit = bit
 | |
|   context.pairs = pairs
 | |
|   context.ipairs = ipairs
 | |
|   context.tostring = tostring
 | |
|   context.math = math
 | |
|   context.table = table
 | |
|   context.setmetatable = setmetatable
 | |
|   context.string = string
 | |
|   context.tonumber = tonumber
 | |
|   context.type = type
 | |
|   context.pcall = pcall
 | |
|   context.os = {
 | |
|     time = os.time,
 | |
|     difftime = os.difftime,
 | |
|     date = os.date,
 | |
|     clock = os.clock
 | |
|   }
 | |
|   context.load = function(str) return assert(load(str, nil, nil, context)) end
 | |
|   context.loadstring = context.load
 | |
|   context.assert = assert
 | |
|   context.dofile = function(file) assert(load(g_resources.readFileContents("/bot/" .. config .. "/" .. file), file, nil, context))() end
 | |
|   context.gcinfo = gcinfo
 | |
|   context.tr = tr
 | |
|   context.json = json
 | |
|   context.base64 = base64
 | |
|   context.regexMatch = regexMatch
 | |
|   context.getDistanceBetween = function(p1, p2)
 | |
|     return math.max(math.abs(p1.x - p2.x), math.abs(p1.y - p2.y))
 | |
|   end
 | |
|   context.isMobile = g_app.isMobile
 | |
|   context.getVersion = g_app.getVersion
 | |
|   
 | |
|   -- classes
 | |
|   context.g_resources = g_resources
 | |
|   context.g_game = g_game
 | |
|   context.g_map = g_map
 | |
|   context.g_ui = g_ui
 | |
|   context.g_sounds = g_sounds
 | |
|   context.g_window = g_window
 | |
|   context.g_mouse = g_mouse
 | |
|   context.g_keyboard = g_keyboard
 | |
|   context.g_things = g_things
 | |
|   context.g_settings = g_settings
 | |
|   context.g_platform = {
 | |
|     openUrl = g_platform.openUrl,
 | |
|     openDir = g_platform.openDir,
 | |
|   }
 | |
| 
 | |
|   context.Item = Item
 | |
|   context.Creature = Creature
 | |
|   context.ThingType = ThingType
 | |
|   context.Effect = Effect
 | |
|   context.Missile = Missile
 | |
|   context.Player = Player
 | |
|   context.Monster = Monster
 | |
|   context.StaticText = StaticText
 | |
|   context.HTTP = HTTP
 | |
|   context.OutputMessage = OutputMessage
 | |
|   context.modules = modules
 | |
| 
 | |
|   -- log functions
 | |
|   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      
 | |
| 
 | |
|   -- init context
 | |
|   context.now = g_clock.millis()
 | |
|   context.time = g_clock.millis()
 | |
|   context.player = g_game.getLocalPlayer()
 | |
| 
 | |
|   -- init functions
 | |
|   G.botContext = context
 | |
|   dofiles("functions")
 | |
|   context.Panels = {}
 | |
|   dofiles("panels")
 | |
|   G.botContext = nil
 | |
| 
 | |
|   -- run ui scripts
 | |
|   for i, file in ipairs(uiFiles) do
 | |
|     g_ui.importStyle(file)
 | |
|   end
 | |
| 
 | |
|   -- run lua script
 | |
|   for i, file in ipairs(luaFiles) do
 | |
|     assert(load(g_resources.readFileContents(file), file, nil, context))()
 | |
|     context.panel = context.mainTab -- reset default tab
 | |
|   end
 | |
| 
 | |
|   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.enabled then
 | |
|           local status, result = pcall(function()
 | |
|             if macro.callback(macro) then
 | |
|                 macro.lastExecution = context.now
 | |
|             end
 | |
|           end)
 | |
|           if not status then
 | |
|             context.error("Macro: " .. macro.name .. " execution error: " .. result)
 | |
|           end
 | |
|         end
 | |
|       end
 | |
|       
 | |
|       while #context._scheduler > 0 and context._scheduler[1].execution <= g_clock.millis() do
 | |
|         local status, result = pcall(function()
 | |
|           context._scheduler[1].callback()
 | |
|         end)
 | |
|         if not status then
 | |
|           context.error("Schedule execution error: " .. result)
 | |
|         end
 | |
|         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 then
 | |
|           if hotkey.single then
 | |
|             if hotkey.callback() then
 | |
|               hotkey.lastExecution = context.now            
 | |
|             end
 | |
|           end
 | |
|           if hotkey.switch then
 | |
|             hotkey.switch:setOn(true)
 | |
|           end
 | |
|         end
 | |
|         for i, callback in ipairs(context._callbacks.onKeyDown) do
 | |
|           callback(keyDesc)
 | |
|         end
 | |
|       end,
 | |
|       onKeyUp = function(keyCode, keyboardModifiers)
 | |
|         local keyDesc = determineKeyComboDesc(keyCode, keyboardModifiers)
 | |
|         local hotkey = context._hotkeys[keyDesc]
 | |
|         if hotkey then        
 | |
|           if hotkey.switch then
 | |
|             hotkey.switch:setOn(false)
 | |
|           end
 | |
|         end
 | |
|         for i, callback in ipairs(context._callbacks.onKeyUp) do
 | |
|           callback(keyDesc)
 | |
|         end
 | |
|       end,
 | |
|       onKeyPress = function(keyCode, keyboardModifiers, autoRepeatTicks)
 | |
|         local keyDesc = determineKeyComboDesc(keyCode, keyboardModifiers)
 | |
|         local hotkey = context._hotkeys[keyDesc]
 | |
|         if hotkey and not hotkey.single then
 | |
|           if hotkey.callback() then
 | |
|             hotkey.lastExecution = context.now          
 | |
|           end
 | |
|         end
 | |
|         for i, callback in ipairs(context._callbacks.onKeyPress) do
 | |
|           callback(keyDesc, autoRepeatTicks)
 | |
|         end
 | |
|       end,
 | |
|       onTalk = function(name, level, mode, text, channelId, pos)
 | |
|         for i, callback in ipairs(context._callbacks.onTalk) do
 | |
|           callback(name, level, mode, text, channelId, pos)
 | |
|         end
 | |
|       end,
 | |
|       onImbuementWindow = function(itemId, slots, activeSlots, imbuements, needItems)
 | |
|         for i, callback in ipairs(context._callbacks.onImbuementWindow) do
 | |
|           callback(itemId, slots, activeSlots, imbuements, needItems)
 | |
|         end
 | |
|       end,
 | |
|       onTextMessage = function(mode, text)
 | |
|         for i, callback in ipairs(context._callbacks.onTextMessage) do
 | |
|           callback(mode, text)
 | |
|         end
 | |
|       end,
 | |
|       onLoginAdvice = function(message)
 | |
|         for i, callback in ipairs(context._callbacks.onLoginAdvice) do
 | |
|           callback(message)
 | |
|         end
 | |
|       end,      
 | |
|       onAddThing = function(tile, thing)
 | |
|         for i, callback in ipairs(context._callbacks.onAddThing) do
 | |
|           callback(tile, thing)
 | |
|         end      
 | |
|       end,
 | |
|       onRemoveThing = function(tile, thing)
 | |
|         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,
 | |
|       onUse = function(pos, itemId, stackPos, subType)
 | |
|         for i, callback in ipairs(context._callbacks.onUse) do
 | |
|           callback(pos, itemId, stackPos, subType)
 | |
|         end      
 | |
|       end,
 | |
|       onUseWith = function(pos, itemId, target, subType)
 | |
|         for i, callback in ipairs(context._callbacks.onUseWith) do
 | |
|           callback(pos, itemId, target, subType)
 | |
|         end
 | |
|       end,
 | |
|       onContainerOpen = function(container, previousContainer)
 | |
|         for i, callback in ipairs(context._callbacks.onContainerOpen) do
 | |
|           callback(container, previousContainer)
 | |
|         end
 | |
|       end,
 | |
|       onContainerClose = function(container)
 | |
|         for i, callback in ipairs(context._callbacks.onContainerClose) do
 | |
|           callback(container)
 | |
|         end
 | |
|       end,
 | |
|       onContainerUpdateItem = function(container, slot, item, oldItem)
 | |
|         for i, callback in ipairs(context._callbacks.onContainerUpdateItem) do
 | |
|           callback(container, slot, item, oldItem)
 | |
|         end
 | |
|       end,
 | |
|       onMissle = function(missle)
 | |
|         for i, callback in ipairs(context._callbacks.onMissle) do
 | |
|           callback(missle)
 | |
|         end
 | |
|       end,
 | |
|       onAnimatedText = function(thing, text)
 | |
|         for i, callback in ipairs(context._callbacks.onAnimatedText) do
 | |
|           callback(thing, text)
 | |
|         end
 | |
|       end,
 | |
|       onStaticText = function(thing, text)
 | |
|         for i, callback in ipairs(context._callbacks.onStaticText) do
 | |
|           callback(thing, text)
 | |
|         end
 | |
|       end,
 | |
|       onChannelList = function(channels)
 | |
|         for i, callback in ipairs(context._callbacks.onChannelList) do
 | |
|           callback(channels)
 | |
|         end      
 | |
|       end,
 | |
|       onOpenChannel = function(channelId, channelName)
 | |
|         for i, callback in ipairs(context._callbacks.onOpenChannel) do
 | |
|           callback(channels)
 | |
|         end      
 | |
|       end,
 | |
|       onCloseChannel = function(channelId)
 | |
|         for i, callback in ipairs(context._callbacks.onCloseChannel) do
 | |
|           callback(channelId)
 | |
|         end      
 | |
|       end,
 | |
|       onChannelEvent = function(channelId, name, event)
 | |
|         for i, callback in ipairs(context._callbacks.onChannelEvent) do
 | |
|           callback(channelId, name, event)
 | |
|         end      
 | |
|       end,
 | |
|       onTurn = function(creature, direction)
 | |
|         for i, callback in ipairs(context._callbacks.onTurn) do
 | |
|           callback(creature, direction)
 | |
|         end      
 | |
|       end,
 | |
|       onWalk = function(creature, oldPos, newPos)
 | |
|         for i, callback in ipairs(context._callbacks.onWalk) do
 | |
|           callback(creature, oldPos, newPos)
 | |
|         end      
 | |
|       end,
 | |
|       onModalDialog = function(id, title, message, buttons, enterButton, escapeButton, choices, priority)
 | |
|         for i, callback in ipairs(context._callbacks.onModalDialog) do
 | |
|           callback(id, title, message, buttons, enterButton, escapeButton, choices, priority)
 | |
|         end
 | |
|       end,
 | |
|       onGameEditText = function(id, itemId, maxLength, text, writer, time)
 | |
|         for i, callback in ipairs(context._callbacks.onGameEditText) do
 | |
|           callback(id, itemId, maxLength, text, writer, time)
 | |
|         end
 | |
|       end,
 | |
|       onAttackingCreatureChange = function(creature, oldCreature)
 | |
|         for i, callback in ipairs(context._callbacks.onAttackingCreatureChange) do
 | |
|           callback(creature, oldCreature)
 | |
|         end
 | |
|       end,
 | |
|       onManaChange = function(player, mana, maxMana, oldMana, oldMaxMana)
 | |
|         for i, callback in ipairs(context._callbacks.onManaChange) do
 | |
|           callback(player, mana, maxMana, oldMana, oldMaxMana)
 | |
|         end
 | |
|       end,
 | |
|       onAddItem = function(container, slot, item)
 | |
|         for i, callback in ipairs(context._callbacks.onAddItem) do
 | |
|           callback(container, slot, item)
 | |
|         end
 | |
|       end,
 | |
|       onRemoveItem = function(container, slot, item)
 | |
|         for i, callback in ipairs(context._callbacks.onRemoveItem) do
 | |
|           callback(container, slot, item)
 | |
|         end
 | |
|       end,
 | |
|       onStatesChange = function(player, states, oldStates)
 | |
|         for i, callback in ipairs(context._callbacks.onStatesChange) do
 | |
|           callback(player, states, oldStates)
 | |
|         end
 | |
|       end,
 | |
|       onGroupSpellCooldown = function(iconId, duration)
 | |
|         for i, callback in ipairs(context._callbacks.onGroupSpellCooldown) do
 | |
|           callback(iconId, duration)
 | |
|         end
 | |
|       end,
 | |
|       onSpellCooldown = function(iconId, duration)
 | |
|         for i, callback in ipairs(context._callbacks.onSpellCooldown) do
 | |
|           callback(iconId, duration)
 | |
|         end
 | |
|       end,
 | |
|       onSpellCooldown = function(iconId, duration)
 | |
|         for i, callback in ipairs(context._callbacks.onSpellCooldown) do
 | |
|           callback(iconId, duration)
 | |
|         end
 | |
|       end,
 | |
|       onInventoryChange = function(player, slot, item, oldItem)
 | |
|         for i, callback in ipairs(context._callbacks.onInventoryChange) do
 | |
|           callback(player, slot, item, oldItem)
 | |
|         end
 | |
|       end
 | |
|     }    
 | |
|   }
 | |
| end | 
