mirror of
https://github.com/OTCv8/otclientv8.git
synced 2025-11-02 03:46:24 +01:00
Updated to OTCv8 3.1 rev 224
This commit is contained in:
65
modules/game_bot/default_configs/vBot_4.7/_Loader.lua
Normal file
65
modules/game_bot/default_configs/vBot_4.7/_Loader.lua
Normal file
@@ -0,0 +1,65 @@
|
||||
-- load all otui files, order doesn't matter
|
||||
local configName = modules.game_bot.contentsPanel.config:getCurrentOption().text
|
||||
|
||||
local configFiles = g_resources.listDirectoryFiles("/bot/" .. configName .. "/vBot", true, false)
|
||||
for i, file in ipairs(configFiles) do
|
||||
local ext = file:split(".")
|
||||
if ext[#ext]:lower() == "ui" or ext[#ext]:lower() == "otui" then
|
||||
g_ui.importStyle(file)
|
||||
end
|
||||
end
|
||||
|
||||
local function loadScript(name)
|
||||
return dofile("/vBot/" .. name .. ".lua")
|
||||
end
|
||||
|
||||
-- here you can set manually order of scripts
|
||||
-- libraries should be loaded first
|
||||
local luaFiles = {
|
||||
"main",
|
||||
"items",
|
||||
"vlib",
|
||||
"new_cavebot_lib",
|
||||
"configs", -- do not change this and above
|
||||
"extras",
|
||||
"cavebot",
|
||||
"playerlist",
|
||||
"BotServer",
|
||||
"alarms",
|
||||
"Conditions",
|
||||
"Equipper",
|
||||
"pushmax",
|
||||
"combo",
|
||||
"HealBot",
|
||||
"new_healer",
|
||||
"AttackBot", -- last of major modules
|
||||
"ingame_editor",
|
||||
"Dropper",
|
||||
"Containers",
|
||||
"quiver_manager",
|
||||
"quiver_label",
|
||||
"tools",
|
||||
"antiRs",
|
||||
"depot_withdraw",
|
||||
"cast_food",
|
||||
"eat_food",
|
||||
"equip",
|
||||
"exeta",
|
||||
"analyzer",
|
||||
"spy_level",
|
||||
"supplies",
|
||||
"depositer_config",
|
||||
"npc_talk",
|
||||
"xeno_menu",
|
||||
"hold_target",
|
||||
"cavebot_control_panel"
|
||||
}
|
||||
|
||||
for i, file in ipairs(luaFiles) do
|
||||
loadScript(file)
|
||||
end
|
||||
|
||||
setDefaultTab("Main")
|
||||
UI.Separator()
|
||||
UI.Label("Private Scripts:")
|
||||
UI.Separator()
|
||||
505
modules/game_bot/default_configs/vBot_4.7/cavebot/actions.lua
Normal file
505
modules/game_bot/default_configs/vBot_4.7/cavebot/actions.lua
Normal file
@@ -0,0 +1,505 @@
|
||||
CaveBot.Actions = {}
|
||||
vBot.lastLabel = ""
|
||||
local oldTibia = g_game.getClientVersion() < 960
|
||||
local nextTile = nil
|
||||
|
||||
local noPath = 0
|
||||
|
||||
-- antistuck f()
|
||||
local nextPos = nil -- creature
|
||||
local nextPosF = nil -- furniture
|
||||
local function modPos(dir)
|
||||
local y = 0
|
||||
local x = 0
|
||||
|
||||
if dir == 0 then
|
||||
y = -1
|
||||
elseif dir == 1 then
|
||||
x = 1
|
||||
elseif dir == 2 then
|
||||
y = 1
|
||||
elseif dir == 3 then
|
||||
x = -1
|
||||
elseif dir == 4 then
|
||||
y = -1
|
||||
x = 1
|
||||
elseif dir == 5 then
|
||||
y = 1
|
||||
x = 1
|
||||
elseif dir == 6 then
|
||||
y = 1
|
||||
x = -1
|
||||
elseif dir == 7 then
|
||||
y = -1
|
||||
x = -1
|
||||
end
|
||||
|
||||
return {x, y}
|
||||
end
|
||||
|
||||
-- stack-covered antystuck, in & out pz
|
||||
local lastMoved = now - 200
|
||||
onTextMessage(function(mode, text)
|
||||
if text ~= 'There is not enough room.' then return end
|
||||
if CaveBot.isOff() then return end
|
||||
|
||||
local tiles = getNearTiles(pos())
|
||||
|
||||
for i, tile in ipairs(tiles) do
|
||||
if not tile:hasCreature() and tile:isWalkable() and #tile:getItems() > 9 then
|
||||
local topThing = tile:getTopThing()
|
||||
if not isInPz() then
|
||||
return useWith(3197, tile:getTopThing()) -- disintegrate
|
||||
else
|
||||
if now < lastMoved + 200 then return end -- delay to prevent clogging
|
||||
local nearTiles = getNearTiles(tile:getPosition())
|
||||
for i, tile in ipairs(nearTiles) do
|
||||
local tpos = tile:getPosition()
|
||||
if pos() ~= tpos then
|
||||
if tile:isWalkable() then
|
||||
lastMoved = now
|
||||
return g_game.move(topThing, tpos) -- move item
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local furnitureIgnore = { 2986 }
|
||||
local function breakFurniture(destPos)
|
||||
if isInPz() then return false end
|
||||
local candidate = {thing=nil, dist=100}
|
||||
for i, tile in ipairs(g_map.getTiles(posz())) do
|
||||
local walkable = tile:isWalkable()
|
||||
local topThing = tile:getTopThing()
|
||||
local isWg = topThing and topThing:getId() == 2130
|
||||
if topThing and (isWg or not table.find(furnitureIgnore, topThing:getId()) and topThing:isItem()) then
|
||||
local moveable = not topThing:isNotMoveable()
|
||||
local tpos = tile:getPosition()
|
||||
local path = findPath(player:getPosition(), tpos, 7, { ignoreNonPathable = true, precision = 1 })
|
||||
|
||||
if path then
|
||||
if isWg or (not walkable and moveable) then
|
||||
local distance = getDistanceBetween(destPos, tpos)
|
||||
|
||||
if distance < candidate.dist then
|
||||
candidate = {thing=topThing, dist=distance}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local thing = candidate.thing
|
||||
if thing then
|
||||
useWith(3197, thing)
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function pushPlayer(creature)
|
||||
local cpos = creature:getPosition()
|
||||
local tiles = getNearTiles(cpos)
|
||||
|
||||
for i, tile in ipairs(tiles) do
|
||||
local pos = tile:getPosition()
|
||||
local minimapColor = g_map.getMinimapColor(pos)
|
||||
local stairs = (minimapColor >= 210 and minimapColor <= 213)
|
||||
|
||||
if not stairs and tile:isWalkable() then
|
||||
g_game.move(creature, pos)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local function pathfinder()
|
||||
if not storage.extras.pathfinding then return end
|
||||
if noPath < 10 then return end
|
||||
|
||||
if not CaveBot.gotoNextWaypointInRange() then
|
||||
if getConfigFromName and getConfigFromName() then
|
||||
local profile = CaveBot.getCurrentProfile()
|
||||
local config = getConfigFromName()
|
||||
local newProfile = profile == '#Unibase' and config or '#Unibase'
|
||||
|
||||
CaveBot.setCurrentProfile(newProfile)
|
||||
end
|
||||
end
|
||||
noPath = 0
|
||||
return true
|
||||
end
|
||||
|
||||
-- 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 warn("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 warn("Invalid cavebot action: " .. action)
|
||||
end
|
||||
|
||||
if not widget.action or not widget.value then
|
||||
return warn("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 warn("Duplicated acction: " .. action)
|
||||
end
|
||||
CaveBot.Actions[action] = {
|
||||
color=color,
|
||||
callback=callback
|
||||
}
|
||||
end
|
||||
|
||||
CaveBot.registerAction("label", "yellow", function(value, retries, prev)
|
||||
vBot.lastLabel = value
|
||||
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
|
||||
local data = string.split(value, ",")
|
||||
local val = tonumber(data[1]:trim())
|
||||
local random
|
||||
local final
|
||||
|
||||
|
||||
if #data == 2 then
|
||||
random = tonumber(data[2]:trim())
|
||||
end
|
||||
|
||||
if random then
|
||||
local diff = (val/100) * random
|
||||
local min = val - diff
|
||||
local max = val + diff
|
||||
final = math.random(min, max)
|
||||
end
|
||||
final = final or val
|
||||
|
||||
CaveBot.delay(final)
|
||||
return "retry"
|
||||
end
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("follow", "#FF8400", function(value, retries, prev)
|
||||
local c = getCreatureByName(value)
|
||||
if not c then
|
||||
print("CaveBot[follow]: can't find creature to follow")
|
||||
return false
|
||||
end
|
||||
local cpos = c:getPosition()
|
||||
local pos = pos()
|
||||
if getDistanceBetween(cpos, pos) < 2 then
|
||||
g_game.cancelFollow()
|
||||
return true
|
||||
else
|
||||
follow(c)
|
||||
delay(200)
|
||||
return "retry"
|
||||
end
|
||||
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() warn('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
|
||||
warn("warn 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
|
||||
warn("Invalid cavebot goto action value. It should be position (x,y,z), is: " .. value)
|
||||
return false
|
||||
end
|
||||
|
||||
-- reset pathfinder
|
||||
nextPosF = nil
|
||||
nextPos = nil
|
||||
|
||||
if CaveBot.Config.get("mapClick") then
|
||||
if retries >= 5 then
|
||||
noPath = noPath + 1
|
||||
pathfinder()
|
||||
return false -- tried 5 times, can't get there
|
||||
end
|
||||
else
|
||||
if retries >= 100 then
|
||||
noPath = noPath + 1
|
||||
pathfinder()
|
||||
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
|
||||
noPath = noPath + 1
|
||||
pathfinder()
|
||||
return false -- different floor
|
||||
end
|
||||
|
||||
local maxDist = storage.extras.gotoMaxDistance or 40
|
||||
|
||||
if math.abs(pos.x-playerPos.x) + math.abs(pos.y-playerPos.y) > maxDist then
|
||||
noPath = noPath + 1
|
||||
pathfinder()
|
||||
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
|
||||
noPath = 0
|
||||
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
|
||||
noPath = 0
|
||||
return true -- already at position
|
||||
end
|
||||
-- check if there's a path to that place, ignore creatures and fields
|
||||
local path = findPath(playerPos, pos, maxDist, { ignoreNonPathable = true, precision = 1, ignoreCreatures = true, allowUnseen = true, allowOnlyVisibleTiles = false })
|
||||
if not path then
|
||||
if breakFurniture(pos, storage.extras.machete) then
|
||||
CaveBot.delay(1000)
|
||||
retries = 0
|
||||
return "retry"
|
||||
end
|
||||
noPath = noPath + 1
|
||||
pathfinder()
|
||||
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, maxDist, { ignoreNonPathable = true, precision = 1 })
|
||||
if not path2 then
|
||||
local foundMonster = false
|
||||
for i, dir in ipairs(path) do
|
||||
local dirs = modPos(dir)
|
||||
nextPos = nextPos or playerPos
|
||||
nextPos.x = nextPos.x + dirs[1]
|
||||
nextPos.y = nextPos.y + dirs[2]
|
||||
|
||||
local tile = g_map.getTile(nextPos)
|
||||
if tile then
|
||||
if tile:hasCreature() then
|
||||
local creature = tile:getCreatures()[1]
|
||||
local hppc = creature:getHealthPercent()
|
||||
if creature:isMonster() and (hppc and hppc > 0) and (oldTibia or creature:getType() < 3) then
|
||||
-- real blocking creature can not meet those conditions - ie. it could be player, so just in case check if the next creature is reachable
|
||||
local path = findPath(playerPos, creature:getPosition(), 7, { ignoreNonPathable = true, precision = 1 })
|
||||
if path then
|
||||
foundMonster = true
|
||||
if g_game.getAttackingCreature() ~= creature then
|
||||
attack(creature)
|
||||
end
|
||||
g_game.setChaseMode(1)
|
||||
CaveBot.delay(100)
|
||||
retries = 0 -- reset retries, we are trying to unclog the cavebot
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not foundMonster then
|
||||
foundMonster = false
|
||||
return false -- no other 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, maxDist, { ignoreNonPathable = true, allowUnseen = true, allowOnlyVisibleTiles = false }) 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, allowUnseen = true, allowOnlyVisibleTiles = false }) then
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
|
||||
if not CaveBot.Config.get("mapClick") and retries >= 5 then
|
||||
noPath = noPath + 1
|
||||
pathfinder()
|
||||
return false
|
||||
end
|
||||
|
||||
if CaveBot.Config.get("skipBlocked") then
|
||||
noPath = noPath + 1
|
||||
pathfinder()
|
||||
return false
|
||||
end
|
||||
|
||||
-- everything else failed, try to walk ignoring creatures, maybe will work
|
||||
CaveBot.walkTo(pos, maxDist, { ignoreNonPathable = true, precision = 1, ignoreCreatures = true, allowUnseen = true, allowOnlyVisibleTiles = false })
|
||||
return "retry"
|
||||
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
|
||||
warn("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
|
||||
warn("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)
|
||||
CaveBot.registerAction("npcsay", "#FF55FF", function(value, retries, prev)
|
||||
NPC.say(value)
|
||||
return true
|
||||
end)
|
||||
92
modules/game_bot/default_configs/vBot_4.7/cavebot/bank.lua
Normal file
92
modules/game_bot/default_configs/vBot_4.7/cavebot/bank.lua
Normal file
@@ -0,0 +1,92 @@
|
||||
CaveBot.Extensions.Bank = {}
|
||||
|
||||
local balance = 0
|
||||
|
||||
CaveBot.Extensions.Bank.setup = function()
|
||||
CaveBot.registerAction("bank", "#db5a5a", function(value, retries)
|
||||
local data = string.split(value, ",")
|
||||
local waitVal = 300
|
||||
local amount = 0
|
||||
local actionType
|
||||
local npcName
|
||||
local transferName
|
||||
local balanceLeft
|
||||
if #data ~= 3 and #data ~= 2 and #data ~= 4 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
|
||||
if #data == 4 then
|
||||
transferName = data[3]:trim()
|
||||
balanceLeft = tonumber(data[4]:trim())
|
||||
end
|
||||
end
|
||||
|
||||
if actionType ~= "withdraw" and actionType ~= "deposit" and actionType ~= "transfer" then
|
||||
warn("CaveBot[Bank]: incorrect action type! should be withdraw/deposit/transfer, 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
|
||||
|
||||
if not CaveBot.ReachNPC(npcName) then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
if actionType == "deposit" then
|
||||
CaveBot.Conversation("hi", "deposit all", "yes")
|
||||
CaveBot.delay(storage.extras.talkDelay*3)
|
||||
return true
|
||||
elseif actionType == "withdraw" then
|
||||
CaveBot.Conversation("hi", "withdraw", value, "yes")
|
||||
CaveBot.delay(storage.extras.talkDelay*4)
|
||||
return true
|
||||
else
|
||||
-- first check balance
|
||||
CaveBot.Conversation("hi", "balance")
|
||||
schedule(5000, function()
|
||||
local amountToTransfer = balance - balanceLeft
|
||||
if amountToTransfer <= 0 then
|
||||
warn("CaveBot[Bank] Not enough gold to transfer! proceeding")
|
||||
return false
|
||||
end
|
||||
CaveBot.Conversation("hi", "transfer", amountToTransfer, transferName, "yes")
|
||||
warn("CaveBot[Bank] transferred "..amountToTransfer.." gold to: "..transferName)
|
||||
end)
|
||||
CaveBot.delay(storage.extras.talkDelay*11)
|
||||
return true
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("bank", "bank", {
|
||||
value="action, NPC name",
|
||||
title="Banker",
|
||||
description="action type(withdraw/deposit/transfer), NPC name, (if withdraw: amount|if transfer: name, balance left)",
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
onTalk(function(name, level, mode, text, channelId, pos)
|
||||
if mode == 51 and text:find("Your account balance is") then
|
||||
balance = getFirstNumberInText(text)
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,76 @@
|
||||
CaveBot.Extensions.BuySupplies = {}
|
||||
|
||||
CaveBot.Extensions.BuySupplies.setup = function()
|
||||
CaveBot.registerAction("BuySupplies", "#C300FF", function(value, retries)
|
||||
local possibleItems = {}
|
||||
|
||||
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 npcName = val[1]:trim()
|
||||
local npc = getCreatureByName(npcName)
|
||||
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 > 50 then
|
||||
print("CaveBot[BuySupplies]: Too many tries, can't buy")
|
||||
return false
|
||||
end
|
||||
|
||||
if not CaveBot.ReachNPC(npcName) then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
if not NPC.isTrading() then
|
||||
CaveBot.OpenNpcTrade()
|
||||
CaveBot.delay(storage.extras.talkDelay*2)
|
||||
return "retry"
|
||||
end
|
||||
|
||||
-- get items from npc
|
||||
local npcItems = NPC.getBuyItems()
|
||||
for i,v in pairs(npcItems) do
|
||||
table.insert(possibleItems, v.id)
|
||||
end
|
||||
|
||||
for id, values in pairs(Supplies.getItemsData()) do
|
||||
id = tonumber(id)
|
||||
if table.find(possibleItems, id) then
|
||||
local max = values.max
|
||||
local current = player:getItemsCount(id)
|
||||
local toBuy = max - current
|
||||
|
||||
if toBuy > 0 then
|
||||
toBuy = math.min(100, toBuy)
|
||||
|
||||
NPC.buy(id, math.min(100, toBuy))
|
||||
print("CaveBot[BuySupplies]: bought " .. toBuy .. "x " .. id)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
print("CaveBot[BuySupplies]: bought everything, proceeding")
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("buysupplies", "buy supplies", {
|
||||
value="NPC name",
|
||||
title="Buy Supplies",
|
||||
description="NPC Name, delay(in ms, optional)",
|
||||
})
|
||||
end
|
||||
447
modules/game_bot/default_configs/vBot_4.7/cavebot/cavebot.lua
Normal file
447
modules/game_bot/default_configs/vBot_4.7/cavebot/cavebot.lua
Normal file
@@ -0,0 +1,447 @@
|
||||
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 walking3
|
||||
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
|
||||
warn("Invalid return from cavebot action (" .. currentAction.action .. "), should be \"retry\", false or true, is: " .. tostring(result))
|
||||
end
|
||||
else
|
||||
warn("warn while executing cavebot action (" .. currentAction.action .. "):\n" .. result)
|
||||
end
|
||||
else
|
||||
warn("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
|
||||
warn("warn 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
|
||||
warn("warn 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.getCurrentProfile = function()
|
||||
return storage._configs.cavebot_configs.selected
|
||||
end
|
||||
|
||||
CaveBot.lastReachedLabel = function()
|
||||
return vBot.lastLabel
|
||||
end
|
||||
|
||||
CaveBot.gotoNextWaypointInRange = function()
|
||||
local currentAction = ui.list:getFocusedChild()
|
||||
local index = ui.list:getChildIndex(currentAction)
|
||||
local actions = ui.list:getChildren()
|
||||
|
||||
-- start searching from current index
|
||||
for i, child in ipairs(actions) do
|
||||
if i > index then
|
||||
local text = child:getText()
|
||||
if string.starts(text, "goto:") then
|
||||
local re = regexMatch(text, [[(?:goto:)([^,]+),([^,]+),([^,]+)]])
|
||||
local pos = {x = tonumber(re[1][2]), y = tonumber(re[1][3]), z = tonumber(re[1][4])}
|
||||
|
||||
if posz() == pos.z then
|
||||
local maxDist = storage.extras.gotoMaxDistance
|
||||
if distanceFromPlayer(pos) <= maxDist then
|
||||
if findPath(player:getPosition(), pos, maxDist, { ignoreNonPathable = true }) then
|
||||
ui.list:focusChild(ui.list:getChildByIndex(i-1))
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- if not found then damn go from start
|
||||
for i, child in ipairs(actions) do
|
||||
if i <= index then
|
||||
local text = child:getText()
|
||||
if string.starts(text, "goto:") then
|
||||
local re = regexMatch(text, [[(?:goto:)([^,]+),([^,]+),([^,]+)]])
|
||||
local pos = {x = tonumber(re[1][2]), y = tonumber(re[1][3]), z = tonumber(re[1][4])}
|
||||
|
||||
if posz() == pos.z then
|
||||
local maxDist = storage.extras.gotoMaxDistance
|
||||
if distanceFromPlayer(pos) <= maxDist then
|
||||
if findPath(player:getPosition(), pos, maxDist, { ignoreNonPathable = true }) then
|
||||
ui.list:focusChild(ui.list:getChildByIndex(i-1))
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- not found
|
||||
return false
|
||||
end
|
||||
|
||||
local function reverseTable(t, max)
|
||||
local reversedTable = {}
|
||||
local itemCount = max or #t
|
||||
for i, v in ipairs(t) do
|
||||
reversedTable[itemCount + 1 - i] = v
|
||||
end
|
||||
return reversedTable
|
||||
end
|
||||
|
||||
function rpairs(t)
|
||||
test()
|
||||
return function(t, i)
|
||||
i = i - 1
|
||||
if i ~= 0 then
|
||||
return i, t[i]
|
||||
end
|
||||
end, t, #t + 1
|
||||
end
|
||||
|
||||
CaveBot.gotoFirstPreviousReachableWaypoint = function()
|
||||
local currentAction = ui.list:getFocusedChild()
|
||||
local currentIndex = ui.list:getChildIndex(currentAction)
|
||||
local index = ui.list:getChildIndex(currentAction)
|
||||
|
||||
-- check up to 100 childs
|
||||
for i=0,100 do
|
||||
index = index - i
|
||||
if index <= 0 or index > currentIndex or math.abs(index-currentIndex) > 100 then
|
||||
break
|
||||
end
|
||||
|
||||
local child = ui.list:getChildByIndex(index)
|
||||
|
||||
if child then
|
||||
local text = child:getText()
|
||||
if string.starts(text, "goto:") then
|
||||
local re = regexMatch(text, [[(?:goto:)([^,]+),([^,]+),([^,]+)]])
|
||||
local pos = {x = tonumber(re[1][2]), y = tonumber(re[1][3]), z = tonumber(re[1][4])}
|
||||
|
||||
if posz() == pos.z then
|
||||
if distanceFromPlayer(pos) <= storage.extras.gotoMaxDistance/2 then
|
||||
print("found pos, going back "..currentIndex-index.. " waypoints.")
|
||||
return ui.list:focusChild(child)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- not found
|
||||
print("previous pos not found, proceeding")
|
||||
return false
|
||||
end
|
||||
|
||||
CaveBot.getFirstWaypointBeforeLabel = function(label)
|
||||
label = "label:"..label
|
||||
label = label:lower()
|
||||
local actions = ui.list:getChildren()
|
||||
local index
|
||||
|
||||
-- find index of label
|
||||
for i, child in pairs(actions) do
|
||||
local name = child:getText():lower()
|
||||
if name == label then
|
||||
index = i
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- if there's no index then label was not found
|
||||
if not index then return false end
|
||||
|
||||
for i=1,#actions do
|
||||
if index - 1 < 1 then
|
||||
-- did not found any waypoint in range before label
|
||||
return false
|
||||
end
|
||||
|
||||
local child = ui.list:getChildByIndex(index-i)
|
||||
if child then
|
||||
local text = child:getText()
|
||||
if string.starts(text, "goto:") then
|
||||
local re = regexMatch(text, [[(?:goto:)([^,]+),([^,]+),([^,]+)]])
|
||||
local pos = {x = tonumber(re[1][2]), y = tonumber(re[1][3]), z = tonumber(re[1][4])}
|
||||
|
||||
if posz() == pos.z then
|
||||
if distanceFromPlayer(pos) <= storage.extras.gotoMaxDistance/2 then
|
||||
return ui.list:focusChild(child)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CaveBot.getPreviousLabel = function()
|
||||
local actions = ui.list:getChildren()
|
||||
-- check if config is empty
|
||||
if #actions == 0 then return false end
|
||||
|
||||
local currentAction = ui.list:getFocusedChild()
|
||||
--check we made any progress in waypoints, if no focused or first then no point checking
|
||||
if not currentAction or currentAction == ui.list:getFirstChild() then return false end
|
||||
|
||||
local index = ui.list:getChildIndex(currentAction)
|
||||
|
||||
-- if not index then something went wrong and there's no selected child
|
||||
if not index then return false end
|
||||
|
||||
for i=1,#actions do
|
||||
if index - i < 1 then
|
||||
-- did not found any waypoint in range before label
|
||||
return false
|
||||
end
|
||||
|
||||
local child = ui.list:getChildByIndex(index-i)
|
||||
if child then
|
||||
if child.action == "label" then
|
||||
return child.value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CaveBot.getNextLabel = function()
|
||||
local actions = ui.list:getChildren()
|
||||
-- check if config is empty
|
||||
if #actions == 0 then return false end
|
||||
|
||||
local currentAction = ui.list:getFocusedChild() or ui.list:getFirstChild()
|
||||
local index = ui.list:getChildIndex(currentAction)
|
||||
|
||||
-- if not index then something went wrong
|
||||
if not index then return false end
|
||||
|
||||
for i=1,#actions do
|
||||
if index + i > #actions then
|
||||
-- did not found any waypoint in range before label
|
||||
return false
|
||||
end
|
||||
|
||||
local child = ui.list:getChildByIndex(index+i)
|
||||
if child then
|
||||
if child.action == "label" then
|
||||
return child.value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local botConfigName = modules.game_bot.contentsPanel.config:getCurrentOption().text
|
||||
CaveBot.setCurrentProfile = function(name)
|
||||
if not g_resources.fileExists("/bot/"..botConfigName.."/cavebot_configs/"..name..".cfg") then
|
||||
return warn("there is no cavebot profile with that name!")
|
||||
end
|
||||
CaveBot.setOff()
|
||||
storage._configs.cavebot_configs.selected = name
|
||||
CaveBot.setOn()
|
||||
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
|
||||
|
||||
CaveBotList = function()
|
||||
return ui.list
|
||||
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
|
||||
128
modules/game_bot/default_configs/vBot_4.7/cavebot/clear_tile.lua
Normal file
128
modules/game_bot/default_configs/vBot_4.7/cavebot/clear_tile.lua
Normal file
@@ -0,0 +1,128 @@
|
||||
CaveBot.Extensions.ClearTile = {}
|
||||
|
||||
CaveBot.Extensions.ClearTile.setup = function()
|
||||
CaveBot.registerAction("ClearTile", "#00FFFF", function(value, retries)
|
||||
local data = string.split(value, ",")
|
||||
local pos = {x=tonumber(data[1]), y=tonumber(data[2]), z=tonumber(data[3])}
|
||||
local doors = false
|
||||
local stand = false
|
||||
local pPos = player:getPosition()
|
||||
|
||||
|
||||
for i, value in ipairs(data) do
|
||||
value = value:lower():trim()
|
||||
if value == "stand" then
|
||||
stand = true
|
||||
elseif value == "doors" then
|
||||
doors = true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if not #pos == 3 then
|
||||
warn("CaveBot[ClearTile]: invalid value. It should be position (x,y,z), is: " .. value)
|
||||
return false
|
||||
end
|
||||
|
||||
if retries >= 20 then
|
||||
print("CaveBot[ClearTile]: too many tries, can't clear it")
|
||||
return false -- tried 20 times, can't clear it
|
||||
end
|
||||
|
||||
if getDistanceBetween(player:getPosition(), pos) == 0 then
|
||||
print("CaveBot[ClearTile]: tile reached, proceeding")
|
||||
return true
|
||||
end
|
||||
local tile = g_map.getTile(pos)
|
||||
if not tile then
|
||||
print("CaveBot[ClearTile]: can't find tile or tile is unreachable, skipping")
|
||||
return false
|
||||
end
|
||||
local tPos = tile:getPosition()
|
||||
|
||||
-- no items on tile and walkability means we are done
|
||||
if tile:isWalkable() and tile:getTopUseThing():isNotMoveable() and not tile:hasCreature() and not doors then
|
||||
if stand then
|
||||
if not CaveBot.MatchPosition(tPos, 0) then
|
||||
CaveBot.GoTo(tPos, 0)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
print("CaveBot[ClearTile]: tile clear, proceeding")
|
||||
return true
|
||||
end
|
||||
|
||||
if not CaveBot.MatchPosition(tPos, 3) then
|
||||
CaveBot.GoTo(tPos, 3)
|
||||
return "retry"
|
||||
end
|
||||
|
||||
if retries > 0 then
|
||||
delay(1100)
|
||||
end
|
||||
|
||||
-- monster
|
||||
if tile:hasCreature() then
|
||||
local c = tile:getCreatures()[1]
|
||||
if c:isMonster() then
|
||||
attack(c)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
|
||||
-- moveable item
|
||||
local item = tile:getTopMoveThing()
|
||||
if item:isItem() then
|
||||
if item and not item:isNotMoveable() then
|
||||
print("CaveBot[ClearTile]: moving item... " .. item:getId().. " from tile")
|
||||
g_game.move(item, pPos, item:getCount())
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
|
||||
-- player
|
||||
|
||||
-- push creature
|
||||
if tile:hasCreature() then
|
||||
local c = tile:getCreatures()[1]
|
||||
if c and c:isPlayer() then
|
||||
|
||||
local candidates = {}
|
||||
for _, tile in ipairs(g_map.getTiles(posz())) do
|
||||
local tPos = tile:getPosition()
|
||||
if getDistanceBetween(c:getPosition(), tPos) == 1 and tPos ~= pPos and tile:isWalkable() then
|
||||
table.insert(candidates, tPos)
|
||||
end
|
||||
end
|
||||
|
||||
if #candidates == 0 then
|
||||
print("CaveBot[ClearTile]: can't find tile to push, cannot clear way, skipping")
|
||||
return false
|
||||
else
|
||||
print("CaveBot[ClearTile]: pushing player... " .. c:getName() .. " out of the way")
|
||||
local pos = candidates[math.random(1,#candidates)]
|
||||
local tile = g_map.getTile(pos)
|
||||
tile:setText("here")
|
||||
schedule(500, function() tile:setText("") end)
|
||||
g_game.move(c, pos, 1)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- doors
|
||||
if doors then
|
||||
use(tile:getTopUseThing())
|
||||
return "retry"
|
||||
end
|
||||
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("cleartile", "clear tile", {
|
||||
value=function() return posx() .. "," .. posy() .. "," .. posz() end,
|
||||
title="position of tile to clear",
|
||||
description="tile position (x,y,z), doors/stand - optional",
|
||||
multiline=false
|
||||
})
|
||||
end
|
||||
111
modules/game_bot/default_configs/vBot_4.7/cavebot/config.lua
Normal file
111
modules/game_bot/default_configs/vBot_4.7/cavebot/config.lua
Normal file
@@ -0,0 +1,111 @@
|
||||
-- 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 warn("Duplicated config key: " .. id)
|
||||
end
|
||||
|
||||
local panel
|
||||
local setter -- sets value
|
||||
if type(defaultValue) == "number" then
|
||||
panel = UI.createWidget("CaveBotConfigNumberValuePanel", CaveBot.Config.ui)
|
||||
panel:setId(id)
|
||||
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)
|
||||
panel:setId(id)
|
||||
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 warn("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 warn("Invalid CaveBot.Config.get, id: " .. id)
|
||||
end
|
||||
return CaveBot.Config.values[id]
|
||||
end
|
||||
|
||||
CaveBot.Config.set = function(id, value)
|
||||
local valueType = CaveBot.Config.get(id)
|
||||
local panel = CaveBot.Config.ui[id]
|
||||
|
||||
if valueType == 'boolean' then
|
||||
CaveBot.Config.values[id] = value
|
||||
panel.value:setOn(value, true)
|
||||
CaveBot.save()
|
||||
else
|
||||
CaveBot.Config.values[id] = value
|
||||
panel.value:setText(value, true)
|
||||
CaveBot.save()
|
||||
end
|
||||
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
|
||||
105
modules/game_bot/default_configs/vBot_4.7/cavebot/d_withdraw.lua
Normal file
105
modules/game_bot/default_configs/vBot_4.7/cavebot/d_withdraw.lua
Normal file
@@ -0,0 +1,105 @@
|
||||
CaveBot.Extensions.DWithdraw = {}
|
||||
|
||||
CaveBot.Extensions.DWithdraw.setup = function()
|
||||
CaveBot.registerAction("dpwithdraw", "#002FFF", function(value, retries)
|
||||
local capLimit
|
||||
local data = string.split(value, ",")
|
||||
if retries > 600 then
|
||||
print("CaveBot[DepotWithdraw]: actions limit reached, proceeding")
|
||||
return false
|
||||
end
|
||||
local destContainer
|
||||
local depotContainer
|
||||
delay(70)
|
||||
|
||||
-- input validation
|
||||
if not value or #data ~= 3 and #data ~= 4 then
|
||||
warn("CaveBot[DepotWithdraw]: incorrect value!")
|
||||
return false
|
||||
end
|
||||
local indexDp = tonumber(data[1]:trim())
|
||||
local destName = data[2]:trim():lower()
|
||||
local destId = tonumber(data[3]:trim())
|
||||
if #data == 4 then
|
||||
capLimit = tonumber(data[4]:trim())
|
||||
end
|
||||
|
||||
|
||||
-- cap check
|
||||
if freecap() < (capLimit or 200) then
|
||||
for i, container in ipairs(getContainers()) do
|
||||
if container:getName():lower():find("depot") or container:getName():lower():find("locker") then
|
||||
g_game.close(container)
|
||||
end
|
||||
end
|
||||
print("CaveBot[DepotWithdraw]: cap limit reached, proceeding")
|
||||
return false
|
||||
end
|
||||
|
||||
-- containers
|
||||
for i, container in ipairs(getContainers()) do
|
||||
local cName = container:getName():lower()
|
||||
if destName == cName then
|
||||
destContainer = container
|
||||
elseif cName:find("depot box") then
|
||||
depotContainer = container
|
||||
end
|
||||
end
|
||||
|
||||
if not destContainer then
|
||||
print("CaveBot[DepotWithdraw]: container not found!")
|
||||
return false
|
||||
end
|
||||
|
||||
if containerIsFull(destContainer) then
|
||||
for i, item in pairs(destContainer:getItems()) do
|
||||
if item:getId() == destId then
|
||||
g_game.open(item, destContainer)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- stash validation
|
||||
if depotContainer and #depotContainer:getItems() == 0 then
|
||||
print("CaveBot[DepotWithdraw]: all items withdrawn")
|
||||
g_game.close(depotContainer)
|
||||
return true
|
||||
end
|
||||
|
||||
if containerIsFull(destContainer) then
|
||||
for i, item in pairs(destContainer:getItems()) do
|
||||
if item:getId() == destId then
|
||||
g_game.open(foundNextContainer, destContainer)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
print("CaveBot[DepotWithdraw]: loot containers full!")
|
||||
return false
|
||||
end
|
||||
|
||||
if not CaveBot.OpenDepotBox(indexDp) then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
CaveBot.PingDelay(2)
|
||||
|
||||
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
|
||||
statusMessage("[D_Withdraw] witdhrawing item: "..item:getId())
|
||||
g_game.move(item, destContainer:getSlotPosition(destContainer:getItemsCount()), item:getCount())
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("dpwithdraw", "dpwithdraw", {
|
||||
value="1, shopping bag, 21411",
|
||||
title="Loot Withdraw",
|
||||
description="insert index, destination container name and it's ID",
|
||||
})
|
||||
end
|
||||
138
modules/game_bot/default_configs/vBot_4.7/cavebot/depositor.lua
Normal file
138
modules/game_bot/default_configs/vBot_4.7/cavebot/depositor.lua
Normal file
@@ -0,0 +1,138 @@
|
||||
CaveBot.Extensions.Depositor = {}
|
||||
|
||||
--local variables
|
||||
local destination = nil
|
||||
local lootTable = nil
|
||||
local reopenedContainers = false
|
||||
|
||||
local function resetCache()
|
||||
reopenedContainers = false
|
||||
destination = nil
|
||||
lootTable = nil
|
||||
|
||||
for i, container in ipairs(getContainers()) do
|
||||
if container:getName():lower():find("depot") or container:getName():lower():find("locker") then
|
||||
g_game.close(container)
|
||||
end
|
||||
end
|
||||
|
||||
if storage.caveBot.backStop then
|
||||
storage.caveBot.backStop = false
|
||||
CaveBot.setOff()
|
||||
elseif storage.caveBot.backTrainers then
|
||||
storage.caveBot.backTrainers = false
|
||||
CaveBot.gotoLabel('toTrainers')
|
||||
elseif storage.caveBot.backOffline then
|
||||
storage.caveBot.backOffline = false
|
||||
CaveBot.gotoLabel('toOfflineTraining')
|
||||
end
|
||||
end
|
||||
|
||||
local description = g_game.getClientVersion() > 960 and "No - just deposit \n Yes - also reopen loot containers" or "currently not supported, will be added in near future"
|
||||
|
||||
CaveBot.Extensions.Depositor.setup = function()
|
||||
CaveBot.registerAction("depositor", "#002FFF", function(value, retries)
|
||||
-- version check, TODO old tibia
|
||||
if g_game.getClientVersion() < 960 then
|
||||
resetCache()
|
||||
warn("CaveBot[Depositor]: unsupported Tibia version, will be added in near future")
|
||||
return false
|
||||
end
|
||||
|
||||
-- loot list check
|
||||
lootTable = lootTable or CaveBot.GetLootItems()
|
||||
if #lootTable == 0 then
|
||||
print("CaveBot[Depositor]: no items in loot list. Wrong TargetBot Config? Proceeding")
|
||||
resetCache()
|
||||
return true
|
||||
end
|
||||
|
||||
delay(70)
|
||||
|
||||
-- backpacks etc
|
||||
if value:lower() == "yes" then
|
||||
if not reopenedContainers then
|
||||
CaveBot.CloseAllLootContainers()
|
||||
delay(3000)
|
||||
reopenedContainers = true
|
||||
return "retry"
|
||||
end
|
||||
-- open next backpacks if no more loot
|
||||
if not CaveBot.HasLootItems() then
|
||||
local lootContainers = CaveBot.GetLootContainers()
|
||||
for _, container in ipairs(getContainers()) do
|
||||
local cId = container:getContainerItem():getId()
|
||||
if table.find(lootContainers, cId) then
|
||||
for i, item in ipairs(container:getItems()) do
|
||||
if item:getId() == cId then
|
||||
g_game.open(item, container)
|
||||
delay(100)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- couldn't find next container, so we done
|
||||
print("CaveBot[Depositor]: all items stashed, no backpack to open next, proceeding")
|
||||
CaveBot.CloseAllLootContainers()
|
||||
delay(3000)
|
||||
resetCache()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- first check items
|
||||
if retries == 0 then
|
||||
if not CaveBot.HasLootItems() then -- resource consuming function
|
||||
print("CaveBot[Depositor]: no items to stash, proceeding")
|
||||
resetCache()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- next check retries
|
||||
if retries > 400 then
|
||||
print("CaveBot[Depositor]: Depositor actions limit reached, proceeding")
|
||||
resetCache()
|
||||
return true
|
||||
end
|
||||
|
||||
-- reaching and opening depot
|
||||
if not CaveBot.ReachAndOpenDepot() then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
-- add delay to prevent bugging
|
||||
CaveBot.PingDelay(2)
|
||||
|
||||
-- prep time and stashing
|
||||
destination = destination or getContainerByName("Depot chest")
|
||||
if not destination then return "retry" end
|
||||
|
||||
for _, container in pairs(getContainers()) do
|
||||
local name = container:getName():lower()
|
||||
if not name:find("depot") and not name:find("your inbox") then
|
||||
for _, item in pairs(container:getItems()) do
|
||||
local id = item:getId()
|
||||
if table.find(lootTable, id) then
|
||||
local index = getStashingIndex(id) or item:isStackable() and 1 or 0
|
||||
statusMessage("[Depositer] stashing item: " ..id.. " to depot: "..index+1)
|
||||
CaveBot.StashItem(item, index, destination)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- we gucci
|
||||
resetCache()
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("depositor", "depositor", {
|
||||
value="no",
|
||||
title="Depositor",
|
||||
description=description,
|
||||
validation="(yes|Yes|YES|no|No|NO)"
|
||||
})
|
||||
end
|
||||
58
modules/game_bot/default_configs/vBot_4.7/cavebot/doors.lua
Normal file
58
modules/game_bot/default_configs/vBot_4.7/cavebot/doors.lua
Normal file
@@ -0,0 +1,58 @@
|
||||
CaveBot.Extensions.OpenDoors = {}
|
||||
|
||||
CaveBot.Extensions.OpenDoors.setup = function()
|
||||
CaveBot.registerAction("OpenDoors", "#00FFFF", function(value, retries)
|
||||
local pos = string.split(value, ",")
|
||||
local key = nil
|
||||
if #pos == 4 then
|
||||
key = tonumber(pos[4])
|
||||
end
|
||||
if not pos[1] then
|
||||
warn("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]), y=tonumber(pos[2]), z=tonumber(pos[3])}
|
||||
|
||||
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
|
||||
if not key then
|
||||
use(doorTile:getTopUseThing())
|
||||
delay(200)
|
||||
return "retry"
|
||||
else
|
||||
useWith(key, doorTile:getTopUseThing())
|
||||
delay(200)
|
||||
return "retry"
|
||||
end
|
||||
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) and key id (optional)",
|
||||
multiline=false,
|
||||
validation=[[\d{1,5},\d{1,5},\d{1,2}(?:,\d{1,5}$|$)]]
|
||||
})
|
||||
end
|
||||
186
modules/game_bot/default_configs/vBot_4.7/cavebot/editor.lua
Normal file
186
modules/game_bot/default_configs/vBot_4.7/cavebot/editor.lua
Normal file
@@ -0,0 +1,186 @@
|
||||
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 warn("CaveBot editor warn: 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),randomness (in percent-optional)",
|
||||
multiline=false,
|
||||
validation="^[0-9]{1,10}$|^[0-9]{1,10},[0-9]{1,4}$"
|
||||
})
|
||||
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("follow", {
|
||||
value="NPC name",
|
||||
title="Follow Creature",
|
||||
description="insert creature name to follow",
|
||||
multiline=false
|
||||
})
|
||||
registerAction("npcsay", {
|
||||
value="text",
|
||||
title="NPC Say",
|
||||
description="Enter text to NPC 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,114 @@
|
||||
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 PZ and wait until dropped", [[
|
||||
if retries > 25 or not isPzLocked() then
|
||||
return true
|
||||
else
|
||||
if isPoisioned() then
|
||||
say("exana pox")
|
||||
end
|
||||
if isPzLocked() then
|
||||
delay(8000)
|
||||
end
|
||||
return "retry"
|
||||
end
|
||||
]])
|
||||
|
||||
addExampleFunction("Check for stamina and imbues", [[
|
||||
if stamina() < 900 or player:getSkillLevel(11) == 0 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"
|
||||
]])
|
||||
|
||||
addExampleFunction("Close Loot Containers", [[
|
||||
CaveBot.CloseAllLootContainers()
|
||||
delay(3000)
|
||||
return true
|
||||
]])
|
||||
@@ -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
|
||||
119
modules/game_bot/default_configs/vBot_4.7/cavebot/imbuing.lua
Normal file
119
modules/game_bot/default_configs/vBot_4.7/cavebot/imbuing.lua
Normal file
@@ -0,0 +1,119 @@
|
||||
-- imbuing window should be handled separatly
|
||||
-- reequiping should be handled separatly (ie. equipment manager)
|
||||
|
||||
CaveBot.Extensions.Imbuing = {}
|
||||
|
||||
local SHRINES = {25060, 25061, 25182, 25183}
|
||||
local currentIndex = 1
|
||||
local shrine = nil
|
||||
local item = nil
|
||||
local currentId = 0
|
||||
local triedToTakeOff = false
|
||||
local destination = nil
|
||||
|
||||
local function reset()
|
||||
EquipManager.setOn()
|
||||
shrine = nil
|
||||
currentIndex = 1
|
||||
item = nil
|
||||
currentId = 0
|
||||
triedToTakeOff = false
|
||||
destination = nil
|
||||
end
|
||||
|
||||
CaveBot.Extensions.Imbuing.setup = function()
|
||||
CaveBot.registerAction("imbuing", "red", function(value, retries)
|
||||
local data = string.split(value, ",")
|
||||
local ids = {}
|
||||
|
||||
if #data == 0 and value ~= 'name' then
|
||||
warn("CaveBot[Imbuing] no items added, proceeding")
|
||||
reset()
|
||||
return false
|
||||
end
|
||||
|
||||
-- setting of equipment manager so it wont disturb imbuing process
|
||||
EquipManager.setOff()
|
||||
|
||||
if value == 'name' then
|
||||
local imbuData = AutoImbueTable[player:getName()]
|
||||
for id, imbues in pairs(imbuData) do
|
||||
table.insert(ids, id)
|
||||
end
|
||||
else
|
||||
-- convert to number
|
||||
for i, id in ipairs(data) do
|
||||
id = tonumber(id)
|
||||
if not table.find(ids, id) then
|
||||
table.insert(ids, id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- all items imbued, can proceed
|
||||
if currentIndex > #ids then
|
||||
warn("CaveBot[Imbuing] used shrine on all items, proceeding")
|
||||
reset()
|
||||
return true
|
||||
end
|
||||
|
||||
for _, tile in ipairs(g_map.getTiles(posz())) do
|
||||
for _, item in ipairs(tile:getItems()) do
|
||||
local id = item:getId()
|
||||
if table.find(SHRINES, id) then
|
||||
shrine = item
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- if not shrine
|
||||
if not shrine then
|
||||
warn("CaveBot[Imbuing] shrine not found! proceeding")
|
||||
reset()
|
||||
return false
|
||||
end
|
||||
|
||||
destination = shrine:getPosition()
|
||||
|
||||
currentId = ids[currentIndex]
|
||||
item = findItem(currentId)
|
||||
|
||||
-- maybe equipped? try to take off
|
||||
if not item then
|
||||
-- did try before, still not found so item is unavailable
|
||||
if triedToTakeOff then
|
||||
warn("CaveBot[Imbuing] item not found! skipping: "..currentId)
|
||||
triedToTakeOff = false
|
||||
currentIndex = currentIndex + 1
|
||||
return "retry"
|
||||
end
|
||||
triedToTakeOff = true
|
||||
g_game.equipItemId(currentId)
|
||||
delay(1000)
|
||||
return "retry"
|
||||
end
|
||||
|
||||
-- we are past unequiping so just in case we were forced before, reset var
|
||||
triedToTakeOff = false
|
||||
|
||||
-- reaching shrine
|
||||
if not CaveBot.MatchPosition(destination, 1) then
|
||||
CaveBot.GoTo(destination, 1)
|
||||
delay(200)
|
||||
return "retry"
|
||||
end
|
||||
|
||||
useWith(shrine, item)
|
||||
currentIndex = currentIndex + 1
|
||||
warn("CaveBot[Imbuing] Using shrine on item: "..currentId)
|
||||
delay(4000)
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("imbuing", "imbuing", {
|
||||
value="name",
|
||||
title="Auto Imbuing",
|
||||
description="insert below item ids to be imbued, separated by comma\nor 'name' to load from file",
|
||||
})
|
||||
end
|
||||
@@ -0,0 +1,91 @@
|
||||
CaveBot.Extensions.InWithdraw = {}
|
||||
|
||||
CaveBot.Extensions.InWithdraw.setup = function()
|
||||
CaveBot.registerAction("inwithdraw", "#002FFF", function(value, retries)
|
||||
local data = string.split(value, ",")
|
||||
local withdrawId
|
||||
local amount
|
||||
|
||||
-- validation
|
||||
if #data ~= 2 then
|
||||
warn("CaveBot[InboxWithdraw]: incorrect withdraw value")
|
||||
return false
|
||||
else
|
||||
withdrawId = tonumber(data[1])
|
||||
amount = tonumber(data[2])
|
||||
end
|
||||
|
||||
local currentAmount = itemAmount(withdrawId)
|
||||
|
||||
if currentAmount >= amount then
|
||||
print("CaveBot[InboxWithdraw]: enough items, proceeding")
|
||||
return true
|
||||
end
|
||||
|
||||
if retries > 400 then
|
||||
print("CaveBot[InboxWithdraw]: actions limit reached, proceeding")
|
||||
return true
|
||||
end
|
||||
|
||||
-- actions
|
||||
local inboxContainer = getContainerByName("your inbox")
|
||||
delay(100)
|
||||
if not inboxContainer then
|
||||
if not CaveBot.ReachAndOpenInbox() then
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
local inboxAmount = 0
|
||||
if not inboxContainer then
|
||||
return "retry"
|
||||
end
|
||||
for i, item in pairs(inboxContainer:getItems()) do
|
||||
if item:getId() == withdrawId then
|
||||
inboxAmount = inboxAmount + item:getCount()
|
||||
end
|
||||
end
|
||||
if inboxAmount == 0 then
|
||||
warn("CaveBot[InboxWithdraw]: not enough items in inbox container, proceeding")
|
||||
g_game.close(inboxContainer)
|
||||
return true
|
||||
end
|
||||
|
||||
local destination
|
||||
for i, container in pairs(getContainers()) do
|
||||
if container:getCapacity() > #container:getItems() and not string.find(container:getName():lower(), "quiver") 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 not destination then
|
||||
print("CaveBot[InboxWithdraw]: couldn't find proper destination container, skipping")
|
||||
g_game.close(inboxContainer)
|
||||
return false
|
||||
end
|
||||
|
||||
CaveBot.PingDelay(2)
|
||||
|
||||
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(), (amount - currentAmount)))
|
||||
return "retry"
|
||||
else
|
||||
g_game.move(item, destination:getSlotPosition(destination:getItemsCount()), 1)
|
||||
return "retry"
|
||||
end
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("inwithdraw", "in withdraw", {
|
||||
value="id,amount",
|
||||
title="Withdraw Items",
|
||||
description="insert item id and amount",
|
||||
})
|
||||
end
|
||||
29
modules/game_bot/default_configs/vBot_4.7/cavebot/lure.lua
Normal file
29
modules/game_bot/default_configs/vBot_4.7/cavebot/lure.lua
Normal file
@@ -0,0 +1,29 @@
|
||||
CaveBot.Extensions.Lure = {}
|
||||
|
||||
CaveBot.Extensions.Lure.setup = function()
|
||||
CaveBot.registerAction("lure", "#FF0090", function(value, retries)
|
||||
value = value:lower()
|
||||
if value == "start" then
|
||||
TargetBot.setOff()
|
||||
elseif value == "stop" then
|
||||
TargetBot.setOn()
|
||||
elseif value == "toggle" then
|
||||
if TargetBot.isOn() then
|
||||
TargetBot.setOff()
|
||||
else
|
||||
TargetBot.setOn()
|
||||
end
|
||||
else
|
||||
warn("incorrect lure value!")
|
||||
end
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("lure", "lure", {
|
||||
value="toggle",
|
||||
title="Lure",
|
||||
description="TargetBot: start, stop, toggle",
|
||||
multiline=false,
|
||||
validation=[[(start|stop|toggle)$]]
|
||||
})
|
||||
end
|
||||
@@ -0,0 +1,26 @@
|
||||
local minimap = modules.game_minimap.minimapWidget
|
||||
|
||||
minimap.onMouseRelease = function(widget,pos,button)
|
||||
if not minimap.allowNextRelease then return true end
|
||||
minimap.allowNextRelease = false
|
||||
|
||||
local mapPos = minimap:getTilePosition(pos)
|
||||
if not mapPos then return end
|
||||
|
||||
if button == 1 then
|
||||
local player = g_game.getLocalPlayer()
|
||||
if minimap.autowalk then
|
||||
player:autoWalk(mapPos)
|
||||
end
|
||||
return true
|
||||
elseif button == 2 then
|
||||
local menu = g_ui.createWidget('PopupMenu')
|
||||
menu:setId("minimapMenu")
|
||||
menu:setGameMenu(true)
|
||||
menu:addOption(tr('Create mark'), function() minimap:createFlagWindow(mapPos) end)
|
||||
menu:addOption(tr('Add CaveBot GoTo'), function() CaveBot.addAction("goto", mapPos.x .. "," .. mapPos.y .. "," .. mapPos.z, true) CaveBot.save() end)
|
||||
menu:display(pos)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
@@ -0,0 +1,47 @@
|
||||
CaveBot.Extensions.PosCheck = {}
|
||||
|
||||
local 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
|
||||
warn("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 posCheckRetries > 10 then
|
||||
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
|
||||
posCheckRetries = 0
|
||||
print("CaveBot[CheckPos]: position reached, proceeding")
|
||||
return true
|
||||
else
|
||||
posCheckRetries = posCheckRetries + 1
|
||||
if data[1] == "last" then
|
||||
CaveBot.gotoFirstPreviousReachableWaypoint()
|
||||
print("CaveBot[CheckPos]: position not-reached, going back to first reachable waypoint.")
|
||||
return false
|
||||
else
|
||||
CaveBot.gotoLabel(data[1])
|
||||
print("CaveBot[CheckPos]: position not-reached, going back to label: " .. data[1])
|
||||
return false
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("poscheck", "pos check", {
|
||||
value=function() return "last" .. "," .. "10" .. "," .. posx() .. "," .. posy() .. "," .. posz() end,
|
||||
title="Location Check",
|
||||
description="label name, accepted dist from coordinates, x, y, z",
|
||||
multiline=false,
|
||||
})
|
||||
end
|
||||
@@ -0,0 +1,69 @@
|
||||
-- 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
|
||||
local function addStairs(pos)
|
||||
CaveBot.addAction("goto", pos.x .. "," .. pos.y .. "," .. pos.z .. ",0", 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
|
||||
addStairs(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,66 @@
|
||||
CaveBot.Extensions.SellAll = {}
|
||||
|
||||
local sellAllCap = 0
|
||||
CaveBot.Extensions.SellAll.setup = function()
|
||||
CaveBot.registerAction("SellAll", "#C300FF", function(value, retries)
|
||||
local val = string.split(value, ",")
|
||||
local wait
|
||||
|
||||
-- table formatting
|
||||
for i, v in ipairs(val) do
|
||||
v = v:trim()
|
||||
v = tonumber(v) or v
|
||||
val[i] = v
|
||||
end
|
||||
|
||||
if table.find(val, "yes", true) then
|
||||
wait = true
|
||||
end
|
||||
|
||||
local npcName = val[1]
|
||||
local npc = getCreatureByName(npcName)
|
||||
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() == sellAllCap then
|
||||
sellAllCap = 0
|
||||
print("CaveBot[SellAll]: Sold everything, proceeding")
|
||||
return true
|
||||
end
|
||||
|
||||
delay(800)
|
||||
if not CaveBot.ReachNPC(npcName) then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
if not NPC.isTrading() then
|
||||
CaveBot.OpenNpcTrade()
|
||||
delay(storage.extras.talkDelay*2)
|
||||
return "retry"
|
||||
else
|
||||
sellAllCap = freecap()
|
||||
end
|
||||
|
||||
modules.game_npctrade.sellAll(wait, val)
|
||||
if wait 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="NPC Name, 'yes' if sell with delay, exceptions: id separated by comma",
|
||||
})
|
||||
end
|
||||
186
modules/game_bot/default_configs/vBot_4.7/cavebot/stand_lure.lua
Normal file
186
modules/game_bot/default_configs/vBot_4.7/cavebot/stand_lure.lua
Normal file
@@ -0,0 +1,186 @@
|
||||
CaveBot.Extensions.StandLure = {}
|
||||
local enable = nil
|
||||
|
||||
local function modPos(dir)
|
||||
local y = 0
|
||||
local x = 0
|
||||
|
||||
if dir == 0 then
|
||||
y = -1
|
||||
elseif dir == 1 then
|
||||
x = 1
|
||||
elseif dir == 2 then
|
||||
y = 1
|
||||
elseif dir == 3 then
|
||||
x = -1
|
||||
elseif dir == 4 then
|
||||
y = -1
|
||||
x = 1
|
||||
elseif dir == 5 then
|
||||
y = 1
|
||||
x = 1
|
||||
elseif dir == 6 then
|
||||
y = 1
|
||||
x = -1
|
||||
elseif dir == 7 then
|
||||
y = -1
|
||||
x = -1
|
||||
end
|
||||
|
||||
return {x, y}
|
||||
end
|
||||
local function reset(delay)
|
||||
if type(Supplies.hasEnough()) == 'table' then
|
||||
return
|
||||
end
|
||||
delay = delay or 0
|
||||
CaveBot.delay(delay)
|
||||
if delay == nil then
|
||||
enable = nil
|
||||
end
|
||||
end
|
||||
|
||||
local resetRetries = false
|
||||
CaveBot.Extensions.StandLure.setup = function()
|
||||
CaveBot.registerAction(
|
||||
"rushlure",
|
||||
"#FF0090",
|
||||
function(value, retries)
|
||||
local nextPos = nil
|
||||
local data = string.split(value, ",")
|
||||
if not data[1] then
|
||||
warn("Invalid cavebot lure action value. It should be position (x,y,z), delay(ms) is: " .. value)
|
||||
return false
|
||||
end
|
||||
|
||||
if type(Supplies.hasEnough()) == 'table' then -- do not execute if no supplies
|
||||
return false
|
||||
end
|
||||
|
||||
local pos = {x = tonumber(data[1]), y = tonumber(data[2]), z = tonumber(data[3])}
|
||||
|
||||
local delayTime = data[4] and tonumber(data[4]) or 1000
|
||||
if not data[5] then
|
||||
enable = nil
|
||||
elseif data[5] == "yes" then
|
||||
enable = true
|
||||
else
|
||||
enable = false
|
||||
end
|
||||
|
||||
delay(100)
|
||||
|
||||
if retries > 50 and not resetRetries then
|
||||
reset()
|
||||
warn("[Rush Lure] Too many tries, can't reach position")
|
||||
return false -- can't stand on tile
|
||||
end
|
||||
|
||||
if resetRetries then
|
||||
resetRetries = false
|
||||
end
|
||||
|
||||
if distanceFromPlayer(pos) > 30 then
|
||||
reset()
|
||||
return false -- not reachable
|
||||
end
|
||||
|
||||
local playerPos = player:getPosition()
|
||||
local pathWithoutMonsters = findPath(playerPos, pos, 30, { ignoreFields = true, ignoreNonPathable = true, ignoreCreatures = true, precision = 0})
|
||||
local pathWithMonsters = findPath(playerPos, pos, maxDist, { ignoreFields = true, ignoreNonPathable = true, ignoreCreatures = false, precision = 0 })
|
||||
|
||||
if not pathWithoutMonsters then
|
||||
reset()
|
||||
warn("[Rush Lure] No possible path to reach position, skipping.")
|
||||
return false -- spot is unreachable
|
||||
elseif pathWithoutMonsters and not pathWithMonsters then
|
||||
local foundMonster = false
|
||||
for i, dir in ipairs(pathWithoutMonsters) do
|
||||
local dirs = modPos(dir)
|
||||
nextPos = nextPos or playerPos
|
||||
nextPos.x = nextPos.x + dirs[1]
|
||||
nextPos.y = nextPos.y + dirs[2]
|
||||
|
||||
|
||||
local tile = g_map.getTile(nextPos)
|
||||
if tile then
|
||||
if tile:hasCreature() then
|
||||
local creature = tile:getCreatures()[1]
|
||||
local hppc = creature:getHealthPercent()
|
||||
if creature:isMonster() and (hppc and hppc > 0) and (oldTibia or creature:getType() < 3) then
|
||||
-- real blocking creature can not meet those conditions - ie. it could be player, so just in case check if the next creature is reachable
|
||||
local path = findPath(playerPos, creature:getPosition(), 7, { ignoreNonPathable = true, precision = 1 })
|
||||
if path then
|
||||
creature:setMarked('#00FF00')
|
||||
if g_game.getAttackingCreature() ~= creature then
|
||||
attack(creature)
|
||||
end
|
||||
g_game.setChaseMode(1)
|
||||
resetRetries = true -- reset retries, we are trying to unclog the cavebot
|
||||
delay(100)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not g_game.getAttackingCreature() then
|
||||
reset()
|
||||
warn("[Rush Lure] No path, no blocking monster, skipping.")
|
||||
return false -- no other way
|
||||
end
|
||||
end
|
||||
|
||||
-- reaching position, delay targetbot in process
|
||||
if not CaveBot.MatchPosition(pos, 0) then
|
||||
TargetBot.delay(300)
|
||||
CaveBot.walkTo(pos, 30, { ignoreCreatures = false, ignoreFields = true, ignoreNonPathable = true, precision = 0})
|
||||
delay(100)
|
||||
resetRetries = true
|
||||
return "retry"
|
||||
end
|
||||
|
||||
TargetBot.setOn()
|
||||
reset(delayTime)
|
||||
return true
|
||||
end
|
||||
)
|
||||
|
||||
CaveBot.Editor.registerAction(
|
||||
"rushlure",
|
||||
"rush lure",
|
||||
{
|
||||
value = function()
|
||||
return posx() .. "," .. posy() .. "," .. posz() .. ",1000"
|
||||
end,
|
||||
title = "Stand Lure",
|
||||
description = "Run to position(x,y,z), delay(ms), targetbot on/off (yes/no)",
|
||||
multiline = false,
|
||||
validation = [[\d{1,5},\d{1,5},\d{1,2},\d{1,5}(?:,(yes|no)$|$)]]
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
local next = false
|
||||
schedule(5, function() -- delay because cavebot.lua is loaded after this file
|
||||
modules.game_bot.connect(CaveBotList(), {
|
||||
onChildFocusChange = function(widget, newChild, oldChild)
|
||||
|
||||
if oldChild and oldChild.action == "rushlure" then
|
||||
next = true
|
||||
return
|
||||
end
|
||||
|
||||
if next then
|
||||
if enable then
|
||||
TargetBot.setOn()
|
||||
elseif enable == false then
|
||||
TargetBot.setOff()
|
||||
end
|
||||
|
||||
enable = nil -- reset
|
||||
next = false
|
||||
end
|
||||
end})
|
||||
end)
|
||||
@@ -0,0 +1,137 @@
|
||||
CaveBot.Extensions.SupplyCheck = {}
|
||||
|
||||
local supplyRetries = 0
|
||||
local missedChecks = 0
|
||||
local rawRound = 0
|
||||
local time = now
|
||||
vBot.CaveBotData =
|
||||
vBot.CaveBotData or
|
||||
{
|
||||
refills = 0,
|
||||
rounds = 0,
|
||||
time = {},
|
||||
lastRefill = os.time(),
|
||||
refillTime = {}
|
||||
}
|
||||
|
||||
local function setCaveBotData(hunting)
|
||||
if hunting then
|
||||
supplyRetries = supplyRetries + 1
|
||||
else
|
||||
supplyRetries = 0
|
||||
table.insert(vBot.CaveBotData.refillTime, os.difftime(os.time() - vBot.CaveBotData.lastRefill))
|
||||
vBot.CaveBotData.lastRefill = os.time()
|
||||
vBot.CaveBotData.refills = vBot.CaveBotData.refills + 1
|
||||
end
|
||||
|
||||
table.insert(vBot.CaveBotData.time, rawRound)
|
||||
vBot.CaveBotData.rounds = vBot.CaveBotData.rounds + 1
|
||||
missedChecks = 0
|
||||
end
|
||||
|
||||
CaveBot.Extensions.SupplyCheck.setup = function()
|
||||
CaveBot.registerAction(
|
||||
"supplyCheck",
|
||||
"#db5a5a",
|
||||
function(value)
|
||||
local data = string.split(value, ",")
|
||||
local round = 0
|
||||
rawRound = 0
|
||||
local label = data[1]:trim()
|
||||
local pos = nil
|
||||
if #data == 4 then
|
||||
pos = {x = tonumber(data[2]), y = tonumber(data[3]), z = tonumber(data[4])}
|
||||
end
|
||||
|
||||
if pos then
|
||||
if missedChecks >= 4 then
|
||||
missedChecks = 0
|
||||
supplyRetries = 0
|
||||
print("CaveBot[SupplyCheck]: Missed 5 supply checks, proceeding with waypoints")
|
||||
return true
|
||||
end
|
||||
if getDistanceBetween(player:getPosition(), pos) > 10 then
|
||||
missedChecks = missedChecks + 1
|
||||
print("CaveBot[SupplyCheck]: Missed supply check! " .. 5 - missedChecks .. " tries left before skipping.")
|
||||
return CaveBot.gotoLabel(label)
|
||||
end
|
||||
end
|
||||
|
||||
if time then
|
||||
rawRound = math.ceil((now - time) / 1000)
|
||||
round = rawRound .. "s"
|
||||
else
|
||||
round = ""
|
||||
end
|
||||
time = now
|
||||
|
||||
local softCount = itemAmount(6529) + itemAmount(3549)
|
||||
local supplyData = Supplies.hasEnough()
|
||||
local supplyInfo = Supplies.getAdditionalData()
|
||||
|
||||
if storage.caveBot.forceRefill then
|
||||
print("CaveBot[SupplyCheck]: User forced, going back on refill. Last round took: " .. round)
|
||||
storage.caveBot.forceRefill = false
|
||||
supplyRetries = 0
|
||||
missedChecks = 0
|
||||
return false
|
||||
elseif storage.caveBot.backStop then
|
||||
print("CaveBot[SupplyCheck]: User forced, going back to city and turning off CaveBot. Last round took: " .. round)
|
||||
supplyRetries = 0
|
||||
missedChecks = 0
|
||||
return false
|
||||
elseif storage.caveBot.backTrainers then
|
||||
print("CaveBot[SupplyCheck]: User forced, going back to city, then on trainers. Last round took: " .. round)
|
||||
supplyRetries = 0
|
||||
missedChecks = 0
|
||||
return false
|
||||
elseif storage.caveBot.backOffline then
|
||||
print("CaveBot[SupplyCheck]: User forced, going back to city, then on offline training. Last round took: " .. round)
|
||||
supplyRetries = 0
|
||||
missedChecks = 0
|
||||
return false
|
||||
elseif supplyRetries > (storage.extras.huntRoutes or 50) then
|
||||
print("CaveBot[SupplyCheck]: Round limit reached, going back on refill. Last round took: " .. round)
|
||||
setCaveBotData()
|
||||
return false
|
||||
elseif (supplyInfo.imbues.enabled and player:getSkillLevel(11) == 0) then
|
||||
print("CaveBot[SupplyCheck]: Imbues ran out. Going on refill. Last round took: " .. round)
|
||||
setCaveBotData()
|
||||
return false
|
||||
elseif (supplyInfo.stamina.enabled and stamina() < tonumber(supplyInfo.stamina.value)) then
|
||||
print("CaveBot[SupplyCheck]: Stamina ran out. Going on refill. Last round took: " .. round)
|
||||
setCaveBotData()
|
||||
return false
|
||||
elseif (supplyInfo.softBoots.enabled and softCount < 1) then
|
||||
print("CaveBot[SupplyCheck]: No soft boots left. Going on refill. Last round took: " .. round)
|
||||
setCaveBotData()
|
||||
return false
|
||||
elseif type(supplyData) == "table" then
|
||||
print("CaveBot[SupplyCheck]: Not enough item: " .. supplyData.id .. "(only " .. supplyData.amount .. " left). Going on refill. Last round took: " .. round)
|
||||
setCaveBotData()
|
||||
return false
|
||||
elseif (supplyInfo.capacity.enabled and freecap() < tonumber(supplyInfo.capacity.value)) then
|
||||
print("CaveBot[SupplyCheck]: Not enough capacity. Going on refill. Last round took: " .. round)
|
||||
setCaveBotData()
|
||||
return false
|
||||
else
|
||||
print("CaveBot[SupplyCheck]: Enough supplies. Hunting. Round (" .. supplyRetries .. "/" .. (storage.extras.huntRoutes or 50) .. "). Last round took: " .. round)
|
||||
setCaveBotData(true)
|
||||
return CaveBot.gotoLabel(label)
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
CaveBot.Editor.registerAction(
|
||||
"supplycheck",
|
||||
"supply check",
|
||||
{
|
||||
value = function()
|
||||
return "startHunt," .. posx() .. "," .. posy() .. "," .. posz()
|
||||
end,
|
||||
title = "Supply check label",
|
||||
description = "Insert here hunting start label",
|
||||
validation = [[[^,]+,\d{1,5},\d{1,5},\d{1,2}$]]
|
||||
}
|
||||
)
|
||||
end
|
||||
178
modules/game_bot/default_configs/vBot_4.7/cavebot/tasker.lua
Normal file
178
modules/game_bot/default_configs/vBot_4.7/cavebot/tasker.lua
Normal file
@@ -0,0 +1,178 @@
|
||||
CaveBot.Extensions.Tasker = {}
|
||||
|
||||
local dataValidationFailed = function()
|
||||
print("CaveBot[Tasker]: data validation failed! incorrect data, check cavebot/tasker for more info")
|
||||
return false
|
||||
end
|
||||
|
||||
-- miniconfig
|
||||
local talkDelay = storage.extras.talkDelay
|
||||
if not storage.caveBotTasker then
|
||||
storage.caveBotTasker = {
|
||||
inProgress = false,
|
||||
monster = "",
|
||||
taskName = "",
|
||||
count = 0,
|
||||
max = 0
|
||||
}
|
||||
end
|
||||
|
||||
local resetTaskData = function()
|
||||
storage.caveBotTasker.inProgress = false
|
||||
storage.caveBotTasker.monster = ""
|
||||
storage.caveBotTasker.monster2 = ""
|
||||
storage.caveBotTasker.taskName = ""
|
||||
storage.caveBotTasker.count = 0
|
||||
storage.caveBotTasker.max = 0
|
||||
end
|
||||
|
||||
CaveBot.Extensions.Tasker.setup = function()
|
||||
CaveBot.registerAction("Tasker", "#FF0090", function(value, retries)
|
||||
local taskName = ""
|
||||
local monster = ""
|
||||
local monster2 = ""
|
||||
local count = 0
|
||||
local label1 = ""
|
||||
local label2 = ""
|
||||
local task
|
||||
|
||||
local data = string.split(value, ",")
|
||||
if not data or #data < 1 then
|
||||
dataValidationFailed()
|
||||
end
|
||||
local marker = tonumber(data[1])
|
||||
|
||||
if not marker then
|
||||
dataValidationFailed()
|
||||
resetTaskData()
|
||||
elseif marker == 1 then
|
||||
if getNpcs(3) == 0 then
|
||||
print("CaveBot[Tasker]: no NPC found in range! skipping")
|
||||
return false
|
||||
end
|
||||
if #data ~= 4 and #data ~= 5 then
|
||||
dataValidationFailed()
|
||||
resetTaskData()
|
||||
else
|
||||
taskName = data[2]:lower():trim()
|
||||
count = tonumber(data[3]:trim())
|
||||
monster = data[4]:lower():trim()
|
||||
if #data == 5 then
|
||||
monster2 = data[5]:lower():trim()
|
||||
end
|
||||
end
|
||||
elseif marker == 2 then
|
||||
if #data ~= 3 then
|
||||
dataValidationFailed()
|
||||
else
|
||||
label1 = data[2]:lower():trim()
|
||||
label2 = data[3]:lower():trim()
|
||||
end
|
||||
elseif marker == 3 then
|
||||
if getNpcs(3) == 0 then
|
||||
print("CaveBot[Tasker]: no NPC found in range! skipping")
|
||||
return false
|
||||
end
|
||||
if #data ~= 1 then
|
||||
dataValidationFailed()
|
||||
end
|
||||
end
|
||||
|
||||
-- let's cover markers now
|
||||
if marker == 1 then -- starting task
|
||||
CaveBot.Conversation("hi", "task", taskName, "yes")
|
||||
delay(talkDelay*4)
|
||||
|
||||
storage.caveBotTasker.monster = monster
|
||||
if monster2 then storage.caveBotTasker.monster2 = monster2 end
|
||||
storage.caveBotTasker.taskName = taskName
|
||||
storage.caveBotTasker.inProgress = true
|
||||
storage.caveBotTasker.max = count
|
||||
storage.caveBotTasker.count = 0
|
||||
|
||||
print("CaveBot[Tasker]: taken task for: " .. monster .. " x" .. count)
|
||||
return true
|
||||
elseif marker == 2 then -- only checking
|
||||
if not storage.caveBotTasker.inProgress then
|
||||
CaveBot.gotoLabel(label2)
|
||||
print("CaveBot[Tasker]: there is no task in progress so going to take one.")
|
||||
return true
|
||||
end
|
||||
|
||||
local max = storage.caveBotTasker.max
|
||||
local count = storage.caveBotTasker.count
|
||||
|
||||
if count >= max then
|
||||
CaveBot.gotoLabel(label2)
|
||||
print("CaveBot[Tasker]: task completed: " .. storage.caveBotTasker.taskName)
|
||||
return true
|
||||
else
|
||||
CaveBot.gotoLabel(label1)
|
||||
print("CaveBot[Tasker]: task in progress, left: " .. max - count .. " " .. storage.caveBotTasker.taskName)
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
elseif marker == 3 then -- reporting task
|
||||
CaveBot.Conversation("hi", "report", "task")
|
||||
delay(talkDelay*3)
|
||||
|
||||
resetTaskData()
|
||||
print("CaveBot[Tasker]: task reported, done")
|
||||
return true
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("tasker", "tasker", {
|
||||
value=[[ There is 3 scenarios for this extension, as example we will use medusa:
|
||||
|
||||
1. start task,
|
||||
parameters:
|
||||
- scenario for extension: 1
|
||||
- task name in gryzzly adams: medusae
|
||||
- monster count: 500
|
||||
- monster name to track: medusa
|
||||
- optional, monster name 2:
|
||||
2. check status,
|
||||
to be used on refill to decide whether to go back or spawn or go give task back
|
||||
parameters:
|
||||
- scenario for extension: 2
|
||||
- label if task in progress: skipTask
|
||||
- label if task done: taskDone
|
||||
3. report task,
|
||||
parameters:
|
||||
- scenario for extension: 3
|
||||
|
||||
Strong suggestion, almost mandatory - USE POS CHECK to verify position! this module will only check if there is ANY npc in range!
|
||||
|
||||
when begin remove all the text and leave just a single string of parameters
|
||||
some examples:
|
||||
|
||||
2, skipReport, goReport
|
||||
3
|
||||
1, drakens, 500, draken warmaster, draken spellweaver
|
||||
1, medusae, 500, medusa]],
|
||||
title="Tasker",
|
||||
multiline = true
|
||||
})
|
||||
end
|
||||
|
||||
local regex = "Loot of ([a-z])* ([a-z A-Z]*):"
|
||||
local regex2 = "Loot of ([a-z A-Z]*):"
|
||||
onTextMessage(function(mode, text)
|
||||
-- if CaveBot.isOff() then return end
|
||||
if not text:lower():find("loot of") then return end
|
||||
if #regexMatch(text, regex) == 1 and #regexMatch(text, regex)[1] == 3 then
|
||||
monster = regexMatch(text, regex)[1][3]
|
||||
elseif #regexMatch(text, regex2) == 1 and #regexMatch(text, regex2)[1] == 2 then
|
||||
monster = regexMatch(text, regex2)[1][2]
|
||||
end
|
||||
|
||||
local m1 = storage.caveBotTasker.monster
|
||||
local m2 = storage.caveBotTasker.monster2
|
||||
|
||||
if monster == m1 or monster == m2 and storage.caveBotTasker.count then
|
||||
storage.caveBotTasker.count = storage.caveBotTasker.count + 1
|
||||
end
|
||||
end)
|
||||
40
modules/game_bot/default_configs/vBot_4.7/cavebot/travel.lua
Normal file
40
modules/game_bot/default_configs/vBot_4.7/cavebot/travel.lua
Normal file
@@ -0,0 +1,40 @@
|
||||
CaveBot.Extensions.Travel = {}
|
||||
|
||||
CaveBot.Extensions.Travel.setup = function()
|
||||
CaveBot.registerAction("Travel", "#db5a5a", function(value, retries)
|
||||
local data = string.split(value, ",")
|
||||
if #data < 2 then
|
||||
warn("CaveBot[Travel]: incorrect travel value!")
|
||||
return false
|
||||
end
|
||||
|
||||
local npcName = data[1]:trim()
|
||||
local dest = data[2]:trim()
|
||||
|
||||
if retries > 5 then
|
||||
print("CaveBot[Travel]: too many tries, can't travel")
|
||||
return false
|
||||
end
|
||||
|
||||
local npc = getCreatureByName(npcName)
|
||||
if not npc then
|
||||
print("CaveBot[Travel]: NPC not found, can't travel")
|
||||
return false
|
||||
end
|
||||
|
||||
if not CaveBot.ReachNPC(npcName) then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
CaveBot.Travel(dest)
|
||||
delay(storage.extras.talkDelay*3)
|
||||
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(default is 200ms)",
|
||||
})
|
||||
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,56 @@
|
||||
CaveBot.Extensions.Withdraw = {}
|
||||
|
||||
CaveBot.Extensions.Withdraw.setup = function()
|
||||
CaveBot.registerAction("withdraw", "#002FFF", function(value, retries)
|
||||
-- validation
|
||||
local data = string.split(value, ",")
|
||||
if #data ~= 3 then
|
||||
print("CaveBot[Withdraw]: incorrect data! skipping")
|
||||
return false
|
||||
end
|
||||
|
||||
-- variables declaration
|
||||
local source = tonumber(data[1])
|
||||
local id = tonumber(data[2])
|
||||
local amount = tonumber(data[3])
|
||||
|
||||
-- validation for correct values
|
||||
if not id or not amount then
|
||||
print("CaveBot[Withdraw]: incorrect id or amount! skipping")
|
||||
return false
|
||||
end
|
||||
|
||||
-- check for retries
|
||||
if retries > 100 then
|
||||
print("CaveBot[Withdraw]: actions limit reached, proceeding")
|
||||
for i, container in ipairs(getContainers()) do
|
||||
if container:getName():lower():find("depot") or container:getName():lower():find("locker") then
|
||||
g_game.close(container)
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- check for items
|
||||
if itemAmount(id) >= amount then
|
||||
print("CaveBot[Withdraw]: enough items, proceeding")
|
||||
for i, container in ipairs(getContainers()) do
|
||||
if container:getName():lower():find("depot") or container:getName():lower():find("locker") then
|
||||
g_game.close(container)
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
statusMessage("[Withdraw] withdrawing item: " ..id.. " x"..amount)
|
||||
CaveBot.WithdrawItem(id, amount, source)
|
||||
CaveBot.PingDelay()
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("withdraw", "withdraw", {
|
||||
value="source,id,amount",
|
||||
title="Withdraw Items",
|
||||
description="index/inbox, item id and amount",
|
||||
})
|
||||
end
|
||||
@@ -0,0 +1,99 @@
|
||||
|
||||
TargetBot.Creature = {}
|
||||
TargetBot.Creature.configsCache = {}
|
||||
TargetBot.Creature.cached = 0
|
||||
|
||||
TargetBot.Creature.resetConfigs = function()
|
||||
TargetBot.targetList:destroyChildren()
|
||||
TargetBot.Creature.resetConfigsCache()
|
||||
end
|
||||
|
||||
TargetBot.Creature.resetConfigsCache = function()
|
||||
TargetBot.Creature.configsCache = {}
|
||||
TargetBot.Creature.cached = 0
|
||||
end
|
||||
|
||||
TargetBot.Creature.addConfig = function(config, focus)
|
||||
if type(config) ~= 'table' or type(config.name) ~= 'string' then
|
||||
return error("Invalid targetbot creature config (missing name)")
|
||||
end
|
||||
TargetBot.Creature.resetConfigsCache()
|
||||
|
||||
if not config.regex then
|
||||
config.regex = ""
|
||||
for part in string.gmatch(config.name, "[^,]+") do
|
||||
if config.regex:len() > 0 then
|
||||
config.regex = config.regex .. "|"
|
||||
end
|
||||
config.regex = config.regex .. "^" .. part:trim():lower():gsub("%*", ".*"):gsub("%?", ".?") .. "$"
|
||||
end
|
||||
end
|
||||
|
||||
local widget = UI.createWidget("TargetBotEntry", TargetBot.targetList)
|
||||
widget:setText(config.name)
|
||||
widget.value = config
|
||||
|
||||
widget.onDoubleClick = function(entry) -- edit on double click
|
||||
schedule(20, function() -- schedule to have correct focus
|
||||
TargetBot.Creature.edit(entry.value, function(newConfig)
|
||||
entry:setText(newConfig.name)
|
||||
entry.value = newConfig
|
||||
TargetBot.Creature.resetConfigsCache()
|
||||
TargetBot.save()
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
if focus then
|
||||
widget:focus()
|
||||
TargetBot.targetList:ensureChildVisible(widget)
|
||||
end
|
||||
return widget
|
||||
end
|
||||
|
||||
TargetBot.Creature.getConfigs = function(creature)
|
||||
if not creature then return {} end
|
||||
local name = creature:getName():trim():lower()
|
||||
-- this function may be slow, so it will be using cache
|
||||
if TargetBot.Creature.configsCache[name] then
|
||||
return TargetBot.Creature.configsCache[name]
|
||||
end
|
||||
local configs = {}
|
||||
for _, config in ipairs(TargetBot.targetList:getChildren()) do
|
||||
if regexMatch(name, config.value.regex)[1] then
|
||||
table.insert(configs, config.value)
|
||||
end
|
||||
end
|
||||
if TargetBot.Creature.cached > 1000 then
|
||||
TargetBot.Creature.resetConfigsCache() -- too big cache size, reset
|
||||
end
|
||||
TargetBot.Creature.configsCache[name] = configs -- add to cache
|
||||
TargetBot.Creature.cached = TargetBot.Creature.cached + 1
|
||||
return configs
|
||||
end
|
||||
|
||||
TargetBot.Creature.calculateParams = function(creature, path)
|
||||
local configs = TargetBot.Creature.getConfigs(creature)
|
||||
local priority = 0
|
||||
local danger = 0
|
||||
local selectedConfig = nil
|
||||
for _, config in ipairs(configs) do
|
||||
local config_priority = TargetBot.Creature.calculatePriority(creature, config, path)
|
||||
if config_priority > priority then
|
||||
priority = config_priority
|
||||
danger = TargetBot.Creature.calculateDanger(creature, config, path)
|
||||
selectedConfig = config
|
||||
end
|
||||
end
|
||||
return {
|
||||
config = selectedConfig,
|
||||
creature = creature,
|
||||
danger = danger,
|
||||
priority = priority
|
||||
}
|
||||
end
|
||||
|
||||
TargetBot.Creature.calculateDanger = function(creature, config, path)
|
||||
-- config is based on creature_editor
|
||||
return config.danger
|
||||
end
|
||||
@@ -0,0 +1,245 @@
|
||||
local targetBotLure = false
|
||||
local targetCount = 0
|
||||
local delayValue = 0
|
||||
local lureMax = 0
|
||||
local anchorPosition = nil
|
||||
local lastCall = now
|
||||
local delayFrom = nil
|
||||
local dynamicLureDelay = false
|
||||
|
||||
function getWalkableTilesCount(position)
|
||||
local count = 0
|
||||
|
||||
for i, tile in pairs(getNearTiles(position)) do
|
||||
if tile:isWalkable() or tile:hasCreature() then
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
function rePosition(minTiles)
|
||||
minTiles = minTiles or 8
|
||||
if now - lastCall < 500 then return end
|
||||
local pPos = player:getPosition()
|
||||
local tiles = getNearTiles(pPos)
|
||||
local playerTilesCount = getWalkableTilesCount(pPos)
|
||||
local tilesTable = {}
|
||||
|
||||
if playerTilesCount > minTiles then return end
|
||||
for i, tile in ipairs(tiles) do
|
||||
tilesTable[tile] = not tile:hasCreature() and tile:isWalkable() and getWalkableTilesCount(tile:getPosition()) or nil
|
||||
end
|
||||
|
||||
local best = 0
|
||||
local target = nil
|
||||
for k,v in pairs(tilesTable) do
|
||||
if v > best and v > playerTilesCount then
|
||||
best = v
|
||||
target = k:getPosition()
|
||||
end
|
||||
end
|
||||
|
||||
if target then
|
||||
lastCall = now
|
||||
return CaveBot.GoTo(target, 0)
|
||||
end
|
||||
end
|
||||
|
||||
TargetBot.Creature.attack = function(params, targets, isLooting) -- params {config, creature, danger, priority}
|
||||
if player:isWalking() then
|
||||
lastWalk = now
|
||||
end
|
||||
|
||||
local config = params.config
|
||||
local creature = params.creature
|
||||
|
||||
if g_game.getAttackingCreature() ~= creature then
|
||||
g_game.attack(creature)
|
||||
end
|
||||
|
||||
if not isLooting then -- walk only when not looting
|
||||
TargetBot.Creature.walk(creature, config, targets)
|
||||
end
|
||||
|
||||
-- attacks
|
||||
local mana = player:getMana()
|
||||
if config.useGroupAttack and config.groupAttackSpell:len() > 1 and mana > config.minManaGroup then
|
||||
local creatures = g_map.getSpectatorsInRange(player:getPosition(), false, config.groupAttackRadius, config.groupAttackRadius)
|
||||
local playersAround = false
|
||||
local monsters = 0
|
||||
for _, creature in ipairs(creatures) do
|
||||
if not creature:isLocalPlayer() and creature:isPlayer() and (not config.groupAttackIgnoreParty or creature:getShield() <= 2) then
|
||||
playersAround = true
|
||||
elseif creature:isMonster() then
|
||||
monsters = monsters + 1
|
||||
end
|
||||
end
|
||||
if monsters >= config.groupAttackTargets and (not playersAround or config.groupAttackIgnorePlayers) then
|
||||
if TargetBot.sayAttackSpell(config.groupAttackSpell, config.groupAttackDelay) then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if config.useGroupAttackRune and config.groupAttackRune > 100 then
|
||||
local creatures = g_map.getSpectatorsInRange(creature:getPosition(), false, config.groupRuneAttackRadius, config.groupRuneAttackRadius)
|
||||
local playersAround = false
|
||||
local monsters = 0
|
||||
for _, creature in ipairs(creatures) do
|
||||
if not creature:isLocalPlayer() and creature:isPlayer() and (not config.groupAttackIgnoreParty or creature:getShield() <= 2) then
|
||||
playersAround = true
|
||||
elseif creature:isMonster() then
|
||||
monsters = monsters + 1
|
||||
end
|
||||
end
|
||||
if monsters >= config.groupRuneAttackTargets and (not playersAround or config.groupAttackIgnorePlayers) then
|
||||
if TargetBot.useAttackItem(config.groupAttackRune, 0, creature, config.groupRuneAttackDelay) then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
if config.useSpellAttack and config.attackSpell:len() > 1 and mana > config.minMana then
|
||||
if TargetBot.sayAttackSpell(config.attackSpell, config.attackSpellDelay) then
|
||||
return
|
||||
end
|
||||
end
|
||||
if config.useRuneAttack and config.attackRune > 100 then
|
||||
if TargetBot.useAttackItem(config.attackRune, 0, creature, config.attackRuneDelay) then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
TargetBot.Creature.walk = function(creature, config, targets)
|
||||
local cpos = creature:getPosition()
|
||||
local pos = player:getPosition()
|
||||
|
||||
local isTrapped = true
|
||||
local pos = player:getPosition()
|
||||
local dirs = {{-1,1}, {0,1}, {1,1}, {-1, 0}, {1, 0}, {-1, -1}, {0, -1}, {1, -1}}
|
||||
for i=1,#dirs do
|
||||
local tile = g_map.getTile({x=pos.x-dirs[i][1],y=pos.y-dirs[i][2],z=pos.z})
|
||||
if tile and tile:isWalkable(false) then
|
||||
isTrapped = false
|
||||
end
|
||||
end
|
||||
|
||||
-- data for external dynamic lure
|
||||
if config.lureMin and config.lureMax and config.dynamicLure then
|
||||
if config.lureMin >= targets then
|
||||
targetBotLure = true
|
||||
elseif targets >= config.lureMax then
|
||||
targetBotLure = false
|
||||
end
|
||||
end
|
||||
targetCount = targets
|
||||
delayValue = config.lureDelay
|
||||
|
||||
if config.lureMax then
|
||||
lureMax = config.lureMax
|
||||
end
|
||||
|
||||
dynamicLureDelay = config.dynamicLureDelay
|
||||
delayFrom = config.delayFrom
|
||||
|
||||
-- luring
|
||||
if config.closeLure and config.closeLureAmount <= getMonsters(1) then
|
||||
return TargetBot.allowCaveBot(150)
|
||||
end
|
||||
if TargetBot.canLure() and (config.lure or config.lureCavebot or config.dynamicLure) and not (creature:getHealthPercent() < (storage.extras.killUnder or 30)) and not isTrapped then
|
||||
if targetBotLure then
|
||||
anchorPosition = nil
|
||||
return TargetBot.allowCaveBot(150)
|
||||
else
|
||||
if targets < config.lureCount then
|
||||
if config.lureCavebot then
|
||||
anchorPosition = nil
|
||||
return TargetBot.allowCaveBot(150)
|
||||
else
|
||||
local path = findPath(pos, cpos, 5, {ignoreNonPathable=true, precision=2})
|
||||
if path then
|
||||
return TargetBot.walkTo(cpos, 10, {marginMin=5, marginMax=6, ignoreNonPathable=true})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local currentDistance = findPath(pos, cpos, 10, {ignoreCreatures=true, ignoreNonPathable=true, ignoreCost=true})
|
||||
if (not config.chase or #currentDistance == 1) and not config.avoidAttacks and not config.keepDistance and config.rePosition and (creature:getHealthPercent() >= storage.extras.killUnder) then
|
||||
return rePosition(config.rePositionAmount or 6)
|
||||
end
|
||||
if ((storage.extras.killUnder > 1 and (creature:getHealthPercent() < storage.extras.killUnder)) or config.chase) and not config.keepDistance then
|
||||
if #currentDistance > 1 then
|
||||
return TargetBot.walkTo(cpos, 10, {ignoreNonPathable=true, precision=1})
|
||||
end
|
||||
elseif config.keepDistance then
|
||||
if not anchorPosition or distanceFromPlayer(anchorPosition) > config.anchorRange then
|
||||
anchorPosition = pos
|
||||
end
|
||||
if #currentDistance ~= config.keepDistanceRange and #currentDistance ~= config.keepDistanceRange + 1 then
|
||||
if config.anchor and anchorPosition and getDistanceBetween(pos, anchorPosition) <= config.anchorRange*2 then
|
||||
return TargetBot.walkTo(cpos, 10, {ignoreNonPathable=true, marginMin=config.keepDistanceRange, marginMax=config.keepDistanceRange + 1, maxDistanceFrom={anchorPosition, config.anchorRange}})
|
||||
else
|
||||
return TargetBot.walkTo(cpos, 10, {ignoreNonPathable=true, marginMin=config.keepDistanceRange, marginMax=config.keepDistanceRange + 1})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--target only movement
|
||||
if config.avoidAttacks then
|
||||
local diffx = cpos.x - pos.x
|
||||
local diffy = cpos.y - pos.y
|
||||
local candidates = {}
|
||||
if math.abs(diffx) == 1 and diffy == 0 then
|
||||
candidates = {{x=pos.x, y=pos.y-1, z=pos.z}, {x=pos.x, y=pos.y+1, z=pos.z}}
|
||||
elseif diffx == 0 and math.abs(diffy) == 1 then
|
||||
candidates = {{x=pos.x-1, y=pos.y, z=pos.z}, {x=pos.x+1, y=pos.y, z=pos.z}}
|
||||
end
|
||||
for _, candidate in ipairs(candidates) do
|
||||
local tile = g_map.getTile(candidate)
|
||||
if tile and tile:isWalkable() then
|
||||
return TargetBot.walkTo(candidate, 2, {ignoreNonPathable=true})
|
||||
end
|
||||
end
|
||||
elseif config.faceMonster then
|
||||
local diffx = cpos.x - pos.x
|
||||
local diffy = cpos.y - pos.y
|
||||
local candidates = {}
|
||||
if diffx == 1 and diffy == 1 then
|
||||
candidates = {{x=pos.x+1, y=pos.y, z=pos.z}, {x=pos.x, y=pos.y-1, z=pos.z}}
|
||||
elseif diffx == -1 and diffy == 1 then
|
||||
candidates = {{x=pos.x-1, y=pos.y, z=pos.z}, {x=pos.x, y=pos.y-1, z=pos.z}}
|
||||
elseif diffx == -1 and diffy == -1 then
|
||||
candidates = {{x=pos.x, y=pos.y-1, z=pos.z}, {x=pos.x-1, y=pos.y, z=pos.z}}
|
||||
elseif diffx == 1 and diffy == -1 then
|
||||
candidates = {{x=pos.x, y=pos.y-1, z=pos.z}, {x=pos.x+1, y=pos.y, z=pos.z}}
|
||||
else
|
||||
local dir = player:getDirection()
|
||||
if diffx == 1 and dir ~= 1 then turn(1)
|
||||
elseif diffx == -1 and dir ~= 3 then turn(3)
|
||||
elseif diffy == 1 and dir ~= 2 then turn(2)
|
||||
elseif diffy == -1 and dir ~= 0 then turn(0)
|
||||
end
|
||||
end
|
||||
for _, candidate in ipairs(candidates) do
|
||||
local tile = g_map.getTile(candidate)
|
||||
if tile and tile:isWalkable() then
|
||||
return TargetBot.walkTo(candidate, 2, {ignoreNonPathable=true})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
onPlayerPositionChange(function(newPos, oldPos)
|
||||
if CaveBot.isOff() then return end
|
||||
if TargetBot.isOff() then return end
|
||||
if not lureMax then return end
|
||||
if storage.TargetBotDelayWhenPlayer then return end
|
||||
if not dynamicLureDelay then return end
|
||||
|
||||
if targetCount < (delayFrom or lureMax/2) or not target() then return end
|
||||
CaveBot.delay(delayValue or 0)
|
||||
end)
|
||||
@@ -0,0 +1,106 @@
|
||||
TargetBot.Creature.edit = function(config, callback) -- callback = function(newConfig)
|
||||
config = config or {}
|
||||
|
||||
local editor = UI.createWindow('TargetBotCreatureEditorWindow')
|
||||
local values = {} -- (key, function returning value of key)
|
||||
|
||||
editor.name:setText(config.name or "")
|
||||
table.insert(values, {"name", function() return editor.name:getText() end})
|
||||
|
||||
local addScrollBar = function(id, title, min, max, defaultValue)
|
||||
local widget = UI.createWidget('TargetBotCreatureEditorScrollBar', editor.content.left)
|
||||
widget.scroll.onValueChange = function(scroll, value)
|
||||
widget.text:setText(title .. ": " .. value)
|
||||
end
|
||||
widget.scroll:setRange(min, max)
|
||||
if max-min > 1000 then
|
||||
widget.scroll:setStep(100)
|
||||
elseif max-min > 100 then
|
||||
widget.scroll:setStep(10)
|
||||
end
|
||||
widget.scroll:setValue(config[id] or defaultValue)
|
||||
widget.scroll.onValueChange(widget.scroll, widget.scroll:getValue())
|
||||
table.insert(values, {id, function() return widget.scroll:getValue() end})
|
||||
end
|
||||
|
||||
local addTextEdit = function(id, title, defaultValue)
|
||||
local widget = UI.createWidget('TargetBotCreatureEditorTextEdit', editor.content.right)
|
||||
widget.text:setText(title)
|
||||
widget.textEdit:setText(config[id] or defaultValue or "")
|
||||
table.insert(values, {id, function() return widget.textEdit:getText() end})
|
||||
end
|
||||
|
||||
local addCheckBox = function(id, title, defaultValue)
|
||||
local widget = UI.createWidget('TargetBotCreatureEditorCheckBox', editor.content.right)
|
||||
widget.onClick = function()
|
||||
widget:setOn(not widget:isOn())
|
||||
end
|
||||
widget:setText(title)
|
||||
if config[id] == nil then
|
||||
widget:setOn(defaultValue)
|
||||
else
|
||||
widget:setOn(config[id])
|
||||
end
|
||||
table.insert(values, {id, function() return widget:isOn() end})
|
||||
end
|
||||
|
||||
local addItem = function(id, title, defaultItem)
|
||||
local widget = UI.createWidget('TargetBotCreatureEditorItem', editor.content.right)
|
||||
widget.text:setText(title)
|
||||
widget.item:setItemId(config[id] or defaultItem)
|
||||
table.insert(values, {id, function() return widget.item:getItemId() end})
|
||||
end
|
||||
|
||||
editor.cancel.onClick = function()
|
||||
editor:destroy()
|
||||
end
|
||||
editor.onEscape = editor.cancel.onClick
|
||||
|
||||
editor.ok.onClick = function()
|
||||
local newConfig = {}
|
||||
for _, value in ipairs(values) do
|
||||
newConfig[value[1]] = value[2]()
|
||||
end
|
||||
if newConfig.name:len() < 1 then return end
|
||||
|
||||
newConfig.regex = ""
|
||||
for part in string.gmatch(newConfig.name, "[^,]+") do
|
||||
if newConfig.regex:len() > 0 then
|
||||
newConfig.regex = newConfig.regex .. "|"
|
||||
end
|
||||
newConfig.regex = newConfig.regex .. "^" .. part:trim():lower():gsub("%*", ".*"):gsub("%?", ".?") .. "$"
|
||||
end
|
||||
|
||||
editor:destroy()
|
||||
callback(newConfig)
|
||||
end
|
||||
|
||||
-- values
|
||||
addScrollBar("priority", "Priority", 0, 10, 1)
|
||||
addScrollBar("danger", "Danger", 0, 10, 1)
|
||||
addScrollBar("maxDistance", "Max distance", 1, 10, 10)
|
||||
addScrollBar("keepDistanceRange", "Keep distance", 1, 5, 1)
|
||||
addScrollBar("anchorRange", "Anchoring Range", 1, 10, 3)
|
||||
addScrollBar("lureCount", "Classic Lure", 0, 5, 1)
|
||||
addScrollBar("lureMin", "Dynamic lure min", 0, 29, 1)
|
||||
addScrollBar("lureMax", "Dynamic lure max", 1, 30, 3)
|
||||
addScrollBar("lureDelay", "Dynamic lure delay", 100, 1000, 250)
|
||||
addScrollBar("delayFrom", "Start delay when monsters", 1, 29, 2)
|
||||
addScrollBar("rePositionAmount", "Min tiles to rePosition", 0, 7, 5)
|
||||
addScrollBar("closeLureAmount", "Close Pull Until", 0, 8, 3)
|
||||
|
||||
addCheckBox("chase", "Chase", true)
|
||||
addCheckBox("keepDistance", "Keep Distance", false)
|
||||
addCheckBox("anchor", "Anchoring", false)
|
||||
addCheckBox("dontLoot", "Don't loot", false)
|
||||
addCheckBox("lure", "Lure", false)
|
||||
addCheckBox("lureCavebot", "Lure using cavebot", false)
|
||||
addCheckBox("faceMonster", "Face monsters", false)
|
||||
addCheckBox("avoidAttacks", "Avoid wave attacks", false)
|
||||
addCheckBox("dynamicLure", "Dynamic lure", false)
|
||||
addCheckBox("dynamicLureDelay", "Dynamic lure delay", false)
|
||||
addCheckBox("diamondArrows", "D-Arrows priority", false)
|
||||
addCheckBox("rePosition", "rePosition to better tile", false)
|
||||
addCheckBox("closeLure", "Close Pulling Monsters", false)
|
||||
addCheckBox("rpSafe", "RP PVP SAFE - (DA)", false)
|
||||
end
|
||||
@@ -0,0 +1,164 @@
|
||||
TargetBotCreatureEditorScrollBar < Panel
|
||||
height: 28
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: text
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
|
||||
HorizontalScrollBar
|
||||
id: scroll
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
minimum: 0
|
||||
maximum: 10
|
||||
step: 1
|
||||
|
||||
TargetBotCreatureEditorTextEdit < Panel
|
||||
height: 40
|
||||
margin-top: 7
|
||||
|
||||
Label
|
||||
id: text
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
|
||||
TextEdit
|
||||
id: textEdit
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
minimum: 0
|
||||
maximum: 10
|
||||
step: 1
|
||||
|
||||
TargetBotCreatureEditorItem < Panel
|
||||
height: 34
|
||||
margin-top: 7
|
||||
margin-left: 25
|
||||
margin-right: 25
|
||||
|
||||
Label
|
||||
id: text
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: next.verticalCenter
|
||||
|
||||
BotItem
|
||||
id: item
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
|
||||
|
||||
TargetBotCreatureEditorCheckBox < BotSwitch
|
||||
height: 20
|
||||
margin-top: 7
|
||||
|
||||
TargetBotCreatureEditorWindow < MainWindow
|
||||
text: TargetBot creature editor
|
||||
width: 500
|
||||
height: 425
|
||||
|
||||
$mobile:
|
||||
height: 300
|
||||
|
||||
Label
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
!text: tr('You can use * (any characters) and ? (any character) in target name')
|
||||
|
||||
Label
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
text-align: center
|
||||
!text: tr('You can also enter multiple targets, separate them by ,')
|
||||
|
||||
TextEdit
|
||||
id: name
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-left: 90
|
||||
margin-top: 5
|
||||
|
||||
Label
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: parent.left
|
||||
text: Target name:
|
||||
|
||||
VerticalScrollBar
|
||||
id: contentScroll
|
||||
anchors.top: name.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: help.top
|
||||
step: 28
|
||||
pixels-scroll: true
|
||||
margin-right: -10
|
||||
margin-top: 5
|
||||
margin-bottom: 5
|
||||
|
||||
ScrollablePanel
|
||||
id: content
|
||||
anchors.top: name.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: help.top
|
||||
vertical-scrollbar: contentScroll
|
||||
margin-bottom: 10
|
||||
|
||||
Panel
|
||||
id: left
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
margin-top: 5
|
||||
margin-left: 10
|
||||
margin-right: 10
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
Panel
|
||||
id: right
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
margin-top: 5
|
||||
margin-left: 10
|
||||
margin-right: 10
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
Button
|
||||
id: help
|
||||
!text: tr('Help & Tutorials')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
width: 150
|
||||
@onClick: g_platform.openUrl("http://bot.otclient.ovh/")
|
||||
|
||||
Button
|
||||
id: ok
|
||||
!text: tr('Ok')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: next.left
|
||||
margin-right: 10
|
||||
width: 60
|
||||
|
||||
Button
|
||||
id: cancel
|
||||
!text: tr('Cancel')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
width: 60
|
||||
@@ -0,0 +1,61 @@
|
||||
TargetBot.Creature.calculatePriority = function(creature, config, path)
|
||||
-- config is based on creature_editor
|
||||
local priority = 0
|
||||
local currentTarget = g_game.getAttackingCreature()
|
||||
|
||||
-- extra priority if it's current target
|
||||
if currentTarget == creature then
|
||||
priority = priority + 1
|
||||
end
|
||||
|
||||
-- check if distance is ok
|
||||
if #path > config.maxDistance then
|
||||
if config.rpSafe then
|
||||
if currentTarget == creature then
|
||||
g_game.cancelAttackAndFollow() -- if not, stop attack (pvp safe)
|
||||
end
|
||||
end
|
||||
return priority
|
||||
end
|
||||
|
||||
-- add config priority
|
||||
priority = priority + config.priority
|
||||
|
||||
-- extra priority for close distance
|
||||
local path_length = #path
|
||||
if path_length == 1 then
|
||||
priority = priority + 10
|
||||
elseif path_length <= 3 then
|
||||
priority = priority + 5
|
||||
end
|
||||
|
||||
-- extra priority for paladin diamond arrows
|
||||
if config.diamondArrows then
|
||||
local mobCount = getCreaturesInArea(creature:getPosition(), diamondArrowArea, 2)
|
||||
priority = priority + (mobCount * 4)
|
||||
|
||||
if config.rpSafe then
|
||||
if getCreaturesInArea(creature:getPosition(), largeRuneArea, 3) > 0 then
|
||||
if currentTarget == creature then
|
||||
g_game.cancelAttackAndFollow()
|
||||
end
|
||||
return 0 -- pvp safe
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- extra priority for low health
|
||||
if config.chase and creature:getHealthPercent() < 30 then
|
||||
priority = priority + 5
|
||||
elseif creature:getHealthPercent() < 20 then
|
||||
priority = priority + 2.5
|
||||
elseif creature:getHealthPercent() < 40 then
|
||||
priority = priority + 1.5
|
||||
elseif creature:getHealthPercent() < 60 then
|
||||
priority = priority + 0.5
|
||||
elseif creature:getHealthPercent() < 80 then
|
||||
priority = priority + 0.2
|
||||
end
|
||||
|
||||
return priority
|
||||
end
|
||||
324
modules/game_bot/default_configs/vBot_4.7/targetbot/looting.lua
Normal file
324
modules/game_bot/default_configs/vBot_4.7/targetbot/looting.lua
Normal file
@@ -0,0 +1,324 @@
|
||||
TargetBot.Looting = {}
|
||||
TargetBot.Looting.list = {} -- list of containers to loot
|
||||
|
||||
local ui
|
||||
local items = {}
|
||||
local containers = {}
|
||||
local itemsById = {}
|
||||
local containersById = {}
|
||||
local dontSave = false
|
||||
|
||||
TargetBot.Looting.setup = function()
|
||||
ui = UI.createWidget("TargetBotLootingPanel")
|
||||
UI.Container(TargetBot.Looting.onItemsUpdate, true, nil, ui.items)
|
||||
UI.Container(TargetBot.Looting.onContainersUpdate, true, nil, ui.containers)
|
||||
ui.everyItem.onClick = function()
|
||||
ui.everyItem:setOn(not ui.everyItem:isOn())
|
||||
TargetBot.save()
|
||||
end
|
||||
ui.maxDangerPanel.value.onTextChange = function()
|
||||
local value = tonumber(ui.maxDangerPanel.value:getText())
|
||||
if not value then
|
||||
ui.maxDangerPanel.value:setText(0)
|
||||
end
|
||||
if dontSave then return end
|
||||
TargetBot.save()
|
||||
end
|
||||
ui.minCapacityPanel.value.onTextChange = function()
|
||||
local value = tonumber(ui.minCapacityPanel.value:getText())
|
||||
if not value then
|
||||
ui.minCapacityPanel.value:setText(0)
|
||||
end
|
||||
if dontSave then return end
|
||||
TargetBot.save()
|
||||
end
|
||||
end
|
||||
|
||||
TargetBot.Looting.onItemsUpdate = function()
|
||||
if dontSave then return end
|
||||
TargetBot.save()
|
||||
TargetBot.Looting.updateItemsAndContainers()
|
||||
end
|
||||
|
||||
TargetBot.Looting.onContainersUpdate = function()
|
||||
if dontSave then return end
|
||||
TargetBot.save()
|
||||
TargetBot.Looting.updateItemsAndContainers()
|
||||
end
|
||||
|
||||
TargetBot.Looting.update = function(data)
|
||||
dontSave = true
|
||||
TargetBot.Looting.list = {}
|
||||
ui.items:setItems(data['items'] or {})
|
||||
ui.containers:setItems(data['containers'] or {})
|
||||
ui.everyItem:setOn(data['everyItem'])
|
||||
ui.maxDangerPanel.value:setText(data['maxDanger'] or 10)
|
||||
ui.minCapacityPanel.value:setText(data['minCapacity'] or 100)
|
||||
TargetBot.Looting.updateItemsAndContainers()
|
||||
dontSave = false
|
||||
--vBot
|
||||
vBot.lootConainers = {}
|
||||
vBot.lootItems = {}
|
||||
for i, item in ipairs(ui.containers:getItems()) do
|
||||
table.insert(vBot.lootConainers, item['id'])
|
||||
end
|
||||
for i, item in ipairs(ui.items:getItems()) do
|
||||
table.insert(vBot.lootItems, item['id'])
|
||||
end
|
||||
end
|
||||
|
||||
TargetBot.Looting.save = function(data)
|
||||
data['items'] = ui.items:getItems()
|
||||
data['containers'] = ui.containers:getItems()
|
||||
data['maxDanger'] = tonumber(ui.maxDangerPanel.value:getText())
|
||||
data['minCapacity'] = tonumber(ui.minCapacityPanel.value:getText())
|
||||
data['everyItem'] = ui.everyItem:isOn()
|
||||
end
|
||||
|
||||
TargetBot.Looting.updateItemsAndContainers = function()
|
||||
items = ui.items:getItems()
|
||||
containers = ui.containers:getItems()
|
||||
itemsById = {}
|
||||
containersById = {}
|
||||
for i, item in ipairs(items) do
|
||||
itemsById[item.id] = 1
|
||||
end
|
||||
for i, container in ipairs(containers) do
|
||||
containersById[container.id] = 1
|
||||
end
|
||||
end
|
||||
|
||||
local waitTill = 0
|
||||
local waitingForContainer = nil
|
||||
local status = ""
|
||||
local lastFoodConsumption = 0
|
||||
|
||||
TargetBot.Looting.getStatus = function()
|
||||
return status
|
||||
end
|
||||
|
||||
TargetBot.Looting.process = function(targets, dangerLevel)
|
||||
if (not items[1] and not ui.everyItem:isOn()) or not containers[1] then
|
||||
status = ""
|
||||
return false
|
||||
end
|
||||
if dangerLevel > tonumber(ui.maxDangerPanel.value:getText()) then
|
||||
status = "High danger"
|
||||
return false
|
||||
end
|
||||
if player:getFreeCapacity() < tonumber(ui.minCapacityPanel.value:getText()) then
|
||||
status = "No cap"
|
||||
TargetBot.Looting.list = {}
|
||||
return false
|
||||
end
|
||||
local loot = storage.extras.lootLast and TargetBot.Looting.list[#TargetBot.Looting.list] or TargetBot.Looting.list[1]
|
||||
if loot == nil then
|
||||
status = ""
|
||||
return false
|
||||
end
|
||||
|
||||
if waitTill > now then
|
||||
return true
|
||||
end
|
||||
local containers = g_game.getContainers()
|
||||
local lootContainers = TargetBot.Looting.getLootContainers(containers)
|
||||
|
||||
-- check if there's container for loot and has empty space for it
|
||||
if not lootContainers[1] then
|
||||
-- there's no space, don't loot
|
||||
status = "No space"
|
||||
return false
|
||||
end
|
||||
|
||||
status = "Looting"
|
||||
|
||||
for index, container in pairs(containers) do
|
||||
if container.lootContainer then
|
||||
TargetBot.Looting.lootContainer(lootContainers, container)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local pos = player:getPosition()
|
||||
local dist = math.max(math.abs(pos.x-loot.pos.x), math.abs(pos.y-loot.pos.y))
|
||||
local maxRange = storage.extras.looting or 40
|
||||
if loot.tries > 30 or loot.pos.z ~= pos.z or dist > maxRange then
|
||||
table.remove(TargetBot.Looting.list, storage.extras.lootLast and #TargetBot.Looting.list or 1)
|
||||
return true
|
||||
end
|
||||
|
||||
local tile = g_map.getTile(loot.pos)
|
||||
if dist >= 3 or not tile then
|
||||
loot.tries = loot.tries + 1
|
||||
TargetBot.walkTo(loot.pos, 20, { ignoreNonPathable = true, precision = 2 })
|
||||
return true
|
||||
end
|
||||
|
||||
local container = tile:getTopUseThing()
|
||||
if not container or not container:isContainer() then
|
||||
table.remove(TargetBot.Looting.list, storage.extras.lootLast and #TargetBot.Looting.list or 1)
|
||||
return true
|
||||
end
|
||||
|
||||
g_game.open(container)
|
||||
waitTill = now + math.min(g_game.getPing(),100)
|
||||
waitingForContainer = container:getId()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
TargetBot.Looting.getLootContainers = function(containers)
|
||||
local lootContainers = {}
|
||||
local openedContainersById = {}
|
||||
local toOpen = nil
|
||||
for index, container in pairs(containers) do
|
||||
openedContainersById[container:getContainerItem():getId()] = 1
|
||||
if containersById[container:getContainerItem():getId()] and not container.lootContainer then
|
||||
if container:getItemsCount() < container:getCapacity() or container:hasPages() then
|
||||
table.insert(lootContainers, container)
|
||||
else -- it's full, open next container if possible
|
||||
for slot, item in ipairs(container:getItems()) do
|
||||
if item:isContainer() and containersById[item:getId()] then
|
||||
toOpen = {item, container}
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if not lootContainers[1] then
|
||||
if toOpen then
|
||||
g_game.open(toOpen[1], toOpen[2])
|
||||
waitTill = now + 500 -- wait 0.5s
|
||||
return lootContainers
|
||||
end
|
||||
-- check containers one more time, maybe there's any loot container
|
||||
for index, container in pairs(containers) do
|
||||
if not containersById[container:getContainerItem():getId()] and not container.lootContainer then
|
||||
for slot, item in ipairs(container:getItems()) do
|
||||
if item:isContainer() and containersById[item:getId()] then
|
||||
g_game.open(item)
|
||||
waitTill = now + 500 -- wait 0.5s
|
||||
return lootContainers
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- can't find any lootContainer, let's check slots, maybe there's one
|
||||
for slot = InventorySlotFirst, InventorySlotLast do
|
||||
local item = getInventoryItem(slot)
|
||||
if item and item:isContainer() and not openedContainersById[item:getId()] then
|
||||
-- container which is not opened yet, let's open it
|
||||
g_game.open(item)
|
||||
waitTill = now + 500 -- wait 0.5s
|
||||
return lootContainers
|
||||
end
|
||||
end
|
||||
end
|
||||
return lootContainers
|
||||
end
|
||||
|
||||
TargetBot.Looting.lootContainer = function(lootContainers, container)
|
||||
-- loot items
|
||||
local nextContainer = nil
|
||||
for i, item in ipairs(container:getItems()) do
|
||||
if item:isContainer() and not itemsById[item:getId()] then
|
||||
nextContainer = item
|
||||
elseif itemsById[item:getId()] or (ui.everyItem:isOn() and not item:isContainer()) then
|
||||
item.lootTries = (item.lootTries or 0) + 1
|
||||
if item.lootTries < 5 then -- if can't be looted within 0.5s then skip it
|
||||
return TargetBot.Looting.lootItem(lootContainers, item)
|
||||
end
|
||||
elseif storage.foodItems and storage.foodItems[1] and lastFoodConsumption + 5000 < now then
|
||||
for _, food in ipairs(storage.foodItems) do
|
||||
if item:getId() == food.id then
|
||||
g_game.use(item)
|
||||
lastFoodConsumption = now
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- no more items to loot, open next container
|
||||
if nextContainer then
|
||||
nextContainer.lootTries = (nextContainer.lootTries or 0) + 1
|
||||
if nextContainer.lootTries < 2 then -- max 0.6s to open it
|
||||
g_game.open(nextContainer, container)
|
||||
waitTill = now + 300 -- give it 0.3s to open
|
||||
waitingForContainer = nextContainer:getId()
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- looting finished, remove container from list
|
||||
container.lootContainer = false
|
||||
g_game.close(container)
|
||||
table.remove(TargetBot.Looting.list, storage.extras.lootLast and #TargetBot.Looting.list or 1)
|
||||
end
|
||||
|
||||
onTextMessage(function(mode, text)
|
||||
if TargetBot.isOff() then return end
|
||||
if #TargetBot.Looting.list == 0 then return end
|
||||
if string.find(text:lower(), "you are not the owner") then -- if we are not the owners of corpse then its a waste of time to try to loot it
|
||||
table.remove(TargetBot.Looting.list, storage.extras.lootLast and #TargetBot.Looting.list or 1)
|
||||
end
|
||||
end)
|
||||
|
||||
TargetBot.Looting.lootItem = function(lootContainers, item)
|
||||
if item:isStackable() then
|
||||
local count = item:getCount()
|
||||
for _, container in ipairs(lootContainers) do
|
||||
for slot, citem in ipairs(container:getItems()) do
|
||||
if item:getId() == citem:getId() and citem:getCount() < 100 then
|
||||
g_game.move(item, container:getSlotPosition(slot - 1), count)
|
||||
waitTill = now + 300 -- give it 0.3s to move item
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local container = lootContainers[1]
|
||||
g_game.move(item, container:getSlotPosition(container:getItemsCount()), 1)
|
||||
waitTill = now + 300 -- give it 0.3s to move item
|
||||
end
|
||||
|
||||
onContainerOpen(function(container, previousContainer)
|
||||
if container:getContainerItem():getId() == waitingForContainer then
|
||||
container.lootContainer = true
|
||||
waitingForContainer = nil
|
||||
end
|
||||
end)
|
||||
|
||||
onCreatureDisappear(function(creature)
|
||||
if isInPz() then return end
|
||||
if not TargetBot.isOn() then return end
|
||||
if not creature:isMonster() then return end
|
||||
local config = TargetBot.Creature.calculateParams(creature, {}) -- return {craeture, config, danger, priority}
|
||||
if not config.config or config.config.dontLoot then
|
||||
return
|
||||
end
|
||||
local pos = player:getPosition()
|
||||
local mpos = creature:getPosition()
|
||||
local name = creature:getName()
|
||||
if pos.z ~= mpos.z or math.max(math.abs(pos.x-mpos.x), math.abs(pos.y-mpos.y)) > 6 then return end
|
||||
schedule(20, function() -- check in 20ms if there's container (dead body) on that tile
|
||||
if not containers[1] then return end
|
||||
if TargetBot.Looting.list[20] then return end -- too many items to loot
|
||||
local tile = g_map.getTile(mpos)
|
||||
if not tile then return end
|
||||
local container = tile:getTopUseThing()
|
||||
if not container or not container:isContainer() then return end
|
||||
if not findPath(player:getPosition(), mpos, 6, {ignoreNonPathable=true, ignoreCreatures=true, ignoreCost=true}) then return end
|
||||
table.insert(TargetBot.Looting.list, {pos=mpos, creature=name, container=container:getId(), added=now, tries=0})
|
||||
|
||||
table.sort(TargetBot.Looting.list, function(a,b)
|
||||
a.dist = distanceFromPlayer(a.pos)
|
||||
b.dist = distanceFromPlayer(b.pos)
|
||||
|
||||
return a.dist > b.dist
|
||||
end)
|
||||
container:setMarked('#000088')
|
||||
end)
|
||||
end)
|
||||
@@ -0,0 +1,69 @@
|
||||
TargetBotLootingPanel < Panel
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
HorizontalSeparator
|
||||
margin-top: 5
|
||||
|
||||
Label
|
||||
margin-top: 5
|
||||
text: Items to loot
|
||||
text-align: center
|
||||
|
||||
BotContainer
|
||||
id: items
|
||||
margin-top: 3
|
||||
|
||||
BotSwitch
|
||||
id: everyItem
|
||||
!text: tr("Loot every item")
|
||||
margin-top: 2
|
||||
|
||||
Label
|
||||
margin-top: 5
|
||||
text: Containers for loot
|
||||
text-align: center
|
||||
|
||||
BotContainer
|
||||
id: containers
|
||||
margin-top: 3
|
||||
height: 45
|
||||
|
||||
Panel
|
||||
id: maxDangerPanel
|
||||
height: 20
|
||||
margin-top: 5
|
||||
|
||||
BotTextEdit
|
||||
id: value
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 6
|
||||
width: 80
|
||||
|
||||
Label
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
text: Max. danger:
|
||||
margin-left: 5
|
||||
|
||||
Panel
|
||||
id: minCapacityPanel
|
||||
height: 20
|
||||
margin-top: 3
|
||||
|
||||
BotTextEdit
|
||||
id: value
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 6
|
||||
width: 80
|
||||
|
||||
Label
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
text: Min. capacity:
|
||||
margin-left: 5
|
||||
328
modules/game_bot/default_configs/vBot_4.7/targetbot/target.lua
Normal file
328
modules/game_bot/default_configs/vBot_4.7/targetbot/target.lua
Normal file
@@ -0,0 +1,328 @@
|
||||
local targetbotMacro = nil
|
||||
local config = nil
|
||||
local lastAction = 0
|
||||
local cavebotAllowance = 0
|
||||
local lureEnabled = true
|
||||
local dangerValue = 0
|
||||
local looterStatus = ""
|
||||
|
||||
-- ui
|
||||
local configWidget = UI.Config()
|
||||
local ui = UI.createWidget("TargetBotPanel")
|
||||
|
||||
ui.list = ui.listPanel.list -- shortcut
|
||||
TargetBot.targetList = ui.list
|
||||
TargetBot.Looting.setup()
|
||||
|
||||
ui.status.left:setText("Status:")
|
||||
ui.status.right:setText("Off")
|
||||
ui.target.left:setText("Target:")
|
||||
ui.target.right:setText("-")
|
||||
ui.config.left:setText("Config:")
|
||||
ui.config.right:setText("-")
|
||||
ui.danger.left:setText("Danger:")
|
||||
ui.danger.right:setText("0")
|
||||
|
||||
ui.editor.debug.onClick = function()
|
||||
local on = ui.editor.debug:isOn()
|
||||
ui.editor.debug:setOn(not on)
|
||||
if on then
|
||||
for _, spec in ipairs(getSpectators()) do
|
||||
spec:clearText()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local oldTibia = g_game.getClientVersion() < 960
|
||||
|
||||
-- main loop, controlled by config
|
||||
targetbotMacro = macro(100, function()
|
||||
local pos = player:getPosition()
|
||||
local specs = g_map.getSpectatorsInRange(pos, false, 6, 6) -- 12x12 area
|
||||
local creatures = 0
|
||||
for i, spec in ipairs(specs) do
|
||||
if spec:isMonster() then
|
||||
creatures = creatures + 1
|
||||
end
|
||||
end
|
||||
if creatures > 10 then -- if there are too many monsters around, limit area
|
||||
creatures = g_map.getSpectatorsInRange(pos, false, 3, 3) -- 6x6 area
|
||||
else
|
||||
creatures = specs
|
||||
end
|
||||
local highestPriority = 0
|
||||
local dangerLevel = 0
|
||||
local targets = 0
|
||||
local highestPriorityParams = nil
|
||||
for i, creature in ipairs(creatures) do
|
||||
local hppc = creature:getHealthPercent()
|
||||
if hppc and hppc > 0 then
|
||||
local path = findPath(player:getPosition(), creature:getPosition(), 7, {ignoreLastCreature=true, ignoreNonPathable=true, ignoreCost=true, ignoreCreatures=true})
|
||||
if creature:isMonster() and (oldTibia or creature:getType() < 3) and path then
|
||||
local params = TargetBot.Creature.calculateParams(creature, path) -- return {craeture, config, danger, priority}
|
||||
dangerLevel = dangerLevel + params.danger
|
||||
if params.priority > 0 then
|
||||
targets = targets + 1
|
||||
if params.priority > highestPriority then
|
||||
highestPriority = params.priority
|
||||
highestPriorityParams = params
|
||||
end
|
||||
if ui.editor.debug:isOn() then
|
||||
creature:setText(params.config.name .. "\n" .. params.priority)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- reset walking
|
||||
TargetBot.walkTo(nil)
|
||||
|
||||
-- looting
|
||||
local looting = TargetBot.Looting.process(targets, dangerLevel)
|
||||
local lootingStatus = TargetBot.Looting.getStatus()
|
||||
looterStatus = TargetBot.Looting.getStatus()
|
||||
dangerValue = dangerLevel
|
||||
|
||||
ui.danger.right:setText(dangerLevel)
|
||||
if highestPriorityParams and not isInPz() then
|
||||
ui.target.right:setText(highestPriorityParams.creature:getName())
|
||||
ui.config.right:setText(highestPriorityParams.config.name)
|
||||
TargetBot.Creature.attack(highestPriorityParams, targets, looting)
|
||||
if lootingStatus:len() > 0 then
|
||||
TargetBot.setStatus("Attack & " .. lootingStatus)
|
||||
elseif cavebotAllowance > now then
|
||||
TargetBot.setStatus("Luring using CaveBot")
|
||||
else
|
||||
TargetBot.setStatus("Attacking")
|
||||
if not lureEnabled then
|
||||
TargetBot.setStatus("Attacking (luring off)")
|
||||
end
|
||||
end
|
||||
TargetBot.walk()
|
||||
lastAction = now
|
||||
return
|
||||
end
|
||||
|
||||
ui.target.right:setText("-")
|
||||
ui.config.right:setText("-")
|
||||
if looting then
|
||||
TargetBot.walk()
|
||||
lastAction = now
|
||||
end
|
||||
if lootingStatus:len() > 0 then
|
||||
TargetBot.setStatus(lootingStatus)
|
||||
else
|
||||
TargetBot.setStatus("Waiting")
|
||||
end
|
||||
end)
|
||||
|
||||
-- config, its callback is called immediately, data can be nil
|
||||
config = Config.setup("targetbot_configs", configWidget, "json", function(name, enabled, data)
|
||||
if not data then
|
||||
ui.status.right:setText("Off")
|
||||
return targetbotMacro.setOff()
|
||||
end
|
||||
TargetBot.Creature.resetConfigs()
|
||||
for _, value in ipairs(data["targeting"] or {}) do
|
||||
TargetBot.Creature.addConfig(value)
|
||||
end
|
||||
TargetBot.Looting.update(data["looting"] or {})
|
||||
|
||||
-- add configs
|
||||
if enabled then
|
||||
ui.status.right:setText("On")
|
||||
else
|
||||
ui.status.right:setText("Off")
|
||||
end
|
||||
|
||||
targetbotMacro.setOn(enabled)
|
||||
targetbotMacro.delay = nil
|
||||
lureEnabled = true
|
||||
end)
|
||||
|
||||
-- setup ui
|
||||
ui.editor.buttons.add.onClick = function()
|
||||
TargetBot.Creature.edit(nil, function(newConfig)
|
||||
TargetBot.Creature.addConfig(newConfig, true)
|
||||
TargetBot.save()
|
||||
end)
|
||||
end
|
||||
|
||||
ui.editor.buttons.edit.onClick = function()
|
||||
local entry = ui.list:getFocusedChild()
|
||||
if not entry then return end
|
||||
TargetBot.Creature.edit(entry.value, function(newConfig)
|
||||
entry:setText(newConfig.name)
|
||||
entry.value = newConfig
|
||||
TargetBot.Creature.resetConfigsCache()
|
||||
TargetBot.save()
|
||||
end)
|
||||
end
|
||||
|
||||
ui.editor.buttons.remove.onClick = function()
|
||||
local entry = ui.list:getFocusedChild()
|
||||
if not entry then return end
|
||||
entry:destroy()
|
||||
TargetBot.Creature.resetConfigsCache()
|
||||
TargetBot.save()
|
||||
end
|
||||
|
||||
-- public function, you can use them in your scripts
|
||||
TargetBot.isActive = function() -- return true if attacking or looting takes place
|
||||
return lastAction + 300 > now
|
||||
end
|
||||
|
||||
TargetBot.isCaveBotActionAllowed = function()
|
||||
return cavebotAllowance > now
|
||||
end
|
||||
|
||||
TargetBot.setStatus = function(text)
|
||||
return ui.status.right:setText(text)
|
||||
end
|
||||
|
||||
TargetBot.getStatus = function()
|
||||
return ui.status.right:getText()
|
||||
end
|
||||
|
||||
TargetBot.isOn = function()
|
||||
return config.isOn()
|
||||
end
|
||||
|
||||
TargetBot.isOff = function()
|
||||
return config.isOff()
|
||||
end
|
||||
|
||||
TargetBot.setOn = function(val)
|
||||
if val == false then
|
||||
return TargetBot.setOff(true)
|
||||
end
|
||||
config.setOn()
|
||||
end
|
||||
|
||||
TargetBot.setOff = function(val)
|
||||
if val == false then
|
||||
return TargetBot.setOn(true)
|
||||
end
|
||||
config.setOff()
|
||||
end
|
||||
|
||||
TargetBot.getCurrentProfile = function()
|
||||
return storage._configs.targetbot_configs.selected
|
||||
end
|
||||
|
||||
local botConfigName = modules.game_bot.contentsPanel.config:getCurrentOption().text
|
||||
TargetBot.setCurrentProfile = function(name)
|
||||
if not g_resources.fileExists("/bot/"..botConfigName.."/targetbot_configs/"..name..".json") then
|
||||
return warn("there is no targetbot profile with that name!")
|
||||
end
|
||||
TargetBot.setOff()
|
||||
storage._configs.targetbot_configs.selected = name
|
||||
TargetBot.setOn()
|
||||
end
|
||||
|
||||
TargetBot.delay = function(value)
|
||||
targetbotMacro.delay = now + value
|
||||
end
|
||||
|
||||
TargetBot.save = function()
|
||||
local data = {targeting={}, looting={}}
|
||||
for _, entry in ipairs(ui.list:getChildren()) do
|
||||
table.insert(data.targeting, entry.value)
|
||||
end
|
||||
TargetBot.Looting.save(data.looting)
|
||||
config.save(data)
|
||||
end
|
||||
|
||||
TargetBot.allowCaveBot = function(time)
|
||||
cavebotAllowance = now + time
|
||||
end
|
||||
|
||||
TargetBot.disableLuring = function()
|
||||
lureEnabled = false
|
||||
end
|
||||
|
||||
TargetBot.enableLuring = function()
|
||||
lureEnabled = true
|
||||
end
|
||||
|
||||
TargetBot.Danger = function()
|
||||
return dangerValue
|
||||
end
|
||||
|
||||
TargetBot.lootStatus = function()
|
||||
return looterStatus
|
||||
end
|
||||
|
||||
|
||||
-- attacks
|
||||
local lastSpell = 0
|
||||
local lastAttackSpell = 0
|
||||
|
||||
TargetBot.saySpell = function(text, delay)
|
||||
if type(text) ~= 'string' or text:len() < 1 then return end
|
||||
if not delay then delay = 500 end
|
||||
if g_game.getProtocolVersion() < 1090 then
|
||||
lastAttackSpell = now -- pause attack spells, healing spells are more important
|
||||
end
|
||||
if lastSpell + delay < now then
|
||||
say(text)
|
||||
lastSpell = now
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
TargetBot.sayAttackSpell = function(text, delay)
|
||||
if type(text) ~= 'string' or text:len() < 1 then return end
|
||||
if not delay then delay = 2000 end
|
||||
if lastAttackSpell + delay < now then
|
||||
say(text)
|
||||
lastAttackSpell = now
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local lastItemUse = 0
|
||||
local lastRuneAttack = 0
|
||||
|
||||
TargetBot.useItem = function(item, subType, target, delay)
|
||||
if not delay then delay = 200 end
|
||||
if lastItemUse + delay < now then
|
||||
local thing = g_things.getThingType(item)
|
||||
if not thing or not thing:isFluidContainer() then
|
||||
subType = g_game.getClientVersion() >= 860 and 0 or 1
|
||||
end
|
||||
if g_game.getClientVersion() < 780 then
|
||||
local tmpItem = g_game.findPlayerItem(item, subType)
|
||||
if not tmpItem then return end
|
||||
g_game.useWith(tmpItem, target, subType) -- using item from bp
|
||||
else
|
||||
g_game.useInventoryItemWith(item, target, subType) -- hotkey
|
||||
end
|
||||
lastItemUse = now
|
||||
end
|
||||
end
|
||||
|
||||
TargetBot.useAttackItem = function(item, subType, target, delay)
|
||||
if not delay then delay = 2000 end
|
||||
if lastRuneAttack + delay < now then
|
||||
local thing = g_things.getThingType(item)
|
||||
if not thing or not thing:isFluidContainer() then
|
||||
subType = g_game.getClientVersion() >= 860 and 0 or 1
|
||||
end
|
||||
if g_game.getClientVersion() < 780 then
|
||||
local tmpItem = g_game.findPlayerItem(item, subType)
|
||||
if not tmpItem then return end
|
||||
g_game.useWith(tmpItem, target, subType) -- using item from bp
|
||||
else
|
||||
g_game.useInventoryItemWith(item, target, subType) -- hotkey
|
||||
end
|
||||
lastRuneAttack = now
|
||||
end
|
||||
end
|
||||
|
||||
TargetBot.canLure = function()
|
||||
return lureEnabled
|
||||
end
|
||||
115
modules/game_bot/default_configs/vBot_4.7/targetbot/target.otui
Normal file
115
modules/game_bot/default_configs/vBot_4.7/targetbot/target.otui
Normal file
@@ -0,0 +1,115 @@
|
||||
TargetBotEntry < Label
|
||||
background-color: alpha
|
||||
text-offset: 2 0
|
||||
focusable: true
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
TargetBotDualLabel < Panel
|
||||
height: 18
|
||||
margin-left: 3
|
||||
margin-right: 4
|
||||
|
||||
Label
|
||||
id: left
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-auto-resize: true
|
||||
|
||||
Label
|
||||
id: right
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
text-auto-resize: true
|
||||
|
||||
TargetBotPanel < Panel
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
HorizontalSeparator
|
||||
margin-top: 2
|
||||
margin-bottom: 5
|
||||
|
||||
TargetBotDualLabel
|
||||
id: status
|
||||
TargetBotDualLabel
|
||||
id: target
|
||||
TargetBotDualLabel
|
||||
id: config
|
||||
TargetBotDualLabel
|
||||
id: danger
|
||||
|
||||
Panel
|
||||
id: listPanel
|
||||
height: 40
|
||||
|
||||
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: configButton
|
||||
@onClick: |
|
||||
self:setOn(not self:isOn())
|
||||
self:getParent().listPanel:setHeight(self:isOn() and 100 or 40)
|
||||
self:getParent().editor:setVisible(self:isOn())
|
||||
|
||||
$on:
|
||||
text: Hide target editor
|
||||
|
||||
$!on:
|
||||
text: Show target editor
|
||||
|
||||
Panel
|
||||
id: editor
|
||||
visible: false
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
Panel
|
||||
id: buttons
|
||||
height: 20
|
||||
margin-top: 2
|
||||
|
||||
Button
|
||||
id: add
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
text: Add
|
||||
width: 56
|
||||
|
||||
Button
|
||||
id: edit
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: Edit
|
||||
width: 56
|
||||
|
||||
Button
|
||||
id: remove
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
text: Remove
|
||||
width: 56
|
||||
|
||||
BotSwitch
|
||||
id: debug
|
||||
text: Show target priority
|
||||
@@ -0,0 +1,28 @@
|
||||
local dest
|
||||
local maxDist
|
||||
local params
|
||||
|
||||
TargetBot.walkTo = function(_dest, _maxDist, _params)
|
||||
dest = _dest
|
||||
maxDist = _maxDist
|
||||
params = _params
|
||||
end
|
||||
|
||||
-- called every 100ms if targeting or looting is active
|
||||
TargetBot.walk = function()
|
||||
if not dest then return end
|
||||
if player:isWalking() then return end
|
||||
local pos = player:getPosition()
|
||||
if pos.z ~= dest.z then return end
|
||||
local dist = math.max(math.abs(pos.x-dest.x), math.abs(pos.y-dest.y))
|
||||
if params.precision and params.precision >= dist then return end
|
||||
if params.marginMin and params.marginMax then
|
||||
if dist >= params.marginMin and dist <= params.marginMax then
|
||||
return
|
||||
end
|
||||
end
|
||||
local path = getPath(pos, dest, maxDist, params)
|
||||
if path then
|
||||
walk(path[1])
|
||||
end
|
||||
end
|
||||
1248
modules/game_bot/default_configs/vBot_4.7/vBot/AttackBot.lua
Normal file
1248
modules/game_bot/default_configs/vBot_4.7/vBot/AttackBot.lua
Normal file
File diff suppressed because it is too large
Load Diff
624
modules/game_bot/default_configs/vBot_4.7/vBot/AttackBot.otui
Normal file
624
modules/game_bot/default_configs/vBot_4.7/vBot/AttackBot.otui
Normal file
@@ -0,0 +1,624 @@
|
||||
AttackEntry < UIWidget
|
||||
background-color: alpha
|
||||
text-offset: 35 1
|
||||
focusable: true
|
||||
height: 16
|
||||
font: verdana-11px-rounded
|
||||
text-align: left
|
||||
|
||||
CheckBox
|
||||
id: enabled
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 15
|
||||
height: 15
|
||||
margin-top: 2
|
||||
margin-left: 3
|
||||
|
||||
UIItem
|
||||
id: id
|
||||
anchors.left: prev.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
size: 16 16
|
||||
focusable: false
|
||||
visible: false
|
||||
|
||||
UIWidget
|
||||
id: spell
|
||||
anchors.left: enabled.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
size: 12 12
|
||||
margin-left: 1
|
||||
image-source: /images/game/dangerous
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
Button
|
||||
id: remove
|
||||
!text: tr('x')
|
||||
anchors.right: parent.right
|
||||
margin-right: 15
|
||||
width: 15
|
||||
height: 15
|
||||
|
||||
AttackBotBotPanel < Panel
|
||||
height: 38
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('AttackBot')
|
||||
|
||||
Button
|
||||
id: settings
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Setup
|
||||
|
||||
Button
|
||||
id: 1
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
text: 1
|
||||
margin-right: 2
|
||||
margin-top: 4
|
||||
size: 17 17
|
||||
|
||||
Button
|
||||
id: 2
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
text: 2
|
||||
margin-left: 4
|
||||
size: 17 17
|
||||
|
||||
Button
|
||||
id: 3
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
text: 3
|
||||
margin-left: 4
|
||||
size: 17 17
|
||||
|
||||
Button
|
||||
id: 4
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
text: 4
|
||||
margin-left: 4
|
||||
size: 17 17
|
||||
|
||||
Button
|
||||
id: 5
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
text: 5
|
||||
margin-left: 4
|
||||
size: 17 17
|
||||
|
||||
Label
|
||||
id: name
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
margin-left: 4
|
||||
height: 17
|
||||
text: Profile #1
|
||||
background: #292A2A
|
||||
|
||||
CategoryLabel < Panel
|
||||
size: 315 15
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 5
|
||||
padding: 1
|
||||
|
||||
Label
|
||||
id: description
|
||||
anchors.fill: parent
|
||||
text-align: center
|
||||
text: Area Rune (avalanche, great fireball, etc)
|
||||
font: verdana-11px-rounded
|
||||
background: #363636
|
||||
|
||||
SourceLabel < Panel
|
||||
size: 105 15
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 5
|
||||
padding: 1
|
||||
|
||||
Label
|
||||
id: description
|
||||
anchors.fill: parent
|
||||
text-align: center
|
||||
text: Monster Name
|
||||
font: verdana-11px-rounded
|
||||
background: #363636
|
||||
|
||||
RangeLabel < Panel
|
||||
size: 323 15
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 5
|
||||
padding: 1
|
||||
|
||||
Label
|
||||
id: description
|
||||
anchors.fill: parent
|
||||
text-align: center
|
||||
text: 5 Sqm
|
||||
font: verdana-11px-rounded
|
||||
background: #363636
|
||||
|
||||
PreButton < PreviousButton
|
||||
background: #363636
|
||||
height: 15
|
||||
|
||||
NexButton < NextButton
|
||||
background: #363636
|
||||
height: 15
|
||||
|
||||
AttackBotPanel < Panel
|
||||
size: 500 200
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 5
|
||||
padding: 5
|
||||
|
||||
TextList
|
||||
id: entryList
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
margin-top: 3
|
||||
size: 430 100
|
||||
vertical-scrollbar: entryListScrollBar
|
||||
|
||||
VerticalScrollBar
|
||||
id: entryListScrollBar
|
||||
anchors.top: entryList.top
|
||||
anchors.bottom: entryList.bottom
|
||||
anchors.right: entryList.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
PreButton
|
||||
id: previousCategory
|
||||
anchors.left: entryList.left
|
||||
anchors.top: entryList.bottom
|
||||
margin-top: 8
|
||||
|
||||
NexButton
|
||||
id: nextCategory
|
||||
anchors.left: category.right
|
||||
anchors.top: entryList.bottom
|
||||
margin-top: 8
|
||||
margin-left: 2
|
||||
|
||||
CategoryLabel
|
||||
id: category
|
||||
anchors.top: entryList.bottom
|
||||
anchors.left: previousCategory.right
|
||||
anchors.verticalCenter: previousCategory.verticalCenter
|
||||
margin-left: 3
|
||||
|
||||
PreButton
|
||||
id: previousSource
|
||||
anchors.left: entryList.left
|
||||
anchors.top: category.bottom
|
||||
margin-top: 8
|
||||
|
||||
NexButton
|
||||
id: nextSource
|
||||
anchors.left: source.right
|
||||
anchors.top: category.bottom
|
||||
margin-top: 8
|
||||
margin-left: 2
|
||||
|
||||
SourceLabel
|
||||
id: source
|
||||
anchors.top: category.bottom
|
||||
anchors.left: previousSource.right
|
||||
anchors.verticalCenter: previousSource.verticalCenter
|
||||
margin-left: 3
|
||||
|
||||
PreButton
|
||||
id: previousRange
|
||||
anchors.left: nextSource.right
|
||||
anchors.verticalCenter: nextSource.verticalCenter
|
||||
margin-left: 8
|
||||
|
||||
NexButton
|
||||
id: nextRange
|
||||
anchors.left: range.right
|
||||
anchors.verticalCenter: range.verticalCenter
|
||||
margin-left: 2
|
||||
|
||||
RangeLabel
|
||||
id: range
|
||||
anchors.left: previousRange.right
|
||||
anchors.verticalCenter: previousRange.verticalCenter
|
||||
margin-left: 3
|
||||
|
||||
TextEdit
|
||||
id: monsters
|
||||
anchors.left: entryList.left
|
||||
anchors.top: range.bottom
|
||||
margin-top: 5
|
||||
size: 405 15
|
||||
text: monster names
|
||||
font: cipsoftFont
|
||||
background: #363636
|
||||
|
||||
Label
|
||||
anchors.left: prev.left
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 6
|
||||
margin-left: 3
|
||||
text-align: center
|
||||
text: Mana%:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
SpinBox
|
||||
id: manaPercent
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 4
|
||||
size: 30 20
|
||||
minimum: 0
|
||||
maximum: 99
|
||||
step: 1
|
||||
editable: true
|
||||
focusable: true
|
||||
|
||||
Label
|
||||
anchors.left: prev.right
|
||||
margin-left: 7
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
text: Creatures:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
SpinBox
|
||||
id: creatures
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 4
|
||||
size: 30 20
|
||||
minimum: 1
|
||||
maximum: 99
|
||||
step: 1
|
||||
editable: true
|
||||
focusable: true
|
||||
|
||||
CheckBox
|
||||
id: orMore
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
tooltip: or more creatures
|
||||
|
||||
Label
|
||||
anchors.left: prev.right
|
||||
margin-left: 7
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
text: HP:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
SpinBox
|
||||
id: minHp
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 4
|
||||
size: 40 20
|
||||
minimum: 0
|
||||
maximum: 99
|
||||
value: 0
|
||||
editable: true
|
||||
focusable: true
|
||||
|
||||
Label
|
||||
anchors.left: prev.right
|
||||
margin-left: 4
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
text: -
|
||||
font: verdana-11px-rounded
|
||||
|
||||
SpinBox
|
||||
id: maxHp
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 4
|
||||
size: 40 20
|
||||
minimum: 1
|
||||
maximum: 100
|
||||
value: 100
|
||||
editable: true
|
||||
focusable: true
|
||||
|
||||
Label
|
||||
anchors.left: prev.right
|
||||
margin-left: 7
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
text: CD:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
SpinBox
|
||||
id: cooldown
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 4
|
||||
size: 60 20
|
||||
minimum: 0
|
||||
maximum: 999999
|
||||
step: 100
|
||||
value: 0
|
||||
editable: true
|
||||
focusable: true
|
||||
|
||||
Button
|
||||
id: up
|
||||
anchors.right: parent.right
|
||||
anchors.top: entryList.bottom
|
||||
size: 60 17
|
||||
text: Move Up
|
||||
text-align: center
|
||||
font: cipsoftFont
|
||||
margin-top: 7
|
||||
margin-right: 8
|
||||
|
||||
Button
|
||||
id: down
|
||||
anchors.right: prev.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
size: 60 17
|
||||
margin-right: 5
|
||||
text: Move Down
|
||||
text-align: center
|
||||
font: cipsoftFont
|
||||
|
||||
Button
|
||||
id: addEntry
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 40 19
|
||||
text-align: center
|
||||
text: New
|
||||
font: cipsoftFont
|
||||
|
||||
BotItem
|
||||
id: itemId
|
||||
anchors.right: addEntry.left
|
||||
margin-right: 5
|
||||
anchors.bottom: parent.bottom
|
||||
margin-bottom: 2
|
||||
tooltip: drag item here on press to open window
|
||||
|
||||
TextEdit
|
||||
id: spellName
|
||||
anchors.top: monsters.top
|
||||
anchors.left: monsters.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 5
|
||||
height: 15
|
||||
text: spell name
|
||||
background: #363636
|
||||
font: cipsoftFont
|
||||
visible: false
|
||||
|
||||
SettingsPanel < Panel
|
||||
size: 500 200
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 5
|
||||
padding: 10
|
||||
|
||||
VerticalSeparator
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: Visible.right
|
||||
margin-left: 10
|
||||
margin-top: 5
|
||||
margin-bottom: 5
|
||||
|
||||
Label
|
||||
anchors.top: parent.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 10
|
||||
text-align: center
|
||||
font: verdana-11px-rounded
|
||||
text: Profile:
|
||||
|
||||
TextEdit
|
||||
id: profileName
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
anchors.left: prev.left
|
||||
anchors.right: prev.right
|
||||
margin-left: 20
|
||||
margin-right: 20
|
||||
|
||||
Button
|
||||
id: resetSettings
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
text-align: center
|
||||
text: Reset Settings
|
||||
|
||||
CheckBox
|
||||
id: IgnoreMana
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-top: 5
|
||||
width: 200
|
||||
text: Check RL Tibia conditions
|
||||
|
||||
CheckBox
|
||||
id: Kills
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 8
|
||||
width: 200
|
||||
height: 22
|
||||
text: Don't use area attacks if less than kills to red skull
|
||||
text-wrap: true
|
||||
text-align: left
|
||||
|
||||
SpinBox
|
||||
id: KillsAmount
|
||||
anchors.top: prev.top
|
||||
anchors.bottom: prev.bottom
|
||||
anchors.left: prev.right
|
||||
text-align: left
|
||||
width: 30
|
||||
minimum: 1
|
||||
maximum: 10
|
||||
focusable: true
|
||||
margin-left: 5
|
||||
|
||||
CheckBox
|
||||
id: Rotate
|
||||
anchors.top: Kills.bottom
|
||||
anchors.left: Kills.left
|
||||
margin-top: 8
|
||||
width: 220
|
||||
text: Turn to side with most monsters
|
||||
|
||||
CheckBox
|
||||
id: Cooldown
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 8
|
||||
width: 220
|
||||
text: Check spell cooldowns
|
||||
|
||||
CheckBox
|
||||
id: Visible
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 8
|
||||
width: 245
|
||||
text: Items must be visible (recommended)
|
||||
|
||||
CheckBox
|
||||
id: PvpMode
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 8
|
||||
width: 245
|
||||
text: PVP mode
|
||||
|
||||
CheckBox
|
||||
id: PvpSafe
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 8
|
||||
width: 245
|
||||
text: PVP safe
|
||||
|
||||
CheckBox
|
||||
id: Training
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 8
|
||||
width: 245
|
||||
text: Stop when attacking trainers
|
||||
|
||||
CheckBox
|
||||
id: BlackListSafe
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 8
|
||||
width: 200
|
||||
height: 18
|
||||
text: Stop if Anti-RS player in range
|
||||
|
||||
SpinBox
|
||||
id: AntiRsRange
|
||||
anchors.top: prev.top
|
||||
anchors.bottom: prev.bottom
|
||||
anchors.left: prev.right
|
||||
text-align: center
|
||||
width: 50
|
||||
minimum: 1
|
||||
maximum: 10
|
||||
focusable: true
|
||||
margin-left: 5
|
||||
|
||||
AttackBotWindow < MainWindow
|
||||
size: 535 300
|
||||
padding: 15
|
||||
text: AttackBot v2
|
||||
@onEscape: self:hide()
|
||||
|
||||
Label
|
||||
id: mainLabel
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
margin-top: 10
|
||||
margin-left: 2
|
||||
!text: tr('More important methods come first (Example: Exori gran above Exori)')
|
||||
text-align: left
|
||||
font: verdana-11px-rounded
|
||||
color: #aeaeae
|
||||
|
||||
SettingsPanel
|
||||
id: settingsPanel
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 10
|
||||
anchors.left: parent.left
|
||||
margin-left: 2
|
||||
|
||||
Label
|
||||
id: settingsLabel
|
||||
anchors.verticalCenter: prev.top
|
||||
anchors.left: prev.left
|
||||
margin-left: 3
|
||||
text: Settings
|
||||
color: #fe4400
|
||||
font: verdana-11px-rounded
|
||||
|
||||
AttackBotPanel
|
||||
id: mainPanel
|
||||
anchors.top: mainLabel.bottom
|
||||
margin-top: 10
|
||||
anchors.left: parent.left
|
||||
margin-left: 2
|
||||
visible: false
|
||||
|
||||
Label
|
||||
id: shooterLabel
|
||||
anchors.verticalCenter: prev.top
|
||||
anchors.left: prev.left
|
||||
margin-left: 3
|
||||
text: Spell Shooter
|
||||
color: #fe4400
|
||||
font: verdana-11px-rounded
|
||||
visible: false
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 10
|
||||
|
||||
Button
|
||||
id: closeButton
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
text: Close
|
||||
font: cipsoftFont
|
||||
|
||||
Button
|
||||
id: settings
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
size: 50 21
|
||||
font: cipsoftFont
|
||||
text: Settings
|
||||
203
modules/game_bot/default_configs/vBot_4.7/vBot/BotServer.lua
Normal file
203
modules/game_bot/default_configs/vBot_4.7/vBot/BotServer.lua
Normal file
@@ -0,0 +1,203 @@
|
||||
setDefaultTab("Main")
|
||||
|
||||
local panelName = "BOTserver"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 18
|
||||
Button
|
||||
id: botServer
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
height: 18
|
||||
!text: tr('BotServer')
|
||||
]])
|
||||
ui:setId(panelName)
|
||||
|
||||
if not storage[panelName] then
|
||||
storage[panelName] = {
|
||||
manaInfo = true,
|
||||
mwallInfo = true,
|
||||
vocation = true,
|
||||
outfit = false,
|
||||
broadcasts = true
|
||||
}
|
||||
end
|
||||
|
||||
local config = storage[panelName]
|
||||
|
||||
if not storage.BotServerChannel then
|
||||
math.randomseed(os.time())
|
||||
storage.BotServerChannel = tostring(math.random(1000000000000,9999999999999))
|
||||
end
|
||||
|
||||
local channel = tostring(storage.BotServerChannel)
|
||||
BotServer.init(name(), channel)
|
||||
|
||||
vBot.BotServerMembers = {}
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
botServerWindow = g_ui.createWidget('BotServerWindow', rootWidget)
|
||||
botServerWindow:hide()
|
||||
|
||||
|
||||
botServerWindow.Data.Channel:setText(storage.BotServerChannel)
|
||||
botServerWindow.Data.Channel.onTextChange = function(widget, text)
|
||||
storage.BotServerChannel = text
|
||||
end
|
||||
botServerWindow.Data.Random.onClick = function(widget)
|
||||
storage.BotServerChannel = tostring(math.random(1000000000000,9999999999999))
|
||||
botServerWindow.Data.Channel:setText(storage.BotServerChannel)
|
||||
end
|
||||
botServerWindow.Features.Feature1:setOn(config.manaInfo)
|
||||
botServerWindow.Features.Feature1.onClick = function(widget)
|
||||
config.manaInfo = not config.manaInfo
|
||||
widget:setOn(config.manaInfo)
|
||||
end
|
||||
botServerWindow.Features.Feature2:setOn(config.mwallInfo)
|
||||
botServerWindow.Features.Feature2.onClick = function(widget)
|
||||
config.mwallInfo = not config.mwallInfo
|
||||
widget:setOn(config.mwallInfo)
|
||||
end
|
||||
botServerWindow.Features.Feature3:setOn(config.vocation)
|
||||
botServerWindow.Features.Feature3.onClick = function(widget)
|
||||
config.vocation = not config.vocation
|
||||
if config.vocation then
|
||||
BotServer.send("voc", player:getVocation())
|
||||
end
|
||||
widget:setOn(config.vocation)
|
||||
end
|
||||
botServerWindow.Features.Feature4:setOn(config.outfit)
|
||||
botServerWindow.Features.Feature4.onClick = function(widget)
|
||||
config.outfit = not config.outfit
|
||||
widget:setOn(config.outfit)
|
||||
end
|
||||
botServerWindow.Features.Feature5:setOn(config.broadcasts)
|
||||
botServerWindow.Features.Feature5.onClick = function(widget)
|
||||
config.broadcasts = not config.broadcasts
|
||||
widget:setOn(config.broadcasts)
|
||||
end
|
||||
botServerWindow.Features.Broadcast.onClick = function(widget)
|
||||
if BotServer._websocket then
|
||||
BotServer.send("broadcast", botServerWindow.Features.broadcastText:getText())
|
||||
end
|
||||
botServerWindow.Features.broadcastText:setText('')
|
||||
end
|
||||
end
|
||||
|
||||
function updateStatusText()
|
||||
if BotServer._websocket then
|
||||
botServerWindow.Data.ServerStatus:setText("CONNECTED")
|
||||
if serverCount then
|
||||
botServerWindow.Data.Members:setText("Members: "..#serverCount)
|
||||
if ServerMembers then
|
||||
local text = ""
|
||||
local regex = [["([a-z 'A-z-]*)"*]]
|
||||
local re = regexMatch(ServerMembers, regex)
|
||||
--re[name][2]
|
||||
for i=1,#re do
|
||||
if i == 1 then
|
||||
text = re[i][2]
|
||||
else
|
||||
text = text .. "\n" .. re[i][2]
|
||||
end
|
||||
end
|
||||
botServerWindow.Data.Members:setTooltip(text)
|
||||
end
|
||||
end
|
||||
else
|
||||
botServerWindow.Data.ServerStatus:setText("DISCONNECTED")
|
||||
botServerWindow.Data.Participants:setText("-")
|
||||
end
|
||||
end
|
||||
|
||||
macro(2000, function()
|
||||
if BotServer._websocket then
|
||||
BotServer.send("list")
|
||||
end
|
||||
updateStatusText()
|
||||
end)
|
||||
|
||||
local regex = [["(.*?)"]]
|
||||
BotServer.listen("list", function(name, data)
|
||||
serverCount = regexMatch(json.encode(data), regex)
|
||||
ServerMembers = json.encode(data)
|
||||
end)
|
||||
|
||||
ui.botServer.onClick = function(widget)
|
||||
botServerWindow:show()
|
||||
botServerWindow:raise()
|
||||
botServerWindow:focus()
|
||||
end
|
||||
|
||||
botServerWindow.closeButton.onClick = function(widget)
|
||||
botServerWindow:hide()
|
||||
end
|
||||
|
||||
-- scripts
|
||||
|
||||
-- mwalls
|
||||
config.mwalls = {}
|
||||
BotServer.listen("mwall", function(name, message)
|
||||
if config.mwallInfo then
|
||||
if not config.mwalls[message["pos"]] or config.mwalls[message["pos"]] < now then
|
||||
config.mwalls[message["pos"]] = now + message["duration"] - 150 -- 150 is latency correction
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
onAddThing(function(tile, thing)
|
||||
if config.mwallInfo then
|
||||
if thing:isItem() and thing:getId() == 2129 then
|
||||
local pos = tile:getPosition().x .. "," .. tile:getPosition().y .. "," .. tile:getPosition().z
|
||||
if not config.mwalls[pos] or config.mwalls[pos] < now then
|
||||
config.mwalls[pos] = now + 20000
|
||||
BotServer.send("mwall", {pos=pos, duration=20000})
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- mana
|
||||
local lastMana = 0
|
||||
macro(500, function()
|
||||
if config.manaInfo then
|
||||
if manapercent() ~= lastMana then
|
||||
lastMana = manapercent()
|
||||
BotServer.send("mana", {mana=lastMana})
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
BotServer.listen("mana", function(name, message)
|
||||
if config.manaInfo then
|
||||
local creature = getPlayerByName(name)
|
||||
if creature then
|
||||
creature:setManaPercent(message["mana"])
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- vocation
|
||||
if config.vocation then
|
||||
BotServer.send("voc", player:getVocation())
|
||||
BotServer.send("voc", "yes")
|
||||
end
|
||||
|
||||
BotServer.listen("voc", function(name, message)
|
||||
if message == "yes" and config.vocation then
|
||||
BotServer.send("voc", player:getVocation())
|
||||
else
|
||||
vBot.BotServerMembers[name] = message
|
||||
end
|
||||
end)
|
||||
|
||||
-- broadcast
|
||||
BotServer.listen("broadcast", function(name, message)
|
||||
if config.broadcasts then
|
||||
broadcastMessage(name..": "..message)
|
||||
end
|
||||
end)
|
||||
|
||||
addSeparator()
|
||||
188
modules/game_bot/default_configs/vBot_4.7/vBot/BotServer.otui
Normal file
188
modules/game_bot/default_configs/vBot_4.7/vBot/BotServer.otui
Normal file
@@ -0,0 +1,188 @@
|
||||
BotServerData < Panel
|
||||
size: 340 70
|
||||
image-source: /images/ui/window
|
||||
image-border: 6
|
||||
padding: 3
|
||||
|
||||
Label
|
||||
id: label
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
!text: tr("BotServer Data")
|
||||
|
||||
Label
|
||||
id: label
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-top: 23
|
||||
text-align: center
|
||||
text: Channel Name:
|
||||
margin-left: 6
|
||||
|
||||
TextEdit
|
||||
id: Channel
|
||||
anchors.top: parent.top
|
||||
anchors.left: prev.right
|
||||
margin-top: 20
|
||||
width: 150
|
||||
margin-left: 5
|
||||
text-align: center
|
||||
|
||||
Button
|
||||
id: Random
|
||||
anchors.left: prev.right
|
||||
anchors.top: prev.top
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
text: Randomize
|
||||
margin-left: 6
|
||||
margin-right: 6
|
||||
|
||||
Label
|
||||
id: label
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
margin-left: 6
|
||||
margin-bottom: 4
|
||||
text-align: center
|
||||
text: Status:
|
||||
|
||||
BotLabel
|
||||
id: ServerStatus
|
||||
anchors.left: prev.right
|
||||
anchors.bottom: parent.bottom
|
||||
margin-left: 10
|
||||
margin-bottom: 4
|
||||
text-align: center
|
||||
text: CONNECTED
|
||||
|
||||
BotLabel
|
||||
id: Participants
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 8
|
||||
margin-bottom: 4
|
||||
text-align: center
|
||||
|
||||
UIWidget
|
||||
id: Members
|
||||
anchors.right: Participants.left
|
||||
anchors.bottom: parent.bottom
|
||||
size: 80 21
|
||||
text-align: center
|
||||
text: Members:
|
||||
|
||||
FeaturePanel < Panel
|
||||
size: 340 150
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 5
|
||||
padding: 3
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text-align: center
|
||||
text: Features
|
||||
|
||||
HorizontalSeparator
|
||||
id: sep
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 2
|
||||
|
||||
BotSwitch
|
||||
id: Feature1
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
margin-left: 3
|
||||
margin-top: 5
|
||||
text: Mana info
|
||||
|
||||
BotSwitch
|
||||
id: Feature2
|
||||
anchors.top: sep.bottom
|
||||
anchors.left: prev.right
|
||||
margin-top: 5
|
||||
margin-left: 5
|
||||
text: MWall info
|
||||
|
||||
BotSwitch
|
||||
id: Feature3
|
||||
anchors.top: sep.bottom
|
||||
anchors.left: prev.right
|
||||
margin-top: 5
|
||||
margin-left: 5
|
||||
text: Send Vocation
|
||||
|
||||
BotSwitch
|
||||
id: Feature4
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
text: Outfit Vocation
|
||||
|
||||
BotSwitch
|
||||
id: Feature5
|
||||
anchors.bottom: prev.bottom
|
||||
anchors.left: prev.right
|
||||
margin-top: 3
|
||||
margin-left: 5
|
||||
text: Broadcasts
|
||||
|
||||
|
||||
TextEdit
|
||||
id: broadcastText
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
margin-bottom: 3
|
||||
margin-right: 80
|
||||
|
||||
Button
|
||||
id: Broadcast
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-right: 3
|
||||
margin-left: 3
|
||||
height: 22
|
||||
text: Broadcast
|
||||
|
||||
BotServerWindow < MainWindow
|
||||
!text: tr('BotServer')
|
||||
size: 370 310
|
||||
@onEscape: self:hide()
|
||||
|
||||
BotServerData
|
||||
id: Data
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
FeaturePanel
|
||||
id: Features
|
||||
anchors.top: prev.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
margin-top: 10
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 8
|
||||
|
||||
Button
|
||||
id: closeButton
|
||||
!text: tr('Close')
|
||||
font: cipsoftFont
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
margin-top: 15
|
||||
margin-right: 5
|
||||
262
modules/game_bot/default_configs/vBot_4.7/vBot/Conditions.lua
Normal file
262
modules/game_bot/default_configs/vBot_4.7/vBot/Conditions.lua
Normal file
@@ -0,0 +1,262 @@
|
||||
setDefaultTab("HP")
|
||||
local panelName = "ConditionPanel"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 19
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('Conditions')
|
||||
|
||||
Button
|
||||
id: conditionList
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Setup
|
||||
|
||||
]])
|
||||
ui:setId(panelName)
|
||||
|
||||
if not HealBotConfig[panelName] then
|
||||
HealBotConfig[panelName] = {
|
||||
enabled = false,
|
||||
curePosion = false,
|
||||
poisonCost = 20,
|
||||
cureCurse = false,
|
||||
curseCost = 80,
|
||||
cureBleed = false,
|
||||
bleedCost = 45,
|
||||
cureBurn = false,
|
||||
burnCost = 30,
|
||||
cureElectrify = false,
|
||||
electrifyCost = 22,
|
||||
cureParalyse = false,
|
||||
paralyseCost = 40,
|
||||
paralyseSpell = "utani hur",
|
||||
holdHaste = false,
|
||||
hasteCost = 40,
|
||||
hasteSpell = "utani hur",
|
||||
holdUtamo = false,
|
||||
utamoCost = 40,
|
||||
holdUtana = false,
|
||||
utanaCost = 440,
|
||||
holdUtura = false,
|
||||
uturaType = "",
|
||||
uturaCost = 100,
|
||||
ignoreInPz = true,
|
||||
stopHaste = false
|
||||
}
|
||||
end
|
||||
|
||||
local config = HealBotConfig[panelName]
|
||||
|
||||
ui.title:setOn(config.enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
config.enabled = not config.enabled
|
||||
widget:setOn(config.enabled)
|
||||
vBotConfigSave("heal")
|
||||
end
|
||||
|
||||
ui.conditionList.onClick = function(widget)
|
||||
conditionsWindow:show()
|
||||
conditionsWindow:raise()
|
||||
conditionsWindow:focus()
|
||||
end
|
||||
|
||||
|
||||
|
||||
local rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
conditionsWindow = UI.createWindow('ConditionsWindow', rootWidget)
|
||||
conditionsWindow:hide()
|
||||
|
||||
|
||||
conditionsWindow.onVisibilityChange = function(widget, visible)
|
||||
if not visible then
|
||||
vBotConfigSave("heal")
|
||||
end
|
||||
end
|
||||
|
||||
-- text edits
|
||||
conditionsWindow.Cure.PoisonCost:setText(config.poisonCost)
|
||||
conditionsWindow.Cure.PoisonCost.onTextChange = function(widget, text)
|
||||
config.poisonCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.CurseCost:setText(config.curseCost)
|
||||
conditionsWindow.Cure.CurseCost.onTextChange = function(widget, text)
|
||||
config.curseCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.BleedCost:setText(config.bleedCost)
|
||||
conditionsWindow.Cure.BleedCost.onTextChange = function(widget, text)
|
||||
config.bleedCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.BurnCost:setText(config.burnCost)
|
||||
conditionsWindow.Cure.BurnCost.onTextChange = function(widget, text)
|
||||
config.burnCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.ElectrifyCost:setText(config.electrifyCost)
|
||||
conditionsWindow.Cure.ElectrifyCost.onTextChange = function(widget, text)
|
||||
config.electrifyCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.ParalyseCost:setText(config.paralyseCost)
|
||||
conditionsWindow.Cure.ParalyseCost.onTextChange = function(widget, text)
|
||||
config.paralyseCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.ParalyseSpell:setText(config.paralyseSpell)
|
||||
conditionsWindow.Cure.ParalyseSpell.onTextChange = function(widget, text)
|
||||
config.paralyseSpell = text
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.HasteSpell:setText(config.hasteSpell)
|
||||
conditionsWindow.Hold.HasteSpell.onTextChange = function(widget, text)
|
||||
config.hasteSpell = text
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.HasteCost:setText(config.hasteCost)
|
||||
conditionsWindow.Hold.HasteCost.onTextChange = function(widget, text)
|
||||
config.hasteCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.UtamoCost:setText(config.utamoCost)
|
||||
conditionsWindow.Hold.UtamoCost.onTextChange = function(widget, text)
|
||||
config.utamoCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.UtanaCost:setText(config.utanaCost)
|
||||
conditionsWindow.Hold.UtanaCost.onTextChange = function(widget, text)
|
||||
config.utanaCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.UturaCost:setText(config.uturaCost)
|
||||
conditionsWindow.Hold.UturaCost.onTextChange = function(widget, text)
|
||||
config.uturaCost = tonumber(text)
|
||||
end
|
||||
|
||||
-- combo box
|
||||
conditionsWindow.Hold.UturaType:setOption(config.uturaType)
|
||||
conditionsWindow.Hold.UturaType.onOptionChange = function(widget)
|
||||
config.uturaType = widget:getCurrentOption().text
|
||||
end
|
||||
|
||||
-- checkboxes
|
||||
conditionsWindow.Cure.CurePoison:setChecked(config.curePoison)
|
||||
conditionsWindow.Cure.CurePoison.onClick = function(widget)
|
||||
config.curePoison = not config.curePoison
|
||||
widget:setChecked(config.curePoison)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.CureCurse:setChecked(config.cureCurse)
|
||||
conditionsWindow.Cure.CureCurse.onClick = function(widget)
|
||||
config.cureCurse = not config.cureCurse
|
||||
widget:setChecked(config.cureCurse)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.CureBleed:setChecked(config.cureBleed)
|
||||
conditionsWindow.Cure.CureBleed.onClick = function(widget)
|
||||
config.cureBleed = not config.cureBleed
|
||||
widget:setChecked(config.cureBleed)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.CureBurn:setChecked(config.cureBurn)
|
||||
conditionsWindow.Cure.CureBurn.onClick = function(widget)
|
||||
config.cureBurn = not config.cureBurn
|
||||
widget:setChecked(config.cureBurn)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.CureElectrify:setChecked(config.cureElectrify)
|
||||
conditionsWindow.Cure.CureElectrify.onClick = function(widget)
|
||||
config.cureElectrify = not config.cureElectrify
|
||||
widget:setChecked(config.cureElectrify)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.CureParalyse:setChecked(config.cureParalyse)
|
||||
conditionsWindow.Cure.CureParalyse.onClick = function(widget)
|
||||
config.cureParalyse = not config.cureParalyse
|
||||
widget:setChecked(config.cureParalyse)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.HoldHaste:setChecked(config.holdHaste)
|
||||
conditionsWindow.Hold.HoldHaste.onClick = function(widget)
|
||||
config.holdHaste = not config.holdHaste
|
||||
widget:setChecked(config.holdHaste)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.HoldUtamo:setChecked(config.holdUtamo)
|
||||
conditionsWindow.Hold.HoldUtamo.onClick = function(widget)
|
||||
config.holdUtamo = not config.holdUtamo
|
||||
widget:setChecked(config.holdUtamo)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.HoldUtana:setChecked(config.holdUtana)
|
||||
conditionsWindow.Hold.HoldUtana.onClick = function(widget)
|
||||
config.holdUtana = not config.holdUtana
|
||||
widget:setChecked(config.holdUtana)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.HoldUtura:setChecked(config.holdUtura)
|
||||
conditionsWindow.Hold.HoldUtura.onClick = function(widget)
|
||||
config.holdUtura = not config.holdUtura
|
||||
widget:setChecked(config.holdUtura)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.IgnoreInPz:setChecked(config.ignoreInPz)
|
||||
conditionsWindow.Hold.IgnoreInPz.onClick = function(widget)
|
||||
config.ignoreInPz = not config.ignoreInPz
|
||||
widget:setChecked(config.ignoreInPz)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.StopHaste:setChecked(config.stopHaste)
|
||||
conditionsWindow.Hold.StopHaste.onClick = function(widget)
|
||||
config.stopHaste = not config.stopHaste
|
||||
widget:setChecked(config.stopHaste)
|
||||
end
|
||||
|
||||
-- buttons
|
||||
conditionsWindow.closeButton.onClick = function(widget)
|
||||
conditionsWindow:hide()
|
||||
end
|
||||
|
||||
Conditions = {}
|
||||
Conditions.show = function()
|
||||
conditionsWindow:show()
|
||||
conditionsWindow:raise()
|
||||
conditionsWindow:focus()
|
||||
end
|
||||
end
|
||||
|
||||
local utanaCast = nil
|
||||
macro(500, function()
|
||||
if not config.enabled or modules.game_cooldown.isGroupCooldownIconActive(2) then return end
|
||||
if hppercent() > 95 then
|
||||
if config.curePoison and mana() >= config.poisonCost and isPoisioned() then say("exana pox")
|
||||
elseif config.cureCurse and mana() >= config.curseCost and isCursed() then say("exana mort")
|
||||
elseif config.cureBleed and mana() >= config.bleedCost and isBleeding() then say("exana kor")
|
||||
elseif config.cureBurn and mana() >= config.burnCost and isBurning() then say("exana flam")
|
||||
elseif config.cureElectrify and mana() >= config.electrifyCost and isEnergized() then say("exana vis")
|
||||
end
|
||||
end
|
||||
if (not config.ignoreInPz or not isInPz()) and config.holdUtura and mana() >= config.uturaCost and canCast(config.uturaType) and hppercent() < 90 then say(config.uturaType)
|
||||
elseif (not config.ignoreInPz or not isInPz()) and config.holdUtana and mana() >= config.utanaCost and (not utanaCast or (now - utanaCast > 120000)) then say("utana vid") utanaCast = now
|
||||
end
|
||||
end)
|
||||
|
||||
macro(50, function()
|
||||
if not config.enabled then return end
|
||||
if (not config.ignoreInPz or not isInPz()) and config.holdUtamo and mana() >= config.utamoCost and not hasManaShield() then say("utamo vita")
|
||||
elseif ((not config.ignoreInPz or not isInPz()) and standTime() < 5000 and config.holdHaste and mana() >= config.hasteCost and not hasHaste() and not getSpellCoolDown(config.hasteSpell) and (not target() or not config.stopHaste or TargetBot.isCaveBotActionAllowed())) and standTime() < 3000 then say(config.hasteSpell)
|
||||
elseif config.cureParalyse and mana() >= config.paralyseCost and isParalyzed() and not getSpellCoolDown(config.paralyseSpell) then say(config.paralyseSpell)
|
||||
end
|
||||
end)
|
||||
463
modules/game_bot/default_configs/vBot_4.7/vBot/Conditions.otui
Normal file
463
modules/game_bot/default_configs/vBot_4.7/vBot/Conditions.otui
Normal file
@@ -0,0 +1,463 @@
|
||||
UturaComboBoxPopupMenu < ComboBoxPopupMenu
|
||||
UturaComboBoxPopupMenuButton < ComboBoxPopupMenuButton
|
||||
UturaComboBox < ComboBox
|
||||
@onSetup: |
|
||||
self:addOption("Utura")
|
||||
self:addOption("Utura Gran")
|
||||
|
||||
CureConditions < Panel
|
||||
id: Cure
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 6
|
||||
padding: 3
|
||||
size: 200 190
|
||||
|
||||
Label
|
||||
id: label1
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-top: 10
|
||||
margin-left: 5
|
||||
text: Poison
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label11
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 40
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: PoisonCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: CurePoison
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label2
|
||||
anchors.left: label1.left
|
||||
anchors.top: label1.bottom
|
||||
margin-top: 10
|
||||
text: Curse
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label22
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 44
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: CurseCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: CureCurse
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label3
|
||||
anchors.left: label2.left
|
||||
anchors.top: label2.bottom
|
||||
margin-top: 10
|
||||
text: Bleed
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label33
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 46
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: BleedCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: CureBleed
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label4
|
||||
anchors.left: label3.left
|
||||
anchors.top: label3.bottom
|
||||
margin-top: 10
|
||||
text: Burn
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label44
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 50
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: BurnCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: CureBurn
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label5
|
||||
anchors.left: label4.left
|
||||
anchors.top: label4.bottom
|
||||
margin-top: 10
|
||||
text: Electify
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label55
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 33
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: ElectrifyCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: CureElectrify
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label6
|
||||
anchors.left: label5.left
|
||||
anchors.top: label5.bottom
|
||||
margin-top: 10
|
||||
text: Paralyse
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label66
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 26
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: ParalyseCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: CureParalyse
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label7
|
||||
anchors.left: label6.left
|
||||
anchors.top: label6.bottom
|
||||
margin-top: 10
|
||||
margin-left: 12
|
||||
text: Spell:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: ParalyseSpell
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 10
|
||||
width: 100
|
||||
font: verdana-11px-rounded
|
||||
|
||||
HoldConditions < Panel
|
||||
id: Hold
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 6
|
||||
padding: 3
|
||||
size: 200 190
|
||||
|
||||
Label
|
||||
id: label1
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-top: 10
|
||||
margin-left: 5
|
||||
text: Haste
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label11
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 44
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: HasteCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: HoldHaste
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label2
|
||||
anchors.left: label1.left
|
||||
anchors.top: label1.bottom
|
||||
margin-top: 10
|
||||
margin-left: 12
|
||||
text: Spell:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: HasteSpell
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 10
|
||||
width: 100
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label3
|
||||
anchors.left: label1.left
|
||||
anchors.top: label2.bottom
|
||||
margin-top: 10
|
||||
text: Utana Vid
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label33
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 21
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: UtanaCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: HoldUtana
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label4
|
||||
anchors.left: label3.left
|
||||
anchors.top: label3.bottom
|
||||
margin-top: 10
|
||||
text: Utamo Vita
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label44
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 12
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: UtamoCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: HoldUtamo
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label5
|
||||
anchors.left: label4.left
|
||||
anchors.top: label4.bottom
|
||||
margin-top: 10
|
||||
text: Recovery
|
||||
color: #ffaa00
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: label55
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 20
|
||||
text: Mana:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: UturaCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: HoldUtura
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: label6
|
||||
anchors.left: label5.left
|
||||
anchors.top: label5.bottom
|
||||
margin-top: 10
|
||||
margin-left: 12
|
||||
text: Spell:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
UturaComboBox
|
||||
id: UturaType
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 10
|
||||
width: 100
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: IgnoreInPz
|
||||
anchors.left: label5.left
|
||||
anchors.top: label6.bottom
|
||||
margin-top: 12
|
||||
|
||||
Label
|
||||
anchors.verticalCenter: IgnoreInPz.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-top: 3
|
||||
margin-left: 5
|
||||
text: Don't Cast in Protection Zones
|
||||
font: cipsoftFont
|
||||
|
||||
CheckBox
|
||||
id: StopHaste
|
||||
anchors.horizontalCenter: IgnoreInPz.horizontalCenter
|
||||
anchors.top: IgnoreInPz.bottom
|
||||
margin-top: 8
|
||||
|
||||
Label
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-top: 3
|
||||
margin-left: 5
|
||||
text: Stop Haste if TargetBot Is Active
|
||||
font: cipsoftFont
|
||||
|
||||
ConditionsWindow < MainWindow
|
||||
!text: tr('Condition Manager')
|
||||
size: 445 280
|
||||
@onEscape: self:hide()
|
||||
|
||||
CureConditions
|
||||
id: Cure
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-top: 7
|
||||
|
||||
Label
|
||||
id: label
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text: Cure Conditions
|
||||
color: #88e3dd
|
||||
margin-left: 10
|
||||
font: verdana-11px-rounded
|
||||
|
||||
HoldConditions
|
||||
id: Hold
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
margin-top: 7
|
||||
|
||||
Label
|
||||
id: label
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
text: Hold Conditions
|
||||
color: #88e3dd
|
||||
margin-right: 100
|
||||
font: verdana-11px-rounded
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 8
|
||||
|
||||
Button
|
||||
id: closeButton
|
||||
!text: tr('Close')
|
||||
font: cipsoftFont
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
margin-top: 15
|
||||
margin-right: 5
|
||||
674
modules/game_bot/default_configs/vBot_4.7/vBot/Containers.lua
Normal file
674
modules/game_bot/default_configs/vBot_4.7/vBot/Containers.lua
Normal file
@@ -0,0 +1,674 @@
|
||||
setDefaultTab("Tools")
|
||||
local panelName = "renameContainers"
|
||||
if type(storage[panelName]) ~= "table" then
|
||||
storage[panelName] = {
|
||||
enabled = false;
|
||||
height = 170,
|
||||
purse = true;
|
||||
list = {
|
||||
{
|
||||
value = "Main Backpack",
|
||||
enabled = true,
|
||||
item = 9601,
|
||||
min = false,
|
||||
items = { 3081, 3048 }
|
||||
},
|
||||
{
|
||||
value = "Runes",
|
||||
enabled = true,
|
||||
item = 2866,
|
||||
min = true,
|
||||
items = { 3161, 3180 }
|
||||
},
|
||||
{
|
||||
value = "Money",
|
||||
enabled = true,
|
||||
item = 2871,
|
||||
min = true,
|
||||
items = { 3031, 3035, 3043 }
|
||||
},
|
||||
{
|
||||
value = "Purse",
|
||||
enabled = true,
|
||||
item = 23396,
|
||||
min = true,
|
||||
items = {}
|
||||
},
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
local config = storage[panelName]
|
||||
|
||||
UI.Separator()
|
||||
local renameContui = setupUI([[
|
||||
Panel
|
||||
height: 50
|
||||
|
||||
Label
|
||||
text-align: center
|
||||
text: Container Panel
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
font: verdana-11px-rounded
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('Open Minimised')
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Button
|
||||
id: editContList
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Setup
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Button
|
||||
id: reopenCont
|
||||
!text: tr('Reopen All')
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
anchors.right: parent.horizontalCenter
|
||||
margin-right: 2
|
||||
height: 17
|
||||
margin-top: 3
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Button
|
||||
id: minimiseCont
|
||||
!text: tr('Minimise All')
|
||||
anchors.top: prev.top
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
margin-right: 2
|
||||
height: 17
|
||||
font: verdana-11px-rounded
|
||||
]])
|
||||
renameContui:setId(panelName)
|
||||
|
||||
g_ui.loadUIFromString([[
|
||||
BackpackName < Label
|
||||
background-color: alpha
|
||||
text-offset: 18 2
|
||||
focusable: true
|
||||
height: 17
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: enabled
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 15
|
||||
height: 15
|
||||
margin-top: 1
|
||||
margin-left: 3
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
Button
|
||||
id: state
|
||||
!text: tr('M')
|
||||
anchors.right: remove.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
margin-right: 1
|
||||
width: 15
|
||||
height: 15
|
||||
|
||||
Button
|
||||
id: remove
|
||||
!text: tr('X')
|
||||
!tooltip: tr('Remove')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
margin-right: 15
|
||||
width: 15
|
||||
height: 15
|
||||
|
||||
Button
|
||||
id: openNext
|
||||
!text: tr('N')
|
||||
anchors.right: state.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
margin-right: 1
|
||||
width: 15
|
||||
height: 15
|
||||
tooltip: Open container inside with the same ID.
|
||||
|
||||
ContListsWindow < MainWindow
|
||||
!text: tr('Container Names')
|
||||
size: 465 170
|
||||
@onEscape: self:hide()
|
||||
|
||||
TextList
|
||||
id: itemList
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: separator.top
|
||||
width: 200
|
||||
margin-bottom: 6
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
vertical-scrollbar: itemListScrollBar
|
||||
|
||||
VerticalScrollBar
|
||||
id: itemListScrollBar
|
||||
anchors.top: itemList.top
|
||||
anchors.bottom: itemList.bottom
|
||||
anchors.right: itemList.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
VerticalSeparator
|
||||
id: sep
|
||||
anchors.top: parent.top
|
||||
anchors.left: itemList.right
|
||||
anchors.bottom: separator.top
|
||||
margin-top: 3
|
||||
margin-bottom: 6
|
||||
margin-left: 10
|
||||
|
||||
Label
|
||||
id: lblName
|
||||
anchors.left: sep.right
|
||||
anchors.top: sep.top
|
||||
width: 70
|
||||
text: Name:
|
||||
margin-left: 10
|
||||
margin-top: 3
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: contName
|
||||
anchors.left: lblName.right
|
||||
anchors.top: sep.top
|
||||
anchors.right: parent.right
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: lblCont
|
||||
anchors.left: lblName.left
|
||||
anchors.verticalCenter: contId.verticalCenter
|
||||
width: 70
|
||||
text: Container:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
BotItem
|
||||
id: contId
|
||||
anchors.left: contName.left
|
||||
anchors.top: contName.bottom
|
||||
margin-top: 3
|
||||
|
||||
BotContainer
|
||||
id: sortList
|
||||
anchors.left: prev.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
anchors.bottom: separator.top
|
||||
margin-bottom: 6
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
anchors.left: lblCont.left
|
||||
anchors.verticalCenter: sortList.verticalCenter
|
||||
width: 70
|
||||
text: Items:
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Button
|
||||
id: addItem
|
||||
anchors.right: contName.right
|
||||
anchors.top: contName.bottom
|
||||
margin-top: 5
|
||||
text: Add
|
||||
width: 40
|
||||
font: cipsoftFont
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 8
|
||||
|
||||
CheckBox
|
||||
id: purse
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
text: Open Purse
|
||||
tooltip: Opens Store/Charm Purse
|
||||
width: 85
|
||||
height: 15
|
||||
margin-top: 2
|
||||
margin-left: 3
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: sort
|
||||
anchors.left: prev.right
|
||||
anchors.bottom: parent.bottom
|
||||
text: Sort Items
|
||||
tooltip: Sort items based on items widget
|
||||
width: 85
|
||||
height: 15
|
||||
margin-top: 2
|
||||
margin-left: 15
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: forceOpen
|
||||
anchors.left: prev.right
|
||||
anchors.bottom: parent.bottom
|
||||
text: Keep Open
|
||||
tooltip: Will keep open containers all the time
|
||||
width: 85
|
||||
height: 15
|
||||
margin-top: 2
|
||||
margin-left: 15
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: lootBag
|
||||
anchors.left: prev.right
|
||||
anchors.bottom: parent.bottom
|
||||
text: Loot Bag
|
||||
tooltip: Open Loot Bag (gunzodus franchaise)
|
||||
width: 85
|
||||
height: 15
|
||||
margin-top: 2
|
||||
margin-left: 15
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Button
|
||||
id: closeButton
|
||||
!text: tr('Close')
|
||||
font: cipsoftFont
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
margin-top: 15
|
||||
|
||||
ResizeBorder
|
||||
id: bottomResizeBorder
|
||||
anchors.fill: separator
|
||||
height: 3
|
||||
minimum: 170
|
||||
maximum: 245
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
background: #ffffff88
|
||||
]])
|
||||
|
||||
function findItemsInArray(t, tfind)
|
||||
local tArray = {}
|
||||
for x,v in pairs(t) do
|
||||
if type(v) == "table" then
|
||||
local aItem = t[x].item
|
||||
local aEnabled = t[x].enabled
|
||||
if aItem then
|
||||
if tfind and aItem == tfind then
|
||||
return x
|
||||
elseif not tfind then
|
||||
if aEnabled then
|
||||
table.insert(tArray, aItem)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if not tfind then return tArray end
|
||||
end
|
||||
|
||||
local lstBPs
|
||||
|
||||
|
||||
local openContainer = function(id)
|
||||
local t = {getRight(), getLeft(), getAmmo()} -- if more slots needed then add them here
|
||||
for i=1,#t do
|
||||
local slotItem = t[i]
|
||||
if slotItem and slotItem:getId() == id then
|
||||
return g_game.open(slotItem, nil)
|
||||
end
|
||||
end
|
||||
|
||||
for i, container in pairs(g_game.getContainers()) do
|
||||
for i, item in ipairs(container:getItems()) do
|
||||
if item:isContainer() and item:getId() == id then
|
||||
return g_game.open(item, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function reopenBackpacks()
|
||||
lstBPs = findItemsInArray(config.list)
|
||||
|
||||
for _, container in pairs(g_game.getContainers()) do g_game.close(container) end
|
||||
bpItem = getBack()
|
||||
if bpItem ~= nil then
|
||||
g_game.open(bpItem)
|
||||
end
|
||||
|
||||
schedule(500, function()
|
||||
local delay = 200
|
||||
|
||||
if config.purse then
|
||||
local item = getPurse()
|
||||
if item then
|
||||
use(item)
|
||||
end
|
||||
end
|
||||
for i=1,#lstBPs do
|
||||
schedule(delay, function()
|
||||
openContainer(lstBPs[i])
|
||||
end)
|
||||
delay = delay + 250
|
||||
end
|
||||
end)
|
||||
|
||||
end
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
contListWindow = UI.createWindow('ContListsWindow', rootWidget)
|
||||
contListWindow:hide()
|
||||
|
||||
contListWindow.onGeometryChange = function(widget, old, new)
|
||||
if old.height == 0 then return end
|
||||
|
||||
config.height = new.height
|
||||
end
|
||||
|
||||
contListWindow:setHeight(config.height or 170)
|
||||
|
||||
renameContui.editContList.onClick = function(widget)
|
||||
contListWindow:show()
|
||||
contListWindow:raise()
|
||||
contListWindow:focus()
|
||||
end
|
||||
|
||||
renameContui.reopenCont.onClick = function(widget)
|
||||
reopenBackpacks()
|
||||
end
|
||||
|
||||
renameContui.minimiseCont.onClick = function(widget)
|
||||
for i, container in ipairs(getContainers()) do
|
||||
local containerWindow = container.window
|
||||
containerWindow:setContentHeight(34)
|
||||
end
|
||||
end
|
||||
|
||||
renameContui.title:setOn(config.enabled)
|
||||
renameContui.title.onClick = function(widget)
|
||||
config.enabled = not config.enabled
|
||||
widget:setOn(config.enabled)
|
||||
end
|
||||
|
||||
contListWindow.closeButton.onClick = function(widget)
|
||||
contListWindow:hide()
|
||||
end
|
||||
|
||||
contListWindow.purse.onClick = function(widget)
|
||||
config.purse = not config.purse
|
||||
contListWindow.purse:setChecked(config.purse)
|
||||
end
|
||||
contListWindow.purse:setChecked(config.purse)
|
||||
|
||||
contListWindow.sort.onClick = function(widget)
|
||||
config.sort = not config.sort
|
||||
contListWindow.sort:setChecked(config.sort)
|
||||
end
|
||||
contListWindow.sort:setChecked(config.sort)
|
||||
|
||||
contListWindow.forceOpen.onClick = function(widget)
|
||||
config.forceOpen = not config.forceOpen
|
||||
contListWindow.forceOpen:setChecked(config.forceOpen)
|
||||
end
|
||||
contListWindow.forceOpen:setChecked(config.forceOpen)
|
||||
|
||||
contListWindow.lootBag.onClick = function(widget)
|
||||
config.lootBag = not config.lootBag
|
||||
contListWindow.lootBag:setChecked(config.lootBag)
|
||||
end
|
||||
contListWindow.lootBag:setChecked(config.lootBag)
|
||||
|
||||
local function refreshSortList(k, t)
|
||||
t = t or {}
|
||||
UI.Container(function()
|
||||
t = contListWindow.sortList:getItems()
|
||||
config.list[k].items = t
|
||||
end, true, nil, contListWindow.sortList)
|
||||
contListWindow.sortList:setItems(t)
|
||||
end
|
||||
refreshSortList(t)
|
||||
|
||||
local refreshContNames = function(tFocus)
|
||||
local storageVal = config.list
|
||||
if storageVal and #storageVal > 0 then
|
||||
for i, child in pairs(contListWindow.itemList:getChildren()) do
|
||||
child:destroy()
|
||||
end
|
||||
for k, entry in pairs(storageVal) do
|
||||
local label = g_ui.createWidget("BackpackName", contListWindow.itemList)
|
||||
label.onMouseRelease = function()
|
||||
contListWindow.contId:setItemId(entry.item)
|
||||
contListWindow.contName:setText(entry.value)
|
||||
if not entry.items then
|
||||
entry.items = {}
|
||||
end
|
||||
contListWindow.sortList:setItems(entry.items)
|
||||
refreshSortList(k, entry.items)
|
||||
end
|
||||
label.enabled.onClick = function(widget)
|
||||
entry.enabled = not entry.enabled
|
||||
label.enabled:setChecked(entry.enabled)
|
||||
label.enabled:setTooltip(entry.enabled and 'Disable' or 'Enable')
|
||||
label.enabled:setImageColor(entry.enabled and '#00FF00' or '#FF0000')
|
||||
end
|
||||
label.remove.onClick = function(widget)
|
||||
table.removevalue(config.list, entry)
|
||||
label:destroy()
|
||||
end
|
||||
label.state:setChecked(entry.min)
|
||||
label.state.onClick = function(widget)
|
||||
entry.min = not entry.min
|
||||
label.state:setChecked(entry.min)
|
||||
label.state:setColor(entry.min and '#00FF00' or '#FF0000')
|
||||
label.state:setTooltip(entry.min and 'Open Minimised' or 'Do not minimise')
|
||||
end
|
||||
label.openNext.onClick = function(widget)
|
||||
entry.openNext = not entry.openNext
|
||||
label.openNext:setChecked(entry.openNext)
|
||||
label.openNext:setColor(entry.openNext and '#00FF00' or '#FF0000')
|
||||
end
|
||||
label:setText(entry.value)
|
||||
label.enabled:setChecked(entry.enabled)
|
||||
label.enabled:setTooltip(entry.enabled and 'Disable' or 'Enable')
|
||||
label.enabled:setImageColor(entry.enabled and '#00FF00' or '#FF0000')
|
||||
label.state:setColor(entry.min and '#00FF00' or '#FF0000')
|
||||
label.state:setTooltip(entry.min and 'Open Minimised' or 'Do not minimise')
|
||||
label.openNext:setColor(entry.openNext and '#00FF00' or '#FF0000')
|
||||
|
||||
if tFocus and entry.item == tFocus then
|
||||
tFocus = label
|
||||
end
|
||||
end
|
||||
if tFocus then contListWindow.itemList:focusChild(tFocus) end
|
||||
end
|
||||
end
|
||||
contListWindow.addItem.onClick = function(widget)
|
||||
local id = contListWindow.contId:getItemId()
|
||||
local trigger = contListWindow.contName:getText()
|
||||
|
||||
if id > 100 and trigger:len() > 0 then
|
||||
local ifind = findItemsInArray(config.list, id)
|
||||
if ifind then
|
||||
config.list[ifind] = { item = id, value = trigger, enabled = config.list[ifind].enabled, min = config.list[ifind].min, items = config.list[ifind].items}
|
||||
else
|
||||
table.insert(config.list, { item = id, value = trigger, enabled = true, min = false, items = {} })
|
||||
end
|
||||
contListWindow.contId:setItemId(0)
|
||||
contListWindow.contName:setText('')
|
||||
contListWindow.contName:setColor('white')
|
||||
contListWindow.contName:setImageColor('#ffffff')
|
||||
contListWindow.contId:setImageColor('#ffffff')
|
||||
refreshContNames(id)
|
||||
else
|
||||
contListWindow.contId:setImageColor('red')
|
||||
contListWindow.contName:setImageColor('red')
|
||||
contListWindow.contName:setColor('red')
|
||||
end
|
||||
end
|
||||
refreshContNames()
|
||||
end
|
||||
|
||||
onContainerOpen(function(container, previousContainer)
|
||||
if not container.window then return end
|
||||
local containerWindow = container.window
|
||||
if not previousContainer then
|
||||
containerWindow:setContentHeight(34)
|
||||
end
|
||||
|
||||
local storageVal = config.list
|
||||
if storageVal and #storageVal > 0 then
|
||||
for _, entry in pairs(storageVal) do
|
||||
if entry.enabled and string.find(container:getContainerItem():getId(), entry.item) then
|
||||
if entry.min then
|
||||
containerWindow:minimize()
|
||||
end
|
||||
if renameContui.title:isOn() then
|
||||
containerWindow:setText(entry.value)
|
||||
end
|
||||
if entry.openNext then
|
||||
for i, item in ipairs(container:getItems()) do
|
||||
if item:getId() == entry.item then
|
||||
local time = #storageVal * 250
|
||||
schedule(time, function()
|
||||
time = time + 250
|
||||
g_game.open(item)
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local function nameContainersOnLogin()
|
||||
for i, container in ipairs(getContainers()) do
|
||||
if renameContui.title:isOn() then
|
||||
if not container.window then return end
|
||||
local containerWindow = container.window
|
||||
local storageVal = config.list
|
||||
if storageVal and #storageVal > 0 then
|
||||
for _, entry in pairs(storageVal) do
|
||||
if entry.enabled and string.find(container:getContainerItem():getId(), entry.item) then
|
||||
containerWindow:setText(entry.value)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
nameContainersOnLogin()
|
||||
|
||||
local function moveItem(item, destination)
|
||||
return g_game.move(item, destination:getSlotPosition(destination:getItemsCount()), item:getCount())
|
||||
end
|
||||
|
||||
local function properTable(t)
|
||||
local r = {}
|
||||
for _, entry in pairs(t) do
|
||||
if type(entry) == "number" then
|
||||
table.insert(r, entry)
|
||||
else
|
||||
table.insert(r, entry.id)
|
||||
end
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
local mainLoop = macro(150, function(macro)
|
||||
if not config.sort and not config.purse then return end
|
||||
|
||||
local storageVal = config.list
|
||||
for _, entry in pairs(storageVal) do
|
||||
local dId = entry.item
|
||||
local items = properTable(entry.items)
|
||||
-- sorting
|
||||
if config.sort then
|
||||
for _, container in pairs(getContainers()) do
|
||||
local cName = container:getName():lower()
|
||||
if not cName:find("depot") and not cName:find("depot") and not cName:find("quiver") then
|
||||
local cId = container:getContainerItem():getId()
|
||||
for __, item in ipairs(container:getItems()) do
|
||||
local id = item:getId()
|
||||
if table.find(items, id) and cId ~= dId then
|
||||
local destination = getContainerByItem(dId, true)
|
||||
if destination and not containerIsFull(destination) then
|
||||
return moveItem(item, destination)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- keep open / purse 23396
|
||||
if config.forceOpen then
|
||||
local container = getContainerByItem(dId)
|
||||
if not container then
|
||||
local t = {getBack(), getAmmo(), getFinger(), getNeck(), getLeft(), getRight()}
|
||||
for i=1,#t do
|
||||
local slot = t[i]
|
||||
if slot and slot:getId() == dId then
|
||||
return g_game.open(slot)
|
||||
end
|
||||
end
|
||||
local cItem = findItem(dId)
|
||||
if cItem then
|
||||
return g_game.open(cItem)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if config.purse and config.forceOpen and not getContainerByItem(23396) then
|
||||
return use(getPurse())
|
||||
end
|
||||
if config.lootBag and config.forceOpen and not getContainerByItem(23721) then
|
||||
if findItem(23721) then
|
||||
g_game.open(findItem(23721), getContainerByItem(23396))
|
||||
else
|
||||
return use(getPurse())
|
||||
end
|
||||
end
|
||||
macro:setOff()
|
||||
end)
|
||||
|
||||
|
||||
onContainerOpen(function(container, previousContainer)
|
||||
mainLoop:setOn()
|
||||
end)
|
||||
|
||||
onAddItem(function(container, slot, item, oldItem)
|
||||
mainLoop:setOn()
|
||||
end)
|
||||
|
||||
onPlayerInventoryChange(function(slot, item, oldItem)
|
||||
mainLoop:setOn()
|
||||
end)
|
||||
|
||||
onContainerClose(function(container)
|
||||
if not container.lootContainer then
|
||||
mainLoop:setOn()
|
||||
end
|
||||
end)
|
||||
146
modules/game_bot/default_configs/vBot_4.7/vBot/Dropper.lua
Normal file
146
modules/game_bot/default_configs/vBot_4.7/vBot/Dropper.lua
Normal file
@@ -0,0 +1,146 @@
|
||||
setDefaultTab("Tools")
|
||||
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 19
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('Dropper')
|
||||
|
||||
Button
|
||||
id: edit
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Edit
|
||||
]])
|
||||
|
||||
local edit = setupUI([[
|
||||
Panel
|
||||
height: 150
|
||||
|
||||
Label
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 5
|
||||
text-align: center
|
||||
text: Trash:
|
||||
|
||||
BotContainer
|
||||
id: TrashItems
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 32
|
||||
|
||||
Label
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
text: Use:
|
||||
|
||||
BotContainer
|
||||
id: UseItems
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 32
|
||||
|
||||
Label
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
text: Drop if below 150 cap:
|
||||
|
||||
BotContainer
|
||||
id: CapItems
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 32
|
||||
]])
|
||||
edit:hide()
|
||||
|
||||
if not storage.dropper then
|
||||
storage.dropper = {
|
||||
enabled = false,
|
||||
trashItems = { 283, 284, 285 },
|
||||
useItems = { 21203, 14758 },
|
||||
capItems = { 21175 }
|
||||
}
|
||||
end
|
||||
|
||||
local config = storage.dropper
|
||||
|
||||
local showEdit = false
|
||||
ui.edit.onClick = function(widget)
|
||||
showEdit = not showEdit
|
||||
if showEdit then
|
||||
edit:show()
|
||||
else
|
||||
edit:hide()
|
||||
end
|
||||
end
|
||||
|
||||
ui.title:setOn(config.enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
config.enabled = not config.enabled
|
||||
ui.title:setOn(config.enabled)
|
||||
end
|
||||
|
||||
UI.Container(function()
|
||||
config.trashItems = edit.TrashItems:getItems()
|
||||
end, true, nil, edit.TrashItems)
|
||||
edit.TrashItems:setItems(config.trashItems)
|
||||
|
||||
UI.Container(function()
|
||||
config.useItems = edit.UseItems:getItems()
|
||||
end, true, nil, edit.UseItems)
|
||||
edit.UseItems:setItems(config.useItems)
|
||||
|
||||
UI.Container(function()
|
||||
config.capItems = edit.CapItems:getItems()
|
||||
end, true, nil, edit.CapItems)
|
||||
edit.CapItems:setItems(config.capItems)
|
||||
|
||||
local function properTable(t)
|
||||
local r = {}
|
||||
|
||||
for _, entry in pairs(t) do
|
||||
table.insert(r, entry.id)
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
macro(200, function()
|
||||
if not config.enabled then return end
|
||||
local tables = {properTable(config.capItems), properTable(config.useItems), properTable(config.trashItems)}
|
||||
|
||||
local containers = getContainers()
|
||||
for i=1,3 do
|
||||
for _, container in pairs(containers) do
|
||||
for __, item in ipairs(container:getItems()) do
|
||||
for ___, userItem in ipairs(tables[i]) do
|
||||
if item:getId() == userItem then
|
||||
return i == 1 and freecap() < 150 and dropItem(item) or
|
||||
i == 2 and use(item) or
|
||||
i == 3 and dropItem(item)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
||||
770
modules/game_bot/default_configs/vBot_4.7/vBot/Equipper.lua
Normal file
770
modules/game_bot/default_configs/vBot_4.7/vBot/Equipper.lua
Normal file
@@ -0,0 +1,770 @@
|
||||
local panelName = "EquipperPanel"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 19
|
||||
|
||||
BotSwitch
|
||||
id: switch
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('EQ Manager')
|
||||
|
||||
Button
|
||||
id: setup
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Setup
|
||||
]])
|
||||
ui:setId(panelName)
|
||||
|
||||
if not storage[panelName] or not storage[panelName].bosses then -- no bosses - old ver
|
||||
storage[panelName] = {
|
||||
enabled = false,
|
||||
rules = {},
|
||||
bosses = {}
|
||||
}
|
||||
end
|
||||
|
||||
local config = storage[panelName]
|
||||
|
||||
ui.switch:setOn(config.enabled)
|
||||
ui.switch.onClick = function(widget)
|
||||
config.enabled = not config.enabled
|
||||
widget:setOn(config.enabled)
|
||||
end
|
||||
|
||||
local conditions = { -- always add new conditions at the bottom
|
||||
"Item is available and not worn.", -- nothing 1
|
||||
"Monsters around is more than: ", -- spinbox 2
|
||||
"Monsters around is less than: ", -- spinbox 3
|
||||
"Health precent is below:", -- spinbox 4
|
||||
"Health precent is above:", -- spinbox 5
|
||||
"Mana precent is below:", -- spinbox 6
|
||||
"Mana precent is above:", -- spinbox 7
|
||||
"Target name is:", -- BotTextEdit 8
|
||||
"Hotkey is being pressed:", -- BotTextEdit 9
|
||||
"Player is paralyzed", -- nothing 10
|
||||
"Player is in protection zone", -- nothing 11
|
||||
"Players around is more than:", -- spinbox 12
|
||||
"Players around is less than:", -- spinbox 13
|
||||
"TargetBot Danger is Above:", -- spinbox 14
|
||||
"Blacklist player in range (sqm)", -- spinbox 15
|
||||
"Target is Boss" -- nothing
|
||||
}
|
||||
|
||||
local conditionNumber = 1
|
||||
local optionalConditionNumber = 2
|
||||
|
||||
local mainWindow = UI.createWindow("EquipWindow")
|
||||
mainWindow:hide()
|
||||
|
||||
ui.setup.onClick = function()
|
||||
mainWindow:show()
|
||||
mainWindow:raise()
|
||||
mainWindow:focus()
|
||||
end
|
||||
|
||||
local inputPanel = mainWindow.inputPanel
|
||||
local listPanel = mainWindow.listPanel
|
||||
local namePanel = mainWindow.profileName
|
||||
local eqPanel = mainWindow.setup
|
||||
local bossPanel = mainWindow.bossPanel
|
||||
|
||||
local slotWidgets = {eqPanel.head, eqPanel.body, eqPanel.legs, eqPanel.feet, eqPanel.neck, eqPanel["left-hand"], eqPanel["right-hand"], eqPanel.finger, eqPanel.ammo} -- back is disabled
|
||||
|
||||
local function setCondition(first, n)
|
||||
local widget
|
||||
local spinBox
|
||||
local textEdit
|
||||
|
||||
if first then
|
||||
widget = inputPanel.condition.description.text
|
||||
spinBox = inputPanel.condition.spinbox
|
||||
textEdit = inputPanel.condition.text
|
||||
else
|
||||
widget = inputPanel.optionalCondition.description.text
|
||||
spinBox = inputPanel.optionalCondition.spinbox
|
||||
textEdit = inputPanel.optionalCondition.text
|
||||
end
|
||||
|
||||
-- reset values after change
|
||||
spinBox:setValue(0)
|
||||
textEdit:setText('')
|
||||
|
||||
if n == 1 or n == 10 or n == 11 or n == 16 then
|
||||
spinBox:hide()
|
||||
textEdit:hide()
|
||||
elseif n == 9 or n == 8 then
|
||||
spinBox:hide()
|
||||
textEdit:show()
|
||||
if n == 9 then
|
||||
textEdit:setWidth(75)
|
||||
else
|
||||
textEdit:setWidth(200)
|
||||
end
|
||||
else
|
||||
spinBox:show()
|
||||
textEdit:hide()
|
||||
end
|
||||
widget:setText(conditions[n])
|
||||
end
|
||||
|
||||
local function resetFields()
|
||||
conditionNumber = 1
|
||||
optionalConditionNumber = 2
|
||||
setCondition(false, optionalConditionNumber)
|
||||
setCondition(true, conditionNumber)
|
||||
for i, widget in ipairs(slotWidgets) do
|
||||
widget:setItemId(0)
|
||||
widget:setChecked(false)
|
||||
end
|
||||
for i, child in ipairs(listPanel.list:getChildren()) do
|
||||
child.display = false
|
||||
end
|
||||
namePanel.profileName:setText("")
|
||||
inputPanel.condition.text:setText('')
|
||||
inputPanel.condition.spinbox:setValue(0)
|
||||
inputPanel.useSecondCondition:setText('-')
|
||||
inputPanel.optionalCondition.text:setText('')
|
||||
inputPanel.optionalCondition.spinbox:setValue(0)
|
||||
inputPanel.optionalCondition:hide()
|
||||
bossPanel:hide()
|
||||
listPanel:show()
|
||||
mainWindow.bossList:setText('Boss List')
|
||||
bossPanel.name:setText('')
|
||||
end
|
||||
resetFields()
|
||||
|
||||
mainWindow.closeButton.onClick = function()
|
||||
resetFields()
|
||||
mainWindow:hide()
|
||||
end
|
||||
|
||||
inputPanel.optionalCondition:hide()
|
||||
inputPanel.useSecondCondition.onOptionChange = function(widget, option, data)
|
||||
if option ~= "-" then
|
||||
inputPanel.optionalCondition:show()
|
||||
else
|
||||
inputPanel.optionalCondition:hide()
|
||||
end
|
||||
end
|
||||
|
||||
-- add default text & windows
|
||||
setCondition(true, 1)
|
||||
setCondition(false, 2)
|
||||
|
||||
-- in/de/crementation buttons
|
||||
inputPanel.condition.nex.onClick = function()
|
||||
local max = #conditions
|
||||
|
||||
if inputPanel.optionalCondition:isVisible() then
|
||||
if conditionNumber == max then
|
||||
if optionalConditionNumber == 1 then
|
||||
conditionNumber = 2
|
||||
else
|
||||
conditionNumber = 1
|
||||
end
|
||||
else
|
||||
local futureNumber = conditionNumber + 1
|
||||
local safeFutureNumber = conditionNumber + 2 > max and 1 or conditionNumber + 2
|
||||
conditionNumber = futureNumber ~= optionalConditionNumber and futureNumber or safeFutureNumber
|
||||
end
|
||||
else
|
||||
conditionNumber = conditionNumber == max and 1 or conditionNumber + 1
|
||||
if optionalConditionNumber == conditionNumber then
|
||||
optionalConditionNumber = optionalConditionNumber == max and 1 or optionalConditionNumber + 1
|
||||
setCondition(false, optionalConditionNumber)
|
||||
end
|
||||
end
|
||||
setCondition(true, conditionNumber)
|
||||
end
|
||||
|
||||
inputPanel.condition.pre.onClick = function()
|
||||
local max = #conditions
|
||||
|
||||
if inputPanel.optionalCondition:isVisible() then
|
||||
if conditionNumber == 1 then
|
||||
if optionalConditionNumber == max then
|
||||
conditionNumber = max-1
|
||||
else
|
||||
conditionNumber = max
|
||||
end
|
||||
else
|
||||
local futureNumber = conditionNumber - 1
|
||||
local safeFutureNumber = conditionNumber - 2 < 1 and max or conditionNumber - 2
|
||||
conditionNumber = futureNumber ~= optionalConditionNumber and futureNumber or safeFutureNumber
|
||||
end
|
||||
else
|
||||
conditionNumber = conditionNumber == 1 and max or conditionNumber - 1
|
||||
if optionalConditionNumber == conditionNumber then
|
||||
optionalConditionNumber = optionalConditionNumber == 1 and max or optionalConditionNumber - 1
|
||||
setCondition(false, optionalConditionNumber)
|
||||
end
|
||||
end
|
||||
setCondition(true, conditionNumber)
|
||||
end
|
||||
|
||||
inputPanel.optionalCondition.nex.onClick = function()
|
||||
local max = #conditions
|
||||
|
||||
if optionalConditionNumber == max then
|
||||
if conditionNumber == 1 then
|
||||
optionalConditionNumber = 2
|
||||
else
|
||||
optionalConditionNumber = 1
|
||||
end
|
||||
else
|
||||
local futureNumber = optionalConditionNumber + 1
|
||||
local safeFutureNumber = optionalConditionNumber + 2 > max and 1 or optionalConditionNumber + 2
|
||||
optionalConditionNumber = futureNumber ~= conditionNumber and futureNumber or safeFutureNumber
|
||||
end
|
||||
setCondition(false, optionalConditionNumber)
|
||||
end
|
||||
|
||||
inputPanel.optionalCondition.pre.onClick = function()
|
||||
local max = #conditions
|
||||
|
||||
if optionalConditionNumber == 1 then
|
||||
if conditionNumber == max then
|
||||
optionalConditionNumber = max-1
|
||||
else
|
||||
optionalConditionNumber = max
|
||||
end
|
||||
else
|
||||
local futureNumber = optionalConditionNumber - 1
|
||||
local safeFutureNumber = optionalConditionNumber - 2 < 1 and max or optionalConditionNumber - 2
|
||||
optionalConditionNumber = futureNumber ~= conditionNumber and futureNumber or safeFutureNumber
|
||||
end
|
||||
setCondition(false, optionalConditionNumber)
|
||||
end
|
||||
|
||||
listPanel.up.onClick = function(widget)
|
||||
local focused = listPanel.list:getFocusedChild()
|
||||
local n = listPanel.list:getChildIndex(focused)
|
||||
local t = config.rules
|
||||
|
||||
t[n], t[n-1] = t[n-1], t[n]
|
||||
if n-1 == 1 then
|
||||
widget:setEnabled(false)
|
||||
end
|
||||
listPanel.down:setEnabled(true)
|
||||
listPanel.list:moveChildToIndex(focused, n-1)
|
||||
listPanel.list:ensureChildVisible(focused)
|
||||
end
|
||||
|
||||
listPanel.down.onClick = function(widget)
|
||||
local focused = listPanel.list:getFocusedChild()
|
||||
local n = listPanel.list:getChildIndex(focused)
|
||||
local t = config.rules
|
||||
|
||||
t[n], t[n+1] = t[n+1], t[n]
|
||||
if n + 1 == listPanel.list:getChildCount() then
|
||||
widget:setEnabled(false)
|
||||
end
|
||||
listPanel.up:setEnabled(true)
|
||||
listPanel.list:moveChildToIndex(focused, n+1)
|
||||
listPanel.list:ensureChildVisible(focused)
|
||||
end
|
||||
|
||||
eqPanel.cloneEq.onClick = function(widget)
|
||||
eqPanel.head:setItemId(getHead() and getHead():getId() or 0)
|
||||
eqPanel.body:setItemId(getBody() and getBody():getId() or 0)
|
||||
eqPanel.legs:setItemId(getLeg() and getLeg():getId() or 0)
|
||||
eqPanel.feet:setItemId(getFeet() and getFeet():getId() or 0)
|
||||
eqPanel.neck:setItemId(getNeck() and getNeck():getId() or 0)
|
||||
eqPanel["left-hand"]:setItemId(getLeft() and getLeft():getId() or 0)
|
||||
eqPanel["right-hand"]:setItemId(getRight() and getRight():getId() or 0)
|
||||
eqPanel.finger:setItemId(getFinger() and getFinger():getId() or 0)
|
||||
eqPanel.ammo:setItemId(getAmmo() and getAmmo():getId() or 0)
|
||||
end
|
||||
|
||||
eqPanel.default.onClick = resetFields
|
||||
|
||||
-- buttons disabled by default
|
||||
listPanel.up:setEnabled(false)
|
||||
listPanel.down:setEnabled(false)
|
||||
|
||||
-- correct background image
|
||||
for i, widget in ipairs(slotWidgets) do
|
||||
widget:setTooltip("Right click to set as slot to unequip")
|
||||
widget.onItemChange = function(widget)
|
||||
local selfId = widget:getItemId()
|
||||
widget:setOn(selfId > 100)
|
||||
if widget:isChecked() then
|
||||
widget:setChecked(selfId < 100)
|
||||
end
|
||||
end
|
||||
widget.onMouseRelease = function(widget, mousePos, mouseButton)
|
||||
if mouseButton == 2 then
|
||||
local clearItem = widget:isChecked() == false
|
||||
widget:setChecked(not widget:isChecked())
|
||||
if clearItem then
|
||||
widget:setItemId(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
inputPanel.condition.description.onMouseWheel = function(widget, mousePos, scroll)
|
||||
if scroll == 1 then
|
||||
inputPanel.condition.nex.onClick()
|
||||
else
|
||||
inputPanel.condition.pre.onClick()
|
||||
end
|
||||
end
|
||||
|
||||
inputPanel.optionalCondition.description.onMouseWheel = function(widget, mousePos, scroll)
|
||||
if scroll == 1 then
|
||||
inputPanel.optionalCondition.nex.onClick()
|
||||
else
|
||||
inputPanel.optionalCondition.pre.onClick()
|
||||
end
|
||||
end
|
||||
|
||||
namePanel.profileName.onTextChange = function(widget, text)
|
||||
local button = inputPanel.add
|
||||
text = text:lower()
|
||||
|
||||
for i, child in ipairs(listPanel.list:getChildren()) do
|
||||
local name = child:getText():lower()
|
||||
|
||||
button:setText(name == text and "Overwrite" or "Add Rule")
|
||||
button:setTooltip(name == text and "Overwrite existing rule named: "..name, "Add new rule to the list: "..name)
|
||||
end
|
||||
end
|
||||
|
||||
local function setupPreview(display, data)
|
||||
namePanel.profileName:setText('')
|
||||
if not display then
|
||||
resetFields()
|
||||
else
|
||||
for i, value in ipairs(data) do
|
||||
local widget = slotWidgets[i]
|
||||
if value == false then
|
||||
widget:setChecked(false)
|
||||
widget:setItemId(0)
|
||||
elseif value == true then
|
||||
widget:setChecked(true)
|
||||
widget:setItemId(0)
|
||||
else
|
||||
widget:setChecked(false)
|
||||
widget:setItemId(value)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function refreshRules()
|
||||
local list = listPanel.list
|
||||
|
||||
list:destroyChildren()
|
||||
for i,v in ipairs(config.rules) do
|
||||
local widget = UI.createWidget('Rule', list)
|
||||
widget:setId(v.name)
|
||||
widget:setText(v.name)
|
||||
widget.ruleData = v
|
||||
widget.remove.onClick = function()
|
||||
widget:destroy()
|
||||
table.remove(config.rules, table.find(config.rules, v))
|
||||
listPanel.up:setEnabled(false)
|
||||
listPanel.down:setEnabled(false)
|
||||
refreshRules()
|
||||
end
|
||||
widget.visible:setColor(v.visible and "green" or "red")
|
||||
widget.visible.onClick = function()
|
||||
v.visible = not v.visible
|
||||
widget.visible:setColor(v.visible and "green" or "red")
|
||||
end
|
||||
widget.enabled:setChecked(v.enabled)
|
||||
widget.enabled.onClick = function()
|
||||
v.enabled = not v.enabled
|
||||
widget.enabled:setChecked(v.enabled)
|
||||
end
|
||||
widget.onHoverChange = function(widget, hover)
|
||||
for i, child in ipairs(list:getChildren()) do
|
||||
if child.display then return end
|
||||
end
|
||||
setupPreview(hover, widget.ruleData.data)
|
||||
end
|
||||
widget.onDoubleClick = function(widget)
|
||||
local ruleData = widget.ruleData
|
||||
widget.display = true
|
||||
setupPreview(true, ruleData.data)
|
||||
conditionNumber = ruleData.mainCondition
|
||||
optionalConditionNumber = ruleData.optionalCondition
|
||||
setCondition(false, optionalConditionNumber)
|
||||
setCondition(true, conditionNumber)
|
||||
inputPanel.useSecondCondition:setOption(ruleData.relation)
|
||||
namePanel.profileName:setText(v.name)
|
||||
|
||||
if type(ruleData.mainValue) == "string" then
|
||||
inputPanel.condition.text:setText(ruleData.mainValue)
|
||||
elseif type(ruleData.mainValue) == "number" then
|
||||
inputPanel.condition.spinbox:setValue(ruleData.mainValue)
|
||||
end
|
||||
|
||||
if type(ruleData.optValue) == "string" then
|
||||
inputPanel.optionalCondition.text:setText(ruleData.optValue)
|
||||
elseif type(ruleData.optValue) == "number" then
|
||||
inputPanel.optionalCondition.spinbox:setValue(ruleData.optValue)
|
||||
end
|
||||
end
|
||||
widget.onClick = function()
|
||||
local panel = listPanel
|
||||
if #panel.list:getChildren() == 1 then
|
||||
panel.up:setEnabled(false)
|
||||
panel.down:setEnabled(false)
|
||||
elseif panel.list:getChildIndex(panel.list:getFocusedChild()) == 1 then
|
||||
panel.up:setEnabled(false)
|
||||
panel.down:setEnabled(true)
|
||||
elseif panel.list:getChildIndex(panel.list:getFocusedChild()) == #panel.list:getChildren() then
|
||||
panel.up:setEnabled(true)
|
||||
panel.down:setEnabled(false)
|
||||
else
|
||||
panel.up:setEnabled(true)
|
||||
panel.down:setEnabled(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
refreshRules()
|
||||
|
||||
inputPanel.add.onClick = function(widget)
|
||||
local mainVal
|
||||
local optVal
|
||||
local t = {}
|
||||
local relation = inputPanel.useSecondCondition:getText()
|
||||
local profileName = namePanel.profileName:getText()
|
||||
if profileName:len() == 0 then
|
||||
return warn("Please fill profile name!")
|
||||
end
|
||||
|
||||
for i, widget in ipairs(slotWidgets) do
|
||||
local checked = widget:isChecked()
|
||||
local id = widget:getItemId()
|
||||
|
||||
if checked then
|
||||
table.insert(t, true) -- unequip selected slot
|
||||
elseif id then
|
||||
table.insert(t, id) -- equip selected item
|
||||
else
|
||||
table.insert(t, false) -- ignore slot
|
||||
end
|
||||
end
|
||||
|
||||
if conditionNumber == 1 then
|
||||
mainVal = nil
|
||||
elseif conditionNumber == 8 then
|
||||
mainVal = inputPanel.condition.text:getText()
|
||||
if mainVal:len() == 0 then
|
||||
return warn("[vBot Equipper] Please fill the name of the creature.")
|
||||
end
|
||||
elseif conditionNumber == 9 then
|
||||
mainVal = inputPanel.condition.text:getText()
|
||||
if mainVal:len() == 0 then
|
||||
return warn("[vBot Equipper] Please set correct hotkey.")
|
||||
end
|
||||
else
|
||||
mainVal = inputPanel.condition.spinbox:getValue()
|
||||
end
|
||||
|
||||
if relation ~= "-" then
|
||||
if optionalConditionNumber == 1 then
|
||||
optVal = nil
|
||||
elseif optionalConditionNumber == 8 then
|
||||
optVal = inputPanel.optionalCondition.text:getText()
|
||||
if optVal:len() == 0 then
|
||||
return warn("[vBot Equipper] Please fill the name of the creature.")
|
||||
end
|
||||
elseif optionalConditionNumber == 9 then
|
||||
optVal = inputPanel.optionalCondition.text:getText()
|
||||
if optVal:len() == 0 then
|
||||
return warn("[vBot Equipper] Please set correct hotkey.")
|
||||
end
|
||||
else
|
||||
optVal = inputPanel.optionalCondition.spinbox:getValue()
|
||||
end
|
||||
end
|
||||
|
||||
local index
|
||||
for i, v in ipairs(config.rules) do
|
||||
if v.name == profileName then
|
||||
index = i -- search if there's already rule with this name
|
||||
end
|
||||
end
|
||||
|
||||
local ruleData = {
|
||||
name = profileName,
|
||||
data = t,
|
||||
enabled = true,
|
||||
visible = true,
|
||||
mainCondition = conditionNumber,
|
||||
optionalCondition = optionalConditionNumber,
|
||||
mainValue = mainVal,
|
||||
optValue = optVal,
|
||||
relation = relation,
|
||||
}
|
||||
|
||||
if index then
|
||||
config.rules[index] = ruleData -- overwrite
|
||||
else
|
||||
table.insert(config.rules, ruleData) -- create new one
|
||||
end
|
||||
|
||||
for i, child in ipairs(listPanel.list:getChildren()) do
|
||||
child.display = false
|
||||
end
|
||||
resetFields()
|
||||
refreshRules()
|
||||
end
|
||||
|
||||
mainWindow.bossList.onClick = function(widget)
|
||||
if bossPanel:isVisible() then
|
||||
bossPanel:hide()
|
||||
listPanel:show()
|
||||
widget:setText('Boss List')
|
||||
else
|
||||
bossPanel:show()
|
||||
listPanel:hide()
|
||||
widget:setText('Rule List')
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
-- create boss labels
|
||||
for i, v in ipairs(config.bosses) do
|
||||
local widget = UI.createWidget("BossLabel", bossPanel.list)
|
||||
widget:setText(v)
|
||||
widget.remove.onClick = function()
|
||||
table.remove(config.bosses, table.find(config.bosses, v))
|
||||
widget:destroy()
|
||||
end
|
||||
end
|
||||
|
||||
bossPanel.add.onClick = function()
|
||||
local name = bossPanel.name:getText()
|
||||
|
||||
if name:len() == 0 then
|
||||
return warn("[Equipped] Please enter boss name!")
|
||||
elseif table.find(config.bosses, name:lower(), true) then
|
||||
return warn("[Equipper] Boss already added!")
|
||||
end
|
||||
|
||||
local widget = UI.createWidget("BossLabel", bossPanel.list)
|
||||
widget:setText(name)
|
||||
widget.remove.onClick = function()
|
||||
table.remove(config.bosses, table.find(config.bosses, name))
|
||||
widget:destroy()
|
||||
end
|
||||
|
||||
table.insert(config.bosses, name)
|
||||
bossPanel.name:setText('')
|
||||
end
|
||||
|
||||
local function interpreteCondition(n, v)
|
||||
|
||||
if n == 1 then
|
||||
return true
|
||||
elseif n == 2 then
|
||||
return getMonsters() > v
|
||||
elseif n == 3 then
|
||||
return getMonsters() < v
|
||||
elseif n == 4 then
|
||||
return hppercent() < v
|
||||
elseif n == 5 then
|
||||
return hppercent() > v
|
||||
elseif n == 6 then
|
||||
return manapercent() < v
|
||||
elseif n == 7 then
|
||||
return manapercent() > v
|
||||
elseif n == 8 then
|
||||
return target() and target():getName():lower() == v:lower() or false
|
||||
elseif n == 9 then
|
||||
return g_keyboard.isKeyPressed(v)
|
||||
elseif n == 10 then
|
||||
return isParalyzed()
|
||||
elseif n == 11 then
|
||||
return isInPz()
|
||||
elseif n == 12 then
|
||||
return getPlayers() > v
|
||||
elseif n == 13 then
|
||||
return getPlayers() < v
|
||||
elseif n == 14 then
|
||||
return TargetBot.Danger() > v and TargetBot.isOn()
|
||||
elseif n == 15 then
|
||||
return isBlackListedPlayerInRange(v)
|
||||
elseif n == 16 then
|
||||
return target() and table.find(config.bosses, target():getName():lower(), true) and true or false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local function finalCheck(first,relation,second)
|
||||
if relation == "-" then
|
||||
return first
|
||||
elseif relation == "and" then
|
||||
return first and second
|
||||
elseif relation == "or" then
|
||||
return first or second
|
||||
end
|
||||
end
|
||||
|
||||
local function isEquipped(id)
|
||||
local t = {getNeck(), getHead(), getBody(), getRight(), getLeft(), getLeg(), getFeet(), getFinger(), getAmmo()}
|
||||
local ids = {id, getInactiveItemId(id), getActiveItemId(id)}
|
||||
|
||||
for i, slot in pairs(t) do
|
||||
if slot and table.find(ids, slot:getId()) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function unequipItem(table)
|
||||
local slots = {getHead(), getBody(), getLeg(), getFeet(), getNeck(), getLeft(), getRight(), getFinger(), getAmmo()}
|
||||
|
||||
if type(table) ~= "table" then return end
|
||||
for i, slot in ipairs(table) do
|
||||
local physicalSlot = slots[i]
|
||||
|
||||
if slot == true and physicalSlot then
|
||||
local id = physicalSlot:getId()
|
||||
|
||||
if g_game.getClientVersion() >= 910 then
|
||||
-- new tibia
|
||||
g_game.equipItemId(id)
|
||||
else
|
||||
-- old tibia
|
||||
local dest
|
||||
for i, container in ipairs(getContainers()) do
|
||||
local cname = container:getName()
|
||||
if not containerIsFull(container) then
|
||||
if not cname:find("loot") and (cname:find("backpack") or cname:find("bag") or cname:find("chess")) then
|
||||
dest = container
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not dest then return true end
|
||||
local pos = dest:getSlotPosition(dest:getItemsCount())
|
||||
g_game.move(physicalSlot, pos, physicalSlot:getCount())
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function equipItem(id, slot)
|
||||
-- need to correct slots...
|
||||
if slot == 2 then
|
||||
slot = 4
|
||||
elseif slot == 3 then
|
||||
slot = 7
|
||||
elseif slot == 8 then
|
||||
slot = 9
|
||||
elseif slot == 5 then
|
||||
slot = 2
|
||||
elseif slot == 4 then
|
||||
slot = 8
|
||||
elseif slot == 9 then
|
||||
slot = 10
|
||||
elseif slot == 7 then
|
||||
slot = 5
|
||||
end
|
||||
|
||||
|
||||
if g_game.getClientVersion() >= 910 then
|
||||
-- new tibia
|
||||
return g_game.equipItemId(id)
|
||||
else
|
||||
-- old tibia
|
||||
local item = findItem(id)
|
||||
return moveToSlot(item, slot)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function markChild(child)
|
||||
if mainWindow:isVisible() then
|
||||
for i, child in ipairs(listPanel.list:getChildren()) do
|
||||
if child ~= widget then
|
||||
child:setColor('white')
|
||||
end
|
||||
end
|
||||
widget:setColor('green')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local missingItem = false
|
||||
local lastRule = false
|
||||
local correctEq = false
|
||||
EquipManager = macro(50, function()
|
||||
if not config.enabled then return end
|
||||
if #config.rules == 0 then return end
|
||||
|
||||
for i, widget in ipairs(listPanel.list:getChildren()) do
|
||||
local rule = widget.ruleData
|
||||
if rule.enabled then
|
||||
|
||||
-- conditions
|
||||
local firstCondition = interpreteCondition(rule.mainCondition, rule.mainValue)
|
||||
local optionalCondition = nil
|
||||
if rule.relation ~= "-" then
|
||||
optionalCondition = interpreteCondition(rule.optionalCondition, rule.optValue)
|
||||
end
|
||||
|
||||
-- checks
|
||||
if finalCheck(firstCondition, rule.relation, optionalCondition) then
|
||||
|
||||
-- performance edits, loop reset
|
||||
local resetLoop = not missingItem and correctEq and lastRule == rule
|
||||
if resetLoop then return end
|
||||
|
||||
-- reset executed rule
|
||||
|
||||
|
||||
-- first check unequip
|
||||
if unequipItem(rule.data) == true then
|
||||
delay(200)
|
||||
return
|
||||
end
|
||||
|
||||
-- equiploop
|
||||
for slot, item in ipairs(rule.data) do
|
||||
if type(item) == "number" and item > 100 then
|
||||
if not isEquipped(item) then
|
||||
if rule.visible then
|
||||
if findItem(item) then
|
||||
missingItem = false
|
||||
delay(200)
|
||||
return equipItem(item, slot)
|
||||
else
|
||||
missingItem = true
|
||||
end
|
||||
else
|
||||
missingItem = false
|
||||
delay(200)
|
||||
return equipItem(item, slot)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
correctEq = not missingItem and true or false
|
||||
-- even if nothing was done, exit function to hold rule
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end)
|
||||
712
modules/game_bot/default_configs/vBot_4.7/vBot/HealBot.lua
Normal file
712
modules/game_bot/default_configs/vBot_4.7/vBot/HealBot.lua
Normal file
@@ -0,0 +1,712 @@
|
||||
local standBySpells = false
|
||||
local standByItems = false
|
||||
|
||||
local red = "#ff0800" -- "#ff0800" / #ea3c53 best
|
||||
local blue = "#7ef9ff"
|
||||
|
||||
setDefaultTab("HP")
|
||||
local healPanelName = "healbot"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 38
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('HealBot')
|
||||
|
||||
Button
|
||||
id: settings
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Setup
|
||||
|
||||
Button
|
||||
id: 1
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
text: 1
|
||||
margin-right: 2
|
||||
margin-top: 4
|
||||
size: 17 17
|
||||
|
||||
Button
|
||||
id: 2
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
text: 2
|
||||
margin-left: 4
|
||||
size: 17 17
|
||||
|
||||
Button
|
||||
id: 3
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
text: 3
|
||||
margin-left: 4
|
||||
size: 17 17
|
||||
|
||||
Button
|
||||
id: 4
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
text: 4
|
||||
margin-left: 4
|
||||
size: 17 17
|
||||
|
||||
Button
|
||||
id: 5
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
text: 5
|
||||
margin-left: 4
|
||||
size: 17 17
|
||||
|
||||
Label
|
||||
id: name
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
margin-left: 4
|
||||
height: 17
|
||||
text: Profile #1
|
||||
background: #292A2A
|
||||
]])
|
||||
ui:setId(healPanelName)
|
||||
|
||||
if not HealBotConfig[healPanelName] or not HealBotConfig[healPanelName][1] or #HealBotConfig[healPanelName] ~= 5 then
|
||||
HealBotConfig[healPanelName] = {
|
||||
[1] = {
|
||||
enabled = false,
|
||||
spellTable = {},
|
||||
itemTable = {},
|
||||
name = "Profile #1",
|
||||
Visible = true,
|
||||
Cooldown = true,
|
||||
Interval = true,
|
||||
Conditions = true,
|
||||
Delay = true,
|
||||
MessageDelay = false
|
||||
},
|
||||
[2] = {
|
||||
enabled = false,
|
||||
spellTable = {},
|
||||
itemTable = {},
|
||||
name = "Profile #2",
|
||||
Visible = true,
|
||||
Cooldown = true,
|
||||
Interval = true,
|
||||
Conditions = true,
|
||||
Delay = true,
|
||||
MessageDelay = false
|
||||
},
|
||||
[3] = {
|
||||
enabled = false,
|
||||
spellTable = {},
|
||||
itemTable = {},
|
||||
name = "Profile #3",
|
||||
Visible = true,
|
||||
Cooldown = true,
|
||||
Interval = true,
|
||||
Conditions = true,
|
||||
Delay = true,
|
||||
MessageDelay = false
|
||||
},
|
||||
[4] = {
|
||||
enabled = false,
|
||||
spellTable = {},
|
||||
itemTable = {},
|
||||
name = "Profile #4",
|
||||
Visible = true,
|
||||
Cooldown = true,
|
||||
Interval = true,
|
||||
Conditions = true,
|
||||
Delay = true,
|
||||
MessageDelay = false
|
||||
},
|
||||
[5] = {
|
||||
enabled = false,
|
||||
spellTable = {},
|
||||
itemTable = {},
|
||||
name = "Profile #5",
|
||||
Visible = true,
|
||||
Cooldown = true,
|
||||
Interval = true,
|
||||
Conditions = true,
|
||||
Delay = true,
|
||||
MessageDelay = false
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
if not HealBotConfig.currentHealBotProfile or HealBotConfig.currentHealBotProfile == 0 or HealBotConfig.currentHealBotProfile > 5 then
|
||||
HealBotConfig.currentHealBotProfile = 1
|
||||
end
|
||||
|
||||
-- finding correct table, manual unfortunately
|
||||
local currentSettings
|
||||
local setActiveProfile = function()
|
||||
local n = HealBotConfig.currentHealBotProfile
|
||||
currentSettings = HealBotConfig[healPanelName][n]
|
||||
end
|
||||
setActiveProfile()
|
||||
|
||||
local activeProfileColor = function()
|
||||
for i=1,5 do
|
||||
if i == HealBotConfig.currentHealBotProfile then
|
||||
ui[i]:setColor("green")
|
||||
else
|
||||
ui[i]:setColor("white")
|
||||
end
|
||||
end
|
||||
end
|
||||
activeProfileColor()
|
||||
|
||||
ui.title:setOn(currentSettings.enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
currentSettings.enabled = not currentSettings.enabled
|
||||
widget:setOn(currentSettings.enabled)
|
||||
vBotConfigSave("heal")
|
||||
end
|
||||
|
||||
ui.settings.onClick = function(widget)
|
||||
healWindow:show()
|
||||
healWindow:raise()
|
||||
healWindow:focus()
|
||||
end
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
healWindow = UI.createWindow('HealWindow', rootWidget)
|
||||
healWindow:hide()
|
||||
|
||||
healWindow.onVisibilityChange = function(widget, visible)
|
||||
if not visible then
|
||||
vBotConfigSave("heal")
|
||||
healWindow.healer:show()
|
||||
healWindow.settings:hide()
|
||||
healWindow.settingsButton:setText("Settings")
|
||||
end
|
||||
end
|
||||
|
||||
healWindow.settingsButton.onClick = function(widget)
|
||||
if healWindow.healer:isVisible() then
|
||||
healWindow.healer:hide()
|
||||
healWindow.settings:show()
|
||||
widget:setText("Back")
|
||||
else
|
||||
healWindow.healer:show()
|
||||
healWindow.settings:hide()
|
||||
widget:setText("Settings")
|
||||
end
|
||||
end
|
||||
|
||||
local setProfileName = function()
|
||||
ui.name:setText(currentSettings.name)
|
||||
end
|
||||
healWindow.settings.profiles.Name.onTextChange = function(widget, text)
|
||||
currentSettings.name = text
|
||||
setProfileName()
|
||||
end
|
||||
healWindow.settings.list.Visible.onClick = function(widget)
|
||||
currentSettings.Visible = not currentSettings.Visible
|
||||
healWindow.settings.list.Visible:setChecked(currentSettings.Visible)
|
||||
end
|
||||
healWindow.settings.list.Cooldown.onClick = function(widget)
|
||||
currentSettings.Cooldown = not currentSettings.Cooldown
|
||||
healWindow.settings.list.Cooldown:setChecked(currentSettings.Cooldown)
|
||||
end
|
||||
healWindow.settings.list.Interval.onClick = function(widget)
|
||||
currentSettings.Interval = not currentSettings.Interval
|
||||
healWindow.settings.list.Interval:setChecked(currentSettings.Interval)
|
||||
end
|
||||
healWindow.settings.list.Conditions.onClick = function(widget)
|
||||
currentSettings.Conditions = not currentSettings.Conditions
|
||||
healWindow.settings.list.Conditions:setChecked(currentSettings.Conditions)
|
||||
end
|
||||
healWindow.settings.list.Delay.onClick = function(widget)
|
||||
currentSettings.Delay = not currentSettings.Delay
|
||||
healWindow.settings.list.Delay:setChecked(currentSettings.Delay)
|
||||
end
|
||||
healWindow.settings.list.MessageDelay.onClick = function(widget)
|
||||
currentSettings.MessageDelay = not currentSettings.MessageDelay
|
||||
healWindow.settings.list.MessageDelay:setChecked(currentSettings.MessageDelay)
|
||||
end
|
||||
|
||||
local refreshSpells = function()
|
||||
if currentSettings.spellTable then
|
||||
healWindow.healer.spells.spellList:destroyChildren()
|
||||
for _, entry in pairs(currentSettings.spellTable) do
|
||||
local label = UI.createWidget("SpellEntry", healWindow.healer.spells.spellList)
|
||||
label.enabled:setChecked(entry.enabled)
|
||||
label.enabled.onClick = function(widget)
|
||||
standBySpells = false
|
||||
standByItems = false
|
||||
entry.enabled = not entry.enabled
|
||||
label.enabled:setChecked(entry.enabled)
|
||||
end
|
||||
label.remove.onClick = function(widget)
|
||||
standBySpells = false
|
||||
standByItems = false
|
||||
table.removevalue(currentSettings.spellTable, entry)
|
||||
reindexTable(currentSettings.spellTable)
|
||||
label:destroy()
|
||||
end
|
||||
label:setText("(MP>" .. entry.cost .. ") " .. entry.origin .. entry.sign .. entry.value .. ": " .. entry.spell)
|
||||
end
|
||||
end
|
||||
end
|
||||
refreshSpells()
|
||||
|
||||
local refreshItems = function()
|
||||
if currentSettings.itemTable then
|
||||
healWindow.healer.items.itemList:destroyChildren()
|
||||
for _, entry in pairs(currentSettings.itemTable) do
|
||||
local label = UI.createWidget("ItemEntry", healWindow.healer.items.itemList)
|
||||
label.enabled:setChecked(entry.enabled)
|
||||
label.enabled.onClick = function(widget)
|
||||
standBySpells = false
|
||||
standByItems = false
|
||||
entry.enabled = not entry.enabled
|
||||
label.enabled:setChecked(entry.enabled)
|
||||
end
|
||||
label.remove.onClick = function(widget)
|
||||
standBySpells = false
|
||||
standByItems = false
|
||||
table.removevalue(currentSettings.itemTable, entry)
|
||||
reindexTable(currentSettings.itemTable)
|
||||
label:destroy()
|
||||
end
|
||||
label.id:setItemId(entry.item)
|
||||
label:setText(entry.origin .. entry.sign .. entry.value .. ": " .. entry.item)
|
||||
end
|
||||
end
|
||||
end
|
||||
refreshItems()
|
||||
|
||||
healWindow.healer.spells.MoveUp.onClick = function(widget)
|
||||
local input = healWindow.healer.spells.spellList:getFocusedChild()
|
||||
if not input then return end
|
||||
local index = healWindow.healer.spells.spellList:getChildIndex(input)
|
||||
if index < 2 then return end
|
||||
|
||||
local t = currentSettings.spellTable
|
||||
|
||||
t[index],t[index-1] = t[index-1], t[index]
|
||||
healWindow.healer.spells.spellList:moveChildToIndex(input, index - 1)
|
||||
healWindow.healer.spells.spellList:ensureChildVisible(input)
|
||||
end
|
||||
|
||||
healWindow.healer.spells.MoveDown.onClick = function(widget)
|
||||
local input = healWindow.healer.spells.spellList:getFocusedChild()
|
||||
if not input then return end
|
||||
local index = healWindow.healer.spells.spellList:getChildIndex(input)
|
||||
if index >= healWindow.healer.spells.spellList:getChildCount() then return end
|
||||
|
||||
local t = currentSettings.spellTable
|
||||
|
||||
t[index],t[index+1] = t[index+1],t[index]
|
||||
healWindow.healer.spells.spellList:moveChildToIndex(input, index + 1)
|
||||
healWindow.healer.spells.spellList:ensureChildVisible(input)
|
||||
end
|
||||
|
||||
healWindow.healer.items.MoveUp.onClick = function(widget)
|
||||
local input = healWindow.healer.items.itemList:getFocusedChild()
|
||||
if not input then return end
|
||||
local index = healWindow.healer.items.itemList:getChildIndex(input)
|
||||
if index < 2 then return end
|
||||
|
||||
local t = currentSettings.itemTable
|
||||
|
||||
t[index],t[index-1] = t[index-1], t[index]
|
||||
healWindow.healer.items.itemList:moveChildToIndex(input, index - 1)
|
||||
healWindow.healer.items.itemList:ensureChildVisible(input)
|
||||
end
|
||||
|
||||
healWindow.healer.items.MoveDown.onClick = function(widget)
|
||||
local input = healWindow.healer.items.itemList:getFocusedChild()
|
||||
if not input then return end
|
||||
local index = healWindow.healer.items.itemList:getChildIndex(input)
|
||||
if index >= healWindow.healer.items.itemList:getChildCount() then return end
|
||||
|
||||
local t = currentSettings.itemTable
|
||||
|
||||
t[index],t[index+1] = t[index+1],t[index]
|
||||
healWindow.healer.items.itemList:moveChildToIndex(input, index + 1)
|
||||
healWindow.healer.items.itemList:ensureChildVisible(input)
|
||||
end
|
||||
|
||||
healWindow.healer.spells.addSpell.onClick = function(widget)
|
||||
|
||||
local spellFormula = healWindow.healer.spells.spellFormula:getText():trim()
|
||||
local manaCost = tonumber(healWindow.healer.spells.manaCost:getText())
|
||||
local spellTrigger = tonumber(healWindow.healer.spells.spellValue:getText())
|
||||
local spellSource = healWindow.healer.spells.spellSource:getCurrentOption().text
|
||||
local spellEquasion = healWindow.healer.spells.spellCondition:getCurrentOption().text
|
||||
local source
|
||||
local equasion
|
||||
|
||||
if not manaCost then
|
||||
warn("HealBot: incorrect mana cost value!")
|
||||
healWindow.healer.spells.spellFormula:setText('')
|
||||
healWindow.healer.spells.spellValue:setText('')
|
||||
healWindow.healer.spells.manaCost:setText('')
|
||||
return
|
||||
end
|
||||
if not spellTrigger then
|
||||
warn("HealBot: incorrect condition value!")
|
||||
healWindow.healer.spells.spellFormula:setText('')
|
||||
healWindow.healer.spells.spellValue:setText('')
|
||||
healWindow.healer.spells.manaCost:setText('')
|
||||
return
|
||||
end
|
||||
|
||||
if spellSource == "Current Mana" then
|
||||
source = "MP"
|
||||
elseif spellSource == "Current Health" then
|
||||
source = "HP"
|
||||
elseif spellSource == "Mana Percent" then
|
||||
source = "MP%"
|
||||
elseif spellSource == "Health Percent" then
|
||||
source = "HP%"
|
||||
else
|
||||
source = "burst"
|
||||
end
|
||||
|
||||
if spellEquasion == "Above" then
|
||||
equasion = ">"
|
||||
elseif spellEquasion == "Below" then
|
||||
equasion = "<"
|
||||
else
|
||||
equasion = "="
|
||||
end
|
||||
|
||||
if spellFormula:len() > 0 then
|
||||
table.insert(currentSettings.spellTable, {index = #currentSettings.spellTable+1, spell = spellFormula, sign = equasion, origin = source, cost = manaCost, value = spellTrigger, enabled = true})
|
||||
healWindow.healer.spells.spellFormula:setText('')
|
||||
healWindow.healer.spells.spellValue:setText('')
|
||||
healWindow.healer.spells.manaCost:setText('')
|
||||
end
|
||||
standBySpells = false
|
||||
standByItems = false
|
||||
refreshSpells()
|
||||
end
|
||||
|
||||
healWindow.healer.items.addItem.onClick = function(widget)
|
||||
|
||||
local id = healWindow.healer.items.itemId:getItemId()
|
||||
local trigger = tonumber(healWindow.healer.items.itemValue:getText())
|
||||
local src = healWindow.healer.items.itemSource:getCurrentOption().text
|
||||
local eq = healWindow.healer.items.itemCondition:getCurrentOption().text
|
||||
local source
|
||||
local equasion
|
||||
|
||||
if not trigger then
|
||||
warn("HealBot: incorrect trigger value!")
|
||||
healWindow.healer.items.itemId:setItemId(0)
|
||||
healWindow.healer.items.itemValue:setText('')
|
||||
return
|
||||
end
|
||||
|
||||
if src == "Current Mana" then
|
||||
source = "MP"
|
||||
elseif src == "Current Health" then
|
||||
source = "HP"
|
||||
elseif src == "Mana Percent" then
|
||||
source = "MP%"
|
||||
elseif src == "Health Percent" then
|
||||
source = "HP%"
|
||||
else
|
||||
source = "burst"
|
||||
end
|
||||
|
||||
if eq == "Above" then
|
||||
equasion = ">"
|
||||
elseif eq == "Below" then
|
||||
equasion = "<"
|
||||
else
|
||||
equasion = "="
|
||||
end
|
||||
|
||||
if id > 100 then
|
||||
table.insert(currentSettings.itemTable, {index = #currentSettings.itemTable+1,item = id, sign = equasion, origin = source, value = trigger, enabled = true})
|
||||
standBySpells = false
|
||||
standByItems = false
|
||||
refreshItems()
|
||||
healWindow.healer.items.itemId:setItemId(0)
|
||||
healWindow.healer.items.itemValue:setText('')
|
||||
end
|
||||
end
|
||||
|
||||
healWindow.closeButton.onClick = function(widget)
|
||||
healWindow:hide()
|
||||
end
|
||||
|
||||
local loadSettings = function()
|
||||
ui.title:setOn(currentSettings.enabled)
|
||||
setProfileName()
|
||||
healWindow.settings.profiles.Name:setText(currentSettings.name)
|
||||
refreshSpells()
|
||||
refreshItems()
|
||||
healWindow.settings.list.Visible:setChecked(currentSettings.Visible)
|
||||
healWindow.settings.list.Cooldown:setChecked(currentSettings.Cooldown)
|
||||
healWindow.settings.list.Delay:setChecked(currentSettings.Delay)
|
||||
healWindow.settings.list.MessageDelay:setChecked(currentSettings.MessageDelay)
|
||||
healWindow.settings.list.Interval:setChecked(currentSettings.Interval)
|
||||
healWindow.settings.list.Conditions:setChecked(currentSettings.Conditions)
|
||||
end
|
||||
loadSettings()
|
||||
|
||||
local profileChange = function()
|
||||
setActiveProfile()
|
||||
activeProfileColor()
|
||||
loadSettings()
|
||||
vBotConfigSave("heal")
|
||||
end
|
||||
|
||||
local resetSettings = function()
|
||||
currentSettings.enabled = false
|
||||
currentSettings.spellTable = {}
|
||||
currentSettings.itemTable = {}
|
||||
currentSettings.Visible = true
|
||||
currentSettings.Cooldown = true
|
||||
currentSettings.Delay = true
|
||||
currentSettings.MessageDelay = false
|
||||
currentSettings.Interval = true
|
||||
currentSettings.Conditions = true
|
||||
currentSettings.name = "Profile #" .. HealBotConfig.currentBotProfile
|
||||
end
|
||||
|
||||
-- profile buttons
|
||||
for i=1,5 do
|
||||
local button = ui[i]
|
||||
button.onClick = function()
|
||||
HealBotConfig.currentHealBotProfile = i
|
||||
profileChange()
|
||||
end
|
||||
end
|
||||
|
||||
healWindow.settings.profiles.ResetSettings.onClick = function()
|
||||
resetSettings()
|
||||
loadSettings()
|
||||
end
|
||||
|
||||
|
||||
-- public functions
|
||||
HealBot = {} -- global table
|
||||
|
||||
HealBot.isOn = function()
|
||||
return currentSettings.enabled
|
||||
end
|
||||
|
||||
HealBot.isOff = function()
|
||||
return not currentSettings.enabled
|
||||
end
|
||||
|
||||
HealBot.setOff = function()
|
||||
currentSettings.enabled = false
|
||||
ui.title:setOn(currentSettings.enabled)
|
||||
vBotConfigSave("atk")
|
||||
end
|
||||
|
||||
HealBot.setOn = function()
|
||||
currentSettings.enabled = true
|
||||
ui.title:setOn(currentSettings.enabled)
|
||||
vBotConfigSave("atk")
|
||||
end
|
||||
|
||||
HealBot.getActiveProfile = function()
|
||||
return HealBotConfig.currentHealBotProfile -- returns number 1-5
|
||||
end
|
||||
|
||||
HealBot.setActiveProfile = function(n)
|
||||
if not n or not tonumber(n) or n < 1 or n > 5 then
|
||||
return error("[HealBot] wrong profile parameter! should be 1 to 5 is " .. n)
|
||||
else
|
||||
HealBotConfig.currentHealBotProfile = n
|
||||
profileChange()
|
||||
end
|
||||
end
|
||||
|
||||
HealBot.show = function()
|
||||
healWindow:show()
|
||||
healWindow:raise()
|
||||
healWindow:focus()
|
||||
end
|
||||
end
|
||||
|
||||
-- spells
|
||||
macro(100, function()
|
||||
if standBySpells then return end
|
||||
if not currentSettings.enabled then return end
|
||||
local somethingIsOnCooldown = false
|
||||
|
||||
for _, entry in pairs(currentSettings.spellTable) do
|
||||
if entry.enabled and entry.cost < mana() then
|
||||
if canCast(entry.spell, not currentSettings.Conditions, not currentSettings.Cooldown) then
|
||||
if entry.origin == "HP%" then
|
||||
if entry.sign == "=" and hppercent() == entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == ">" and hppercent() >= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == "<" and hppercent() <= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "HP" then
|
||||
if entry.sign == "=" and hp() == entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == ">" and hp() >= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == "<" and hp() <= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "MP%" then
|
||||
if entry.sign == "=" and manapercent() == entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == ">" and manapercent() >= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == "<" and manapercent() <= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "MP" then
|
||||
if entry.sign == "=" and mana() == entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == ">" and mana() >= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == "<" and mana() <= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "burst" then
|
||||
if entry.sign == "=" and burstDamageValue() == entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == ">" and burstDamageValue() >= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
elseif entry.sign == "<" and burstDamageValue() <= entry.value then
|
||||
say(entry.spell)
|
||||
return
|
||||
end
|
||||
end
|
||||
else
|
||||
somethingIsOnCooldown = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if not somethingIsOnCooldown then
|
||||
standBySpells = true
|
||||
end
|
||||
end)
|
||||
|
||||
-- items
|
||||
macro(100, function()
|
||||
if standByItems then return end
|
||||
if not currentSettings.enabled or #currentSettings.itemTable == 0 then return end
|
||||
if currentSettings.Delay and vBot.isUsing then return end
|
||||
if currentSettings.MessageDelay and vBot.isUsingPotion then return end
|
||||
|
||||
if not currentSettings.MessageDelay then
|
||||
delay(400)
|
||||
end
|
||||
|
||||
if TargetBot.isOn() and TargetBot.Looting.getStatus():len() > 0 and currentSettings.Interval then
|
||||
if not currentSettings.MessageDelay then
|
||||
delay(700)
|
||||
else
|
||||
delay(200)
|
||||
end
|
||||
end
|
||||
|
||||
for _, entry in pairs(currentSettings.itemTable) do
|
||||
local item = findItem(entry.item)
|
||||
if (not currentSettings.Visible or item) and entry.enabled then
|
||||
if entry.origin == "HP%" then
|
||||
if entry.sign == "=" and hppercent() == entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == ">" and hppercent() >= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == "<" and hppercent() <= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "HP" then
|
||||
if entry.sign == "=" and hp() == tonumberentry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == ">" and hp() >= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == "<" and hp() <= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "MP%" then
|
||||
if entry.sign == "=" and manapercent() == entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == ">" and manapercent() >= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == "<" and manapercent() <= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "MP" then
|
||||
if entry.sign == "=" and mana() == entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == ">" and mana() >= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == "<" and mana() <= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "burst" then
|
||||
if entry.sign == "=" and burstDamageValue() == entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == ">" and burstDamageValue() >= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == "<" and burstDamageValue() <= entry.value then
|
||||
g_game.useInventoryItemWith(entry.item, player)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
standByItems = true
|
||||
end)
|
||||
UI.Separator()
|
||||
|
||||
onPlayerHealthChange(function(healthPercent)
|
||||
standByItems = false
|
||||
standBySpells = false
|
||||
end)
|
||||
|
||||
onManaChange(function(player, mana, maxMana, oldMana, oldMaxMana)
|
||||
standByItems = false
|
||||
standBySpells = false
|
||||
end)
|
||||
492
modules/game_bot/default_configs/vBot_4.7/vBot/HealBot.otui
Normal file
492
modules/game_bot/default_configs/vBot_4.7/vBot/HealBot.otui
Normal file
@@ -0,0 +1,492 @@
|
||||
SettingCheckBox < CheckBox
|
||||
text-wrap: true
|
||||
text-auto-resize: true
|
||||
margin-top: 3
|
||||
font: verdana-11px-rounded
|
||||
|
||||
SpellSourceBoxPopupMenu < ComboBoxPopupMenu
|
||||
SpellSourceBoxPopupMenuButton < ComboBoxPopupMenuButton
|
||||
SpellSourceBox < ComboBox
|
||||
@onSetup: |
|
||||
self:addOption("Current Mana")
|
||||
self:addOption("Current Health")
|
||||
self:addOption("Mana Percent")
|
||||
self:addOption("Health Percent")
|
||||
self:addOption("Burst Damage")
|
||||
|
||||
SpellConditionBoxPopupMenu < ComboBoxPopupMenu
|
||||
SpellConditionBoxPopupMenuButton < ComboBoxPopupMenuButton
|
||||
SpellConditionBox < ComboBox
|
||||
@onSetup: |
|
||||
self:addOption("Below")
|
||||
self:addOption("Above")
|
||||
self:addOption("Equal To")
|
||||
|
||||
SpellEntry < Label
|
||||
background-color: alpha
|
||||
text-offset: 18 1
|
||||
focusable: true
|
||||
height: 16
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: enabled
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 15
|
||||
height: 15
|
||||
margin-top: 2
|
||||
margin-left: 3
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
Button
|
||||
id: remove
|
||||
!text: tr('x')
|
||||
anchors.right: parent.right
|
||||
margin-right: 15
|
||||
text-offset: 1 0
|
||||
width: 15
|
||||
height: 15
|
||||
|
||||
ItemEntry < Label
|
||||
background-color: alpha
|
||||
text-offset: 40 1
|
||||
focusable: true
|
||||
height: 16
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: enabled
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 15
|
||||
height: 15
|
||||
margin-top: 2
|
||||
margin-left: 3
|
||||
|
||||
UIItem
|
||||
id: id
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
size: 15 15
|
||||
focusable: false
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
Button
|
||||
id: remove
|
||||
!text: tr('x')
|
||||
anchors.right: parent.right
|
||||
margin-right: 15
|
||||
text-offset: 1 0
|
||||
width: 15
|
||||
height: 15
|
||||
|
||||
SpellHealing < FlatPanel
|
||||
size: 490 130
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.verticalCenter: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-left: 5
|
||||
text: Spell Healing
|
||||
color: #269e26
|
||||
font: verdana-11px-rounded
|
||||
|
||||
SpellSourceBox
|
||||
id: spellSource
|
||||
anchors.top: spellList.top
|
||||
anchors.left: spellList.right
|
||||
margin-left: 80
|
||||
width: 125
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: whenSpell
|
||||
anchors.left: spellList.right
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
text: When
|
||||
margin-left: 7
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: isSpell
|
||||
anchors.left: spellList.right
|
||||
anchors.top: whenSpell.bottom
|
||||
text: Is
|
||||
margin-top: 9
|
||||
margin-left: 7
|
||||
font: verdana-11px-rounded
|
||||
|
||||
SpellConditionBox
|
||||
id: spellCondition
|
||||
anchors.left: spellSource.left
|
||||
anchors.top: spellSource.bottom
|
||||
marin-top: 15
|
||||
width: 80
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: spellValue
|
||||
anchors.left: spellCondition.right
|
||||
anchors.top: spellCondition.top
|
||||
anchors.bottom: spellCondition.bottom
|
||||
anchors.right: spellSource.right
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: castSpell
|
||||
anchors.left: isSpell.left
|
||||
anchors.top: isSpell.bottom
|
||||
text: Cast
|
||||
margin-top: 9
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: spellFormula
|
||||
anchors.left: spellCondition.left
|
||||
anchors.top: spellCondition.bottom
|
||||
anchors.right: spellValue.right
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: manaSpell
|
||||
anchors.left: castSpell.left
|
||||
anchors.top: castSpell.bottom
|
||||
text: Mana Cost:
|
||||
margin-top: 8
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: manaCost
|
||||
anchors.left: spellFormula.left
|
||||
anchors.top: spellFormula.bottom
|
||||
width: 40
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextList
|
||||
id: spellList
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.top: parent.top
|
||||
padding: 1
|
||||
padding-top: 2
|
||||
width: 270
|
||||
margin-bottom: 7
|
||||
margin-left: 7
|
||||
margin-top: 10
|
||||
vertical-scrollbar: spellListScrollBar
|
||||
|
||||
VerticalScrollBar
|
||||
id: spellListScrollBar
|
||||
anchors.top: spellList.top
|
||||
anchors.bottom: spellList.bottom
|
||||
anchors.right: spellList.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
Button
|
||||
id: addSpell
|
||||
anchors.right: spellFormula.right
|
||||
anchors.bottom: spellList.bottom
|
||||
text: Add
|
||||
size: 40 17
|
||||
font: cipsoftFont
|
||||
|
||||
Button
|
||||
id: MoveUp
|
||||
anchors.right: prev.left
|
||||
anchors.bottom: prev.bottom
|
||||
margin-right: 5
|
||||
text: Move Up
|
||||
size: 55 17
|
||||
font: cipsoftFont
|
||||
|
||||
Button
|
||||
id: MoveDown
|
||||
anchors.right: prev.left
|
||||
anchors.bottom: prev.bottom
|
||||
margin-right: 5
|
||||
text: Move Down
|
||||
size: 55 17
|
||||
font: cipsoftFont
|
||||
|
||||
ItemHealing < FlatPanel
|
||||
size: 490 120
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.verticalCenter: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-left: 5
|
||||
text: Item Healing
|
||||
color: #ff4513
|
||||
font: verdana-11px-rounded
|
||||
|
||||
SpellSourceBox
|
||||
id: itemSource
|
||||
anchors.top: itemList.top
|
||||
anchors.right: parent.right
|
||||
margin-right: 10
|
||||
width: 128
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: whenItem
|
||||
anchors.left: itemList.right
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
text: When
|
||||
margin-left: 7
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: isItem
|
||||
anchors.left: itemList.right
|
||||
anchors.top: whenItem.bottom
|
||||
text: Is
|
||||
margin-top: 9
|
||||
margin-left: 7
|
||||
font: verdana-11px-rounded
|
||||
|
||||
SpellConditionBox
|
||||
id: itemCondition
|
||||
anchors.left: itemSource.left
|
||||
anchors.top: itemSource.bottom
|
||||
marin-top: 15
|
||||
width: 80
|
||||
font: verdana-11px-rounded
|
||||
|
||||
TextEdit
|
||||
id: itemValue
|
||||
anchors.left: itemCondition.right
|
||||
anchors.top: itemCondition.top
|
||||
anchors.bottom: itemCondition.bottom
|
||||
width: 49
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Label
|
||||
id: useItem
|
||||
anchors.left: isItem.left
|
||||
anchors.top: isItem.bottom
|
||||
text: Use
|
||||
margin-top: 15
|
||||
font: verdana-11px-rounded
|
||||
|
||||
BotItem
|
||||
id: itemId
|
||||
anchors.left: itemCondition.left
|
||||
anchors.top: itemCondition.bottom
|
||||
|
||||
TextList
|
||||
id: itemList
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.top: parent.top
|
||||
padding: 1
|
||||
padding-top: 2
|
||||
width: 270
|
||||
margin-top: 10
|
||||
margin-bottom: 7
|
||||
margin-left: 8
|
||||
vertical-scrollbar: itemListScrollBar
|
||||
|
||||
VerticalScrollBar
|
||||
id: itemListScrollBar
|
||||
anchors.top: itemList.top
|
||||
anchors.bottom: itemList.bottom
|
||||
anchors.right: itemList.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
Button
|
||||
id: addItem
|
||||
anchors.right: itemValue.right
|
||||
anchors.bottom: itemList.bottom
|
||||
text: Add
|
||||
size: 40 17
|
||||
font: cipsoftFont
|
||||
|
||||
Button
|
||||
id: MoveUp
|
||||
anchors.right: prev.left
|
||||
anchors.bottom: prev.bottom
|
||||
margin-right: 5
|
||||
text: Move Up
|
||||
size: 55 17
|
||||
font: cipsoftFont
|
||||
|
||||
Button
|
||||
id: MoveDown
|
||||
anchors.right: prev.left
|
||||
anchors.bottom: prev.bottom
|
||||
margin-right: 5
|
||||
text: Move Down
|
||||
size: 55 17
|
||||
font: cipsoftFont
|
||||
|
||||
HealerPanel < Panel
|
||||
size: 510 275
|
||||
|
||||
SpellHealing
|
||||
id: spells
|
||||
anchors.top: parent.top
|
||||
margin-top: 8
|
||||
anchors.left: parent.left
|
||||
|
||||
ItemHealing
|
||||
id: items
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
margin-top: 10
|
||||
|
||||
HealBotSettingsPanel < Panel
|
||||
size: 500 267
|
||||
padding-top: 8
|
||||
|
||||
FlatPanel
|
||||
id: list
|
||||
anchors.fill: parent
|
||||
margin-right: 240
|
||||
padding-left: 6
|
||||
padding-right: 6
|
||||
padding-top: 6
|
||||
layout:
|
||||
type: verticalBox
|
||||
|
||||
Label
|
||||
text: Additional Settings
|
||||
text-align: center
|
||||
font: verdana-11px-rounded
|
||||
|
||||
HorizontalSeparator
|
||||
|
||||
SettingCheckBox
|
||||
id: Cooldown
|
||||
text: Check spell cooldowns
|
||||
margin-top: 10
|
||||
|
||||
SettingCheckBox
|
||||
id: Visible
|
||||
text: Items must be visible (recommended)
|
||||
|
||||
SettingCheckBox
|
||||
id: Delay
|
||||
text: Don't use items when interacting
|
||||
|
||||
SettingCheckBox
|
||||
id: Interval
|
||||
text: Additional delay when looting corpses
|
||||
|
||||
SettingCheckBox
|
||||
id: Conditions
|
||||
text: Also check conditions from RL Tibia
|
||||
|
||||
SettingCheckBox
|
||||
id: MessageDelay
|
||||
text: Cooldown based on "Aaaah..." message
|
||||
|
||||
VerticalSeparator
|
||||
anchors.top: prev.top
|
||||
anchors.bottom: prev.bottom
|
||||
anchors.left: prev.right
|
||||
margin-left: 8
|
||||
|
||||
FlatPanel
|
||||
id: profiles
|
||||
anchors.fill: parent
|
||||
anchors.left: prev.left
|
||||
margin-left: 8
|
||||
margin-right: 8
|
||||
padding: 8
|
||||
|
||||
Label
|
||||
text: Profile Settings
|
||||
text-align: center
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
font: verdana-11px-rounded
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Label
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 30
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
font: verdana-11px-rounded
|
||||
text: Profile Name:
|
||||
|
||||
TextEdit
|
||||
id: Name
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Button
|
||||
id: ResetSettings
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: Reset Current Profile
|
||||
text-auto-resize: true
|
||||
color: #ff4513
|
||||
|
||||
HealWindow < MainWindow
|
||||
!text: tr('Self Healer')
|
||||
size: 520 360
|
||||
@onEscape: self:hide()
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
margin-left: 2
|
||||
!text: tr('More important methods come first (Example: Exura gran above Exura)')
|
||||
text-align: left
|
||||
font: verdana-11px-rounded
|
||||
color: #aeaeae
|
||||
|
||||
HealerPanel
|
||||
id: healer
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
|
||||
HealBotSettingsPanel
|
||||
id: settings
|
||||
anchors.top: title.bottom
|
||||
anchors.left: parent.left
|
||||
visible: false
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 8
|
||||
|
||||
Button
|
||||
id: closeButton
|
||||
!text: tr('Close')
|
||||
font: cipsoftFont
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
margin-right: 5
|
||||
|
||||
Button
|
||||
id: settingsButton
|
||||
!text: tr('Settings')
|
||||
font: cipsoftFont
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
252
modules/game_bot/default_configs/vBot_4.7/vBot/Sio.lua
Normal file
252
modules/game_bot/default_configs/vBot_4.7/vBot/Sio.lua
Normal file
@@ -0,0 +1,252 @@
|
||||
setDefaultTab("Main")
|
||||
local panelName = "advancedFriendHealer"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 19
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('Friend Healer')
|
||||
|
||||
Button
|
||||
id: editList
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Setup
|
||||
|
||||
]], parent)
|
||||
ui:setId(panelName)
|
||||
|
||||
if not storage[panelName] then
|
||||
storage[panelName] = {
|
||||
minMana = 60,
|
||||
minFriendHp = 40,
|
||||
customSpellName = "exura max sio",
|
||||
customSpell = false,
|
||||
distance = 8,
|
||||
itemHeal = false,
|
||||
id = 3160,
|
||||
exuraSio = false,
|
||||
exuraGranSio = false,
|
||||
exuraMasRes = false,
|
||||
healEk = false,
|
||||
healRp = false,
|
||||
healEd = false,
|
||||
healMs = false
|
||||
}
|
||||
end
|
||||
|
||||
local config = storage[panelName]
|
||||
|
||||
-- basic elements
|
||||
ui.title:setOn(config.enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
config.enabled = not config.enabled
|
||||
widget:setOn(config.enabled)
|
||||
end
|
||||
ui.editList.onClick = function(widget)
|
||||
sioListWindow:show()
|
||||
sioListWindow:raise()
|
||||
sioListWindow:focus()
|
||||
end
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
sioListWindow = UI.createWindow('SioListWindow', rootWidget)
|
||||
sioListWindow:hide()
|
||||
|
||||
-- TextWindow
|
||||
sioListWindow.spellName:setText(config.customSpellName)
|
||||
sioListWindow.spellName.onTextChange = function(widget, text)
|
||||
config.customSpellName = text
|
||||
end
|
||||
|
||||
-- botswitches
|
||||
sioListWindow.spell:setOn(config.customSpell)
|
||||
sioListWindow.spell.onClick = function(widget)
|
||||
config.customSpell = not config.customSpell
|
||||
widget:setOn(config.customSpell)
|
||||
end
|
||||
sioListWindow.item:setOn(config.itemHeal)
|
||||
sioListWindow.item.onClick = function(widget)
|
||||
config.itemHeal = not config.itemHeal
|
||||
widget:setOn(config.itemHeal)
|
||||
end
|
||||
sioListWindow.exuraSio:setOn(config.exuraSio)
|
||||
sioListWindow.exuraSio.onClick = function(widget)
|
||||
config.exuraSio = not config.exuraSio
|
||||
widget:setOn(config.exuraSio)
|
||||
end
|
||||
sioListWindow.exuraGranSio:setOn(config.exuraGranSio)
|
||||
sioListWindow.exuraGranSio.onClick = function(widget)
|
||||
config.exuraGranSio = not config.exuraGranSio
|
||||
widget:setOn(config.exuraGranSio)
|
||||
end
|
||||
sioListWindow.exuraMasRes:setOn(config.exuraMasRes)
|
||||
sioListWindow.exuraMasRes.onClick = function(widget)
|
||||
config.exuraMasRes = not config.exuraMasRes
|
||||
widget:setOn(config.exuraMasRes)
|
||||
end
|
||||
sioListWindow.vocation.ED:setOn(config.healEd)
|
||||
sioListWindow.vocation.ED.onClick = function(widget)
|
||||
config.healEd = not config.healEd
|
||||
widget:setOn(config.healEd)
|
||||
end
|
||||
sioListWindow.vocation.MS:setOn(config.healMs)
|
||||
sioListWindow.vocation.MS.onClick = function(widget)
|
||||
config.healMs = not config.healMs
|
||||
widget:setOn(config.healMs)
|
||||
end
|
||||
sioListWindow.vocation.EK:setOn(config.healEk)
|
||||
sioListWindow.vocation.EK.onClick = function(widget)
|
||||
config.healEk = not config.healEk
|
||||
widget:setOn(config.healEk)
|
||||
end
|
||||
sioListWindow.vocation.RP:setOn(config.healRp)
|
||||
sioListWindow.vocation.RP.onClick = function(widget)
|
||||
config.healRp = not config.healRp
|
||||
widget:setOn(config.healRp)
|
||||
end
|
||||
|
||||
-- functions
|
||||
local updateMinManaText = function()
|
||||
sioListWindow.manaInfo:setText("Minimum Mana >= " .. config.minMana .. "%")
|
||||
end
|
||||
local updateFriendHpText = function()
|
||||
sioListWindow.friendHp:setText("Heal Friend Below " .. config.minFriendHp .. "% hp")
|
||||
end
|
||||
local updateDistanceText = function()
|
||||
sioListWindow.distText:setText("Max Distance: " .. config.distance)
|
||||
end
|
||||
|
||||
-- scrollbars and text updates
|
||||
sioListWindow.Distance:setValue(config.distance)
|
||||
sioListWindow.Distance.onValueChange = function(scroll, value)
|
||||
config.distance = value
|
||||
updateDistanceText()
|
||||
end
|
||||
updateDistanceText()
|
||||
|
||||
sioListWindow.minMana:setValue(config.minMana)
|
||||
sioListWindow.minMana.onValueChange = function(scroll, value)
|
||||
config.minMana = value
|
||||
updateMinManaText()
|
||||
end
|
||||
updateMinManaText()
|
||||
|
||||
sioListWindow.minFriendHp:setValue(config.minFriendHp)
|
||||
sioListWindow.minFriendHp.onValueChange = function(scroll, value)
|
||||
config.minFriendHp = value
|
||||
updateFriendHpText()
|
||||
end
|
||||
updateFriendHpText()
|
||||
|
||||
sioListWindow.itemId:setItemId(config.id)
|
||||
sioListWindow.itemId.onItemChange = function(widget)
|
||||
config.id = widget:getItemId()
|
||||
end
|
||||
|
||||
sioListWindow.closeButton.onClick = function(widget)
|
||||
sioListWindow:hide()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- local variables
|
||||
local newTibia = g_game.getClientVersion() >= 960
|
||||
|
||||
local function isValid(name)
|
||||
if not newTibia then return true end
|
||||
|
||||
local voc = vBot.BotServerMembers[name]
|
||||
if not voc then return true end
|
||||
|
||||
if voc == 11 then voc = 1
|
||||
elseif voc == 12 then voc = 2
|
||||
elseif voc == 13 then voc = 3
|
||||
elseif voc == 14 then voc = 4
|
||||
end
|
||||
|
||||
local isOk = false
|
||||
if voc == 1 and config.healEk then
|
||||
isOk = true
|
||||
elseif voc == 2 and config.healRp then
|
||||
isOk = true
|
||||
elseif voc == 3 and config.healMs then
|
||||
isOk = true
|
||||
elseif voc == 4 and config.healEd then
|
||||
isOk = true
|
||||
end
|
||||
|
||||
return isOk
|
||||
end
|
||||
|
||||
macro(200, function()
|
||||
if not config.enabled then return end
|
||||
if modules.game_cooldown.isGroupCooldownIconActive(2) then return end
|
||||
|
||||
--[[
|
||||
1. custom spell
|
||||
2. exura gran sio - at 50% of minHpValue
|
||||
3. exura gran mas res
|
||||
4. exura sio
|
||||
5. item healing
|
||||
--]]
|
||||
|
||||
-- exura gran sio & custom spell
|
||||
if config.customSpell or config.exuraGranSio then
|
||||
for i, spec in ipairs(getSpectators()) do
|
||||
if spec:isPlayer() and spec ~= player and isValid(spec:getName()) and spec:canShoot() then
|
||||
if isFriend(spec) then
|
||||
if config.customSpell and spec:getHealthPercent() <= config.minFriendHp then
|
||||
return cast(config.customSpellName .. ' "' .. spec:getName() .. '"', 1000)
|
||||
end
|
||||
if config.exuraGranSio and spec:getHealthPercent() <= config.minFriendHp/3 then
|
||||
if canCast('exura gran sio "' .. spec:getName() ..'"') then
|
||||
return cast('exura gran sio "' .. spec:getName() ..'"', 60000)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- exura gran mas res and standard sio
|
||||
local friends = 0
|
||||
if config.exuraMasRes then
|
||||
for i, spec in ipairs(getSpectators(player, largeRuneArea)) do
|
||||
if spec:isPlayer() and spec ~= player and isValid(spec:getName()) and spec:canShoot() then
|
||||
if isFriend(spec) and spec:getHealthPercent() <= config.minFriendHp then
|
||||
friends = friends + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
if friends > 1 then
|
||||
return cast('exura gran mas res', 2000)
|
||||
end
|
||||
end
|
||||
if config.exuraSio or config.itemHeal then
|
||||
for i, spec in ipairs(getSpectators()) do
|
||||
if spec:isPlayer() and spec ~= player and isValid(spec:getName()) and spec:canShoot() then
|
||||
if isFriend(spec) then
|
||||
if spec:getHealthPercent() <= config.minFriendHp then
|
||||
if config.exuraSio then
|
||||
return cast('exura sio "' .. spec:getName() .. '"', 1000)
|
||||
elseif findItem(config.id) and distanceFromPlayer(spec:getPosition()) <= config.distance then
|
||||
return useWith(config.id, spec)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
||||
addSeparator()
|
||||
272
modules/game_bot/default_configs/vBot_4.7/vBot/alarms.lua
Normal file
272
modules/game_bot/default_configs/vBot_4.7/vBot/alarms.lua
Normal file
@@ -0,0 +1,272 @@
|
||||
local panelName = "alarms"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 19
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('Alarms')
|
||||
|
||||
Button
|
||||
id: alerts
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Edit
|
||||
|
||||
]])
|
||||
ui:setId(panelName)
|
||||
|
||||
if not storage[panelName] then
|
||||
storage[panelName] = {
|
||||
enabled = false,
|
||||
playerAttack = false,
|
||||
playerDetected = false,
|
||||
playerDetectedLogout = false,
|
||||
creatureDetected = false,
|
||||
healthBelow = false,
|
||||
healthValue = 40,
|
||||
manaBelow = false,
|
||||
manaValue = 50,
|
||||
privateMessage = false,
|
||||
ignoreFriends = true,
|
||||
warnBoss = false,
|
||||
bossName = '[B]'
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
|
||||
local config = storage[panelName]
|
||||
|
||||
ui.title:setOn(config.enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
config.enabled = not config.enabled
|
||||
widget:setOn(config.enabled)
|
||||
end
|
||||
|
||||
-- new var's validation
|
||||
config.messageText = config.messageText or ""
|
||||
config.bossName = config.bossName or ""
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
alarmsWindow = UI.createWindow('AlarmsWindow', rootWidget)
|
||||
alarmsWindow:hide()
|
||||
|
||||
alarmsWindow.closeButton.onClick = function(widget)
|
||||
alarmsWindow:hide()
|
||||
end
|
||||
|
||||
alarmsWindow.playerAttack:setOn(config.playerAttack)
|
||||
alarmsWindow.playerAttack.onClick = function(widget)
|
||||
config.playerAttack = not config.playerAttack
|
||||
widget:setOn(config.playerAttack)
|
||||
end
|
||||
|
||||
alarmsWindow.playerDetected:setOn(config.playerDetected)
|
||||
alarmsWindow.playerDetected.onClick = function(widget)
|
||||
config.playerDetected = not config.playerDetected
|
||||
widget:setOn(config.playerDetected)
|
||||
end
|
||||
|
||||
alarmsWindow.playerDetectedLogout:setChecked(config.playerDetectedLogout)
|
||||
alarmsWindow.playerDetectedLogout.onClick = function(widget)
|
||||
config.playerDetectedLogout = not config.playerDetectedLogout
|
||||
widget:setChecked(config.playerDetectedLogout)
|
||||
end
|
||||
|
||||
alarmsWindow.creatureDetected:setOn(config.creatureDetected)
|
||||
alarmsWindow.creatureDetected.onClick = function(widget)
|
||||
config.creatureDetected = not config.creatureDetected
|
||||
widget:setOn(config.creatureDetected)
|
||||
end
|
||||
|
||||
alarmsWindow.healthBelow:setOn(config.healthBelow)
|
||||
alarmsWindow.healthBelow.onClick = function(widget)
|
||||
config.healthBelow = not config.healthBelow
|
||||
widget:setOn(config.healthBelow)
|
||||
end
|
||||
|
||||
alarmsWindow.healthValue.onValueChange = function(scroll, value)
|
||||
config.healthValue = value
|
||||
alarmsWindow.healthBelow:setText("Health < " .. config.healthValue .. "%")
|
||||
end
|
||||
alarmsWindow.healthValue:setValue(config.healthValue)
|
||||
|
||||
alarmsWindow.manaBelow:setOn(config.manaBelow)
|
||||
alarmsWindow.manaBelow.onClick = function(widget)
|
||||
config.manaBelow = not config.manaBelow
|
||||
widget:setOn(config.manaBelow)
|
||||
end
|
||||
|
||||
alarmsWindow.manaValue.onValueChange = function(scroll, value)
|
||||
config.manaValue = value
|
||||
alarmsWindow.manaBelow:setText("Mana < " .. config.manaValue .. "%")
|
||||
end
|
||||
alarmsWindow.manaValue:setValue(config.manaValue)
|
||||
|
||||
alarmsWindow.privateMessage:setOn(config.privateMessage)
|
||||
alarmsWindow.privateMessage.onClick = function(widget)
|
||||
config.privateMessage = not config.privateMessage
|
||||
widget:setOn(config.privateMessage)
|
||||
end
|
||||
|
||||
alarmsWindow.ignoreFriends:setOn(config.ignoreFriends)
|
||||
alarmsWindow.ignoreFriends.onClick = function(widget)
|
||||
config.ignoreFriends = not config.ignoreFriends
|
||||
widget:setOn(config.ignoreFriends)
|
||||
end
|
||||
|
||||
alarmsWindow.warnBoss:setOn(config.warnBoss)
|
||||
alarmsWindow.warnBoss.onClick = function(widget)
|
||||
config.warnBoss = not config.warnBoss
|
||||
widget:setOn(config.warnBoss)
|
||||
end
|
||||
|
||||
alarmsWindow.bossName:setText(config.bossName)
|
||||
alarmsWindow.bossName.onTextChange = function(widget, text)
|
||||
config.bossName = text
|
||||
end
|
||||
|
||||
alarmsWindow.warnMessage:setOn(config.warnMessage)
|
||||
alarmsWindow.warnMessage.onClick = function(widget)
|
||||
config.warnMessage = not config.warnMessage
|
||||
widget:setOn(config.warnMessage)
|
||||
end
|
||||
|
||||
alarmsWindow.messageText:setText(config.messageText)
|
||||
alarmsWindow.messageText.onTextChange = function(widget, text)
|
||||
config.messageText = text
|
||||
end
|
||||
|
||||
local pName = player:getName()
|
||||
onTextMessage(function(mode, text)
|
||||
if config.enabled and config.playerAttack and string.match(text, "hitpoints due to an attack") and not string.match(text, "hitpoints due to an attack by a ") then
|
||||
playSound("/sounds/Player_Attack.ogg")
|
||||
g_window.setTitle(pName .. " - Player Attacks!")
|
||||
return
|
||||
end
|
||||
|
||||
if config.warnMessage and config.messageText:len() > 0 then
|
||||
text = text:lower()
|
||||
local parts = string.split(config.messageText, ",")
|
||||
for i=1,#parts do
|
||||
local part = parts[i]
|
||||
part = part:trim()
|
||||
part = part:lower()
|
||||
|
||||
if text:find(part) then
|
||||
delay(1500)
|
||||
playSound(g_resources.fileExists("/sounds/Special_Message.ogg") and "/sounds/Special_Message.ogg" or "/sounds/Private_Message.ogg")
|
||||
g_window.setTitle(pName .. " - Special Message Detected: "..part)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
macro(100, function()
|
||||
if not config.enabled then
|
||||
return
|
||||
end
|
||||
local specs = getSpectators()
|
||||
if config.playerDetected then
|
||||
for _, spec in ipairs(specs) do
|
||||
if spec:isPlayer() and spec:getName() ~= name() then
|
||||
local specPos = spec:getPosition()
|
||||
if (not config.ignoreFriends or not isFriend(spec)) and math.max(math.abs(posx()-specPos.x), math.abs(posy()-specPos.y)) <= 8 then
|
||||
playSound("/sounds/Player_Detected.ogg")
|
||||
delay(1500)
|
||||
g_window.setTitle(pName .. " - Player Detected! "..spec:getName())
|
||||
if config.playerDetectedLogout then
|
||||
modules.game_interface.tryLogout(false)
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if config.creatureDetected then
|
||||
for _, spec in ipairs(specs) do
|
||||
if not spec:isPlayer() then
|
||||
local specPos = spec:getPosition()
|
||||
if math.max(math.abs(posx()-specPos.x), math.abs(posy()-specPos.y)) <= 8 then
|
||||
playSound("/sounds/Creature_Detected.ogg")
|
||||
delay(1500)
|
||||
g_window.setTitle(pName .. " - Creature Detected! "..spec:getName())
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if config.warnBoss then
|
||||
-- experimental, but since we check only names i think the best way would be to combine all spec's names into one string and then check it to avoid multiple loops
|
||||
if config.bossName:len() > 0 then
|
||||
local names = string.split(config.bossName, ",")
|
||||
local combinedString = ""
|
||||
for _, spec in ipairs(specs) do
|
||||
local specPos = spec:getPosition()
|
||||
if math.max(math.abs(posx() - specPos.x), math.abs(posy() - specPos.y)) <= 8 then
|
||||
local name = spec:getName():lower()
|
||||
-- add special sign between names to avoid unwanted combining mistakes
|
||||
combinedString = combinedString .."&"..name
|
||||
end
|
||||
end
|
||||
for i=1,#names do
|
||||
local name = names[i]
|
||||
name = name:trim()
|
||||
name = name:lower()
|
||||
|
||||
if combinedString:find(name) then
|
||||
playSound(g_resources.fileExists("/sounds/Special_Creature.ogg") and "/sounds/Special_Creature.ogg" or "/sounds/Creature_Detected.ogg")
|
||||
delay(1500)
|
||||
g_window.setTitle(pName .. " - Special Creature Detected: "..name)
|
||||
return
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if config.healthBelow then
|
||||
if hppercent() <= config.healthValue then
|
||||
playSound("/sounds/Low_Health.ogg")
|
||||
delay(1500)
|
||||
g_window.setTitle(pName .. " - Low Health! only: "..hppercent().."%")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if config.manaBelow then
|
||||
if manapercent() <= config.manaValue then
|
||||
playSound("/sounds/Low_Mana.ogg")
|
||||
delay(1500)
|
||||
g_window.setTitle(pName .. " - Low Mana! only: "..manapercent().."%")
|
||||
return
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
onTalk(function(name, level, mode, text, channelId, pos)
|
||||
if mode == 4 and config.enabled and config.privateMessage then
|
||||
playSound("/sounds/Private_Message.ogg")
|
||||
g_window.setTitle(pName .. " - Private Message from: " .. name)
|
||||
return
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
ui.alerts.onClick = function(widget)
|
||||
alarmsWindow:show()
|
||||
alarmsWindow:raise()
|
||||
alarmsWindow:focus()
|
||||
end
|
||||
181
modules/game_bot/default_configs/vBot_4.7/vBot/alarms.otui
Normal file
181
modules/game_bot/default_configs/vBot_4.7/vBot/alarms.otui
Normal file
@@ -0,0 +1,181 @@
|
||||
AlarmsWindow < MainWindow
|
||||
!text: tr('Alarms')
|
||||
size: 300 280
|
||||
@onEscape: self:hide()
|
||||
|
||||
BotSwitch
|
||||
id: playerAttack
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
text: Player Attack
|
||||
!tooltip: tr('Alerts when attacked by player.')
|
||||
|
||||
BotSwitch
|
||||
id: playerDetected
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 4
|
||||
text-align: center
|
||||
text: Player Detected
|
||||
!tooltip: tr('Alerts when a player is detected on screen.')
|
||||
|
||||
CheckBox
|
||||
id: playerDetectedLogout
|
||||
anchors.top: playerDetected.top
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
margin-top: 3
|
||||
margin-left: 4
|
||||
text: Logout
|
||||
!tooltip: tr('Attempts to logout when a player is detected on screen.')
|
||||
|
||||
BotSwitch
|
||||
id: ignoreFriends
|
||||
anchors.left: parent.left
|
||||
anchors.top: playerDetected.bottom
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
margin-top: 4
|
||||
text: Ignore Friends
|
||||
!tooltip: tr('Player detection alerts will ignore friends.')
|
||||
|
||||
HorizontalSeparator
|
||||
id: sepPlayer
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 4
|
||||
|
||||
BotSwitch
|
||||
id: creatureDetected
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: sepPlayer.bottom
|
||||
margin-top: 4
|
||||
text-align: center
|
||||
text: Creature Detected
|
||||
!tooltip: tr('Alerts when a creature is detected on screen.')
|
||||
|
||||
BotSwitch
|
||||
id: warnBoss
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
anchors.right: parent.horizontalCenter
|
||||
text-align: center
|
||||
margin-top: 5
|
||||
text: Creature Name
|
||||
!tooltip: tr('Alerts when a creature/npc with name is detected on screen. \n eg: Benjamin or [boss] would detect a creature with [boss] in name. \n You can add many examples, just separate them by comma.')
|
||||
|
||||
BotTextEdit
|
||||
id: bossName
|
||||
anchors.left: prev.right
|
||||
margin-left: 4
|
||||
anchors.top: prev.top
|
||||
anchors.right: parent.right
|
||||
margin-top: 1
|
||||
height: 17
|
||||
font: terminus-10px
|
||||
|
||||
HorizontalSeparator
|
||||
id: sepCreature
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 4
|
||||
|
||||
BotSwitch
|
||||
id: healthBelow
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
anchors.right: parent.horizontalCenter
|
||||
text-align: center
|
||||
margin-top: 4
|
||||
text: Health < 50%
|
||||
|
||||
HorizontalScrollBar
|
||||
id: healthValue
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.top: healthBelow.top
|
||||
margin-left: 3
|
||||
margin-top: 2
|
||||
minimum: 1
|
||||
maximum: 100
|
||||
step: 1
|
||||
|
||||
BotSwitch
|
||||
id: manaBelow
|
||||
anchors.left: parent.left
|
||||
anchors.top: healthBelow.bottom
|
||||
anchors.right: parent.horizontalCenter
|
||||
text-align: center
|
||||
margin-top: 4
|
||||
text: Mana < 50%
|
||||
|
||||
HorizontalScrollBar
|
||||
id: manaValue
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.top: manaBelow.top
|
||||
margin-left: 3
|
||||
margin-top: 2
|
||||
minimum: 1
|
||||
maximum: 100
|
||||
step: 1
|
||||
|
||||
HorizontalSeparator
|
||||
id: sepMessages
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 4
|
||||
|
||||
BotSwitch
|
||||
id: privateMessage
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
margin-top: 4
|
||||
text: Private Message
|
||||
!tooltip: tr('Alerts when recieving a private message.')
|
||||
|
||||
BotSwitch
|
||||
id: warnMessage
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
anchors.right: parent.horizontalCenter
|
||||
text-align: center
|
||||
margin-top: 5
|
||||
text: Message Alert
|
||||
!tooltip: tr('Alerts when players receive a message that contains given part. \n Eg. event - will trigger alert whenever a message with word event appears. \n You can give many examples, just separate them by comma.')
|
||||
|
||||
BotTextEdit
|
||||
id: messageText
|
||||
anchors.left: prev.right
|
||||
margin-left: 4
|
||||
anchors.top: prev.top
|
||||
anchors.right: parent.right
|
||||
margin-top: 1
|
||||
height: 17
|
||||
font: terminus-10px
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 8
|
||||
|
||||
Button
|
||||
id: closeButton
|
||||
!text: tr('Close')
|
||||
font: cipsoftFont
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
margin-top: 15
|
||||
margin-right: 5
|
||||
1721
modules/game_bot/default_configs/vBot_4.7/vBot/analyzer.lua
Normal file
1721
modules/game_bot/default_configs/vBot_4.7/vBot/analyzer.lua
Normal file
File diff suppressed because it is too large
Load Diff
443
modules/game_bot/default_configs/vBot_4.7/vBot/analyzer.otui
Normal file
443
modules/game_bot/default_configs/vBot_4.7/vBot/analyzer.otui
Normal file
@@ -0,0 +1,443 @@
|
||||
TrackerItem < Panel
|
||||
height: 40
|
||||
|
||||
BotItem
|
||||
id: item
|
||||
anchors.top: parent.top
|
||||
margin-top: 2
|
||||
anchors.left: parent.left
|
||||
image-source:
|
||||
|
||||
UIWidget
|
||||
id: name
|
||||
anchors.top: prev.top
|
||||
margin-top: 1
|
||||
anchors.bottom: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 5
|
||||
text: Set Item to start track.
|
||||
text-align:left
|
||||
font: verdana-11px-rounded
|
||||
color: #FFFFFF
|
||||
|
||||
UIWidget
|
||||
id: drops
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
anchors.bottom: Item.bottom
|
||||
anchors.left: prev.left
|
||||
anchors.right: parent.right
|
||||
font: verdana-11px-rounded
|
||||
text-align:left
|
||||
text: Loot Drops: 0
|
||||
color: #CCCCCC
|
||||
|
||||
|
||||
DualLabel < Label
|
||||
height: 15
|
||||
text-offset: 4 0
|
||||
font: verdana-11px-rounded
|
||||
text-align: left
|
||||
width: 50
|
||||
|
||||
Label
|
||||
id: value
|
||||
anchors.right: parent.right
|
||||
margin-right: 4
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 200
|
||||
font: verdana-11px-rounded
|
||||
text-align: right
|
||||
text: 0
|
||||
|
||||
MemberWidget < Panel
|
||||
height: 85
|
||||
margin-top: 3
|
||||
|
||||
UICreature
|
||||
id: creature
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
size: 28 28
|
||||
|
||||
UIWidget
|
||||
id: name
|
||||
anchors.left: prev.right
|
||||
margin-left: 5
|
||||
anchors.top: parent.top
|
||||
height: 12
|
||||
anchors.right: parent.right
|
||||
text: Player Name
|
||||
font: verdana-11px-rounded
|
||||
text-align: left
|
||||
|
||||
ProgressBar
|
||||
id: health
|
||||
anchors.left: prev.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 2
|
||||
height: 7
|
||||
background-color: #00c000
|
||||
phantom: false
|
||||
|
||||
ProgressBar
|
||||
id: mana
|
||||
anchors.left: prev.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
height: 7
|
||||
background-color: #0000FF
|
||||
phantom: false
|
||||
|
||||
DualLabel
|
||||
id: balance
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 5
|
||||
text: Balance:
|
||||
|
||||
DualLabel
|
||||
id: damage
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 2
|
||||
text: Damage:
|
||||
|
||||
DualLabel
|
||||
id: healing
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 2
|
||||
text: Healing:
|
||||
|
||||
AnalyzerPriceLabel < Label
|
||||
background-color: alpha
|
||||
text-offset: 2 0
|
||||
focusable: true
|
||||
height: 16
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
Button
|
||||
id: remove
|
||||
!text: tr('x')
|
||||
anchors.right: parent.right
|
||||
margin-right: 15
|
||||
width: 15
|
||||
height: 15
|
||||
|
||||
AnalyzerListPanel < Panel
|
||||
padding-left: 4
|
||||
padding-right: 4
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
|
||||
ListLabel < Label
|
||||
height: 15
|
||||
font: verdana-11px-rounded
|
||||
text-offset: 15 0
|
||||
|
||||
AnalyzerItemsPanel < Panel
|
||||
id: List
|
||||
padding: 2
|
||||
layout:
|
||||
type: grid
|
||||
cell-size: 33 33
|
||||
cell-spacing: 1
|
||||
num-columns: 5
|
||||
fit-children: true
|
||||
|
||||
AnalyzerLootItem < UIItem
|
||||
opacity: 0.87
|
||||
height: 37
|
||||
margin-left: 1
|
||||
virtual: true
|
||||
background-color: alpha
|
||||
|
||||
Label
|
||||
id: count
|
||||
font: verdana-11px-rounded
|
||||
color: white
|
||||
opacity: 0.87
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 2
|
||||
text-align: right
|
||||
text: 0
|
||||
|
||||
AnalyzerGraph < UIGraph
|
||||
height: 140
|
||||
capacity: 400
|
||||
line-width: 1
|
||||
color: red
|
||||
margin-top: 5
|
||||
margin-left: 5
|
||||
margin-right: 5
|
||||
background-color: #383636
|
||||
padding: 5
|
||||
font: verdana-11px-rounded
|
||||
image-source: /images/ui/graph_background
|
||||
|
||||
AnalyzerProgressBar < ProgressBar
|
||||
background-color: green
|
||||
height: 5
|
||||
margin-top: 3
|
||||
phantom: false
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
border: 1 black
|
||||
|
||||
AnalyzerButton < Button
|
||||
height: 22
|
||||
margin-bottom: 2
|
||||
font: verdana-11px-rounded
|
||||
text-offset: 0 4
|
||||
|
||||
MainAnalyzerWindow < MiniWindow
|
||||
id: MainAnalyzerWindow
|
||||
text: Analytics Selector
|
||||
height: 266
|
||||
icon: /images/topbuttons/analyzers
|
||||
|
||||
MiniWindowContents
|
||||
padding-left: 5
|
||||
padding-right: 5
|
||||
padding-top: 5
|
||||
layout: verticalBox
|
||||
|
||||
AnalyzerButton
|
||||
id: HuntingAnalyzer
|
||||
text: Hunting Analyzer
|
||||
|
||||
AnalyzerButton
|
||||
id: LootAnalyzer
|
||||
text: Loot Analyzer
|
||||
|
||||
AnalyzerButton
|
||||
id: SupplyAnalyzer
|
||||
text: Supply Analyzer
|
||||
|
||||
AnalyzerButton
|
||||
id: ImpactAnalyzer
|
||||
text: Impact Analyzer
|
||||
|
||||
AnalyzerButton
|
||||
id: XPAnalyzer
|
||||
text: XP Analyzer
|
||||
|
||||
AnalyzerButton
|
||||
id: DropTracker
|
||||
text: Drop Tracker
|
||||
|
||||
AnalyzerButton
|
||||
id: Stats
|
||||
text: CaveBot Stats
|
||||
color: #74B73E
|
||||
|
||||
AnalyzerButton
|
||||
id: PartyHunt
|
||||
text: Party Hunt
|
||||
color: #3895D3
|
||||
|
||||
AnalyzerButton
|
||||
id: Settings
|
||||
text: Features & Settings
|
||||
color: #FABD02
|
||||
|
||||
AnalyzerButton
|
||||
id: ResetSession
|
||||
text: Reset Session
|
||||
color: #FF0000
|
||||
|
||||
HuntingAnalyzer < MiniWindow
|
||||
id: HuntingAnalyzerWindow
|
||||
text: Hunt Analyzer
|
||||
icon: /images/topbuttons/analyzers
|
||||
|
||||
MiniWindowContents
|
||||
padding-top: 3
|
||||
layout: verticalBox
|
||||
|
||||
LootAnalyzer < MiniWindow
|
||||
id: LootAnalyzerWindow
|
||||
text: Loot Analyzer
|
||||
icon: /images/topbuttons/analyzers
|
||||
|
||||
MiniWindowContents
|
||||
padding-top: 3
|
||||
layout: verticalBox
|
||||
|
||||
SupplyAnalyzer < MiniWindow
|
||||
id: SupplyAnalyzerWindow
|
||||
text: Supply Analyzer
|
||||
icon: /images/topbuttons/analyzers
|
||||
|
||||
MiniWindowContents
|
||||
padding-top: 3
|
||||
layout: verticalBox
|
||||
|
||||
ImpactAnalyzer < MiniWindow
|
||||
id: ImpactAnalyzerWindow
|
||||
text: Impact Analyzer
|
||||
icon: /images/topbuttons/analyzers
|
||||
|
||||
MiniWindowContents
|
||||
padding-top: 3
|
||||
layout: verticalBox
|
||||
|
||||
XPAnalyzer < MiniWindow
|
||||
id: XPAnalyzerWindow
|
||||
text: XP Analyzer
|
||||
height: 150
|
||||
icon: /images/topbuttons/analyzers
|
||||
|
||||
MiniWindowContents
|
||||
padding-top: 3
|
||||
layout: verticalBox
|
||||
|
||||
PartyAnalyzerWindow < MiniWindow
|
||||
id: PartyAnalyzerWindow
|
||||
text: Party Hunt
|
||||
height: 200
|
||||
icon: /images/topbuttons/analyzers
|
||||
|
||||
MiniWindowContents
|
||||
padding-left: 3
|
||||
padding-right: 3
|
||||
padding-top: 1
|
||||
layout: verticalBox
|
||||
|
||||
DropTracker < MiniWindow
|
||||
id: DropTracker
|
||||
text: Drop Tracker
|
||||
height: 200
|
||||
icon: /images/topbuttons/analyzers
|
||||
|
||||
MiniWindowContents
|
||||
padding-left: 3
|
||||
padding-right: 3
|
||||
padding-top: 1
|
||||
layout: verticalBox
|
||||
|
||||
CaveBotStats < MiniWindow
|
||||
id: CaveBotStats
|
||||
text: CaveBot Stats
|
||||
height: 200
|
||||
icon: /images/topbuttons/analyzers
|
||||
|
||||
MiniWindowContents
|
||||
padding-left: 3
|
||||
padding-right: 3
|
||||
padding-top: 1
|
||||
layout: verticalBox
|
||||
|
||||
FeaturesWindow < MainWindow
|
||||
id: FeaturesWindow
|
||||
size: 250 370
|
||||
padding: 15
|
||||
text: Analyzers Features
|
||||
@onEscape: self:hide()
|
||||
|
||||
TextList
|
||||
id: CustomPrices
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 10
|
||||
padding: 1
|
||||
height: 220
|
||||
vertical-scrollbar: CustomPricesScrollBar
|
||||
|
||||
VerticalScrollBar
|
||||
id: CustomPricesScrollBar
|
||||
anchors.top: CustomPrices.top
|
||||
anchors.bottom: CustomPrices.bottom
|
||||
anchors.right: CustomPrices.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
BotItem
|
||||
id: ID
|
||||
anchors.left: CustomPrices.left
|
||||
anchors.top: CustomPrices.bottom
|
||||
margin-top: 5
|
||||
|
||||
SpinBox
|
||||
id: NewPrice
|
||||
anchors.left: prev.right
|
||||
margin-left: 5
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
width: 100
|
||||
minimum: 0
|
||||
maximum: 1000000000
|
||||
step: 1
|
||||
text-align: center
|
||||
focusable: true
|
||||
|
||||
Button
|
||||
id: addItem
|
||||
anchors.left: prev.right
|
||||
margin-left: 5
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: CustomPrices.right
|
||||
text: Add
|
||||
font: verdana-11px-rounded
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.left: ID.right
|
||||
margin-left: 5
|
||||
anchors.right: CustomPrices.right
|
||||
anchors.verticalCenter: ID.top
|
||||
|
||||
HorizontalSeparator
|
||||
id: secondSeparator
|
||||
anchors.left: ID.right
|
||||
margin-left: 5
|
||||
anchors.right: CustomPrices.right
|
||||
anchors.bottom: ID.bottom
|
||||
|
||||
BotSwitch
|
||||
id: LootChannel
|
||||
anchors.left: CustomPrices.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
margin-right: 2
|
||||
anchors.top: prev.top
|
||||
margin-top: 20
|
||||
text: Loot Channel
|
||||
font: verdana-11px-rounded
|
||||
|
||||
BotSwitch
|
||||
id: RarityFrames
|
||||
anchors.left: parent.horizontalCenter
|
||||
margin-left: 2
|
||||
anchors.right: CustomPrices.right
|
||||
anchors.top: secondSeparator.top
|
||||
margin-top: 20
|
||||
text: Rarity Frames
|
||||
font: verdana-11px-rounded
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 8
|
||||
|
||||
Button
|
||||
id: closeButton
|
||||
!text: tr('Close')
|
||||
font: cipsoftFont
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
margin-top: 15
|
||||
margin-right: 5
|
||||
33
modules/game_bot/default_configs/vBot_4.7/vBot/antiRs.lua
Normal file
33
modules/game_bot/default_configs/vBot_4.7/vBot/antiRs.lua
Normal file
@@ -0,0 +1,33 @@
|
||||
setDefaultTab("Tools")
|
||||
g_game.cancelAttackAndFollow()
|
||||
|
||||
local frags = 0
|
||||
local unequip = false
|
||||
local m = macro(50, "AntiRS & Msg", function() end)
|
||||
|
||||
function safeExit()
|
||||
CaveBot.setOff()
|
||||
TargetBot.setOff()
|
||||
g_game.cancelAttackAndFollow()
|
||||
g_game.cancelAttackAndFollow()
|
||||
g_game.cancelAttackAndFollow()
|
||||
modules.game_interface.forceExit()
|
||||
end
|
||||
|
||||
onTextMessage(function(mode, text)
|
||||
if not m.isOn() then return end
|
||||
if not text:find("Warning! The murder of") then return end
|
||||
frags = frags + 1
|
||||
if killsToRs() < 6 or frags > 1 then
|
||||
EquipManager.setOff()
|
||||
schedule(100, function()
|
||||
local id = getLeft() and getLeft():getId()
|
||||
|
||||
if id and not unequip then
|
||||
unequip = true
|
||||
g_game.equipItemId(id)
|
||||
end
|
||||
safeExit()
|
||||
end)
|
||||
end
|
||||
end)
|
||||
22
modules/game_bot/default_configs/vBot_4.7/vBot/cast_food.lua
Normal file
22
modules/game_bot/default_configs/vBot_4.7/vBot/cast_food.lua
Normal file
@@ -0,0 +1,22 @@
|
||||
setDefaultTab("HP")
|
||||
if voc() ~= 1 and voc() ~= 11 then
|
||||
if storage.foodItems then
|
||||
local t = {}
|
||||
for i, v in pairs(storage.foodItems) do
|
||||
if not table.find(t, v.id) then
|
||||
table.insert(t, v.id)
|
||||
end
|
||||
end
|
||||
local foodItems = { 3607, 3585, 3592, 3600, 3601 }
|
||||
for i, item in pairs(foodItems) do
|
||||
if not table.find(t, item) then
|
||||
table.insert(storage.foodItems, item)
|
||||
end
|
||||
end
|
||||
end
|
||||
macro(500, "Cast Food", function()
|
||||
if player:getRegenerationTime() <= 400 then
|
||||
cast("exevo pan", 5000)
|
||||
end
|
||||
end)
|
||||
end
|
||||
53
modules/game_bot/default_configs/vBot_4.7/vBot/cavebot.lua
Normal file
53
modules/game_bot/default_configs/vBot_4.7/vBot/cavebot.lua
Normal file
@@ -0,0 +1,53 @@
|
||||
-- Cavebot by otclient@otclient.ovh
|
||||
-- visit http://bot.otclient.ovh/
|
||||
|
||||
local cavebotTab = "Cave"
|
||||
local targetingTab = storage.extras.joinBot and "Cave" or "Target"
|
||||
|
||||
setDefaultTab(cavebotTab)
|
||||
CaveBot.Extensions = {}
|
||||
importStyle("/cavebot/cavebot.otui")
|
||||
importStyle("/cavebot/config.otui")
|
||||
importStyle("/cavebot/editor.otui")
|
||||
dofile("/cavebot/actions.lua")
|
||||
dofile("/cavebot/config.lua")
|
||||
dofile("/cavebot/editor.lua")
|
||||
dofile("/cavebot/example_functions.lua")
|
||||
dofile("/cavebot/recorder.lua")
|
||||
dofile("/cavebot/walking.lua")
|
||||
dofile("/cavebot/minimap.lua")
|
||||
-- in this section you can add extensions, check extension_template.lua
|
||||
--dofile("/cavebot/extension_template.lua")
|
||||
dofile("/cavebot/sell_all.lua")
|
||||
dofile("/cavebot/depositor.lua")
|
||||
dofile("/cavebot/buy_supplies.lua")
|
||||
dofile("/cavebot/d_withdraw.lua")
|
||||
dofile("/cavebot/supply_check.lua")
|
||||
dofile("/cavebot/travel.lua")
|
||||
dofile("/cavebot/doors.lua")
|
||||
dofile("/cavebot/pos_check.lua")
|
||||
dofile("/cavebot/withdraw.lua")
|
||||
dofile("/cavebot/inbox_withdraw.lua")
|
||||
dofile("/cavebot/lure.lua")
|
||||
dofile("/cavebot/bank.lua")
|
||||
dofile("/cavebot/clear_tile.lua")
|
||||
dofile("/cavebot/tasker.lua")
|
||||
dofile("/cavebot/imbuing.lua")
|
||||
dofile("/cavebot/stand_lure.lua")
|
||||
-- main cavebot file, must be last
|
||||
dofile("/cavebot/cavebot.lua")
|
||||
|
||||
setDefaultTab(targetingTab)
|
||||
if storage.extras.joinBot then UI.Label("-- [[ TargetBot ]] --") end
|
||||
TargetBot = {} -- global namespace
|
||||
importStyle("/targetbot/looting.otui")
|
||||
importStyle("/targetbot/target.otui")
|
||||
importStyle("/targetbot/creature_editor.otui")
|
||||
dofile("/targetbot/creature.lua")
|
||||
dofile("/targetbot/creature_attack.lua")
|
||||
dofile("/targetbot/creature_editor.lua")
|
||||
dofile("/targetbot/creature_priority.lua")
|
||||
dofile("/targetbot/looting.lua")
|
||||
dofile("/targetbot/walking.lua")
|
||||
-- main targetbot file, must be last
|
||||
dofile("/targetbot/target.lua")
|
||||
@@ -0,0 +1,63 @@
|
||||
setDefaultTab("Cave")
|
||||
|
||||
g_ui.loadUIFromString([[
|
||||
CaveBotControlPanel < Panel
|
||||
margin-top: 5
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
HorizontalSeparator
|
||||
|
||||
Label
|
||||
text-align: center
|
||||
text: CaveBot Control Panel
|
||||
font: verdana-11px-rounded
|
||||
margin-top: 3
|
||||
|
||||
HorizontalSeparator
|
||||
|
||||
Panel
|
||||
id: buttons
|
||||
margin-top: 2
|
||||
layout:
|
||||
type: grid
|
||||
cell-size: 86 20
|
||||
cell-spacing: 1
|
||||
flow: true
|
||||
fit-children: true
|
||||
|
||||
HorizontalSeparator
|
||||
margin-top: 3
|
||||
]])
|
||||
|
||||
local panel = UI.createWidget("CaveBotControlPanel")
|
||||
|
||||
storage.caveBot = {
|
||||
forceRefill = false,
|
||||
backStop = false,
|
||||
backTrainers = false,
|
||||
backOffline = false
|
||||
}
|
||||
|
||||
-- [[ B U T T O N S ]] --
|
||||
|
||||
local forceRefill = UI.Button("Force Refill", function(widget)
|
||||
storage.caveBot.forceRefill = true
|
||||
print("[CaveBot] Going back on refill on next supply check.")
|
||||
end, panel.buttons)
|
||||
|
||||
local backStop = UI.Button("Back & Stop", function(widget)
|
||||
storage.caveBot.backStop = true
|
||||
print("[CaveBot] Going back to city on next supply check and turning off CaveBot on depositer action.")
|
||||
end, panel.buttons)
|
||||
|
||||
local backTrainers = UI.Button("To Trainers", function(widget)
|
||||
storage.caveBot.backTrainers = true
|
||||
print("[CaveBot] Going back to city on next supply check and going to label 'toTrainers' on depositer action.")
|
||||
end, panel.buttons)
|
||||
|
||||
local backOffline = UI.Button("Offline", function(widget)
|
||||
storage.caveBot.backOffline = true
|
||||
print("[CaveBot] Going back to city on next supply check and going to label 'toOfflineTraining' on depositer action.")
|
||||
end, panel.buttons)
|
||||
443
modules/game_bot/default_configs/vBot_4.7/vBot/combo.lua
Normal file
443
modules/game_bot/default_configs/vBot_4.7/vBot/combo.lua
Normal file
@@ -0,0 +1,443 @@
|
||||
setDefaultTab("Main")
|
||||
local panelName = "combobot"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 19
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('ComboBot')
|
||||
|
||||
Button
|
||||
id: combos
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Setup
|
||||
|
||||
]])
|
||||
ui:setId(panelName)
|
||||
|
||||
if not storage[panelName] then
|
||||
storage[panelName] = {
|
||||
enabled = false,
|
||||
onSayEnabled = false,
|
||||
onShootEnabled = false,
|
||||
onCastEnabled = false,
|
||||
followLeaderEnabled = false,
|
||||
attackLeaderTargetEnabled = false,
|
||||
attackSpellEnabled = false,
|
||||
attackItemToggle = false,
|
||||
sayLeader = "",
|
||||
shootLeader = "",
|
||||
castLeader = "",
|
||||
sayPhrase = "",
|
||||
spell = "",
|
||||
serverLeader = "",
|
||||
item = 3155,
|
||||
attack = "",
|
||||
follow = "",
|
||||
commandsEnabled = true,
|
||||
serverEnabled = false,
|
||||
serverLeaderTarget = false,
|
||||
serverTriggers = true
|
||||
}
|
||||
end
|
||||
|
||||
local config = storage[panelName]
|
||||
|
||||
ui.title:setOn(config.enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
config.enabled = not config.enabled
|
||||
widget:setOn(config.enabled)
|
||||
end
|
||||
|
||||
ui.combos.onClick = function(widget)
|
||||
comboWindow:show()
|
||||
comboWindow:raise()
|
||||
comboWindow:focus()
|
||||
end
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
comboWindow = UI.createWindow('ComboWindow', rootWidget)
|
||||
comboWindow:hide()
|
||||
|
||||
-- bot item
|
||||
|
||||
comboWindow.actions.attackItem:setItemId(config.item)
|
||||
comboWindow.actions.attackItem.onItemChange = function(widget)
|
||||
config.item = widget:getItemId()
|
||||
end
|
||||
|
||||
-- switches
|
||||
|
||||
comboWindow.actions.commandsToggle:setOn(config.commandsEnabled)
|
||||
comboWindow.actions.commandsToggle.onClick = function(widget)
|
||||
config.commandsEnabled = not config.commandsEnabled
|
||||
widget:setOn(config.commandsEnabled)
|
||||
end
|
||||
|
||||
comboWindow.server.botServerToggle:setOn(config.serverEnabled)
|
||||
comboWindow.server.botServerToggle.onClick = function(widget)
|
||||
config.serverEnabled = not config.serverEnabled
|
||||
widget:setOn(config.serverEnabled)
|
||||
end
|
||||
|
||||
comboWindow.server.Triggers:setOn(config.serverTriggers)
|
||||
comboWindow.server.Triggers.onClick = function(widget)
|
||||
config.serverTriggers = not config.serverTriggers
|
||||
widget:setOn(config.serverTriggers)
|
||||
end
|
||||
|
||||
comboWindow.server.targetServerLeaderToggle:setOn(config.serverLeaderTarget)
|
||||
comboWindow.server.targetServerLeaderToggle.onClick = function(widget)
|
||||
config.serverLeaderTarget = not config.serverLeaderTarget
|
||||
widget:setOn(config.serverLeaderTarget)
|
||||
end
|
||||
|
||||
-- buttons
|
||||
comboWindow.closeButton.onClick = function(widget)
|
||||
comboWindow:hide()
|
||||
end
|
||||
|
||||
-- combo boxes
|
||||
|
||||
comboWindow.actions.followLeader:setOption(config.follow)
|
||||
comboWindow.actions.followLeader.onOptionChange = function(widget)
|
||||
config.follow = widget:getCurrentOption().text
|
||||
end
|
||||
|
||||
comboWindow.actions.attackLeaderTarget:setOption(config.attack)
|
||||
comboWindow.actions.attackLeaderTarget.onOptionChange = function(widget)
|
||||
config.attack = widget:getCurrentOption().text
|
||||
end
|
||||
|
||||
-- checkboxes
|
||||
comboWindow.trigger.onSayToggle:setChecked(config.onSayEnabled)
|
||||
comboWindow.trigger.onSayToggle.onClick = function(widget)
|
||||
config.onSayEnabled = not config.onSayEnabled
|
||||
widget:setChecked(config.onSayEnabled)
|
||||
end
|
||||
|
||||
comboWindow.trigger.onShootToggle:setChecked(config.onShootEnabled)
|
||||
comboWindow.trigger.onShootToggle.onClick = function(widget)
|
||||
config.onShootEnabled = not config.onShootEnabled
|
||||
widget:setChecked(config.onShootEnabled)
|
||||
end
|
||||
|
||||
comboWindow.trigger.onCastToggle:setChecked(config.onCastEnabled)
|
||||
comboWindow.trigger.onCastToggle.onClick = function(widget)
|
||||
config.onCastEnabled = not config.onCastEnabled
|
||||
widget:setChecked(config.onCastEnabled)
|
||||
end
|
||||
|
||||
comboWindow.actions.followLeaderToggle:setChecked(config.followLeaderEnabled)
|
||||
comboWindow.actions.followLeaderToggle.onClick = function(widget)
|
||||
config.followLeaderEnabled = not config.followLeaderEnabled
|
||||
widget:setChecked(config.followLeaderEnabled)
|
||||
end
|
||||
|
||||
comboWindow.actions.attackLeaderTargetToggle:setChecked(config.attackLeaderTargetEnabled)
|
||||
comboWindow.actions.attackLeaderTargetToggle.onClick = function(widget)
|
||||
config.attackLeaderTargetEnabled = not config.attackLeaderTargetEnabled
|
||||
widget:setChecked(config.attackLeaderTargetEnabled)
|
||||
end
|
||||
|
||||
comboWindow.actions.attackSpellToggle:setChecked(config.attackSpellEnabled)
|
||||
comboWindow.actions.attackSpellToggle.onClick = function(widget)
|
||||
config.attackSpellEnabled = not config.attackSpellEnabled
|
||||
widget:setChecked(config.attackSpellEnabled)
|
||||
end
|
||||
|
||||
comboWindow.actions.attackItemToggle:setChecked(config.attackItemEnabled)
|
||||
comboWindow.actions.attackItemToggle.onClick = function(widget)
|
||||
config.attackItemEnabled = not config.attackItemEnabled
|
||||
widget:setChecked(config.attackItemEnabled)
|
||||
end
|
||||
|
||||
-- text edits
|
||||
comboWindow.trigger.onSayLeader:setText(config.sayLeader)
|
||||
comboWindow.trigger.onSayLeader.onTextChange = function(widget, text)
|
||||
config.sayLeader = text
|
||||
end
|
||||
|
||||
comboWindow.trigger.onShootLeader:setText(config.shootLeader)
|
||||
comboWindow.trigger.onShootLeader.onTextChange = function(widget, text)
|
||||
config.shootLeader = text
|
||||
end
|
||||
|
||||
comboWindow.trigger.onCastLeader:setText(config.castLeader)
|
||||
comboWindow.trigger.onCastLeader.onTextChange = function(widget, text)
|
||||
config.castLeader = text
|
||||
end
|
||||
|
||||
comboWindow.trigger.onSayPhrase:setText(config.sayPhrase)
|
||||
comboWindow.trigger.onSayPhrase.onTextChange = function(widget, text)
|
||||
config.sayPhrase = text
|
||||
end
|
||||
|
||||
comboWindow.actions.attackSpell:setText(config.spell)
|
||||
comboWindow.actions.attackSpell.onTextChange = function(widget, text)
|
||||
config.spell = text
|
||||
end
|
||||
|
||||
comboWindow.server.botServerLeader:setText(config.serverLeader)
|
||||
comboWindow.server.botServerLeader.onTextChange = function(widget, text)
|
||||
config.serverLeader = text
|
||||
end
|
||||
end
|
||||
|
||||
-- bot server
|
||||
-- [[ join party made by Frosty ]] --
|
||||
|
||||
local shouldCloseWindow = false
|
||||
local firstInvitee = true
|
||||
local isInComboTeam = false
|
||||
macro(10, function()
|
||||
if shouldCloseWindow and config.serverEnabled and config.enabled then
|
||||
local channelsWindow = modules.game_console.channelsWindow
|
||||
if channelsWindow then
|
||||
local child = channelsWindow:getChildById("buttonCancel")
|
||||
if child then
|
||||
child:onClick()
|
||||
shouldCloseWindow = false
|
||||
isInComboTeam = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
comboWindow.server.partyButton.onClick = function(widget)
|
||||
if config.serverEnabled and config.enabled then
|
||||
if config.serverLeader:len() > 0 and storage.BotServerChannel:len() > 0 then
|
||||
talkPrivate(config.serverLeader, "request invite " .. storage.BotServerChannel)
|
||||
else
|
||||
error("Request failed. Lack of data.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
onTextMessage(function(mode, text)
|
||||
if config.serverEnabled and config.enabled then
|
||||
if mode == 20 then
|
||||
if string.find(text, "invited you to") then
|
||||
local regex = "[a-zA-Z]*"
|
||||
local regexData = regexMatch(text, regex)
|
||||
if regexData[1][1]:lower() == config.serverLeader:lower() then
|
||||
local leader = getCreatureByName(regexData[1][1])
|
||||
if leader then
|
||||
g_game.partyJoin(leader:getId())
|
||||
g_game.requestChannels()
|
||||
g_game.joinChannel(1)
|
||||
shouldCloseWindow = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
onTalk(function(name, level, mode, text, channelId, pos)
|
||||
if config.serverEnabled and config.enabled then
|
||||
if mode == 4 then
|
||||
if string.find(text, "request invite") then
|
||||
local access = string.match(text, "%d.*")
|
||||
if access and access == storage.BotServerChannel then
|
||||
local minion = getCreatureByName(name)
|
||||
if minion then
|
||||
g_game.partyInvite(minion:getId())
|
||||
if firstInvitee then
|
||||
g_game.requestChannels()
|
||||
g_game.joinChannel(1)
|
||||
shouldCloseWindow = true
|
||||
firstInvitee = false
|
||||
end
|
||||
end
|
||||
else
|
||||
talkPrivate(name, "Incorrect access key!")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- [[ End of Frosty's Code ]] --
|
||||
if config.enabled and config.enabled then
|
||||
if name:lower() == config.sayLeader:lower() and string.find(text, config.sayPhrase) and config.onSayEnabled then
|
||||
startCombo = true
|
||||
end
|
||||
if (config.castLeader and name:lower() == config.castLeader:lower()) and isAttSpell(text) and config.onCastEnabled then
|
||||
startCombo = true
|
||||
end
|
||||
end
|
||||
if config.enabled and config.commandsEnabled and (config.shootLeader and name:lower() == config.shootLeader:lower()) or (config.sayLeader and name:lower() == config.sayLeader:lower()) or (config.castLeader and name:lower() == config.castLeader:lower()) then
|
||||
if string.find(text, "ue") then
|
||||
say(config.spell)
|
||||
elseif string.find(text, "sd") then
|
||||
local params = string.split(text, ",")
|
||||
if #params == 2 then
|
||||
local target = params[2]:trim()
|
||||
if getCreatureByName(target) then
|
||||
useWith(3155, getCreatureByName(target))
|
||||
end
|
||||
end
|
||||
elseif string.find(text, "att") then
|
||||
local attParams = string.split(text, ",")
|
||||
if #attParams == 2 then
|
||||
local atTarget = attParams[2]:trim()
|
||||
if getCreatureByName(atTarget) and config.attack == "COMMAND TARGET" then
|
||||
g_game.attack(getCreatureByName(atTarget))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if isAttSpell(text) and config.enabled and config.serverEnabled then
|
||||
BotServer.send("trigger", "start")
|
||||
end
|
||||
end)
|
||||
|
||||
onMissle(function(missle)
|
||||
if config.enabled and config.onShootEnabled then
|
||||
if not config.shootLeader or config.shootLeader:len() == 0 then
|
||||
return
|
||||
end
|
||||
local src = missle:getSource()
|
||||
if src.z ~= posz() then
|
||||
return
|
||||
end
|
||||
local from = g_map.getTile(src)
|
||||
local to = g_map.getTile(missle:getDestination())
|
||||
if not from or not to then
|
||||
return
|
||||
end
|
||||
local fromCreatures = from:getCreatures()
|
||||
local toCreatures = to:getCreatures()
|
||||
if #fromCreatures ~= 1 or #toCreatures ~= 1 then
|
||||
return
|
||||
end
|
||||
local c1 = fromCreatures[1]
|
||||
local t1 = toCreatures[1]
|
||||
leaderTarget = t1
|
||||
if c1:getName():lower() == config.shootLeader:lower() then
|
||||
if config.attackItemEnabled and config.item and config.item > 100 and findItem(config.item) then
|
||||
useWith(config.item, t1)
|
||||
end
|
||||
if config.attackSpellEnabled and config.spell:len() > 1 then
|
||||
say(config.spell)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
macro(10, function()
|
||||
if not config.enabled or not config.attackLeaderTargetEnabled then return end
|
||||
if leaderTarget and config.attack == "LEADER TARGET" then
|
||||
if not getTarget() or (getTarget() and getTarget():getName() ~= leaderTarget:getName()) then
|
||||
g_game.attack(leaderTarget)
|
||||
end
|
||||
end
|
||||
if config.enabled and config.serverEnabled and config.attack == "SERVER LEADER TARGET" and serverTarget then
|
||||
if serverTarget and not getTarget() or (getTarget() and getTarget():getname() ~= serverTarget)
|
||||
then
|
||||
g_game.attack(serverTarget)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
local toFollow
|
||||
local toFollowPos = {}
|
||||
|
||||
macro(100, function()
|
||||
toFollow = nil
|
||||
if not config.enabled or not config.followLeaderEnabled then return end
|
||||
if leaderTarget and config.follow == "LEADER TARGET" and leaderTarget:isPlayer() then
|
||||
toFollow = leaderTarget:getName()
|
||||
elseif config.follow == "SERVER LEADER TARGET" and config.serverLeader:len() ~= 0 then
|
||||
toFollow = serverTarget
|
||||
elseif config.follow == "SERVER LEADER" and config.serverLeader:len() ~= 0 then
|
||||
toFollow = config.serverLeader
|
||||
elseif config.follow == "LEADER" then
|
||||
if config.onSayEnabled and config.sayLeader:len() ~= 0 then
|
||||
toFollow = config.sayLeader
|
||||
elseif config.onCastEnabled and config.castLeader:len() ~= 0 then
|
||||
toFollow = config.castLeader
|
||||
elseif config.onShootEnabled and config.shootLeader:len() ~= 0 then
|
||||
toFollow = config.shootLeader
|
||||
end
|
||||
end
|
||||
if not toFollow then return end
|
||||
local target = getCreatureByName(toFollow)
|
||||
if target then
|
||||
local tpos = target:getPosition()
|
||||
toFollowPos[tpos.z] = tpos
|
||||
end
|
||||
if player:isWalking() then return end
|
||||
local p = toFollowPos[posz()]
|
||||
if not p then return end
|
||||
if CaveBot.walkTo(p, 20, {ignoreNonPathable=true, precision=1, ignoreStairs=false}) then
|
||||
delay(100)
|
||||
end
|
||||
end)
|
||||
|
||||
onCreaturePositionChange(function(creature, oldPos, newPos)
|
||||
if creature:getName() == toFollow and newPos then
|
||||
toFollowPos[newPos.z] = newPos
|
||||
end
|
||||
end)
|
||||
|
||||
local timeout = now
|
||||
macro(10, function()
|
||||
if config.enabled and startCombo then
|
||||
if config.attackItemEnabled and config.item and config.item > 100 and findItem(config.item) then
|
||||
useWith(config.item, getTarget())
|
||||
end
|
||||
if config.attackSpellEnabled and config.spell:len() > 1 then
|
||||
say(config.spell)
|
||||
end
|
||||
startCombo = false
|
||||
end
|
||||
-- attack part / server
|
||||
if BotServer._websocket and config.enabled and config.serverEnabled then
|
||||
if target() and now - timeout > 500 then
|
||||
targetPos = target():getName()
|
||||
BotServer.send("target", targetPos)
|
||||
timeout = now
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
onUseWith(function(pos, itemId, target, subType)
|
||||
if BotServer._websocket and itemId == 3155 then
|
||||
BotServer.send("useWith", target:getPosition())
|
||||
end
|
||||
end)
|
||||
|
||||
if BotServer._websocket and config.enabled and config.serverEnabled then
|
||||
BotServer.listen("trigger", function(name, message)
|
||||
if message == "start" and name:lower() ~= player:getName():lower() and name:lower() == config.serverLeader:lower() and config.serverTriggers then
|
||||
startCombo = true
|
||||
end
|
||||
end)
|
||||
BotServer.listen("target", function(name, message)
|
||||
if name:lower() ~= player:getName():lower() and name:lower() == config.serverLeader:lower() then
|
||||
if not target() or target():getName() == getCreatureByName(message) then
|
||||
if config.serverLeaderTarget then
|
||||
serverTarget = getCreatureByName(message)
|
||||
g_game.attack(getCreatureByName(message))
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
BotServer.listen("useWith", function(name, message)
|
||||
local tile = g_map.getTile(message)
|
||||
if config.serverTriggers and name:lower() ~= player:getName():lower() and name:lower() == config.serverLeader:lower() and config.attackItemEnabled and config.item and findItem(config.item) then
|
||||
useWith(config.item, tile:getTopUseThing())
|
||||
end
|
||||
end)
|
||||
end
|
||||
391
modules/game_bot/default_configs/vBot_4.7/vBot/combo.otui
Normal file
391
modules/game_bot/default_configs/vBot_4.7/vBot/combo.otui
Normal file
@@ -0,0 +1,391 @@
|
||||
AttackComboBoxPopupMenu < ComboBoxPopupMenu
|
||||
AttackComboBoxPopupMenuButton < ComboBoxPopupMenuButton
|
||||
AttackComboBox < ComboBox
|
||||
@onSetup: |
|
||||
self:addOption("LEADER TARGET")
|
||||
self:addOption("COMMAND TARGET")
|
||||
|
||||
FollowComboBoxPopupMenu < ComboBoxPopupMenu
|
||||
FollowComboBoxPopupMenuButton < ComboBoxPopupMenuButton
|
||||
FollowComboBox < ComboBox
|
||||
@onSetup: |
|
||||
self:addOption("LEADER TARGET")
|
||||
self:addOption("SERVER LEADER TARGET")
|
||||
self:addOption("LEADER")
|
||||
self:addOption("SERVER LEADER")
|
||||
|
||||
ComboTrigger < Panel
|
||||
id: trigger
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 6
|
||||
padding: 3
|
||||
size: 450 72
|
||||
|
||||
Label
|
||||
id: triggerLabel1
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
text: On Say
|
||||
margin-top: 8
|
||||
margin-left: 5
|
||||
color: #ffaa00
|
||||
|
||||
Label
|
||||
id: leaderLabel
|
||||
anchors.left: triggerLabel1.right
|
||||
anchors.top: triggerLabel1.top
|
||||
text: Leader:
|
||||
margin-left: 35
|
||||
|
||||
TextEdit
|
||||
id: onSayLeader
|
||||
anchors.left: leaderLabel.right
|
||||
anchors.top: leaderLabel.top
|
||||
anchors.bottom: leaderLabel.bottom
|
||||
margin-left: 5
|
||||
width: 120
|
||||
font: cipsoftFont
|
||||
|
||||
Label
|
||||
id: phrase
|
||||
anchors.left: onSayLeader.right
|
||||
anchors.top: onSayLeader.top
|
||||
text: Phrase:
|
||||
margin-left: 5
|
||||
|
||||
TextEdit
|
||||
id: onSayPhrase
|
||||
anchors.left: phrase.right
|
||||
anchors.top: leaderLabel.top
|
||||
anchors.bottom: leaderLabel.bottom
|
||||
margin-left: 5
|
||||
width: 120
|
||||
font: cipsoftFont
|
||||
|
||||
CheckBox
|
||||
id: onSayToggle
|
||||
anchors.left: onSayPhrase.right
|
||||
anchors.top: onSayPhrase.top
|
||||
margin-top: 1
|
||||
margin-left: 5
|
||||
|
||||
Label
|
||||
id: triggerLabel2
|
||||
anchors.left: triggerLabel1.left
|
||||
anchors.top: triggerLabel1.bottom
|
||||
text: On Shoot
|
||||
margin-top: 5
|
||||
color: #ffaa00
|
||||
|
||||
Label
|
||||
id: leaderLabel1
|
||||
anchors.left: triggerLabel2.right
|
||||
anchors.top: triggerLabel2.top
|
||||
text: Leader:
|
||||
margin-left: 24
|
||||
|
||||
TextEdit
|
||||
id: onShootLeader
|
||||
anchors.left: leaderLabel1.right
|
||||
anchors.top: leaderLabel1.top
|
||||
anchors.bottom: leaderLabel1.bottom
|
||||
anchors.right: onSayPhrase.right
|
||||
margin-left: 5
|
||||
width: 120
|
||||
font: cipsoftFont
|
||||
|
||||
CheckBox
|
||||
id: onShootToggle
|
||||
anchors.left: onShootLeader.right
|
||||
anchors.top: onShootLeader.top
|
||||
margin-top: 1
|
||||
margin-left: 5
|
||||
|
||||
Label
|
||||
id: triggerLabel3
|
||||
anchors.left: triggerLabel2.left
|
||||
anchors.top: triggerLabel2.bottom
|
||||
text: On Cast
|
||||
margin-top: 5
|
||||
color: #ffaa00
|
||||
|
||||
Label
|
||||
id: leaderLabel2
|
||||
anchors.left: triggerLabel3.right
|
||||
anchors.top: triggerLabel3.top
|
||||
text: Leader:
|
||||
margin-left: 32
|
||||
|
||||
TextEdit
|
||||
id: onCastLeader
|
||||
anchors.left: leaderLabel2.right
|
||||
anchors.top: leaderLabel2.top
|
||||
anchors.bottom: leaderLabel2.bottom
|
||||
anchors.right: onSayPhrase.right
|
||||
margin-left: 5
|
||||
width: 120
|
||||
font: cipsoftFont
|
||||
|
||||
CheckBox
|
||||
id: onCastToggle
|
||||
anchors.left: onCastLeader.right
|
||||
anchors.top: onCastLeader.top
|
||||
margin-top: 1
|
||||
margin-left: 5
|
||||
|
||||
ComboActions < Panel
|
||||
id: actions
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 6
|
||||
padding: 3
|
||||
size: 220 100
|
||||
|
||||
Label
|
||||
id: label1
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
text: Follow:
|
||||
margin-top: 5
|
||||
margin-left: 3
|
||||
height: 15
|
||||
color: #ffaa00
|
||||
|
||||
FollowComboBox
|
||||
id: followLeader
|
||||
anchors.left: prev.right
|
||||
anchors.top: prev.top
|
||||
margin-left: 7
|
||||
height: 15
|
||||
width: 145
|
||||
font: cipsoftFont
|
||||
|
||||
CheckBox
|
||||
id: followLeaderToggle
|
||||
anchors.left: followLeader.right
|
||||
anchors.top: followLeader.top
|
||||
margin-top: 2
|
||||
margin-left: 5
|
||||
|
||||
Label
|
||||
id: label2
|
||||
anchors.left: label1.left
|
||||
anchors.top: label1.bottom
|
||||
margin-top: 5
|
||||
text: Attack:
|
||||
color: #ffaa00
|
||||
|
||||
AttackComboBox
|
||||
id: attackLeaderTarget
|
||||
anchors.left: prev.right
|
||||
anchors.top: prev.top
|
||||
margin-left: 5
|
||||
height: 15
|
||||
width: 145
|
||||
font: cipsoftFont
|
||||
|
||||
CheckBox
|
||||
id: attackLeaderTargetToggle
|
||||
anchors.left: attackLeaderTarget.right
|
||||
anchors.top: attackLeaderTarget.top
|
||||
margin-top: 2
|
||||
margin-left: 5
|
||||
|
||||
Label
|
||||
id: label3
|
||||
anchors.left: label2.left
|
||||
anchors.top: label2.bottom
|
||||
margin-top: 5
|
||||
text: Spell:
|
||||
color: #ffaa00
|
||||
|
||||
TextEdit
|
||||
id: attackSpell
|
||||
anchors.left: prev.right
|
||||
anchors.top: prev.top
|
||||
anchors.right: attackLeaderTarget.right
|
||||
margin-left: 17
|
||||
height: 15
|
||||
width: 145
|
||||
font: cipsoftFont
|
||||
|
||||
CheckBox
|
||||
id: attackSpellToggle
|
||||
anchors.left: attackSpell.right
|
||||
anchors.top: attackSpell.top
|
||||
margin-top: 2
|
||||
margin-left: 5
|
||||
|
||||
Label
|
||||
id: label4
|
||||
anchors.left: label3.left
|
||||
anchors.top: label3.bottom
|
||||
margin-top: 15
|
||||
text: Attack Item:
|
||||
color: #ffaa00
|
||||
|
||||
BotItem
|
||||
id: attackItem
|
||||
anchors.left: prev.right
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
margin-left: 10
|
||||
|
||||
CheckBox
|
||||
id: attackItemToggle
|
||||
anchors.left: prev.right
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
margin-left: 5
|
||||
|
||||
BotSwitch
|
||||
id: commandsToggle
|
||||
anchors.left: prev.right
|
||||
anchors.top: attackItem.top
|
||||
anchors.right: attackSpellToggle.right
|
||||
anchors.bottom: attackItem.bottom
|
||||
margin-left: 5
|
||||
text: Leader Commands
|
||||
text-wrap: true
|
||||
multiline: true
|
||||
|
||||
BotServer < Panel
|
||||
id: server
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 6
|
||||
padding: 3
|
||||
size: 220 100
|
||||
|
||||
Label
|
||||
id: labelX
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
text: Leader:
|
||||
height: 15
|
||||
color: #ffaa00
|
||||
margin-left: 3
|
||||
margin-top: 5
|
||||
|
||||
TextEdit
|
||||
id: botServerLeader
|
||||
anchors.left: prev.right
|
||||
anchors.top: prev.top
|
||||
anchors.right: parent.right
|
||||
margin-right: 3
|
||||
margin-left: 9
|
||||
height: 15
|
||||
font: cipsoftFont
|
||||
|
||||
Button
|
||||
id: partyButton
|
||||
anchors.left: labelX.left
|
||||
anchors.top: botServerLeader.bottom
|
||||
margin-top: 5
|
||||
height: 30
|
||||
text: Join Party
|
||||
text-wrap: true
|
||||
multiline: true
|
||||
|
||||
BotSwitch
|
||||
id: botServerToggle
|
||||
anchors.left: prev.right
|
||||
anchors.top: botServerLeader.bottom
|
||||
anchors.right: parent.right
|
||||
height: 30
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
margin-top: 5
|
||||
text: Server Enabled
|
||||
|
||||
BotSwitch
|
||||
id: targetServerLeaderToggle
|
||||
anchors.left: partyButton.left
|
||||
anchors.top: partyButton.bottom
|
||||
anchors.right: partyButton.right
|
||||
margin-top: 3
|
||||
height: 30
|
||||
text: Leader Targets
|
||||
|
||||
BotSwitch
|
||||
id: Triggers
|
||||
anchors.left: prev.right
|
||||
anchors.top: partyButton.bottom
|
||||
anchors.right: parent.right
|
||||
margin-top: 3
|
||||
height: 30
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
text: Triggers
|
||||
|
||||
ComboWindow < MainWindow
|
||||
!text: tr('Combo Options')
|
||||
size: 500 280
|
||||
@onEscape: self:hide()
|
||||
|
||||
ComboTrigger
|
||||
id: trigger
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
margin-top: 7
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-left: 10
|
||||
text: Combo Trigger
|
||||
color: #ff7700
|
||||
|
||||
ComboActions
|
||||
id: actions
|
||||
anchors.top: trigger.bottom
|
||||
anchors.left: trigger.left
|
||||
margin-top: 15
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-left: 10
|
||||
margin-top: 85
|
||||
text: Combo Actions
|
||||
color: #ff7700
|
||||
|
||||
BotServer
|
||||
id: server
|
||||
anchors.top: actions.top
|
||||
anchors.left: actions.right
|
||||
margin-left: 10
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: server.left
|
||||
margin-left: 3
|
||||
margin-top: 85
|
||||
text: BotServer
|
||||
color: #ff7700
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 8
|
||||
|
||||
Button
|
||||
id: closeButton
|
||||
!text: tr('Close')
|
||||
font: cipsoftFont
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
margin-top: 15
|
||||
margin-right: 5
|
||||
|
||||
Button
|
||||
id: toolsButton
|
||||
!text: tr('Help')
|
||||
font: cipsoftFont
|
||||
anchors.right: closeButton.left
|
||||
anchors.top: closeButton.top
|
||||
margin-right: 10
|
||||
size: 45 21
|
||||
@onClick: g_platform.openUrl("http://bot.otclient.ovh/books/scripts/page/combobot")
|
||||
97
modules/game_bot/default_configs/vBot_4.7/vBot/configs.lua
Normal file
97
modules/game_bot/default_configs/vBot_4.7/vBot/configs.lua
Normal file
@@ -0,0 +1,97 @@
|
||||
--[[
|
||||
Configs for modules
|
||||
Based on Kondrah storage method
|
||||
--]]
|
||||
local configName = modules.game_bot.contentsPanel.config:getCurrentOption().text
|
||||
|
||||
-- make vBot config dir
|
||||
if not g_resources.directoryExists("/bot/".. configName .."/vBot_configs/") then
|
||||
g_resources.makeDir("/bot/".. configName .."/vBot_configs/")
|
||||
end
|
||||
|
||||
-- make profile dirs
|
||||
for i=1,10 do
|
||||
local path = "/bot/".. configName .."/vBot_configs/profile_"..i
|
||||
if not g_resources.directoryExists(path) then
|
||||
g_resources.makeDir(path)
|
||||
end
|
||||
end
|
||||
|
||||
local profile = g_settings.getNumber('profile')
|
||||
|
||||
HealBotConfig = {}
|
||||
local healBotFile = "/bot/" .. configName .. "/vBot_configs/profile_".. profile .. "/HealBot.json"
|
||||
AttackBotConfig = {}
|
||||
local attackBotFile = "/bot/" .. configName .. "/vBot_configs/profile_".. profile .. "/AttackBot.json"
|
||||
SuppliesConfig = {}
|
||||
local suppliesFile = "/bot/" .. configName .. "/vBot_configs/profile_".. profile .. "/Supplies.json"
|
||||
|
||||
|
||||
--healbot
|
||||
if g_resources.fileExists(healBotFile) then
|
||||
local status, result = pcall(function()
|
||||
return json.decode(g_resources.readFileContents(healBotFile))
|
||||
end)
|
||||
if not status then
|
||||
return onError("Error while reading config file (" .. healBotFile .. "). To fix this problem you can delete HealBot.json. Details: " .. result)
|
||||
end
|
||||
HealBotConfig = result
|
||||
end
|
||||
|
||||
--attackbot
|
||||
if g_resources.fileExists(attackBotFile) then
|
||||
local status, result = pcall(function()
|
||||
return json.decode(g_resources.readFileContents(attackBotFile))
|
||||
end)
|
||||
if not status then
|
||||
return onError("Error while reading config file (" .. attackBotFile .. "). To fix this problem you can delete HealBot.json. Details: " .. result)
|
||||
end
|
||||
AttackBotConfig = result
|
||||
end
|
||||
|
||||
--supplies
|
||||
if g_resources.fileExists(suppliesFile) then
|
||||
local status, result = pcall(function()
|
||||
return json.decode(g_resources.readFileContents(suppliesFile))
|
||||
end)
|
||||
if not status then
|
||||
return onError("Error while reading config file (" .. suppliesFile .. "). To fix this problem you can delete HealBot.json. Details: " .. result)
|
||||
end
|
||||
SuppliesConfig = result
|
||||
end
|
||||
|
||||
function vBotConfigSave(file)
|
||||
-- file can be either
|
||||
--- heal
|
||||
--- atk
|
||||
--- supply
|
||||
local configFile
|
||||
local configTable
|
||||
if not file then return end
|
||||
file = file:lower()
|
||||
if file == "heal" then
|
||||
configFile = healBotFile
|
||||
configTable = HealBotConfig
|
||||
elseif file == "atk" then
|
||||
configFile = attackBotFile
|
||||
configTable = AttackBotConfig
|
||||
elseif file == "supply" then
|
||||
configFile = suppliesFile
|
||||
configTable = SuppliesConfig
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
local status, result = pcall(function()
|
||||
return json.encode(configTable, 2)
|
||||
end)
|
||||
if not status then
|
||||
return onError("Error while saving config. it won't be saved. Details: " .. result)
|
||||
end
|
||||
|
||||
if result:len() > 100 * 1024 * 1024 then
|
||||
return onError("config file is too big, above 100MB, it won't be saved")
|
||||
end
|
||||
|
||||
g_resources.writeFileContents(configFile, result)
|
||||
end
|
||||
@@ -0,0 +1,123 @@
|
||||
setDefaultTab("Cave")
|
||||
local panelName = "specialDeposit"
|
||||
local depositerPanel
|
||||
|
||||
UI.Button("Stashing Settings", function()
|
||||
depositerPanel:show()
|
||||
depositerPanel:raise()
|
||||
depositerPanel:focus()
|
||||
end)
|
||||
|
||||
if not storage[panelName] then
|
||||
storage[panelName] = {
|
||||
items = {},
|
||||
height = 380
|
||||
}
|
||||
end
|
||||
|
||||
local config = storage[panelName]
|
||||
|
||||
depositerPanel = UI.createWindow('DepositerPanel', rootWidget)
|
||||
depositerPanel:hide()
|
||||
-- basic one
|
||||
depositerPanel.CloseButton.onClick = function()
|
||||
depositerPanel:hide()
|
||||
end
|
||||
|
||||
depositerPanel:setHeight(config.height or 380)
|
||||
depositerPanel.onGeometryChange = function(widget, old, new)
|
||||
if old.height == 0 then return end
|
||||
config.height = new.height
|
||||
end
|
||||
|
||||
function arabicToRoman(n)
|
||||
local t = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XI", "XII", "XIV", "XV", "XVI", "XVII"}
|
||||
return t[n]
|
||||
end
|
||||
|
||||
local function refreshEntries()
|
||||
depositerPanel.DepositerList:destroyChildren()
|
||||
for _, entry in ipairs(config.items) do
|
||||
local panel = g_ui.createWidget("StashItem", depositerPanel.DepositerList)
|
||||
panel.name:setText(Item.create(entry.id):getMarketData().name)
|
||||
for i, child in ipairs(panel:getChildren()) do
|
||||
if child:getId() ~= "slot" then
|
||||
child:setTooltip("Clear item or double click to remove entry.")
|
||||
child.onDoubleClick = function(widget)
|
||||
table.remove(config.items, table.find(entry))
|
||||
panel:destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
panel.item:setItemId(entry.id)
|
||||
if entry.id > 0 then
|
||||
panel.item:setImageSource('')
|
||||
end
|
||||
panel.item.onItemChange = function(widget)
|
||||
local id = widget:getItemId()
|
||||
if id < 100 then
|
||||
table.remove(config.items, table.find(entry))
|
||||
panel:destroy()
|
||||
else
|
||||
for i, data in ipairs(config.items) do
|
||||
if data.id == id then
|
||||
warn("[Depositer Panel] Item already added!")
|
||||
return
|
||||
end
|
||||
end
|
||||
entry.id = id
|
||||
panel.item:setImageSource('')
|
||||
panel.name:setText(Item.create(entry.id):getMarketData().name)
|
||||
if entry.index == 0 then
|
||||
local window = modules.client_textedit.show(panel.slot, {
|
||||
title = "Set depot for "..panel.name:getText(),
|
||||
description = "Select depot to which item should be stashed, choose between 3 and 17",
|
||||
validation = [[^([3-9]|1[0-7])$]]
|
||||
})
|
||||
window.text:setText(entry.index)
|
||||
schedule(50, function()
|
||||
window:raise()
|
||||
window:focus()
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
if entry.id > 0 then
|
||||
panel.slot:setText("Stash to depot: ".. entry.index)
|
||||
end
|
||||
panel.slot:setTooltip("Click to set stashing destination.")
|
||||
panel.slot.onClick = function(widget)
|
||||
local window = modules.client_textedit.show(widget, {
|
||||
title = "Set depot for "..panel.name:getText(),
|
||||
description = "Select depot to which item should be stashed, choose between 3 and 17",
|
||||
validation = [[^([3-9]|1[0-7])$]]
|
||||
})
|
||||
window.text:setText(entry.index)
|
||||
schedule(50, function()
|
||||
window:raise()
|
||||
window:focus()
|
||||
end)
|
||||
end
|
||||
panel.slot.onTextChange = function(widget, text)
|
||||
local n = tonumber(text)
|
||||
if n then
|
||||
entry.index = n
|
||||
widget:setText("Stash to depot: "..entry.index)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
refreshEntries()
|
||||
|
||||
depositerPanel.title.onDoubleClick = function(widget)
|
||||
table.insert(config.items, {id=0, index=0})
|
||||
refreshEntries()
|
||||
end
|
||||
|
||||
function getStashingIndex(id)
|
||||
for _, v in pairs(config.items) do
|
||||
if v.id == id then
|
||||
return v.index - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,99 @@
|
||||
StashItem < Panel
|
||||
height: 40
|
||||
|
||||
BotItem
|
||||
id: item
|
||||
anchors.top: parent.top
|
||||
margin-top: 2
|
||||
anchors.left: parent.left
|
||||
|
||||
UIWidget
|
||||
id: name
|
||||
anchors.top: prev.top
|
||||
margin-top: 1
|
||||
anchors.bottom: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 5
|
||||
text-align:left
|
||||
text: item name
|
||||
font: verdana-11px-rounded
|
||||
color: #FFFFFF
|
||||
|
||||
UIWidget
|
||||
id: slot
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
anchors.bottom: Item.bottom
|
||||
anchors.left: prev.left
|
||||
anchors.right: parent.right
|
||||
font: verdana-11px-rounded
|
||||
text-align:left
|
||||
text: Add item to select locker.
|
||||
color: #CCCCCC
|
||||
|
||||
DepositerPanel < MainWindow
|
||||
size: 230 380
|
||||
!text: tr('Depositer Panel')
|
||||
@onEscape: self:hide()
|
||||
|
||||
UIWidget
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text: Double click here to add item.
|
||||
text-align: left
|
||||
font: verdana-11px-rounded
|
||||
color: #aeaeae
|
||||
|
||||
ScrollablePanel
|
||||
id: DepositerList
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 1
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: sep.top
|
||||
margin-bottom: 10
|
||||
padding: 2
|
||||
padding-left: 4
|
||||
vertical-scrollbar: DepositerScrollBar
|
||||
layout:
|
||||
type: verticalBox
|
||||
|
||||
VerticalScrollBar
|
||||
id: DepositerScrollBar
|
||||
anchors.top: DepositerList.top
|
||||
anchors.bottom: DepositerList.bottom
|
||||
anchors.right: DepositerList.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
visible: false
|
||||
|
||||
ResizeBorder
|
||||
id: bottomResizeBorder
|
||||
anchors.fill: next
|
||||
height: 3
|
||||
minimum: 180
|
||||
maximum: 800
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
background: #ffffff88
|
||||
|
||||
HorizontalSeparator
|
||||
id: sep
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: CloseButton.top
|
||||
margin-bottom: 8
|
||||
|
||||
Button
|
||||
id: CloseButton
|
||||
!text: tr('Close')
|
||||
font: cipsoftFont
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
margin-right: 5
|
||||
@@ -0,0 +1,76 @@
|
||||
-- config
|
||||
setDefaultTab("Tools")
|
||||
local defaultBp = "shopping bag"
|
||||
local id = 21411
|
||||
|
||||
-- script
|
||||
|
||||
local playerContainer = nil
|
||||
local depotContainer = nil
|
||||
local mailContainer = nil
|
||||
|
||||
function reopenLootContainer()
|
||||
for _, container in pairs(getContainers()) do
|
||||
if container:getName():lower() == defaultBp:lower() then
|
||||
g_game.close(container)
|
||||
end
|
||||
end
|
||||
|
||||
local lootItem = findItem(id)
|
||||
if lootItem then
|
||||
schedule(500, function() g_game.open(lootItem) end)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
macro(50, "Depot Withdraw", function()
|
||||
|
||||
-- set the containers
|
||||
if not potionsContainer or not runesContainer or not ammoContainer then
|
||||
for i, container in pairs(getContainers()) do
|
||||
if container:getName() == defaultBp then
|
||||
playerContainer = container
|
||||
elseif string.find(container:getName(), "Depot") then
|
||||
depotContainer = container
|
||||
elseif string.find(container:getName(), "your inbox") then
|
||||
mailContainer = container
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if playerContainer and #playerContainer:getItems() == 20 then
|
||||
for j, item in pairs(playerContainer:getItems()) do
|
||||
if item:getId() == id then
|
||||
g_game.open(item, playerContainer)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if playerContainer and freecap() >= 200 then
|
||||
local time = 500
|
||||
if depotContainer then
|
||||
for i, container in pairs(getContainers()) do
|
||||
if string.find(container:getName(), "Depot") then
|
||||
for j, item in pairs(container:getItems()) do
|
||||
g_game.move(item, playerContainer:getSlotPosition(playerContainer:getItemsCount()), item:getCount())
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if mailContainer then
|
||||
for i, container in pairs(getContainers()) do
|
||||
if string.find(container:getName(), "your inbox") then
|
||||
for j, item in pairs(container:getItems()) do
|
||||
g_game.move(item, playerContainer:getSlotPosition(playerContainer:getItemsCount()), item:getCount())
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
||||
28
modules/game_bot/default_configs/vBot_4.7/vBot/eat_food.lua
Normal file
28
modules/game_bot/default_configs/vBot_4.7/vBot/eat_food.lua
Normal file
@@ -0,0 +1,28 @@
|
||||
setDefaultTab("HP")
|
||||
|
||||
UI.Label("Eatable items:")
|
||||
if type(storage.foodItems) ~= "table" then
|
||||
storage.foodItems = {3582, 3577}
|
||||
end
|
||||
|
||||
local foodContainer = UI.Container(function(widget, items)
|
||||
storage.foodItems = items
|
||||
end, true)
|
||||
foodContainer:setHeight(35)
|
||||
foodContainer:setItems(storage.foodItems)
|
||||
|
||||
|
||||
macro(500, "Eat Food", function()
|
||||
if player:getRegenerationTime() > 400 or not storage.foodItems[1] then return end
|
||||
-- search for food in containers
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
for __, item in ipairs(container:getItems()) do
|
||||
for i, foodItem in ipairs(storage.foodItems) do
|
||||
if item:getId() == foodItem.id then
|
||||
return g_game.use(item)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
UI.Separator()
|
||||
36
modules/game_bot/default_configs/vBot_4.7/vBot/equip.lua
Normal file
36
modules/game_bot/default_configs/vBot_4.7/vBot/equip.lua
Normal file
@@ -0,0 +1,36 @@
|
||||
-- config
|
||||
setDefaultTab("HP")
|
||||
local scripts = 2 -- if you want more auto equip panels you can change 2 to higher value
|
||||
|
||||
-- script by kondrah, don't edit below unless you know what you are doing
|
||||
UI.Label("Auto equip")
|
||||
if type(storage.autoEquip) ~= "table" then
|
||||
storage.autoEquip = {}
|
||||
end
|
||||
for i=1,scripts do
|
||||
if not storage.autoEquip[i] then
|
||||
storage.autoEquip[i] = {on=false, title="Auto Equip", item1=i == 1 and 3052 or 0, item2=i == 1 and 3089 or 0, slot=i == 1 and 9 or 0}
|
||||
end
|
||||
UI.TwoItemsAndSlotPanel(storage.autoEquip[i], function(widget, newParams)
|
||||
storage.autoEquip[i] = newParams
|
||||
end)
|
||||
end
|
||||
macro(250, function()
|
||||
local containers = g_game.getContainers()
|
||||
for index, autoEquip in ipairs(storage.autoEquip) do
|
||||
if autoEquip.on then
|
||||
local slotItem = getSlot(autoEquip.slot)
|
||||
if not slotItem or (slotItem:getId() ~= autoEquip.item1 and slotItem:getId() ~= autoEquip.item2) then
|
||||
for _, container in pairs(containers) do
|
||||
for __, item in ipairs(container:getItems()) do
|
||||
if item:getId() == autoEquip.item1 or item:getId() == autoEquip.item2 then
|
||||
g_game.move(item, {x=65535, y=autoEquip.slot, z=0}, item:getCount())
|
||||
delay(1000) -- don't call it too often
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
539
modules/game_bot/default_configs/vBot_4.7/vBot/equipper.otui
Normal file
539
modules/game_bot/default_configs/vBot_4.7/vBot/equipper.otui
Normal file
@@ -0,0 +1,539 @@
|
||||
SlotBotItem < BotItem
|
||||
border-width: 0
|
||||
$on:
|
||||
image-source: /images/ui/item
|
||||
$checked:
|
||||
border-width: 1
|
||||
border-color: #FF0000
|
||||
|
||||
BossLabel < UIWidget
|
||||
background-color: alpha
|
||||
text-offset: 3 1
|
||||
focusable: true
|
||||
height: 16
|
||||
font: verdana-11px-rounded
|
||||
text-align: left
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
Button
|
||||
id: remove
|
||||
!text: tr('X')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 14
|
||||
height: 14
|
||||
margin-right: 15
|
||||
text-align: center
|
||||
text-offset: 0 1
|
||||
tooltip: Remove profile from the list.
|
||||
|
||||
ConditionBoxPopupMenu < ComboBoxPopupMenu
|
||||
ConditionBoxPopupMenuButton < ComboBoxPopupMenuButton
|
||||
ConditionBox < ComboBox
|
||||
@onSetup: |
|
||||
self:addOption("-")
|
||||
self:addOption("and")
|
||||
self:addOption("or")
|
||||
|
||||
PreButton < PreviousButton
|
||||
background: #363636
|
||||
height: 15
|
||||
|
||||
NexButton < NextButton
|
||||
background: #363636
|
||||
height: 15
|
||||
|
||||
CondidionLabel < FlatPanel
|
||||
padding: 1
|
||||
height: 15
|
||||
|
||||
Label
|
||||
id: text
|
||||
anchors.fill: parent
|
||||
text-align: center
|
||||
font: verdana-11px-rounded
|
||||
background: #363636
|
||||
|
||||
Rule < UIWidget
|
||||
background-color: alpha
|
||||
text-offset: 18 2
|
||||
focusable: true
|
||||
height: 16
|
||||
text-align: left
|
||||
font: verdana-11px-rounded
|
||||
|
||||
CheckBox
|
||||
id: enabled
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 15
|
||||
height: 15
|
||||
margin-top: 2
|
||||
margin-left: 3
|
||||
tooltip: Entry enabled/disabled
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
Button
|
||||
id: remove
|
||||
text: X
|
||||
anchors.right: parent.right
|
||||
margin-right: 15
|
||||
width: 14
|
||||
height: 14
|
||||
text-align: center
|
||||
tooltip: Remove entry
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Button
|
||||
id: visible
|
||||
text: V
|
||||
anchors.right: prev.left
|
||||
margin-right: 3
|
||||
width: 14
|
||||
height: 14
|
||||
text-align: center
|
||||
tooltip: Items must be visible
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
|
||||
ConditionPanel < Panel
|
||||
height: 58
|
||||
|
||||
NexButton
|
||||
id: nex
|
||||
anchors.top: parent.top
|
||||
margin-top: 5
|
||||
anchors.right: parent.right
|
||||
|
||||
PreButton
|
||||
id: pre
|
||||
anchors.top: parent.top
|
||||
margin-top: 5
|
||||
anchors.left: parent.left
|
||||
|
||||
CondidionLabel
|
||||
id: description
|
||||
anchors.top: parent.top
|
||||
margin-top: 5
|
||||
anchors.left: prev.right
|
||||
anchors.right: nex.left
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
SpinBox
|
||||
id: spinbox
|
||||
anchors.top: description.bottom
|
||||
margin-top: 10
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: 100
|
||||
text-align: center
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
step: 1
|
||||
focusable: true
|
||||
|
||||
BotTextEdit
|
||||
id: text
|
||||
anchors.top: description.bottom
|
||||
margin-top: 10
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: 200
|
||||
text-align: center
|
||||
|
||||
|
||||
|
||||
ListPanel < FlatPanel
|
||||
size: 270 300
|
||||
padding-left: 10
|
||||
padding-right: 10
|
||||
padding-bottom: 10
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.verticalCenter: parent.top
|
||||
anchors.left: parent.left
|
||||
text: Rules List
|
||||
font: verdana-11px-rounded
|
||||
color: #FABD02
|
||||
|
||||
Label
|
||||
id: mainLabel
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
margin-top: 10
|
||||
margin-left: 2
|
||||
!text: tr('More important methods come first.')
|
||||
text-align: left
|
||||
font: verdana-11px-rounded
|
||||
color: #aeaeae
|
||||
|
||||
TextList
|
||||
id: list
|
||||
anchors.fill: parent
|
||||
margin-top: 25
|
||||
margin-bottom: 18
|
||||
vertical-scrollbar: listScrollBar
|
||||
padding: 2
|
||||
|
||||
VerticalScrollBar
|
||||
id: listScrollBar
|
||||
anchors.top: list.top
|
||||
anchors.bottom: list.bottom
|
||||
anchors.right: list.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
Button
|
||||
id: up
|
||||
anchors.right: parent.right
|
||||
anchors.top: list.bottom
|
||||
size: 60 17
|
||||
text: Move Up
|
||||
text-align: center
|
||||
font: cipsoftFont
|
||||
margin-top: 5
|
||||
tooltip: Increase priority of selected rule.
|
||||
|
||||
Button
|
||||
id: down
|
||||
anchors.right: prev.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
size: 60 17
|
||||
margin-right: 5
|
||||
text: Move Down
|
||||
text-align: center
|
||||
font: cipsoftFont
|
||||
tooltip: Decrease priority of selected rule.
|
||||
|
||||
InputPanel < FlatPanel
|
||||
size: 270 300
|
||||
padding-left: 10
|
||||
padding-right: 10
|
||||
padding-bottom: 10
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.verticalCenter: parent.top
|
||||
anchors.left: parent.left
|
||||
text: Condition Panel
|
||||
font: verdana-11px-rounded
|
||||
color: #FF0000
|
||||
|
||||
Label
|
||||
id: mainLabel
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 10
|
||||
text: Equip selected items when:
|
||||
text-align: center
|
||||
font: verdana-11px-rounded
|
||||
color: #aeaeae
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 4
|
||||
|
||||
ConditionPanel
|
||||
id: condition
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: mainLabel.bottom
|
||||
margin-top: 15
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.verticalCenter: next.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
ConditionBox
|
||||
id: useSecondCondition
|
||||
anchors.top: condition.bottom
|
||||
margin-top: 10
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: 50
|
||||
|
||||
ConditionPanel
|
||||
id: optionalCondition
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 10
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
|
||||
BotButton
|
||||
id: add
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
margin-bottom: 10
|
||||
text: Add Rule
|
||||
|
||||
EQPanel < FlatPanel
|
||||
size: 160 230
|
||||
padding-left: 10
|
||||
padding-right: 10
|
||||
padding-bottom: 10
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.verticalCenter: parent.top
|
||||
anchors.left: parent.left
|
||||
text: Equipment Setup
|
||||
font: verdana-11px-rounded
|
||||
color: #03C04A
|
||||
|
||||
SlotBotItem
|
||||
id: head
|
||||
image-source: /images/game/slots/head
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 15
|
||||
$on:
|
||||
image-source: /images/ui/item
|
||||
|
||||
SlotBotItem
|
||||
id: body
|
||||
image-source: /images/game/slots/body
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
$on:
|
||||
image-source: /images/ui/item
|
||||
|
||||
SlotBotItem
|
||||
id: legs
|
||||
image-source: /images/game/slots/legs
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
$on:
|
||||
image-source: /images/ui/item
|
||||
|
||||
SlotBotItem
|
||||
id: feet
|
||||
image-source: /images/game/slots/feet
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
$on:
|
||||
image-source: /images/ui/item
|
||||
|
||||
SlotBotItem
|
||||
id: neck
|
||||
image-source: /images/game/slots/neck
|
||||
anchors.top: head.top
|
||||
margin-top: 13
|
||||
anchors.right: head.left
|
||||
margin-right: 5
|
||||
$on:
|
||||
image-source: /images/ui/item
|
||||
|
||||
SlotBotItem
|
||||
id: left-hand
|
||||
image-source: /images/game/slots/left-hand
|
||||
anchors.horizontalCenter: prev.horizontalCenter
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
$on:
|
||||
image-source: /images/ui/item
|
||||
|
||||
SlotBotItem
|
||||
id: finger
|
||||
image-source: /images/game/slots/finger
|
||||
anchors.horizontalCenter: prev.horizontalCenter
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
$on:
|
||||
image-source: /images/ui/item
|
||||
|
||||
Item
|
||||
id: back
|
||||
image-source: /images/game/slots/back-blessed
|
||||
anchors.top: head.top
|
||||
margin-top: 13
|
||||
anchors.left: head.right
|
||||
margin-left: 5
|
||||
tooltip: Main back container modifications are unavailable.
|
||||
|
||||
SlotBotItem
|
||||
id: right-hand
|
||||
image-source: /images/game/slots/right-hand
|
||||
anchors.horizontalCenter: prev.horizontalCenter
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
$on:
|
||||
image-source: /images/ui/item
|
||||
|
||||
SlotBotItem
|
||||
id: ammo
|
||||
image-source: /images/game/slots/ammo
|
||||
anchors.horizontalCenter: prev.horizontalCenter
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
|
||||
BotButton
|
||||
id: cloneEq
|
||||
anchors.top: feet.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 15
|
||||
text: Clone Current EQ
|
||||
font: verdana-11px-rounded
|
||||
tooltip: Copy currently equipped and non-equipped items.
|
||||
|
||||
BotButton
|
||||
id: default
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 3
|
||||
text: Reset fields
|
||||
font: verdana-11px-rounded
|
||||
tooltip: Reset all fields to the blank state
|
||||
|
||||
Profile < FlatPanel
|
||||
size: 160 35
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.verticalCenter: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-left: 10
|
||||
text: Profile Name
|
||||
font: verdana-11px-rounded
|
||||
|
||||
BotTextEdit
|
||||
id: profileName
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
margin: 5
|
||||
|
||||
BossList < FlatPanel
|
||||
padding-left: 10
|
||||
padding-right: 10
|
||||
padding-bottom: 10
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.verticalCenter: parent.top
|
||||
anchors.left: parent.left
|
||||
text: Boss List
|
||||
font: verdana-11px-rounded
|
||||
color: #FABD02
|
||||
|
||||
TextList
|
||||
id: list
|
||||
anchors.fill: parent
|
||||
margin-top: 10
|
||||
margin-bottom: 20
|
||||
vertical-scrollbar: listScrollBar
|
||||
padding: 2
|
||||
|
||||
VerticalScrollBar
|
||||
id: listScrollBar
|
||||
anchors.top: list.top
|
||||
anchors.bottom: list.bottom
|
||||
anchors.right: list.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
BotTextEdit
|
||||
id: name
|
||||
anchors.left: list.left
|
||||
anchors.top: list.bottom
|
||||
margin-top: 4
|
||||
anchors.right: next.left
|
||||
|
||||
Button
|
||||
id: add
|
||||
anchors.right: list.right
|
||||
anchors.top: list.bottom
|
||||
margin-top: 3
|
||||
height: 21
|
||||
text: Add Boss
|
||||
text-align: center
|
||||
font: verdana-11px-rounded
|
||||
tooltip: Creature with given name will be considered as boss.
|
||||
|
||||
EquipWindow < MainWindow
|
||||
size: 750 350
|
||||
text: Equipment Manager
|
||||
@onEscape: self:hide()
|
||||
|
||||
ListPanel
|
||||
id: listPanel
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: bottomSep.top
|
||||
margin-bottom: 5
|
||||
margin-left: -2
|
||||
visible: false
|
||||
|
||||
BossList
|
||||
id: bossPanel
|
||||
anchors.fill: prev
|
||||
visible: true
|
||||
|
||||
VerticalSeparator
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: bottomSep.top
|
||||
margin-bottom: 5
|
||||
anchors.left: prev.right
|
||||
margin-left: 10
|
||||
|
||||
Profile
|
||||
id: profileName
|
||||
anchors.top: parent.top
|
||||
anchors.left: prev.right
|
||||
margin-left: 10
|
||||
|
||||
EQPanel
|
||||
id: setup
|
||||
anchors.left: prev.left
|
||||
anchors.top: prev.bottom
|
||||
anchors.bottom: bottomSep.top
|
||||
margin-bottom: 5
|
||||
margin-top: 10
|
||||
|
||||
InputPanel
|
||||
id: inputPanel
|
||||
anchors.left: prev.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: bottomSep.top
|
||||
margin-bottom: 5
|
||||
margin-left: 5
|
||||
|
||||
HorizontalSeparator
|
||||
id: bottomSep
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 8
|
||||
|
||||
Button
|
||||
id: closeButton
|
||||
!text: tr('Close')
|
||||
font: cipsoftFont
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
|
||||
Button
|
||||
id: bossList
|
||||
!text: tr('Boss list')
|
||||
font: cipsoftFont
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
size: 65 21
|
||||
27
modules/game_bot/default_configs/vBot_4.7/vBot/exeta.lua
Normal file
27
modules/game_bot/default_configs/vBot_4.7/vBot/exeta.lua
Normal file
@@ -0,0 +1,27 @@
|
||||
local voc = player:getVocation()
|
||||
if voc == 1 or voc == 11 then
|
||||
setDefaultTab("Cave")
|
||||
UI.Separator()
|
||||
local m = macro(100000, "Exeta when low hp", function() end)
|
||||
local lastCast = now
|
||||
onCreatureHealthPercentChange(function(creature, healthPercent)
|
||||
if m.isOff() then return end
|
||||
if healthPercent > 15 then return end
|
||||
if CaveBot.isOff() or TargetBot.isOff() then return end
|
||||
if modules.game_cooldown.isGroupCooldownIconActive(3) then return end
|
||||
if creature:getPosition() and getDistanceBetween(pos(),creature:getPosition()) > 1 then return end
|
||||
if canCast("exeta res") and now - lastCast > 6000 then
|
||||
say("exeta res")
|
||||
lastCast = now
|
||||
end
|
||||
end)
|
||||
|
||||
macro(500, "ExetaIfPlayer", function()
|
||||
if CaveBot.isOff() then return end
|
||||
if getMonsters(1) >= 1 and getPlayers(6) > 0 then
|
||||
say("exeta res")
|
||||
delay(6000)
|
||||
end
|
||||
end)
|
||||
UI.Separator()
|
||||
end
|
||||
643
modules/game_bot/default_configs/vBot_4.7/vBot/extras.lua
Normal file
643
modules/game_bot/default_configs/vBot_4.7/vBot/extras.lua
Normal file
@@ -0,0 +1,643 @@
|
||||
setDefaultTab("Main")
|
||||
|
||||
-- securing storage namespace
|
||||
local panelName = "extras"
|
||||
if not storage[panelName] then
|
||||
storage[panelName] = {}
|
||||
end
|
||||
local settings = storage[panelName]
|
||||
|
||||
-- basic elements
|
||||
extrasWindow = UI.createWindow('ExtrasWindow', rootWidget)
|
||||
extrasWindow:hide()
|
||||
extrasWindow.closeButton.onClick = function(widget)
|
||||
extrasWindow:hide()
|
||||
end
|
||||
|
||||
extrasWindow.onGeometryChange = function(widget, old, new)
|
||||
if old.height == 0 then return end
|
||||
|
||||
settings.height = new.height
|
||||
end
|
||||
|
||||
extrasWindow:setHeight(settings.height or 360)
|
||||
|
||||
-- available options for dest param
|
||||
local rightPanel = extrasWindow.content.right
|
||||
local leftPanel = extrasWindow.content.left
|
||||
|
||||
-- objects made by Kondrah - taken from creature editor, minor changes to adapt
|
||||
local addCheckBox = function(id, title, defaultValue, dest, tooltip)
|
||||
local widget = UI.createWidget('ExtrasCheckBox', dest)
|
||||
widget.onClick = function()
|
||||
widget:setOn(not widget:isOn())
|
||||
settings[id] = widget:isOn()
|
||||
if id == "checkPlayer" then
|
||||
local label = rootWidget.newHealer.targetSettings.vocations.title
|
||||
if not widget:isOn() then
|
||||
label:setColor("#d9321f")
|
||||
label:setTooltip("! WARNING ! \nTurn on check players in extras to use this feature!")
|
||||
else
|
||||
label:setColor("#dfdfdf")
|
||||
label:setTooltip("")
|
||||
end
|
||||
end
|
||||
end
|
||||
widget:setText(title)
|
||||
widget:setTooltip(tooltip)
|
||||
if settings[id] == nil then
|
||||
widget:setOn(defaultValue)
|
||||
else
|
||||
widget:setOn(settings[id])
|
||||
end
|
||||
settings[id] = widget:isOn()
|
||||
end
|
||||
|
||||
local addItem = function(id, title, defaultItem, dest, tooltip)
|
||||
local widget = UI.createWidget('ExtrasItem', dest)
|
||||
widget.text:setText(title)
|
||||
widget.text:setTooltip(tooltip)
|
||||
widget.item:setTooltip(tooltip)
|
||||
widget.item:setItemId(settings[id] or defaultItem)
|
||||
widget.item.onItemChange = function(widget)
|
||||
settings[id] = widget:getItemId()
|
||||
end
|
||||
settings[id] = settings[id] or defaultItem
|
||||
end
|
||||
|
||||
local addTextEdit = function(id, title, defaultValue, dest, tooltip)
|
||||
local widget = UI.createWidget('ExtrasTextEdit', dest)
|
||||
widget.text:setText(title)
|
||||
widget.textEdit:setText(settings[id] or defaultValue or "")
|
||||
widget.text:setTooltip(tooltip)
|
||||
widget.textEdit.onTextChange = function(widget,text)
|
||||
settings[id] = text
|
||||
end
|
||||
settings[id] = settings[id] or defaultValue or ""
|
||||
end
|
||||
|
||||
local addScrollBar = function(id, title, min, max, defaultValue, dest, tooltip)
|
||||
local widget = UI.createWidget('ExtrasScrollBar', dest)
|
||||
widget.text:setTooltip(tooltip)
|
||||
widget.scroll.onValueChange = function(scroll, value)
|
||||
widget.text:setText(title .. ": " .. value)
|
||||
if value == 0 then
|
||||
value = 1
|
||||
end
|
||||
settings[id] = value
|
||||
end
|
||||
widget.scroll:setRange(min, max)
|
||||
widget.scroll:setTooltip(tooltip)
|
||||
if max-min > 1000 then
|
||||
widget.scroll:setStep(100)
|
||||
elseif max-min > 100 then
|
||||
widget.scroll:setStep(10)
|
||||
end
|
||||
widget.scroll:setValue(settings[id] or defaultValue)
|
||||
widget.scroll.onValueChange(widget.scroll, widget.scroll:getValue())
|
||||
end
|
||||
|
||||
UI.Button("vBot Settings and Scripts", function()
|
||||
extrasWindow:show()
|
||||
extrasWindow:raise()
|
||||
extrasWindow:focus()
|
||||
end)
|
||||
UI.Separator()
|
||||
|
||||
---- to maintain order, add options right after another:
|
||||
--- add object
|
||||
--- add variables for function (optional)
|
||||
--- add callback (optional)
|
||||
--- optionals should be addionaly sandboxed (if true then end)
|
||||
|
||||
addItem("rope", "Rope Item", 9596, leftPanel, "This item will be used in various bot related scripts as default rope item.")
|
||||
addItem("shovel", "Shovel Item", 9596, leftPanel, "This item will be used in various bot related scripts as default shovel item.")
|
||||
addItem("machete", "Machete Item", 9596, leftPanel, "This item will be used in various bot related scripts as default machete item.")
|
||||
addItem("scythe", "Scythe Item", 9596, leftPanel, "This item will be used in various bot related scripts as default scythe item.")
|
||||
addCheckBox("pathfinding", "CaveBot Pathfinding", true, leftPanel, "Cavebot will automatically search for first reachable waypoint after missing 10 goto's.")
|
||||
addScrollBar("talkDelay", "Global NPC Talk Delay", 0, 2000, 1000, leftPanel, "Breaks between each talk action in cavebot (time in miliseconds).")
|
||||
addScrollBar("looting", "Max Loot Distance", 0, 50, 40, leftPanel, "Every loot corpse futher than set distance (in sqm) will be ignored and forgotten.")
|
||||
addScrollBar("huntRoutes", "Hunting Rounds Limit", 0, 300, 50, leftPanel, "Round limit for supply check, if character already made more rounds than set, on next supply check will return to city.")
|
||||
addScrollBar("killUnder", "Kill monsters below", 0, 100, 1, leftPanel, "Force TargetBot to kill added creatures when they are below set percentage of health - will ignore all other TargetBot settings.")
|
||||
addScrollBar("gotoMaxDistance", "Max GoTo Distance", 0, 127, 30, leftPanel, "Maximum distance to next goto waypoint for the bot to try to reach.")
|
||||
addCheckBox("lootLast", "Start loot from last corpse", true, leftPanel, "Looting sequence will be reverted and bot will start looting newest bodies.")
|
||||
addCheckBox("joinBot", "Join TargetBot and CaveBot", false, leftPanel, "Cave and Target tabs will be joined into one.")
|
||||
addCheckBox("reachable", "Target only pathable mobs", false, leftPanel, "Ignore monsters that can't be reached.")
|
||||
|
||||
addCheckBox("title", "Custom Window Title", true, rightPanel, "Personalize OTCv8 window name according to character specific.")
|
||||
if true then
|
||||
local vocText = ""
|
||||
|
||||
if voc() == 1 or voc() == 11 then
|
||||
vocText = "- EK"
|
||||
elseif voc() == 2 or voc() == 12 then
|
||||
vocText = "- RP"
|
||||
elseif voc() == 3 or voc() == 13 then
|
||||
vocText = "- MS"
|
||||
elseif voc() == 4 or voc() == 14 then
|
||||
vocText = "- ED"
|
||||
end
|
||||
|
||||
macro(5000, function()
|
||||
if settings.title then
|
||||
if hppercent() > 0 then
|
||||
g_window.setTitle("Tibia - " .. name() .. " - " .. lvl() .. "lvl " .. vocText)
|
||||
else
|
||||
g_window.setTitle("Tibia - " .. name() .. " - DEAD")
|
||||
end
|
||||
else
|
||||
g_window.setTitle("Tibia - " .. name())
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
addCheckBox("separatePm", "Open PM's in new Window", false, rightPanel, "PM's will be automatically opened in new tab after receiving one.")
|
||||
if true then
|
||||
onTalk(function(name, level, mode, text, channelId, pos)
|
||||
if mode == 4 and settings.separatePm then
|
||||
local g_console = modules.game_console
|
||||
local privateTab = g_console.getTab(name)
|
||||
if privateTab == nil then
|
||||
privateTab = g_console.addTab(name, true)
|
||||
g_console.addPrivateText(g_console.applyMessagePrefixies(name, level, text), g_console.SpeakTypesSettings['private'], name, false, name)
|
||||
end
|
||||
return
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
addTextEdit("useAll", "Use All Hotkey", "space", rightPanel, "Set hotkey for universal actions - rope, shovel, scythe, use, open doors")
|
||||
if true then
|
||||
local useId = { 34847, 1764, 21051, 30823, 6264, 5282, 20453, 20454, 20474, 11708, 11705,
|
||||
6257, 6256, 2772, 27260, 2773, 1632, 1633, 1948, 435, 6252, 6253, 5007, 4911,
|
||||
1629, 1630, 5108, 5107, 5281, 1968, 435, 1948, 5542, 31116, 31120, 30742, 31115,
|
||||
31118, 20474, 5737, 5736, 5734, 5733, 31202, 31228, 31199, 31200, 33262, 30824,
|
||||
5125, 5126, 5116, 5117, 8257, 8258, 8255, 8256, 5120, 30777, 30776, 23873, 23877,
|
||||
5736, 6264, 31262, 31130, 31129, 6250, 6249, 5122, 30049, 7131, 7132, 7727 }
|
||||
local shovelId = { 606, 593, 867, 608 }
|
||||
local ropeId = { 17238, 12202, 12935, 386, 421, 21966, 14238 }
|
||||
local macheteId = { 2130, 3696 }
|
||||
local scytheId = { 3653 }
|
||||
|
||||
setDefaultTab("Tools")
|
||||
-- script
|
||||
if settings.useAll and settings.useAll:len() > 0 then
|
||||
hotkey(settings.useAll, function()
|
||||
if not modules.game_walking.wsadWalking then return end
|
||||
for _, tile in pairs(g_map.getTiles(posz())) do
|
||||
if distanceFromPlayer(tile:getPosition()) < 2 then
|
||||
for _, item in pairs(tile:getItems()) do
|
||||
-- use
|
||||
if table.find(useId, item:getId()) then
|
||||
use(item)
|
||||
return
|
||||
elseif table.find(shovelId, item:getId()) then
|
||||
useWith(settings.shovel, item)
|
||||
return
|
||||
elseif table.find(ropeId, item:getId()) then
|
||||
useWith(settings.rope, item)
|
||||
return
|
||||
elseif table.find(macheteId, item:getId()) then
|
||||
useWith(settings.machete, item)
|
||||
return
|
||||
elseif table.find(scytheId, item:getId()) then
|
||||
useWith(settings.scythe, item)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
addCheckBox("timers", "MW & WG Timers", true, rightPanel, "Show times for Magic Walls and Wild Growths.")
|
||||
if true then
|
||||
local activeTimers = {}
|
||||
|
||||
onAddThing(function(tile, thing)
|
||||
if not settings.timers then return end
|
||||
if not thing:isItem() then
|
||||
return
|
||||
end
|
||||
local timer = 0
|
||||
if thing:getId() == 2129 then -- mwall id
|
||||
timer = 20000 -- mwall time
|
||||
elseif thing:getId() == 2130 then -- wg id
|
||||
timer = 45000 -- wg time
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
local pos = tile:getPosition().x .. "," .. tile:getPosition().y .. "," .. tile:getPosition().z
|
||||
if not activeTimers[pos] or activeTimers[pos] < now then
|
||||
activeTimers[pos] = now + timer
|
||||
end
|
||||
tile:setTimer(activeTimers[pos] - now)
|
||||
end)
|
||||
|
||||
onRemoveThing(function(tile, thing)
|
||||
if not settings.timers then return end
|
||||
if not thing:isItem() then
|
||||
return
|
||||
end
|
||||
if (thing:getId() == 2129 or thing:getId() == 2130) and tile:getGround() then
|
||||
local pos = tile:getPosition().x .. "," .. tile:getPosition().y .. "," .. tile:getPosition().z
|
||||
activeTimers[pos] = nil
|
||||
tile:setTimer(0)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
addCheckBox("antiKick", "Anti - Kick", true, rightPanel, "Turn every 10 minutes to prevent kick.")
|
||||
if true then
|
||||
macro(600*1000, function()
|
||||
if not settings.antiKick then return end
|
||||
local dir = player:getDirection()
|
||||
turn((dir + 1) % 4)
|
||||
schedule(50, function() turn(dir) end)
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
addCheckBox("stake", "Skin Monsters", false, leftPanel, "Automatically skin & stake corpses when cavebot is enabled")
|
||||
if true then
|
||||
local knifeBodies = {4286, 4272, 4173, 4011, 4025, 4047, 4052, 4057, 4062, 4112, 4212, 4321, 4324, 4327, 10352, 10356, 10360, 10364}
|
||||
local stakeBodies = {4097, 4137, 8738, 18958}
|
||||
local fishingBodies = {9582}
|
||||
macro(500, function()
|
||||
if not CaveBot.isOn() or not settings.stake then return end
|
||||
for i, tile in ipairs(g_map.getTiles(posz())) do
|
||||
local item = tile:getTopThing()
|
||||
if item and item:isContainer() then
|
||||
if table.find(knifeBodies, item:getId()) and findItem(5908) then
|
||||
CaveBot.delay(550)
|
||||
useWith(5908, item)
|
||||
return
|
||||
end
|
||||
if table.find(stakeBodies, item:getId()) and findItem(5942) then
|
||||
CaveBot.delay(550)
|
||||
useWith(5942, item)
|
||||
return
|
||||
end
|
||||
if table.find(fishingBodies, item:getId()) and findItem(3483) then
|
||||
CaveBot.delay(550)
|
||||
useWith(3483, item)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
addCheckBox("oberon", "Auto Reply Oberon", true, rightPanel, "Auto reply to Grand Master Oberon talk minigame.")
|
||||
if true then
|
||||
onTalk(function(name, level, mode, text, channelId, pos)
|
||||
if not settings.oberon then return end
|
||||
if mode == 34 then
|
||||
if string.find(text, "world will suffer for") then
|
||||
say("Are you ever going to fight or do you prefer talking?")
|
||||
elseif string.find(text, "feet when they see me") then
|
||||
say("Even before they smell your breath?")
|
||||
elseif string.find(text, "from this plane") then
|
||||
say("Too bad you barely exist at all!")
|
||||
elseif string.find(text, "ESDO LO") then
|
||||
say("SEHWO ASIMO, TOLIDO ESD")
|
||||
elseif string.find(text, "will soon rule this world") then
|
||||
say("Excuse me but I still do not get the message!")
|
||||
elseif string.find(text, "honourable and formidable") then
|
||||
say("Then why are we fighting alone right now?")
|
||||
elseif string.find(text, "appear like a worm") then
|
||||
say("How appropriate, you look like something worms already got the better of!")
|
||||
elseif string.find(text, "will be the end of mortal") then
|
||||
say("Then let me show you the concept of mortality before it!")
|
||||
elseif string.find(text, "virtues of chivalry") then
|
||||
say("Dare strike up a Minnesang and you will receive your last accolade!")
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
addCheckBox("autoOpenDoors", "Auto Open Doors", true, rightPanel, "Open doors when trying to step on them.")
|
||||
if true then
|
||||
local doorsIds = { 5007, 8265, 1629, 1632, 5129, 6252, 6249, 7715, 7712, 7714,
|
||||
7719, 6256, 1669, 1672, 5125, 5115, 5124, 17701, 17710, 1642,
|
||||
6260, 5107, 4912, 6251, 5291, 1683, 1696, 1692, 5006, 2179, 5116,
|
||||
1632, 11705, 30772, 30774, 6248, 5735, 5732, 5120, 23873, 5736,
|
||||
6264, 5122, 30049, 30042, 7727 }
|
||||
|
||||
function checkForDoors(pos)
|
||||
local tile = g_map.getTile(pos)
|
||||
if tile then
|
||||
local useThing = tile:getTopUseThing()
|
||||
if useThing and table.find(doorsIds, useThing:getId()) then
|
||||
g_game.use(useThing)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
onKeyPress(function(keys)
|
||||
local wsadWalking = modules.game_walking.wsadWalking
|
||||
if not settings.autoOpenDoors then return end
|
||||
local pos = player:getPosition()
|
||||
if keys == 'Up' or (wsadWalking and keys == 'W') then
|
||||
pos.y = pos.y - 1
|
||||
elseif keys == 'Down' or (wsadWalking and keys == 'S') then
|
||||
pos.y = pos.y + 1
|
||||
elseif keys == 'Left' or (wsadWalking and keys == 'A') then
|
||||
pos.x = pos.x - 1
|
||||
elseif keys == 'Right' or (wsadWalking and keys == 'D') then
|
||||
pos.x = pos.x + 1
|
||||
elseif wsadWalking and keys == "Q" then
|
||||
pos.y = pos.y - 1
|
||||
pos.x = pos.x - 1
|
||||
elseif wsadWalking and keys == "E" then
|
||||
pos.y = pos.y - 1
|
||||
pos.x = pos.x + 1
|
||||
elseif wsadWalking and keys == "Z" then
|
||||
pos.y = pos.y + 1
|
||||
pos.x = pos.x - 1
|
||||
elseif wsadWalking and keys == "C" then
|
||||
pos.y = pos.y + 1
|
||||
pos.x = pos.x + 1
|
||||
end
|
||||
checkForDoors(pos)
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
addCheckBox("bless", "Buy bless at login", true, rightPanel, "Say !bless at login.")
|
||||
if true then
|
||||
local blessed = false
|
||||
onTextMessage(function(mode,text)
|
||||
if not settings.bless then return end
|
||||
|
||||
text = text:lower()
|
||||
|
||||
if text == "you already have all blessings." then
|
||||
blessed = true
|
||||
end
|
||||
end)
|
||||
if settings.bless then
|
||||
if player:getBlessings() == 0 then
|
||||
say("!bless")
|
||||
schedule(2000, function()
|
||||
if g_game.getClientVersion() > 1000 then
|
||||
if not blessed and player:getBlessings() == 0 then
|
||||
warn("!! Blessings not bought !!")
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
addCheckBox("reUse", "Keep Crosshair", false, rightPanel, "Keep crosshair after using with item")
|
||||
if true then
|
||||
local excluded = {268, 237, 238, 23373, 266, 236, 239, 7643, 23375, 7642, 23374, 5908, 5942}
|
||||
|
||||
onUseWith(function(pos, itemId, target, subType)
|
||||
if settings.reUse and not table.find(excluded, itemId) then
|
||||
schedule(50, function()
|
||||
item = findItem(itemId)
|
||||
if item then
|
||||
modules.game_interface.startUseWith(item)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
addCheckBox("suppliesControl", "TargetBot off if low supply", false, leftPanel, "Turn off TargetBot if either one of supply amount is below 50% of minimum.")
|
||||
if true then
|
||||
macro(500, function()
|
||||
if not settings.suppliesControl then return end
|
||||
if TargetBot.isOff() then return end
|
||||
if CaveBot.isOff() then return end
|
||||
if type(hasSupplies()) == 'table' then
|
||||
TargetBot.setOff()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
addCheckBox("holdMwall", "Hold MW/WG", true, rightPanel, "Mark tiles with below hotkeys to automatically use Magic Wall or Wild Growth")
|
||||
addTextEdit("holdMwHot", "Magic Wall Hotkey: ", "F5", rightPanel)
|
||||
addTextEdit("holdWgHot", "Wild Growth Hotkey: ", "F6", rightPanel)
|
||||
if true then
|
||||
|
||||
local hold = 0
|
||||
local mwHot
|
||||
local wgHot
|
||||
|
||||
local candidates = {}
|
||||
local m = macro(20, function()
|
||||
mwHot = settings.holdMwHot
|
||||
wgHot = settings.holdWgHot
|
||||
|
||||
if not settings.holdMwall then return end
|
||||
if #candidates == 0 then return end
|
||||
|
||||
for i, pos in pairs(candidates) do
|
||||
local tile = g_map.getTile(pos)
|
||||
if tile then
|
||||
if tile:getText():len() == 0 then
|
||||
table.remove(candidates, i)
|
||||
end
|
||||
local rune = tile:getText() == "HOLD MW" and 3180 or tile:getText() == "HOLD WG" and 3156
|
||||
if tile:canShoot() and not isInPz() and tile:isWalkable() and tile:getTopUseThing():getId() ~= 2130 then
|
||||
if math.abs(player:getPosition().x-tile:getPosition().x) < 8 and math.abs(player:getPosition().y-tile:getPosition().y) < 6 then
|
||||
return useWith(rune, tile:getTopUseThing())
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
onRemoveThing(function(tile, thing)
|
||||
if not settings.holdMwall then return end
|
||||
if thing:getId() ~= 2129 then return end
|
||||
if tile:getText():find("HOLD") then
|
||||
table.insert(candidates, tile:getPosition())
|
||||
local rune = tile:getText() == "HOLD MW" and 3180 or tile:getText() == "HOLD WG" and 3156
|
||||
if math.abs(player:getPosition().x-tile:getPosition().x) < 8 and math.abs(player:getPosition().y-tile:getPosition().y) < 6 then
|
||||
return useWith(rune, tile:getTopUseThing())
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
onAddThing(function(tile, thing)
|
||||
if not settings.holdMwall then return end
|
||||
if m.isOff() then return end
|
||||
if thing:getId() ~= 2129 then return end
|
||||
if tile:getText():len() > 0 then
|
||||
table.remove(candidates, table.find(candidates,tile))
|
||||
end
|
||||
end)
|
||||
|
||||
onKeyDown(function(keys)
|
||||
local wsadWalking = modules.game_walking.wsadWalking
|
||||
if not wsadWalking then return end
|
||||
if not settings.holdMwall then return end
|
||||
if m.isOff() then return end
|
||||
if keys ~= mwHot and keys ~= wgHot then return end
|
||||
hold = now
|
||||
|
||||
local tile = getTileUnderCursor()
|
||||
if not tile then return end
|
||||
|
||||
if tile:getText():len() > 0 then
|
||||
tile:setText("")
|
||||
else
|
||||
if keys == mwHot then
|
||||
tile:setText("HOLD MW")
|
||||
else
|
||||
tile:setText("HOLD WG")
|
||||
end
|
||||
table.insert(candidates, tile:getPosition())
|
||||
end
|
||||
end)
|
||||
|
||||
onKeyPress(function(keys)
|
||||
local wsadWalking = modules.game_walking.wsadWalking
|
||||
if not wsadWalking then return end
|
||||
if not settings.holdMwall then return end
|
||||
if m.isOff() then return end
|
||||
if keys ~= mwHot and keys ~= wgHot then return end
|
||||
|
||||
if (hold - now) < -1000 then
|
||||
candidates = {}
|
||||
for i, tile in ipairs(g_map.getTiles(posz())) do
|
||||
local text = tile:getText()
|
||||
if text:find("HOLD") then
|
||||
tile:setText("")
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
addCheckBox("checkPlayer", "Check Players", true, rightPanel, "Auto look on players and mark level and vocation on character model")
|
||||
if true then
|
||||
local found
|
||||
local function checkPlayers()
|
||||
for i, spec in ipairs(getSpectators()) do
|
||||
if spec:isPlayer() and spec:getText() == "" and spec:getPosition().z == posz() and spec ~= player then
|
||||
g_game.look(spec)
|
||||
found = now
|
||||
end
|
||||
end
|
||||
end
|
||||
if settings.checkPlayer then
|
||||
schedule(500, function()
|
||||
checkPlayers()
|
||||
end)
|
||||
end
|
||||
|
||||
onPlayerPositionChange(function(x,y)
|
||||
if not settings.checkPlayer then return end
|
||||
if x.z ~= y.z then
|
||||
schedule(20, function() checkPlayers() end)
|
||||
end
|
||||
end)
|
||||
|
||||
onCreatureAppear(function(creature)
|
||||
if not settings.checkPlayer then return end
|
||||
if creature:isPlayer() and creature:getText() == "" and creature:getPosition().z == posz() and creature ~= player then
|
||||
g_game.look(creature)
|
||||
found = now
|
||||
end
|
||||
end)
|
||||
|
||||
local regex = [[You see ([^\(]*) \(Level ([0-9]*)\)((?:.)* of the ([\w ]*),|)]]
|
||||
onTextMessage(function(mode, text)
|
||||
if not settings.checkPlayer then return end
|
||||
|
||||
local re = regexMatch(text, regex)
|
||||
if #re ~= 0 then
|
||||
local name = re[1][2]
|
||||
local level = re[1][3]
|
||||
local guild = re[1][5] or ""
|
||||
|
||||
if guild:len() > 10 then
|
||||
guild = guild:sub(1,10) -- change to proper (last) values
|
||||
guild = guild.."..."
|
||||
end
|
||||
local voc
|
||||
if text:lower():find("sorcerer") then
|
||||
voc = "MS"
|
||||
elseif text:lower():find("druid") then
|
||||
voc = "ED"
|
||||
elseif text:lower():find("knight") then
|
||||
voc = "EK"
|
||||
elseif text:lower():find("paladin") then
|
||||
voc = "RP"
|
||||
end
|
||||
local creature = getCreatureByName(name)
|
||||
if creature then
|
||||
creature:setText("\n"..level..voc.."\n"..guild)
|
||||
end
|
||||
if found and now - found < 500 then
|
||||
modules.game_textmessage.clearMessages()
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
addCheckBox("nextBackpack", "Open Next Loot Container", true, leftPanel, "Auto open next loot container if full - has to have the same ID.")
|
||||
local function openNextLootContainer()
|
||||
if not settings.nextBackpack then return end
|
||||
local containers = getContainers()
|
||||
local lootCotaniersIds = CaveBot.GetLootContainers()
|
||||
|
||||
for i, container in ipairs(containers) do
|
||||
local cId = container:getContainerItem():getId()
|
||||
if containerIsFull(container) then
|
||||
if table.find(lootCotaniersIds, cId) then
|
||||
for _, item in ipairs(container:getItems()) do
|
||||
if item:getId() == cId then
|
||||
return g_game.open(item, container)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if true then
|
||||
onContainerOpen(function(container, previousContainer)
|
||||
schedule(100, function()
|
||||
openNextLootContainer()
|
||||
end)
|
||||
end)
|
||||
|
||||
onAddItem(function(container, slot, item, oldItem)
|
||||
schedule(100, function()
|
||||
openNextLootContainer()
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
addCheckBox("highlightTarget", "Highlight Current Target", true, rightPanel, "Additionaly hightlight current target with red glow")
|
||||
if true then
|
||||
local function forceMarked(creature)
|
||||
if target() == creature then
|
||||
creature:setMarked("red")
|
||||
return schedule(333, function() forceMarked(creature) end)
|
||||
end
|
||||
end
|
||||
|
||||
onAttackingCreatureChange(function(newCreature, oldCreature)
|
||||
if not settings.highlightTarget then return end
|
||||
if oldCreature then
|
||||
oldCreature:setMarked('')
|
||||
end
|
||||
if newCreature then
|
||||
forceMarked(newCreature)
|
||||
end
|
||||
end)
|
||||
end
|
||||
158
modules/game_bot/default_configs/vBot_4.7/vBot/extras.otui
Normal file
158
modules/game_bot/default_configs/vBot_4.7/vBot/extras.otui
Normal file
@@ -0,0 +1,158 @@
|
||||
ExtrasScrollBar < Panel
|
||||
height: 28
|
||||
margin-top: 3
|
||||
|
||||
UIWidget
|
||||
id: text
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
|
||||
HorizontalScrollBar
|
||||
id: scroll
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
minimum: 0
|
||||
maximum: 10
|
||||
step: 1
|
||||
|
||||
ExtrasTextEdit < Panel
|
||||
height: 40
|
||||
margin-top: 7
|
||||
|
||||
UIWidget
|
||||
id: text
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
|
||||
TextEdit
|
||||
id: textEdit
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
minimum: 0
|
||||
maximum: 10
|
||||
step: 1
|
||||
text-align: center
|
||||
|
||||
ExtrasItem < Panel
|
||||
height: 34
|
||||
margin-top: 7
|
||||
margin-left: 25
|
||||
margin-right: 25
|
||||
|
||||
UIWidget
|
||||
id: text
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: next.verticalCenter
|
||||
|
||||
BotItem
|
||||
id: item
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
|
||||
|
||||
ExtrasCheckBox < BotSwitch
|
||||
height: 20
|
||||
margin-top: 7
|
||||
|
||||
ExtrasWindow < MainWindow
|
||||
!text: tr('Extras')
|
||||
size: 440 360
|
||||
padding: 25
|
||||
|
||||
Label
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
text: < CaveBot >
|
||||
|
||||
Label
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
text: < Miscellaneous >
|
||||
|
||||
VerticalScrollBar
|
||||
id: contentScroll
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: separator.top
|
||||
step: 28
|
||||
pixels-scroll: true
|
||||
margin-right: -10
|
||||
margin-top: 5
|
||||
margin-bottom: 5
|
||||
|
||||
ScrollablePanel
|
||||
id: content
|
||||
anchors.top: prev.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: separator.top
|
||||
vertical-scrollbar: contentScroll
|
||||
margin-bottom: 10
|
||||
|
||||
Panel
|
||||
id: left
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
margin-top: 5
|
||||
margin-left: 10
|
||||
margin-right: 10
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
Panel
|
||||
id: right
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
margin-top: 5
|
||||
margin-left: 10
|
||||
margin-right: 10
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
VerticalSeparator
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.horizontalCenter
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 8
|
||||
|
||||
ResizeBorder
|
||||
id: bottomResizeBorder
|
||||
anchors.fill: separator
|
||||
height: 3
|
||||
minimum: 260
|
||||
maximum: 600
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
background: #ffffff88
|
||||
|
||||
Button
|
||||
id: closeButton
|
||||
!text: tr('Close')
|
||||
font: cipsoftFont
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
margin-right: 5
|
||||
@@ -0,0 +1,30 @@
|
||||
setDefaultTab("Tools")
|
||||
|
||||
local targetID = nil
|
||||
|
||||
-- escape when attacking will reset hold target
|
||||
onKeyPress(function(keys)
|
||||
if keys == "Escape" and targetID then
|
||||
targetID = nil
|
||||
end
|
||||
end)
|
||||
|
||||
macro(100, "Hold Target", function()
|
||||
-- if attacking then save it as target, but check pos z in case of marking by mistake on other floor
|
||||
if target() and target():getPosition().z == posz() and not target():isNpc() then
|
||||
targetID = target():getId()
|
||||
elseif not target() then
|
||||
-- there is no saved data, do nothing
|
||||
if not targetID then return end
|
||||
|
||||
-- look for target
|
||||
for i, spec in ipairs(getSpectators()) do
|
||||
local sameFloor = spec:getPosition().z == posz()
|
||||
local oldTarget = spec:getId() == targetID
|
||||
|
||||
if sameFloor and oldTarget then
|
||||
attack(spec)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,23 @@
|
||||
setDefaultTab("Tools")
|
||||
-- allows to test/edit bot lua scripts ingame, you can have multiple scripts like this, just change storage.ingame_lua
|
||||
UI.Button("Ingame script editor", function(newText)
|
||||
UI.MultilineEditorWindow(storage.ingame_hotkeys or "", {title="Hotkeys editor", description="You can add your custom scrupts here"}, function(text)
|
||||
storage.ingame_hotkeys = text
|
||||
reload()
|
||||
end)
|
||||
end)
|
||||
|
||||
UI.Separator()
|
||||
|
||||
for _, scripts in pairs({storage.ingame_hotkeys}) do
|
||||
if type(scripts) == "string" and scripts:len() > 3 then
|
||||
local status, result = pcall(function()
|
||||
assert(load(scripts, "ingame_editor"))()
|
||||
end)
|
||||
if not status then
|
||||
error("Ingame edior error:\n" .. result)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
UI.Separator()
|
||||
1404
modules/game_bot/default_configs/vBot_4.7/vBot/items.lua
Normal file
1404
modules/game_bot/default_configs/vBot_4.7/vBot/items.lua
Normal file
File diff suppressed because it is too large
Load Diff
40
modules/game_bot/default_configs/vBot_4.7/vBot/main.lua
Normal file
40
modules/game_bot/default_configs/vBot_4.7/vBot/main.lua
Normal file
@@ -0,0 +1,40 @@
|
||||
local version = "4.7"
|
||||
local currentVersion
|
||||
local available = false
|
||||
|
||||
storage.checkVersion = storage.checkVersion or 0
|
||||
|
||||
-- check max once per 12hours
|
||||
if os.time() > storage.checkVersion + (12 * 60 * 60) then
|
||||
|
||||
storage.checkVersion = os.time()
|
||||
|
||||
HTTP.get("https://raw.githubusercontent.com/Vithrax/vBot/main/vBot/version.txt", function(data, err)
|
||||
if err then
|
||||
warn("[vBot updater]: Unable to check version:\n" .. err)
|
||||
return
|
||||
end
|
||||
|
||||
currentVersion = data
|
||||
available = true
|
||||
end)
|
||||
|
||||
end
|
||||
|
||||
UI.Label("vBot v".. version .." \n Vithrax#5814")
|
||||
UI.Button("Official OTCv8 Discord!", function() g_platform.openUrl("https://discord.gg/yhqBE4A") end)
|
||||
UI.Separator()
|
||||
|
||||
schedule(5000, function()
|
||||
|
||||
if not available then return end
|
||||
if currentVersion ~= version then
|
||||
|
||||
UI.Separator()
|
||||
UI.Label("New vBot is available for download! v"..currentVersion)
|
||||
UI.Button("Go to vBot GitHub Page", function() g_platform.openUrl("https://github.com/Vithrax/vBot") end)
|
||||
UI.Separator()
|
||||
|
||||
end
|
||||
|
||||
end)
|
||||
@@ -0,0 +1,518 @@
|
||||
CaveBot = {} -- global namespace
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- CaveBot lib 1.0
|
||||
-- Contains a universal set of functions to be used in CaveBot
|
||||
|
||||
----------------------[[ basic assumption ]]-----------------------
|
||||
-- in general, functions cannot be slowed from within, only externally, by event calls, delays etc.
|
||||
-- considering that and the fact that there is no while loop, every function return action
|
||||
-- thus, functions will need to be verified outside themselfs or by another function
|
||||
-- overall tips to creating extension:
|
||||
-- - functions return action(nil) or true(done)
|
||||
-- - extensions are controlled by retries var
|
||||
-------------------------------------------------------------------
|
||||
|
||||
-- local variables, constants and functions, used by global functions
|
||||
local LOCKERS_LIST = {3497, 3498, 3499, 3500}
|
||||
local LOCKER_ACCESSTILE_MODIFIERS = {
|
||||
[3497] = {0,-1},
|
||||
[3498] = {1,0},
|
||||
[3499] = {0,1},
|
||||
[3500] = {-1,0}
|
||||
}
|
||||
|
||||
local function CaveBotConfigParse()
|
||||
local name = storage["_configs"]["targetbot_configs"]["selected"]
|
||||
if not name then
|
||||
return warn("[vBot] Please create a new TargetBot config and reset bot")
|
||||
end
|
||||
local file = configDir .. "/targetbot_configs/" .. name .. ".json"
|
||||
local data = g_resources.readFileContents(file)
|
||||
return Config.parse(data)['looting']
|
||||
end
|
||||
|
||||
local function getNearTiles(pos)
|
||||
if type(pos) ~= "table" then
|
||||
pos = pos:getPosition()
|
||||
end
|
||||
|
||||
local tiles = {}
|
||||
local dirs = {
|
||||
{-1, 1},
|
||||
{0, 1},
|
||||
{1, 1},
|
||||
{-1, 0},
|
||||
{1, 0},
|
||||
{-1, -1},
|
||||
{0, -1},
|
||||
{1, -1}
|
||||
}
|
||||
for i = 1, #dirs do
|
||||
local tile =
|
||||
g_map.getTile(
|
||||
{
|
||||
x = pos.x - dirs[i][1],
|
||||
y = pos.y - dirs[i][2],
|
||||
z = pos.z
|
||||
}
|
||||
)
|
||||
if tile then
|
||||
table.insert(tiles, tile)
|
||||
end
|
||||
end
|
||||
|
||||
return tiles
|
||||
end
|
||||
|
||||
-- ##################### --
|
||||
-- [[ Information class ]] --
|
||||
-- ##################### --
|
||||
|
||||
--- global variable to reflect current CaveBot status
|
||||
CaveBot.Status = "waiting"
|
||||
|
||||
--- Parses config and extracts loot list.
|
||||
-- @return table
|
||||
function CaveBot.GetLootItems()
|
||||
local t = CaveBotConfigParse() and CaveBotConfigParse()["items"] or nil
|
||||
|
||||
local returnTable = {}
|
||||
if type(t) == "table" then
|
||||
for i, item in pairs(t) do
|
||||
table.insert(returnTable, item["id"])
|
||||
end
|
||||
end
|
||||
|
||||
return returnTable
|
||||
end
|
||||
|
||||
|
||||
--- Checks whether player has any visible items to be stashed
|
||||
-- @return boolean
|
||||
function CaveBot.HasLootItems()
|
||||
for _, container in pairs(getContainers()) do
|
||||
local name = container:getName():lower()
|
||||
if not name:find("depot") and not name:find("your inbox") then
|
||||
for _, item in pairs(container:getItems()) do
|
||||
local id = item:getId()
|
||||
if table.find(CaveBot.GetLootItems(), id) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Parses config and extracts loot containers.
|
||||
-- @return table
|
||||
function CaveBot.GetLootContainers()
|
||||
local t = CaveBotConfigParse() and CaveBotConfigParse()["containers"] or nil
|
||||
|
||||
local returnTable = {}
|
||||
if type(t) == "table" then
|
||||
for i, container in pairs(t) do
|
||||
table.insert(returnTable, container["id"])
|
||||
end
|
||||
end
|
||||
|
||||
return returnTable
|
||||
end
|
||||
|
||||
--- Information about open containers.
|
||||
-- @param amount is boolean
|
||||
-- @return table or integer
|
||||
function CaveBot.GetOpenedLootContainers(containerTable)
|
||||
local containers = CaveBot.GetLootContainers()
|
||||
|
||||
local t = {}
|
||||
for i, container in pairs(getContainers()) do
|
||||
local containerId = container:getContainerItem():getId()
|
||||
if table.find(containers, containerId) then
|
||||
table.insert(t, container)
|
||||
end
|
||||
end
|
||||
|
||||
return containerTable and t or #t
|
||||
end
|
||||
|
||||
--- Some actions needs to be additionally slowed down in case of high ping.
|
||||
-- Maximum at 2000ms in case of lag spike.
|
||||
-- @param multiplayer is integer
|
||||
-- @return void
|
||||
function CaveBot.PingDelay(multiplayer)
|
||||
multiplayer = multiplayer or 1
|
||||
if ping() and ping() > 150 then -- in most cases ping above 150 affects CaveBot
|
||||
local value = math.min(ping() * multiplayer, 2000)
|
||||
return delay(value)
|
||||
end
|
||||
end
|
||||
|
||||
-- ##################### --
|
||||
-- [[ Container class ]] --
|
||||
-- ##################### --
|
||||
|
||||
--- Closes any loot container that is open.
|
||||
-- @return void or boolean
|
||||
function CaveBot.CloseLootContainer()
|
||||
local containers = CaveBot.GetLootContainers()
|
||||
|
||||
for i, container in pairs(getContainers()) do
|
||||
local containerId = container:getContainerItem():getId()
|
||||
if table.find(containers, containerId) then
|
||||
return g_game.close(container)
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function CaveBot.CloseAllLootContainers()
|
||||
local containers = CaveBot.GetLootContainers()
|
||||
|
||||
for i, container in pairs(getContainers()) do
|
||||
local containerId = container:getContainerItem():getId()
|
||||
if table.find(containers, containerId) then
|
||||
g_game.close(container)
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--- Opens any loot container that isn't already opened.
|
||||
-- @return void or boolean
|
||||
function CaveBot.OpenLootContainer()
|
||||
local containers = CaveBot.GetLootContainers()
|
||||
|
||||
local t = {}
|
||||
for i, container in pairs(getContainers()) do
|
||||
local containerId = container:getContainerItem():getId()
|
||||
table.insert(t, containerId)
|
||||
end
|
||||
|
||||
for _, container in pairs(getContainers()) do
|
||||
for _, item in pairs(container:getItems()) do
|
||||
local id = item:getId()
|
||||
if table.find(containers, id) and not table.find(t, id) then
|
||||
return g_game.open(item)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- ##################### --
|
||||
-- [[[ Position class ]] --
|
||||
-- ##################### --
|
||||
|
||||
--- Compares distance between player position and given pos.
|
||||
-- @param position is table
|
||||
-- @param distance is integer
|
||||
-- @return boolean
|
||||
function CaveBot.MatchPosition(position, distance)
|
||||
local pPos = player:getPosition()
|
||||
distance = distance or 1
|
||||
return getDistanceBetween(pPos, position) <= distance
|
||||
end
|
||||
|
||||
--- Stripped down to take less space.
|
||||
-- Use only to safe position, like pz movement or reaching npc.
|
||||
-- Needs to be called between 200-500ms to achieve fluid movement.
|
||||
-- @param position is table
|
||||
-- @param distance is integer
|
||||
-- @return void
|
||||
function CaveBot.GoTo(position, precision)
|
||||
if not precision then
|
||||
precision = 3
|
||||
end
|
||||
return CaveBot.walkTo(position, 20, {ignoreCreatures = true, precision = precision})
|
||||
end
|
||||
|
||||
--- Finds position of npc by name and reaches its position.
|
||||
-- @return void(acion) or boolean
|
||||
function CaveBot.ReachNPC(name)
|
||||
name = name:lower()
|
||||
|
||||
local npc = nil
|
||||
for i, spec in pairs(getSpectators()) do
|
||||
if spec:isNpc() and spec:getName():lower() == name then
|
||||
npc = spec
|
||||
end
|
||||
end
|
||||
|
||||
if not CaveBot.MatchPosition(npc:getPosition(), 3) then
|
||||
CaveBot.GoTo(npc:getPosition())
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- ##################### --
|
||||
-- [[[[ Depot class ]]]] --
|
||||
-- ##################### --
|
||||
|
||||
--- Reaches closest locker.
|
||||
-- @return void(acion) or boolean
|
||||
|
||||
local depositerLockerTarget = nil
|
||||
local depositerLockerReachRetries = 0
|
||||
function CaveBot.ReachDepot()
|
||||
local pPos = player:getPosition()
|
||||
local tiles = getNearTiles(player:getPosition())
|
||||
|
||||
for i, tile in pairs(tiles) do
|
||||
for i, item in pairs(tile:getItems()) do
|
||||
if table.find(LOCKERS_LIST, item:getId()) then
|
||||
depositerLockerTarget = nil
|
||||
depositerLockerReachRetries = 0
|
||||
return true -- if near locker already then return function
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if depositerLockerReachRetries > 20 then
|
||||
depositerLockerTarget = nil
|
||||
depositerLockerReachRetries = 0
|
||||
end
|
||||
|
||||
local candidates = {}
|
||||
|
||||
if not depositerLockerTarget or distanceFromPlayer(depositerLockerTarget, pPos) > 12 then
|
||||
for i, tile in pairs(g_map.getTiles(posz())) do
|
||||
local tPos = tile:getPosition()
|
||||
for i, item in pairs(tile:getItems()) do
|
||||
if table.find(LOCKERS_LIST, item:getId()) then
|
||||
local lockerTilePos = tile:getPosition()
|
||||
lockerTilePos.x = lockerTilePos.x + LOCKER_ACCESSTILE_MODIFIERS[item:getId()][1]
|
||||
lockerTilePos.y = lockerTilePos.y + LOCKER_ACCESSTILE_MODIFIERS[item:getId()][2]
|
||||
local lockerTile = g_map.getTile(lockerTilePos)
|
||||
if not lockerTile:hasCreature() then
|
||||
if findPath(pos(), tPos, 20, {ignoreNonPathable = false, precision = 1, ignoreCreatures = true}) then
|
||||
local distance = getDistanceBetween(tPos, pPos)
|
||||
table.insert(candidates, {pos=tPos, dist=distance})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #candidates > 1 then
|
||||
table.sort(candidates, function(a,b) return a.dist < b.dist end)
|
||||
end
|
||||
end
|
||||
|
||||
depositerLockerTarget = depositerLockerTarget or candidates[1].pos
|
||||
|
||||
if depositerLockerTarget then
|
||||
if not CaveBot.MatchPosition(depositerLockerTarget) then
|
||||
depositerLockerReachRetries = depositerLockerReachRetries + 1
|
||||
return CaveBot.GoTo(depositerLockerTarget, 1)
|
||||
else
|
||||
depositerLockerReachRetries = 0
|
||||
depositerLockerTarget = nil
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Opens locker item.
|
||||
-- @return void(acion) or boolean
|
||||
function CaveBot.OpenLocker()
|
||||
local pPos = player:getPosition()
|
||||
local tiles = getNearTiles(player:getPosition())
|
||||
|
||||
local locker = getContainerByName("Locker")
|
||||
if not locker then
|
||||
for i, tile in pairs(tiles) do
|
||||
for i, item in pairs(tile:getItems()) do
|
||||
if table.find(LOCKERS_LIST, item:getId()) then
|
||||
local topThing = tile:getTopUseThing()
|
||||
if not topThing:isNotMoveable() then
|
||||
g_game.move(topThing, pPos, topThing:getCount())
|
||||
else
|
||||
return g_game.open(item)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
--- Opens depot chest.
|
||||
-- @return void(acion) or boolean
|
||||
function CaveBot.OpenDepotChest()
|
||||
local depot = getContainerByName("Depot chest")
|
||||
if not depot then
|
||||
local locker = getContainerByName("Locker")
|
||||
if not locker then
|
||||
return CaveBot.OpenLocker()
|
||||
end
|
||||
for i, item in pairs(locker:getItems()) do
|
||||
if item:getId() == 3502 then
|
||||
return g_game.open(item, locker)
|
||||
end
|
||||
end
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
--- Opens inbox inside locker.
|
||||
-- @return void(acion) or boolean
|
||||
function CaveBot.OpenInbox()
|
||||
local inbox = getContainerByName("Your inbox")
|
||||
if not inbox then
|
||||
local locker = getContainerByName("Locker")
|
||||
if not locker then
|
||||
return CaveBot.OpenLocker()
|
||||
end
|
||||
for i, item in pairs(locker:getItems()) do
|
||||
if item:getId() == 12902 then
|
||||
return g_game.open(item)
|
||||
end
|
||||
end
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
--- Opens depot box of given number.
|
||||
-- @param index is integer
|
||||
-- @return void or boolean
|
||||
function CaveBot.OpenDepotBox(index)
|
||||
local depot = getContainerByName("Depot chest")
|
||||
if not depot then
|
||||
return CaveBot.ReachAndOpenDepot()
|
||||
end
|
||||
|
||||
local foundParent = false
|
||||
for i, container in pairs(getContainers()) do
|
||||
if container:getName():lower():find("depot box") then
|
||||
foundParent = container
|
||||
break
|
||||
end
|
||||
end
|
||||
if foundParent then return true end
|
||||
|
||||
for i, container in pairs(depot:getItems()) do
|
||||
if i == index then
|
||||
return g_game.open(container)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Reaches and opens depot.
|
||||
-- Combined for shorthand usage.
|
||||
-- @return boolean whether succeed to reach and open depot
|
||||
function CaveBot.ReachAndOpenDepot()
|
||||
if CaveBot.ReachDepot() and CaveBot.OpenDepotChest() then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- Reaches and opens imbox.
|
||||
-- Combined for shorthand usage.
|
||||
-- @return boolean whether succeed to reach and open depot
|
||||
function CaveBot.ReachAndOpenInbox()
|
||||
if CaveBot.ReachDepot() and CaveBot.OpenInbox() then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- Stripped down function to stash item.
|
||||
-- @param item is object
|
||||
-- @param index is integer
|
||||
-- @param destination is object
|
||||
-- @return void
|
||||
function CaveBot.StashItem(item, index, destination)
|
||||
destination = destination or getContainerByName("Depot chest")
|
||||
if not destination then return false end
|
||||
|
||||
return g_game.move(item, destination:getSlotPosition(index), item:getCount())
|
||||
end
|
||||
|
||||
--- Withdraws item from depot chest or mail inbox.
|
||||
-- main function for depositer/withdrawer
|
||||
-- @param id is integer
|
||||
-- @param amount is integer
|
||||
-- @param fromDepot is boolean or integer
|
||||
-- @param destination is object
|
||||
-- @return void
|
||||
function CaveBot.WithdrawItem(id, amount, fromDepot, destination)
|
||||
if destination and type(destination) == "string" then
|
||||
destination = getContainerByName(destination)
|
||||
end
|
||||
local itemCount = itemAmount(id)
|
||||
local depot
|
||||
for i, container in pairs(getContainers()) do
|
||||
if container:getName():lower():find("depot box") or container:getName():lower():find("your inbox") then
|
||||
depot = container
|
||||
break
|
||||
end
|
||||
end
|
||||
if not depot then
|
||||
if fromDepot then
|
||||
if not CaveBot.OpenDepotBox(fromDepot) then return end
|
||||
else
|
||||
return CaveBot.ReachAndOpenInbox()
|
||||
end
|
||||
return
|
||||
end
|
||||
if not destination then
|
||||
for i, container in pairs(getContainers()) do
|
||||
if container:getCapacity() > #container:getItems() and not string.find(container:getName():lower(), "quiver") 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
|
||||
end
|
||||
|
||||
if itemCount >= amount then
|
||||
return true
|
||||
end
|
||||
|
||||
local toMove = amount - itemCount
|
||||
for i, item in pairs(depot:getItems()) do
|
||||
if item:getId() == id then
|
||||
return g_game.move(item, destination:getSlotPosition(destination:getItemsCount()), math.min(toMove, item:getCount()))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- ##################### --
|
||||
-- [[[[[ Talk class ]]]] --
|
||||
-- ##################### --
|
||||
|
||||
--- Controlled by event caller.
|
||||
-- Simple way to build npc conversations instead of multiline overcopied code.
|
||||
-- @return void
|
||||
function CaveBot.Conversation(...)
|
||||
local expressions = {...}
|
||||
local delay = storage.extras.talkDelay or 1000
|
||||
|
||||
local talkDelay = 0
|
||||
for i, expr in ipairs(expressions) do
|
||||
schedule(talkDelay, function() NPC.say(expr) end)
|
||||
talkDelay = talkDelay + delay
|
||||
end
|
||||
end
|
||||
|
||||
--- Says hi trade to NPC.
|
||||
-- Used as shorthand to open NPC trade window.
|
||||
-- @return void
|
||||
function CaveBot.OpenNpcTrade()
|
||||
return CaveBot.Conversation("hi", "trade")
|
||||
end
|
||||
|
||||
--- Says hi destination yes to NPC.
|
||||
-- Used as shorthand to travel.
|
||||
-- @param destination is string
|
||||
-- @return void
|
||||
function CaveBot.Travel(destination)
|
||||
return CaveBot.Conversation("hi", destination, "yes")
|
||||
end
|
||||
455
modules/game_bot/default_configs/vBot_4.7/vBot/new_healer.lua
Normal file
455
modules/game_bot/default_configs/vBot_4.7/vBot/new_healer.lua
Normal file
@@ -0,0 +1,455 @@
|
||||
setDefaultTab("Main")
|
||||
local panelName = "newHealer"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 19
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('Friend Healer')
|
||||
|
||||
Button
|
||||
id: edit
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Setup
|
||||
|
||||
]])
|
||||
ui:setId(panelName)
|
||||
|
||||
-- validate current settings
|
||||
if not storage[panelName] or not storage[panelName].priorities then
|
||||
storage[panelName] = nil
|
||||
end
|
||||
|
||||
if not storage[panelName] then
|
||||
storage[panelName] = {
|
||||
enabled = false,
|
||||
customPlayers = {},
|
||||
vocations = {},
|
||||
groups = {},
|
||||
priorities = {
|
||||
|
||||
{name="Custom Spell", enabled=false, custom=true},
|
||||
{name="Exura Gran Sio", enabled=true, strong = true},
|
||||
{name="Exura Sio", enabled=true, normal = true},
|
||||
{name="Exura Gran Mas Res", enabled=true, area = true},
|
||||
{name="Health Item", enabled=true, health=true},
|
||||
{name="Mana Item", enabled=true, mana=true}
|
||||
|
||||
},
|
||||
settings = {
|
||||
|
||||
{type="HealItem", text="Mana Item ", value=268},
|
||||
{type="HealScroll", text="Item Range: ", value=6},
|
||||
{type="HealItem", text="Health Item ", value=3160},
|
||||
{type="HealScroll", text="Mas Res Players: ", value=2},
|
||||
{type="HealScroll", text="Heal Friend at: ", value=80},
|
||||
{type="HealScroll", text="Use Gran Sio at: ", value=80},
|
||||
{type="HealScroll", text="Min Player HP%: ", value=80},
|
||||
{type="HealScroll", text="Min Player MP%: ", value=50},
|
||||
|
||||
},
|
||||
conditions = {
|
||||
knights = true,
|
||||
paladins = true,
|
||||
druids = false,
|
||||
sorcerers = false,
|
||||
party = true,
|
||||
guild = false,
|
||||
botserver = false,
|
||||
friends = false
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
local config = storage[panelName]
|
||||
local healerWindow = UI.createWindow('FriendHealer')
|
||||
healerWindow:hide()
|
||||
healerWindow:setId(panelName)
|
||||
|
||||
ui.title:setOn(config.enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
config.enabled = not config.enabled
|
||||
widget:setOn(config.enabled)
|
||||
end
|
||||
|
||||
ui.edit.onClick = function()
|
||||
healerWindow:show()
|
||||
healerWindow:raise()
|
||||
healerWindow:focus()
|
||||
end
|
||||
|
||||
local conditions = healerWindow.conditions
|
||||
local targetSettings = healerWindow.targetSettings
|
||||
local customList = healerWindow.customList
|
||||
local priority = healerWindow.priority
|
||||
|
||||
-- customList
|
||||
-- create entries on the list
|
||||
for name, health in pairs(config.customPlayers) do
|
||||
local widget = UI.createWidget("HealerPlayerEntry", customList.playerList.list)
|
||||
widget.remove.onClick = function()
|
||||
config.customPlayers[name] = nil
|
||||
widget:destroy()
|
||||
end
|
||||
widget:setText("["..health.."%] "..name)
|
||||
end
|
||||
|
||||
customList.playerList.onDoubleClick = function()
|
||||
customList.playerList:hide()
|
||||
end
|
||||
|
||||
local function clearFields()
|
||||
customList.addPanel.name:setText("friend name")
|
||||
customList.addPanel.health:setText("1")
|
||||
customList.playerList:show()
|
||||
end
|
||||
|
||||
local function capitalFistLetter(str)
|
||||
return (string.gsub(str, "^%l", string.upper))
|
||||
end
|
||||
|
||||
customList.addPanel.add.onClick = function()
|
||||
local name = ""
|
||||
local words = string.split(customList.addPanel.name:getText(), " ")
|
||||
local health = tonumber(customList.addPanel.health:getText())
|
||||
for i, word in ipairs(words) do
|
||||
name = name .. " " .. capitalFistLetter(word)
|
||||
end
|
||||
|
||||
if not health then
|
||||
clearFields()
|
||||
return warn("[Friend Healer] Please enter health percent value!")
|
||||
end
|
||||
|
||||
if name:len() == 0 or name:lower() == "friend name" then
|
||||
clearFields()
|
||||
return warn("[Friend Healer] Please enter friend name to be added!")
|
||||
end
|
||||
|
||||
if config.customPlayers[name] or config.customPlayers[name:lower()] then
|
||||
clearFields()
|
||||
return warn("[Friend Healer] Player already added to custom list.")
|
||||
else
|
||||
config.customPlayers[name] = health
|
||||
local widget = UI.createWidget("HealerPlayerEntry", customList.playerList.list)
|
||||
widget.remove.onClick = function()
|
||||
config.customPlayers[name] = nil
|
||||
widget:destroy()
|
||||
end
|
||||
widget:setText("["..health.."%] "..name)
|
||||
end
|
||||
|
||||
clearFields()
|
||||
end
|
||||
|
||||
local function validate(widget, category)
|
||||
local list = widget:getParent()
|
||||
local label = list:getParent().title
|
||||
-- 1 - priorities | 2 - vocation
|
||||
category = category or 0
|
||||
|
||||
if category == 2 and not storage.extras.checkPlayer then
|
||||
label:setColor("#d9321f")
|
||||
label:setTooltip("! WARNING ! \nTurn on check players in extras to use this feature!")
|
||||
return
|
||||
else
|
||||
label:setColor("#dfdfdf")
|
||||
label:setTooltip("")
|
||||
end
|
||||
|
||||
local checked = false
|
||||
for i, child in ipairs(list:getChildren()) do
|
||||
if category == 1 and child.enabled:isChecked() or child:isChecked() then
|
||||
checked = true
|
||||
end
|
||||
end
|
||||
|
||||
if not checked then
|
||||
label:setColor("#d9321f")
|
||||
label:setTooltip("! WARNING ! \nNo category selected!")
|
||||
else
|
||||
label:setColor("#dfdfdf")
|
||||
label:setTooltip("")
|
||||
end
|
||||
end
|
||||
-- targetSettings
|
||||
targetSettings.vocations.box.knights:setChecked(config.conditions.knights)
|
||||
targetSettings.vocations.box.knights.onClick = function(widget)
|
||||
config.conditions.knights = not config.conditions.knights
|
||||
widget:setChecked(config.conditions.knights)
|
||||
validate(widget, 2)
|
||||
end
|
||||
|
||||
targetSettings.vocations.box.paladins:setChecked(config.conditions.paladins)
|
||||
targetSettings.vocations.box.paladins.onClick = function(widget)
|
||||
config.conditions.paladins = not config.conditions.paladins
|
||||
widget:setChecked(config.conditions.paladins)
|
||||
validate(widget, 2)
|
||||
end
|
||||
|
||||
targetSettings.vocations.box.druids:setChecked(config.conditions.druids)
|
||||
targetSettings.vocations.box.druids.onClick = function(widget)
|
||||
config.conditions.druids = not config.conditions.druids
|
||||
widget:setChecked(config.conditions.druids)
|
||||
validate(widget, 2)
|
||||
end
|
||||
|
||||
targetSettings.vocations.box.sorcerers:setChecked(config.conditions.sorcerers)
|
||||
targetSettings.vocations.box.sorcerers.onClick = function(widget)
|
||||
config.conditions.sorcerers = not config.conditions.sorcerers
|
||||
widget:setChecked(config.conditions.sorcerers)
|
||||
validate(widget, 2)
|
||||
end
|
||||
|
||||
targetSettings.groups.box.friends:setChecked(config.conditions.friends)
|
||||
targetSettings.groups.box.friends.onClick = function(widget)
|
||||
config.conditions.friends = not config.conditions.friends
|
||||
widget:setChecked(config.conditions.friends)
|
||||
validate(widget)
|
||||
end
|
||||
|
||||
targetSettings.groups.box.party:setChecked(config.conditions.party)
|
||||
targetSettings.groups.box.party.onClick = function(widget)
|
||||
config.conditions.party = not config.conditions.party
|
||||
widget:setChecked(config.conditions.party)
|
||||
validate(widget)
|
||||
end
|
||||
|
||||
targetSettings.groups.box.guild:setChecked(config.conditions.guild)
|
||||
targetSettings.groups.box.guild.onClick = function(widget)
|
||||
config.conditions.guild = not config.conditions.guild
|
||||
widget:setChecked(config.conditions.guild)
|
||||
validate(widget)
|
||||
end
|
||||
|
||||
targetSettings.groups.box.botserver:setChecked(config.conditions.botserver)
|
||||
targetSettings.groups.box.botserver.onClick = function(widget)
|
||||
config.conditions.botserver = not config.conditions.botserver
|
||||
widget:setChecked(config.conditions.botserver)
|
||||
validate(widget)
|
||||
end
|
||||
|
||||
validate(targetSettings.vocations.box.knights)
|
||||
validate(targetSettings.groups.box.friends)
|
||||
validate(targetSettings.vocations.box.sorcerers, 2)
|
||||
|
||||
-- conditions
|
||||
for i, setting in ipairs(config.settings) do
|
||||
local widget = UI.createWidget(setting.type, conditions.box)
|
||||
local text = setting.text
|
||||
local val = setting.value
|
||||
widget.text:setText(text)
|
||||
|
||||
if setting.type == "HealScroll" then
|
||||
widget.text:setText(widget.text:getText()..val)
|
||||
if not (text:find("Range") or text:find("Mas Res")) then
|
||||
widget.text:setText(widget.text:getText().."%")
|
||||
end
|
||||
widget.scroll:setValue(val)
|
||||
widget.scroll.onValueChange = function(scroll, value)
|
||||
setting.value = value
|
||||
widget.text:setText(text..value)
|
||||
if not (text:find("Range") or text:find("Mas Res")) then
|
||||
widget.text:setText(widget.text:getText().."%")
|
||||
end
|
||||
end
|
||||
if text:find("Range") or text:find("Mas Res") then
|
||||
widget.scroll:setMaximum(10)
|
||||
end
|
||||
else
|
||||
widget.item:setItemId(val)
|
||||
widget.item:setShowCount(false)
|
||||
widget.item.onItemChange = function(widget)
|
||||
setting.value = widget:getItemId()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- priority and toggles
|
||||
local function setCrementalButtons()
|
||||
for i, child in ipairs(priority.list:getChildren()) do
|
||||
if i == 1 then
|
||||
child.increment:disable()
|
||||
elseif i == 6 then
|
||||
child.decrement:disable()
|
||||
else
|
||||
child.increment:enable()
|
||||
child.decrement:enable()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i, action in ipairs(config.priorities) do
|
||||
local widget = UI.createWidget("PriorityEntry", priority.list)
|
||||
|
||||
widget:setText(action.name)
|
||||
widget.increment.onClick = function()
|
||||
local index = priority.list:getChildIndex(widget)
|
||||
local table = config.priorities
|
||||
|
||||
priority.list:moveChildToIndex(widget, index-1)
|
||||
table[index], table[index-1] = table[index-1], table[index]
|
||||
setCrementalButtons()
|
||||
end
|
||||
widget.decrement.onClick = function()
|
||||
local index = priority.list:getChildIndex(widget)
|
||||
local table = config.priorities
|
||||
|
||||
priority.list:moveChildToIndex(widget, index+1)
|
||||
table[index], table[index+1] = table[index+1], table[index]
|
||||
setCrementalButtons()
|
||||
end
|
||||
widget.enabled:setChecked(action.enabled)
|
||||
widget:setColor(action.enabled and "#98BF64" or "#dfdfdf")
|
||||
widget.enabled.onClick = function()
|
||||
action.enabled = not action.enabled
|
||||
widget:setColor(action.enabled and "#98BF64" or "#dfdfdf")
|
||||
widget.enabled:setChecked(action.enabled)
|
||||
validate(widget, 1)
|
||||
end
|
||||
if action.custom then
|
||||
widget.onDoubleClick = function()
|
||||
local window = modules.client_textedit.show(widget, {title = "Custom Spell", description = "Enter below formula for a custom healing spell"})
|
||||
schedule(50, function()
|
||||
window:raise()
|
||||
window:focus()
|
||||
end)
|
||||
end
|
||||
widget.onTextChange = function(widget,text)
|
||||
action.name = text
|
||||
end
|
||||
widget:setTooltip("Double click to set spell formula.")
|
||||
end
|
||||
|
||||
if i == #config.priorities then
|
||||
validate(widget, 1)
|
||||
setCrementalButtons()
|
||||
end
|
||||
end
|
||||
|
||||
local lastItemUse = now
|
||||
local function friendHealerAction(spec, targetsInRange)
|
||||
local name = spec:getName()
|
||||
local health = spec:getHealthPercent()
|
||||
local mana = spec:getManaPercent()
|
||||
local dist = distanceFromPlayer(spec:getPosition())
|
||||
targetsInRange = targetsInRange or 0
|
||||
|
||||
local masResAmount = config.settings[4].value
|
||||
local itemRange = config.settings[2].value
|
||||
local healItem = config.settings[3].value
|
||||
local manaItem = config.settings[1].value
|
||||
local normalHeal = config.customPlayers[name] or config.settings[5].value
|
||||
local strongHeal = config.customPlayers[name] and normalHeal/2 or config.settings[6].value
|
||||
|
||||
for i, action in ipairs(config.priorities) do
|
||||
if action.enabled then
|
||||
if action.area and masResAmount <= targetsInRange and canCast("exura gran mas res") then
|
||||
return say("exura gran mas res")
|
||||
end
|
||||
if action.mana and findItem(manaItem) and mana <= normalHeal and dist <= itemRange and now - lastItemUse > 1000 then
|
||||
lastItemUse = now
|
||||
return useWith(manaItem, spec)
|
||||
end
|
||||
if action.health and findItem(healItem) and health <= normalHeal and dist <= itemRange and now - lastItemUse > 1000 then
|
||||
lastItemUse = now
|
||||
return useWith(healItem, spec)
|
||||
end
|
||||
if action.strong and health <= strongHeal and not modules.game_cooldown.isCooldownIconActive(101) then
|
||||
return say('exura gran sio "'..name)
|
||||
end
|
||||
if (action.normal or action.custom) and health <= normalHeal and canCast('exura sio "'..name) then
|
||||
return say('exura sio "'..name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
macro(100, function()
|
||||
if not config.enabled then return end
|
||||
if modules.game_cooldown.isGroupCooldownIconActive(2) then return end
|
||||
|
||||
local minHp = config.settings[7].value
|
||||
local minMp = config.settings[8].value
|
||||
|
||||
-- first index will be heal target
|
||||
local finalTable = {}
|
||||
local inMasResRange = 0
|
||||
|
||||
-- check basic
|
||||
if hppercent() <= minHp or manapercent() <= minMp then return end
|
||||
|
||||
-- get all spectators
|
||||
local spectators = getSpectators()
|
||||
|
||||
-- clear table from irrelevant spectators
|
||||
for i, spec in ipairs(getSpectators()) do
|
||||
if spec:isLocalPlayer() or not spec:isPlayer() or not spec:canShoot() then
|
||||
if not config.customPlayers[name] then
|
||||
table.remove(spectators, table.find(spectators, spec))
|
||||
end
|
||||
else
|
||||
local specText = spec:getText()
|
||||
-- check players is enabled and spectator already verified
|
||||
if storage.extras.checkPlayer and specText:len() > 0 then
|
||||
if specText:find("EK") and not config.conditions.knights or
|
||||
specText:find("RP") and not config.conditions.paladins or
|
||||
specText:find("ED") and not config.conditions.druids or
|
||||
specText:find("MS") and not config.conditions.sorcerers then
|
||||
if not config.customPlayers[name] then
|
||||
table.remove(spectators, table.find(spectators, spec))
|
||||
end
|
||||
end
|
||||
end
|
||||
local okParty = config.conditions.party and spec:isPartyMember()
|
||||
local okFriend = config.conditions.friends and isFriend(spec)
|
||||
local okGuild = config.conditions.guild and spec:getEmblem() == 1
|
||||
local okBotServer = config.conditions.botserver and vBot.BotServerMembers[spec:getName()]
|
||||
if not (okParty or okFriend or okGuild or okBotServer) then
|
||||
if not config.customPlayers[name] then
|
||||
table.remove(spectators, table.find(spectators, spec))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- no targets, return
|
||||
if #spectators == 0 then return end
|
||||
|
||||
for name, health in pairs(config.customPlayers) do
|
||||
for i, spec in ipairs(spectators) do
|
||||
local specHp = spec:getHealthPercent()
|
||||
if spec:getName() == name and specHp <= health then
|
||||
if distanceFromPlayer(spec:getPosition()) <= 2 then
|
||||
inMasResRange = inMasResRange + 1
|
||||
end
|
||||
table.insert(finalTable, spec)
|
||||
table.remove(spectators, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i=1,#spectators do
|
||||
local spec = spectators[i]
|
||||
if distanceFromPlayer(spec:getPosition()) <= 3 then
|
||||
inMasResRange = inMasResRange + 1
|
||||
end
|
||||
table.insert(finalTable, spec)
|
||||
end
|
||||
|
||||
-- no targets, return
|
||||
if #finalTable == 0 then return end
|
||||
|
||||
friendHealerAction(finalTable[1], inMasResRange)
|
||||
end)
|
||||
413
modules/game_bot/default_configs/vBot_4.7/vBot/new_healer.otui
Normal file
413
modules/game_bot/default_configs/vBot_4.7/vBot/new_healer.otui
Normal file
@@ -0,0 +1,413 @@
|
||||
CategoryCheckBox < CheckBox
|
||||
font: verdana-11px-rounded
|
||||
margin-top: 3
|
||||
|
||||
$checked:
|
||||
color: #98BF64
|
||||
|
||||
HealScroll < Panel
|
||||
|
||||
ToolTipLabel
|
||||
id: text
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
text: test
|
||||
|
||||
HorizontalScrollBar
|
||||
id: scroll
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
step: 1
|
||||
|
||||
HealItem < Panel
|
||||
|
||||
BotItem
|
||||
id: item
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
size: 34 34
|
||||
|
||||
ToolTipLabel
|
||||
id: text
|
||||
anchors.fill: parent
|
||||
anchors.left: prev.right
|
||||
margin-left: 8
|
||||
text-wrap: true
|
||||
text-align: left
|
||||
|
||||
ToolTipLabel < UIWidget
|
||||
font: verdana-11px-rounded
|
||||
color: #dfdfdf
|
||||
height: 14
|
||||
text-align: center
|
||||
|
||||
HealerPlayerEntry < Label
|
||||
background-color: alpha
|
||||
text-offset: 5 1
|
||||
focusable: true
|
||||
height: 16
|
||||
font: verdana-11px-rounded
|
||||
text-align: left
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
Button
|
||||
id: remove
|
||||
anchors.right: parent.right
|
||||
margin-right: 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
size: 15 15
|
||||
margin-right: 15
|
||||
text: X
|
||||
tooltip: Remove player from the list
|
||||
|
||||
PriorityEntry < ToolTipLabel
|
||||
background-color: alpha
|
||||
text-offset: 18 1
|
||||
focusable: true
|
||||
height: 16
|
||||
font: verdana-11px-rounded
|
||||
text-align: left
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
CheckBox
|
||||
id: enabled
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
size: 15 15
|
||||
margin-top: 2
|
||||
margin-left: 3
|
||||
|
||||
Button
|
||||
id: increment
|
||||
anchors.right: parent.right
|
||||
margin-right: 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
size: 14 14
|
||||
text: +
|
||||
tooltip: Increase Priority
|
||||
|
||||
Button
|
||||
id: decrement
|
||||
anchors.right: prev.left
|
||||
margin-right: 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
size: 14 14
|
||||
text: -
|
||||
tooltip: Decrease Priority
|
||||
|
||||
TargetSettings < Panel
|
||||
size: 280 125
|
||||
padding: 3
|
||||
image-source: /images/ui/window
|
||||
image-border: 6
|
||||
|
||||
Label
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
font: verdana-11px-rounded
|
||||
text: Heal Target Settings
|
||||
|
||||
Groups
|
||||
id: groups
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 8
|
||||
anchors.left: parent.left
|
||||
margin-left: 9
|
||||
|
||||
Vocations
|
||||
id: vocations
|
||||
anchors.left: prev.right
|
||||
margin-left: 5
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
|
||||
Groups < FlatPanel
|
||||
size: 150 90
|
||||
padding: 3
|
||||
padding-top: 5
|
||||
|
||||
ToolTipLabel
|
||||
id: title
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
text: Groups
|
||||
tooltip: Players added in custom list will always be in scope
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 2
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Panel
|
||||
id: box
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 2
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
padding: 2
|
||||
layout:
|
||||
type: verticalBox
|
||||
|
||||
CategoryCheckBox
|
||||
id: friends
|
||||
text: Friends
|
||||
|
||||
CategoryCheckBox
|
||||
id: party
|
||||
text: Party Members
|
||||
|
||||
CategoryCheckBox
|
||||
id: guild
|
||||
text: Guild Members
|
||||
|
||||
CategoryCheckBox
|
||||
id: botserver
|
||||
text: BotServer Members
|
||||
|
||||
Vocations < FlatPanel
|
||||
size: 100 90
|
||||
padding: 3
|
||||
padding-top: 5
|
||||
|
||||
ToolTipLabel
|
||||
id: title
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
font: verdana-11px-rounded
|
||||
text: Vocations
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 2
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Panel
|
||||
id: box
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 2
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
padding: 2
|
||||
|
||||
layout:
|
||||
type: verticalBox
|
||||
|
||||
CategoryCheckBox
|
||||
id: knights
|
||||
text: Knights
|
||||
|
||||
CategoryCheckBox
|
||||
id: paladins
|
||||
text: Paladins
|
||||
|
||||
CategoryCheckBox
|
||||
id: druids
|
||||
text: Druids
|
||||
|
||||
CategoryCheckBox
|
||||
id: sorcerers
|
||||
text: Sorcerers
|
||||
|
||||
Priority < Panel
|
||||
size: 190 123
|
||||
padding: 6
|
||||
padding-top: 3
|
||||
image-source: /images/ui/window
|
||||
image-border: 6
|
||||
|
||||
ToolTipLabel
|
||||
id: title
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
font: verdana-11px-rounded
|
||||
text: Priority & Toggles
|
||||
|
||||
TextList
|
||||
id: list
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
fit-children: true
|
||||
padding-top: 1
|
||||
|
||||
AddPlayer < FlatPanel
|
||||
padding: 5
|
||||
|
||||
Label
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
font: verdana-11px-rounded
|
||||
text: Add Player to Custom List
|
||||
text-align: center
|
||||
text-wrap: true
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 2
|
||||
|
||||
SpinBox
|
||||
id: health
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 20
|
||||
width: 50
|
||||
minimum: 1
|
||||
maximum: 99
|
||||
step: 1
|
||||
focusable: true
|
||||
text-align: center
|
||||
|
||||
Label
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
font: verdana-11px-rounded
|
||||
text: %HP - heal if below
|
||||
|
||||
TextEdit
|
||||
id: name
|
||||
anchors.top: health.bottom
|
||||
margin-top: 5
|
||||
anchors.left: health.left
|
||||
anchors.right: parent.right
|
||||
font: verdana-11px-rounded
|
||||
text-align: center
|
||||
text: friend name
|
||||
|
||||
Button
|
||||
id: add
|
||||
anchors.left: health.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
font: verdana-11px-rounded
|
||||
text: Add Player
|
||||
|
||||
PlayerList < Panel
|
||||
|
||||
TextList
|
||||
id: list
|
||||
anchors.fill: parent
|
||||
fit-children: true
|
||||
padding-top: 2
|
||||
vertical-scrollbar: listScrollBar
|
||||
|
||||
VerticalScrollBar
|
||||
id: listScrollBar
|
||||
anchors.top: list.top
|
||||
anchors.bottom: list.bottom
|
||||
anchors.right: list.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
CustomList < Panel
|
||||
size: 190 172
|
||||
padding: 6
|
||||
padding-top: 3
|
||||
image-source: /images/ui/window
|
||||
image-border: 6
|
||||
|
||||
ToolTipLabel
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
font: verdana-11px-rounded
|
||||
text: Custom Player List
|
||||
tooltip: Double click on the list below to add new player.
|
||||
|
||||
AddPlayer
|
||||
id: addPanel
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
PlayerList
|
||||
id: playerList
|
||||
anchors.fill: prev
|
||||
|
||||
Conditions < Panel
|
||||
size: 280 170
|
||||
padding: 3
|
||||
image-source: /images/ui/window
|
||||
image-border: 6
|
||||
|
||||
Label
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
font: verdana-11px-rounded
|
||||
text: Player Conditions
|
||||
|
||||
Panel
|
||||
id: box
|
||||
anchors.fill: parent
|
||||
margin-top: 16
|
||||
padding: 5
|
||||
padding-top: 3
|
||||
layout:
|
||||
type: grid
|
||||
cell-size: 128 31
|
||||
cell-spacing: 5
|
||||
num-columns: 2
|
||||
|
||||
FriendHealer < MainWindow
|
||||
!text: tr('Friend Healer')
|
||||
size: 512 390
|
||||
padding-top: 30
|
||||
@onEscape: self:hide()
|
||||
|
||||
Conditions
|
||||
id: conditions
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
|
||||
TargetSettings
|
||||
id: targetSettings
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 10
|
||||
anchors.left: prev.left
|
||||
|
||||
Priority
|
||||
id: priority
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
||||
CustomList
|
||||
id: customList
|
||||
anchors.top: priority.bottom
|
||||
margin-top: 10
|
||||
anchors.left: priority.left
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 8
|
||||
|
||||
Button
|
||||
id: closeButton
|
||||
!text: tr('Close')
|
||||
font: cipsoftFont
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
@onClick: self:getParent():hide()
|
||||
@@ -0,0 +1,5 @@
|
||||
onAttackingCreatureChange(function(creature, OldCreature)
|
||||
if creature and creature:isNpc() and distanceFromPlayer(creature:getPosition()) <= 3 then
|
||||
CaveBot.Conversation("hi", "trade")
|
||||
end
|
||||
end)
|
||||
351
modules/game_bot/default_configs/vBot_4.7/vBot/playerlist.lua
Normal file
351
modules/game_bot/default_configs/vBot_4.7/vBot/playerlist.lua
Normal file
@@ -0,0 +1,351 @@
|
||||
--[[
|
||||
configuration for check players
|
||||
example made on server Gunzodus
|
||||
|
||||
example link for player overview:
|
||||
https://www.gunzodus.net/character/show/Sir_Vithrax
|
||||
|
||||
*note that space in character name was replaced with underscore (_) - this character will be important
|
||||
|
||||
in this case:
|
||||
link = "https://www.gunzodus.net/character/show/" -- everything with all the characters up to the start of the name
|
||||
spacing = "_" -- space replacement in character name
|
||||
]]
|
||||
|
||||
local link = "https://www.gunzodus.net/character/show/"
|
||||
local spacing = "_"
|
||||
|
||||
|
||||
|
||||
-- do not edit below
|
||||
setDefaultTab("Main")
|
||||
local tabs = {"Friends", "Enemies", "BlackList"}
|
||||
local panelName = "playerList"
|
||||
local colors = {"#03C04A", "#fc4c4e", "orange"}
|
||||
|
||||
if not storage[panelName] then
|
||||
storage[panelName] = {
|
||||
enemyList = {},
|
||||
friendList = {},
|
||||
blackList = {},
|
||||
groupMembers = true,
|
||||
outfits = false,
|
||||
marks = false,
|
||||
highlight = false
|
||||
}
|
||||
end
|
||||
|
||||
local config = storage[panelName]
|
||||
local playerTables = {config.friendList, config.enemyList, config.blackList}
|
||||
|
||||
-- functions
|
||||
local function clearCachedPlayers()
|
||||
CachedFriends = {}
|
||||
CachedEnemies = {}
|
||||
end
|
||||
|
||||
local refreshStatus = function()
|
||||
for _, spec in ipairs(getSpectators()) do
|
||||
if spec:isPlayer() and not spec:isLocalPlayer() then
|
||||
if config.outfits then
|
||||
local specOutfit = spec:getOutfit()
|
||||
if isFriend(spec:getName()) then
|
||||
if config.highlight then
|
||||
spec:setMarked('#0000FF')
|
||||
end
|
||||
specOutfit.head = 88
|
||||
specOutfit.body = 88
|
||||
specOutfit.legs = 88
|
||||
specOutfit.feet = 88
|
||||
if storage.BOTserver.outfit then
|
||||
local voc = vBot.BotServerMembers[spec:getName()]
|
||||
specOutfit.addons = 3
|
||||
if voc == 1 then
|
||||
specOutfit.type = 131
|
||||
elseif voc == 2 then
|
||||
specOutfit.type = 129
|
||||
elseif voc == 3 then
|
||||
specOutfit.type = 130
|
||||
elseif voc == 4 then
|
||||
specOutfit.type = 144
|
||||
end
|
||||
end
|
||||
spec:setOutfit(specOutfit)
|
||||
elseif isEnemy(spec:getName()) then
|
||||
if config.highlight then
|
||||
spec:setMarked('#FF0000')
|
||||
end
|
||||
specOutfit.head = 94
|
||||
specOutfit.body = 94
|
||||
specOutfit.legs = 94
|
||||
specOutfit.feet = 94
|
||||
spec:setOutfit(specOutfit)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
refreshStatus()
|
||||
|
||||
local checkStatus = function(creature)
|
||||
if not creature:isPlayer() or creature:isLocalPlayer() then return end
|
||||
|
||||
local specName = creature:getName()
|
||||
local specOutfit = creature:getOutfit()
|
||||
|
||||
if isFriend(specName) then
|
||||
if config.highlight then
|
||||
creature:setMarked('#0000FF')
|
||||
end
|
||||
if config.outfits then
|
||||
specOutfit.head = 88
|
||||
specOutfit.body = 88
|
||||
specOutfit.legs = 88
|
||||
specOutfit.feet = 88
|
||||
if storage.BOTserver.outfit then
|
||||
local voc = vBot.BotServerMembers[creature:getName()]
|
||||
specOutfit.addons = 3
|
||||
if voc == 1 then
|
||||
specOutfit.type = 131
|
||||
elseif voc == 2 then
|
||||
specOutfit.type = 129
|
||||
elseif voc == 3 then
|
||||
specOutfit.type = 130
|
||||
elseif voc == 4 then
|
||||
specOutfit.type = 144
|
||||
end
|
||||
end
|
||||
creature:setOutfit(specOutfit)
|
||||
end
|
||||
elseif isEnemy(specName) then
|
||||
if config.highlight then
|
||||
creature:setMarked('#FF0000')
|
||||
end
|
||||
if config.outfits then
|
||||
specOutfit.head = 94
|
||||
specOutfit.body = 94
|
||||
specOutfit.legs = 94
|
||||
specOutfit.feet = 94
|
||||
creature:setOutfit(specOutfit)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
local ListWindow = UI.createWindow('PlayerListWindow', rootWidget)
|
||||
ListWindow:hide()
|
||||
|
||||
UI.Button("Player Lists", function()
|
||||
ListWindow:show()
|
||||
ListWindow:raise()
|
||||
ListWindow:focus()
|
||||
end)
|
||||
|
||||
-- settings
|
||||
ListWindow.settings.Members:setChecked(config.groupMembers)
|
||||
ListWindow.settings.Members.onClick = function(widget)
|
||||
config.groupMembers = not config.groupMembers
|
||||
if not config.groupMembers then
|
||||
clearCachedPlayers()
|
||||
end
|
||||
refreshStatus()
|
||||
widget:setChecked(config.groupMembers)
|
||||
end
|
||||
ListWindow.settings.Outfit:setChecked(config.outfits)
|
||||
ListWindow.settings.Outfit.onClick = function(widget)
|
||||
config.outfits = not config.outfits
|
||||
widget:setChecked(config.outfits)
|
||||
refreshStatus()
|
||||
end
|
||||
ListWindow.settings.NeutralsAreEnemy:setChecked(config.marks)
|
||||
ListWindow.settings.NeutralsAreEnemy.onClick = function(widget)
|
||||
config.marks = not config.marks
|
||||
widget:setChecked(config.marks)
|
||||
end
|
||||
ListWindow.settings.Highlight:setChecked(config.highlight)
|
||||
ListWindow.settings.Highlight.onClick = function(widget)
|
||||
config.highlight = not config.highlight
|
||||
widget:setChecked(config.highlight)
|
||||
end
|
||||
|
||||
ListWindow.settings.AutoAdd:setChecked(config.autoAdd)
|
||||
ListWindow.settings.AutoAdd.onClick = function(widget)
|
||||
config.autoAdd = not config.autoAdd
|
||||
widget:setChecked(config.autoAdd)
|
||||
end
|
||||
|
||||
local TabBar = ListWindow.tmpTabBar
|
||||
TabBar:setContentWidget(ListWindow.tmpTabContent)
|
||||
local blacklistList
|
||||
|
||||
for v = 1, 3 do
|
||||
local listPanel = g_ui.createWidget("tPanel") -- Creates Panel
|
||||
local playerList = playerTables[v]
|
||||
listPanel:setId(tabs[v].."Tab")
|
||||
TabBar:addTab(tabs[v], listPanel)
|
||||
|
||||
-- elements
|
||||
local addButton = listPanel.add
|
||||
local nameTab = listPanel.name
|
||||
local list = listPanel.list
|
||||
if v == 3 then
|
||||
blacklistList = list
|
||||
end
|
||||
|
||||
for i, name in ipairs(playerList) do
|
||||
local label = UI.createWidget("PlayerLabel", list)
|
||||
label:setText(name)
|
||||
label.remove.onClick = function()
|
||||
table.remove(playerList, table.find(playerList, name))
|
||||
label:destroy()
|
||||
clearCachedPlayers()
|
||||
refreshStatus()
|
||||
end
|
||||
label.onMouseRelease = function(widget, mousePos, mouseButton)
|
||||
if mouseButton == 2 then
|
||||
local child = rootWidget:recursiveGetChildByPos(mousePos)
|
||||
if child == widget then
|
||||
local menu = g_ui.createWidget('PopupMenu')
|
||||
menu:setId("blzMenu")
|
||||
menu:setGameMenu(true)
|
||||
menu:addOption('Check Player', function()
|
||||
local name = widget:getText():gsub(" ", spacing)
|
||||
g_platform.openUrl(link..name)
|
||||
end, "")
|
||||
menu:addOption('Copy Name', function()
|
||||
g_window.setClipboardText(widget:getText())
|
||||
end, "")
|
||||
menu:display(mousePos)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local tabButton = TabBar.buttonsPanel:getChildren()[v]
|
||||
|
||||
tabButton.onStyleApply = function(widget)
|
||||
if TabBar:getCurrentTab() == widget then
|
||||
widget:setColor(colors[v])
|
||||
end
|
||||
end
|
||||
|
||||
-- callbacks
|
||||
addButton.onClick = function()
|
||||
local names = string.split(nameTab:getText(), ",")
|
||||
|
||||
if #names == 0 then
|
||||
warn("vBot[PlayerList]: Name is missing!")
|
||||
return
|
||||
end
|
||||
|
||||
for i=1,#names do
|
||||
local name = names[i]:trim()
|
||||
if name:len() == 0 then
|
||||
warn("vBot[PlayerList]: Name is missing!")
|
||||
else
|
||||
if not table.find(playerList, name) then
|
||||
table.insert(playerList, name)
|
||||
local label = UI.createWidget("PlayerLabel", list)
|
||||
label:setText(name)
|
||||
label.remove.onClick = function()
|
||||
table.remove(playerList, table.find(playerList, name))
|
||||
label:destroy()
|
||||
end
|
||||
label.onMouseRelease = function(widget, mousePos, mouseButton)
|
||||
if mouseButton == 2 then
|
||||
local child = rootWidget:recursiveGetChildByPos(mousePos)
|
||||
if child == widget then
|
||||
local menu = g_ui.createWidget('PopupMenu')
|
||||
menu:setId("blzMenu")
|
||||
menu:setGameMenu(true)
|
||||
menu:addOption('Check Player', function()
|
||||
local name = widget:getText():gsub(" ", "_")
|
||||
local link = "https://www.gunzodus.net/character/show/"
|
||||
g_platform.openUrl(link..name)
|
||||
end, "")
|
||||
menu:addOption('Copy Name', function()
|
||||
g_window.setClipboardText(widget:getText())
|
||||
end, "")
|
||||
menu:display(mousePos)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
nameTab:setText("")
|
||||
else
|
||||
warn("vBot[PlayerList]: Player ".. name .." is already added!")
|
||||
nameTab:setText("")
|
||||
end
|
||||
clearCachedPlayers()
|
||||
refreshStatus()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
nameTab.onKeyPress = function(widget, keyCode, keyboardModifiers)
|
||||
if keyCode ~= 5 then
|
||||
return false
|
||||
end
|
||||
addButton.onClick()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function addBlackListPlayer(name)
|
||||
if table.find(config.blackList, name) then return end
|
||||
|
||||
table.insert(config.blackList, name)
|
||||
local label = UI.createWidget("PlayerLabel", blacklistList)
|
||||
label:setText(name)
|
||||
label.remove.onClick = function()
|
||||
table.remove(playerList, table.find(playerList, name))
|
||||
label:destroy()
|
||||
end
|
||||
label.onMouseRelease = function(widget, mousePos, mouseButton)
|
||||
if mouseButton == 2 then
|
||||
local child = rootWidget:recursiveGetChildByPos(mousePos)
|
||||
if child == widget then
|
||||
local menu = g_ui.createWidget('PopupMenu')
|
||||
menu:setId("blzMenu")
|
||||
menu:setGameMenu(true)
|
||||
menu:addOption('Check Player', function()
|
||||
local name = widget:getText():gsub(" ", "_")
|
||||
local link = "https://www.gunzodus.net/character/show/"
|
||||
g_platform.openUrl(link..name)
|
||||
end, "")
|
||||
menu:addOption('Copy Name', function()
|
||||
g_window.setClipboardText(widget:getText())
|
||||
end, "")
|
||||
menu:display(mousePos)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
onTextMessage(function(mode,text)
|
||||
if not config.autoAdd then return end
|
||||
if CaveBot.isOff() or TargetBot.isOff() then return end
|
||||
if not text:find("Warning! The murder of") then return end
|
||||
|
||||
text = string.split(text, "Warning! The murder of ")[1]
|
||||
text = string.split(text, " was not justified.")[1]
|
||||
|
||||
addBlackListPlayer(text)
|
||||
end)
|
||||
|
||||
onCreatureAppear(function(creature)
|
||||
checkStatus(creature)
|
||||
end)
|
||||
|
||||
onPlayerPositionChange(function(x,y)
|
||||
if x.z ~= y.z then
|
||||
schedule(20, function()
|
||||
refreshStatus()
|
||||
end)
|
||||
end
|
||||
end)
|
||||
151
modules/game_bot/default_configs/vBot_4.7/vBot/playerlist.otui
Normal file
151
modules/game_bot/default_configs/vBot_4.7/vBot/playerlist.otui
Normal file
@@ -0,0 +1,151 @@
|
||||
PlayerLabel < UIWidget
|
||||
background-color: alpha
|
||||
text-offset: 3 1
|
||||
focusable: true
|
||||
height: 16
|
||||
font: verdana-11px-rounded
|
||||
text-align: left
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
Button
|
||||
id: remove
|
||||
!text: tr('X')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 14
|
||||
height: 14
|
||||
margin-right: 15
|
||||
text-align: center
|
||||
text-offset: 0 1
|
||||
tooltip: Remove profile from the list.
|
||||
|
||||
SettingCheckBox < CheckBox
|
||||
text-wrap: true
|
||||
text-auto-resize: true
|
||||
margin-top: 3
|
||||
font: verdana-11px-rounded
|
||||
|
||||
Settings < FlatPanel
|
||||
padding: 6
|
||||
layout:
|
||||
type: verticalBox
|
||||
|
||||
Label
|
||||
text: Additional Settings
|
||||
text-align: center
|
||||
font: verdana-11px-rounded
|
||||
|
||||
HorizontalSeparator
|
||||
|
||||
SettingCheckBox
|
||||
id: Members
|
||||
margin-top: 6
|
||||
text: Consider group members as friends.
|
||||
|
||||
SettingCheckBox
|
||||
id: Outfit
|
||||
text: Color listed player outfits to red or blue.
|
||||
|
||||
SettingCheckBox
|
||||
id: NeutralsAreEnemy
|
||||
text: Consider every non friend player as enemy.
|
||||
|
||||
SettingCheckBox
|
||||
id: Highlight
|
||||
text: Hightlight listed players in red or blue color.
|
||||
|
||||
SettingCheckBox
|
||||
id: AutoAdd
|
||||
text: Automatically add killed players while cave botting to blacklist.
|
||||
|
||||
tPanel < Panel
|
||||
margin: 3
|
||||
padding: 3
|
||||
|
||||
TextList
|
||||
id: list
|
||||
height: 200
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
vertical-scrollbar: listScrollBar
|
||||
|
||||
VerticalScrollBar
|
||||
id: listScrollBar
|
||||
anchors.top: list.top
|
||||
anchors.bottom: list.bottom
|
||||
anchors.right: list.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
TextEdit
|
||||
id: name
|
||||
anchors.top: list.bottom
|
||||
margin-top: 3
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Button
|
||||
id: add
|
||||
text: Add Player
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
font: verdana-11px-rounded
|
||||
|
||||
PlayerListWindow < MainWindow
|
||||
!text: tr('Player List')
|
||||
size: 405 356
|
||||
@onEscape: self:hide()
|
||||
|
||||
TabBar
|
||||
id: tmpTabBar
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
width: 180
|
||||
|
||||
FlatPanel
|
||||
id: tmpTabContent
|
||||
anchors.top: tmpTabBar.bottom
|
||||
anchors.left: parent.left
|
||||
width: 180
|
||||
anchors.bottom: separator.top
|
||||
margin-bottom: 5
|
||||
|
||||
VerticalSeparator
|
||||
id: verticalSep
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: separator.top
|
||||
margin-bottom: 5
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
Settings
|
||||
id: settings
|
||||
anchors.left: prev.right
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: next.top
|
||||
margin: 3
|
||||
margin-left: 6
|
||||
margin-bottom: 4
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 8
|
||||
|
||||
Button
|
||||
id: closeButton
|
||||
!text: tr('Close')
|
||||
font: cipsoftFont
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
margin-top: 15
|
||||
margin-right: 5
|
||||
@onClick: self:getParent():hide()
|
||||
287
modules/game_bot/default_configs/vBot_4.7/vBot/pushmax.lua
Normal file
287
modules/game_bot/default_configs/vBot_4.7/vBot/pushmax.lua
Normal file
@@ -0,0 +1,287 @@
|
||||
---@diagnostic disable: undefined-global
|
||||
setDefaultTab("Main")
|
||||
|
||||
local panelName = "pushmax"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 19
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('PUSHMAX')
|
||||
|
||||
Button
|
||||
id: push
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Setup
|
||||
|
||||
]])
|
||||
ui:setId(panelName)
|
||||
|
||||
if not storage[panelName] then
|
||||
storage[panelName] = {
|
||||
enabled = true,
|
||||
pushDelay = 1060,
|
||||
pushMaxRuneId = 3188,
|
||||
mwallBlockId = 2128,
|
||||
pushMaxKey = "PageUp"
|
||||
}
|
||||
end
|
||||
|
||||
local config = storage[panelName]
|
||||
|
||||
ui.title:setOn(config.enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
config.enabled = not config.enabled
|
||||
widget:setOn(config.enabled)
|
||||
end
|
||||
|
||||
ui.push.onClick = function(widget)
|
||||
pushWindow:show()
|
||||
pushWindow:raise()
|
||||
pushWindow:focus()
|
||||
end
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
pushWindow = UI.createWindow('PushMaxWindow', rootWidget)
|
||||
pushWindow:hide()
|
||||
|
||||
pushWindow.closeButton.onClick = function(widget)
|
||||
pushWindow:hide()
|
||||
end
|
||||
|
||||
local updateDelayText = function()
|
||||
pushWindow.delayText:setText("Push Delay: ".. config.pushDelay)
|
||||
end
|
||||
updateDelayText()
|
||||
pushWindow.delay.onValueChange = function(scroll, value)
|
||||
config.pushDelay = value
|
||||
updateDelayText()
|
||||
end
|
||||
pushWindow.delay:setValue(config.pushDelay)
|
||||
|
||||
pushWindow.runeId.onItemChange = function(widget)
|
||||
config.pushMaxRuneId = widget:getItemId()
|
||||
end
|
||||
pushWindow.runeId:setItemId(config.pushMaxRuneId)
|
||||
pushWindow.mwallId.onItemChange = function(widget)
|
||||
config.mwallBlockId = widget:getItemId()
|
||||
end
|
||||
pushWindow.mwallId:setItemId(config.mwallBlockId)
|
||||
|
||||
pushWindow.hotkey.onTextChange = function(widget, text)
|
||||
config.pushMaxKey = text
|
||||
end
|
||||
pushWindow.hotkey:setText(config.pushMaxKey)
|
||||
end
|
||||
|
||||
|
||||
-- variables for config
|
||||
local fieldTable = {2118, 105, 2122}
|
||||
local cleanTile = nil
|
||||
|
||||
-- scripts
|
||||
|
||||
local targetTile
|
||||
local pushTarget
|
||||
|
||||
local resetData = function()
|
||||
for i, tile in pairs(g_map.getTiles(posz())) do
|
||||
if tile:getText() == "TARGET" or tile:getText() == "DEST" or tile:getText() == "CLEAR" then
|
||||
tile:setText('')
|
||||
end
|
||||
end
|
||||
pushTarget = nil
|
||||
targetTile = nil
|
||||
cleanTile = nil
|
||||
end
|
||||
|
||||
local getCreatureById = function(id)
|
||||
for i, spec in ipairs(getSpectators()) do
|
||||
if spec:getId() == id then
|
||||
return spec
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local isNotOk = function(t,tile)
|
||||
local tileItems = {}
|
||||
|
||||
for i, item in pairs(tile:getItems()) do
|
||||
table.insert(tileItems, item:getId())
|
||||
end
|
||||
for i, field in ipairs(t) do
|
||||
if table.find(tileItems, field) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local isOk = function(a,b)
|
||||
return getDistanceBetween(a,b) == 1
|
||||
end
|
||||
|
||||
-- to mark
|
||||
local hold = 0
|
||||
onKeyDown(function(keys)
|
||||
if not config.enabled then return end
|
||||
if keys ~= config.pushMaxKey then return end
|
||||
hold = now
|
||||
local tile = getTileUnderCursor()
|
||||
if not tile then return end
|
||||
if pushTarget and targetTile then
|
||||
resetData()
|
||||
return
|
||||
end
|
||||
local creature = tile:getCreatures()[1]
|
||||
if not pushTarget and creature then
|
||||
pushTarget = creature
|
||||
if pushTarget then
|
||||
tile:setText('TARGET')
|
||||
pushTarget:setMarked('#00FF00')
|
||||
end
|
||||
elseif not targetTile and pushTarget then
|
||||
if pushTarget and getDistanceBetween(tile:getPosition(),pushTarget:getPosition()) ~= 1 then
|
||||
resetData()
|
||||
return
|
||||
else
|
||||
tile:setText('DEST')
|
||||
targetTile = tile
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- mark tile to throw anything from it
|
||||
onKeyPress(function(keys)
|
||||
if not config.enabled then return end
|
||||
if keys ~= config.pushMaxKey then return end
|
||||
local tile = getTileUnderCursor()
|
||||
if not tile then return end
|
||||
|
||||
if (hold - now) < -2500 then
|
||||
if cleanTile and tile ~= cleanTile then
|
||||
resetData()
|
||||
elseif not cleanTile then
|
||||
cleanTile = tile
|
||||
tile:setText("CLEAR")
|
||||
end
|
||||
end
|
||||
hold = 0
|
||||
end)
|
||||
|
||||
onCreaturePositionChange(function(creature, newPos, oldPos)
|
||||
if not config.enabled then return end
|
||||
if creature == player then
|
||||
resetData()
|
||||
end
|
||||
if not pushTarget or not targetTile then return end
|
||||
if creature == pushTarget and newPos == targetTile then
|
||||
resetData()
|
||||
end
|
||||
end)
|
||||
|
||||
macro(50, function()
|
||||
if not config.enabled then return end
|
||||
|
||||
local pushDelay = tonumber(config.pushDelay)
|
||||
local rune = tonumber(config.pushMaxRuneId)
|
||||
local customMwall = config.mwallBlockId
|
||||
|
||||
if cleanTile then
|
||||
local tilePos = cleanTile:getPosition()
|
||||
local pPos = player:getPosition()
|
||||
if not isOk(tilePos, pPos) then
|
||||
resetData()
|
||||
return
|
||||
end
|
||||
|
||||
if not cleanTile:hasCreature() then return end
|
||||
local tiles = getNearTiles(tilePos)
|
||||
local destTile
|
||||
local forbidden = {}
|
||||
-- unfortunately double loop
|
||||
for i, tile in pairs(tiles) do
|
||||
local minimapColor = g_map.getMinimapColor(tile:getPosition())
|
||||
local stairs = (minimapColor >= 210 and minimapColor <= 213)
|
||||
if stairs then
|
||||
table.insert(forbidden, tile:getPosition())
|
||||
end
|
||||
end
|
||||
for i, tile in pairs(tiles) do
|
||||
local minimapColor = g_map.getMinimapColor(tile:getPosition())
|
||||
local stairs = (minimapColor >= 210 and minimapColor <= 213)
|
||||
if tile:isWalkable() and not isNotOk(fieldTable, tile) and not tile:hasCreature() and not stairs then
|
||||
local tooClose = false
|
||||
if #forbidden ~= 0 then
|
||||
for i=1,#forbidden do
|
||||
local pos = forbidden[i]
|
||||
if isOk(pos, tile:getPosition()) then
|
||||
tooClose = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if not tooClose then
|
||||
destTile = tile
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not destTile then return end
|
||||
local parcel = cleanTile:getCreatures()[1]
|
||||
if parcel then
|
||||
test()
|
||||
g_game.move(parcel,destTile:getPosition())
|
||||
delay(2000)
|
||||
end
|
||||
else
|
||||
if not pushTarget or not targetTile then return end
|
||||
local tilePos = targetTile:getPosition()
|
||||
local targetPos = pushTarget:getPosition()
|
||||
if not isOk(tilePos,targetPos) then return end
|
||||
|
||||
local tileOfTarget = g_map.getTile(targetPos)
|
||||
|
||||
if not targetTile:isWalkable() then
|
||||
local topThing = targetTile:getTopUseThing():getId()
|
||||
if topThing == 2129 or topThing == 2130 or topThing == customMwall then
|
||||
if targetTile:getTimer() < pushDelay+500 then
|
||||
vBot.isUsing = true
|
||||
schedule(pushDelay+700, function()
|
||||
vBot.isUsing = false
|
||||
end)
|
||||
end
|
||||
if targetTile:getTimer() > pushDelay then
|
||||
return
|
||||
end
|
||||
else
|
||||
return resetData()
|
||||
end
|
||||
end
|
||||
|
||||
if not tileOfTarget:getTopUseThing():isNotMoveable() and targetTile:getTimer() < pushDelay+500 then
|
||||
return useWith(rune, pushTarget)
|
||||
end
|
||||
if isNotOk(fieldTable, targetTile) then
|
||||
if targetTile:canShoot() then
|
||||
return useWith(3148, targetTile:getTopUseThing())
|
||||
else
|
||||
return
|
||||
end
|
||||
end
|
||||
g_game.move(pushTarget,tilePos)
|
||||
delay(2000)
|
||||
end
|
||||
end)
|
||||
85
modules/game_bot/default_configs/vBot_4.7/vBot/pushmax.otui
Normal file
85
modules/game_bot/default_configs/vBot_4.7/vBot/pushmax.otui
Normal file
@@ -0,0 +1,85 @@
|
||||
PushMaxWindow < MainWindow
|
||||
!text: tr('Pushmax Settings')
|
||||
size: 200 240
|
||||
@onEscape: self:hide()
|
||||
|
||||
BotLabel
|
||||
id: delayText
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
|
||||
HorizontalScrollBar
|
||||
id: delay
|
||||
anchors.left: delayText.left
|
||||
anchors.right: delayText.right
|
||||
anchors.top: delayText.bottom
|
||||
margin-top: 5
|
||||
minimum: 800
|
||||
maximum: 2000
|
||||
step: 10
|
||||
|
||||
Label
|
||||
id: label2
|
||||
anchors.top: delay.bottom
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
text: Custom WallID
|
||||
margin-top: 5
|
||||
|
||||
Label
|
||||
id: label3
|
||||
anchors.top: delay.bottom
|
||||
anchors.right: parent.horizontalCenter
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
text: VS AntiPush
|
||||
margin-top: 5
|
||||
|
||||
BotItem
|
||||
id: runeId
|
||||
anchors.horizontalCenter: label3.horizontalCenter
|
||||
anchors.top: label3.bottom
|
||||
margin-top: 5
|
||||
|
||||
BotItem
|
||||
id: mwallId
|
||||
anchors.horizontalCenter: label2.horizontalCenter
|
||||
anchors.top: label2.bottom
|
||||
margin-top: 5
|
||||
|
||||
Label
|
||||
id: label1
|
||||
anchors.top: mwallId.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 10
|
||||
text-align: center
|
||||
text: Hotkey for PUSHMAX
|
||||
|
||||
TextEdit
|
||||
id: hotkey
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: label1.bottom
|
||||
margin-top: 5
|
||||
text-align: center
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 8
|
||||
|
||||
Button
|
||||
id: closeButton
|
||||
!text: tr('Close')
|
||||
font: cipsoftFont
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
margin-top: 15
|
||||
margin-right: 5
|
||||
@@ -0,0 +1,58 @@
|
||||
local quiverSlot = modules.game_inventory.inventoryWindow:recursiveGetChildById('slot5')
|
||||
local label = quiverSlot.count
|
||||
|
||||
label = label or g_ui.loadUIFromString([[
|
||||
Label
|
||||
id: count
|
||||
color: #bfbfbf
|
||||
font: verdana-11px-rounded
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
text-align: right
|
||||
margin-right: 3
|
||||
margin-left: 3
|
||||
text:
|
||||
]], quiverSlot)
|
||||
|
||||
|
||||
function getQuiverAmount()
|
||||
-- old tibia
|
||||
if g_game.getClientVersion() < 1000 then return end
|
||||
|
||||
|
||||
local isQuiverEquipped = getRight() and getRight():isContainer() or false
|
||||
local quiver = isQuiverEquipped and getContainerByItem(getRight():getId())
|
||||
local count = 0
|
||||
|
||||
if quiver then
|
||||
for i, item in ipairs(quiver:getItems()) do
|
||||
count = count + item:getCount()
|
||||
end
|
||||
else
|
||||
return label:setText("")
|
||||
end
|
||||
|
||||
return label:setText(count)
|
||||
end
|
||||
getQuiverAmount()
|
||||
|
||||
onContainerOpen(function(container, previousContainer)
|
||||
getQuiverAmount()
|
||||
end)
|
||||
|
||||
onContainerClose(function(container)
|
||||
getQuiverAmount()
|
||||
end)
|
||||
|
||||
onAddItem(function(container, slot, item, oldItem)
|
||||
getQuiverAmount()
|
||||
end)
|
||||
|
||||
onRemoveItem(function(container, slot, item)
|
||||
getQuiverAmount()
|
||||
end)
|
||||
|
||||
onContainerUpdateItem(function(container, slot, item, oldItem)
|
||||
getQuiverAmount()
|
||||
end)
|
||||
@@ -0,0 +1,91 @@
|
||||
if voc() == 2 or voc() == 12 then
|
||||
local bows = { 3350, 31581, 27455, 8027, 20082, 36664, 7438, 28718, 36665, 14246, 19362, 35518, 34150, 29417, 9378, 16164, 22866, 12733, 8029, 20083, 20084, 8026, 8028, 34088}
|
||||
local xbows = { 30393, 3349, 27456, 20085, 16163, 5947, 8021, 14247, 22867, 8023, 22711, 19356, 20086, 20087, 34089}
|
||||
local arrows = { 16143, 763, 761, 7365, 3448, 762, 21470, 7364, 14251, 3447, 3449, 15793, 25757, 774, 35901 }
|
||||
local bolts = { 6528, 7363, 3450, 16141, 25758, 14252, 3446, 16142, 35902 }
|
||||
local hold = false
|
||||
|
||||
onContainerOpen(function(container, previousContainer)
|
||||
hold = false
|
||||
end)
|
||||
|
||||
onContainerClose(function(container)
|
||||
hold = false
|
||||
end)
|
||||
|
||||
onAddItem(function(container, slot, item, oldItem)
|
||||
hold = false
|
||||
end)
|
||||
|
||||
onRemoveItem(function(container, slot, item)
|
||||
hold = false
|
||||
end)
|
||||
|
||||
onContainerUpdateItem(function(container, slot, item, oldItem)
|
||||
hold = false
|
||||
end)
|
||||
|
||||
|
||||
|
||||
local function manageQuiver(isBowEquipped, quiverContainer)
|
||||
local ammo = isBowEquipped and arrows or bolts
|
||||
local dest = nil
|
||||
local containers = getContainers()
|
||||
for i, container in ipairs(containers) do
|
||||
if container ~= quiverContainer and not containerIsFull(container) then
|
||||
local cname = container:getName():lower()
|
||||
if not cname:find("loot") and (cname:find("backpack") or cname:find("bag") or cname:find("chess")) then
|
||||
dest = container
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- clearing
|
||||
if dest then
|
||||
for i, item in ipairs(quiverContainer:getItems()) do
|
||||
if not table.find(ammo, item:getId()) then
|
||||
local pos = dest:getSlotPosition(dest:getItemsCount())
|
||||
return g_game.move(item, pos, item:getCount())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not containerIsFull(quiverContainer) then
|
||||
for i, container in ipairs(containers) do
|
||||
if container ~= quiverContainer then
|
||||
for j, item in ipairs(container:getItems()) do
|
||||
if table.find(ammo, item:getId()) then
|
||||
local pos = quiverContainer:getSlotPosition(quiverContainer:getItemsCount())
|
||||
return g_game.move(item, pos, item:getCount())
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
UI.Separator()
|
||||
macro(100, "Quiver Manager", function()
|
||||
if hold then return end -- do nothing if nothing to do
|
||||
local hand = getLeft() and getLeft():getId()
|
||||
local quiverEquipped = getRight() and getRight():isContainer()
|
||||
|
||||
if not hand then return end
|
||||
if not quiverEquipped then return end
|
||||
|
||||
local quiverContainer = getContainerByItem(getRight():getId())
|
||||
if not quiverContainer then return end
|
||||
|
||||
local isBowEquipped = getLeft() and table.find(bows, hand) and true or false
|
||||
if not isBowEquipped then
|
||||
if not table.find(xbows, hand) then
|
||||
return -- neither bow and xbow is equipped
|
||||
end
|
||||
end
|
||||
|
||||
if manageQuiver(isBowEquipped, quiverContainer) then -- if true then it didn't do anything
|
||||
hold = true
|
||||
end
|
||||
end)
|
||||
end
|
||||
192
modules/game_bot/default_configs/vBot_4.7/vBot/siolist.otui
Normal file
192
modules/game_bot/default_configs/vBot_4.7/vBot/siolist.otui
Normal file
@@ -0,0 +1,192 @@
|
||||
VocationPanel < Panel
|
||||
padding: 3
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 6
|
||||
size: 190 55
|
||||
|
||||
Label
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
text: for BotServer, Heal only:
|
||||
|
||||
BotSwitch
|
||||
id: ED
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
text: Druids
|
||||
|
||||
BotSwitch
|
||||
id: MS
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
text: Sorcerers
|
||||
|
||||
BotSwitch
|
||||
id: EK
|
||||
anchors.bottom: ED.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
text: Knights
|
||||
|
||||
BotSwitch
|
||||
id: RP
|
||||
anchors.bottom: ED.top
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
text: Paladins
|
||||
|
||||
|
||||
|
||||
SioListWindow < MainWindow
|
||||
!text: tr('Healer Options')
|
||||
size: 220 360
|
||||
@onEscape: self:hide()
|
||||
|
||||
BotSwitch
|
||||
id: exuraSio
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
text: Exura Sio
|
||||
margin-right: 2
|
||||
|
||||
BotSwitch
|
||||
id: exuraGranSio
|
||||
anchors.top: parent.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
text: Exura Gran Sio
|
||||
margin-left: 2
|
||||
|
||||
BotSwitch
|
||||
id: exuraMasRes
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text: Exura Gran Mas Res
|
||||
margin-top: 3
|
||||
|
||||
BotSwitch
|
||||
id: spell
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text: Custom Spell
|
||||
margin-top: 3
|
||||
text-align: center
|
||||
|
||||
BotTextEdit
|
||||
id: spellName
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 10
|
||||
|
||||
BotItem
|
||||
id: itemId
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
margin-top: 10
|
||||
|
||||
BotSwitch
|
||||
id: item
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: prev.verticalCenter
|
||||
text-align: center
|
||||
text: Item Healing
|
||||
margin-left: 2
|
||||
|
||||
BotLabel
|
||||
id: distText
|
||||
anchors.top: itemId.verticalCenter
|
||||
anchors.left: itemId.right
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: itemId.bottom
|
||||
text-align: center
|
||||
text: Max Distance
|
||||
|
||||
HorizontalScrollBar
|
||||
id: Distance
|
||||
anchors.left: parent.left
|
||||
anchors.top: itemId.bottom
|
||||
anchors.right: parent.right
|
||||
margin-top: 3
|
||||
minimum: 1
|
||||
maximum: 10
|
||||
step: 1
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 8
|
||||
|
||||
BotLabel
|
||||
id: manaInfo
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
text-align: center
|
||||
margin-top: 5
|
||||
|
||||
HorizontalScrollBar
|
||||
id: minMana
|
||||
anchors.left: spellName.left
|
||||
anchors.right: spellName.right
|
||||
anchors.top: manaInfo.bottom
|
||||
margin-top: 2
|
||||
minimum: 1
|
||||
maximum: 100
|
||||
step: 1
|
||||
|
||||
BotLabel
|
||||
id: friendHp
|
||||
anchors.left: spellName.left
|
||||
anchors.right: spellName.right
|
||||
anchors.top: prev.bottom
|
||||
text-align: center
|
||||
margin-top: 5
|
||||
|
||||
HorizontalScrollBar
|
||||
id: minFriendHp
|
||||
anchors.left: spellName.left
|
||||
anchors.right: spellName.right
|
||||
anchors.top: friendHp.bottom
|
||||
margin-top: 2
|
||||
minimum: 1
|
||||
maximum: 100
|
||||
step: 1
|
||||
|
||||
VocationPanel
|
||||
id: vocation
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 6
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 8
|
||||
|
||||
Button
|
||||
id: closeButton
|
||||
!text: tr('Close')
|
||||
font: cipsoftFont
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
margin-top: 15
|
||||
margin-right: 5
|
||||
24
modules/game_bot/default_configs/vBot_4.7/vBot/spy_level.lua
Normal file
24
modules/game_bot/default_configs/vBot_4.7/vBot/spy_level.lua
Normal file
@@ -0,0 +1,24 @@
|
||||
-- config
|
||||
|
||||
local keyUp = "="
|
||||
local keyDown = "-"
|
||||
setDefaultTab("Tools")
|
||||
|
||||
-- script
|
||||
|
||||
local lockedLevel = pos().z
|
||||
|
||||
onPlayerPositionChange(function(newPos, oldPos)
|
||||
lockedLevel = pos().z
|
||||
modules.game_interface.getMapPanel():unlockVisibleFloor()
|
||||
end)
|
||||
|
||||
onKeyPress(function(keys)
|
||||
if keys == keyDown then
|
||||
lockedLevel = lockedLevel + 1
|
||||
modules.game_interface.getMapPanel():lockVisibleFloor(lockedLevel)
|
||||
elseif keys == keyUp then
|
||||
lockedLevel = lockedLevel - 1
|
||||
modules.game_interface.getMapPanel():lockVisibleFloor(lockedLevel)
|
||||
end
|
||||
end)
|
||||
473
modules/game_bot/default_configs/vBot_4.7/vBot/supplies.lua
Normal file
473
modules/game_bot/default_configs/vBot_4.7/vBot/supplies.lua
Normal file
@@ -0,0 +1,473 @@
|
||||
setDefaultTab("Cave")
|
||||
local panelName = "supplies"
|
||||
if not SuppliesConfig[panelName] or SuppliesConfig[panelName].item1 then
|
||||
SuppliesConfig[panelName] = {
|
||||
currentProfile = "Default",
|
||||
["Default"] = {}
|
||||
}
|
||||
end
|
||||
|
||||
local function convertOldConfig(config)
|
||||
if config and config.items then
|
||||
return config
|
||||
end -- config is new
|
||||
|
||||
local newConfig = {
|
||||
items = {},
|
||||
capSwitch = config.capSwitch,
|
||||
SoftBoots = config.SoftBoots,
|
||||
imbues = config.imbues,
|
||||
staminaSwitch = config.staminaSwitch,
|
||||
capValue = config.capValue,
|
||||
staminaValue = config.staminaValue
|
||||
}
|
||||
|
||||
local items = {
|
||||
config.item1,
|
||||
config.item2,
|
||||
config.item3,
|
||||
config.item4,
|
||||
config.item5,
|
||||
config.item6
|
||||
}
|
||||
local mins = {
|
||||
config.item1Min,
|
||||
config.item2Min,
|
||||
config.item3Min,
|
||||
config.item4Min,
|
||||
config.item5Min,
|
||||
config.item6Min
|
||||
}
|
||||
local maxes = {
|
||||
config.item1Max,
|
||||
config.item2Max,
|
||||
config.item3Max,
|
||||
config.item4Max,
|
||||
config.item5Max,
|
||||
config.item6Max
|
||||
}
|
||||
|
||||
for i, item in ipairs(items) do
|
||||
if item > 100 then
|
||||
local min = mins[i]
|
||||
local max = maxes[i]
|
||||
newConfig.items[tostring(item)] = {
|
||||
min = min,
|
||||
max = max,
|
||||
avg = 0
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return newConfig
|
||||
end
|
||||
|
||||
-- convert old configs
|
||||
for k, profile in pairs(SuppliesConfig[panelName]) do
|
||||
if type(profile) == 'table' then
|
||||
SuppliesConfig[panelName][k] = convertOldConfig(profile)
|
||||
end
|
||||
end
|
||||
|
||||
local currentProfile = SuppliesConfig[panelName].currentProfile
|
||||
local config = SuppliesConfig[panelName][currentProfile]
|
||||
|
||||
vBotConfigSave("supply")
|
||||
|
||||
if not config then
|
||||
for k, v in pairs(SuppliesConfig[panelName]) do
|
||||
if type(v) == "table" then
|
||||
SuppliesConfig[panelName].currentProfile = k
|
||||
config = SuppliesConfig[panelName][k]
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function getEmptyItemPanels()
|
||||
local panel = SuppliesWindow.items
|
||||
local count = 0
|
||||
|
||||
for i, child in ipairs(panel:getChildren()) do
|
||||
count = child:getId() == "blank" and count + 1 or count
|
||||
end
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
function deleteFirstEmptyPanel()
|
||||
local panel = SuppliesWindow.items
|
||||
|
||||
for i, child in ipairs(panel:getChildren()) do
|
||||
if child:getId() == "blank" then
|
||||
child:destroy()
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function clearEmptyPanels()
|
||||
local panel = SuppliesWindow.items
|
||||
|
||||
if panel:getChildCount() > 1 then
|
||||
if getEmptyItemPanels() > 1 then
|
||||
deleteFirstEmptyPanel()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function addItemPanel()
|
||||
local parent = SuppliesWindow.items
|
||||
local childs = parent:getChildCount()
|
||||
local panel = UI.createWidget("ItemPanel", parent)
|
||||
local item = panel.id
|
||||
local min = panel.min
|
||||
local max = panel.max
|
||||
local avg = panel.avg
|
||||
|
||||
panel:setId("blank")
|
||||
item:setShowCount(false)
|
||||
|
||||
item.onItemChange = function(widget)
|
||||
local id = widget:getItemId()
|
||||
local panelId = panel:getId()
|
||||
|
||||
-- empty, verify
|
||||
if id < 100 then
|
||||
config.items[panelId] = nil
|
||||
panel:setId("blank")
|
||||
clearEmptyPanels() -- clear empty panels if any
|
||||
return
|
||||
end
|
||||
|
||||
-- itemId was not changed, ignore
|
||||
if tonumber(panelId) == id then
|
||||
return
|
||||
end
|
||||
|
||||
-- check if isnt already added
|
||||
if config[tostring(id)] then
|
||||
warn("vBot[Drop Tracker]: Item already added!")
|
||||
widget:setItemId(0)
|
||||
return
|
||||
end
|
||||
|
||||
-- new item id
|
||||
config.items[tostring(id)] = config.items[tostring(id)] or {} -- min, max, avg
|
||||
panel:setId(id)
|
||||
addItemPanel() -- add new panel
|
||||
end
|
||||
|
||||
return panel
|
||||
end
|
||||
|
||||
SuppliesWindow = UI.createWindow("SuppliesWindow")
|
||||
SuppliesWindow:hide()
|
||||
|
||||
UI.Button(
|
||||
"Supply Settings",
|
||||
function()
|
||||
SuppliesWindow:setVisible(not SuppliesWindow:isVisible())
|
||||
end
|
||||
)
|
||||
|
||||
-- load settings
|
||||
local function loadSettings()
|
||||
-- panels
|
||||
SuppliesWindow.items:destroyChildren()
|
||||
|
||||
for id, data in pairs(config.items) do
|
||||
local widget = addItemPanel()
|
||||
widget:setId(id)
|
||||
widget.id:setItemId(tonumber(id))
|
||||
widget.min:setText(data.min)
|
||||
widget.max:setText(data.max)
|
||||
widget.avg:setText(data.avg)
|
||||
end
|
||||
addItemPanel() -- add empty panel
|
||||
|
||||
-- switches and values
|
||||
SuppliesWindow.capSwitch:setOn(config.capSwitch)
|
||||
SuppliesWindow.SoftBoots:setOn(config.SoftBoots)
|
||||
SuppliesWindow.imbues:setOn(config.imbues)
|
||||
SuppliesWindow.staminaSwitch:setOn(config.staminaSwitch)
|
||||
SuppliesWindow.capValue:setText(config.capValue or 0)
|
||||
SuppliesWindow.staminaValue:setText(config.staminaValue or 0)
|
||||
end
|
||||
loadSettings()
|
||||
|
||||
-- save settings
|
||||
SuppliesWindow.onVisibilityChange = function(widget, visible)
|
||||
if not visible then
|
||||
local currentProfile = SuppliesConfig[panelName].currentProfile
|
||||
SuppliesConfig[panelName][currentProfile].items = {}
|
||||
local parent = SuppliesWindow.items
|
||||
|
||||
-- items
|
||||
for i, panel in ipairs(parent:getChildren()) do
|
||||
if panel.id:getItemId() > 100 then
|
||||
local id = tostring(panel.id:getItemId())
|
||||
local min = panel.min:getValue()
|
||||
local max = panel.max:getValue()
|
||||
local avg = panel.avg:getValue()
|
||||
|
||||
SuppliesConfig[panelName][currentProfile].items[id] = {
|
||||
min = min,
|
||||
max = max,
|
||||
avg = avg
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
vBotConfigSave("supply")
|
||||
end
|
||||
end
|
||||
|
||||
local function refreshProfileList()
|
||||
local profiles = SuppliesConfig[panelName]
|
||||
|
||||
SuppliesWindow.profiles:destroyChildren()
|
||||
for k, v in pairs(profiles) do
|
||||
if type(v) == "table" then
|
||||
local label = UI.createWidget("ProfileLabel", SuppliesWindow.profiles)
|
||||
label:setText(k)
|
||||
label:setTooltip("Click to load this profile. \nDouble click to change the name.")
|
||||
label.remove.onClick = function()
|
||||
local childs = SuppliesWindow.profiles:getChildCount()
|
||||
if childs == 1 then
|
||||
return info("vBot[Supplies] You need at least one profile!")
|
||||
end
|
||||
profiles[k] = nil
|
||||
label:destroy()
|
||||
vBotConfigSave("supply")
|
||||
end
|
||||
label.onDoubleClick = function(widget)
|
||||
local window =
|
||||
modules.client_textedit.show(
|
||||
widget,
|
||||
{title = "Set Profile Name", description = "Enter a new name for selected profile"}
|
||||
)
|
||||
schedule(
|
||||
50,
|
||||
function()
|
||||
window:raise()
|
||||
window:focus()
|
||||
end
|
||||
)
|
||||
end
|
||||
label.onClick = function()
|
||||
SuppliesConfig[panelName].currentProfile = label:getText()
|
||||
config = SuppliesConfig[panelName][label:getText()]
|
||||
loadSettings()
|
||||
vBotConfigSave("supply")
|
||||
end
|
||||
label.onTextChange = function(widget, text)
|
||||
currentProfile = text
|
||||
SuppliesConfig[panelName].currentProfile = text
|
||||
profiles[text] = profiles[k]
|
||||
profiles[k] = nil
|
||||
vBotConfigSave("supply")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
refreshProfileList()
|
||||
|
||||
local function setProfileFocus()
|
||||
for i, v in ipairs(SuppliesWindow.profiles:getChildren()) do
|
||||
local name = v:getText()
|
||||
if name == SuppliesConfig[panelName].currentProfile then
|
||||
return v:focus()
|
||||
end
|
||||
end
|
||||
end
|
||||
setProfileFocus()
|
||||
|
||||
SuppliesWindow.newProfile.onClick = function()
|
||||
local n = SuppliesWindow.profiles:getChildCount()
|
||||
if n > 6 then
|
||||
return info("vBot[Supplies] - max profile count reached!")
|
||||
end
|
||||
local name = "Profile #" .. n + 1
|
||||
SuppliesConfig[panelName][name] = {items = {}}
|
||||
refreshProfileList()
|
||||
setProfileFocus()
|
||||
vBotConfigSave("supply")
|
||||
end
|
||||
|
||||
SuppliesWindow.capSwitch.onClick = function(widget)
|
||||
config.capSwitch = not config.capSwitch
|
||||
widget:setOn(config.capSwitch)
|
||||
end
|
||||
|
||||
SuppliesWindow.SoftBoots.onClick = function(widget)
|
||||
config.SoftBoots = not config.SoftBoots
|
||||
widget:setOn(config.SoftBoots)
|
||||
end
|
||||
|
||||
SuppliesWindow.imbues.onClick = function(widget)
|
||||
config.imbues = not config.imbues
|
||||
widget:setOn(config.imbues)
|
||||
end
|
||||
|
||||
SuppliesWindow.staminaSwitch.onClick = function(widget)
|
||||
config.staminaSwitch = not config.staminaSwitch
|
||||
widget:setOn(config.staminaSwitch)
|
||||
end
|
||||
|
||||
SuppliesWindow.capValue.onTextChange = function(widget, text)
|
||||
local value = tonumber(SuppliesWindow.capValue:getText())
|
||||
if not value then
|
||||
SuppliesWindow.capValue:setText(0)
|
||||
config.capValue = 0
|
||||
else
|
||||
text = text:match("0*(%d+)")
|
||||
config.capValue = text
|
||||
end
|
||||
end
|
||||
|
||||
SuppliesWindow.staminaValue.onTextChange = function(widget, text)
|
||||
local value = tonumber(SuppliesWindow.staminaValue:getText())
|
||||
if not value then
|
||||
SuppliesWindow.staminaValue:setText(0)
|
||||
config.staminaValue = 0
|
||||
else
|
||||
text = text:match("0*(%d+)")
|
||||
config.staminaValue = text
|
||||
end
|
||||
end
|
||||
|
||||
SuppliesWindow.increment.onClick = function(widget)
|
||||
for i, panel in ipairs(SuppliesWindow.items:getChildren()) do
|
||||
if panel.id:getItemId() > 100 then
|
||||
local max = panel.max:getValue()
|
||||
local avg = panel.avg:getValue()
|
||||
|
||||
if avg > 0 then
|
||||
panel.max:setText(max + avg)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SuppliesWindow.decrement.onClick = function(widget)
|
||||
for i, panel in ipairs(SuppliesWindow.items:getChildren()) do
|
||||
if panel.id:getItemId() > 100 then
|
||||
local max = panel.max:getValue()
|
||||
local avg = panel.avg:getValue()
|
||||
|
||||
if avg > 0 then
|
||||
panel.max:setText(math.max(0, max - avg)) -- dont go below 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SuppliesWindow.increment.onMouseWheel = function(widget, mousePos, dir)
|
||||
if dir == 1 then
|
||||
SuppliesWindow.increment.onClick()
|
||||
elseif dir == 2 then
|
||||
SuppliesWindow.decrement.onClick()
|
||||
end
|
||||
end
|
||||
|
||||
SuppliesWindow.decrement.onMouseWheel = SuppliesWindow.increment.onMouseWheel
|
||||
|
||||
Supplies = {} -- public functions
|
||||
Supplies.show = function()
|
||||
SuppliesWindow:show()
|
||||
SuppliesWindow:raise()
|
||||
SuppliesWindow:focus()
|
||||
end
|
||||
|
||||
Supplies.getItemsData = function()
|
||||
local t = {}
|
||||
-- items
|
||||
for i, panel in ipairs(SuppliesWindow.items:getChildren()) do
|
||||
if panel.id:getItemId() > 100 then
|
||||
local id = tostring(panel.id:getItemId())
|
||||
local min = panel.min:getValue()
|
||||
local max = panel.max:getValue()
|
||||
local avg = panel.avg:getValue()
|
||||
|
||||
t[id] = {
|
||||
min = min,
|
||||
max = max,
|
||||
avg = avg
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return t
|
||||
end
|
||||
|
||||
Supplies.isSupplyItem = function(id)
|
||||
local data = Supplies.getItemsData()
|
||||
id = tostring(id)
|
||||
|
||||
if data[id] then
|
||||
return data[id]
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
Supplies.hasEnough = function()
|
||||
local data = Supplies.getItemsData()
|
||||
|
||||
for id, values in pairs(data) do
|
||||
id = tonumber(id)
|
||||
local minimum = values.min
|
||||
local current = player:getItemsCount(id) or 0
|
||||
|
||||
if current < minimum then
|
||||
return {id=id, amount=current}
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
hasSupplies = Supplies.hasEnough
|
||||
|
||||
Supplies.setAverageValues = function(data)
|
||||
for id, amount in pairs(data) do
|
||||
local widget = SuppliesWindow.items[id]
|
||||
|
||||
if widget then
|
||||
widget.avg:setText(amount)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Supplies.addSupplyItem = function(id, min, max, avg)
|
||||
if not id then
|
||||
return
|
||||
end
|
||||
|
||||
local widget = addItemPanel()
|
||||
widget:setId(id)
|
||||
widget.id:setItemId(tonumber(id))
|
||||
widget.min:setText(min or 0)
|
||||
widget.max:setText(max or 0)
|
||||
widget.avg:setText(avg or 0)
|
||||
end
|
||||
|
||||
Supplies.getAdditionalData = function()
|
||||
local data = {
|
||||
stamina = {enabled = config.staminaSwitch, value = config.staminaValue},
|
||||
capacity = {enabled = config.capSwitch, value = config.capValue},
|
||||
softBoots = {enabled = config.SoftBoots},
|
||||
imbues = {enabled = config.imbues}
|
||||
}
|
||||
return data
|
||||
end
|
||||
|
||||
Supplies.getFullData = function()
|
||||
local data = {
|
||||
items = Supplies.getItemsData(),
|
||||
additional = Supplies.getAdditionalData()
|
||||
}
|
||||
|
||||
return data
|
||||
end
|
||||
244
modules/game_bot/default_configs/vBot_4.7/vBot/supplies.otui
Normal file
244
modules/game_bot/default_configs/vBot_4.7/vBot/supplies.otui
Normal file
@@ -0,0 +1,244 @@
|
||||
ProfileLabel < UIWidget
|
||||
background-color: alpha
|
||||
text-offset: 3 1
|
||||
focusable: true
|
||||
height: 16
|
||||
font: verdana-11px-rounded
|
||||
text-align: left
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
Button
|
||||
id: remove
|
||||
!text: tr('X')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 14
|
||||
height: 14
|
||||
margin-right: 3
|
||||
text-align: center
|
||||
text-offset: 0 1
|
||||
tooltip: Remove profile from the list.
|
||||
|
||||
SupplySpinBox < SpinBox
|
||||
height: 20
|
||||
margin-left: 3
|
||||
width: 75
|
||||
minimum: 0
|
||||
maximum: 9999
|
||||
text-align: center
|
||||
focusable: true
|
||||
text: 0
|
||||
|
||||
ItemPanel < Panel
|
||||
height: 38
|
||||
|
||||
BotItem
|
||||
id: id
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
SupplySpinBox
|
||||
id: min
|
||||
anchors.left: prev.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
SupplySpinBox
|
||||
id: max
|
||||
anchors.left: prev.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
SupplySpinBox
|
||||
id: avg
|
||||
anchors.left: prev.right
|
||||
anchors.bottom: parent.bottom
|
||||
width: 50
|
||||
|
||||
UIWidget
|
||||
anchors.left: min.left
|
||||
anchors.bottom: min.top
|
||||
width: 75
|
||||
text-align: center
|
||||
font: verdana-11px-rounded
|
||||
text: Min
|
||||
tooltip: Amount of given supplies for bot to leave the spawn.
|
||||
|
||||
UIWidget
|
||||
anchors.left: max.left
|
||||
anchors.bottom: max.top
|
||||
width: 75
|
||||
text-align: center
|
||||
font: verdana-11px-rounded
|
||||
text: Max
|
||||
tooltip: Amount of given supplies to purchase
|
||||
|
||||
UIWidget
|
||||
anchors.left: avg.left
|
||||
anchors.bottom: avg.top
|
||||
width: 55
|
||||
text-align: center
|
||||
font: verdana-11px-rounded
|
||||
text: AVG
|
||||
!tooltip: ("This is average consumption of supplies by round to help calculate the amount to purchase\n (info provided by CaveBot Stats)")
|
||||
|
||||
SuppliesWindow < MainWindow
|
||||
!text: tr('Supplies')
|
||||
size: 430 330
|
||||
@onEscape: self:hide()
|
||||
|
||||
VerticalSeparator
|
||||
id: sep
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
margin-right: 140
|
||||
anchors.bottom: bottomSep.top
|
||||
margin-bottom: 5
|
||||
margin-left: 10
|
||||
visible: false
|
||||
|
||||
Label
|
||||
anchors.left: sep.right
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
margin-left: 10
|
||||
margin-top: 3
|
||||
text-align: center
|
||||
text: Additional Conditions:
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
anchors.right: prev.right
|
||||
margin-top: 3
|
||||
|
||||
BotSwitch
|
||||
id: SoftBoots
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: sep.right
|
||||
anchors.right: parent.right
|
||||
margin-top: 5
|
||||
margin-left: 10
|
||||
text: No Soft
|
||||
tooltip: Go refill if there's no more active soft boots.
|
||||
|
||||
BotSwitch
|
||||
id: capSwitch
|
||||
height: 20
|
||||
anchors.left: SoftBoots.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
margin-right: 50
|
||||
text-align: center
|
||||
text: Cap Below:
|
||||
tooltip: Go refill if capacity is below set value.
|
||||
|
||||
BotTextEdit
|
||||
id: capValue
|
||||
size: 40 20
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.top
|
||||
margin-left: 5
|
||||
|
||||
BotSwitch
|
||||
id: staminaSwitch
|
||||
height: 20
|
||||
anchors.left: SoftBoots.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
margin-right: 50
|
||||
text-align: center
|
||||
text: Stamina:
|
||||
tooltip: Go refill if stamina is below set value. (in minutes)
|
||||
|
||||
BotTextEdit
|
||||
id: staminaValue
|
||||
size: 40 20
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.top
|
||||
margin-left: 5
|
||||
|
||||
BotSwitch
|
||||
id: imbues
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: sep.right
|
||||
anchors.right: parent.right
|
||||
margin-top: 5
|
||||
margin-left: 10
|
||||
text: No Imbues
|
||||
tooltip: Go refill when mana leech imbue has worn off.
|
||||
|
||||
TextList
|
||||
id: profiles
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
anchors.left: prev.left
|
||||
anchors.right: prev.right
|
||||
anchors.bottom: bottomSep.top
|
||||
margin-bottom: 25
|
||||
|
||||
BotButton
|
||||
id: newProfile
|
||||
anchors.left: prev.left
|
||||
anchors.top: prev.bottom
|
||||
size: 35 15
|
||||
text: New
|
||||
font: cipsoftFont
|
||||
tooltip: Create new supplies profile.
|
||||
|
||||
VerticalScrollBar
|
||||
id: itemsScrollBar
|
||||
anchors.top: items.top
|
||||
anchors.bottom: items.bottom
|
||||
anchors.right: items.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
ScrollablePanel
|
||||
id: items
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: sep.left
|
||||
anchors.bottom: bottomSep.top
|
||||
margin-bottom: 8
|
||||
vertical-scrollbar: itemsScrollBar
|
||||
layout: verticalBox
|
||||
|
||||
HorizontalSeparator
|
||||
id: bottomSep
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: closeButton.top
|
||||
margin-bottom: 8
|
||||
|
||||
Button
|
||||
id: closeButton
|
||||
!text: tr('Close')
|
||||
font: cipsoftFont
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
size: 45 21
|
||||
margin-top: 15
|
||||
tooltip: Close supplies window and save settings.
|
||||
@onClick: self:getParent():hide()
|
||||
|
||||
Button
|
||||
id: increment
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: items.right
|
||||
text: +
|
||||
width: 50
|
||||
tooltip: increase all max supplies amount by average
|
||||
|
||||
Button
|
||||
id: decrement
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.right: prev.left
|
||||
margin-right: 3
|
||||
text: -
|
||||
width: 50
|
||||
tooltip: decrease all max supplies amount by average
|
||||
46
modules/game_bot/default_configs/vBot_4.7/vBot/tools.lua
Normal file
46
modules/game_bot/default_configs/vBot_4.7/vBot/tools.lua
Normal file
@@ -0,0 +1,46 @@
|
||||
-- tools tab
|
||||
setDefaultTab("Tools")
|
||||
|
||||
if type(storage.moneyItems) ~= "table" then
|
||||
storage.moneyItems = {3031, 3035}
|
||||
end
|
||||
macro(1000, "Exchange money", function()
|
||||
if not storage.moneyItems[1] then return end
|
||||
local containers = g_game.getContainers()
|
||||
for index, container in pairs(containers) do
|
||||
if not container.lootContainer then -- ignore monster containers
|
||||
for i, item in ipairs(container:getItems()) do
|
||||
if item:getCount() == 100 then
|
||||
for m, moneyId in ipairs(storage.moneyItems) do
|
||||
if item:getId() == moneyId.id then
|
||||
return g_game.use(item)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local moneyContainer = UI.Container(function(widget, items)
|
||||
storage.moneyItems = items
|
||||
end, true)
|
||||
moneyContainer:setHeight(35)
|
||||
moneyContainer:setItems(storage.moneyItems)
|
||||
|
||||
UI.Separator()
|
||||
|
||||
macro(60000, "Send message on trade", function()
|
||||
local trade = getChannelId("advertising")
|
||||
if not trade then
|
||||
trade = getChannelId("trade")
|
||||
end
|
||||
if trade and storage.autoTradeMessage:len() > 0 then
|
||||
sayChannel(trade, storage.autoTradeMessage)
|
||||
end
|
||||
end)
|
||||
UI.TextEdit(storage.autoTradeMessage or "I'm using OTClientV8!", function(widget, text)
|
||||
storage.autoTradeMessage = text
|
||||
end)
|
||||
|
||||
UI.Separator()
|
||||
@@ -0,0 +1 @@
|
||||
4.7
|
||||
1173
modules/game_bot/default_configs/vBot_4.7/vBot/vlib.lua
Normal file
1173
modules/game_bot/default_configs/vBot_4.7/vBot/vlib.lua
Normal file
File diff suppressed because it is too large
Load Diff
30
modules/game_bot/default_configs/vBot_4.7/vBot/xeno_menu.lua
Normal file
30
modules/game_bot/default_configs/vBot_4.7/vBot/xeno_menu.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
modules.game_interface.gameRootPanel.onMouseRelease = function(widget, mousePos, mouseButton)
|
||||
if mouseButton == 2 then
|
||||
local child = rootWidget:recursiveGetChildByPos(mousePos)
|
||||
if child == widget then
|
||||
local menu = g_ui.createWidget('PopupMenu')
|
||||
menu:setId("blzMenu")
|
||||
menu:setGameMenu(true)
|
||||
menu:addOption('AttackBot', AttackBot.show, "OTCv8")
|
||||
menu:addOption('HealBot', HealBot.show, "OTCv8")
|
||||
menu:addOption('Conditions', Conditions.show, "OTCv8")
|
||||
menu:addSeparator()
|
||||
menu:addOption('CaveBot', function()
|
||||
if CaveBot.isOn() then
|
||||
CaveBot.setOff()
|
||||
else
|
||||
CaveBot.setOn()
|
||||
end
|
||||
end, CaveBot.isOn() and "ON " or "OFF ")
|
||||
menu:addOption('TargetBot', function()
|
||||
if TargetBot.isOn() then
|
||||
TargetBot.setOff()
|
||||
else
|
||||
TargetBot.setOn()
|
||||
end
|
||||
end, TargetBot.isOn() and "ON " or "OFF ")
|
||||
menu:display(mousePos)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user