Version 0.999 BETA - a lot of bug fixes, improvments and more advanced bot

This commit is contained in:
OTCv8
2019-10-31 05:46:22 +01:00
parent 017fa290b4
commit 06b08af1df
36 changed files with 1513 additions and 415 deletions

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -0,0 +1,3 @@
local context = G.botContext
context.test = function() return context.info("test") end

View 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

View 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