mirror of
https://github.com/OTCv8/otclientv8.git
synced 2025-10-20 22:53:26 +02:00
Version 2.6.1
This commit is contained in:
315
modules/game_bot/default_configs/vithrax_1.3/cavebot/actions.lua
Normal file
315
modules/game_bot/default_configs/vithrax_1.3/cavebot/actions.lua
Normal file
@@ -0,0 +1,315 @@
|
||||
CaveBot.Actions = {}
|
||||
|
||||
-- it adds an action widget to list
|
||||
CaveBot.addAction = function(action, value, focus)
|
||||
action = action:lower()
|
||||
local raction = CaveBot.Actions[action]
|
||||
if not raction then
|
||||
return error("Invalid cavebot action: " .. action)
|
||||
end
|
||||
if type(value) == 'number' then
|
||||
value = tostring(value)
|
||||
end
|
||||
local widget = UI.createWidget("CaveBotAction", CaveBot.actionList)
|
||||
widget:setText(action .. ":" .. value:split("\n")[1])
|
||||
widget.action = action
|
||||
widget.value = value
|
||||
if raction.color then
|
||||
widget:setColor(raction.color)
|
||||
end
|
||||
widget.onDoubleClick = function(cwidget) -- edit on double click
|
||||
if CaveBot.Editor then
|
||||
schedule(20, function() -- schedule to have correct focus
|
||||
CaveBot.Editor.edit(cwidget.action, cwidget.value, function(action, value)
|
||||
CaveBot.editAction(cwidget, action, value)
|
||||
CaveBot.save()
|
||||
end)
|
||||
end)
|
||||
end
|
||||
end
|
||||
if focus then
|
||||
widget:focus()
|
||||
CaveBot.actionList:ensureChildVisible(widget)
|
||||
end
|
||||
return widget
|
||||
end
|
||||
|
||||
-- it updates existing widget, you should call CaveBot.save() later
|
||||
CaveBot.editAction = function(widget, action, value)
|
||||
action = action:lower()
|
||||
local raction = CaveBot.Actions[action]
|
||||
if not raction then
|
||||
return error("Invalid cavebot action: " .. action)
|
||||
end
|
||||
|
||||
if not widget.action or not widget.value then
|
||||
return error("Invalid cavebot action widget, has missing action or value")
|
||||
end
|
||||
|
||||
widget:setText(action .. ":" .. value:split("\n")[1])
|
||||
widget.action = action
|
||||
widget.value = value
|
||||
if raction.color then
|
||||
widget:setColor(raction.color)
|
||||
end
|
||||
return widget
|
||||
end
|
||||
|
||||
--[[
|
||||
registerAction:
|
||||
action - string, color - string, callback = function(value, retries, prev)
|
||||
value is a string value of action, retries is number which will grow by 1 if return is "retry"
|
||||
prev is a true when previuos action was executed succesfully, false otherwise
|
||||
it must return true if executed correctly, false otherwise
|
||||
it can also return string "retry", then the function will be called again in 20 ms
|
||||
]]--
|
||||
CaveBot.registerAction = function(action, color, callback)
|
||||
action = action:lower()
|
||||
if CaveBot.Actions[action] then
|
||||
return error("Duplicated acction: " .. action)
|
||||
end
|
||||
CaveBot.Actions[action] = {
|
||||
color=color,
|
||||
callback=callback
|
||||
}
|
||||
end
|
||||
|
||||
CaveBot.registerAction("label", "yellow", function(value, retries, prev)
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("gotolabel", "#FFFF55", function(value, retries, prev)
|
||||
return CaveBot.gotoLabel(value)
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("delay", "#AAAAAA", function(value, retries, prev)
|
||||
if retries == 0 then
|
||||
CaveBot.delay(tonumber(value))
|
||||
return "retry"
|
||||
end
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("function", "red", function(value, retries, prev)
|
||||
local prefix = "local retries = " .. retries .. "\nlocal prev = " .. tostring(prev) .. "\nlocal delay = CaveBot.delay\nlocal gotoLabel = CaveBot.gotoLabel\n"
|
||||
prefix = prefix .. "local macro = function() error('Macros inside cavebot functions are not allowed') end\n"
|
||||
for extension, callbacks in pairs(CaveBot.Extensions) do
|
||||
prefix = prefix .. "local " .. extension .. " = CaveBot.Extensions." .. extension .. "\n"
|
||||
end
|
||||
local status, result = pcall(function()
|
||||
return assert(load(prefix .. value, "cavebot_function"))()
|
||||
end)
|
||||
if not status then
|
||||
error("Error in cavebot function:\n" .. result)
|
||||
return false
|
||||
end
|
||||
return result
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("goto", "green", function(value, retries, prev)
|
||||
local pos = regexMatch(value, "\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+),?\\s*([0-9]?)")
|
||||
if not pos[1] then
|
||||
error("Invalid cavebot goto action value. It should be position (x,y,z), is: " .. value)
|
||||
return false
|
||||
end
|
||||
|
||||
if CaveBot.Config.get("mapClick") then
|
||||
if retries >= 5 then
|
||||
return false -- tried 5 times, can't get there
|
||||
end
|
||||
else
|
||||
if retries >= 100 then
|
||||
return false -- tried 100 times, can't get there
|
||||
end
|
||||
end
|
||||
|
||||
local precision = tonumber(pos[1][5])
|
||||
pos = {x=tonumber(pos[1][2]), y=tonumber(pos[1][3]), z=tonumber(pos[1][4])}
|
||||
local playerPos = player:getPosition()
|
||||
if pos.z ~= playerPos.z then
|
||||
return false -- different floor
|
||||
end
|
||||
|
||||
if math.abs(pos.x-playerPos.x) + math.abs(pos.y-playerPos.y) > 40 then
|
||||
return false -- too far way
|
||||
end
|
||||
|
||||
local minimapColor = g_map.getMinimapColor(pos)
|
||||
local stairs = (minimapColor >= 210 and minimapColor <= 213)
|
||||
|
||||
if stairs then
|
||||
if math.abs(pos.x-playerPos.x) == 0 and math.abs(pos.y-playerPos.y) <= 0 then
|
||||
return true -- already at position
|
||||
end
|
||||
elseif math.abs(pos.x-playerPos.x) == 0 and math.abs(pos.y-playerPos.y) <= (precision or 1) then
|
||||
return true -- already at position
|
||||
end
|
||||
-- check if there's a path to that place, ignore creatures and fields
|
||||
local path = findPath(playerPos, pos, 40, { ignoreNonPathable = true, precision = 1, ignoreCreatures = true })
|
||||
if not path then
|
||||
return false -- there's no way
|
||||
end
|
||||
|
||||
-- check if there's a path to destination but consider Creatures (attack only if trapped)
|
||||
local path2 = findPath(playerPos, pos, 40, { ignoreNonPathable = true, precision = 1 })
|
||||
if not path2 then
|
||||
local monsters = {}
|
||||
for i, spec in pairs(getSpectators()) do
|
||||
if spec:isMonster() and spec:getType() ~= 3 and spec:canShoot() and findPath(playerPos, spec:getPosition(), 20, {ignoreNonPathable = true, precision = 1}) then
|
||||
table.insert(monsters, {mob = spec, dist = getDistanceBetween(pos, spec:getPosition())})
|
||||
end
|
||||
end
|
||||
table.sort(monsters, function(a,b) return a.dist < b.dist end)
|
||||
if monsters[1] then
|
||||
g_game.attack(monsters[1].mob)
|
||||
storage.blockMonster = monsters[1].mob
|
||||
autoWalk(storage.blockMonster, 10, {precision = 1})
|
||||
storage.clearing = true
|
||||
CaveBot.setOff()
|
||||
g_game.setChaseMode(1)
|
||||
schedule(10000, function() CaveBot.setOn() end) -- just in case callback trigger fails
|
||||
return "retry"
|
||||
else
|
||||
return false -- there's no way
|
||||
end
|
||||
end
|
||||
|
||||
-- try to find path, don't ignore creatures, don't ignore fields
|
||||
if not CaveBot.Config.get("ignoreFields") and CaveBot.walkTo(pos, 40) then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
-- try to find path, don't ignore creatures, ignore fields
|
||||
if CaveBot.walkTo(pos, 40, { ignoreNonPathable = true }) then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
if retries >= 3 then
|
||||
-- try to lower precision, find something close to final position
|
||||
local precison = retries - 1
|
||||
if stairs then
|
||||
precison = 0
|
||||
end
|
||||
if CaveBot.walkTo(pos, 50, { ignoreNonPathable = true, precision = precison }) then
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
|
||||
if not CaveBot.Config.get("mapClick") and retries >= 5 then
|
||||
return false
|
||||
end
|
||||
|
||||
if CaveBot.Config.get("skipBlocked") then
|
||||
return false
|
||||
end
|
||||
|
||||
-- everything else failed, try to walk ignoring creatures, maybe will work
|
||||
CaveBot.walkTo(pos, 40, { ignoreNonPathable = true, precision = 1, ignoreCreatures = true })
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
onCreatureDisappear(function(creature)
|
||||
if creature ~= storage.blockMonster then return end
|
||||
if storage.clearing then
|
||||
CaveBot.setOn()
|
||||
storage.blockMonster = nil
|
||||
storage.clearing = false
|
||||
end
|
||||
end)
|
||||
|
||||
onCreaturePositionChange(function(creature, newPos, oldPos)
|
||||
if creature ~= storage.blockMonster and creature ~= player then return end
|
||||
if storage.clearing then
|
||||
if creature == storage.blockMonster and not findPath(player:getPosition(), newPos, 20, {ignoreNonPathable = true, precision = 1}) then
|
||||
CaveBot.setOn()
|
||||
storage.blockMonster = nil
|
||||
storage.clearing = false
|
||||
end
|
||||
if creature == player then
|
||||
if oldPos.z ~= newPos.z then
|
||||
CaveBot.setOn()
|
||||
storage.blockMonster = nil
|
||||
storage.clearing = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("use", "#FFB272", function(value, retries, prev)
|
||||
local pos = regexMatch(value, "\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)")
|
||||
if not pos[1] then
|
||||
local itemid = tonumber(value)
|
||||
if not itemid then
|
||||
error("Invalid cavebot use action value. It should be (x,y,z) or item id, is: " .. value)
|
||||
return false
|
||||
end
|
||||
use(itemid)
|
||||
return true
|
||||
end
|
||||
|
||||
pos = {x=tonumber(pos[1][2]), y=tonumber(pos[1][3]), z=tonumber(pos[1][4])}
|
||||
local playerPos = player:getPosition()
|
||||
if pos.z ~= playerPos.z then
|
||||
return false -- different floor
|
||||
end
|
||||
|
||||
if math.max(math.abs(pos.x-playerPos.x), math.abs(pos.y-playerPos.y)) > 7 then
|
||||
return false -- too far way
|
||||
end
|
||||
|
||||
local tile = g_map.getTile(pos)
|
||||
if not tile then
|
||||
return false
|
||||
end
|
||||
|
||||
local topThing = tile:getTopUseThing()
|
||||
if not topThing then
|
||||
return false
|
||||
end
|
||||
|
||||
use(topThing)
|
||||
CaveBot.delay(CaveBot.Config.get("useDelay") + CaveBot.Config.get("ping"))
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("usewith", "#EEB292", function(value, retries, prev)
|
||||
local pos = regexMatch(value, "\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)")
|
||||
if not pos[1] then
|
||||
if not itemid then
|
||||
error("Invalid cavebot usewith action value. It should be (itemid,x,y,z) or item id, is: " .. value)
|
||||
return false
|
||||
end
|
||||
use(itemid)
|
||||
return true
|
||||
end
|
||||
|
||||
local itemid = tonumber(pos[1][2])
|
||||
pos = {x=tonumber(pos[1][3]), y=tonumber(pos[1][4]), z=tonumber(pos[1][5])}
|
||||
local playerPos = player:getPosition()
|
||||
if pos.z ~= playerPos.z then
|
||||
return false -- different floor
|
||||
end
|
||||
|
||||
if math.max(math.abs(pos.x-playerPos.x), math.abs(pos.y-playerPos.y)) > 7 then
|
||||
return false -- too far way
|
||||
end
|
||||
|
||||
local tile = g_map.getTile(pos)
|
||||
if not tile then
|
||||
return false
|
||||
end
|
||||
|
||||
local topThing = tile:getTopUseThing()
|
||||
if not topThing then
|
||||
return false
|
||||
end
|
||||
|
||||
usewith(itemid, topThing)
|
||||
CaveBot.delay(CaveBot.Config.get("useDelay") + CaveBot.Config.get("ping"))
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("say", "#FF55FF", function(value, retries, prev)
|
||||
say(value)
|
||||
return true
|
||||
end)
|
@@ -0,0 +1,72 @@
|
||||
CaveBot.Extensions.Bank = {}
|
||||
|
||||
CaveBot.Extensions.Bank.setup = function()
|
||||
CaveBot.registerAction("bank", "#00FFFF", function(value, retries)
|
||||
local data = string.split(value, ",")
|
||||
local waitVal = 300
|
||||
local amount = 0
|
||||
local actionType
|
||||
local npcName
|
||||
if #data ~= 3 and #data ~= 2 then
|
||||
warn("CaveBot[Bank]: incorrect value!")
|
||||
return false
|
||||
else
|
||||
actionType = data[1]:trim():lower()
|
||||
npcName = data[2]:trim()
|
||||
if #data == 3 then
|
||||
amount = tonumber(data[3]:trim())
|
||||
end
|
||||
end
|
||||
|
||||
if actionType ~= "withdraw" and actionType ~= "deposit" then
|
||||
warn("CaveBot[Bank]: incorrect action type! should be withdraw/deposit, is: " .. actionType)
|
||||
return false
|
||||
elseif actionType == "withdraw" then
|
||||
local value = tonumber(amount)
|
||||
if not value then
|
||||
warn("CaveBot[Bank]: incorrect amount value! should be number, is: " .. amount)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if retries > 5 then
|
||||
print("CaveBot[Bank]: too many tries, skipping")
|
||||
return false
|
||||
end
|
||||
|
||||
local npc = getCreatureByName(npcName)
|
||||
if not npc then
|
||||
print("CaveBot[Bank]: NPC not found, skipping")
|
||||
return false
|
||||
end
|
||||
|
||||
local pos = player:getPosition()
|
||||
local npcPos = npc:getPosition()
|
||||
if math.max(math.abs(pos.x - npcPos.x), math.abs(pos.y - npcPos.y)) > 3 then
|
||||
CaveBot.walkTo(npcPos, 20, {ignoreNonPathable = true, precision=3})
|
||||
delay(300)
|
||||
return "retry"
|
||||
end
|
||||
|
||||
if actionType == "deposit" then
|
||||
NPC.say("hi")
|
||||
schedule(waitVal, function() NPC.say("deposit all") end)
|
||||
schedule(waitVal*2, function() NPC.say("yes") end)
|
||||
CaveBot.delay(waitVal*3)
|
||||
return true
|
||||
else
|
||||
NPC.say("hi")
|
||||
schedule(waitVal, function() NPC.say("withdraw") end)
|
||||
schedule(waitVal*2, function() NPC.say(value) end)
|
||||
schedule(waitVal*3, function() NPC.say("yes") end)
|
||||
CaveBot.delay(waitVal*4)
|
||||
return true
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("bank", "bank", {
|
||||
value="action, NPC name",
|
||||
title="Banker",
|
||||
description="action type(withdraw/deposit), NPC name, if withdraw: amount",
|
||||
})
|
||||
end
|
@@ -0,0 +1,116 @@
|
||||
CaveBot.Extensions.BuySupplies = {}
|
||||
|
||||
storage.buySuppliesCap = 0
|
||||
CaveBot.Extensions.BuySupplies.setup = function()
|
||||
CaveBot.registerAction("BuySupplies", "#00FFFF", function(value, retries)
|
||||
local item1Count = 0
|
||||
local item2Count = 0
|
||||
local item3Count = 0
|
||||
local item4Count = 0
|
||||
local item5Count = 0
|
||||
|
||||
local val = string.split(value, ",")
|
||||
local waitVal
|
||||
if #val == 0 or #val > 2 then
|
||||
warn("CaveBot[BuySupplies]: incorrect BuySupplies value")
|
||||
return false
|
||||
elseif #val == 2 then
|
||||
waitVal = tonumber(val[2]:trim())
|
||||
end
|
||||
|
||||
local npc = getCreatureByName(val[1]:trim())
|
||||
if not npc then
|
||||
print("CaveBot[BuySupplies]: NPC not found")
|
||||
return false
|
||||
end
|
||||
|
||||
if not waitVal and #val == 2 then
|
||||
warn("CaveBot[BuySupplies]: incorrect delay values!")
|
||||
elseif waitVal and #val == 2 then
|
||||
delay(waitVal)
|
||||
end
|
||||
|
||||
if retries > 40 then
|
||||
print("CaveBot[BuySupplies]: Too many tries, can't buy")
|
||||
return false
|
||||
end
|
||||
|
||||
if freecap() == storage.buySuppliesCap then
|
||||
storage.buySuppliesCap = 0
|
||||
print("CaveBot[BuySupplies]: Bought Everything, proceeding")
|
||||
return true
|
||||
end
|
||||
|
||||
delay(800)
|
||||
|
||||
local pos = player:getPosition()
|
||||
local npcPos = npc:getPosition()
|
||||
if math.max(math.abs(pos.x - npcPos.x), math.abs(pos.y - npcPos.y)) > 3 then
|
||||
CaveBot.walkTo(npcPos, 20, {ignoreNonPathable = true, precision=3})
|
||||
delay(300)
|
||||
return "retry"
|
||||
end
|
||||
|
||||
for _, container in pairs(getContainers()) do
|
||||
for _, item in ipairs(container:getItems()) do
|
||||
if (storage[suppliesPanelName].item1 > 100) and (item:getId() == storage[suppliesPanelName].item1) then
|
||||
item1Count = item1Count + item:getCount()
|
||||
end
|
||||
if (storage[suppliesPanelName].item2 > 100) and (item:getId() == storage[suppliesPanelName].item2) then
|
||||
item2Count = item2Count + item:getCount()
|
||||
end
|
||||
if (storage[suppliesPanelName].item3 > 100) and (item:getId() == storage[suppliesPanelName].item3) then
|
||||
item3Count = item3Count + item:getCount()
|
||||
end
|
||||
if (storage[suppliesPanelName].item4 > 100) and (item:getId() == storage[suppliesPanelName].item4) then
|
||||
item4Count = item4Count + item:getCount()
|
||||
end
|
||||
if (storage[suppliesPanelName].item5 > 100) and (item:getId() == storage[suppliesPanelName].item5) then
|
||||
item5Count = item5Count + item:getCount()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local itemList = {
|
||||
item1 = {ID = storage[suppliesPanelName].item1, maxAmount = storage[suppliesPanelName].item1Max, currentAmount = item1Count},
|
||||
item2 = {ID = storage[suppliesPanelName].item2, maxAmount = storage[suppliesPanelName].item2Max, currentAmount = item2Count},
|
||||
item3 = {ID = storage[suppliesPanelName].item3, maxAmount = storage[suppliesPanelName].item3Max, currentAmount = item3Count},
|
||||
item4 = {ID = storage[suppliesPanelName].item4, maxAmount = storage[suppliesPanelName].item4Max, currentAmount = item4Count},
|
||||
item5 = {ID = storage[suppliesPanelName].item5, maxAmount = storage[suppliesPanelName].item5Max, currentAmount = item5Count}
|
||||
}
|
||||
|
||||
if not NPC.isTrading() then
|
||||
NPC.say("hi")
|
||||
schedule(500, function() NPC.say("trade") end)
|
||||
else
|
||||
storage.buySuppliesCap = freecap()
|
||||
end
|
||||
|
||||
for i, item in pairs(itemList) do
|
||||
if item["ID"] > 100 then
|
||||
local amountToBuy = item["maxAmount"] - item["currentAmount"]
|
||||
if amountToBuy > 100 then
|
||||
for i=1, math.ceil(amountToBuy/100), 1 do
|
||||
NPC.buy(item["ID"], math.min(100, amountToBuy))
|
||||
amountToBuy = amountToBuy - math.min(100, amountToBuy)
|
||||
print("CaveBot[BuySupplies]: bought " .. amountToBuy .. "x " .. item["ID"])
|
||||
return "retry"
|
||||
end
|
||||
else
|
||||
if amountToBuy > 0 then
|
||||
NPC.buy(item["ID"], amountToBuy)
|
||||
print("CaveBot[BuySupplies]: bought " .. amountToBuy .. "x " .. item["ID"])
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("buysupplies", "buy supplies", {
|
||||
value="NPC name",
|
||||
title="Buy Supplies",
|
||||
description="NPC Name, delay(in ms, optional)",
|
||||
})
|
||||
end
|
224
modules/game_bot/default_configs/vithrax_1.3/cavebot/cavebot.lua
Normal file
224
modules/game_bot/default_configs/vithrax_1.3/cavebot/cavebot.lua
Normal file
@@ -0,0 +1,224 @@
|
||||
local cavebotMacro = nil
|
||||
local config = nil
|
||||
|
||||
-- ui
|
||||
local configWidget = UI.Config()
|
||||
local ui = UI.createWidget("CaveBotPanel")
|
||||
|
||||
ui.list = ui.listPanel.list -- shortcut
|
||||
CaveBot.actionList = ui.list
|
||||
|
||||
if CaveBot.Editor then
|
||||
CaveBot.Editor.setup()
|
||||
end
|
||||
if CaveBot.Config then
|
||||
CaveBot.Config.setup()
|
||||
end
|
||||
for extension, callbacks in pairs(CaveBot.Extensions) do
|
||||
if callbacks.setup then
|
||||
callbacks.setup()
|
||||
end
|
||||
end
|
||||
|
||||
-- main loop, controlled by config
|
||||
local actionRetries = 0
|
||||
local prevActionResult = true
|
||||
cavebotMacro = macro(20, function()
|
||||
if TargetBot and TargetBot.isActive() and not TargetBot.isCaveBotActionAllowed() then
|
||||
CaveBot.resetWalking()
|
||||
return -- target bot or looting is working, wait
|
||||
end
|
||||
|
||||
if CaveBot.doWalking() then
|
||||
return -- executing walking
|
||||
end
|
||||
|
||||
local actions = ui.list:getChildCount()
|
||||
if actions == 0 then return end
|
||||
local currentAction = ui.list:getFocusedChild()
|
||||
if not currentAction then
|
||||
currentAction = ui.list:getFirstChild()
|
||||
end
|
||||
local action = CaveBot.Actions[currentAction.action]
|
||||
local value = currentAction.value
|
||||
local retry = false
|
||||
if action then
|
||||
local status, result = pcall(function()
|
||||
CaveBot.resetWalking()
|
||||
return action.callback(value, actionRetries, prevActionResult)
|
||||
end)
|
||||
if status then
|
||||
if result == "retry" then
|
||||
actionRetries = actionRetries + 1
|
||||
retry = true
|
||||
elseif type(result) == 'boolean' then
|
||||
actionRetries = 0
|
||||
prevActionResult = result
|
||||
else
|
||||
error("Invalid return from cavebot action (" .. currentAction.action .. "), should be \"retry\", false or true, is: " .. tostring(result))
|
||||
end
|
||||
else
|
||||
error("Error while executing cavebot action (" .. currentAction.action .. "):\n" .. result)
|
||||
end
|
||||
else
|
||||
error("Invalid cavebot action: " .. currentAction.action)
|
||||
end
|
||||
|
||||
if retry then
|
||||
return
|
||||
end
|
||||
|
||||
if currentAction ~= ui.list:getFocusedChild() then
|
||||
-- focused child can change durring action, get it again and reset state
|
||||
currentAction = ui.list:getFocusedChild() or ui.list:getFirstChild()
|
||||
actionRetries = 0
|
||||
prevActionResult = true
|
||||
end
|
||||
local nextAction = ui.list:getChildIndex(currentAction) + 1
|
||||
if nextAction > actions then
|
||||
nextAction = 1
|
||||
end
|
||||
ui.list:focusChild(ui.list:getChildByIndex(nextAction))
|
||||
end)
|
||||
|
||||
-- config, its callback is called immediately, data can be nil
|
||||
local lastConfig = ""
|
||||
config = Config.setup("cavebot_configs", configWidget, "cfg", function(name, enabled, data)
|
||||
if enabled and CaveBot.Recorder.isOn() then
|
||||
CaveBot.Recorder.disable()
|
||||
CaveBot.setOff()
|
||||
return
|
||||
end
|
||||
|
||||
local currentActionIndex = ui.list:getChildIndex(ui.list:getFocusedChild())
|
||||
ui.list:destroyChildren()
|
||||
if not data then return cavebotMacro.setOff() end
|
||||
|
||||
local cavebotConfig = nil
|
||||
for k,v in ipairs(data) do
|
||||
if type(v) == "table" and #v == 2 then
|
||||
if v[1] == "config" then
|
||||
local status, result = pcall(function()
|
||||
return json.decode(v[2])
|
||||
end)
|
||||
if not status then
|
||||
error("Error while parsing CaveBot extensions from config:\n" .. result)
|
||||
else
|
||||
cavebotConfig = result
|
||||
end
|
||||
elseif v[1] == "extensions" then
|
||||
local status, result = pcall(function()
|
||||
return json.decode(v[2])
|
||||
end)
|
||||
if not status then
|
||||
error("Error while parsing CaveBot extensions from config:\n" .. result)
|
||||
else
|
||||
for extension, callbacks in pairs(CaveBot.Extensions) do
|
||||
if callbacks.onConfigChange then
|
||||
callbacks.onConfigChange(name, enabled, result[extension])
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
CaveBot.addAction(v[1], v[2])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CaveBot.Config.onConfigChange(name, enabled, cavebotConfig)
|
||||
|
||||
actionRetries = 0
|
||||
CaveBot.resetWalking()
|
||||
prevActionResult = true
|
||||
cavebotMacro.setOn(enabled)
|
||||
cavebotMacro.delay = nil
|
||||
if lastConfig == name then
|
||||
-- restore focused child on the action list
|
||||
ui.list:focusChild(ui.list:getChildByIndex(currentActionIndex))
|
||||
end
|
||||
lastConfig = name
|
||||
end)
|
||||
|
||||
-- ui callbacks
|
||||
ui.showEditor.onClick = function()
|
||||
if not CaveBot.Editor then return end
|
||||
if ui.showEditor:isOn() then
|
||||
CaveBot.Editor.hide()
|
||||
ui.showEditor:setOn(false)
|
||||
else
|
||||
CaveBot.Editor.show()
|
||||
ui.showEditor:setOn(true)
|
||||
end
|
||||
end
|
||||
|
||||
ui.showConfig.onClick = function()
|
||||
if not CaveBot.Config then return end
|
||||
if ui.showConfig:isOn() then
|
||||
CaveBot.Config.hide()
|
||||
ui.showConfig:setOn(false)
|
||||
else
|
||||
CaveBot.Config.show()
|
||||
ui.showConfig:setOn(true)
|
||||
end
|
||||
end
|
||||
|
||||
-- public function, you can use them in your scripts
|
||||
CaveBot.isOn = function()
|
||||
return config.isOn()
|
||||
end
|
||||
|
||||
CaveBot.isOff = function()
|
||||
return config.isOff()
|
||||
end
|
||||
|
||||
CaveBot.setOn = function(val)
|
||||
if val == false then
|
||||
return CaveBot.setOff(true)
|
||||
end
|
||||
config.setOn()
|
||||
end
|
||||
|
||||
CaveBot.setOff = function(val)
|
||||
if val == false then
|
||||
return CaveBot.setOn(true)
|
||||
end
|
||||
config.setOff()
|
||||
end
|
||||
|
||||
CaveBot.delay = function(value)
|
||||
cavebotMacro.delay = math.max(cavebotMacro.delay or 0, now + value)
|
||||
end
|
||||
|
||||
CaveBot.gotoLabel = function(label)
|
||||
label = label:lower()
|
||||
for index, child in ipairs(ui.list:getChildren()) do
|
||||
if child.action == "label" and child.value:lower() == label then
|
||||
ui.list:focusChild(child)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
CaveBot.save = function()
|
||||
local data = {}
|
||||
for index, child in ipairs(ui.list:getChildren()) do
|
||||
table.insert(data, {child.action, child.value})
|
||||
end
|
||||
|
||||
if CaveBot.Config then
|
||||
table.insert(data, {"config", json.encode(CaveBot.Config.save())})
|
||||
end
|
||||
|
||||
local extension_data = {}
|
||||
for extension, callbacks in pairs(CaveBot.Extensions) do
|
||||
if callbacks.onSave then
|
||||
local ext_data = callbacks.onSave()
|
||||
if type(ext_data) == "table" then
|
||||
extension_data[extension] = ext_data
|
||||
end
|
||||
end
|
||||
end
|
||||
table.insert(data, {"extensions", json.encode(extension_data, 2)})
|
||||
config.save(data)
|
||||
end
|
@@ -0,0 +1,58 @@
|
||||
CaveBotAction < Label
|
||||
background-color: alpha
|
||||
text-offset: 2 0
|
||||
focusable: true
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
|
||||
CaveBotPanel < Panel
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
HorizontalSeparator
|
||||
margin-top: 2
|
||||
margin-bottom: 5
|
||||
|
||||
Panel
|
||||
id: listPanel
|
||||
height: 100
|
||||
margin-top: 2
|
||||
|
||||
TextList
|
||||
id: list
|
||||
anchors.fill: parent
|
||||
vertical-scrollbar: listScrollbar
|
||||
margin-right: 15
|
||||
focusable: false
|
||||
auto-focus: first
|
||||
|
||||
VerticalScrollBar
|
||||
id: listScrollbar
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
pixels-scroll: true
|
||||
step: 10
|
||||
|
||||
BotSwitch
|
||||
id: showEditor
|
||||
margin-top: 2
|
||||
|
||||
$on:
|
||||
text: Hide waypoints editor
|
||||
|
||||
$!on:
|
||||
text: Show waypoints editor
|
||||
|
||||
BotSwitch
|
||||
id: showConfig
|
||||
margin-top: 2
|
||||
|
||||
$on:
|
||||
text: Hide config
|
||||
|
||||
$!on:
|
||||
text: Show config
|
@@ -0,0 +1,94 @@
|
||||
-- config for bot
|
||||
CaveBot.Config = {}
|
||||
CaveBot.Config.values = {}
|
||||
CaveBot.Config.default_values = {}
|
||||
CaveBot.Config.value_setters = {}
|
||||
|
||||
CaveBot.Config.setup = function()
|
||||
CaveBot.Config.ui = UI.createWidget("CaveBotConfigPanel")
|
||||
local ui = CaveBot.Config.ui
|
||||
local add = CaveBot.Config.add
|
||||
|
||||
add("ping", "Server ping", 100)
|
||||
add("walkDelay", "Walk delay", 10)
|
||||
add("mapClick", "Use map click", false)
|
||||
add("mapClickDelay", "Map click delay", 100)
|
||||
add("ignoreFields", "Ignore fields", false)
|
||||
add("skipBlocked", "Skip blocked path", false)
|
||||
add("useDelay", "Delay after use", 400)
|
||||
end
|
||||
|
||||
CaveBot.Config.show = function()
|
||||
CaveBot.Config.ui:show()
|
||||
end
|
||||
|
||||
CaveBot.Config.hide = function()
|
||||
CaveBot.Config.ui:hide()
|
||||
end
|
||||
|
||||
CaveBot.Config.onConfigChange = function(configName, isEnabled, configData)
|
||||
for k, v in pairs(CaveBot.Config.default_values) do
|
||||
CaveBot.Config.value_setters[k](v)
|
||||
end
|
||||
if not configData then return end
|
||||
for k, v in pairs(configData) do
|
||||
if CaveBot.Config.value_setters[k] then
|
||||
CaveBot.Config.value_setters[k](v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CaveBot.Config.save = function()
|
||||
return CaveBot.Config.values
|
||||
end
|
||||
|
||||
CaveBot.Config.add = function(id, title, defaultValue)
|
||||
if CaveBot.Config.values[id] then
|
||||
return error("Duplicated config key: " .. id)
|
||||
end
|
||||
|
||||
local panel
|
||||
local setter -- sets value
|
||||
if type(defaultValue) == "number" then
|
||||
panel = UI.createWidget("CaveBotConfigNumberValuePanel", CaveBot.Config.ui)
|
||||
setter = function(value)
|
||||
CaveBot.Config.values[id] = value
|
||||
panel.value:setText(value, true)
|
||||
end
|
||||
setter(defaultValue)
|
||||
panel.value.onTextChange = function(widget, newValue)
|
||||
newValue = tonumber(newValue)
|
||||
if newValue then
|
||||
CaveBot.Config.values[id] = newValue
|
||||
CaveBot.save()
|
||||
end
|
||||
end
|
||||
elseif type(defaultValue) == "boolean" then
|
||||
panel = UI.createWidget("CaveBotConfigBooleanValuePanel", CaveBot.Config.ui)
|
||||
setter = function(value)
|
||||
CaveBot.Config.values[id] = value
|
||||
panel.value:setOn(value, true)
|
||||
end
|
||||
setter(defaultValue)
|
||||
panel.value.onClick = function(widget)
|
||||
widget:setOn(not widget:isOn())
|
||||
CaveBot.Config.values[id] = widget:isOn()
|
||||
CaveBot.save()
|
||||
end
|
||||
else
|
||||
return error("Invalid default value of config for key " .. id .. ", should be number or boolean")
|
||||
end
|
||||
|
||||
panel.title:setText(tr(title) .. ":")
|
||||
|
||||
CaveBot.Config.value_setters[id] = setter
|
||||
CaveBot.Config.values[id] = defaultValue
|
||||
CaveBot.Config.default_values[id] = defaultValue
|
||||
end
|
||||
|
||||
CaveBot.Config.get = function(id)
|
||||
if CaveBot.Config.values[id] == nil then
|
||||
return error("Invalid CaveBot.Config.get, id: " .. id)
|
||||
end
|
||||
return CaveBot.Config.values[id]
|
||||
end
|
@@ -0,0 +1,57 @@
|
||||
CaveBotConfigPanel < Panel
|
||||
id: cavebotEditor
|
||||
visible: false
|
||||
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
HorizontalSeparator
|
||||
margin-top: 5
|
||||
|
||||
Label
|
||||
text-align: center
|
||||
text: CaveBot Config
|
||||
margin-top: 5
|
||||
|
||||
CaveBotConfigNumberValuePanel < Panel
|
||||
height: 20
|
||||
margin-top: 5
|
||||
|
||||
BotTextEdit
|
||||
id: value
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 5
|
||||
width: 50
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
margin-left: 5
|
||||
|
||||
CaveBotConfigBooleanValuePanel < Panel
|
||||
height: 20
|
||||
margin-top: 5
|
||||
|
||||
BotSwitch
|
||||
id: value
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 5
|
||||
width: 50
|
||||
|
||||
$on:
|
||||
text: On
|
||||
|
||||
$!on:
|
||||
text: Off
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
margin-left: 5
|
@@ -0,0 +1,188 @@
|
||||
CaveBot.Extensions.DWithdraw = {}
|
||||
|
||||
comparePosition = function(pPos, tPos)
|
||||
return (getDistanceBetween(pPos, tPos) <= 1)
|
||||
end
|
||||
|
||||
local depotIDs = {3497, 3498, 3499, 3500}
|
||||
local depotContainers = {22797, 22798, 22799, 22800, 22801, 22802, 22803, 22804, 22805, 22806, 22807, 22808, 22809, 22810, 22811, 22812, 22813}
|
||||
storage.stopSearch = false
|
||||
storage.lootContainerOpen = false
|
||||
local i = 1
|
||||
|
||||
|
||||
CaveBot.Extensions.DWithdraw.setup = function()
|
||||
CaveBot.registerAction("dpwithdraw", "#00FFFF", function(value, retries)
|
||||
local capLimit = nil
|
||||
if retries > 600 then
|
||||
print("CaveBot[DepotWithdraw]: actions limit reached, proceeding")
|
||||
return true
|
||||
end
|
||||
delay(50)
|
||||
if not value or #string.split(value, ",") ~= 3 and #string.split(value, ",") ~= 4 then
|
||||
warn("CaveBot[DepotWithdraw]: incorrect value!")
|
||||
return false
|
||||
end
|
||||
local indexDp = tonumber(string.split(value, ",")[1]:trim())
|
||||
local destName = string.split(value, ",")[2]:trim()
|
||||
local destId = tonumber(string.split(value, ",")[3]:trim())
|
||||
if #string.split(value, ",") == 4 then
|
||||
capLimit = tonumber(string.split(value, ",")[4]:trim())
|
||||
end
|
||||
if freecap() < (capLimit or 200) then
|
||||
print("CaveBot[DepotWithdraw]: cap limit reached, proceeding")
|
||||
return true
|
||||
end
|
||||
local destContainer
|
||||
|
||||
for i, container in pairs(getContainers()) do
|
||||
if container:getName():lower() == destName:lower() then
|
||||
destContainer = container
|
||||
end
|
||||
if string.find(container:getName():lower(), "depot box") then
|
||||
if #container:getItems() == 0 then
|
||||
print("CaveBot[DepotWithdraw]: all items withdrawn")
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
if not destContainer then
|
||||
print("CaveBot[DepotWithdraw]: container not found!")
|
||||
return false
|
||||
end
|
||||
|
||||
if destContainer:getCapacity() == destContainer:getSize() then
|
||||
for j, item in pairs(destContainer:getItems()) do
|
||||
if item:getId() == destId then
|
||||
g_game.open(item, destContainer)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
print("CaveBot[DepotWithdraw]: loot containers full!")
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
local tileList = {}
|
||||
local tPos
|
||||
local depotClear = false
|
||||
local depotOpen = false
|
||||
local depotBoxOpen = false
|
||||
for _,tile in pairs(g_map.getTiles(posz())) do
|
||||
for i,thing in pairs(tile:getThings()) do
|
||||
if table.find(depotIDs, thing:getId()) then
|
||||
table.insert(tileList, {tileObj = tile, distance = getDistanceBetween(pos(), tile:getPosition()), depotID = thing:getId()})
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(tileList, function(a,b) return a.distance < b.distance end)
|
||||
::findEmptyDP::
|
||||
if tileList[i] and not storage.stopSearch then
|
||||
if tileList[i].depotID == 3498 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x + 1, y = tileList[i].tileObj:getPosition().y, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3499 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x, y = tileList[i].tileObj:getPosition().y + 1, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3500 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x - 1, y = tileList[i].tileObj:getPosition().y, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3497 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x, y = tileList[i].tileObj:getPosition().y - 1, z = tileList[i].tileObj:getPosition().z}
|
||||
end
|
||||
if tPos then
|
||||
local dest = g_map.getTile(tPos)
|
||||
if not comparePosition(pos(), dest:getPosition()) then
|
||||
if not dest:getCreatures()[1] and dest:isWalkable() then
|
||||
if CaveBot.walkTo(dest:getPosition(), {ignoreNonPathable=true}) then
|
||||
storage.stopSearch = true
|
||||
delay(100)
|
||||
end
|
||||
else
|
||||
i = i + 1
|
||||
goto findEmptyDP
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if tileList[i].tileObj and not table.find(depotIDs, tileList[i].tileObj:getTopLookThing():getId()) and comparePosition(pos(), tileList[i].tileObj:getPosition()) then
|
||||
for j=1,table.getn(tileList[i].tileObj:getThings()),1 do
|
||||
if not tileList[i].tileObj:getThings()[j]:isNotMoveable() then
|
||||
delay(500)
|
||||
g_game.move(tileList[i].tileObj:getThings()[j], pos(), tileList[i].tileObj:getThings()[j]:getCount())
|
||||
end
|
||||
end
|
||||
if table.find(depotIDs, tileList[i].tileObj:getTopLookThing():getId()) then
|
||||
depotClear = true
|
||||
end
|
||||
else
|
||||
depotClear = true
|
||||
end
|
||||
if depotClear then
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
if container:getName():lower() == "locker" then
|
||||
depotOpen = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if tileList[i].tileObj and depotClear and not depotOpen and not storage.lootContainerOpen then
|
||||
delay(500)
|
||||
g_game.use(tileList[i].tileObj:getTopUseThing())
|
||||
depotOpen = true
|
||||
end
|
||||
i = 1
|
||||
--Version Check to know what to do with the depot--
|
||||
if g_game.getClientVersion() > 910 then
|
||||
if depotOpen then
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
if container:getName():lower() == "depot chest" then
|
||||
depotBoxOpen = true
|
||||
end
|
||||
end
|
||||
if findItem(3502) and not depotBoxOpen then
|
||||
delay(500)
|
||||
g_game.use(findItem(3502))
|
||||
depotBoxOpen = true
|
||||
end
|
||||
end
|
||||
if depotBoxOpen and not storage.lootContainerOpen then
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
if container:getName():lower() == "depot chest" then
|
||||
for _, item in ipairs(container:getItems()) do
|
||||
if item:isContainer() and table.find({22797, 22798}, item:getId()) then
|
||||
g_game.open(findItem(depotContainers[indexDp]), container)
|
||||
delay(500)
|
||||
for _, cont in pairs(g_game.getContainers()) do
|
||||
if string.find(cont:getName():lower(), "depot box") then
|
||||
storage.lootContainerOpen = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i, container in pairs(g_game.getContainers()) do
|
||||
if string.find(container:getName():lower(), "depot box") then
|
||||
for j, item in ipairs(container:getItems()) do
|
||||
g_game.move(item, destContainer:getSlotPosition(destContainer:getItemsCount()), item:getCount())
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("dpwithdraw", "dpwithdraw", {
|
||||
value="1, shopping bag, 21411",
|
||||
title="Loot Withdraw",
|
||||
description="index Depot, destination container name and it's ID",
|
||||
})
|
||||
end
|
||||
|
||||
onPlayerPositionChange(function(newPos, oldPos)
|
||||
storage.lootContainerOpen = false
|
||||
storage.stopSearch = false
|
||||
end)
|
@@ -0,0 +1,27 @@
|
||||
CaveBot.Extensions.Depositer = {}
|
||||
|
||||
local ui
|
||||
|
||||
-- first function called, here you should setup your UI
|
||||
CaveBot.Extensions.Depositer.setup = function()
|
||||
--ui = UI.createWidget('Label')
|
||||
--ui:setText("Depositer UI")
|
||||
end
|
||||
|
||||
-- called when cavebot config changes, configData is a table but it can be nil
|
||||
CaveBot.Extensions.Depositer.onConfigChange = function(configName, isEnabled, configData)
|
||||
if not configData then return end
|
||||
|
||||
end
|
||||
|
||||
-- called when cavebot is saving config, should return table or nil
|
||||
CaveBot.Extensions.Depositer.onSave = function()
|
||||
return {}
|
||||
end
|
||||
|
||||
-- bellow add you custom functions
|
||||
-- this function can be used in cavebot function waypoint as: return Depositer.run(retries, prev)
|
||||
-- there are 2 useful parameters - retries (number) and prev (true/false), check actions.lua to learn more
|
||||
CaveBot.Extensions.Depositer.run = function(retries, prev)
|
||||
return true
|
||||
end
|
@@ -0,0 +1,376 @@
|
||||
CaveBot.Extensions.Depositor = {}
|
||||
|
||||
local depotIDs = {3497, 3498, 3499, 3500}
|
||||
local reset = function()
|
||||
storage.stopSearch = false
|
||||
storage.lootContainerOpen = false
|
||||
storage.containersClosed = false
|
||||
storage.containersReset = false
|
||||
storage.currentStack = 0
|
||||
storage.currentNonStack = nonStackMin
|
||||
storage.lastTry = nil
|
||||
storage.lootItemsCount = 0
|
||||
storage.depositDone = false
|
||||
end
|
||||
local i = 1
|
||||
|
||||
CaveBot.Extensions.Depositor.setup = function()
|
||||
CaveBot.registerAction("depositor", "#00FFFF", function(value, retries)
|
||||
if retries > 400 then
|
||||
print("CaveBot[Depositor]: Depositor actions limit reached, proceeding")
|
||||
reset()
|
||||
return true
|
||||
end
|
||||
|
||||
local name = storage["_configs"]["targetbot_configs"]["selected"]
|
||||
local file = configDir .. "/targetbot_configs/" .. name .. ".json"
|
||||
local data = g_resources.readFileContents(file)
|
||||
local lootList = Config.parse(data)['looting']['items']
|
||||
local lootContainers = Config.parse(data)['looting']['containers']
|
||||
local mainBp
|
||||
local stackBp
|
||||
local nonStackBp
|
||||
|
||||
local valueString = string.split(value, ",") -- if 3 then it's old tibia
|
||||
|
||||
-- if old tibia then setup backpacks
|
||||
if #valueString == 3 then
|
||||
mainBp = tonumber(valueString[1]:trim())
|
||||
stackBp = tonumber(valueString[2]:trim()) -- non-stack bp count
|
||||
nonStackBp = tonumber(valueString[3]:trim()) -- stack bp count
|
||||
|
||||
if not mainBp or not stackBp or not nonStackBp then
|
||||
warn("CaveBot[Depositor]: incorrect values! should be 3x ID of containers!")
|
||||
reset()
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- start with checking the containers
|
||||
local lootDestination = {}
|
||||
for _, container in pairs(lootContainers) do
|
||||
if not table.find(lootDestination, container['id']) then
|
||||
table.insert(lootDestination, container['id'])
|
||||
end
|
||||
end
|
||||
|
||||
-- pretty much every container action is needed only if you want to work with containers
|
||||
if (value:lower() == "yes" or #valueString == 3) and not storage.containersReset then
|
||||
|
||||
-- what is open and what's not
|
||||
local currentContainers = {}
|
||||
for i, container in pairs(getContainers()) do
|
||||
if not table.find(currentContainers, container:getContainerItem():getId()) then
|
||||
table.insert(currentContainers, container:getContainerItem():getId())
|
||||
end
|
||||
end
|
||||
|
||||
delay(500) -- slow down this function until containers reset
|
||||
if #lootDestination > 0 then
|
||||
-- first closing all that are opened
|
||||
if not storage.containersClosed then
|
||||
for i, container in pairs(getContainers()) do
|
||||
if table.find(lootDestination, container:getContainerItem():getId()) then
|
||||
g_game.close(container)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
storage.containersClosed = true
|
||||
end
|
||||
-- now reopen them
|
||||
if not storage.containersReset and storage.containersClosed then
|
||||
for i, container in pairs(getContainers()) do
|
||||
for j, item in pairs(container:getItems()) do
|
||||
if table.find(lootDestination, item:getId()) and not table.find(currentContainers, item:getId()) then
|
||||
g_game.open(item)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
storage.containersReset = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if storage.depositDone then
|
||||
reset()
|
||||
print("CaveBot[Depositor]: Deposit finished, proceeding")
|
||||
return true
|
||||
end
|
||||
|
||||
local tileList = {}
|
||||
local tPos
|
||||
local depotClear = false
|
||||
local depotOpen = false
|
||||
local depotBoxOpen = false
|
||||
for _,tile in pairs(g_map.getTiles(posz())) do
|
||||
for i,thing in pairs(tile:getThings()) do
|
||||
if table.find(depotIDs, thing:getId()) then
|
||||
table.insert(tileList, {tileObj = tile, distance = getDistanceBetween(pos(), tile:getPosition()), depotID = thing:getId()})
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(tileList, function(a,b) return a.distance < b.distance end)
|
||||
::findEmptyDP::
|
||||
if tileList[i] and not storage.stopSearch then
|
||||
if tileList[i].depotID == 3498 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x + 1, y = tileList[i].tileObj:getPosition().y, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3499 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x, y = tileList[i].tileObj:getPosition().y + 1, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3500 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x - 1, y = tileList[i].tileObj:getPosition().y, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3497 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x, y = tileList[i].tileObj:getPosition().y - 1, z = tileList[i].tileObj:getPosition().z}
|
||||
end
|
||||
if tPos then
|
||||
local dest = g_map.getTile(tPos)
|
||||
if not (getDistanceBetween(pos(), dest:getPosition()) <= 1) then
|
||||
if not dest:getCreatures()[1] and dest:isWalkable() then
|
||||
if CaveBot.walkTo(dest:getPosition(), {ignoreNonPathable=true}) then
|
||||
storage.stopSearch = true
|
||||
delay(100)
|
||||
end
|
||||
else
|
||||
i = i + 1
|
||||
goto findEmptyDP
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if tileList[i] and not table.find(depotIDs, tileList[i].tileObj:getTopLookThing():getId()) and (getDistanceBetween(pos(), tileList[i].tileObj:getPosition()) <= 1) then
|
||||
for j=1,table.getn(tileList[i].tileObj:getThings()),1 do
|
||||
if not tileList[i].tileObj:getThings()[j]:isNotMoveable() then
|
||||
delay(500)
|
||||
g_game.move(tileList[i].tileObj:getThings()[j], pos(), tileList[i].tileObj:getThings()[j]:getCount())
|
||||
end
|
||||
end
|
||||
if table.find(depotIDs, tileList[i].tileObj:getTopLookThing():getId()) then
|
||||
depotClear = true
|
||||
end
|
||||
else
|
||||
depotClear = true
|
||||
end
|
||||
if depotClear then
|
||||
for _, container in pairs(getContainers()) do
|
||||
if container:getName():lower() == "locker" then
|
||||
depotOpen = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if tileList[i] and depotClear and not depotOpen and not storage.lootContainerOpen then
|
||||
delay(500)
|
||||
g_game.use(tileList[i].tileObj:getTopUseThing())
|
||||
depotOpen = true
|
||||
end
|
||||
i = 1
|
||||
|
||||
-- finding depot
|
||||
if depotOpen then
|
||||
for _, container in pairs(getContainers()) do
|
||||
if container:getName():lower() == "depot chest" then
|
||||
depotBoxOpen = true
|
||||
end
|
||||
end
|
||||
if findItem(3502) and not depotBoxOpen then
|
||||
delay(500)
|
||||
g_game.use(findItem(3502))
|
||||
depotBoxOpen = true
|
||||
end
|
||||
end
|
||||
if depotBoxOpen and not storage.lootContainerOpen then
|
||||
for _, container in pairs(getContainers()) do
|
||||
if container:getName():lower() == "depot chest" then
|
||||
for _, item in ipairs(container:getItems()) do
|
||||
if #valueString ~= 3 then -- new depot
|
||||
if item:isContainer() and table.find({22797, 22798}, item:getId()) then
|
||||
delay(500)
|
||||
storage.lootContainerOpen = true
|
||||
break
|
||||
end
|
||||
else
|
||||
if item:isContainer() and item:getId() == mainBp then
|
||||
delay(500)
|
||||
g_game.use(item, container)
|
||||
storage.lootContainerOpen = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #valueString == 3 then
|
||||
delay(150)
|
||||
for _, container in pairs(getContainers()) do
|
||||
if container:getContainerItem():getId() == mainBp then
|
||||
storage.lootContainerOpen = true
|
||||
storage.isDepositing = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local looting = {}
|
||||
for _, lootItem in pairs(lootList) do
|
||||
if not table.find(looting, lootItem['id']) and not table.find({3031, 3035, 3043}, lootItem['id']) then
|
||||
table.insert(looting, lootItem['id'])
|
||||
end
|
||||
end
|
||||
delay(200)
|
||||
local currentItems = 0
|
||||
for _, container in pairs(getContainers()) do
|
||||
for _, item in ipairs(container:getItems()) do
|
||||
if table.find(looting, item:getId()) then
|
||||
currentItems = currentItems + item:getCount()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if currentItems == 0 then
|
||||
if value:lower() ~= "yes" and #valueString ~= 3 then
|
||||
storage.containersClosed = false
|
||||
storage.containersReset = false
|
||||
storage.depositDone = true
|
||||
return "retry"
|
||||
end
|
||||
|
||||
for i, container in pairs(getContainers()) do
|
||||
for j, item in pairs(container:getItems()) do
|
||||
if table.find(lootDestination, container:getContainerItem():getId()) and table.find(lootDestination, item:getId()) then
|
||||
g_game.open(item, container)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
storage.containersClosed = false
|
||||
storage.containersReset = false
|
||||
storage.depositDone = true
|
||||
return "retry"
|
||||
end
|
||||
|
||||
-- only if old depot
|
||||
local stackMin
|
||||
local stackMax
|
||||
local nonStackMin
|
||||
local nonStackMax
|
||||
if #valueString == 3 then
|
||||
-- backpacks setup
|
||||
local stack = 0
|
||||
local nonStack = 0
|
||||
for i, container in pairs(getContainers()) do
|
||||
if container:getContainerItem():getId() == mainBp then
|
||||
for i, item in pairs(container:getItems()) do
|
||||
if item:getId() == stackBp then
|
||||
stack = stack + 1
|
||||
elseif item:getId() == nonStackBp then
|
||||
nonStack = nonStack + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
stackMax = stack - 1
|
||||
nonStackMin = stack
|
||||
nonStackMax = (stack + nonStack) - 1
|
||||
|
||||
storage.currentStack = 0
|
||||
storage.currentNonStack = nonStackMin
|
||||
|
||||
if storage.lootItemsCount == currentItems then
|
||||
if storage.lastTry == 1 then
|
||||
if storage.currentStack < stackMax then
|
||||
storage.currentStack = storage.currentStack + 1
|
||||
else
|
||||
warn("CaveBot[Depositer]: Stack Backpack full! Proceeding.")
|
||||
reset()
|
||||
return true
|
||||
end
|
||||
elseif storage.lastTry == 2 then
|
||||
if storage.currentNonStack < nonStackMax then
|
||||
storage.currentNonStack = storage.currentNonStack + 1
|
||||
else
|
||||
warn("CaveBot[Depositer]: Non-Stack Backpack full! Proceeding.")
|
||||
reset()
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
storage.lootItemsCount = currentItems
|
||||
end
|
||||
|
||||
if #looting > 0 then
|
||||
if #valueString ~= 3 then -- version check, if value is set of 3 i
|
||||
for i, depotcontainer in pairs(getContainers()) do
|
||||
containerItemId = depotcontainer:getContainerItem():getId()
|
||||
--check if open depot
|
||||
if containerItemId == 3502 then
|
||||
-- check all containers and items
|
||||
for l, lootcontainer in pairs(getContainers()) do
|
||||
for j, item in ipairs(lootcontainer:getItems()) do
|
||||
-- now the criteria
|
||||
if table.find(looting, item:getId()) then
|
||||
-- move the item
|
||||
if item:isStackable() then
|
||||
g_game.move(item, depotcontainer:getSlotPosition(1), item:getCount())
|
||||
return "retry"
|
||||
else
|
||||
g_game.move(item, depotcontainer:getSlotPosition(0), item:getCount())
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else -- to be written, last part missing is stashing items for old depots
|
||||
for i, depotcontainer in pairs(getContainers()) do
|
||||
containerItemId = depotcontainer:getContainerItem():getId()
|
||||
--check if open depot
|
||||
if containerItemId == mainBp then
|
||||
-- check all containers and items
|
||||
for l, lootcontainer in pairs(getContainers()) do
|
||||
for j, item in ipairs(lootcontainer:getItems()) do
|
||||
-- now the criteria
|
||||
if table.find(looting, item:getId()) then
|
||||
-- move the item
|
||||
if item:isStackable() then
|
||||
g_game.move(item, depotcontainer:getSlotPosition(storage.currentStack), item:getCount())
|
||||
storage.lastTry = 1
|
||||
return "retry"
|
||||
else
|
||||
g_game.move(item, depotcontainer:getSlotPosition(storage.currentNonStack), item:getCount())
|
||||
storage.lastTry = 2
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
else
|
||||
warn("no items in looting list!")
|
||||
reset()
|
||||
return false
|
||||
end
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("depositor", "depositor", {
|
||||
value="no",
|
||||
title="Depositor",
|
||||
description="No - just deposit \n Yes - also reopen loot containers \n mainID, stackId, nonStackId - for older tibia",
|
||||
})
|
||||
end
|
||||
|
||||
onPlayerPositionChange(function(newPos, oldPos)
|
||||
if CaveBot.isOn() then
|
||||
reset()
|
||||
end
|
||||
end)
|
@@ -0,0 +1,47 @@
|
||||
CaveBot.Extensions.OpenDoors = {}
|
||||
|
||||
CaveBot.Extensions.OpenDoors.setup = function()
|
||||
CaveBot.registerAction("OpenDoors", "#00FFFF", function(value, retries)
|
||||
local pos = regexMatch(value, "\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)")
|
||||
if not pos[1] then
|
||||
error("CaveBot[OpenDoors]: invalid value. It should be position (x,y,z), is: " .. value)
|
||||
return false
|
||||
end
|
||||
|
||||
if retries >= 5 then
|
||||
print("CaveBot[OpenDoors]: too many tries, can't open doors")
|
||||
return false -- tried 5 times, can't open
|
||||
end
|
||||
|
||||
pos = {x=tonumber(pos[1][2]), y=tonumber(pos[1][3]), z=tonumber(pos[1][4])}
|
||||
|
||||
local doorTile
|
||||
if not doorTile then
|
||||
for i, tile in ipairs(g_map.getTiles(posz())) do
|
||||
if tile:getPosition().x == pos.x and tile:getPosition().y == pos.y and tile:getPosition().z == pos.z then
|
||||
doorTile = tile
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not doorTile then
|
||||
return false
|
||||
end
|
||||
|
||||
if not doorTile:isWalkable() then
|
||||
use(doorTile:getTopUseThing())
|
||||
return "retry"
|
||||
else
|
||||
print("CaveBot[OpenDoors]: possible to cross, proceeding")
|
||||
return true
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("opendoors", "open doors", {
|
||||
value=function() return posx() .. "," .. posy() .. "," .. posz() end,
|
||||
title="Door position",
|
||||
description="doors position (x,y,z)",
|
||||
multiline=false,
|
||||
validation="^\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)$"
|
||||
})
|
||||
end
|
174
modules/game_bot/default_configs/vithrax_1.3/cavebot/editor.lua
Normal file
174
modules/game_bot/default_configs/vithrax_1.3/cavebot/editor.lua
Normal file
@@ -0,0 +1,174 @@
|
||||
CaveBot.Editor = {}
|
||||
CaveBot.Editor.Actions = {}
|
||||
|
||||
-- also works as registerAction(action, params), then text == action
|
||||
-- params are options for text editor or function to be executed when clicked
|
||||
-- you have many examples how to use it bellow
|
||||
CaveBot.Editor.registerAction = function(action, text, params)
|
||||
if type(text) ~= 'string' then
|
||||
params = text
|
||||
text = action
|
||||
end
|
||||
|
||||
local color = nil
|
||||
if type(params) ~= 'function' then
|
||||
local raction = CaveBot.Actions[action]
|
||||
if not raction then
|
||||
return error("CaveBot editor error: action " .. action .. " doesn't exist")
|
||||
end
|
||||
CaveBot.Editor.Actions[action] = params
|
||||
color = raction.color
|
||||
end
|
||||
|
||||
local button = UI.createWidget('CaveBotEditorButton', CaveBot.Editor.ui.buttons)
|
||||
button:setText(text)
|
||||
if color then
|
||||
button:setColor(color)
|
||||
end
|
||||
button.onClick = function()
|
||||
if type(params) == 'function' then
|
||||
params()
|
||||
return
|
||||
end
|
||||
CaveBot.Editor.edit(action, nil, function(action, value)
|
||||
local focusedAction = CaveBot.actionList:getFocusedChild()
|
||||
local index = CaveBot.actionList:getChildCount()
|
||||
if focusedAction then
|
||||
index = CaveBot.actionList:getChildIndex(focusedAction)
|
||||
end
|
||||
local widget = CaveBot.addAction(action, value)
|
||||
CaveBot.actionList:moveChildToIndex(widget, index + 1)
|
||||
CaveBot.actionList:focusChild(widget)
|
||||
CaveBot.save()
|
||||
end)
|
||||
end
|
||||
return button
|
||||
end
|
||||
|
||||
CaveBot.Editor.setup = function()
|
||||
CaveBot.Editor.ui = UI.createWidget("CaveBotEditorPanel")
|
||||
local ui = CaveBot.Editor.ui
|
||||
local registerAction = CaveBot.Editor.registerAction
|
||||
|
||||
registerAction("move up", function()
|
||||
local action = CaveBot.actionList:getFocusedChild()
|
||||
if not action then return end
|
||||
local index = CaveBot.actionList:getChildIndex(action)
|
||||
if index < 2 then return end
|
||||
CaveBot.actionList:moveChildToIndex(action, index - 1)
|
||||
CaveBot.actionList:ensureChildVisible(action)
|
||||
CaveBot.save()
|
||||
end)
|
||||
registerAction("edit", function()
|
||||
local action = CaveBot.actionList:getFocusedChild()
|
||||
if not action or not action.onDoubleClick then return end
|
||||
action.onDoubleClick(action)
|
||||
end)
|
||||
registerAction("move down", function()
|
||||
local action = CaveBot.actionList:getFocusedChild()
|
||||
if not action then return end
|
||||
local index = CaveBot.actionList:getChildIndex(action)
|
||||
if index >= CaveBot.actionList:getChildCount() then return end
|
||||
CaveBot.actionList:moveChildToIndex(action, index + 1)
|
||||
CaveBot.actionList:ensureChildVisible(action)
|
||||
CaveBot.save()
|
||||
end)
|
||||
registerAction("remove", function()
|
||||
local action = CaveBot.actionList:getFocusedChild()
|
||||
if not action then return end
|
||||
action:destroy()
|
||||
CaveBot.save()
|
||||
end)
|
||||
|
||||
registerAction("label", {
|
||||
value="labelName",
|
||||
title="Label",
|
||||
description="Add label",
|
||||
multiline=false
|
||||
})
|
||||
registerAction("delay", {
|
||||
value="500",
|
||||
title="Delay",
|
||||
description="Delay next action (in milliseconds)",
|
||||
multiline=false,
|
||||
validation="^\\s*[0-9]{1,10}\\s*$"
|
||||
})
|
||||
registerAction("gotolabel", "go to label", {
|
||||
value="labelName",
|
||||
title="Go to label",
|
||||
description="Go to label",
|
||||
multiline=false
|
||||
})
|
||||
registerAction("goto", "go to", {
|
||||
value=function() return posx() .. "," .. posy() .. "," .. posz() end,
|
||||
title="Go to position",
|
||||
description="Go to position (x,y,z)",
|
||||
multiline=false,
|
||||
validation="^\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+),?\\s*([0-9]?)$"
|
||||
})
|
||||
registerAction("use", {
|
||||
value=function() return posx() .. "," .. posy() .. "," .. posz() end,
|
||||
title="Use",
|
||||
description="Use item from position (x,y,z) or from inventory (itemId)",
|
||||
multiline=false
|
||||
})
|
||||
registerAction("usewith", "use with", {
|
||||
value=function() return "itemId," .. posx() .. "," .. posy() .. "," .. posz() end,
|
||||
title="Use with",
|
||||
description="Use item at position (itemid,x,y,z)",
|
||||
multiline=false,
|
||||
validation="^\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)$"
|
||||
})
|
||||
registerAction("say", {
|
||||
value="text",
|
||||
title="Say",
|
||||
description="Enter text to say",
|
||||
multiline=false
|
||||
})
|
||||
registerAction("function", {
|
||||
title="Edit bot function",
|
||||
multiline=true,
|
||||
value=CaveBot.Editor.ExampleFunctions[1][2],
|
||||
examples=CaveBot.Editor.ExampleFunctions,
|
||||
width=650
|
||||
})
|
||||
|
||||
ui.autoRecording.onClick = function()
|
||||
if ui.autoRecording:isOn() then
|
||||
CaveBot.Recorder.disable()
|
||||
else
|
||||
CaveBot.Recorder.enable()
|
||||
end
|
||||
end
|
||||
|
||||
-- callbacks
|
||||
onPlayerPositionChange(function(pos)
|
||||
ui.pos:setText("Position: " .. pos.x .. ", " .. pos.y .. ", " .. pos.z)
|
||||
end)
|
||||
ui.pos:setText("Position: " .. posx() .. ", " .. posy() .. ", " .. posz())
|
||||
end
|
||||
|
||||
CaveBot.Editor.show = function()
|
||||
CaveBot.Editor.ui:show()
|
||||
end
|
||||
|
||||
|
||||
CaveBot.Editor.hide = function()
|
||||
CaveBot.Editor.ui:hide()
|
||||
end
|
||||
|
||||
CaveBot.Editor.edit = function(action, value, callback) -- callback = function(action, value)
|
||||
local params = CaveBot.Editor.Actions[action]
|
||||
if not params then return end
|
||||
if not value then
|
||||
if type(params.value) == 'function' then
|
||||
value = params.value()
|
||||
elseif type(params.value) == 'string' then
|
||||
value = params.value
|
||||
end
|
||||
end
|
||||
|
||||
UI.EditorWindow(value, params, function(newText)
|
||||
callback(action, newText)
|
||||
end)
|
||||
end
|
@@ -0,0 +1,44 @@
|
||||
CaveBotEditorButton < Button
|
||||
|
||||
|
||||
CaveBotEditorPanel < Panel
|
||||
id: cavebotEditor
|
||||
visible: false
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
Label
|
||||
id: pos
|
||||
text-align: center
|
||||
text: -
|
||||
|
||||
Panel
|
||||
id: buttons
|
||||
margin-top: 2
|
||||
layout:
|
||||
type: grid
|
||||
cell-size: 86 20
|
||||
cell-spacing: 1
|
||||
flow: true
|
||||
fit-children: true
|
||||
|
||||
Label
|
||||
text: Double click on action from action list to edit it
|
||||
text-align: center
|
||||
text-auto-resize: true
|
||||
text-wrap: true
|
||||
margin-top: 3
|
||||
margin-left: 2
|
||||
margin-right: 2
|
||||
|
||||
BotSwitch
|
||||
id: autoRecording
|
||||
text: Auto Recording
|
||||
margin-top: 3
|
||||
|
||||
BotButton
|
||||
margin-top: 3
|
||||
margin-bottom: 3
|
||||
text: Documentation
|
||||
@onClick: g_platform.openUrl("http://bot.otclient.ovh/")
|
@@ -0,0 +1,94 @@
|
||||
CaveBot.Editor.ExampleFunctions = {}
|
||||
|
||||
local function addExampleFunction(title, text)
|
||||
return table.insert(CaveBot.Editor.ExampleFunctions, {title, text:trim()})
|
||||
end
|
||||
|
||||
addExampleFunction("Click to browse example functions", [[
|
||||
-- available functions/variables:
|
||||
-- prev - result of previous action (true or false)
|
||||
-- retries - number of retries of current function, goes up by one when you return "retry"
|
||||
-- delay(number) - delays bot next action, value in milliseconds
|
||||
-- gotoLabel(string) - goes to specific label, return true if label exists
|
||||
-- you can easily access bot extensions, Depositer.run() instead of CaveBot.Extensions.Depositer.run()
|
||||
-- also you can access bot global variables, like CaveBot, TargetBot
|
||||
-- use storage variable to store date between calls
|
||||
|
||||
-- function should return false, true or "retry"
|
||||
-- if "retry" is returned, function will be executed again in 20 ms (so better call delay before)
|
||||
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Check for stamina and imbues", [[
|
||||
if stamina() < 900 or player:getSkillLevel(11) ~= 100 then CaveBot.setOff() return false else return true end
|
||||
]])
|
||||
|
||||
addExampleFunction("buy 200 mana potion from npc Eryn", [[
|
||||
--buy 200 mana potions
|
||||
local npc = getCreatureByName("Eryn")
|
||||
if not npc then
|
||||
return false
|
||||
end
|
||||
if retries > 10 then
|
||||
return false
|
||||
end
|
||||
local pos = player:getPosition()
|
||||
local npcPos = npc:getPosition()
|
||||
if math.max(math.abs(pos.x - npcPos.x), math.abs(pos.y - npcPos.y)) > 3 then
|
||||
autoWalk(npcPos, {precision=3})
|
||||
delay(300)
|
||||
return "retry"
|
||||
end
|
||||
if not NPC.isTrading() then
|
||||
NPC.say("hi")
|
||||
NPC.say("trade")
|
||||
delay(200)
|
||||
return "retry"
|
||||
end
|
||||
NPC.buy(268, 100)
|
||||
schedule(1000, function()
|
||||
-- buy again in 1s
|
||||
NPC.buy(268, 100)
|
||||
NPC.closeTrade()
|
||||
NPC.say("bye")
|
||||
end)
|
||||
delay(1200)
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Say hello 5 times with some delay", [[
|
||||
--say hello
|
||||
if retries > 5 then
|
||||
return true -- finish
|
||||
end
|
||||
say("hello")
|
||||
delay(100 + retries * 100)
|
||||
return "retry"
|
||||
]])
|
||||
|
||||
addExampleFunction("Disable TargetBot", [[
|
||||
TargetBot.setOff()
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Enable TargetBot", [[
|
||||
TargetBot.setOn()
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Enable TargetBot luring", [[
|
||||
TargetBot.enableLuring()
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Disable TargetBot luring", [[
|
||||
TargetBot.disableLuring()
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Logout", [[
|
||||
g_game.safeLogout()
|
||||
delay(1000)
|
||||
return "retry"
|
||||
]])
|
@@ -0,0 +1,58 @@
|
||||
-- example cavebot extension (remember to add this file to ../cavebot.lua)
|
||||
CaveBot.Extensions.Example = {}
|
||||
|
||||
local ui
|
||||
|
||||
-- setup is called automaticly when cavebot is ready
|
||||
CaveBot.Extensions.Example.setup = function()
|
||||
ui = UI.createWidget('BotTextEdit')
|
||||
ui:setText("Hello")
|
||||
ui.onTextChange = function()
|
||||
CaveBot.save() -- save new config when you change something
|
||||
end
|
||||
|
||||
-- add custom cavebot action (check out actions.lua)
|
||||
CaveBot.registerAction("sayhello", "orange", function(value, retries, prev)
|
||||
local how_many_times = tonumber(value)
|
||||
if retries >= how_many_times then
|
||||
return true
|
||||
end
|
||||
say("hello " .. (retries + 1))
|
||||
delay(250)
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
-- add this custom action to editor (check out editor.lua)
|
||||
CaveBot.Editor.registerAction("sayhello", "say hello", {
|
||||
value="5",
|
||||
title="Say hello",
|
||||
description="Says hello x times",
|
||||
validation="[0-9]{1,5}" -- regex, optional
|
||||
})
|
||||
end
|
||||
|
||||
-- called when cavebot config changes, configData is a table but it can also be nil
|
||||
CaveBot.Extensions.Example.onConfigChange = function(configName, isEnabled, configData)
|
||||
if not configData then return end
|
||||
if configData["text"] then
|
||||
ui:setText(configData["text"])
|
||||
end
|
||||
end
|
||||
|
||||
-- called when cavebot is saving config (so when CaveBot.save() is called), should return table or nil
|
||||
CaveBot.Extensions.Example.onSave = function()
|
||||
return {text=ui:getText()}
|
||||
end
|
||||
|
||||
-- bellow add you custom functions to be used in cavebot function action
|
||||
-- an example: return Example.run(retries, prev)
|
||||
-- there are 2 useful parameters - retries (number) and prev (true/false), check actions.lua and example_functions.lua to learn more
|
||||
CaveBot.Extensions.Example.run = function(retries, prev)
|
||||
-- it will say text 10 times with some delay and then continue
|
||||
if retries > 10 then
|
||||
return true
|
||||
end
|
||||
say(ui:getText() .. " x" .. retries)
|
||||
delay(100 + retries * 100)
|
||||
return "retry"
|
||||
end
|
@@ -0,0 +1,184 @@
|
||||
CaveBot.Extensions.InWithdraw = {}
|
||||
|
||||
comparePosition = function(pPos, tPos)
|
||||
return (getDistanceBetween(pPos, tPos) <= 1)
|
||||
end
|
||||
|
||||
local depotIDs = {3497, 3498, 3499, 3500}
|
||||
storage.stopSearch = false
|
||||
storage.inboxContainerOpen = false
|
||||
local i = 1
|
||||
|
||||
|
||||
CaveBot.Extensions.InWithdraw.setup = function()
|
||||
CaveBot.registerAction("inwithdraw", "#00FFFF", function(value, retries)
|
||||
local data = string.split(value, ",")
|
||||
local withdrawId
|
||||
local count
|
||||
local itemCount = 0
|
||||
local depotAmount = 0
|
||||
if #data ~= 2 then
|
||||
error("CaveBot[InboxWithdraw]: incorrect withdraw value")
|
||||
return false
|
||||
else
|
||||
withdrawId = tonumber(data[1])
|
||||
count = tonumber(data[2])
|
||||
end
|
||||
|
||||
for i, container in pairs(getContainers()) do
|
||||
if not string.find(container:getName():lower(), "inbox") then
|
||||
for j, item in pairs(container:getItems()) do
|
||||
if item:getId() == withdrawId then
|
||||
itemCount = itemCount + item:getCount()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if itemCount >= count then
|
||||
for i, container in pairs(getContainers()) do
|
||||
if string.find(container:getName():lower(), "your inbox") then
|
||||
g_game.close(container)
|
||||
end
|
||||
end
|
||||
print("CaveBot[InboxWithdraw]: enough items, proceeding")
|
||||
return true
|
||||
end
|
||||
|
||||
if retries > 400 then
|
||||
print("CaveBot[InboxWithdraw]: actions limit reached, proceeding")
|
||||
return true
|
||||
end
|
||||
|
||||
delay(200)
|
||||
local tileList = {}
|
||||
local tPos
|
||||
local depotClear = false
|
||||
local depotOpen = false
|
||||
local depotBoxOpen = false
|
||||
for _,tile in pairs(g_map.getTiles(posz())) do
|
||||
for i,thing in pairs(tile:getThings()) do
|
||||
if table.find(depotIDs, thing:getId()) then
|
||||
table.insert(tileList, {tileObj = tile, distance = getDistanceBetween(pos(), tile:getPosition()), depotID = thing:getId()})
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(tileList, function(a,b) return a.distance < b.distance end)
|
||||
::findEmptyDP::
|
||||
if tileList[i] and not storage.stopSearch then
|
||||
if tileList[i].depotID == 3498 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x + 1, y = tileList[i].tileObj:getPosition().y, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3499 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x, y = tileList[i].tileObj:getPosition().y + 1, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3500 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x - 1, y = tileList[i].tileObj:getPosition().y, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3497 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x, y = tileList[i].tileObj:getPosition().y - 1, z = tileList[i].tileObj:getPosition().z}
|
||||
end
|
||||
if tPos then
|
||||
local dest = g_map.getTile(tPos)
|
||||
if not comparePosition(pos(), dest:getPosition()) then
|
||||
if not dest:getCreatures()[1] and dest:isWalkable() then
|
||||
if CaveBot.walkTo(dest:getPosition(), {ignoreNonPathable=true}) then
|
||||
storage.stopSearch = true
|
||||
delay(100)
|
||||
end
|
||||
else
|
||||
i = i + 1
|
||||
goto findEmptyDP
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if tileList[i].tileObj and not table.find(depotIDs, tileList[i].tileObj:getTopLookThing():getId()) and comparePosition(pos(), tileList[i].tileObj:getPosition()) then
|
||||
for j=1,table.getn(tileList[i].tileObj:getThings()),1 do
|
||||
if not tileList[i].tileObj:getThings()[j]:isNotMoveable() then
|
||||
delay(500)
|
||||
g_game.move(tileList[i].tileObj:getThings()[j], pos(), tileList[i].tileObj:getThings()[j]:getCount())
|
||||
end
|
||||
end
|
||||
if table.find(depotIDs, tileList[i].tileObj:getTopLookThing():getId()) then
|
||||
depotClear = true
|
||||
end
|
||||
else
|
||||
depotClear = true
|
||||
end
|
||||
if depotClear then
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
if container:getName():lower() == "locker" then
|
||||
depotOpen = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if tileList[i].tileObj and depotClear and not depotOpen and not storage.inboxContainerOpen then
|
||||
delay(500)
|
||||
g_game.use(tileList[i].tileObj:getTopUseThing())
|
||||
depotOpen = true
|
||||
end
|
||||
i = 1
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
if container:getName():lower() == "your inbox" then
|
||||
depotBoxOpen = true
|
||||
end
|
||||
end
|
||||
if depotOpen and not depotBoxOpen then
|
||||
if findItem(12902) then
|
||||
delay(500)
|
||||
g_game.use(findItem(12902))
|
||||
depotBoxOpen = true
|
||||
end
|
||||
end
|
||||
|
||||
if depotBoxOpen and not storage.inboxContainerOpen then
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
if container:getName():lower() == "your" then
|
||||
storage.inboxContainerOpen = true
|
||||
end
|
||||
end
|
||||
end
|
||||
delay(500)
|
||||
for i, container in pairs(getContainers()) do
|
||||
if string.find(container:getName():lower(), "your") then
|
||||
for j, item in pairs(container:getItems()) do
|
||||
if item:getId() == withdrawId then
|
||||
depotAmount = depotAmount + item:getCount()
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local destination
|
||||
for i, container in pairs(getContainers()) do
|
||||
if container:getCapacity() > #container:getItems() and not string.find(container:getName():lower(), "depot") and not string.find(container:getName():lower(), "loot") and not string.find(container:getName():lower(), "inbox") then
|
||||
destination = container
|
||||
end
|
||||
end
|
||||
|
||||
if itemCount < count and destination then
|
||||
for i, container in pairs(getContainers()) do
|
||||
if string.find(container:getName():lower(), "your inbox") then
|
||||
for j, item in pairs(container:getItems()) do
|
||||
if item:getId() == withdrawId then
|
||||
if item:isStackable() then
|
||||
g_game.move(item, destination:getSlotPosition(destination:getItemsCount()), math.min(item:getCount(), (count - itemCount)))
|
||||
return "retry"
|
||||
else
|
||||
g_game.move(item, destination:getSlotPosition(destination:getItemsCount()), 1)
|
||||
return "retry"
|
||||
end
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("inwithdraw", "in withdraw", {
|
||||
value="id,amount",
|
||||
title="Withdraw Items",
|
||||
description="insert item id and amount",
|
||||
})
|
||||
end
|
@@ -0,0 +1,23 @@
|
||||
CaveBot.Extensions.Lure = {}
|
||||
|
||||
CaveBot.Extensions.Lure.setup = function()
|
||||
CaveBot.registerAction("lure", "#00FFFF", function(value, retries)
|
||||
if value == "start" then
|
||||
TargetBot.setOff()
|
||||
return true
|
||||
elseif value == "stop" then
|
||||
TargetBot.setOn()
|
||||
return true
|
||||
else
|
||||
warn("incorrect lure value!")
|
||||
return false
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("lure", "lure", {
|
||||
value="start",
|
||||
title="Lure",
|
||||
description="start/stop",
|
||||
multiline=false,
|
||||
})
|
||||
end
|
@@ -0,0 +1,44 @@
|
||||
CaveBot.Extensions.PosCheck = {}
|
||||
|
||||
|
||||
storage.posCheckRetries = 0
|
||||
CaveBot.Extensions.PosCheck.setup = function()
|
||||
CaveBot.registerAction("PosCheck", "#00FFFF", function(value, retries)
|
||||
local tilePos
|
||||
local data = string.split(value, ",")
|
||||
if #data ~= 5 then
|
||||
error("wrong travel format, should be: label, distance, x, y, z")
|
||||
return false
|
||||
end
|
||||
|
||||
local tilePos = player:getPosition()
|
||||
|
||||
tilePos.x = tonumber(data[3])
|
||||
tilePos.y = tonumber(data[4])
|
||||
tilePos.z = tonumber(data[5])
|
||||
|
||||
if storage.posCheckRetries > 10 then
|
||||
storage.posCheckRetries = 0
|
||||
print("CaveBot[CheckPos]: waypoints locked, too many tries, unclogging cavebot and proceeding")
|
||||
return false
|
||||
elseif (tilePos.z == player:getPosition().z) and (getDistanceBetween(player:getPosition(), tilePos) <= tonumber(data[2])) then
|
||||
storage.posCheckRetries = 0
|
||||
print("CaveBot[CheckPos]: position reached, proceeding")
|
||||
return true
|
||||
else
|
||||
storage.posCheckRetries = storage.posCheckRetries + 1
|
||||
CaveBot.gotoLabel(data[1])
|
||||
print("CaveBot[CheckPos]: position not-reached, going back to label: " .. data[1])
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("poscheck", "pos check", {
|
||||
value=function() return "label" .. "," .. "distance" .. "," .. posx() .. "," .. posy() .. "," .. posz() end,
|
||||
title="Location Check",
|
||||
description="label name, accepted dist from coordinates, x, y, z",
|
||||
multiline=false,
|
||||
})
|
||||
end
|
@@ -0,0 +1,65 @@
|
||||
-- auto recording for cavebot
|
||||
CaveBot.Recorder = {}
|
||||
|
||||
local isEnabled = nil
|
||||
local lastPos = nil
|
||||
|
||||
local function setup()
|
||||
local function addPosition(pos)
|
||||
CaveBot.addAction("goto", pos.x .. "," .. pos.y .. "," .. pos.z, true)
|
||||
lastPos = pos
|
||||
end
|
||||
|
||||
onPlayerPositionChange(function(newPos, oldPos)
|
||||
if CaveBot.isOn() or not isEnabled then return end
|
||||
if not lastPos then
|
||||
-- first step
|
||||
addPosition(oldPos)
|
||||
elseif newPos.z ~= oldPos.z or math.abs(oldPos.x - newPos.x) > 1 or math.abs(oldPos.y - newPos.y) > 1 then
|
||||
-- stairs/teleport
|
||||
addPosition(oldPos)
|
||||
elseif math.max(math.abs(lastPos.x - newPos.x), math.abs(lastPos.y - newPos.y)) > 5 then
|
||||
-- 5 steps from last pos
|
||||
addPosition(newPos)
|
||||
end
|
||||
end)
|
||||
|
||||
onUse(function(pos, itemId, stackPos, subType)
|
||||
if CaveBot.isOn() or not isEnabled then return end
|
||||
if pos.x ~= 0xFFFF then
|
||||
lastPos = pos
|
||||
CaveBot.addAction("use", pos.x .. "," .. pos.y .. "," .. pos.z, true)
|
||||
end
|
||||
end)
|
||||
|
||||
onUseWith(function(pos, itemId, target, subType)
|
||||
if CaveBot.isOn() or not isEnabled then return end
|
||||
if not target:isItem() then return end
|
||||
local targetPos = target:getPosition()
|
||||
if targetPos.x == 0xFFFF then return end
|
||||
lastPos = pos
|
||||
CaveBot.addAction("usewith", itemId .. "," .. targetPos.x .. "," .. targetPos.y .. "," .. targetPos.z, true)
|
||||
end)
|
||||
end
|
||||
|
||||
CaveBot.Recorder.isOn = function()
|
||||
return isEnabled
|
||||
end
|
||||
|
||||
CaveBot.Recorder.enable = function()
|
||||
CaveBot.setOff()
|
||||
if isEnabled == nil then
|
||||
setup()
|
||||
end
|
||||
CaveBot.Editor.ui.autoRecording:setOn(true)
|
||||
isEnabled = true
|
||||
lastPos = nil
|
||||
end
|
||||
|
||||
CaveBot.Recorder.disable = function()
|
||||
if isEnabled == true then
|
||||
isEnabled = false
|
||||
end
|
||||
CaveBot.Editor.ui.autoRecording:setOn(false)
|
||||
CaveBot.save()
|
||||
end
|
@@ -0,0 +1,68 @@
|
||||
CaveBot.Extensions.SellAll = {}
|
||||
|
||||
storage.sellAllCap = 0
|
||||
CaveBot.Extensions.SellAll.setup = function()
|
||||
CaveBot.registerAction("SellAll", "#00FFFF", function(value, retries)
|
||||
local val = string.split(value, ",")
|
||||
local wait
|
||||
if #val > 2 then
|
||||
warn("CaveBot[SellAll]: incorrect sell all value!")
|
||||
return false
|
||||
end
|
||||
|
||||
if #val == 2 then
|
||||
wait = true
|
||||
else
|
||||
wait = false
|
||||
end
|
||||
|
||||
local npc = getCreatureByName(value)
|
||||
if not npc then
|
||||
print("CaveBot[SellAll]: NPC not found! skipping")
|
||||
return false
|
||||
end
|
||||
|
||||
if retries > 10 then
|
||||
print("CaveBot[SellAll]: can't sell, skipping")
|
||||
return false
|
||||
end
|
||||
|
||||
if freecap() == storage.sellAllCap then
|
||||
storage.sellAllCap = 0
|
||||
print("CaveBot[SellAll]: Sold everything, proceeding")
|
||||
return true
|
||||
end
|
||||
|
||||
delay(800)
|
||||
|
||||
local pos = player:getPosition()
|
||||
local npcPos = npc:getPosition()
|
||||
if math.max(math.abs(pos.x - npcPos.x), math.abs(pos.y - npcPos.y)) > 3 then
|
||||
CaveBot.walkTo(npcPos, 20, {ignoreNonPathable = true, precision=3})
|
||||
delay(300)
|
||||
return "retry"
|
||||
end
|
||||
|
||||
if not NPC.isTrading() then
|
||||
NPC.say("hi")
|
||||
schedule(500, function() NPC.say("trade") end)
|
||||
else
|
||||
storage.sellAllCap = freecap()
|
||||
end
|
||||
|
||||
NPC.sellAll(wait)
|
||||
if #val == 2 then
|
||||
print("CaveBot[SellAll]: Sold All with delay")
|
||||
else
|
||||
print("CaveBot[SellAll]: Sold All without delay")
|
||||
end
|
||||
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("sellall", "sell all", {
|
||||
value="NPC",
|
||||
title="Sell All",
|
||||
description="Insert NPC name, and 'yes' if sell with delay ",
|
||||
})
|
||||
end
|
@@ -0,0 +1,30 @@
|
||||
CaveBot.Extensions.Supply = {}
|
||||
|
||||
local ui
|
||||
|
||||
-- first function called, here you should setup your UI
|
||||
CaveBot.Extensions.Supply.setup = function()
|
||||
--ui = UI.createWidget('SupplyItemList')
|
||||
--local widget = UI.createWidget('SupplyItem', ui.list)
|
||||
--widget.item.onItemChange = function(newItem)
|
||||
--widget.fields.min.onTextChange = function(newText)
|
||||
-- make it similar to UI.Container, so if there are no free slots, add another one, keep min 4 slots, check if value min/max is number after edit
|
||||
end
|
||||
|
||||
-- called when cavebot config changes, configData is a table but it can be nil
|
||||
CaveBot.Extensions.Supply.onConfigChange = function(configName, isEnabled, configData)
|
||||
if not configData then return end
|
||||
|
||||
end
|
||||
|
||||
-- called when cavebot is saving config, should return table or nil
|
||||
CaveBot.Extensions.Supply.onSave = function()
|
||||
return {}
|
||||
end
|
||||
|
||||
-- bellow add you custom functions
|
||||
-- this function can be used in cavebot function waypoint as: return Supply.run(retries, prev)
|
||||
-- there are 2 useful parameters - retries (number) and prev (true/false), check actions.lua to learn more
|
||||
CaveBot.Extensions.Supply.run = function(retries, prev)
|
||||
return true
|
||||
end
|
@@ -0,0 +1,72 @@
|
||||
SupplyItem < Panel
|
||||
height: 34
|
||||
|
||||
BotItem
|
||||
id: item
|
||||
size: 32 32
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
margin-top: 1
|
||||
|
||||
Panel
|
||||
id: fields
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 2
|
||||
margin-right: 2
|
||||
|
||||
Label
|
||||
id: minLabel
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
margin-right: 2
|
||||
text-align: center
|
||||
text: "Min"
|
||||
|
||||
Label
|
||||
id: maxLabel
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
margin-left: 2
|
||||
text-align: center
|
||||
text: "Max"
|
||||
|
||||
BotTextEdit
|
||||
id: min
|
||||
anchors.top: minLabel.bottom
|
||||
anchors.left: minLabel.left
|
||||
anchors.right: minLabel.right
|
||||
text-align: center
|
||||
text: 1
|
||||
|
||||
BotTextEdit
|
||||
id: max
|
||||
anchors.top: maxLabel.bottom
|
||||
anchors.left: maxLabel.left
|
||||
anchors.right: maxLabel.right
|
||||
text-align: center
|
||||
text: 100
|
||||
|
||||
SupplyItemList < Panel
|
||||
height: 102
|
||||
|
||||
ScrollablePanel
|
||||
id: list
|
||||
anchors.fill: parent
|
||||
vertical-scrollbar: scroll
|
||||
margin-right: 7
|
||||
layout:
|
||||
type: verticalBox
|
||||
cell-height: 34
|
||||
|
||||
BotSmallScrollBar
|
||||
id: scroll
|
||||
anchors.top: prev.top
|
||||
anchors.bottom: prev.bottom
|
||||
anchors.right: parent.right
|
||||
step: 10
|
||||
pixels-scroll: true
|
@@ -0,0 +1,70 @@
|
||||
CaveBot.Extensions.SupplyCheck = {}
|
||||
|
||||
storage.supplyRetries = 0
|
||||
CaveBot.Extensions.SupplyCheck.setup = function()
|
||||
CaveBot.registerAction("supplyCheck", "#00FFFF", function(value)
|
||||
local softCount = itemAmount(6529) + itemAmount(3549)
|
||||
local totalItem1 = itemAmount(storage[suppliesPanelName].item1)
|
||||
local totalItem2 = itemAmount(storage[suppliesPanelName].item2)
|
||||
local totalItem3 = itemAmount(storage[suppliesPanelName].item3)
|
||||
local totalItem4 = itemAmount(storage[suppliesPanelName].item4)
|
||||
local totalItem5 = itemAmount(storage[suppliesPanelName].item5)
|
||||
local totalItem6 = itemAmount(storage[suppliesPanelName].item6)
|
||||
|
||||
if storage.supplyRetries > 50 then
|
||||
print("CaveBot[SupplyCheck]: Round limit reached, going back on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return false
|
||||
elseif (storage[suppliesPanelName].imbues and player:getSkillLevel(11) ~= 100) then
|
||||
print("CaveBot[SupplyCheck]: Imbues ran out. Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return false
|
||||
elseif (storage[suppliesPanelName].staminaSwitch and stamina() < tonumber(storage[suppliesPanelName].staminaValue)) then
|
||||
print("CaveBot[SupplyCheck]: Stamina ran out. Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return false
|
||||
elseif (softCount < 1 and storage[suppliesPanelName].SoftBoots) then
|
||||
print("CaveBot[SupplyCheck]: No soft boots left. Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return false
|
||||
elseif (totalItem1 < tonumber(storage[suppliesPanelName].item1Min) and storage[suppliesPanelName].item1 > 100) then
|
||||
print("CaveBot[SupplyCheck]: Not enough item: " .. storage[suppliesPanelName].item1 .. "(only " .. totalItem1 .. " left). Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return false
|
||||
elseif (totalItem2 < tonumber(storage[suppliesPanelName].item2Min) and storage[suppliesPanelName].item2 > 100) then
|
||||
print("CaveBot[SupplyCheck]: Not enough item: " .. storage[suppliesPanelName].item2 .. "(only " .. totalItem2 .. " left). Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return false
|
||||
elseif (totalItem3 < tonumber(storage[suppliesPanelName].item3Min) and storage[suppliesPanelName].item3 > 100) then
|
||||
print("CaveBot[SupplyCheck]: Not enough item: " .. storage[suppliesPanelName].item3 .. "(only " .. totalItem3 .. " left). Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return false
|
||||
elseif (totalItem4 < tonumber(storage[suppliesPanelName].item4Min) and storage[suppliesPanelName].item4 > 100) then
|
||||
print("CaveBot[SupplyCheck]: Not enough item: " .. storage[suppliesPanelName].item4 .. "(only " .. totalItem4 .. " left). Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return false
|
||||
elseif (totalItem5 < tonumber(storage[suppliesPanelName].item5Min) and storage[suppliesPanelName].item5 > 100) then
|
||||
print("CaveBot[SupplyCheck]: Not enough item: " .. storage[suppliesPanelName].item5 .. "(only " .. totalItem5 .. " left). Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return false
|
||||
elseif (totalItem6 < tonumber(storage[suppliesPanelName].item6Min) and storage[suppliesPanelName].item6 > 100) then
|
||||
print("CaveBot[SupplyCheck]: Not enough item: " .. storage[suppliesPanelName].item6 .. "(only " .. totalItem6 .. " left). Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return false
|
||||
elseif (freecap() < tonumber(storage[suppliesPanelName].capValue) and storage[suppliesPanelName].capSwitch) then
|
||||
print("CaveBot[SupplyCheck]: Not enough capacity. Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return false
|
||||
else
|
||||
print("CaveBot[SupplyCheck]: Enough supplies. Hunting. Round (" .. storage.supplyRetries .. "/50)")
|
||||
storage.supplyRetries = storage.supplyRetries + 1
|
||||
return CaveBot.gotoLabel(value)
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("supplycheck", "supply check", {
|
||||
value="startHunt",
|
||||
title="Supply check label",
|
||||
description="Insert here hunting start label",
|
||||
})
|
||||
end
|
@@ -0,0 +1,52 @@
|
||||
CaveBot.Extensions.Travel = {}
|
||||
|
||||
CaveBot.Extensions.Travel.setup = function()
|
||||
CaveBot.registerAction("Travel", "#00FFFF", function(value, retries)
|
||||
local data = string.split(value, ",")
|
||||
local waitVal = 0
|
||||
if #data < 2 or #data > 3 then
|
||||
warn("CaveBot[Travel]: incorrect travel value!")
|
||||
return false
|
||||
elseif #data == 3 then
|
||||
waitVal = tonumber(data[3]:trim())
|
||||
end
|
||||
|
||||
if not waitVal then
|
||||
warn("CaveBot[Travel]: incorrect travel delay value!")
|
||||
return false
|
||||
end
|
||||
|
||||
if retries > 5 then
|
||||
print("CaveBot[Travel]: too many tries, can't travel")
|
||||
return false
|
||||
end
|
||||
|
||||
local npc = getCreatureByName(data[1]:trim())
|
||||
if not npc then
|
||||
print("CaveBot[Travel]: NPC not found, can't travel")
|
||||
return false
|
||||
end
|
||||
|
||||
local pos = player:getPosition()
|
||||
local npcPos = npc:getPosition()
|
||||
if math.max(math.abs(pos.x - npcPos.x), math.abs(pos.y - npcPos.y)) > 3 then
|
||||
CaveBot.walkTo(npcPos, 20, {ignoreNonPathable = true, precision=3})
|
||||
delay(300)
|
||||
return "retry"
|
||||
end
|
||||
|
||||
NPC.say("hi")
|
||||
schedule(waitVal, function() NPC.say(data[2]:trim()) end)
|
||||
schedule(2*waitVal, function() NPC.say("yes") end)
|
||||
delay(3*waitVal)
|
||||
print("CaveBot[Travel]: travel action finished")
|
||||
return true
|
||||
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("travel", "travel", {
|
||||
value="NPC name, city",
|
||||
title="Travel",
|
||||
description="NPC name, City name, delay in ms(optional)",
|
||||
})
|
||||
end
|
@@ -0,0 +1,93 @@
|
||||
-- walking
|
||||
local expectedDirs = {}
|
||||
local isWalking = {}
|
||||
local walkPath = {}
|
||||
local walkPathIter = 0
|
||||
|
||||
CaveBot.resetWalking = function()
|
||||
expectedDirs = {}
|
||||
walkPath = {}
|
||||
isWalking = false
|
||||
end
|
||||
|
||||
CaveBot.doWalking = function()
|
||||
if CaveBot.Config.get("mapClick") then
|
||||
return false
|
||||
end
|
||||
if #expectedDirs == 0 then
|
||||
return false
|
||||
end
|
||||
if #expectedDirs >= 3 then
|
||||
CaveBot.resetWalking()
|
||||
end
|
||||
local dir = walkPath[walkPathIter]
|
||||
if dir then
|
||||
g_game.walk(dir, false)
|
||||
table.insert(expectedDirs, dir)
|
||||
walkPathIter = walkPathIter + 1
|
||||
CaveBot.delay(CaveBot.Config.get("walkDelay") + player:getStepDuration(false, dir))
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- called when player position has been changed (step has been confirmed by server)
|
||||
onPlayerPositionChange(function(newPos, oldPos)
|
||||
if not oldPos or not newPos then return end
|
||||
|
||||
local dirs = {{NorthWest, North, NorthEast}, {West, 8, East}, {SouthWest, South, SouthEast}}
|
||||
local dir = dirs[newPos.y - oldPos.y + 2]
|
||||
if dir then
|
||||
dir = dir[newPos.x - oldPos.x + 2]
|
||||
end
|
||||
if not dir then
|
||||
dir = 8 -- 8 is invalid dir, it's fine
|
||||
end
|
||||
|
||||
if not isWalking or not expectedDirs[1] then
|
||||
-- some other walk action is taking place (for example use on ladder), wait
|
||||
walkPath = {}
|
||||
CaveBot.delay(CaveBot.Config.get("ping") + player:getStepDuration(false, dir) + 150)
|
||||
return
|
||||
end
|
||||
|
||||
if expectedDirs[1] ~= dir then
|
||||
if CaveBot.Config.get("mapClick") then
|
||||
CaveBot.delay(CaveBot.Config.get("walkDelay") + player:getStepDuration(false, dir))
|
||||
else
|
||||
CaveBot.delay(CaveBot.Config.get("mapClickDelay") + player:getStepDuration(false, dir))
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
table.remove(expectedDirs, 1)
|
||||
if CaveBot.Config.get("mapClick") and #expectedDirs > 0 then
|
||||
CaveBot.delay(CaveBot.Config.get("mapClickDelay") + player:getStepDuration(false, dir))
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.walkTo = function(dest, maxDist, params)
|
||||
local path = getPath(player:getPosition(), dest, maxDist, params)
|
||||
if not path or not path[1] then
|
||||
return false
|
||||
end
|
||||
local dir = path[1]
|
||||
|
||||
if CaveBot.Config.get("mapClick") then
|
||||
local ret = autoWalk(path)
|
||||
if ret then
|
||||
isWalking = true
|
||||
expectedDirs = path
|
||||
CaveBot.delay(CaveBot.Config.get("mapClickDelay") + math.max(CaveBot.Config.get("ping") + player:getStepDuration(false, dir), player:getStepDuration(false, dir) * 2))
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
g_game.walk(dir, false)
|
||||
isWalking = true
|
||||
walkPath = path
|
||||
walkPathIter = 2
|
||||
expectedDirs = { dir }
|
||||
CaveBot.delay(CaveBot.Config.get("walkDelay") + player:getStepDuration(false, dir))
|
||||
return true
|
||||
end
|
@@ -0,0 +1,221 @@
|
||||
CaveBot.Extensions.Withdraw = {}
|
||||
|
||||
comparePosition = function(pPos, tPos)
|
||||
return (getDistanceBetween(pPos, tPos) <= 1)
|
||||
end
|
||||
|
||||
local depotContainers = {22797, 22798, 22799, 22800, 22801, 22802, 22803, 22804, 22805, 22806, 22807, 22808, 22809, 22810, 22811, 22812, 22813}
|
||||
local depotIDs = {3497, 3498, 3499, 3500}
|
||||
storage.stopSearch = false
|
||||
storage.lootContainerOpen = false
|
||||
local i = 1
|
||||
|
||||
|
||||
CaveBot.Extensions.Withdraw.setup = function()
|
||||
CaveBot.registerAction("withdraw", "#00FFFF", function(value, retries)
|
||||
local data = string.split(value, ",")
|
||||
local stashIndex
|
||||
local withdrawId
|
||||
local count
|
||||
local itemCount = 0
|
||||
local depotAmount
|
||||
if #data ~= 3 then
|
||||
warn("incorrect withdraw value")
|
||||
return false
|
||||
else
|
||||
stashIndex = tonumber(data[1])
|
||||
withdrawId = tonumber(data[2])
|
||||
count = tonumber(data[3])
|
||||
end
|
||||
local withdrawSource = depotContainers[stashIndex]
|
||||
|
||||
for i, container in pairs(getContainers()) do
|
||||
if not string.find(container:getName():lower(), "depot") then
|
||||
for j, item in pairs(container:getItems()) do
|
||||
if item:getId() == withdrawId then
|
||||
itemCount = itemCount + item:getCount()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if itemCount >= count then
|
||||
for i, container in pairs(getContainers()) do
|
||||
if string.find(container:getName():lower(), "depot box") then
|
||||
g_game.close(container)
|
||||
end
|
||||
end
|
||||
print("enough items")
|
||||
return true
|
||||
end
|
||||
|
||||
if retries > 400 then
|
||||
return true
|
||||
end
|
||||
|
||||
delay(200)
|
||||
local tileList = {}
|
||||
local tPos
|
||||
local depotClear = false
|
||||
local depotOpen = false
|
||||
local depotBoxOpen = false
|
||||
for _,tile in pairs(g_map.getTiles(posz())) do
|
||||
for i,thing in pairs(tile:getThings()) do
|
||||
if table.find(depotIDs, thing:getId()) then
|
||||
table.insert(tileList, {tileObj = tile, distance = getDistanceBetween(pos(), tile:getPosition()), depotID = thing:getId()})
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(tileList, function(a,b) return a.distance < b.distance end)
|
||||
::findEmptyDP::
|
||||
if tileList[i] and not storage.stopSearch then
|
||||
if tileList[i].depotID == 3498 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x + 1, y = tileList[i].tileObj:getPosition().y, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3499 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x, y = tileList[i].tileObj:getPosition().y + 1, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3500 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x - 1, y = tileList[i].tileObj:getPosition().y, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3497 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x, y = tileList[i].tileObj:getPosition().y - 1, z = tileList[i].tileObj:getPosition().z}
|
||||
end
|
||||
if tPos then
|
||||
local dest = g_map.getTile(tPos)
|
||||
if not comparePosition(pos(), dest:getPosition()) then
|
||||
if not dest:getCreatures()[1] and dest:isWalkable() then
|
||||
if CaveBot.walkTo(dest:getPosition(), {ignoreNonPathable=true}) then
|
||||
storage.stopSearch = true
|
||||
delay(100)
|
||||
end
|
||||
else
|
||||
i = i + 1
|
||||
goto findEmptyDP
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if tileList[i].tileObj and not table.find(depotIDs, tileList[i].tileObj:getTopLookThing():getId()) and comparePosition(pos(), tileList[i].tileObj:getPosition()) then
|
||||
for j=1,table.getn(tileList[i].tileObj:getThings()),1 do
|
||||
if not tileList[i].tileObj:getThings()[j]:isNotMoveable() then
|
||||
delay(500)
|
||||
g_game.move(tileList[i].tileObj:getThings()[j], pos(), tileList[i].tileObj:getThings()[j]:getCount())
|
||||
end
|
||||
end
|
||||
if table.find(depotIDs, tileList[i].tileObj:getTopLookThing():getId()) then
|
||||
depotClear = true
|
||||
end
|
||||
else
|
||||
depotClear = true
|
||||
end
|
||||
if depotClear then
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
if container:getName():lower() == "locker" then
|
||||
depotOpen = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if tileList[i].tileObj and depotClear and not depotOpen and not storage.lootContainerOpen then
|
||||
delay(500)
|
||||
g_game.use(tileList[i].tileObj:getTopUseThing())
|
||||
depotOpen = true
|
||||
end
|
||||
i = 1
|
||||
--Version Check to know what to do with the depot--
|
||||
if g_game.getClientVersion() > 910 then
|
||||
if depotOpen then
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
if container:getName():lower() == "depot chest" then
|
||||
depotBoxOpen = true
|
||||
end
|
||||
end
|
||||
if findItem(3502) and not depotBoxOpen then
|
||||
delay(500)
|
||||
g_game.use(findItem(3502))
|
||||
depotBoxOpen = true
|
||||
end
|
||||
end
|
||||
if depotBoxOpen and not storage.lootContainerOpen then
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
if container:getName():lower() == "depot chest" then
|
||||
for _, item in ipairs(container:getItems()) do
|
||||
if item:isContainer() and table.find({22797, 22798}, item:getId()) then
|
||||
delay(500)
|
||||
storage.lootContainerOpen = true
|
||||
break
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local boxOpened = false
|
||||
for _, container in pairs(getContainers()) do
|
||||
if string.find(container:getName():lower(), "depot box") then
|
||||
boxOpened = true
|
||||
end
|
||||
end
|
||||
|
||||
if not boxOpened then
|
||||
for _, container in pairs(getContainers()) do
|
||||
if container:getName():lower() == "depot chest" then
|
||||
for _, item in pairs(container:getItems()) do
|
||||
if item:getId() == withdrawSource then
|
||||
g_game.open(item)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i, container in pairs(getContainers()) do
|
||||
if string.find(container:getName():lower(), "depot") then
|
||||
for j, item in pairs(container:getItems()) do
|
||||
if item:getId() == withdrawId then
|
||||
depotAmount = depotAmount + item:getCount()
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if depotAmount == 0 then
|
||||
print("lack of withdraw items!")
|
||||
return false
|
||||
end
|
||||
|
||||
local destination
|
||||
for i, container in pairs(getContainers()) do
|
||||
if container:getCapacity() > #container:getItems() and not string.find(container:getName():lower(), "depot") and not string.find(container:getName():lower(), "loot") and not string.find(container:getName():lower(), "inbox") then
|
||||
destination = container
|
||||
end
|
||||
end
|
||||
|
||||
if itemCount < count and destination then
|
||||
for i, container in pairs(getContainers()) do
|
||||
if string.find(container:getName():lower(), "depot box") then
|
||||
for j, item in pairs(container:getItems()) do
|
||||
if item:getId() == withdrawId then
|
||||
if item:isStackable() then
|
||||
g_game.move(item, destination:getSlotPosition(destination:getItemsCount()), math.min(item:getCount(), (count - itemCount)))
|
||||
return "retry"
|
||||
else
|
||||
g_game.move(item, destination:getSlotPosition(destination:getItemsCount()), 1)
|
||||
return "retry"
|
||||
end
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return "retry"
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("withdraw", "withdraw", {
|
||||
value="index,id,amount",
|
||||
title="Withdraw Items",
|
||||
description="insert source index, item id and amount",
|
||||
})
|
||||
end
|
Reference in New Issue
Block a user