mirror of
https://github.com/OTCv8/otclientv8.git
synced 2025-04-29 18:59:20 +02:00
Version 2.6 - http://otclient.net/showthread.php?tid=552
This commit is contained in:
parent
a4f9250ddb
commit
2d1cbaae12
BIN
data/sounds/Creature_Detected.ogg
Normal file
BIN
data/sounds/Creature_Detected.ogg
Normal file
Binary file not shown.
BIN
data/sounds/Low_Health.ogg
Normal file
BIN
data/sounds/Low_Health.ogg
Normal file
Binary file not shown.
BIN
data/sounds/Low_Mana.ogg
Normal file
BIN
data/sounds/Low_Mana.ogg
Normal file
Binary file not shown.
BIN
data/sounds/Player_Attack.ogg
Normal file
BIN
data/sounds/Player_Attack.ogg
Normal file
Binary file not shown.
BIN
data/sounds/Player_Detected.ogg
Normal file
BIN
data/sounds/Player_Detected.ogg
Normal file
Binary file not shown.
BIN
data/sounds/Private_Message.ogg
Normal file
BIN
data/sounds/Private_Message.ogg
Normal file
Binary file not shown.
@ -5,7 +5,8 @@ PageButton < Button
|
||||
|
||||
ContainerWindow < MiniWindow
|
||||
height: 150
|
||||
|
||||
&save: true
|
||||
&containerWindow: true
|
||||
|
||||
UIItem
|
||||
id: containerItemWidget
|
||||
|
2
init.lua
2
init.lua
@ -1,6 +1,6 @@
|
||||
-- CONFIG
|
||||
APP_NAME = "otclientv8" -- important, change it, it's name for config dir and files in appdata
|
||||
APP_VERSION = 1342 -- client version for updater and login to identify outdated client
|
||||
APP_VERSION = 1343 -- client version for updater and login to identify outdated client
|
||||
DEFAULT_LAYOUT = "retro" -- on android it's forced to "mobile", check code bellow
|
||||
|
||||
-- If you don't use updater or other service, set it to updater = ""
|
||||
|
@ -15,9 +15,10 @@ local serverSelector
|
||||
local clientVersionSelector
|
||||
local serverHostTextEdit
|
||||
local rememberPasswordBox
|
||||
local protos = {"740", "760", "772", "792", "800", "810", "854", "860", "870", "961", "1000", "1077", "1090", "1096", "1098", "1099", "1100", "1200", "1220"}
|
||||
local protos = {"740", "760", "772", "792", "800", "810", "854", "860", "870", "910", "961", "1000", "1077", "1090", "1096", "1098", "1099", "1100", "1200", "1220", "1230", "1240", "1250", "1252"}
|
||||
|
||||
local checkedByUpdater = {}
|
||||
local waitingForHttpResults = 0
|
||||
|
||||
-- private functions
|
||||
local function onProtocolError(protocol, message, errorCode)
|
||||
@ -194,10 +195,20 @@ local function onTibia12HTTPResult(session, playdata)
|
||||
onCharacterList(nil, characters, account, nil)
|
||||
end
|
||||
|
||||
local function onHTTPResult(data, err)
|
||||
local function onHTTPResult(data, err)
|
||||
if waitingForHttpResults == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
waitingForHttpResults = waitingForHttpResults - 1
|
||||
if err and waitingForHttpResults > 0 then
|
||||
return -- ignore, wait for other requests
|
||||
end
|
||||
|
||||
if err then
|
||||
return EnterGame.onError(err)
|
||||
end
|
||||
waitingForHttpResults = 0
|
||||
if data['error'] and data['error']:len() > 0 then
|
||||
return EnterGame.onLoginError(data['error'])
|
||||
elseif data['errorMessage'] and data['errorMessage']:len() > 0 then
|
||||
@ -396,7 +407,11 @@ function EnterGame.onServerChange()
|
||||
customServerSelectorPanel:setOn(false)
|
||||
end
|
||||
if Servers and Servers[server] ~= nil then
|
||||
serverHostTextEdit:setText(Servers[server])
|
||||
if type(Servers[server]) == "table" then
|
||||
serverHostTextEdit:setText(Servers[server][1])
|
||||
else
|
||||
serverHostTextEdit:setText(Servers[server])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -541,7 +556,19 @@ function EnterGame.doLoginHttp()
|
||||
stayloggedin = true
|
||||
}
|
||||
|
||||
HTTP.postJSON(G.host, data, onHTTPResult)
|
||||
local server = serverSelector:getText()
|
||||
if Servers and Servers[server] ~= nil then
|
||||
if type(Servers[server]) == "table" then
|
||||
local urls = Servers[server]
|
||||
waitingForHttpResults = #urls
|
||||
for _, url in ipairs(urls) do
|
||||
HTTP.postJSON(url, data, onHTTPResult)
|
||||
end
|
||||
else
|
||||
waitingForHttpResults = 1
|
||||
HTTP.postJSON(G.host, data, onHTTPResult)
|
||||
end
|
||||
end
|
||||
EnterGame.hide()
|
||||
end
|
||||
|
||||
|
@ -11,6 +11,8 @@ local adaptiveRender = nil
|
||||
local slowMain = nil
|
||||
local slowRender = nil
|
||||
local widgetsInfo = nil
|
||||
local packets
|
||||
local slowPackets
|
||||
|
||||
local updateEvent = nil
|
||||
local monitorEvent = nil
|
||||
@ -36,9 +38,11 @@ function init()
|
||||
dispatcherStats = statsWindow:recursiveGetChildById('dispatcherStats')
|
||||
render = statsWindow:recursiveGetChildById('render')
|
||||
atlas = statsWindow:recursiveGetChildById('atlas')
|
||||
packets = statsWindow:recursiveGetChildById('packets')
|
||||
adaptiveRender = statsWindow:recursiveGetChildById('adaptiveRender')
|
||||
slowMain = statsWindow:recursiveGetChildById('slowMain')
|
||||
slowRender = statsWindow:recursiveGetChildById('slowRender')
|
||||
slowPackets = statsWindow:recursiveGetChildById('slowPackets')
|
||||
widgetsInfo = statsWindow:recursiveGetChildById('widgetsInfo')
|
||||
|
||||
lastSend = os.time()
|
||||
@ -177,7 +181,7 @@ function update()
|
||||
return
|
||||
end
|
||||
|
||||
iter = (iter + 1) % 8 -- some functions are slow (~5ms), it will avoid lags
|
||||
iter = (iter + 1) % 9 -- some functions are slow (~5ms), it will avoid lags
|
||||
if iter == 0 then
|
||||
statsWindow.debugPanel.sleepTime:setText("GFPS: " .. g_app.getGraphicsFps() .. " PFPS: " .. g_app.getProcessingFps() .. " Packets: " .. g_game.getRecivedPacketsCount() .. " , " .. (g_game.getRecivedPacketsSize() / 1024) .. " KB")
|
||||
statsWindow.debugPanel.luaRamUsage:setText("Ram usage by lua: " .. gcinfo() .. " kb")
|
||||
@ -200,6 +204,9 @@ function update()
|
||||
--disabled because takes a lot of cpu
|
||||
--widgetsInfo:setText(g_stats.getWidgetsInfo(10, true))
|
||||
elseif iter == 7 then
|
||||
packets:setText(g_stats.get(6, 10, true))
|
||||
slowPackets:setText(g_stats.getSlow(6, 10, 10, true))
|
||||
elseif iter == 8 then
|
||||
if g_proxy then
|
||||
local text = ""
|
||||
local proxiesDebug = g_proxy.getProxiesDebugInfo()
|
||||
|
@ -104,6 +104,13 @@ MainWindow
|
||||
id: widgetsInfo
|
||||
text: Disabled, edit stats.lua to enable
|
||||
|
||||
DebugLabel
|
||||
!text: tr('Packets')
|
||||
|
||||
DebugText
|
||||
id: packets
|
||||
text: -
|
||||
|
||||
DebugLabel
|
||||
!text: tr('Slow main functions')
|
||||
|
||||
@ -117,6 +124,13 @@ MainWindow
|
||||
DebugText
|
||||
id: slowRender
|
||||
text: -
|
||||
|
||||
DebugLabel
|
||||
!text: tr('Slow packets')
|
||||
|
||||
DebugText
|
||||
id: slowPackets
|
||||
text: -
|
||||
|
||||
VerticalScrollBar
|
||||
id: debugScroll
|
||||
|
@ -165,8 +165,7 @@ function UIMiniWindow:setup()
|
||||
self:eraseSettings({height = true})
|
||||
end
|
||||
end
|
||||
|
||||
if selfSettings.closed and not self.forceOpen then
|
||||
if selfSettings.closed and not self.forceOpen and not self.containerWindow then
|
||||
self:close(true)
|
||||
end
|
||||
|
||||
@ -174,7 +173,7 @@ function UIMiniWindow:setup()
|
||||
self:lock(true)
|
||||
end
|
||||
else
|
||||
if not self.forceOpen and self.autoOpen ~= nil and (self.autoOpen == 0 or self.autoOpen == false) then
|
||||
if not self.forceOpen and self.autoOpen ~= nil and (self.autoOpen == 0 or self.autoOpen == false) and not self.containerWindow then
|
||||
self:close(true)
|
||||
end
|
||||
end
|
||||
@ -185,7 +184,7 @@ function UIMiniWindow:setup()
|
||||
self.miniLoaded = true
|
||||
|
||||
if self.save then
|
||||
if oldParent and oldParent:getClassName() == 'UIMiniWindowContainer' then
|
||||
if oldParent and oldParent:getClassName() == 'UIMiniWindowContainer' and not self.containerWindow then
|
||||
addEvent(function() oldParent:order() end)
|
||||
end
|
||||
if newParent and newParent:getClassName() == 'UIMiniWindowContainer' and newParent ~= oldParent then
|
||||
@ -350,6 +349,20 @@ function UIMiniWindow:eraseSettings(data)
|
||||
g_settings.setNode('MiniWindows', settings)
|
||||
end
|
||||
|
||||
function UIMiniWindow:clearSettings()
|
||||
if not self.save then return end
|
||||
|
||||
local settings = g_settings.getNode('MiniWindows')
|
||||
if not settings then
|
||||
settings = {}
|
||||
end
|
||||
|
||||
local id = self:getId()
|
||||
settings[id] = {}
|
||||
|
||||
g_settings.setNode('MiniWindows', settings)
|
||||
end
|
||||
|
||||
function UIMiniWindow:saveParent(parent)
|
||||
local parent = self:getParent()
|
||||
if parent then
|
||||
|
@ -168,7 +168,15 @@ function UIMiniWindowContainer:scheduleInsert(widget, index)
|
||||
local placed = false
|
||||
for nIndex,nWidget in pairs(self.scheduledWidgets) do
|
||||
if nIndex - 1 <= self:getChildCount() then
|
||||
self:insertChild(nIndex, nWidget)
|
||||
local oldParent = nWidget:getParent()
|
||||
if oldParent ~= self then
|
||||
if oldParent then
|
||||
oldParent:removeChild(nWidget)
|
||||
end
|
||||
self:insertChild(nIndex, nWidget)
|
||||
else
|
||||
self:moveChildToIndex(nWidget, nIndex)
|
||||
end
|
||||
self.scheduledWidgets[nIndex] = nil
|
||||
placed = true
|
||||
break
|
||||
@ -176,7 +184,6 @@ function UIMiniWindowContainer:scheduleInsert(widget, index)
|
||||
end
|
||||
if not placed then break end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -285,30 +285,30 @@ function createDefaultConfigs()
|
||||
if not g_resources.directoryExists("/bot/" .. config_name) then
|
||||
return onError("Can't create /bot/" .. config_name .. " directory in " .. g_resources.getWriteDir())
|
||||
end
|
||||
end
|
||||
|
||||
local defaultConfigFiles = g_resources.listDirectoryFiles("default_configs/" .. config_name, true, false)
|
||||
for i, file in ipairs(defaultConfigFiles) do
|
||||
local baseName = file:split("/")
|
||||
baseName = baseName[#baseName]
|
||||
if g_resources.directoryExists(file) then
|
||||
g_resources.makeDir("/bot/" .. config_name .. "/" .. baseName)
|
||||
if not g_resources.directoryExists("/bot/" .. config_name .. "/" .. baseName) then
|
||||
return onError("Can't create /bot/" .. config_name .. "/" .. baseName .. " directory in " .. g_resources.getWriteDir())
|
||||
end
|
||||
local defaultConfigFiles2 = g_resources.listDirectoryFiles("default_configs/" .. config_name .. "/" .. baseName, true, false)
|
||||
for i, file in ipairs(defaultConfigFiles2) do
|
||||
local baseName2 = file:split("/")
|
||||
baseName2 = baseName2[#baseName2]
|
||||
local defaultConfigFiles = g_resources.listDirectoryFiles("default_configs/" .. config_name, true, false)
|
||||
for i, file in ipairs(defaultConfigFiles) do
|
||||
local baseName = file:split("/")
|
||||
baseName = baseName[#baseName]
|
||||
if g_resources.directoryExists(file) then
|
||||
g_resources.makeDir("/bot/" .. config_name .. "/" .. baseName)
|
||||
if not g_resources.directoryExists("/bot/" .. config_name .. "/" .. baseName) then
|
||||
return onError("Can't create /bot/" .. config_name .. "/" .. baseName .. " directory in " .. g_resources.getWriteDir())
|
||||
end
|
||||
local defaultConfigFiles2 = g_resources.listDirectoryFiles("default_configs/" .. config_name .. "/" .. baseName, true, false)
|
||||
for i, file in ipairs(defaultConfigFiles2) do
|
||||
local baseName2 = file:split("/")
|
||||
baseName2 = baseName2[#baseName2]
|
||||
local contents = g_resources.fileExists(file) and g_resources.readFileContents(file) or ""
|
||||
if contents:len() > 0 then
|
||||
g_resources.writeFileContents("/bot/" .. config_name .. "/" .. baseName .. "/" .. baseName2, contents)
|
||||
end
|
||||
end
|
||||
else
|
||||
local contents = g_resources.fileExists(file) and g_resources.readFileContents(file) or ""
|
||||
if contents:len() > 0 then
|
||||
g_resources.writeFileContents("/bot/" .. config_name .. "/" .. baseName .. "/" .. baseName2, contents)
|
||||
end
|
||||
end
|
||||
else
|
||||
local contents = g_resources.fileExists(file) and g_resources.readFileContents(file) or ""
|
||||
if contents:len() > 0 then
|
||||
g_resources.writeFileContents("/bot/" .. config_name .. "/" .. baseName, contents)
|
||||
g_resources.writeFileContents("/bot/" .. config_name .. "/" .. baseName, contents)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -321,8 +321,8 @@ function uploadConfig()
|
||||
if not archive then
|
||||
return displayErrorBox(tr("Config upload failed"), tr("Config %s is invalid (can't be compressed)", config))
|
||||
end
|
||||
if archive:len() > 64 * 1024 then
|
||||
return displayErrorBox(tr("Config upload failed"), tr("Config %s is too big, maximum size is 64KB. Now it has %s KB.", config, math.floor(archive / 1024)))
|
||||
if archive:len() > 1024 * 1024 then
|
||||
return displayErrorBox(tr("Config upload failed"), tr("Config %s is too big, maximum size is 1024KB. Now it has %s KB.", config, math.floor(archive:len() / 1024)))
|
||||
end
|
||||
|
||||
local infoBox = displayInfoBox(tr("Uploading config"), tr("Uploading config %s. Please wait.", config))
|
||||
@ -468,6 +468,7 @@ function initCallbacks()
|
||||
connect(g_game, {
|
||||
onTalk = botOnTalk,
|
||||
onTextMessage = botOnTextMessage,
|
||||
onLoginAdvice = botOnLoginAdvice,
|
||||
onUse = botOnUse,
|
||||
onUseWith = botOnUseWith,
|
||||
onChannelList = botChannelList,
|
||||
@ -486,12 +487,15 @@ function initCallbacks()
|
||||
onDisappear = botCreatureDisappear,
|
||||
onPositionChange = botCreaturePositionChange,
|
||||
onHealthPercentChange = botCraetureHealthPercentChange,
|
||||
onTurn = botCreatureTurn
|
||||
})
|
||||
onTurn = botCreatureTurn,
|
||||
onWalk = botCreatureWalk,
|
||||
})
|
||||
|
||||
connect(LocalPlayer, {
|
||||
onPositionChange = botCreaturePositionChange,
|
||||
onHealthPercentChange = botCraetureHealthPercentChange
|
||||
onHealthPercentChange = botCraetureHealthPercentChange,
|
||||
onTurn = botCreatureTurn,
|
||||
onWalk = botCreatureWalk,
|
||||
})
|
||||
|
||||
connect(Container, {
|
||||
@ -517,6 +521,7 @@ function terminateCallbacks()
|
||||
disconnect(g_game, {
|
||||
onTalk = botOnTalk,
|
||||
onTextMessage = botOnTextMessage,
|
||||
onLoginAdvice = botOnLoginAdvice,
|
||||
onUse = botOnUse,
|
||||
onUseWith = botOnUseWith,
|
||||
onChannelList = botChannelList,
|
||||
@ -535,12 +540,15 @@ function terminateCallbacks()
|
||||
onDisappear = botCreatureDisappear,
|
||||
onPositionChange = botCreaturePositionChange,
|
||||
onHealthPercentChange = botCraetureHealthPercentChange,
|
||||
onTurn = botCreatureTurn
|
||||
onTurn = botCreatureTurn,
|
||||
onWalk = botCreatureWalk,
|
||||
})
|
||||
|
||||
disconnect(LocalPlayer, {
|
||||
onPositionChange = botCreaturePositionChange,
|
||||
onHealthPercentChange = botCraetureHealthPercentChange
|
||||
onHealthPercentChange = botCraetureHealthPercentChange,
|
||||
onTurn = botCreatureTurn,
|
||||
onWalk = botCreatureWalk,
|
||||
})
|
||||
|
||||
disconnect(Container, {
|
||||
@ -591,6 +599,11 @@ function botOnTextMessage(mode, text)
|
||||
safeBotCall(function() botExecutor.callbacks.onTextMessage(mode, text) end)
|
||||
end
|
||||
|
||||
function botOnLoginAdvice(message)
|
||||
if botExecutor == nil then return false end
|
||||
safeBotCall(function() botExecutor.callbacks.onLoginAdvice(message) end)
|
||||
end
|
||||
|
||||
function botAddThing(tile, thing)
|
||||
if botExecutor == nil then return false end
|
||||
safeBotCall(function() botExecutor.callbacks.onAddThing(tile, thing) end)
|
||||
@ -684,4 +697,9 @@ end
|
||||
function botCreatureTurn(creature, direction)
|
||||
if botExecutor == nil then return false end
|
||||
safeBotCall(function() botExecutor.callbacks.onTurn(creature, direction) end)
|
||||
end
|
||||
|
||||
function botCreatureWalk(creature, oldPos, newPos)
|
||||
if botExecutor == nil then return false end
|
||||
safeBotCall(function() botExecutor.callbacks.onWalk(creature, oldPos, newPos) end)
|
||||
end
|
@ -8,12 +8,15 @@ setDefaultTab(cavebotTab)
|
||||
CaveBot = {} -- global namespace
|
||||
CaveBot.Extensions = {}
|
||||
importStyle("/cavebot/cavebot.otui")
|
||||
importStyle("/cavebot/config.otui")
|
||||
importStyle("/cavebot/editor.otui")
|
||||
importStyle("/cavebot/supply.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")
|
||||
-- in this section you can add extensions, check extension_template.lua
|
||||
--dofile("/cavebot/extension_template.lua")
|
||||
dofile("/cavebot/depositer.lua")
|
@ -107,16 +107,23 @@ CaveBot.registerAction("function", "red", function(value, retries, prev)
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("goto", "green", function(value, retries, prev)
|
||||
local pos = regexMatch(value, "\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)")
|
||||
local pos = regexMatch(value, "\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+),?\\s*([0-9]?)")
|
||||
if not pos[1] then
|
||||
error("Invalid cavebot goto action value. It should be position (x,y,z), is: " .. value)
|
||||
return false
|
||||
end
|
||||
|
||||
if retries >= 5 then
|
||||
return false -- tried 5 times, can't get there
|
||||
if CaveBot.Config.get("mapClick") then
|
||||
if retries >= 5 then
|
||||
return false -- tried 5 times, can't get there
|
||||
end
|
||||
else
|
||||
if retries >= 100 then
|
||||
return false -- tried 100 times, can't get there
|
||||
end
|
||||
end
|
||||
|
||||
local precision = tonumber(pos[1][5])
|
||||
pos = {x=tonumber(pos[1][2]), y=tonumber(pos[1][3]), z=tonumber(pos[1][4])}
|
||||
local playerPos = player:getPosition()
|
||||
if pos.z ~= playerPos.z then
|
||||
@ -134,7 +141,7 @@ CaveBot.registerAction("goto", "green", function(value, retries, prev)
|
||||
if math.abs(pos.x-playerPos.x) == 0 and math.abs(pos.y-playerPos.y) <= 0 then
|
||||
return true -- already at position
|
||||
end
|
||||
elseif math.abs(pos.x-playerPos.x) == 0 and math.abs(pos.y-playerPos.y) <= 1 then
|
||||
elseif math.abs(pos.x-playerPos.x) == 0 and math.abs(pos.y-playerPos.y) <= (precision or 1) then
|
||||
return true -- already at position
|
||||
end
|
||||
-- check if there's a path to that place, ignore creatures and fields
|
||||
@ -142,17 +149,14 @@ CaveBot.registerAction("goto", "green", function(value, retries, prev)
|
||||
if not path then
|
||||
return false -- there's no way
|
||||
end
|
||||
|
||||
-- walk will be executed, but it will take some time to get response from server, wait 300ms after autowalk
|
||||
CaveBot.delay(300)
|
||||
|
||||
|
||||
-- try to find path, don't ignore creatures, don't ignore fields
|
||||
if autoWalk(pos, 40) then
|
||||
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 autoWalk(pos, 40, { ignoreNonPathable = true }) then
|
||||
if CaveBot.walkTo(pos, 40, { ignoreNonPathable = true }) then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
@ -162,12 +166,21 @@ CaveBot.registerAction("goto", "green", function(value, retries, prev)
|
||||
if stairs then
|
||||
precison = 0
|
||||
end
|
||||
if autoWalk(pos, 50, { ignoreNonPathable = true, precision = precison }) then
|
||||
if CaveBot.walkTo(pos, 50, { ignoreNonPathable = true, precision = precison }) then
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
|
||||
autoWalk(path) -- everything else failed, try to walk ignoring creatures, maybe will work
|
||||
if not CaveBot.Config.get("mapClick") and retries >= 5 then
|
||||
return false
|
||||
end
|
||||
|
||||
if CaveBot.Config.get("skipBlocked") then
|
||||
return false
|
||||
end
|
||||
|
||||
-- everything else failed, try to walk ignoring creatures, maybe will work
|
||||
CaveBot.walkTo(pos, 40, { ignoreNonPathable = true, precision = 1, ignoreCreatures = true })
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
@ -204,7 +217,7 @@ CaveBot.registerAction("use", "#FFB272", function(value, retries, prev)
|
||||
end
|
||||
|
||||
use(topThing)
|
||||
CaveBot.delay(400)
|
||||
CaveBot.delay(CaveBot.Config.get("useDelay") + CaveBot.Config.get("ping"))
|
||||
return true
|
||||
end)
|
||||
|
||||
@ -241,11 +254,11 @@ CaveBot.registerAction("usewith", "#EEB292", function(value, retries, prev)
|
||||
end
|
||||
|
||||
usewith(itemid, topThing)
|
||||
CaveBot.delay(400)
|
||||
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)
|
||||
end)
|
@ -11,6 +11,9 @@ 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()
|
||||
@ -22,9 +25,14 @@ local actionRetries = 0
|
||||
local prevActionResult = true
|
||||
cavebotMacro = macro(20, function()
|
||||
if TargetBot and TargetBot.isActive() and not TargetBot.isCaveBotActionAllowed() then
|
||||
CaveBot.resetWalking()
|
||||
return -- target bot or looting is working, wait
|
||||
end
|
||||
|
||||
|
||||
if CaveBot.doWalking() then
|
||||
return -- executing walking
|
||||
end
|
||||
|
||||
local actions = ui.list:getChildCount()
|
||||
if actions == 0 then return end
|
||||
local currentAction = ui.list:getFocusedChild()
|
||||
@ -36,6 +44,7 @@ cavebotMacro = macro(20, function()
|
||||
local retry = false
|
||||
if action then
|
||||
local status, result = pcall(function()
|
||||
CaveBot.resetWalking()
|
||||
return action.callback(value, actionRetries, prevActionResult)
|
||||
end)
|
||||
if status then
|
||||
@ -72,11 +81,6 @@ cavebotMacro = macro(20, function()
|
||||
ui.list:focusChild(ui.list:getChildByIndex(nextAction))
|
||||
end)
|
||||
|
||||
onPlayerPositionChange(function()
|
||||
local delayAfterPositionChange = math.max(player:getStepDuration() + 100, 200)
|
||||
cavebotMacro.delay = math.max(cavebotMacro.delay or 0, now + delayAfterPositionChange)
|
||||
end)
|
||||
|
||||
-- config, its callback is called immediately, data can be nil
|
||||
local lastConfig = ""
|
||||
config = Config.setup("cavebot_configs", configWidget, "cfg", function(name, enabled, data)
|
||||
@ -90,9 +94,19 @@ config = Config.setup("cavebot_configs", configWidget, "cfg", function(name, ena
|
||||
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] == "extensions" then
|
||||
if v[1] == "config" then
|
||||
local status, result = pcall(function()
|
||||
return json.decode(v[2])
|
||||
end)
|
||||
if not status then
|
||||
error("Error while parsing CaveBot extensions from config:\n" .. result)
|
||||
else
|
||||
cavebotConfig = result
|
||||
end
|
||||
elseif v[1] == "extensions" then
|
||||
local status, result = pcall(function()
|
||||
return json.decode(v[2])
|
||||
end)
|
||||
@ -110,8 +124,11 @@ config = Config.setup("cavebot_configs", configWidget, "cfg", function(name, ena
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CaveBot.Config.onConfigChange(name, enabled, cavebotConfig)
|
||||
|
||||
actionRetries = 0
|
||||
CaveBot.resetWalking()
|
||||
prevActionResult = true
|
||||
cavebotMacro.setOn(enabled)
|
||||
cavebotMacro.delay = nil
|
||||
@ -134,6 +151,16 @@ ui.showEditor.onClick = function()
|
||||
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()
|
||||
@ -159,7 +186,7 @@ CaveBot.setOff = function(val)
|
||||
end
|
||||
|
||||
CaveBot.delay = function(value)
|
||||
cavebotMacro.delay = now + value
|
||||
cavebotMacro.delay = math.max(cavebotMacro.delay or 0, now + value)
|
||||
end
|
||||
|
||||
CaveBot.gotoLabel = function(label)
|
||||
@ -178,6 +205,11 @@ CaveBot.save = function()
|
||||
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
|
@ -46,3 +46,13 @@ CaveBotPanel < Panel
|
||||
|
||||
$!on:
|
||||
text: Show waypoints editor
|
||||
|
||||
BotSwitch
|
||||
id: showConfig
|
||||
margin-top: 2
|
||||
|
||||
$on:
|
||||
text: Hide config
|
||||
|
||||
$!on:
|
||||
text: Show config
|
@ -0,0 +1,94 @@
|
||||
-- config for bot
|
||||
CaveBot.Config = {}
|
||||
CaveBot.Config.values = {}
|
||||
CaveBot.Config.default_values = {}
|
||||
CaveBot.Config.value_setters = {}
|
||||
|
||||
CaveBot.Config.setup = function()
|
||||
CaveBot.Config.ui = UI.createWidget("CaveBotConfigPanel")
|
||||
local ui = CaveBot.Config.ui
|
||||
local add = CaveBot.Config.add
|
||||
|
||||
add("ping", "Server ping", 100)
|
||||
add("walkDelay", "Walk delay", 10)
|
||||
add("mapClick", "Use map click", false)
|
||||
add("mapClickDelay", "Map click delay", 100)
|
||||
add("ignoreFields", "Ignore fields", false)
|
||||
add("skipBlocked", "Skip blocked path", false)
|
||||
add("useDelay", "Delay after use", 400)
|
||||
end
|
||||
|
||||
CaveBot.Config.show = function()
|
||||
CaveBot.Config.ui:show()
|
||||
end
|
||||
|
||||
CaveBot.Config.hide = function()
|
||||
CaveBot.Config.ui:hide()
|
||||
end
|
||||
|
||||
CaveBot.Config.onConfigChange = function(configName, isEnabled, configData)
|
||||
for k, v in pairs(CaveBot.Config.default_values) do
|
||||
CaveBot.Config.value_setters[k](v)
|
||||
end
|
||||
if not configData then return end
|
||||
for k, v in pairs(configData) do
|
||||
if CaveBot.Config.value_setters[k] then
|
||||
CaveBot.Config.value_setters[k](v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CaveBot.Config.save = function()
|
||||
return CaveBot.Config.values
|
||||
end
|
||||
|
||||
CaveBot.Config.add = function(id, title, defaultValue)
|
||||
if CaveBot.Config.values[id] then
|
||||
return error("Duplicated config key: " .. id)
|
||||
end
|
||||
|
||||
local panel
|
||||
local setter -- sets value
|
||||
if type(defaultValue) == "number" then
|
||||
panel = UI.createWidget("CaveBotConfigNumberValuePanel", CaveBot.Config.ui)
|
||||
setter = function(value)
|
||||
CaveBot.Config.values[id] = value
|
||||
panel.value:setText(value, true)
|
||||
end
|
||||
setter(defaultValue)
|
||||
panel.value.onTextChange = function(widget, newValue)
|
||||
newValue = tonumber(newValue)
|
||||
if newValue then
|
||||
CaveBot.Config.values[id] = newValue
|
||||
CaveBot.save()
|
||||
end
|
||||
end
|
||||
elseif type(defaultValue) == "boolean" then
|
||||
panel = UI.createWidget("CaveBotConfigBooleanValuePanel", CaveBot.Config.ui)
|
||||
setter = function(value)
|
||||
CaveBot.Config.values[id] = value
|
||||
panel.value:setOn(value, true)
|
||||
end
|
||||
setter(defaultValue)
|
||||
panel.value.onClick = function(widget)
|
||||
widget:setOn(not widget:isOn())
|
||||
CaveBot.Config.values[id] = widget:isOn()
|
||||
CaveBot.save()
|
||||
end
|
||||
else
|
||||
return error("Invalid default value of config for key " .. id .. ", should be number or boolean")
|
||||
end
|
||||
|
||||
panel.title:setText(tr(title) .. ":")
|
||||
|
||||
CaveBot.Config.value_setters[id] = setter
|
||||
CaveBot.Config.values[id] = defaultValue
|
||||
CaveBot.Config.default_values[id] = defaultValue
|
||||
end
|
||||
|
||||
CaveBot.Config.get = function(id)
|
||||
if CaveBot.Config.values[id] == nil then
|
||||
return error("Invalid CaveBot.Config.get, id: " .. id)
|
||||
end
|
||||
return CaveBot.Config.values[id]
|
||||
end
|
@ -0,0 +1,57 @@
|
||||
CaveBotConfigPanel < Panel
|
||||
id: cavebotEditor
|
||||
visible: false
|
||||
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
HorizontalSeparator
|
||||
margin-top: 5
|
||||
|
||||
Label
|
||||
text-align: center
|
||||
text: CaveBot Config
|
||||
margin-top: 5
|
||||
|
||||
CaveBotConfigNumberValuePanel < Panel
|
||||
height: 20
|
||||
margin-top: 5
|
||||
|
||||
BotTextEdit
|
||||
id: value
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 5
|
||||
width: 50
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
margin-left: 5
|
||||
|
||||
CaveBotConfigBooleanValuePanel < Panel
|
||||
height: 20
|
||||
margin-top: 5
|
||||
|
||||
BotSwitch
|
||||
id: value
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 5
|
||||
width: 50
|
||||
|
||||
$on:
|
||||
text: On
|
||||
|
||||
$!on:
|
||||
text: Off
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
margin-left: 5
|
@ -104,7 +104,7 @@ CaveBot.Editor.setup = function()
|
||||
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]+)$"
|
||||
validation="^\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+),?\\s*([0-9]?)$"
|
||||
})
|
||||
registerAction("use", {
|
||||
value=function() return posx() .. "," .. posy() .. "," .. posz() end,
|
@ -63,3 +63,28 @@ delay(100 + retries * 100)
|
||||
return "retry"
|
||||
]])
|
||||
|
||||
addExampleFunction("Disable TargetBot", [[
|
||||
TargetBot.setOff()
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Enable TargetBot", [[
|
||||
TargetBot.setOn()
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Enable TargetBot luring", [[
|
||||
TargetBot.enableLuring()
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Disable TargetBot luring", [[
|
||||
TargetBot.disableLuring()
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Logout", [[
|
||||
g_game.safeLogout()
|
||||
delay(1000)
|
||||
return "retry"
|
||||
]])
|
@ -0,0 +1,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
|
@ -1,5 +1,5 @@
|
||||
-- main tab
|
||||
VERSION = "1.2"
|
||||
VERSION = "1.3"
|
||||
|
||||
UI.Label("Config version: " .. VERSION)
|
||||
|
@ -20,7 +20,13 @@ TargetBot.Creature.addConfig = function(config, focus)
|
||||
TargetBot.Creature.resetConfigsCache()
|
||||
|
||||
if not config.regex then
|
||||
config.regex = "^" .. config.name:trim():lower():gsub("%*", ".*"):gsub("%?", ".?") .. "$"
|
||||
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)
|
@ -67,8 +67,18 @@ 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
|
||||
|
||||
-- luring
|
||||
if (config.lure or config.lureCavebot) and not (config.chase and creature:getHealthPercent() < 30) then
|
||||
if TargetBot.canLure() and (config.lure or config.lureCavebot) and not (config.chase and creature:getHealthPercent() < 30) and not isTrapped then
|
||||
local monsters = 0
|
||||
if targets < config.lureCount then
|
||||
if config.lureCavebot then
|
@ -8,7 +8,7 @@ TargetBot.Creature.edit = function(config, callback) -- callback = function(newC
|
||||
table.insert(values, {"name", function() return editor.name:getText() end})
|
||||
|
||||
local addScrollBar = function(id, title, min, max, defaultValue)
|
||||
local widget = UI.createWidget('TargetBotCreatureEditorScrollBar', editor.left)
|
||||
local widget = UI.createWidget('TargetBotCreatureEditorScrollBar', editor.content.left)
|
||||
widget.scroll.onValueChange = function(scroll, value)
|
||||
widget.text:setText(title .. ": " .. value)
|
||||
end
|
||||
@ -24,14 +24,14 @@ TargetBot.Creature.edit = function(config, callback) -- callback = function(newC
|
||||
end
|
||||
|
||||
local addTextEdit = function(id, title, defaultValue)
|
||||
local widget = UI.createWidget('TargetBotCreatureEditorTextEdit', editor.right)
|
||||
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.right)
|
||||
local widget = UI.createWidget('TargetBotCreatureEditorCheckBox', editor.content.right)
|
||||
widget.onClick = function()
|
||||
widget:setOn(not widget:isOn())
|
||||
end
|
||||
@ -45,7 +45,7 @@ TargetBot.Creature.edit = function(config, callback) -- callback = function(newC
|
||||
end
|
||||
|
||||
local addItem = function(id, title, defaultItem)
|
||||
local widget = UI.createWidget('TargetBotCreatureEditorItem', editor.right)
|
||||
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})
|
||||
@ -62,7 +62,14 @@ TargetBot.Creature.edit = function(config, callback) -- callback = function(newC
|
||||
newConfig[value[1]] = value[2]()
|
||||
end
|
||||
if newConfig.name:len() < 1 then return end
|
||||
newConfig.regex = "^" .. newConfig.name:trim():lower():gsub("%*", ".*"):gsub("%?", ".?") .. "$"
|
||||
|
||||
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)
|
||||
@ -88,6 +95,7 @@ TargetBot.Creature.edit = function(config, callback) -- callback = function(newC
|
||||
|
||||
addCheckBox("chase", "Chase", true)
|
||||
addCheckBox("keepDistance", "Keep Distance", false)
|
||||
addCheckBox("dontLoot", "Don't loot", false)
|
||||
addCheckBox("lure", "Lure", false)
|
||||
addCheckBox("lureCavebot", "Lure using cavebot", false)
|
||||
addCheckBox("avoidAttacks", "Avoid wave attacks", false)
|
@ -64,14 +64,24 @@ TargetBotCreatureEditorCheckBox < BotSwitch
|
||||
TargetBotCreatureEditorWindow < MainWindow
|
||||
text: TargetBot creature editor
|
||||
width: 500
|
||||
height: 600
|
||||
height: 630
|
||||
|
||||
$mobile:
|
||||
height: 300
|
||||
|
||||
Label
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
text: You can use * (any characters) and ? (any character) in target name
|
||||
!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
|
||||
@ -86,29 +96,49 @@ TargetBotCreatureEditorWindow < MainWindow
|
||||
anchors.left: parent.left
|
||||
text: Target name:
|
||||
|
||||
Panel
|
||||
id: left
|
||||
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.horizontalCenter
|
||||
margin-top: 5
|
||||
margin-left: 10
|
||||
margin-right: 10
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
Panel
|
||||
id: right
|
||||
anchors.top: name.bottom
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
margin-top: 5
|
||||
margin-left: 10
|
||||
margin-right: 10
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
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
|
@ -277,6 +277,10 @@ end)
|
||||
onCreatureDisappear(function(creature)
|
||||
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()
|
@ -2,6 +2,7 @@ local targetbotMacro = nil
|
||||
local config = nil
|
||||
local lastAction = 0
|
||||
local cavebotAllowance = 0
|
||||
local lureEnabled = true
|
||||
|
||||
-- ui
|
||||
local configWidget = UI.Config()
|
||||
@ -77,6 +78,9 @@ targetbotMacro = macro(100, function()
|
||||
TargetBot.setStatus("Luring using CaveBot")
|
||||
else
|
||||
TargetBot.setStatus("Attacking")
|
||||
if not lureEnabled then
|
||||
TargetBot.setStatus("Attacking (luring off)")
|
||||
end
|
||||
end
|
||||
TargetBot.walk()
|
||||
lastAction = now
|
||||
@ -117,6 +121,7 @@ config = Config.setup("targetbot_configs", configWidget, "json", function(name,
|
||||
|
||||
targetbotMacro.setOn(enabled)
|
||||
targetbotMacro.delay = nil
|
||||
lureEnabled = true
|
||||
end)
|
||||
|
||||
-- setup ui
|
||||
@ -198,6 +203,15 @@ TargetBot.allowCaveBot = function(time)
|
||||
cavebotAllowance = now + time
|
||||
end
|
||||
|
||||
TargetBot.disableLuring = function()
|
||||
lureEnabled = false
|
||||
end
|
||||
|
||||
TargetBot.enableLuring = function()
|
||||
lureEnabled = true
|
||||
end
|
||||
|
||||
|
||||
-- attacks
|
||||
local lastSpell = 0
|
||||
local lastAttackSpell = 0
|
||||
@ -265,3 +279,7 @@ TargetBot.useAttackItem = function(item, subType, target, delay)
|
||||
lastRuneAttack = now
|
||||
end
|
||||
end
|
||||
|
||||
TargetBot.canLure = function()
|
||||
return lureEnabled
|
||||
end
|
235
modules/game_bot/default_configs/vithrax_1.1/# Conditions.lua
Normal file
235
modules/game_bot/default_configs/vithrax_1.1/# Conditions.lua
Normal file
@ -0,0 +1,235 @@
|
||||
setDefaultTab("HP")
|
||||
local conditionPanelName = "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(conditionPanelName)
|
||||
|
||||
if not storage[conditionPanelName] then
|
||||
storage[conditionPanelName] = {
|
||||
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
|
||||
}
|
||||
end
|
||||
|
||||
ui.title:setOn(storage[conditionPanelName].enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
storage[conditionPanelName].enabled = not storage[conditionPanelName].enabled
|
||||
widget:setOn(storage[conditionPanelName].enabled)
|
||||
end
|
||||
|
||||
ui.conditionList.onClick = function(widget)
|
||||
conditionsWindow:show()
|
||||
conditionsWindow:raise()
|
||||
conditionsWindow:focus()
|
||||
end
|
||||
|
||||
|
||||
|
||||
local rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
conditionsWindow = g_ui.createWidget('ConditionsWindow', rootWidget)
|
||||
conditionsWindow:hide()
|
||||
|
||||
-- text edits
|
||||
conditionsWindow.Cure.PoisonCost:setText(storage[conditionPanelName].poisonCost)
|
||||
conditionsWindow.Cure.PoisonCost.onTextChange = function(widget, text)
|
||||
storage[conditionPanelName].poisonCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.CurseCost:setText(storage[conditionPanelName].curseCost)
|
||||
conditionsWindow.Cure.CurseCost.onTextChange = function(widget, text)
|
||||
storage[conditionPanelName].curseCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.BleedCost:setText(storage[conditionPanelName].bleedCost)
|
||||
conditionsWindow.Cure.BleedCost.onTextChange = function(widget, text)
|
||||
storage[conditionPanelName].bleedCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.BurnCost:setText(storage[conditionPanelName].burnCost)
|
||||
conditionsWindow.Cure.BurnCost.onTextChange = function(widget, text)
|
||||
storage[conditionPanelName].burnCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.ElectrifyCost:setText(storage[conditionPanelName].electrifyCost)
|
||||
conditionsWindow.Cure.ElectrifyCost.onTextChange = function(widget, text)
|
||||
storage[conditionPanelName].electrifyCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.ParalyseCost:setText(storage[conditionPanelName].paralyseCost)
|
||||
conditionsWindow.Cure.ParalyseCost.onTextChange = function(widget, text)
|
||||
storage[conditionPanelName].paralyseCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.ParalyseSpell:setText(storage[conditionPanelName].paralyseSpell)
|
||||
conditionsWindow.Cure.ParalyseSpell.onTextChange = function(widget, text)
|
||||
storage[conditionPanelName].paralyseSpell = text
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.HasteSpell:setText(storage[conditionPanelName].hasteSpell)
|
||||
conditionsWindow.Hold.HasteSpell.onTextChange = function(widget, text)
|
||||
storage[conditionPanelName].hasteSpell = text
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.HasteCost:setText(storage[conditionPanelName].hasteCost)
|
||||
conditionsWindow.Hold.HasteCost.onTextChange = function(widget, text)
|
||||
storage[conditionPanelName].hasteCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.UtamoCost:setText(storage[conditionPanelName].utamoCost)
|
||||
conditionsWindow.Hold.UtamoCost.onTextChange = function(widget, text)
|
||||
storage[conditionPanelName].utamoCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.UtanaCost:setText(storage[conditionPanelName].utanaCost)
|
||||
conditionsWindow.Hold.UtanaCost.onTextChange = function(widget, text)
|
||||
storage[conditionPanelName].utanaCost = tonumber(text)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.UturaCost:setText(storage[conditionPanelName].uturaCost)
|
||||
conditionsWindow.Hold.UturaCost.onTextChange = function(widget, text)
|
||||
storage[conditionPanelName].uturaCost = tonumber(text)
|
||||
end
|
||||
|
||||
-- combo box
|
||||
conditionsWindow.Hold.UturaType:setOption(storage[conditionPanelName].uturaType)
|
||||
conditionsWindow.Hold.UturaType.onOptionChange = function(widget)
|
||||
storage[conditionPanelName].uturaType = widget:getCurrentOption().text
|
||||
end
|
||||
|
||||
-- checkboxes
|
||||
conditionsWindow.Cure.CurePoison:setChecked(storage[conditionPanelName].curePoison)
|
||||
conditionsWindow.Cure.CurePoison.onClick = function(widget)
|
||||
storage[conditionPanelName].curePoison = not storage[conditionPanelName].curePoison
|
||||
widget:setChecked(storage[conditionPanelName].curePoison)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.CureCurse:setChecked(storage[conditionPanelName].cureCurse)
|
||||
conditionsWindow.Cure.CureCurse.onClick = function(widget)
|
||||
storage[conditionPanelName].cureCurse = not storage[conditionPanelName].cureCurse
|
||||
widget:setChecked(storage[conditionPanelName].cureCurse)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.CureBleed:setChecked(storage[conditionPanelName].cureBleed)
|
||||
conditionsWindow.Cure.CureBleed.onClick = function(widget)
|
||||
storage[conditionPanelName].cureBleed = not storage[conditionPanelName].cureBleed
|
||||
widget:setChecked(storage[conditionPanelName].cureBleed)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.CureBurn:setChecked(storage[conditionPanelName].cureBurn)
|
||||
conditionsWindow.Cure.CureBurn.onClick = function(widget)
|
||||
storage[conditionPanelName].cureBurn = not storage[conditionPanelName].cureBurn
|
||||
widget:setChecked(storage[conditionPanelName].cureBurn)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.CureElectrify:setChecked(storage[conditionPanelName].cureElectrify)
|
||||
conditionsWindow.Cure.CureElectrify.onClick = function(widget)
|
||||
storage[conditionPanelName].cureElectrify = not storage[conditionPanelName].cureElectrify
|
||||
widget:setChecked(storage[conditionPanelName].cureElectrify)
|
||||
end
|
||||
|
||||
conditionsWindow.Cure.CureParalyse:setChecked(storage[conditionPanelName].cureParalyse)
|
||||
conditionsWindow.Cure.CureParalyse.onClick = function(widget)
|
||||
storage[conditionPanelName].cureParalyse = not storage[conditionPanelName].cureParalyse
|
||||
widget:setChecked(storage[conditionPanelName].cureParalyse)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.HoldHaste:setChecked(storage[conditionPanelName].holdHaste)
|
||||
conditionsWindow.Hold.HoldHaste.onClick = function(widget)
|
||||
storage[conditionPanelName].holdHaste = not storage[conditionPanelName].holdHaste
|
||||
widget:setChecked(storage[conditionPanelName].holdHaste)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.HoldUtamo:setChecked(storage[conditionPanelName].holdUtamo)
|
||||
conditionsWindow.Hold.HoldUtamo.onClick = function(widget)
|
||||
storage[conditionPanelName].holdUtamo = not storage[conditionPanelName].holdUtamo
|
||||
widget:setChecked(storage[conditionPanelName].holdUtamo)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.HoldUtana:setChecked(storage[conditionPanelName].holdUtana)
|
||||
conditionsWindow.Hold.HoldUtana.onClick = function(widget)
|
||||
storage[conditionPanelName].holdUtana = not storage[conditionPanelName].holdUtana
|
||||
widget:setChecked(storage[conditionPanelName].holdUtana)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.HoldUtura:setChecked(storage[conditionPanelName].holdUtura)
|
||||
conditionsWindow.Hold.HoldUtura.onClick = function(widget)
|
||||
storage[conditionPanelName].holdUtura = not storage[conditionPanelName].holdUtura
|
||||
widget:setChecked(storage[conditionPanelName].holdUtura)
|
||||
end
|
||||
|
||||
conditionsWindow.Hold.IgnoreInPz:setChecked(storage[conditionPanelName].ignoreInPz)
|
||||
conditionsWindow.Hold.IgnoreInPz.onClick = function(widget)
|
||||
storage[conditionPanelName].ignoreInPz = not storage[conditionPanelName].ignoreInPz
|
||||
widget:setChecked(storage[conditionPanelName].ignoreInPz)
|
||||
end
|
||||
|
||||
-- buttons
|
||||
conditionsWindow.closeButton.onClick = function(widget)
|
||||
conditionsWindow:hide()
|
||||
end
|
||||
end
|
||||
|
||||
local utanaCast = nil
|
||||
macro(500, function()
|
||||
if not storage[conditionPanelName].enabled or modules.game_cooldown.isGroupCooldownIconActive(2) then return end
|
||||
if storage[conditionPanelName].curePoison and mana() >= storage[conditionPanelName].poisonCost and isPoisioned() then say("exana pox")
|
||||
elseif storage[conditionPanelName].cureCurse and mana() >= storage[conditionPanelName].curseCost and isCursed() then say("exana mort")
|
||||
elseif storage[conditionPanelName].cureBleed and mana() >= storage[conditionPanelName].bleedCost and isBleeding() then say("exana kor")
|
||||
elseif storage[conditionPanelName].cureBurn and mana() >= storage[conditionPanelName].burnCost and isBurning() then say("exana flam")
|
||||
elseif storage[conditionPanelName].cureElectrify and mana() >= storage[conditionPanelName].electrifyCost and isEnergized() then say("exana vis")
|
||||
elseif (not storage[conditionPanelName].ignoreInPz or not isInPz()) and storage[conditionPanelName].holdUtura and mana() >= storage[conditionPanelName].uturaCost and not hasPartyBuff() then say(storage[conditionPanelName].uturaType)
|
||||
elseif (not storage[conditionPanelName].ignoreInPz or not isInPz()) and storage[conditionPanelName].holdUtana and mana() >= storage[conditionPanelName].utanaCost and (not utanaCast or (now - utanaCast > 120000)) then say("utana vid") utanaCast = now
|
||||
end
|
||||
end)
|
||||
|
||||
macro(50, function()
|
||||
if not storage[conditionPanelName].enabled then return end
|
||||
if (not storage[conditionPanelName].ignoreInPz or not isInPz()) and storage[conditionPanelName].holdUtamo and mana() >= storage[conditionPanelName].utamoCost and not hasManaShield() then say("utamo vita")
|
||||
elseif (not storage[conditionPanelName].ignoreInPz or not isInPz()) and storage[conditionPanelName].holdHaste and mana() >= storage[conditionPanelName].hasteCost and not hasHaste() and not getSpellCoolDown(storage[conditionPanelName].hasteSpell) then say(storage[conditionPanelName].hasteSpell)
|
||||
elseif storage[conditionPanelName].cureParalyse and mana() >= storage[conditionPanelName].paralyseCost and isParalyzed() and not getSpellCoolDown(storage[conditionPanelName].paralyseSpell) then say(storage[conditionPanelName].paralyseSpell)
|
||||
end
|
||||
end)
|
60
modules/game_bot/default_configs/vithrax_1.1/# tools.lua
Normal file
60
modules/game_bot/default_configs/vithrax_1.1/# tools.lua
Normal file
@ -0,0 +1,60 @@
|
||||
-- tools tab
|
||||
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 hotkey editor", function(newText)
|
||||
UI.MultilineEditorWindow(storage.ingame_hotkeys or "", {title="Hotkeys editor", description="You can add your custom hotkeys/singlehotkeys 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()
|
||||
|
||||
local moneyIds = {3031, 3035} -- gold coin, platinium coin
|
||||
macro(1000, "Exchange money", function()
|
||||
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(moneyIds) do
|
||||
if item:getId() == moneyId then
|
||||
return g_game.use(item)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
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()
|
53
modules/game_bot/default_configs/vithrax_1.1/#cavebot.lua
Normal file
53
modules/game_bot/default_configs/vithrax_1.1/#cavebot.lua
Normal file
@ -0,0 +1,53 @@
|
||||
-- Cavebot by otclient@otclient.ovh
|
||||
-- visit http://bot.otclient.ovh/
|
||||
|
||||
local cavebotTab = "Cave"
|
||||
local targetingTab = "Target"
|
||||
|
||||
setDefaultTab(cavebotTab)
|
||||
CaveBot = {} -- global namespace
|
||||
CaveBot.Extensions = {}
|
||||
importStyle("/cavebot/cavebot.otui")
|
||||
importStyle("/cavebot/config.otui")
|
||||
importStyle("/cavebot/editor.otui")
|
||||
importStyle("/cavebot/supply.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")
|
||||
-- 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/depositer.lua")
|
||||
dofile("/cavebot/supply.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/depositer.lua")
|
||||
dofile("/cavebot/supply.lua")
|
||||
-- main cavebot file, must be last
|
||||
dofile("/cavebot/cavebot.lua")
|
||||
|
||||
setDefaultTab(targetingTab)
|
||||
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")
|
7
modules/game_bot/default_configs/vithrax_1.1/#main.lua
Normal file
7
modules/game_bot/default_configs/vithrax_1.1/#main.lua
Normal file
@ -0,0 +1,7 @@
|
||||
-- main tab
|
||||
UI.Label("Vithrax CFG v1.1 \n \n Scripting service: \n Vithrax#5814")
|
||||
|
||||
UI.Separator()
|
||||
|
||||
|
||||
|
874
modules/game_bot/default_configs/vithrax_1.1/#vlib.lua
Normal file
874
modules/game_bot/default_configs/vithrax_1.1/#vlib.lua
Normal file
@ -0,0 +1,874 @@
|
||||
-- lib ver 1.4
|
||||
-- Author: Vithrax
|
||||
-- contains mostly basic function shortcuts and code shorteners
|
||||
|
||||
function isBuffed()
|
||||
if (4*(player:getSkillLevel(2) - player:getSkillBaseLevel(2))) < player:getSkillLevel(2) then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function killsToRs()
|
||||
return math.min(g_game.getUnjustifiedPoints().killsDayRemaining, g_game.getUnjustifiedPoints().killsWeekRemaining, g_game.getUnjustifiedPoints().killsMonthRemaining)
|
||||
end
|
||||
|
||||
function canCast(spell)
|
||||
if not spell then return end
|
||||
if not getSpellData(spell) then return true end
|
||||
|
||||
if not getSpellCoolDown(spell) and mana() >= getSpellData(spell).manaCost and level() >= getSpellData(spell).level then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function getSpellData(spell)
|
||||
if not spell then return false end
|
||||
if Spells[spell] then
|
||||
return Spells[spell]
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
Spells = {
|
||||
["adana ani"] = {level = 54, manaCost = 1400},
|
||||
["adana mort"] = {level = 27, manaCost = 600},
|
||||
["adana pox"] = {level = 15, manaCost = 200},
|
||||
["adeta sio"] = {level = 16, manaCost = 200},
|
||||
["adevo grav flam"] = {level = 15, manaCost = 240},
|
||||
["adevo grav pox"] = {level = 14, manaCost = 200},
|
||||
["adevo grav tera"] = {level = 32, manaCost = 750},
|
||||
["adevo grav vis"] = {level = 18, manaCost = 320},
|
||||
["adevo grav vita"] = {level = 27, manaCost = 600},
|
||||
["adevo ina"] = {level = 27, manaCost = 600},
|
||||
["adevo mas flam"] = {level = 27, manaCost = 600},
|
||||
["adevo mas grav flam"] = {level = 33, manaCost = 780},
|
||||
["adevo mas grav pox"] = {level = 29, manaCost = 640},
|
||||
["adevo mas grav vis"] = {level = 41, manaCost = 1000},
|
||||
["adevo mas hur"] = {level = 31, manaCost = 570},
|
||||
["adevo mas pox"] = {level = 25, manaCost = 520},
|
||||
["adevo mas vis"] = {level = 37, manaCost = 880},
|
||||
["adevo res flam"] = {level = 27, manaCost = 420},
|
||||
["adito grav"] = {level = 17, manaCost = 120},
|
||||
["adito tera"] = {level = 21, manaCost = 200},
|
||||
["adori dis min vis"] = {level = 1, manaCost = 5},
|
||||
["adori flam"] = {level = 27, manaCost = 460},
|
||||
["adori frigo"] = {level = 28, manaCost = 460},
|
||||
["adori gran mort"] = {level = 45, manaCost = 985},
|
||||
["adori mas flam"] = {level = 30, manaCost = 530},
|
||||
["adori mas frigo"] = {level = 30, manaCost = 530},
|
||||
["adori mas tera"] = {level = 28, manaCost = 430},
|
||||
["adori mas vis"] = {level = 28, manaCost = 430},
|
||||
["adori min vis"] = {level = 15, manaCost = 120},
|
||||
["adori san"] = {level = 27, manaCost = 300},
|
||||
["adori tera"] = {level = 24, manaCost = 350},
|
||||
["adori vis"] = {level = 25, manaCost = 350},
|
||||
["adura gran"] = {level = 15, manaCost = 120},
|
||||
["adura vita"] = {level = 24, manaCost = 400},
|
||||
["exana flam"] = {level = 30, manaCost = 30},
|
||||
["exana ina"] = {level = 26, manaCost = 200},
|
||||
["exana kor"] = {level = 45, manaCost = 30},
|
||||
["exana mort"] = {level = 80, manaCost = 40},
|
||||
["exana pox"] = {level = 10, manaCost = 30},
|
||||
["exana vis"] = {level = 22, manaCost = 30},
|
||||
["exani tera"] = {level = 9, manaCost = 20},
|
||||
["exeta con"] = {level = 45, manaCost = 350},
|
||||
["exeta res"] = {level = 20, manaCost = 40},
|
||||
["exevo con"] = {level = 13, manaCost = 100},
|
||||
["exevo con flam"] = {level = 25, manaCost = 290},
|
||||
["exevo dis flam hur"] = {level = 1, manaCost = 5},
|
||||
["exevo flam hur"] = {level = 18, manaCost = 25},
|
||||
["exevo frigo hur"] = {level = 18, manaCost = 25},
|
||||
["exevo gran con hur"] = {level = 150, manaCost = 1000},
|
||||
["exevo gran con vis"] = {level = 150, manaCost = 1000},
|
||||
["exevo gran frigo hur"] = {level = 40, manaCost = 170},
|
||||
["exevo gran mas flam"] = {level = 60, manaCost = 1100},
|
||||
["exevo gran mas frigo"] = {level = 60, manaCost = 1050},
|
||||
["exevo gran mas tera"] = {level = 55, manaCost = 700},
|
||||
["exevo gran mas vis"] = {level = 55, manaCost = 600},
|
||||
["exevo gran mort"] = {level = 41, manaCost = 250},
|
||||
["exevo gran vis lux"] = {level = 29, manaCost = 110},
|
||||
["exevo infir con"] = {level = 1, manaCost = 10},
|
||||
["exevo infir flam hur"] = {level = 1, manaCost = 8},
|
||||
["exevo infir frigo hur"] = {level = 1, manaCost = 8},
|
||||
["exevo mas san"] = {level = 50, manaCost = 160},
|
||||
["exevo pan"] = {level = 14, manaCost = 120},
|
||||
["exevo tera hur"] = {level = 38, manaCost = 210},
|
||||
["exevo vis hur"] = {level = 38, manaCost = 170},
|
||||
["exevo vis lux"] = {level = 23, manaCost = 40},
|
||||
["exori"] = {level = 35, manaCost = 115},
|
||||
["exori amp vis"] = {level = 55, manaCost = 60},
|
||||
["exori con"] = {level = 23, manaCost = 25},
|
||||
["exori flam"] = {level = 14, manaCost = 20},
|
||||
["exori frigo"] = {level = 15, manaCost = 20},
|
||||
["exori gran"] = {level = 90, manaCost = 340},
|
||||
["exori gran con"] = {level = 90, manaCost = 55},
|
||||
["exori gran flam"] = {level = 70, manaCost = 60},
|
||||
["exori gran frigo"] = {level = 80, manaCost = 60},
|
||||
["exori gran ico"] = {level = 110, manaCost = 300},
|
||||
["exori gran tera"] = {level = 70, manaCost = 60},
|
||||
["exori gran vis"] = {level = 80, manaCost = 60},
|
||||
["exori hur"] = {level = 28, manaCost = 40},
|
||||
["exori ico"] = {level = 16, manaCost = 30},
|
||||
["exori infir tera"] = {level = 1, manaCost = 6},
|
||||
["exori infir vis"] = {level = 1, manaCost = 6},
|
||||
["exori mas"] = {level = 33, manaCost = 160},
|
||||
["exori max flam"] = {level = 90, manaCost = 100},
|
||||
["exori max frigo"] = {level = 100, manaCost = 100},
|
||||
["exori max tera"] = {level = 90, manaCost = 100},
|
||||
["exori max vis"] = {level = 100, manaCost = 100},
|
||||
["exori min"] = {level = 70, manaCost = 200},
|
||||
["exori min flam"] = {level = 8, manaCost = 6},
|
||||
["exori moe ico"] = {level = 16, manaCost = 20},
|
||||
["exori mort"] = {level = 16, manaCost = 20},
|
||||
["exori san"] = {level = 40, manaCost = 20},
|
||||
["exori tera"] = {level = 13, manaCost = 20},
|
||||
["exori vis"] = {level = 12, manaCost = 20},
|
||||
["exura"] = {level = 8, manaCost = 20},
|
||||
["exura dis"] = {level = 1, manaCost = 5},
|
||||
["exura gran"] = {level = 20, manaCost = 70},
|
||||
["exura gran ico"] = {level = 80, manaCost = 200},
|
||||
["exura gran mas res"] = {level = 36, manaCost = 150},
|
||||
["exura gran san"] = {level = 60, manaCost = 210},
|
||||
["exura ico"] = {level = 8, manaCost = 40},
|
||||
["exura infir"] = {level = 1, manaCost = 6},
|
||||
["exura infir ico"] = {level = 1, manaCost = 10},
|
||||
["exura san"] = {level = 35, manaCost = 160},
|
||||
["exura vita"] = {level = 30, manaCost = 160},
|
||||
["utamo mas sio"] = {level = 32, manaCost = 0},
|
||||
["utamo tempo"] = {level = 55, manaCost = 200},
|
||||
["utamo tempo san"] = {level = 55, manaCost = 400},
|
||||
["utamo vita"] = {level = 14, manaCost = 50},
|
||||
["utana vid"] = {level = 35, manaCost = 440},
|
||||
["utani gran hur"] = {level = 20, manaCost = 100},
|
||||
["utani hur"] = {level = 14, manaCost = 60},
|
||||
["utani tempo hur"] = {level = 25, manaCost = 100},
|
||||
["utevo gran lux"] = {level = 13, manaCost = 60},
|
||||
["utevo gran res dru"] = {level = 200, manaCost = 3000},
|
||||
["utevo gran res eq"] = {level = 200, manaCost = 1000},
|
||||
["utevo gran res sac"] = {level = 200, manaCost = 2000},
|
||||
["utevo gran res ven"] = {level = 200, manaCost = 3000},
|
||||
["utevo lux"] = {level = 8, manaCost = 20},
|
||||
["utevo vis lux"] = {level = 26, manaCost = 140},
|
||||
["utito mas sio"] = {level = 32, manaCost = 0},
|
||||
["utito tempo"] = {level = 60, manaCost = 290},
|
||||
["utito tempo san"] = {level = 60, manaCost = 450},
|
||||
["utori flam"] = {level = 26, manaCost = 30},
|
||||
["utori kor"] = {level = 40, manaCost = 30},
|
||||
["utori mas sio"] = {level = 32, manaCost = 0},
|
||||
["utori mort"] = {level = 75, manaCost = 30},
|
||||
["utori pox"] = {level = 50, manaCost = 30},
|
||||
["utori san"] = {level = 70, manaCost = 30},
|
||||
["utori vis"] = {level = 34, manaCost = 30},
|
||||
["utura"] = {level = 50, manaCost = 75},
|
||||
["utura gran"] = {level = 100, manaCost = 165},
|
||||
["utura mas sio"] = {level = 32, manaCost = 0}
|
||||
}
|
||||
|
||||
function getSpellCoolDown(text)
|
||||
if not text then return false end
|
||||
if text:lower() == "exura" then
|
||||
return modules.game_cooldown.isCooldownIconActive(1)
|
||||
elseif text:lower() == "exura gran" then
|
||||
return modules.game_cooldown.isCooldownIconActive(2)
|
||||
elseif text:lower() == "exura vita" then
|
||||
return modules.game_cooldown.isCooldownIconActive(3)
|
||||
elseif text:lower() == "exura gran mas res" then
|
||||
return modules.game_cooldown.isCooldownIconActive(82)
|
||||
elseif string.find(text:lower(), "exura sio") then
|
||||
return modules.game_cooldown.isCooldownIconActive(84)
|
||||
elseif string.find(text:lower(), "exiva") then
|
||||
return modules.game_cooldown.isCooldownIconActive(20)
|
||||
elseif string.find(text:lower(), "exani hur") then
|
||||
return modules.game_cooldown.isCooldownIconActive(81)
|
||||
elseif string.find(text:lower(), "utevo res ina") then
|
||||
return modules.game_cooldown.isCooldownIconActive(38)
|
||||
elseif string.find(text:lower(), 'utevo res "' ) then
|
||||
return modules.game_cooldown.isCooldownIconActive(9)
|
||||
elseif text:lower() == "exana pox" then
|
||||
return modules.game_cooldown.isCooldownIconActive(29)
|
||||
elseif text:lower() == "utevo lux" then
|
||||
return modules.game_cooldown.isCooldownIconActive(10)
|
||||
elseif text:lower() == "exani tera" then
|
||||
return modules.game_cooldown.isCooldownIconActive(76)
|
||||
elseif text:lower() == "exori vis" then
|
||||
return modules.game_cooldown.isCooldownIconActive(88)
|
||||
elseif text:lower() == "utevo gran lux" then
|
||||
return modules.game_cooldown.isCooldownIconActive(11)
|
||||
elseif text:lower() == "utani hur" then
|
||||
return modules.game_cooldown.isCooldownIconActive(6)
|
||||
elseif text:lower() == "exori tera" then
|
||||
return modules.game_cooldown.isCooldownIconActive(113)
|
||||
elseif text:lower() == "exevo pan" then
|
||||
return modules.game_cooldown.isCooldownIconActive(42)
|
||||
elseif text:lower() == "utamo vita" then
|
||||
return modules.game_cooldown.isCooldownIconActive(44)
|
||||
elseif text:lower() == "exori flam" then
|
||||
return modules.game_cooldown.isCooldownIconActive(89)
|
||||
elseif text:lower() == "exori frigo" then
|
||||
return modules.game_cooldown.isCooldownIconActive(112)
|
||||
elseif text:lower() == "exori moe ico" then
|
||||
return modules.game_cooldown.isCooldownIconActive(148)
|
||||
elseif text:lower() == "exevo frigo hur" then
|
||||
return modules.game_cooldown.isCooldownIconActive(121)
|
||||
elseif text:lower() == "utani gran hur" then
|
||||
return modules.game_cooldown.isCooldownIconActive(39)
|
||||
elseif text:lower() == "exana vis" then
|
||||
return modules.game_cooldown.isCooldownIconActive(146)
|
||||
elseif text:lower() == "utevo vis lux" then
|
||||
return modules.game_cooldown.isCooldownIconActive(75)
|
||||
elseif text:lower() == "exana flam" then
|
||||
return modules.game_cooldown.isCooldownIconActive(145)
|
||||
elseif text:lower() == "utana vid" then
|
||||
return modules.game_cooldown.isCooldownIconActive(45)
|
||||
elseif text:lower() == "exevo tera hur" then
|
||||
return modules.game_cooldown.isCooldownIconActive(120)
|
||||
elseif text:lower() == "exevo gran frigo hur" then
|
||||
return modules.game_cooldown.isCooldownIconActive(43)
|
||||
elseif text:lower() == "exana kor" then
|
||||
return modules.game_cooldown.isCooldownIconActive(144)
|
||||
elseif text:lower() == "utori pox" then
|
||||
return modules.game_cooldown.isCooldownIconActive(142)
|
||||
elseif text:lower() == "exevo gran mas tera" then
|
||||
return modules.game_cooldown.isCooldownIconActive(56)
|
||||
elseif text:lower() == "exevo gran mas frigo" then
|
||||
return modules.game_cooldown.isCooldownIconActive(118)
|
||||
elseif text:lower() == "exevo gran mas tera" then
|
||||
return modules.game_cooldown.isCooldownIconActive(56)
|
||||
elseif text:lower() == "exori gran tera" then
|
||||
return modules.game_cooldown.isCooldownIconActive(153)
|
||||
elseif text:lower() == "exori max tera" then
|
||||
return modules.game_cooldown.isCooldownIconActive(157)
|
||||
elseif text:lower() == "exori gran frigo" then
|
||||
return modules.game_cooldown.isCooldownIconActive(152)
|
||||
elseif text:lower() == "exori max frigo" then
|
||||
return modules.game_cooldown.isCooldownIconActive(156)
|
||||
elseif text:lower() == "exori max tera" then
|
||||
return modules.game_cooldown.isCooldownIconActive(157)
|
||||
elseif text:lower() == "exori con" then
|
||||
return modules.game_cooldown.isCooldownIconActive(111)
|
||||
elseif text:lower() == "exura san" then
|
||||
return modules.game_cooldown.isCooldownIconActive(125)
|
||||
elseif text:lower() == "exevo mas san" then
|
||||
return modules.game_cooldown.isCooldownIconActive(124)
|
||||
elseif text:lower() == "utura" then
|
||||
return modules.game_cooldown.isCooldownIconActive(159)
|
||||
elseif text:lower() == "utura gran" then
|
||||
return modules.game_cooldown.isCooldownIconActive(160)
|
||||
elseif text:lower() == "utamo tempo san" then
|
||||
return modules.game_cooldown.isCooldownIconActive(134)
|
||||
elseif text:lower() == "utito tempo san" then
|
||||
return modules.game_cooldown.isCooldownIconActive(135)
|
||||
elseif text:lower() == "exura gran san" then
|
||||
return modules.game_cooldown.isCooldownIconActive(36)
|
||||
elseif text:lower() == "utori san" then
|
||||
return modules.game_cooldown.isCooldownIconActive(143)
|
||||
elseif text:lower() == "exana mort" then
|
||||
return modules.game_cooldown.isCooldownIconActive(147)
|
||||
elseif text:lower() == "exori gran con" then
|
||||
return modules.game_cooldown.isCooldownIconActive(57)
|
||||
elseif text:lower() == "exura ico" then
|
||||
return modules.game_cooldown.isCooldownIconActive(123)
|
||||
elseif text:lower() == "exeta res" then
|
||||
return modules.game_cooldown.isCooldownIconActive(93)
|
||||
elseif text:lower() == "utani tempo hur" then
|
||||
return modules.game_cooldown.isCooldownIconActive(131)
|
||||
elseif text:lower() == "utamo tempo" then
|
||||
return modules.game_cooldown.isCooldownIconActive(132)
|
||||
elseif text:lower() == "utito tempo" then
|
||||
return modules.game_cooldown.isCooldownIconActive(133)
|
||||
elseif text:lower() == "exura gran ico" then
|
||||
return modules.game_cooldown.isCooldownIconActive(158)
|
||||
elseif text:lower() == "exori hur" then
|
||||
return modules.game_cooldown.isCooldownIconActive(107)
|
||||
elseif text:lower() == "exori ico" then
|
||||
return modules.game_cooldown.isCooldownIconActive(61)
|
||||
elseif text:lower() == "exori" then
|
||||
return modules.game_cooldown.isCooldownIconActive(80)
|
||||
elseif text:lower() == "exori mas" then
|
||||
return modules.game_cooldown.isCooldownIconActive(106)
|
||||
elseif text:lower() == "exori gran" then
|
||||
return modules.game_cooldown.isCooldownIconActive(105)
|
||||
elseif text:lower() == "exori gran ico" then
|
||||
return modules.game_cooldown.isCooldownIconActive(62)
|
||||
elseif text:lower() == "exori min" then
|
||||
return modules.game_cooldown.isCooldownIconActive(59)
|
||||
elseif text:lower() == "exevo gran mas flam" then
|
||||
return modules.game_cooldown.isCooldownIconActive(24)
|
||||
elseif text:lower() == "exevo gran mas vis" then
|
||||
return modules.game_cooldown.isCooldownIconActive(119)
|
||||
elseif text:lower() == "exevo vis hur" then
|
||||
return modules.game_cooldown.isCooldownIconActive(13)
|
||||
elseif text:lower() == "exevo vis lux" then
|
||||
return modules.game_cooldown.isCooldownIconActive(22)
|
||||
elseif text:lower() == "exevo gran vis lux" then
|
||||
return modules.game_cooldown.isCooldownIconActive(23)
|
||||
elseif text:lower() == "exori amp vis" then
|
||||
return modules.game_cooldown.isCooldownIconActive(149)
|
||||
elseif text:lower() == "exori gran vis" then
|
||||
return modules.game_cooldown.isCooldownIconActive(151)
|
||||
elseif text:lower() == "exori gran flam" then
|
||||
return modules.game_cooldown.isCooldownIconActive(150)
|
||||
elseif text:lower() == "exori max vis" then
|
||||
return modules.game_cooldown.isCooldownIconActive(155)
|
||||
elseif text:lower() == "exori max flam" then
|
||||
return modules.game_cooldown.isCooldownIconActive(154)
|
||||
elseif text:lower() == "exevo gran flam hur" then
|
||||
return modules.game_cooldown.isCooldownIconActive(150)
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
storage.isUsing = false
|
||||
|
||||
onUse(function(pos, itemId, stackPos, subType)
|
||||
if pos.x < 65000 then
|
||||
storage.isUsing = true
|
||||
end
|
||||
schedule(1500, function() storage.isUsing = false end)
|
||||
end)
|
||||
|
||||
function string.starts(String,Start)
|
||||
return string.sub(String,1,string.len(Start))==Start
|
||||
end
|
||||
|
||||
function isFriend(name)
|
||||
if not name then return false end
|
||||
|
||||
if getCreatureByName(name, true):isPlayer() and not getCreatureByName(name, true):isLocalPlayer() and table.find(storage.playerList.friendList, name) or string.find(storage.serverMembers, name) or table.find(storage.playerList.friendList, name:lower()) or (storage.playerList.groupMembers and ((getCreatureByName(name, true):getShield() >= 3 and getCreatureByName(name, true):getShield() <= 10) or getCreatureByName(name, true):getEmblem() == 2)) then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function isEnemy(name)
|
||||
if not name then return false end
|
||||
|
||||
if getCreatureByName(name, true):isPlayer() and not getCreatureByName(name, true):isLocalPlayer() and table.find(storage.playerList.enemyList, name) or table.find(storage.playerList.enemyList, name:lower()) or (storage.playerList.marks and not isFriend(name)) then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function isAttSpell(expr)
|
||||
if string.starts(expr, "exori") or string.starts(expr, "exevo") then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function getPlayerByName(name)
|
||||
if not name then
|
||||
return false
|
||||
end
|
||||
|
||||
local creature
|
||||
for i, spec in pairs(getSpectators()) do
|
||||
if spec:isPlayer() and spec:getName():lower() == name:lower() then
|
||||
creature = spec
|
||||
end
|
||||
end
|
||||
|
||||
if creature then
|
||||
return creature
|
||||
end
|
||||
end
|
||||
|
||||
function getActiveItemId(id)
|
||||
if not id then
|
||||
return false
|
||||
end
|
||||
|
||||
if id == 3049 then
|
||||
return 3086
|
||||
elseif id == 3050 then
|
||||
return 3087
|
||||
elseif id == 3051 then
|
||||
return 3088
|
||||
elseif id == 3052 then
|
||||
return 3089
|
||||
elseif id == 3053 then
|
||||
return 3090
|
||||
elseif id == 3091 then
|
||||
return 3094
|
||||
elseif id == 3092 then
|
||||
return 3095
|
||||
elseif id == 3093 then
|
||||
return 3096
|
||||
elseif id == 3097 then
|
||||
return 3099
|
||||
elseif id == 3098 then
|
||||
return 3100
|
||||
elseif id == 16114 then
|
||||
return 16264
|
||||
elseif id == 23531 then
|
||||
return 23532
|
||||
elseif id == 23533 then
|
||||
return 23534
|
||||
elseif id == 23529 then
|
||||
return 23530
|
||||
else
|
||||
return id
|
||||
end
|
||||
end
|
||||
|
||||
function getInactiveItemId(id)
|
||||
if not id then
|
||||
return false
|
||||
end
|
||||
|
||||
if id == 3086 then
|
||||
return 3049
|
||||
elseif id == 3087 then
|
||||
return 3050
|
||||
elseif id == 3088 then
|
||||
return 3051
|
||||
elseif id == 3089 then
|
||||
return 3052
|
||||
elseif id == 3090 then
|
||||
return 3053
|
||||
elseif id == 3094 then
|
||||
return 3091
|
||||
elseif id == 3095 then
|
||||
return 3092
|
||||
elseif id == 3096 then
|
||||
return 3093
|
||||
elseif id == 3099 then
|
||||
return 3097
|
||||
elseif id == 3100 then
|
||||
return 3098
|
||||
elseif id == 16264 then
|
||||
return 16114
|
||||
elseif id == 23532 then
|
||||
return 23531
|
||||
elseif id == 23534 then
|
||||
return 23533
|
||||
elseif id == 23530 then
|
||||
return 23529
|
||||
else
|
||||
return id
|
||||
end
|
||||
end
|
||||
|
||||
function getMonstersInRange(pos, range)
|
||||
if not pos or not range then
|
||||
return false
|
||||
end
|
||||
local monsters = 0
|
||||
for i, spec in pairs(getSpectators()) do
|
||||
if spec:isMonster() and spec:getType() ~= 3 and getDistanceBetween(pos, spec:getPosition()) < range then
|
||||
monsters = monsters + 1
|
||||
end
|
||||
end
|
||||
return monsters
|
||||
end
|
||||
|
||||
function distanceFromPlayer(coords)
|
||||
if not coords then
|
||||
return false
|
||||
end
|
||||
return getDistanceBetween(pos(), coords)
|
||||
end
|
||||
|
||||
function getMonsters(range, multifloor)
|
||||
if not range then
|
||||
range = 10
|
||||
end
|
||||
local mobs = 0;
|
||||
for _, spec in pairs(getSpectators(multifloor)) do
|
||||
mobs = spec:getType() ~= 3 and spec:isMonster() and distanceFromPlayer(spec:getPosition()) <= range and mobs + 1 or mobs;
|
||||
end
|
||||
return mobs;
|
||||
end
|
||||
|
||||
function getPlayers(range, multifloor)
|
||||
if not range then
|
||||
range = 10
|
||||
end
|
||||
local specs = 0;
|
||||
for _, spec in pairs(getSpectators(multifloor)) do
|
||||
specs = not spec:isLocalPlayer() and spec:isPlayer() and distanceFromPlayer(spec:getPosition()) <= range and not ((spec:getShield() >= 3 and spec:getShield() <= 10) or spec:getEmblem() == 1) and specs + 1 or specs;
|
||||
end
|
||||
return specs;
|
||||
end
|
||||
|
||||
function isSafe(range, multifloor, padding)
|
||||
local onSame = 0
|
||||
local onAnother = 0
|
||||
if not multifloor and padding then
|
||||
multifloor = false
|
||||
padding = false
|
||||
end
|
||||
|
||||
for _, spec in pairs(getSpectators(multifloor)) do
|
||||
if spec:isPlayer() and not spec:isLocalPlayer() and not isFriend(spec:getName()) then
|
||||
if spec:getPosition().z == posz() and distanceFromPlayer(spec:getPosition()) <= range then
|
||||
onSame = onSame + 1
|
||||
end
|
||||
if multifloor and padding and spec:getPosition().z ~= posz() and distanceFromPlayer(spec:getPosition()) <= (range + padding) then
|
||||
onAnother = onAnother + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if onSame + onAnother > 0 then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function getAllPlayers(range, multifloor)
|
||||
if not range then
|
||||
range = 10
|
||||
end
|
||||
local specs = 0;
|
||||
for _, spec in pairs(g_map.getSpectators(multifloor)) do
|
||||
specs = not spec:isLocalPlayer() and spec:isPlayer() and distanceFromPlayer(spec:getPosition()) <= range and specs + 1 or specs;
|
||||
end
|
||||
return specs;
|
||||
end
|
||||
|
||||
function getNpcs(range, multifloor)
|
||||
if not range then
|
||||
range = 10
|
||||
end
|
||||
local npcs = 0;
|
||||
for _, spec in pairs(g_map.getSpectators(multifloor)) do
|
||||
npcs = spec:isNpc() and distanceFromPlayer(spec:getPosition()) <= range and npcs + 1 or npcs;
|
||||
end
|
||||
return npcs;
|
||||
end
|
||||
|
||||
function itemAmount(id)
|
||||
local totalItemCount = 0
|
||||
for _, container in pairs(getContainers()) do
|
||||
for _, item in ipairs(container:getItems()) do
|
||||
totalItemCount = item:getId() == id and totalItemCount + item:getCount() or totalItemCount
|
||||
end
|
||||
end
|
||||
if getHead() and getHead():getId() == id then
|
||||
totalItemCount = totalItemCount + getHead():getCount()
|
||||
end
|
||||
if getNeck() and getNeck():getId() == id then
|
||||
totalItemCount = totalItemCount + getNeck():getCount()
|
||||
end
|
||||
if getBack() and getBack():getId() == id then
|
||||
totalItemCount = totalItemCount + getBack():getCount()
|
||||
end
|
||||
if getBody() and getBody():getId() == id then
|
||||
totalItemCount = totalItemCount + getBody():getCount()
|
||||
end
|
||||
if getRight() and getRight():getId() == id then
|
||||
totalItemCount = totalItemCount + getRight():getCount()
|
||||
end
|
||||
if getLeft() and getLeft():getId() == id then
|
||||
totalItemCount = totalItemCount + getLeft():getCount()
|
||||
end
|
||||
if getLeg() and getLeg():getId() == id then
|
||||
totalItemCount = totalItemCount + getLeg():getCount()
|
||||
end
|
||||
if getFeet() and getFeet():getId() == id then
|
||||
totalItemCount = totalItemCount + getFeet():getCount()
|
||||
end
|
||||
if getFinger() and getFinger():getId() == id then
|
||||
totalItemCount = totalItemCount + getFinger():getCount()
|
||||
end
|
||||
if getAmmo() and getAmmo():getId() == id then
|
||||
totalItemCount = totalItemCount + getAmmo():getCount()
|
||||
end
|
||||
return totalItemCount
|
||||
end
|
||||
|
||||
function cordsToPos(x, y, z)
|
||||
if not x or not y or not z then
|
||||
return false
|
||||
end
|
||||
local tilePos = pos()
|
||||
tilePos.x = x
|
||||
tilePos.y = y
|
||||
tilePos.z = z
|
||||
return tilePos
|
||||
end
|
||||
|
||||
function reachGroundItem(id)
|
||||
local targetTile
|
||||
for _, tile in ipairs(g_map.getTiles(posz())) do
|
||||
if tile:getTopUseThing():getId() == id then
|
||||
targetTile = tile:getPosition()
|
||||
end
|
||||
end
|
||||
if distanceFromPlayer(targetTile) > 1 then
|
||||
if autoWalk(targetTile, 10, {ignoreNonPathable = true, precision=1}) then
|
||||
delay(200)
|
||||
end
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function useGroundItem(id)
|
||||
if not id then
|
||||
return false
|
||||
end
|
||||
local targetTile = nil
|
||||
for _, tile in ipairs(g_map.getTiles(posz())) do
|
||||
if tile:getTopUseThing():getId() == id then
|
||||
targetTile = tile:getPosition()
|
||||
end
|
||||
end
|
||||
if targetTile then
|
||||
if distanceFromPlayer(targetTile) > 1 then
|
||||
if autoWalk(targetTile, 20, {ignoreNonWalkable = true, ignoreNonPathable = true, precision=1}) then
|
||||
delay(200)
|
||||
end
|
||||
else
|
||||
g_game.use(g_map.getTile(targetTile):getTopUseThing())
|
||||
return true
|
||||
end
|
||||
else
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
|
||||
function target()
|
||||
if not g_game.isAttacking() then
|
||||
return
|
||||
else
|
||||
return g_game.getAttackingCreature()
|
||||
end
|
||||
end
|
||||
|
||||
function getTarget()
|
||||
return target()
|
||||
end
|
||||
|
||||
function targetPos(dist)
|
||||
if not g_game.isAttacking() then
|
||||
return
|
||||
end
|
||||
if dist then
|
||||
return distanceFromPlayer(target():getPosition())
|
||||
else
|
||||
return target():getPosition()
|
||||
end
|
||||
end
|
||||
|
||||
-- for gunzodus
|
||||
function reopenPurse()
|
||||
schedule(100, function() g_game.open(findItem(23721)) return true end)
|
||||
schedule(1400, function() g_game.open(findItem(23721)) return true end)
|
||||
CaveBot.delay(1500)
|
||||
return true
|
||||
end
|
||||
|
||||
-- getSpectator patterns
|
||||
|
||||
function getCreaturesInArea(param1, param2, param3)
|
||||
-- param1 - pos/creature
|
||||
-- param2 - pattern
|
||||
-- param3 - type of return
|
||||
-- 1 - everyone, 2 - monsters, 3 - players
|
||||
local specs = 0
|
||||
local monsters = 0
|
||||
local players = 0
|
||||
for i, spec in pairs(getSpectators(param1, param2)) do
|
||||
if spec ~= player then
|
||||
specs = specs + 1
|
||||
if spec:isMonster() then
|
||||
monsters = monsters + 1
|
||||
elseif spec:isPlayer() and not isFriend(spec:getName()) then
|
||||
players = players +1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if param3 == 1 then
|
||||
return specs
|
||||
elseif param3 == 2 then
|
||||
return monsters
|
||||
else
|
||||
return players
|
||||
end
|
||||
end
|
||||
|
||||
function getBestTileByPatern(pattern, specType, maxDist, safe)
|
||||
if not pattern or not specType then return end
|
||||
if not maxDist then maxDist = 4 end
|
||||
if not safe then safe = false end
|
||||
|
||||
local fieldList = {}
|
||||
local bestTile = nil
|
||||
-- best area tile to use
|
||||
for _, tile in pairs(g_map.getTiles(posz())) do
|
||||
if tile:canShoot() and distanceFromPlayer(tile:getPosition()) <= maxDist and tile:isWalkable() and getCreaturesInArea(tile:getPosition(), pattern, specType) > 0 and (not safe or getCreaturesInArea(tile:getPosition(), pattern, 3) == 0) then
|
||||
table.insert(fieldList, {pos = tile, count = getCreaturesInArea(tile:getPosition(), pattern, specType)})
|
||||
end
|
||||
end
|
||||
table.sort(fieldList, function(a,b) return a.count > b.count end)
|
||||
|
||||
bestTile = fieldList[1]
|
||||
|
||||
if bestTile then
|
||||
return bestTile
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
LargeUeArea = [[
|
||||
0000001000000
|
||||
0000011100000
|
||||
0000111110000
|
||||
0001111111000
|
||||
0011111111100
|
||||
0111111111110
|
||||
1111111111111
|
||||
0111111111110
|
||||
0011111111100
|
||||
0001111111000
|
||||
0000111110000
|
||||
0000011100000
|
||||
0000001000000
|
||||
]]
|
||||
|
||||
NormalUeAreaMs = [[
|
||||
00000100000
|
||||
00011111000
|
||||
00111111100
|
||||
01111111110
|
||||
01111111110
|
||||
11111111111
|
||||
01111111110
|
||||
01111111110
|
||||
00111111100
|
||||
00001110000
|
||||
00000100000
|
||||
]]
|
||||
|
||||
NormalUeAreaEd = [[
|
||||
00000100000
|
||||
00001110000
|
||||
00011111000
|
||||
00111111100
|
||||
01111111110
|
||||
11111111111
|
||||
01111111110
|
||||
00111111100
|
||||
00011111000
|
||||
00001110000
|
||||
00000100000
|
||||
]]
|
||||
|
||||
smallUeArea = [[
|
||||
0011100
|
||||
0111110
|
||||
1111111
|
||||
1111111
|
||||
1111111
|
||||
0111110
|
||||
0011100
|
||||
]]
|
||||
|
||||
largeRuneArea = [[
|
||||
0011100
|
||||
0111110
|
||||
1111111
|
||||
1111111
|
||||
1111111
|
||||
0111110
|
||||
0011100
|
||||
]]
|
||||
|
||||
adjacentArea = [[
|
||||
111
|
||||
101
|
||||
111
|
||||
]]
|
||||
|
||||
longBeamArea = [[
|
||||
0000000N0000000
|
||||
0000000N0000000
|
||||
0000000N0000000
|
||||
0000000N0000000
|
||||
0000000N0000000
|
||||
0000000N0000000
|
||||
0000000N0000000
|
||||
WWWWWWW0EEEEEEE
|
||||
0000000S0000000
|
||||
0000000S0000000
|
||||
0000000S0000000
|
||||
0000000S0000000
|
||||
0000000S0000000
|
||||
0000000S0000000
|
||||
0000000S0000000
|
||||
]]
|
||||
|
||||
shortBeamArea = [[
|
||||
00000100000
|
||||
00000100000
|
||||
00000100000
|
||||
00000100000
|
||||
00000100000
|
||||
EEEEE0WWWWW
|
||||
00000S00000
|
||||
00000S00000
|
||||
00000S00000
|
||||
00000S00000
|
||||
00000S00000
|
||||
]]
|
||||
|
||||
newWaveArea = [[
|
||||
000NNNNN000
|
||||
000NNNNN000
|
||||
0000NNN0000
|
||||
WW00NNN00EE
|
||||
WWWW0N0EEEE
|
||||
WWWWW0EEEEE
|
||||
WWWW0S0EEEE
|
||||
WW00SSS00EE
|
||||
0000SSS0000
|
||||
000SSSSS000
|
||||
000SSSSS000
|
||||
]]
|
||||
|
||||
bigWaveArea = [[
|
||||
0000NNN0000
|
||||
0000NNN0000
|
||||
0000NNN0000
|
||||
00000N00000
|
||||
WWW00N00EEE
|
||||
WWWWW0EEEEE
|
||||
WWW00S00EEE
|
||||
00000S00000
|
||||
0000SSS0000
|
||||
0000SSS0000
|
||||
0000SSS0000
|
||||
]]
|
||||
|
||||
|
||||
smallWaveArea = [[
|
||||
00NNN00
|
||||
00NNN00
|
||||
WW0N0EE
|
||||
WWW0EEE
|
||||
WW0S0EE
|
||||
00SSS00
|
||||
00SSS00
|
||||
]]
|
||||
|
||||
diamondArrowArea = [[
|
||||
01110
|
||||
11111
|
||||
11111
|
||||
11111
|
||||
01110
|
||||
]]
|
147
modules/game_bot/default_configs/vithrax_1.1/0 BotSever.lua
Normal file
147
modules/game_bot/default_configs/vithrax_1.1/0 BotSever.lua
Normal file
@ -0,0 +1,147 @@
|
||||
setDefaultTab("Main")
|
||||
|
||||
BotPanelName = "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(BotPanelName)
|
||||
|
||||
if not storage[BotPanelName] then
|
||||
storage[BotPanelName] = {
|
||||
manaInfo = true,
|
||||
mwallInfo = true
|
||||
}
|
||||
end
|
||||
|
||||
if not storage.BotServerChannel then
|
||||
storage.BotServerChannel = tostring(math.random(1000000000000,9999999999999))
|
||||
end
|
||||
|
||||
local channel = tostring(storage.BotServerChannel)
|
||||
BotServer.init(name(), channel)
|
||||
|
||||
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(storage[BotPanelName].manaInfo)
|
||||
botServerWindow.Features.Feature1.onClick = function(widget)
|
||||
storage[BotPanelName].manaInfo = not storage[BotPanelName].manaInfo
|
||||
widget:setOn(storage[BotPanelName].manaInfo)
|
||||
end
|
||||
|
||||
botServerWindow.Features.Feature2:setOn(storage[BotPanelName].mwallInfo)
|
||||
botServerWindow.Features.Feature2.onClick = function(widget)
|
||||
storage[BotPanelName].mwallInfo = not storage[BotPanelName].mwallInfo
|
||||
widget:setOn(storage[BotPanelName].mwallInfo)
|
||||
end
|
||||
end
|
||||
|
||||
function updateStatusText()
|
||||
if BotServer._websocket then
|
||||
botServerWindow.Data.ServerStatus:setText("CONNECTED")
|
||||
if serverCount then
|
||||
botServerWindow.Data.Participants:setText(#serverCount)
|
||||
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)
|
||||
storage.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
|
||||
|
||||
storage[BotPanelName].mwalls = {}
|
||||
BotServer.listen("mwall", function(name, message)
|
||||
if storage[BotPanelName].mwallInfo then
|
||||
if not storage[BotPanelName].mwalls[message["pos"]] or storage[BotPanelName].mwalls[message["pos"]] < now then
|
||||
storage[BotPanelName].mwalls[message["pos"]] = now + message["duration"] - 150 -- 150 is latency correction
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
BotServer.listen("mana", function(name, message)
|
||||
if storage[BotPanelName].manaInfo then
|
||||
local creature = getPlayerByName(name)
|
||||
if creature then
|
||||
creature:setManaPercent(message["mana"])
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
onAddThing(function(tile, thing)
|
||||
if storage[BotPanelName].mwallInfo then
|
||||
if thing:isItem() and thing:getId() == 2129 then
|
||||
local pos = tile:getPosition().x .. "," .. tile:getPosition().y .. "," .. tile:getPosition().z
|
||||
if not storage[BotPanelName].mwalls[pos] or storage[BotPanelName].mwalls[pos] < now then
|
||||
storage[BotPanelName].mwalls[pos] = now + 20000
|
||||
BotServer.send("mwall", {pos=pos, duration=20000})
|
||||
end
|
||||
tile:setTimer(storage[BotPanelName].mwalls[pos] - now)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local lastMana = 0
|
||||
macro(100, function()
|
||||
if storage[BotPanelName].manaInfo then
|
||||
if manapercent() ~= lastMana then
|
||||
lastMana = manapercent()
|
||||
BotServer.send("mana", {mana=lastMana})
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
addSeparator()
|
178
modules/game_bot/default_configs/vithrax_1.1/1 alarms.lua
Normal file
178
modules/game_bot/default_configs/vithrax_1.1/1 alarms.lua
Normal file
@ -0,0 +1,178 @@
|
||||
alarmsPanelName = "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(alarmsPanelName)
|
||||
|
||||
if not storage[alarmsPanelName] then
|
||||
storage[alarmsPanelName] = {
|
||||
enabled = false,
|
||||
playerAttack = false,
|
||||
playerDetected = false,
|
||||
playerDetectedLogout = false,
|
||||
creatureDetected = false,
|
||||
healthBelow = false,
|
||||
healthValue = 40,
|
||||
manaBelow = false,
|
||||
manaValue = 50,
|
||||
privateMessage = false
|
||||
}
|
||||
end
|
||||
|
||||
ui.title:setOn(storage[alarmsPanelName].enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
storage[alarmsPanelName].enabled = not storage[alarmsPanelName].enabled
|
||||
widget:setOn(storage[alarmsPanelName].enabled)
|
||||
end
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
alarmsWindow = g_ui.createWidget('AlarmsWindow', rootWidget)
|
||||
alarmsWindow:hide()
|
||||
|
||||
alarmsWindow.closeButton.onClick = function(widget)
|
||||
alarmsWindow:hide()
|
||||
end
|
||||
|
||||
alarmsWindow.playerAttack:setOn(storage[alarmsPanelName].playerAttack)
|
||||
alarmsWindow.playerAttack.onClick = function(widget)
|
||||
storage[alarmsPanelName].playerAttack = not storage[alarmsPanelName].playerAttack
|
||||
widget:setOn(storage[alarmsPanelName].playerAttack)
|
||||
end
|
||||
|
||||
alarmsWindow.playerDetected:setOn(storage[alarmsPanelName].playerDetected)
|
||||
alarmsWindow.playerDetected.onClick = function(widget)
|
||||
storage[alarmsPanelName].playerDetected = not storage[alarmsPanelName].playerDetected
|
||||
widget:setOn(storage[alarmsPanelName].playerDetected)
|
||||
end
|
||||
|
||||
alarmsWindow.playerDetectedLogout:setChecked(storage[alarmsPanelName].playerDetectedLogout)
|
||||
alarmsWindow.playerDetectedLogout.onClick = function(widget)
|
||||
storage[alarmsPanelName].playerDetectedLogout = not storage[alarmsPanelName].playerDetectedLogout
|
||||
widget:setChecked(storage[alarmsPanelName].playerDetectedLogout)
|
||||
end
|
||||
|
||||
alarmsWindow.creatureDetected:setOn(storage[alarmsPanelName].creatureDetected)
|
||||
alarmsWindow.creatureDetected.onClick = function(widget)
|
||||
storage[alarmsPanelName].creatureDetected = not storage[alarmsPanelName].creatureDetected
|
||||
widget:setOn(storage[alarmsPanelName].creatureDetected)
|
||||
end
|
||||
|
||||
alarmsWindow.healthBelow:setOn(storage[alarmsPanelName].healthBelow)
|
||||
alarmsWindow.healthBelow.onClick = function(widget)
|
||||
storage[alarmsPanelName].healthBelow = not storage[alarmsPanelName].healthBelow
|
||||
widget:setOn(storage[alarmsPanelName].healthBelow)
|
||||
end
|
||||
|
||||
alarmsWindow.healthValue.onValueChange = function(scroll, value)
|
||||
storage[alarmsPanelName].healthValue = value
|
||||
alarmsWindow.healthBelow:setText("Health < " .. storage[alarmsPanelName].healthValue .. "%")
|
||||
end
|
||||
alarmsWindow.healthValue:setValue(storage[alarmsPanelName].healthValue)
|
||||
|
||||
alarmsWindow.manaBelow:setOn(storage[alarmsPanelName].manaBelow)
|
||||
alarmsWindow.manaBelow.onClick = function(widget)
|
||||
storage[alarmsPanelName].manaBelow = not storage[alarmsPanelName].manaBelow
|
||||
widget:setOn(storage[alarmsPanelName].manaBelow)
|
||||
end
|
||||
|
||||
alarmsWindow.manaValue.onValueChange = function(scroll, value)
|
||||
storage[alarmsPanelName].manaValue = value
|
||||
alarmsWindow.manaBelow:setText("Mana < " .. storage[alarmsPanelName].manaValue .. "%")
|
||||
end
|
||||
alarmsWindow.manaValue:setValue(storage[alarmsPanelName].manaValue)
|
||||
|
||||
alarmsWindow.privateMessage:setOn(storage[alarmsPanelName].privateMessage)
|
||||
alarmsWindow.privateMessage.onClick = function(widget)
|
||||
storage[alarmsPanelName].privateMessage = not storage[alarmsPanelName].privateMessage
|
||||
widget:setOn(storage[alarmsPanelName].privateMessage)
|
||||
end
|
||||
|
||||
onTextMessage(function(mode, text)
|
||||
if storage[alarmsPanelName].enabled and storage[alarmsPanelName].playerAttack and mode == 16 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")
|
||||
end
|
||||
end)
|
||||
|
||||
macro(100, function()
|
||||
if not storage[alarmsPanelName].enabled then
|
||||
return
|
||||
end
|
||||
if storage[alarmsPanelName].playerDetected then
|
||||
for _, spec in ipairs(getSpectators()) do
|
||||
if spec:isPlayer() and spec:getName() ~= name() then
|
||||
specPos = spec:getPosition()
|
||||
if math.max(math.abs(posx()-specPos.x), math.abs(posy()-specPos.y)) <= 8 then
|
||||
playSound("/sounds/Player_Detected.ogg")
|
||||
delay(1500)
|
||||
if storage[alarmsPanelName].playerDetectedLogout then
|
||||
modules.game_interface.tryLogout(false)
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if storage[alarmsPanelName].creatureDetected then
|
||||
for _, spec in ipairs(getSpectators()) do
|
||||
if not spec:isPlayer()then
|
||||
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)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if storage[alarmsPanelName].healthBelow then
|
||||
if hppercent() <= storage[alarmsPanelName].healthValue then
|
||||
playSound("/sounds/Low_Health.ogg")
|
||||
delay(1500)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if storage[alarmsPanelName].manaBelow then
|
||||
if manapercent() <= storage[alarmsPanelName].manaValue then
|
||||
playSound("/sounds/Low_Mana.ogg")
|
||||
delay(1500)
|
||||
return
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
onTalk(function(name, level, mode, text, channelId, pos)
|
||||
if mode == 4 and storage[alarmsPanelName].enabled and storage[alarmsPanelName].privateMessage then
|
||||
playSound("/sounds/Private_Message.ogg")
|
||||
return
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
ui.alerts.onClick = function(widget)
|
||||
alarmsWindow:show()
|
||||
alarmsWindow:raise()
|
||||
alarmsWindow:focus()
|
||||
end
|
440
modules/game_bot/default_configs/vithrax_1.1/1 combo.lua
Normal file
440
modules/game_bot/default_configs/vithrax_1.1/1 combo.lua
Normal file
@ -0,0 +1,440 @@
|
||||
ComboPanelName = "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(ComboPanelName)
|
||||
|
||||
if not storage[ComboPanelName] then
|
||||
storage[ComboPanelName] = {
|
||||
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
|
||||
|
||||
ui.title:setOn(storage[ComboPanelName].enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
storage[ComboPanelName].enabled = not storage[ComboPanelName].enabled
|
||||
widget:setOn(storage[ComboPanelName].enabled)
|
||||
end
|
||||
|
||||
ui.combos.onClick = function(widget)
|
||||
comboWindow:show()
|
||||
comboWindow:raise()
|
||||
comboWindow:focus()
|
||||
end
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
comboWindow = g_ui.createWidget('ComboWindow', rootWidget)
|
||||
comboWindow:hide()
|
||||
|
||||
-- bot item
|
||||
|
||||
comboWindow.actions.attackItem:setItemId(storage[ComboPanelName].item)
|
||||
comboWindow.actions.attackItem.onItemChange = function(widget)
|
||||
storage[ComboPanelName].item = widget:getItemId()
|
||||
end
|
||||
|
||||
-- switches
|
||||
|
||||
comboWindow.actions.commandsToggle:setOn(storage[ComboPanelName].commandsEnabled)
|
||||
comboWindow.actions.commandsToggle.onClick = function(widget)
|
||||
storage[ComboPanelName].commandsEnabled = not storage[ComboPanelName].commandsEnabled
|
||||
widget:setOn(storage[ComboPanelName].commandsEnabled)
|
||||
end
|
||||
|
||||
comboWindow.server.botServerToggle:setOn(storage[ComboPanelName].serverEnabled)
|
||||
comboWindow.server.botServerToggle.onClick = function(widget)
|
||||
storage[ComboPanelName].serverEnabled = not storage[ComboPanelName].serverEnabled
|
||||
widget:setOn(storage[ComboPanelName].serverEnabled)
|
||||
end
|
||||
|
||||
comboWindow.server.Triggers:setOn(storage[ComboPanelName].serverTriggers)
|
||||
comboWindow.server.Triggers.onClick = function(widget)
|
||||
storage[ComboPanelName].serverTriggers = not storage[ComboPanelName].serverTriggers
|
||||
widget:setOn(storage[ComboPanelName].serverTriggers)
|
||||
end
|
||||
|
||||
comboWindow.server.targetServerLeaderToggle:setOn(storage[ComboPanelName].serverLeaderTarget)
|
||||
comboWindow.server.targetServerLeaderToggle.onClick = function(widget)
|
||||
storage[ComboPanelName].serverLeaderTarget = not storage[ComboPanelName].serverLeaderTarget
|
||||
widget:setOn(storage[ComboPanelName].serverLeaderTarget)
|
||||
end
|
||||
|
||||
-- buttons
|
||||
comboWindow.closeButton.onClick = function(widget)
|
||||
comboWindow:hide()
|
||||
end
|
||||
|
||||
-- combo boxes
|
||||
|
||||
comboWindow.actions.followLeader:setOption(storage[ComboPanelName].follow)
|
||||
comboWindow.actions.followLeader.onOptionChange = function(widget)
|
||||
storage[ComboPanelName].follow = widget:getCurrentOption().text
|
||||
end
|
||||
|
||||
comboWindow.actions.attackLeaderTarget:setOption(storage[ComboPanelName].attack)
|
||||
comboWindow.actions.attackLeaderTarget.onOptionChange = function(widget)
|
||||
storage[ComboPanelName].attack = widget:getCurrentOption().text
|
||||
end
|
||||
|
||||
-- checkboxes
|
||||
comboWindow.trigger.onSayToggle:setChecked(storage[ComboPanelName].onSayEnabled)
|
||||
comboWindow.trigger.onSayToggle.onClick = function(widget)
|
||||
storage[ComboPanelName].onSayEnabled = not storage[ComboPanelName].onSayEnabled
|
||||
widget:setChecked(storage[ComboPanelName].onSayEnabled)
|
||||
end
|
||||
|
||||
comboWindow.trigger.onShootToggle:setChecked(storage[ComboPanelName].onShootEnabled)
|
||||
comboWindow.trigger.onShootToggle.onClick = function(widget)
|
||||
storage[ComboPanelName].onShootEnabled = not storage[ComboPanelName].onShootEnabled
|
||||
widget:setChecked(storage[ComboPanelName].onShootEnabled)
|
||||
end
|
||||
|
||||
comboWindow.trigger.onCastToggle:setChecked(storage[ComboPanelName].onCastEnabled)
|
||||
comboWindow.trigger.onCastToggle.onClick = function(widget)
|
||||
storage[ComboPanelName].onCastEnabled = not storage[ComboPanelName].onCastEnabled
|
||||
widget:setChecked(storage[ComboPanelName].onCastEnabled)
|
||||
end
|
||||
|
||||
comboWindow.actions.followLeaderToggle:setChecked(storage[ComboPanelName].followLeaderEnabled)
|
||||
comboWindow.actions.followLeaderToggle.onClick = function(widget)
|
||||
storage[ComboPanelName].followLeaderEnabled = not storage[ComboPanelName].followLeaderEnabled
|
||||
widget:setChecked(storage[ComboPanelName].followLeaderEnabled)
|
||||
end
|
||||
|
||||
comboWindow.actions.attackLeaderTargetToggle:setChecked(storage[ComboPanelName].attackLeaderTargetEnabled)
|
||||
comboWindow.actions.attackLeaderTargetToggle.onClick = function(widget)
|
||||
storage[ComboPanelName].attackLeaderTargetEnabled = not storage[ComboPanelName].attackLeaderTargetEnabled
|
||||
widget:setChecked(storage[ComboPanelName].attackLeaderTargetEnabled)
|
||||
end
|
||||
|
||||
comboWindow.actions.attackSpellToggle:setChecked(storage[ComboPanelName].attackSpellEnabled)
|
||||
comboWindow.actions.attackSpellToggle.onClick = function(widget)
|
||||
storage[ComboPanelName].attackSpellEnabled = not storage[ComboPanelName].attackSpellEnabled
|
||||
widget:setChecked(storage[ComboPanelName].attackSpellEnabled)
|
||||
end
|
||||
|
||||
comboWindow.actions.attackItemToggle:setChecked(storage[ComboPanelName].attackItemEnabled)
|
||||
comboWindow.actions.attackItemToggle.onClick = function(widget)
|
||||
storage[ComboPanelName].attackItemEnabled = not storage[ComboPanelName].attackItemEnabled
|
||||
widget:setChecked(storage[ComboPanelName].attackItemEnabled)
|
||||
end
|
||||
|
||||
-- text edits
|
||||
comboWindow.trigger.onSayLeader:setText(storage[ComboPanelName].sayLeader)
|
||||
comboWindow.trigger.onSayLeader.onTextChange = function(widget, text)
|
||||
storage[ComboPanelName].sayLeader = text
|
||||
end
|
||||
|
||||
comboWindow.trigger.onShootLeader:setText(storage[ComboPanelName].shootLeader)
|
||||
comboWindow.trigger.onShootLeader.onTextChange = function(widget, text)
|
||||
storage[ComboPanelName].shootLeader = text
|
||||
end
|
||||
|
||||
comboWindow.trigger.onCastLeader:setText(storage[ComboPanelName].castLeader)
|
||||
comboWindow.trigger.onCastLeader.onTextChange = function(widget, text)
|
||||
storage[ComboPanelName].castLeader = text
|
||||
end
|
||||
|
||||
comboWindow.trigger.onSayPhrase:setText(storage[ComboPanelName].sayPhrase)
|
||||
comboWindow.trigger.onSayPhrase.onTextChange = function(widget, text)
|
||||
storage[ComboPanelName].sayPhrase = text
|
||||
end
|
||||
|
||||
comboWindow.actions.attackSpell:setText(storage[ComboPanelName].spell)
|
||||
comboWindow.actions.attackSpell.onTextChange = function(widget, text)
|
||||
storage[ComboPanelName].spell = text
|
||||
end
|
||||
|
||||
comboWindow.server.botServerLeader:setText(storage[ComboPanelName].serverLeader)
|
||||
comboWindow.server.botServerLeader.onTextChange = function(widget, text)
|
||||
storage[ComboPanelName].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 storage[ComboPanelName].serverEnabled and storage[ComboPanelName].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 storage[ComboPanelName].serverEnabled and storage[ComboPanelName].enabled then
|
||||
if storage[ComboPanelName].serverLeader:len() > 0 and storage.BotServerChannel:len() > 0 then
|
||||
talkPrivate(storage[ComboPanelName].serverLeader, "request invite " .. storage.BotServerChannel)
|
||||
else
|
||||
error("Request failed. Lack of data.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
onTextMessage(function(mode, text)
|
||||
if storage[ComboPanelName].serverEnabled and storage[ComboPanelName].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() == storage[ComboPanelName].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 storage[ComboPanelName].serverEnabled and storage[ComboPanelName].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 storage[ComboPanelName].enabled and storage[ComboPanelName].enabled then
|
||||
if name:lower() == storage[ComboPanelName].sayLeader:lower() and string.find(text, storage[ComboPanelName].sayPhrase) and storage[ComboPanelName].onSayEnabled then
|
||||
startCombo = true
|
||||
end
|
||||
if (storage[ComboPanelName].castLeader and name:lower() == storage[ComboPanelName].castLeader:lower()) and isAttSpell(text) and storage[ComboPanelName].onCastEnabled then
|
||||
startCombo = true
|
||||
end
|
||||
end
|
||||
if storage[ComboPanelName].enabled and storage[ComboPanelName].commandsEnabled and (storage[ComboPanelName].shootLeader and name:lower() == storage[ComboPanelName].shootLeader:lower()) or (storage[ComboPanelName].sayLeader and name:lower() == storage[ComboPanelName].sayLeader:lower()) or (storage[ComboPanelName].castLeader and name:lower() == storage[ComboPanelName].castLeader:lower()) then
|
||||
if string.find(text, "ue") then
|
||||
say(storage[ComboPanelName].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 storage[ComboPanelName].attack == "COMMAND TARGET" then
|
||||
g_game.attack(getCreatureByName(atTarget))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if isAttSpell(text) and storage[ComboPanelName].enabled and storage[ComboPanelName].serverEnabled then
|
||||
BotServer.send("trigger", "start")
|
||||
end
|
||||
end)
|
||||
|
||||
onMissle(function(missle)
|
||||
if storage[ComboPanelName].enabled and storage[ComboPanelName].onShootEnabled then
|
||||
if not storage[ComboPanelName].shootLeader or storage[ComboPanelName].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() == storage[ComboPanelName].shootLeader:lower() then
|
||||
if storage[ComboPanelName].attackItemEnabled and storage[ComboPanelName].item and storage[ComboPanelName].item > 100 and findItem(storage[ComboPanelName].item) then
|
||||
useWith(storage[ComboPanelName].item, t1)
|
||||
end
|
||||
if storage[ComboPanelName].attackSpellEnabled and storage[ComboPanelName].spell:len() > 1 then
|
||||
say(storage[ComboPanelName].spell)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
macro(10, function()
|
||||
if not storage[ComboPanelName].enabled or not storage[ComboPanelName].attackLeaderTargetEnabled then return end
|
||||
if leaderTarget and storage[ComboPanelName].attack == "LEADER TARGET" then
|
||||
if not getTarget() or (getTarget() and getTarget():getName() ~= leaderTarget:getName()) then
|
||||
g_game.attack(leaderTarget)
|
||||
end
|
||||
end
|
||||
if storage[ComboPanelName].enabled and storage[ComboPanelName].serverEnabled and storage[ComboPanelName].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 storage[ComboPanelName].enabled or not storage[ComboPanelName].followLeaderEnabled then return end
|
||||
if leaderTarget and storage[ComboPanelName].follow == "LEADER TARGET" and leaderTarget:isPlayer() then
|
||||
toFollow = leaderTarget:getName()
|
||||
elseif storage[ComboPanelName].follow == "SERVER LEADER TARGET" and storage[ComboPanelName].serverLeader:len() ~= 0 then
|
||||
toFollow = serverTarget
|
||||
elseif storage[ComboPanelName].follow == "SERVER LEADER" and storage[ComboPanelName].serverLeader:len() ~= 0 then
|
||||
toFollow = storage[ComboPanelName].serverLeader
|
||||
elseif storage[ComboPanelName].follow == "LEADER" then
|
||||
if storage[ComboPanelName].onSayEnabled and storage[ComboPanelName].sayLeader:len() ~= 0 then
|
||||
toFollow = storage[ComboPanelName].sayLeader
|
||||
elseif storage[ComboPanelName].onCastEnabled and storage[ComboPanelName].castLeader:len() ~= 0 then
|
||||
toFollow = storage[ComboPanelName].castLeader
|
||||
elseif storage[ComboPanelName].onShootEnabled and storage[ComboPanelName].shootLeader:len() ~= 0 then
|
||||
toFollow = storage[ComboPanelName].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 autoWalk(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 storage[ComboPanelName].enabled and startCombo then
|
||||
if storage[ComboPanelName].attackItemEnabled and storage[ComboPanelName].item and storage[ComboPanelName].item > 100 and findItem(storage[ComboPanelName].item) then
|
||||
useWith(storage[ComboPanelName].item, getTarget())
|
||||
end
|
||||
if storage[ComboPanelName].attackSpellEnabled and storage[ComboPanelName].spell:len() > 1 then
|
||||
say(storage[ComboPanelName].spell)
|
||||
end
|
||||
startCombo = false
|
||||
end
|
||||
-- attack part / server
|
||||
if BotServer._websocket and storage[ComboPanelName].enabled and storage[ComboPanelName].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 storage[ComboPanelName].enabled and storage[ComboPanelName].serverEnabled then
|
||||
BotServer.listen("trigger", function(name, message)
|
||||
if message == "start" and name:lower() ~= player:getName():lower() and name:lower() == storage[ComboPanelName].serverLeader:lower() and storage[ComboPanelName].serverTriggers then
|
||||
startCombo = true
|
||||
end
|
||||
end)
|
||||
BotServer.listen("target", function(name, message)
|
||||
if name:lower() ~= player:getName():lower() and name:lower() == storage[ComboPanelName].serverLeader:lower() then
|
||||
if not target() or target():getName() == getCreatureByName(message) then
|
||||
if storage[ComboPanelName].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 storage[ComboPanelName].serverTriggers and name:lower() ~= player:getName():lower() and name:lower() == storage[ComboPanelName].serverLeader:lower() and storage[ComboPanelName].attackItemEnabled and storage[ComboPanelName].item and findItem(storage[ComboPanelName].item) then
|
||||
useWith(storage[ComboPanelName].item, tile:getTopUseThing())
|
||||
end
|
||||
end)
|
||||
end
|
183
modules/game_bot/default_configs/vithrax_1.1/1 pushmax.lua
Normal file
183
modules/game_bot/default_configs/vithrax_1.1/1 pushmax.lua
Normal file
@ -0,0 +1,183 @@
|
||||
setDefaultTab("Main")
|
||||
|
||||
pushPanelName = "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(pushPanelName)
|
||||
|
||||
if not storage[pushPanelName] then
|
||||
storage[pushPanelName] = {
|
||||
enabled = true,
|
||||
pushDelay = 1060,
|
||||
pushMaxRuneId = 3188,
|
||||
mwallBlockId = 2128,
|
||||
pushMaxKey = "PageUp"
|
||||
}
|
||||
end
|
||||
|
||||
ui.title:setOn(storage[pushPanelName].enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
storage[pushPanelName].enabled = not storage[pushPanelName].enabled
|
||||
widget:setOn(storage[pushPanelName].enabled)
|
||||
end
|
||||
|
||||
ui.push.onClick = function(widget)
|
||||
pushWindow:show()
|
||||
pushWindow:raise()
|
||||
pushWindow:focus()
|
||||
end
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
pushWindow = g_ui.createWidget('PushMaxWindow', rootWidget)
|
||||
pushWindow:hide()
|
||||
|
||||
pushWindow.closeButton.onClick = function(widget)
|
||||
pushWindow:hide()
|
||||
end
|
||||
|
||||
local updateDelayText = function()
|
||||
pushWindow.delayText:setText("Push Delay: ".. storage[pushPanelName].pushDelay)
|
||||
end
|
||||
updateDelayText()
|
||||
pushWindow.delay.onValueChange = function(scroll, value)
|
||||
storage[pushPanelName].pushDelay = value
|
||||
updateDelayText()
|
||||
end
|
||||
pushWindow.delay:setValue(storage[pushPanelName].pushDelay)
|
||||
|
||||
pushWindow.runeId.onItemChange = function(widget)
|
||||
storage[pushPanelName].pushMaxRuneId = widget:getItemId()
|
||||
end
|
||||
pushWindow.runeId:setItemId(storage[pushPanelName].pushMaxRuneId)
|
||||
pushWindow.mwallId.onItemChange = function(widget)
|
||||
storage[pushPanelName].mwallBlockId = widget:getItemId()
|
||||
end
|
||||
pushWindow.mwallId:setItemId(storage[pushPanelName].mwallBlockId)
|
||||
|
||||
pushWindow.hotkey.onTextChange = function(widget, text)
|
||||
storage[pushPanelName].pushMaxKey = text
|
||||
end
|
||||
pushWindow.hotkey:setText(storage[pushPanelName].pushMaxKey)
|
||||
end
|
||||
|
||||
|
||||
function matchPosition(curX, curY, destX, destY)
|
||||
return (curX == destX and curY == destY)
|
||||
end
|
||||
|
||||
local target
|
||||
local targetTile
|
||||
local targetOldPos
|
||||
|
||||
macro(10, function()
|
||||
if not storage[pushPanelName].enabled then return end
|
||||
if getTarget() then
|
||||
target = getTarget()
|
||||
else
|
||||
target = g_game.getFollowingCreature()
|
||||
end
|
||||
if target and targetTile then
|
||||
if not matchPosition(target:getPosition().x, target:getPosition().y, targetTile:getPosition().x, targetTile:getPosition().y) then
|
||||
local tile = g_map.getTile(target:getPosition())
|
||||
targetOldPos = tile:getPosition()
|
||||
if tile then
|
||||
if targetTile:getTopThing():getId() == 2129 or targetTile:getTopThing():getId() == 2130 or targetTile:getTopThing():getId() == tonumber(storage[pushPanelName].mwallBlockId) then
|
||||
if targetTile:getTimer() <= tonumber(storage[pushPanelName].pushDelay) then
|
||||
useWith(tonumber(storage[pushPanelName].pushMaxRuneId), target) -- 3197 desintigrate rune / 3188 firebomb rune
|
||||
delay(10)
|
||||
g_game.move(target, targetTile:getPosition())
|
||||
tile:setText("")
|
||||
targetTile:setText("")
|
||||
target = nil
|
||||
targetTile = nil
|
||||
end
|
||||
else
|
||||
if tile:getTopUseThing():isPickupable() or not tile:getTopUseThing():isNotMoveable() then
|
||||
useWith(tonumber(storage[pushPanelName].pushMaxRuneId), target)
|
||||
delay(10)
|
||||
g_game.move(target, targetTile:getPosition())
|
||||
delay(1250)
|
||||
else
|
||||
g_game.move(target, targetTile:getPosition())
|
||||
delay(1250)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if targetOldPos then
|
||||
local tile = g_map.getTile(targetOldPos)
|
||||
if tile then
|
||||
tile:setText("")
|
||||
targetTile:setText("")
|
||||
end
|
||||
end
|
||||
target = nil
|
||||
targetTile = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local resetTimer = now
|
||||
onKeyDown(function(keys)
|
||||
if not target or not storage[pushPanelName].enabled then return end
|
||||
if keys == storage[pushPanelName].pushMaxKey and resetTimer == 0 then
|
||||
local tile = getTileUnderCursor()
|
||||
if tile and not tile:getCreatures()[1] then
|
||||
targetTile = tile
|
||||
tile:setText("DESTINATION")
|
||||
end
|
||||
end
|
||||
resetTimer = now
|
||||
end)
|
||||
onKeyPress(function(keys)
|
||||
if not target or not storage[pushPanelName].enabled then return end
|
||||
if keys == storage[pushPanelName].pushMaxKey and (resetTimer - now) < -10 then
|
||||
for _, tile in ipairs(g_map.getTiles(posz())) do
|
||||
if getDistanceBetween(pos(), tile:getPosition()) < 3 then
|
||||
if tile:getText() ~= "" then
|
||||
tile:setText("")
|
||||
end
|
||||
end
|
||||
end
|
||||
target = nil
|
||||
targetTile = nil
|
||||
resetTimer = 0
|
||||
else
|
||||
resetTimer = 0
|
||||
end
|
||||
end)
|
||||
onCreaturePositionChange(function(creature, newPos, oldPos)
|
||||
if target and target:isPlayer() and storage[pushPanelName].enabled then
|
||||
if creature:getName() == target:getName() then
|
||||
targetTile = nil
|
||||
for _, tile in ipairs(g_map.getTiles(posz())) do
|
||||
if getDistanceBetween(pos(), tile:getPosition()) < 3 then
|
||||
if tile:getText() ~= "" then
|
||||
tile:setText("")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
293
modules/game_bot/default_configs/vithrax_1.1/2HealBot.lua
Normal file
293
modules/game_bot/default_configs/vithrax_1.1/2HealBot.lua
Normal file
@ -0,0 +1,293 @@
|
||||
setDefaultTab("HP")
|
||||
healPanelName = "healbot"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 19
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: center
|
||||
width: 130
|
||||
!text: tr('HealBot')
|
||||
|
||||
Button
|
||||
id: combos
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 3
|
||||
height: 17
|
||||
text: Setup
|
||||
|
||||
]])
|
||||
ui:setId(healPanelName)
|
||||
|
||||
if not storage[healPanelName] or not storage[healPanelName].spellTable or not storage[healPanelName].itemTable then
|
||||
storage[healPanelName] = {
|
||||
enabled = false,
|
||||
spellTable = {},
|
||||
itemTable = {}
|
||||
}
|
||||
end
|
||||
|
||||
ui.title:setOn(storage[healPanelName].enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
storage[healPanelName].enabled = not storage[healPanelName].enabled
|
||||
widget:setOn(storage[healPanelName].enabled)
|
||||
end
|
||||
|
||||
ui.combos.onClick = function(widget)
|
||||
healWindow:show()
|
||||
healWindow:raise()
|
||||
healWindow:focus()
|
||||
end
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
healWindow = g_ui.createWidget('HealWindow', rootWidget)
|
||||
healWindow:hide()
|
||||
|
||||
healWindow.spells.addSpell.onClick = function(widget)
|
||||
|
||||
local spellFormula = healWindow.spells.spellFormula:getText():trim()
|
||||
local manaCost = tonumber(healWindow.spells.manaCost:getText())
|
||||
local spellTrigger = tonumber(healWindow.spells.spellValue:getText())
|
||||
local spellSource = healWindow.spells.spellSource:getCurrentOption().text
|
||||
local spellEquasion = healWindow.spells.spellCondition:getCurrentOption().text
|
||||
local source
|
||||
local equasion
|
||||
|
||||
if not manaCost then
|
||||
warn("HealBot: incorrect mana cost value!")
|
||||
healWindow.spells.spellFormula:setText('')
|
||||
healWindow.spells.spellValue:setText('')
|
||||
healWindow.spells.manaCost:setText('')
|
||||
return
|
||||
end
|
||||
if not spellTrigger then
|
||||
warn("HealBot: incorrect condition value!")
|
||||
healWindow.spells.spellFormula:setText('')
|
||||
healWindow.spells.spellValue:setText('')
|
||||
healWindow.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%"
|
||||
else
|
||||
source = "HP%"
|
||||
end
|
||||
|
||||
if spellEquasion == "Above" then
|
||||
equasion = ">"
|
||||
elseif spellEquasion == "Below" then
|
||||
equasion = "<"
|
||||
else
|
||||
equasion = "="
|
||||
end
|
||||
|
||||
if spellFormula:len() > 0 then
|
||||
table.insert(storage[healPanelName].spellTable, {spell = spellFormula, sign = equasion, origin = source, cost = manaCost, value = spellTrigger})
|
||||
local label = g_ui.createWidget("SpellEntry", healWindow.spells.spellList)
|
||||
label.remove.onClick = function(widget)
|
||||
table.removevalue(storage[healPanelName].spellTable, label:getText())
|
||||
label:destroy()
|
||||
end
|
||||
label:setText("(MP>" .. manaCost .. ") " .. source .. equasion .. spellTrigger .. ":" .. spellFormula)
|
||||
healWindow.spells.spellFormula:setText('')
|
||||
healWindow.spells.spellValue:setText('')
|
||||
healWindow.spells.manaCost:setText('')
|
||||
end
|
||||
end
|
||||
|
||||
healWindow.items.addItem.onClick = function(widget)
|
||||
|
||||
local id = healWindow.items.itemId:getItemId()
|
||||
local trigger = tonumber(healWindow.items.itemValue:getText())
|
||||
local src = healWindow.items.itemSource:getCurrentOption().text
|
||||
local eq = healWindow.items.itemCondition:getCurrentOption().text
|
||||
local source
|
||||
local equasion
|
||||
|
||||
if not trigger then
|
||||
warn("HealBot: incorrect trigger value!")
|
||||
healWindow.items.id:setItemId(0)
|
||||
healWindow.items.trigger:setText('')
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
if src == "Current Mana" then
|
||||
source = "MP"
|
||||
elseif src == "Current Health" then
|
||||
source = "HP"
|
||||
elseif src == "Mana Percent" then
|
||||
source = "MP%"
|
||||
else
|
||||
source = "HP%"
|
||||
end
|
||||
|
||||
if eq == "Above" then
|
||||
equasion = ">"
|
||||
elseif eq == "Below" then
|
||||
equasion = "<"
|
||||
else
|
||||
equasion = "="
|
||||
end
|
||||
|
||||
if id > 100 then
|
||||
table.insert(storage[healPanelName].itemTable, {item = id, sign = equasion, origin = source, value = trigger})
|
||||
local label = g_ui.createWidget("SpellEntry", healWindow.items.itemList)
|
||||
label.remove.onClick = function(widget)
|
||||
table.removevalue(storage[healPanelName].itemTable, label:getText())
|
||||
label:destroy()
|
||||
end
|
||||
label:setText(source .. equasion .. trigger .. ":" .. id)
|
||||
healWindow.items.id:setItemId(0)
|
||||
healWindow.items.trigger:setText('')
|
||||
end
|
||||
end
|
||||
|
||||
if storage[healPanelName].itemTable and #storage[healPanelName].itemTable > 0 then
|
||||
for _, entry in pairs(storage[healPanelName].itemTable) do
|
||||
local label = g_ui.createWidget("SpellEntry", healWindow.items.itemList)
|
||||
label.remove.onClick = function(widget)
|
||||
table.removevalue(storage[healPanelName].itemTable, entry)
|
||||
label:destroy()
|
||||
end
|
||||
label:setText(entry.origin .. entry.sign .. entry.value .. ":" .. entry.item)
|
||||
end
|
||||
end
|
||||
|
||||
if storage[healPanelName].spellTable and #storage[healPanelName].spellTable > 0 then
|
||||
for _, entry in pairs(storage[healPanelName].spellTable) do
|
||||
local label = g_ui.createWidget("SpellEntry", healWindow.spells.spellList)
|
||||
label.remove.onClick = function(widget)
|
||||
table.removevalue(storage[healPanelName].spellTable, entry)
|
||||
label:destroy()
|
||||
end
|
||||
label:setText("(MP>" .. entry.cost .. ") " .. entry.origin .. entry.sign .. entry.value .. ":" .. entry.spell)
|
||||
end
|
||||
end
|
||||
|
||||
healWindow.closeButton.onClick = function(widget)
|
||||
healWindow:hide()
|
||||
end
|
||||
end
|
||||
|
||||
-- spells
|
||||
macro(100, function()
|
||||
if not storage[healPanelName].enabled or modules.game_cooldown.isGroupCooldownIconActive(2) or #storage[healPanelName].spellTable == 0 then return end
|
||||
|
||||
for _, entry in pairs(storage[healPanelName].spellTable) do
|
||||
if mana() >= tonumber(entry.cost) and not getSpellCoolDown(entry.spell) 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
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- items
|
||||
macro(500, function()
|
||||
if not storage[healPanelName].enabled or storage.isUsing or #storage[healPanelName].itemTable == 0 then return end
|
||||
|
||||
for _, entry in pairs(storage[healPanelName].itemTable) do
|
||||
local item = findItem(entry.item)
|
||||
if item then
|
||||
if entry.origin == "HP%" then
|
||||
if entry.sign == "=" and hppercent() == entry.value then
|
||||
useWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == ">" and hppercent() >= entry.value then
|
||||
useWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == "<" and hppercent() <= entry.value then
|
||||
useWith(entry.item, player)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "HP" then
|
||||
if entry.sign == "=" and hp() == tonumberentry.value then
|
||||
useWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == ">" and hp() >= entry.value then
|
||||
useWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == "<" and hp() <= entry.value then
|
||||
useWith(entry.item, player)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "MP%" then
|
||||
if entry.sign == "=" and manapercent() == entry.value then
|
||||
useWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == ">" and manapercent() >= entry.value then
|
||||
useWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == "<" and manapercent() <= entry.value then
|
||||
useWith(entry.item, player)
|
||||
return
|
||||
end
|
||||
elseif entry.origin == "MP" then
|
||||
if entry.sign == "=" and mana() == entry.value then
|
||||
useWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == ">" and mana() >= entry.value then
|
||||
useWith(entry.item, player)
|
||||
return
|
||||
elseif entry.sign == "<" and mana() <= entry.value then
|
||||
useWith(entry.item, player)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
121
modules/game_bot/default_configs/vithrax_1.1/3 Sio.lua
Normal file
121
modules/game_bot/default_configs/vithrax_1.1/3 Sio.lua
Normal file
@ -0,0 +1,121 @@
|
||||
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,
|
||||
spellName = "exura sio",
|
||||
spellHeal = true,
|
||||
distance = 8,
|
||||
itemHeal = true,
|
||||
id = 3160
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
sioListWindow = g_ui.createWidget('SioListWindow', rootWidget)
|
||||
sioListWindow:hide()
|
||||
|
||||
ui.title:setOn(storage[panelName].enabled)
|
||||
sioListWindow.spell:setOn(storage[panelName].spellHeal)
|
||||
sioListWindow.item:setOn(storage[panelName].itemHeal)
|
||||
|
||||
ui.title.onClick = function(widget)
|
||||
storage[panelName].enabled = not storage[panelName].enabled
|
||||
widget:setOn(storage[panelName].enabled)
|
||||
end
|
||||
|
||||
ui.editList.onClick = function(widget)
|
||||
sioListWindow:show()
|
||||
sioListWindow:raise()
|
||||
sioListWindow:focus()
|
||||
end
|
||||
sioListWindow.spell.onClick = function(widget)
|
||||
storage[panelName].spellHeal = not storage[panelName].spellHeal
|
||||
widget:setOn(storage[panelName].spellHeal)
|
||||
end
|
||||
sioListWindow.item.onClick = function(widget)
|
||||
storage[panelName].itemHeal = not storage[panelName].itemHeal
|
||||
widget:setOn(storage[panelName].itemHeal)
|
||||
end
|
||||
sioListWindow.closeButton.onClick = function(widget)
|
||||
sioListWindow:hide()
|
||||
end
|
||||
sioListWindow.spellName.onTextChange = function(widget, text)
|
||||
storage[panelName].spellName = text
|
||||
end
|
||||
local updateMinManaText = function()
|
||||
sioListWindow.manaInfo:setText("Minimum Mana >= " .. storage[panelName].minMana .. "%")
|
||||
end
|
||||
local updateFriendHpText = function()
|
||||
sioListWindow.friendHp:setText("Heal Friend Below " .. storage[panelName].minFriendHp .. "% hp")
|
||||
end
|
||||
local updateDistanceText = function()
|
||||
sioListWindow.distText:setText("Max Distance: " .. storage[panelName].distance)
|
||||
end
|
||||
sioListWindow.Distance.onValueChange = function(scroll, value)
|
||||
storage[panelName].distance = value
|
||||
updateDistanceText()
|
||||
end
|
||||
updateDistanceText()
|
||||
sioListWindow.minMana.onValueChange = function(scroll, value)
|
||||
storage[panelName].minMana = value
|
||||
updateMinManaText()
|
||||
end
|
||||
sioListWindow.minFriendHp.onValueChange = function(scroll, value)
|
||||
storage[panelName].minFriendHp = value
|
||||
|
||||
updateFriendHpText()
|
||||
end
|
||||
sioListWindow.itemId:setItemId(storage[panelName].id)
|
||||
sioListWindow.itemId.onItemChange = function(widget)
|
||||
storage[panelName].id = widget:getItemId()
|
||||
end
|
||||
sioListWindow.spellName:setText(storage[panelName].spellName)
|
||||
sioListWindow.minMana:setValue(storage[panelName].minMana)
|
||||
sioListWindow.minFriendHp:setValue(storage[panelName].minFriendHp)
|
||||
sioListWindow.Distance:setValue(storage[panelName].distance)
|
||||
|
||||
local healItem
|
||||
macro(200, function()
|
||||
if storage[panelName].enabled and storage[panelName].spellName:len() > 0 and manapercent() > storage[panelName].minMana then
|
||||
for _, spec in ipairs(getSpectators()) do
|
||||
if spec:isPlayer() and storage[panelName].minFriendHp >= spec:getHealthPercent() and isFriend(spec:getName()) then
|
||||
if storage[panelName].spellHeal then
|
||||
saySpell(storage[panelName].spellName .. ' "' .. spec:getName(), 100)
|
||||
end
|
||||
healItem = findItem(storage[panelName].id)
|
||||
if storage[panelName].itemHeal and distanceFromPlayer(spec:getPosition()) <= storage[panelName].distance and healItem then
|
||||
useWith(storage[panelName].id, spec)
|
||||
delay(300)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
addSeparator()
|
150
modules/game_bot/default_configs/vithrax_1.1/3 player list.lua
Normal file
150
modules/game_bot/default_configs/vithrax_1.1/3 player list.lua
Normal file
@ -0,0 +1,150 @@
|
||||
local listPanelName = "playerList"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 18
|
||||
|
||||
Button
|
||||
id: editList
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 18
|
||||
text: Player Lists
|
||||
]], parent)
|
||||
ui:setId(listPanelName)
|
||||
|
||||
if not storage[listPanelName] then
|
||||
storage[listPanelName] = {
|
||||
enemyList = {},
|
||||
friendList = {},
|
||||
groupMembers = true,
|
||||
outfits = false,
|
||||
marks = false
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
playerListWindow = g_ui.createWidget('PlayerListsWindow', rootWidget)
|
||||
playerListWindow:hide()
|
||||
|
||||
playerListWindow.Members:setOn(storage[listPanelName].groupMembers)
|
||||
playerListWindow.Members.onClick = function(widget)
|
||||
storage[listPanelName].groupMembers = not storage[listPanelName].groupMembers
|
||||
widget:setOn(storage[listPanelName].groupMembers)
|
||||
end
|
||||
playerListWindow.Outfit:setOn(storage[listPanelName].outfits)
|
||||
playerListWindow.Outfit.onClick = function(widget)
|
||||
storage[listPanelName].outfits = not storage[listPanelName].outfits
|
||||
widget:setOn(storage[listPanelName].outfits)
|
||||
end
|
||||
playerListWindow.Marks:setOn(storage[listPanelName].marks)
|
||||
playerListWindow.Marks.onClick = function(widget)
|
||||
storage[listPanelName].marks = not storage[listPanelName].marks
|
||||
widget:setOn(storage[listPanelName].marks)
|
||||
end
|
||||
|
||||
if storage[listPanelName].enemyList and #storage[listPanelName].enemyList > 0 then
|
||||
for _, name in ipairs(storage[listPanelName].enemyList) do
|
||||
local label = g_ui.createWidget("PlayerName", playerListWindow.EnemyList)
|
||||
label.remove.onClick = function(widget)
|
||||
table.removevalue(storage[listPanelName].enemyList, label:getText())
|
||||
label:destroy()
|
||||
end
|
||||
label:setText(name)
|
||||
end
|
||||
end
|
||||
|
||||
playerListWindow.AddFriend.onClick = function(widget)
|
||||
local friendName = playerListWindow.FriendName:getText()
|
||||
if friendName:len() > 0 and not table.contains(storage[listPanelName].enemyList, friendName, true) then
|
||||
table.insert(storage[listPanelName].enemyList, friendName)
|
||||
local label = g_ui.createWidget("PlayerName", playerListWindow.EnemyList)
|
||||
label.remove.onClick = function(widget)
|
||||
table.removevalue(storage[listPanelName].enemyList, label:getText())
|
||||
label:destroy()
|
||||
end
|
||||
label:setText(friendName)
|
||||
playerListWindow.FriendName:setText('')
|
||||
end
|
||||
end
|
||||
|
||||
if storage[listPanelName].friendList and #storage[listPanelName].friendList > 0 then
|
||||
for _, name in ipairs(storage[listPanelName].friendList) do
|
||||
local label = g_ui.createWidget("PlayerName", playerListWindow.FriendList)
|
||||
label.remove.onClick = function(widget)
|
||||
table.removevalue(storage[listPanelName].friendList, label:getText())
|
||||
label:destroy()
|
||||
end
|
||||
label:setText(name)
|
||||
end
|
||||
end
|
||||
|
||||
playerListWindow.AddFriend.onClick = function(widget)
|
||||
local friendName = playerListWindow.FriendName:getText()
|
||||
if friendName:len() > 0 and not table.contains(storage[listPanelName].friendList, friendName, true) then
|
||||
table.insert(storage[listPanelName].friendList, friendName)
|
||||
local label = g_ui.createWidget("PlayerName", playerListWindow.FriendList)
|
||||
label.remove.onClick = function(widget)
|
||||
table.removevalue(storage[listPanelName].friendList, label:getText())
|
||||
label:destroy()
|
||||
end
|
||||
label:setText(friendName)
|
||||
playerListWindow.FriendName:setText('')
|
||||
end
|
||||
end
|
||||
|
||||
playerListWindow.AddEnemy.onClick = function(widget)
|
||||
local enemyName = playerListWindow.EnemyName:getText()
|
||||
if enemyName:len() > 0 and not table.contains(storage[listPanelName].enemyList, enemyName, true) then
|
||||
table.insert(storage[listPanelName].enemyList, enemyName)
|
||||
local label = g_ui.createWidget("PlayerName", playerListWindow.EnemyList)
|
||||
label.remove.onClick = function(widget)
|
||||
table.removevalue(storage[listPanelName].enemyList, label:getText())
|
||||
label:destroy()
|
||||
end
|
||||
label:setText(enemyName)
|
||||
playerListWindow.EnemyName:setText('')
|
||||
end
|
||||
end
|
||||
|
||||
ui.editList.onClick = function(widget)
|
||||
playerListWindow:show()
|
||||
playerListWindow:raise()
|
||||
playerListWindow:focus()
|
||||
end
|
||||
playerListWindow.closeButton.onClick = function(widget)
|
||||
playerListWindow:hide()
|
||||
end
|
||||
|
||||
function refreshStatus()
|
||||
for _, spec in ipairs(getSpectators()) do
|
||||
if spec:isPlayer() and not spec:isLocalPlayer() then
|
||||
if storage[listPanelName].outfits then
|
||||
specOutfit = spec:getOutfit()
|
||||
if isEnemy(spec:getName()) then
|
||||
specOutfit.head = 112
|
||||
specOutfit.body = 112
|
||||
specOutfit.legs = 112
|
||||
specOutfit.feet = 112
|
||||
spec:setOutfit(specOutfit)
|
||||
elseif isFriend(spec:getName()) then
|
||||
specOutfit.head = 88
|
||||
specOutfit.body = 88
|
||||
specOutfit.legs = 88
|
||||
specOutfit.feet = 88
|
||||
spec:setOutfit(specOutfit)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
refreshStatus()
|
||||
|
||||
onCreatureAppear(function(creature)
|
||||
if creature:isPlayer() then
|
||||
refreshStatus()
|
||||
end
|
||||
end)
|
||||
|
||||
addSeparator()
|
691
modules/game_bot/default_configs/vithrax_1.1/AttackBot.lua
Normal file
691
modules/game_bot/default_configs/vithrax_1.1/AttackBot.lua
Normal file
@ -0,0 +1,691 @@
|
||||
-- if you want to change tab, in line below insert: setDefaultTab("tab name")
|
||||
|
||||
attackPanelName = "attackbot"
|
||||
local ui = setupUI([[
|
||||
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: mode
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
text: Mode: PVP
|
||||
margin-right: 2
|
||||
margin-top: 4
|
||||
font: cipsoftFont
|
||||
height: 17
|
||||
|
||||
Button
|
||||
id: safe
|
||||
anchors.top: settings.bottom
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
text: PVP Safe
|
||||
margin-left: 2
|
||||
margin-top: 4
|
||||
height: 17
|
||||
font:cipsoftFont
|
||||
]])
|
||||
ui:setId(attackPanelName)
|
||||
|
||||
local i = 1
|
||||
local j = 1
|
||||
local k = 1
|
||||
local pvpDedicated = false
|
||||
local item = false
|
||||
|
||||
UI.Separator()
|
||||
|
||||
if not storage[attackPanelName] or not storage[attackPanelName].attackTable then
|
||||
storage[attackPanelName] = {
|
||||
pvpMode = false,
|
||||
pvpSafe = true,
|
||||
enabled = false,
|
||||
attackTable = {}
|
||||
}
|
||||
end
|
||||
|
||||
local categories = {
|
||||
"Select Category",
|
||||
"Area Spell (exevo mas san, exevo gran mas flam etc.)",
|
||||
"Adjacent (exori, exori gran)",
|
||||
"Front Sweep (exori min)",
|
||||
"Wave (exevo tera hur, exevo gran vis lux)",
|
||||
"Targeted Spell (exori ico, exori flam etc.)",
|
||||
"Targeted Rune (sudden death, heavy magic missle etc.)",
|
||||
"Area Rune (great fireball, avalanche etc.)"
|
||||
}
|
||||
|
||||
local labels = {
|
||||
"",
|
||||
"Area Spell",
|
||||
"Adjacent",
|
||||
"Front Sweep",
|
||||
"Wave",
|
||||
"Targeted Spell",
|
||||
"Targeted Rune",
|
||||
"Area Rune",
|
||||
}
|
||||
|
||||
local range = {
|
||||
"Select Range",
|
||||
"Range: 1",
|
||||
"Range: 2",
|
||||
"Range: 3",
|
||||
"Range: 4",
|
||||
"Range: 5",
|
||||
"Range: 6",
|
||||
"Range: 7",
|
||||
"Range: 8",
|
||||
"Range: 9"
|
||||
}
|
||||
|
||||
local pattern = {
|
||||
"Pattern",
|
||||
"Single (exori frigo, SD)",
|
||||
"Large AOE (mas tera)",
|
||||
"Medium AOE (mas frigo)",
|
||||
"Small AOE (mas san)",
|
||||
"Large Wave (tera hur)",
|
||||
"Medium Wave (frigo hur)",
|
||||
"Small Wave (gran frigo hur)",
|
||||
"Beam (exevo vis lux)",
|
||||
"Adjacent (exori)",
|
||||
"Area Rune (GFB, AVA)"
|
||||
}
|
||||
|
||||
local updateModeText = function()
|
||||
local text
|
||||
if storage[attackPanelName].pvpMode then
|
||||
text = "PVP"
|
||||
ui.mode:setColor("yellow")
|
||||
else
|
||||
text = "HUNT"
|
||||
ui.mode:setColor("green")
|
||||
end
|
||||
ui.mode:setText("MODE: " .. text)
|
||||
end
|
||||
updateModeText()
|
||||
|
||||
local updatePvpColor = function()
|
||||
if storage[attackPanelName].pvpSafe then
|
||||
ui.safe:setColor("green")
|
||||
else
|
||||
ui.safe:setColor("white")
|
||||
end
|
||||
end
|
||||
updatePvpColor()
|
||||
|
||||
ui.title:setOn(storage[attackPanelName].enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
storage[attackPanelName].enabled = not storage[attackPanelName].enabled
|
||||
widget:setOn(storage[attackPanelName].enabled)
|
||||
end
|
||||
|
||||
ui.mode.onClick = function(widget)
|
||||
storage[attackPanelName].pvpMode = not storage[attackPanelName].pvpMode
|
||||
updateModeText()
|
||||
end
|
||||
|
||||
ui.safe.onClick = function(widget)
|
||||
storage[attackPanelName].pvpSafe = not storage[attackPanelName].pvpSafe
|
||||
updatePvpColor()
|
||||
end
|
||||
|
||||
ui.settings.onClick = function(widget)
|
||||
attackWindow:show()
|
||||
attackWindow:raise()
|
||||
attackWindow:focus()
|
||||
end
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
if rootWidget then
|
||||
attackWindow = g_ui.createWidget('AttackWindow', rootWidget)
|
||||
attackWindow:hide()
|
||||
|
||||
-- functions
|
||||
local updateCategoryText = function()
|
||||
attackWindow.category:setText(categories[i])
|
||||
end
|
||||
updateCategoryText()
|
||||
local updateParameter1Text = function()
|
||||
attackWindow.parameter1:setText(pattern[k])
|
||||
end
|
||||
updateParameter1Text()
|
||||
local updateParameter2Text = function()
|
||||
attackWindow.parameter2:setText(range[j])
|
||||
end
|
||||
updateParameter2Text()
|
||||
|
||||
-- checkbox
|
||||
attackWindow.pvpSpell.onClick = function(widget)
|
||||
pvpDedicated = not pvpDedicated
|
||||
attackWindow.pvpSpell:setChecked(pvpDedicated)
|
||||
end
|
||||
|
||||
--buttons
|
||||
attackWindow.CloseButton.onClick = function(widget)
|
||||
attackWindow:hide()
|
||||
end
|
||||
|
||||
local inputTypeToggle = function()
|
||||
if attackWindow.category:getText():lower():find("rune") then
|
||||
item = true
|
||||
attackWindow.spellFormula:setText("")
|
||||
attackWindow.spellFormula:hide()
|
||||
attackWindow.spellDescription:hide()
|
||||
attackWindow.itemId:show()
|
||||
attackWindow.itemDescription:show()
|
||||
else
|
||||
item = false
|
||||
attackWindow.itemId:setItemId(0)
|
||||
attackWindow.itemId:hide()
|
||||
attackWindow.itemDescription:hide()
|
||||
attackWindow.spellFormula:show()
|
||||
attackWindow.spellDescription:show()
|
||||
end
|
||||
end
|
||||
inputTypeToggle()
|
||||
|
||||
attackWindow.categoryNext.onClick = function(widget)
|
||||
if i == #categories then
|
||||
i = 1
|
||||
else
|
||||
i = i + 1
|
||||
end
|
||||
updateCategoryText()
|
||||
inputTypeToggle()
|
||||
end
|
||||
|
||||
attackWindow.categoryPrev.onClick = function(widget)
|
||||
if i == 1 then
|
||||
i = #categories
|
||||
else
|
||||
i = i - 1
|
||||
end
|
||||
updateCategoryText()
|
||||
inputTypeToggle()
|
||||
end
|
||||
|
||||
attackWindow.parameter1Next.onClick = function(widget)
|
||||
if k == #pattern then
|
||||
k = 1
|
||||
else
|
||||
k = k + 1
|
||||
end
|
||||
updateParameter1Text()
|
||||
end
|
||||
|
||||
attackWindow.parameter1Prev.onClick = function(widget)
|
||||
if k == 1 then
|
||||
k = #pattern
|
||||
else
|
||||
k = k - 1
|
||||
end
|
||||
updateParameter1Text()
|
||||
end
|
||||
|
||||
attackWindow.parameter2Next.onClick = function(widget)
|
||||
if j == #range then
|
||||
j = 1
|
||||
else
|
||||
j = j + 1
|
||||
end
|
||||
updateParameter2Text()
|
||||
end
|
||||
|
||||
attackWindow.parameter2Prev.onClick = function(widget)
|
||||
if j == 1 then
|
||||
j = #range
|
||||
else
|
||||
j = j - 1
|
||||
end
|
||||
updateParameter2Text()
|
||||
end
|
||||
|
||||
local validVal = function(v)
|
||||
if type(v) ~= "number" then
|
||||
local val = tonumber(v)
|
||||
if not val then return false end
|
||||
end
|
||||
if v >= 0 and v < 101 then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local clearValues = function()
|
||||
attackWindow.spellFormula:setText("")
|
||||
attackWindow.minMana:setText("")
|
||||
attackWindow.minMonsters:setText("")
|
||||
attackWindow.itemId:setItemId(0)
|
||||
pvpDedicated = false
|
||||
item = false
|
||||
attackWindow.pvpSpell:setChecked(false)
|
||||
i = 1
|
||||
j = 1
|
||||
k = 1
|
||||
updateParameter1Text()
|
||||
updateParameter2Text()
|
||||
updateCategoryText()
|
||||
inputTypeToggle()
|
||||
end
|
||||
|
||||
attackWindow.addButton.onClick = function(widget)
|
||||
local val
|
||||
if (item and attackWindow.itemId:getItemId() <= 100) or (not item and attackWindow.spellFormula:getText():len() == 0) then
|
||||
warn("AttackBot: missing spell or item id!")
|
||||
elseif not tonumber(attackWindow.minMana:getText()) or not validVal(tonumber(attackWindow.minMana:getText())) then
|
||||
warn("AttackBot: Mana Values incorrect! it has to be number from between 1 and 100")
|
||||
elseif not tonumber(attackWindow.minMonsters:getText()) or not validVal(tonumber(attackWindow.minMonsters:getText())) then
|
||||
warn("AttackBot: Monsters Count incorrect! it has to be number higher than 0")
|
||||
elseif i == 1 or j == 1 or k == 1 then
|
||||
warn("AttackBot: Categories not changed! You need to be more precise")
|
||||
else
|
||||
if item then
|
||||
val = attackWindow.itemId:getItemId()
|
||||
else
|
||||
val = attackWindow.spellFormula:getText()
|
||||
end
|
||||
local pvpText
|
||||
table.insert(storage[attackPanelName].attackTable, {attack = val, manaCost = tonumber(attackWindow.minMana:getText()), minMonsters = tonumber(attackWindow.minMonsters:getText()), pvp = pvpDedicated, dist = j-1, model = k, category = i})
|
||||
local label = g_ui.createWidget("AttackEntry", attackWindow.attackList)
|
||||
if pvpDedicated then
|
||||
label:setText("(" .. tonumber(attackWindow.minMana:getText()) .. "% MP) " .. labels[i] .. ": " .. val .. " (Range: ".. j-1 .. ")")
|
||||
label:setColor("yellow")
|
||||
else
|
||||
label:setText("(" .. tonumber(attackWindow.minMana:getText()) .. "% MP & mob >= " .. tonumber(attackWindow.minMonsters:getText()) .. ") " .. labels[i] .. ": " .. val .. " (Range: ".. j-1 .. ")")
|
||||
label:setColor("green")
|
||||
end
|
||||
clearValues()
|
||||
end
|
||||
end
|
||||
|
||||
if storage[attackPanelName].attackTable and #storage[attackPanelName].attackTable > 0 then
|
||||
for _, entry in pairs(storage[attackPanelName].attackTable) do
|
||||
local label = g_ui.createWidget("AttackEntry", attackWindow.attackList)
|
||||
label.remove.onClick = function(widget)
|
||||
table.removevalue(storage[attackPanelName].attackTable, entry)
|
||||
label:destroy()
|
||||
end
|
||||
if entry.pvp then
|
||||
label:setText("(" .. entry.manaCost .. "% MP) " .. labels[entry.category] .. ": " .. entry.attack .. " (Range: ".. j-1 .. ")")
|
||||
label:setColor("yellow")
|
||||
else
|
||||
label:setText("(" .. entry.manaCost .. "% MP & mob >= " .. entry.minMonsters .. ") " .. labels[entry.category] .. ": " .. entry.attack .. " (Range: ".. j-1 .. ")")
|
||||
label:setColor("green")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- executor
|
||||
-- table example (attack = 3155, manaCost = 50(%), minMonsters = 5, pvp = true, dist = 3, model = 6, category = 3)
|
||||
-- i = category
|
||||
-- j = range
|
||||
-- k = pattern - covered
|
||||
|
||||
local patterns = {
|
||||
"",
|
||||
[[
|
||||
0000001000000
|
||||
0000011100000
|
||||
0000111110000
|
||||
0001111111000
|
||||
0011111111100
|
||||
0111111111110
|
||||
1111111111111
|
||||
0111111111110
|
||||
0011111111100
|
||||
0001111111000
|
||||
0000111110000
|
||||
0000011100000
|
||||
0000001000000
|
||||
]],
|
||||
[[
|
||||
00000100000
|
||||
00011111000
|
||||
00111111100
|
||||
01111111110
|
||||
01111111110
|
||||
11111111111
|
||||
01111111110
|
||||
01111111110
|
||||
00111111100
|
||||
00001110000
|
||||
00000100000
|
||||
]],
|
||||
[[
|
||||
0011100
|
||||
0111110
|
||||
1111111
|
||||
1111111
|
||||
1111111
|
||||
0111110
|
||||
0011100
|
||||
]],
|
||||
[[
|
||||
0000NNN0000
|
||||
0000NNN0000
|
||||
0000NNN0000
|
||||
00000N00000
|
||||
WWW00N00EEE
|
||||
WWWWW0EEEEE
|
||||
WWW00S00EEE
|
||||
00000S00000
|
||||
0000SSS0000
|
||||
0000SSS0000
|
||||
0000SSS0000
|
||||
]],
|
||||
[[
|
||||
000NNNNN000
|
||||
000NNNNN000
|
||||
0000NNN0000
|
||||
WW00NNN00EE
|
||||
WWWW0N0EEEE
|
||||
WWWWW0EEEEE
|
||||
WWWW0S0EEEE
|
||||
WW00SSS00EE
|
||||
0000SSS0000
|
||||
000SSSSS000
|
||||
000SSSSS000
|
||||
]],
|
||||
[[
|
||||
00NNN00
|
||||
00NNN00
|
||||
WW0N0EE
|
||||
WWW0EEE
|
||||
WW0S0EE
|
||||
00SSS00
|
||||
00SSS00
|
||||
]],
|
||||
[[
|
||||
0000000N0000000
|
||||
0000000N0000000
|
||||
0000000N0000000
|
||||
0000000N0000000
|
||||
0000000N0000000
|
||||
0000000N0000000
|
||||
0000000N0000000
|
||||
WWWWWWW0EEEEEEE
|
||||
0000000S0000000
|
||||
0000000S0000000
|
||||
0000000S0000000
|
||||
0000000S0000000
|
||||
0000000S0000000
|
||||
0000000S0000000
|
||||
0000000S0000000
|
||||
]],
|
||||
"",
|
||||
""
|
||||
}
|
||||
|
||||
local safePatterns = {
|
||||
"",
|
||||
[[
|
||||
000000010000000
|
||||
000000111000000
|
||||
000001111100000
|
||||
000011111110000
|
||||
000111111111000
|
||||
001111111111100
|
||||
011111111111110
|
||||
111111111111111
|
||||
011111111111110
|
||||
001111111111100
|
||||
000111111111000
|
||||
000011111110000
|
||||
000001111100000
|
||||
000000111000000
|
||||
000000010000000
|
||||
]],
|
||||
[[
|
||||
0000011100000
|
||||
0000111110000
|
||||
0001111111000
|
||||
0011111111100
|
||||
0111111111110
|
||||
0111111111110
|
||||
1111111111111
|
||||
0111111111110
|
||||
0111111111110
|
||||
0011111111100
|
||||
0001111111000
|
||||
0000111110000
|
||||
0000011100000
|
||||
]],
|
||||
[[
|
||||
000111000
|
||||
001111100
|
||||
011111110
|
||||
111111111
|
||||
111111111
|
||||
111111111
|
||||
011111110
|
||||
001111100
|
||||
000111000
|
||||
]],
|
||||
[[
|
||||
0000NNNNN0000
|
||||
0000NNNNN0000
|
||||
0000NNNNN0000
|
||||
0000NNNNN0000
|
||||
WWWW0NNN0EEEE
|
||||
WWWWWNNNEEEEE
|
||||
WWWWWW0EEEEEE
|
||||
WWWWWSSSEEEEE
|
||||
WWWW0SSS0EEEE
|
||||
0000SSSSS0000
|
||||
0000SSSSS0000
|
||||
0000SSSSS0000
|
||||
0000SSSSS0000
|
||||
]],
|
||||
[[
|
||||
000NNNNNNN000
|
||||
000NNNNNNN000
|
||||
000NNNNNNN000
|
||||
WWWWNNNNNEEEE
|
||||
WWWWNNNNNEEEE
|
||||
WWWWWNNNEEEEE
|
||||
WWWWWW0EEEEEE
|
||||
WWWWWSSSEEEEE
|
||||
WWWWSSSSSEEEE
|
||||
WWWWSSSSSEEEE
|
||||
000SSSSSSS000
|
||||
000SSSSSSS000
|
||||
000SSSSSSS000
|
||||
]],
|
||||
[[
|
||||
00NNNNN00
|
||||
00NNNNN00
|
||||
WWNNNNNEE
|
||||
WWWWNEEEE
|
||||
WWWW0EEEE
|
||||
WWWWSEEEE
|
||||
WWSSSSSEE
|
||||
00SSSSS00
|
||||
00SSSSS00
|
||||
]],
|
||||
[[
|
||||
0000000NNN0000000
|
||||
0000000NNN0000000
|
||||
0000000NNN0000000
|
||||
0000000NNN0000000
|
||||
0000000NNN0000000
|
||||
0000000NNN0000000
|
||||
0000000NNN0000000
|
||||
WWWWWWWNNNEEEEEEE
|
||||
WWWWWWWW0EEEEEEEE
|
||||
WWWWWWWSSSEEEEEEE
|
||||
0000000SSS0000000
|
||||
0000000SSS0000000
|
||||
0000000SSS0000000
|
||||
0000000SSS0000000
|
||||
0000000SSS0000000
|
||||
0000000SSS0000000
|
||||
0000000SSS0000000
|
||||
]],
|
||||
"",
|
||||
""
|
||||
}
|
||||
|
||||
local posN = [[
|
||||
111
|
||||
000
|
||||
000
|
||||
]]
|
||||
local posE = [[
|
||||
001
|
||||
001
|
||||
001
|
||||
]]
|
||||
local posS = [[
|
||||
000
|
||||
000
|
||||
111
|
||||
]]
|
||||
local posW = [[
|
||||
100
|
||||
100
|
||||
100
|
||||
]]
|
||||
|
||||
macro(1000, function()
|
||||
if not storage[attackPanelName].enabled then return end
|
||||
if #storage[attackPanelName].attackTable == 0 or isInPz() or not target() or modules.game_cooldown.isGroupCooldownIconActive(1) or modules.game_cooldown.isGroupCooldownIconActive(4) then return end
|
||||
|
||||
local monstersN = 0
|
||||
local monstersE = 0
|
||||
local monstersS = 0
|
||||
local monstersW = 0
|
||||
|
||||
monstersN = getCreaturesInArea(pos(), posN, 2)
|
||||
monstersE = getCreaturesInArea(pos(), posE, 2)
|
||||
monstersS = getCreaturesInArea(pos(), posS, 2)
|
||||
monstersW = getCreaturesInArea(pos(), posN, 2)
|
||||
|
||||
local posTable = {monstersE, monstersN, monstersS, monstersW}
|
||||
local bestSide = 0
|
||||
local bestDir
|
||||
|
||||
-- pulling out the biggest number
|
||||
for i, v in pairs(posTable) do
|
||||
if v > bestSide then
|
||||
bestSide = v
|
||||
end
|
||||
end
|
||||
|
||||
-- associate biggest number with turn direction
|
||||
if monstersN == bestSide then bestDir = 0
|
||||
elseif monstersE == bestSide then bestDir = 1
|
||||
elseif monstersS == bestSide then bestDir = 2
|
||||
elseif monstersW == bestSide then bestDir = 3
|
||||
end
|
||||
|
||||
if player:getDirection() ~= bestDir and bestSide > 0 and CaveBot.isOn() then
|
||||
turn(bestDir)
|
||||
end
|
||||
|
||||
for _, entry in pairs(storage[attackPanelName].attackTable) do
|
||||
if (type(entry.attack) == "string" and canCast(entry.attack)) or (type(entry.attack) == "number" and findItem(entry.attack)) then
|
||||
if manapercent() >= entry.manaCost and distanceFromPlayer(target():getPosition()) <= entry.dist then
|
||||
if storage[attackPanelName].pvpMode then
|
||||
if entry.pvp and target():canShoot() then
|
||||
if type(entry.attack) == "string" then
|
||||
say(entry.attack)
|
||||
return
|
||||
else
|
||||
if not storage.isUsing then
|
||||
useWith(entry.attack, target())
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if entry.category == 6 or entry.category == 7 then
|
||||
if getMonsters(4) >= entry.minMonsters then
|
||||
if type(entry.attack) == "number" then
|
||||
if not storage.isUsing then
|
||||
useWith(entry.attack, target())
|
||||
return
|
||||
end
|
||||
else
|
||||
say(entry.attack)
|
||||
return
|
||||
end
|
||||
end
|
||||
else
|
||||
if killsToRs() > 2 then
|
||||
local areaTile = getBestTileByPatern(patterns[4], 2, entry.dist, storage[attackPanelName].pvpSafe)
|
||||
if entry.category == 4 and (not storage[attackPanelName].pvpSafe or isSafe(2, false)) and bestSide >= entry.minMonsters then
|
||||
say(entry.attack)
|
||||
return
|
||||
elseif entry.category == 3 and (not storage[attackPanelName].pvpSafe or isSafe(2, false)) and getMonsters(1) >= entry.minMonsters then
|
||||
say(entry.attack)
|
||||
return
|
||||
elseif entry.category == 5 and getCreaturesInArea(player, patterns[entry.model], 2) >= entry.minMonsters and (not storage[attackPanelName].pvpSafe or getCreaturesInArea(player, safePatterns[entry.model], 3) == 0) then
|
||||
say(entry.attack)
|
||||
return
|
||||
elseif entry.category == 2 and getCreaturesInArea(pos(), patterns[entry.model], 2) >= entry.minMonsters and (not storage[attackPanelName].pvpSafe or getCreaturesInArea(pos(), safePatterns[entry.model], 3) == 0) then
|
||||
say(entry.attack)
|
||||
return
|
||||
elseif entry.category == 8 and areaTile and areaTile.count >= entry.minMonsters then
|
||||
if not storage.isUsing then
|
||||
useWith(entry.attack, areaTile.pos:getTopUseThing())
|
||||
end
|
||||
return
|
||||
else
|
||||
if entry.category == 6 or entry.category == 7 then
|
||||
if getMonsters(4) >= entry.minMonsters then
|
||||
if type(entry.attack) == "number" then
|
||||
if not storage.isUsing then
|
||||
useWith(entry.attack, target())
|
||||
return
|
||||
end
|
||||
else
|
||||
say(entry.attack)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if entry.category == 6 or entry.category == 7 then
|
||||
if getMonsters(4) >= entry.minMonsters then
|
||||
if type(entry.attack) == "number" then
|
||||
if not storage.isUsing then
|
||||
useWith(entry.attack, target())
|
||||
return
|
||||
end
|
||||
else
|
||||
say(entry.attack)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
207
modules/game_bot/default_configs/vithrax_1.1/AttackBot.otui
Normal file
207
modules/game_bot/default_configs/vithrax_1.1/AttackBot.otui
Normal file
@ -0,0 +1,207 @@
|
||||
AttackEntry < 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
|
||||
|
||||
AttackWindow < MainWindow
|
||||
!text: tr('AttackBot')
|
||||
size: 490 350
|
||||
@onEscape: self:hide()
|
||||
|
||||
TextList
|
||||
id: attackList
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
padding: 1
|
||||
size: 470 150
|
||||
margin-left: 3
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
vertical-scrollbar: attackListScrollBar
|
||||
|
||||
VerticalScrollBar
|
||||
id: attackListScrollBar
|
||||
anchors.top: attackList.top
|
||||
anchors.bottom: attackList.bottom
|
||||
anchors.right: attackList.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
Label
|
||||
id: category
|
||||
anchors.top: attackList.bottom
|
||||
anchors.left: attackList.left
|
||||
anchors.right: attackList.right
|
||||
text-align: center
|
||||
margin-top: 5
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 5
|
||||
height: 21
|
||||
margin-left: 25
|
||||
margin-right: 25
|
||||
|
||||
NextButton
|
||||
id: categoryNext
|
||||
anchors.left: category.right
|
||||
anchors.verticalCenter: category.verticalCenter
|
||||
margin-left: 10
|
||||
|
||||
PreviousButton
|
||||
id: categoryPrev
|
||||
anchors.right: category.left
|
||||
anchors.verticalCenter: category.verticalCenter
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: parameter1
|
||||
anchors.top: category.bottom
|
||||
anchors.left: category.left
|
||||
anchors.right: category.horizontalCenter
|
||||
margin-top: 5
|
||||
margin-right: 25
|
||||
height: 21
|
||||
text-align: center
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 5
|
||||
|
||||
NextButton
|
||||
id: parameter1Next
|
||||
anchors.left: parameter1.right
|
||||
anchors.verticalCenter: parameter1.verticalCenter
|
||||
margin-left: 10
|
||||
|
||||
PreviousButton
|
||||
id: parameter1Prev
|
||||
anchors.right: parameter1.left
|
||||
anchors.verticalCenter: parameter1.verticalCenter
|
||||
margin-right: 10
|
||||
|
||||
Label
|
||||
id: parameter2
|
||||
anchors.top: category.bottom
|
||||
anchors.left: category.horizontalCenter
|
||||
anchors.right: category.right
|
||||
margin-top: 5
|
||||
margin-left: 25
|
||||
height: 21
|
||||
text-align: center
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 5
|
||||
|
||||
NextButton
|
||||
id: parameter2Next
|
||||
anchors.left: parameter2.right
|
||||
anchors.verticalCenter: parameter2.verticalCenter
|
||||
margin-left: 10
|
||||
|
||||
PreviousButton
|
||||
id: parameter2Prev
|
||||
anchors.right: parameter2.left
|
||||
anchors.verticalCenter: parameter2.verticalCenter
|
||||
margin-right: 10
|
||||
|
||||
TextEdit
|
||||
id: spellFormula
|
||||
anchors.left: parent.left
|
||||
anchors.top: parameter2Prev.bottom
|
||||
margin-top: 27
|
||||
margin-left: 5
|
||||
width: 200
|
||||
|
||||
Label
|
||||
id: spellDescription
|
||||
anchors.left: prev.left
|
||||
anchors.right: prev.right
|
||||
anchors.bottom: prev.top
|
||||
margin-bottom: 2
|
||||
text-align: center
|
||||
text: Insert Spell Formula Below
|
||||
|
||||
BotItem
|
||||
id: itemId
|
||||
anchors.left: parent.left
|
||||
anchors.top: parameter2Prev.bottom
|
||||
margin-top: 20
|
||||
margin-left: 5
|
||||
|
||||
Label
|
||||
id: itemDescription
|
||||
anchors.left: itemId.right
|
||||
margin-left: 5
|
||||
anchors.verticalCenter: itemId.verticalCenter
|
||||
text: < insert id or drag item here
|
||||
|
||||
Label
|
||||
anchors.left: parameter2Prev.left
|
||||
anchors.top: parameter2Prev.bottom
|
||||
margin-top: 17
|
||||
text-align: center
|
||||
text: Min Monsters:
|
||||
|
||||
TextEdit
|
||||
id: minMonsters
|
||||
anchors.left: prev.right
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
margin-left: 5
|
||||
width: 30
|
||||
|
||||
Label
|
||||
anchors.left: parameter2Prev.left
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 10
|
||||
text-align: center
|
||||
text: Min Mana%:
|
||||
|
||||
TextEdit
|
||||
id: minMana
|
||||
anchors.left: minMonsters.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
width: 30
|
||||
|
||||
CheckBox
|
||||
id: pvpSpell
|
||||
anchors.left: minMonsters.right
|
||||
width: 100
|
||||
margin-left: 10
|
||||
anchors.verticalCenter: minMonsters.verticalCenter
|
||||
text: Spell for PVP
|
||||
|
||||
Button
|
||||
id: addButton
|
||||
anchors.horizontalCenter: pvpSpell.horizontalCenter
|
||||
anchors.verticalCenter: minMana.verticalCenter
|
||||
text-align: center
|
||||
text: Add
|
||||
margin-left: 5
|
||||
margin-left: 5
|
||||
size: 45 21
|
||||
|
||||
HorizontalSeparator
|
||||
id: BottomSeparator
|
||||
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
|
145
modules/game_bot/default_configs/vithrax_1.1/BotServer.otui
Normal file
145
modules/game_bot/default_configs/vithrax_1.1/BotServer.otui
Normal file
@ -0,0 +1,145 @@
|
||||
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
|
||||
|
||||
Label
|
||||
id: label
|
||||
anchors.right: Participants.left
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 10
|
||||
margin-bottom: 4
|
||||
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
|
||||
|
||||
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
|
76
modules/game_bot/default_configs/vithrax_1.1/Castle.lua
Normal file
76
modules/game_bot/default_configs/vithrax_1.1/Castle.lua
Normal file
@ -0,0 +1,76 @@
|
||||
setDefaultTab("Tools")
|
||||
UI.Label("-- [[ ANTI PUSH Panel ]] --")
|
||||
addSeparator()
|
||||
local panelName = "castle"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 40
|
||||
|
||||
BotItem
|
||||
id: item
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-top: 2
|
||||
|
||||
BotSwitch
|
||||
id: skip
|
||||
anchors.top: parent.top
|
||||
anchors.left: item.right
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: item.verticalCenter
|
||||
text-align: center
|
||||
!text: tr('Skip Tiles Near Target')
|
||||
margin-left: 2
|
||||
|
||||
BotSwitch
|
||||
id: title
|
||||
anchors.top: item.verticalCenter
|
||||
anchors.left: item.right
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: item.bottom
|
||||
text-align: center
|
||||
!text: tr('Drop Items Around')
|
||||
margin-left: 2
|
||||
|
||||
]], parent)
|
||||
ui:setId(panelName)
|
||||
|
||||
if not storage[panelName] then
|
||||
storage[panelName] = {
|
||||
id = 2983,
|
||||
around = false,
|
||||
enabled = false
|
||||
}
|
||||
end
|
||||
|
||||
ui.skip:setOn(storage[panelName].around)
|
||||
ui.skip.onClick = function(widget)
|
||||
storage[panelName].around = not storage[panelName].around
|
||||
widget:setOn(storage[panelName].around)
|
||||
end
|
||||
ui.title:setOn(storage[panelName].enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
storage[panelName].enabled = not storage[panelName].enabled
|
||||
widget:setOn(storage[panelName].enabled)
|
||||
end
|
||||
|
||||
ui.item:setItemId(storage[panelName].id)
|
||||
ui.item.onItemChange = function(widget)
|
||||
storage[panelName].id = widget:getItemId()
|
||||
end
|
||||
|
||||
|
||||
macro(175, function()
|
||||
if storage[panelName].enabled then
|
||||
local blockItem = findItem(storage[panelName].id)
|
||||
for _, tile in pairs(g_map.getTiles(posz())) do
|
||||
if distanceFromPlayer(tile:getPosition()) == 1 and tile:isWalkable() and tile:getTopUseThing():getId() ~= storage[panelName].id and (not storage[panelName].around or not target() or (target() and getDistanceBetween(targetPos(), tile:getPosition() > 1))) then
|
||||
g_game.move(blockItem, tile:getPosition())
|
||||
return
|
||||
end
|
||||
end
|
||||
storage[panelName].enabled = false
|
||||
ui.title:setOn(storage[panelName].enabled)
|
||||
end
|
||||
end)
|
||||
addSeparator()
|
412
modules/game_bot/default_configs/vithrax_1.1/Conditions.otui
Normal file
412
modules/game_bot/default_configs/vithrax_1.1/Conditions.otui
Normal file
@ -0,0 +1,412 @@
|
||||
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 180
|
||||
|
||||
Label
|
||||
id: label1
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-top: 10
|
||||
margin-left: 5
|
||||
text: Poison
|
||||
color: #ffaa00
|
||||
|
||||
Label
|
||||
id: label11
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 40
|
||||
text: Mana:
|
||||
|
||||
TextEdit
|
||||
id: PoisonCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
|
||||
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
|
||||
|
||||
Label
|
||||
id: label22
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 44
|
||||
text: Mana:
|
||||
|
||||
TextEdit
|
||||
id: CurseCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
|
||||
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
|
||||
|
||||
Label
|
||||
id: label33
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 46
|
||||
text: Mana:
|
||||
|
||||
TextEdit
|
||||
id: BleedCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
|
||||
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
|
||||
|
||||
Label
|
||||
id: label44
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 50
|
||||
text: Mana:
|
||||
|
||||
TextEdit
|
||||
id: BurnCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
|
||||
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
|
||||
|
||||
Label
|
||||
id: label55
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 33
|
||||
text: Mana:
|
||||
|
||||
TextEdit
|
||||
id: ElectrifyCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
|
||||
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
|
||||
|
||||
Label
|
||||
id: label66
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 26
|
||||
text: Mana:
|
||||
|
||||
TextEdit
|
||||
id: ParalyseCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
|
||||
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:
|
||||
|
||||
TextEdit
|
||||
id: ParalyseSpell
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 10
|
||||
width: 100
|
||||
|
||||
HoldConditions < Panel
|
||||
id: Hold
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 6
|
||||
padding: 3
|
||||
size: 200 180
|
||||
|
||||
Label
|
||||
id: label1
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-top: 10
|
||||
margin-left: 5
|
||||
text: Haste
|
||||
color: #ffaa00
|
||||
|
||||
Label
|
||||
id: label11
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 44
|
||||
text: Mana:
|
||||
|
||||
TextEdit
|
||||
id: HasteCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
|
||||
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:
|
||||
|
||||
TextEdit
|
||||
id: HasteSpell
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 10
|
||||
width: 100
|
||||
|
||||
Label
|
||||
id: label3
|
||||
anchors.left: label1.left
|
||||
anchors.top: label2.bottom
|
||||
margin-top: 10
|
||||
text: Utana Vid
|
||||
color: #ffaa00
|
||||
|
||||
Label
|
||||
id: label33
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 21
|
||||
text: Mana:
|
||||
|
||||
TextEdit
|
||||
id: UtanaCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
|
||||
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
|
||||
|
||||
Label
|
||||
id: label44
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 12
|
||||
text: Mana:
|
||||
|
||||
TextEdit
|
||||
id: UtamoCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
|
||||
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
|
||||
|
||||
Label
|
||||
id: label55
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 20
|
||||
text: Mana:
|
||||
|
||||
TextEdit
|
||||
id: UturaCost
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 3
|
||||
width: 40
|
||||
|
||||
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:
|
||||
|
||||
UturaComboBox
|
||||
id: UturaType
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-left: 10
|
||||
width: 100
|
||||
|
||||
CheckBox
|
||||
id: IgnoreInPz
|
||||
anchors.left: label5.left
|
||||
anchors.top: label6.bottom
|
||||
margin-top: 15
|
||||
|
||||
Label
|
||||
id: label
|
||||
anchors.verticalCenter: IgnoreInPz.verticalCenter
|
||||
anchors.left: prev.right
|
||||
margin-top: 3
|
||||
margin-left: 5
|
||||
text: Don't Cast in Protection Zones
|
||||
font: cipsoftFont
|
||||
|
||||
ConditionsWindow < MainWindow
|
||||
!text: tr('Condition Manager')
|
||||
size: 445 270
|
||||
@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
|
||||
|
||||
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
|
||||
|
||||
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
|
306
modules/game_bot/default_configs/vithrax_1.1/HealBot.otui
Normal file
306
modules/game_bot/default_configs/vithrax_1.1/HealBot.otui
Normal file
@ -0,0 +1,306 @@
|
||||
SpellSourceBoxPopupMenu < ComboBoxPopupMenu
|
||||
SpellSourceBoxPopupMenuButton < ComboBoxPopupMenuButton
|
||||
SpellSourceBox < ComboBox
|
||||
@onSetup: |
|
||||
self:addOption("Current Mana")
|
||||
self:addOption("Current Health")
|
||||
self:addOption("Mana Percent")
|
||||
self:addOption("Health Percent")
|
||||
|
||||
SpellConditionBoxPopupMenu < ComboBoxPopupMenu
|
||||
SpellConditionBoxPopupMenuButton < ComboBoxPopupMenuButton
|
||||
SpellConditionBox < ComboBox
|
||||
@onSetup: |
|
||||
self:addOption("Below")
|
||||
self:addOption("Above")
|
||||
self:addOption("Equal To")
|
||||
|
||||
SpellEntry < 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
|
||||
|
||||
ItemEntry < 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
|
||||
|
||||
SpellHealing < Panel
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 6
|
||||
padding: 3
|
||||
size: 460 130
|
||||
|
||||
Label
|
||||
id: whenSpell
|
||||
anchors.left: spellList.right
|
||||
anchors.top: parent.top
|
||||
text: When
|
||||
margin-top: 10
|
||||
margin-left: 7
|
||||
|
||||
SpellSourceBox
|
||||
id: spellSource
|
||||
anchors.top: parent.top
|
||||
anchors.left: whenSpell.right
|
||||
margin-top: 5
|
||||
margin-left: 35
|
||||
width: 128
|
||||
|
||||
Label
|
||||
id: isSpell
|
||||
anchors.left: spellList.right
|
||||
anchors.top: whenSpell.bottom
|
||||
text: Is
|
||||
margin-top: 9
|
||||
margin-left: 7
|
||||
|
||||
SpellConditionBox
|
||||
id: spellCondition
|
||||
anchors.left: spellSource.left
|
||||
anchors.top: spellSource.bottom
|
||||
marin-top: 15
|
||||
width: 80
|
||||
|
||||
TextEdit
|
||||
id: spellValue
|
||||
anchors.left: spellCondition.right
|
||||
anchors.top: spellCondition.top
|
||||
anchors.bottom: spellCondition.bottom
|
||||
width: 49
|
||||
|
||||
Label
|
||||
id: castSpell
|
||||
anchors.left: isSpell.left
|
||||
anchors.top: isSpell.bottom
|
||||
text: Cast
|
||||
margin-top: 9
|
||||
|
||||
TextEdit
|
||||
id: spellFormula
|
||||
anchors.left: spellCondition.left
|
||||
anchors.top: spellCondition.bottom
|
||||
anchors.right: spellValue.right
|
||||
|
||||
Label
|
||||
id: manaSpell
|
||||
anchors.left: castSpell.left
|
||||
anchors.top: castSpell.bottom
|
||||
text: Mana Cost:
|
||||
margin-top: 8
|
||||
|
||||
TextEdit
|
||||
id: manaCost
|
||||
anchors.left: spellFormula.left
|
||||
anchors.top: spellFormula.bottom
|
||||
width: 40
|
||||
|
||||
TextList
|
||||
id: spellList
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
padding: 1
|
||||
size: 240 116
|
||||
margin-bottom: 3
|
||||
margin-left: 3
|
||||
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: parent.bottom
|
||||
margin-bottom: 2
|
||||
margin-right: 10
|
||||
text: Add
|
||||
size: 40 17
|
||||
font: cipsoftFont
|
||||
|
||||
Button
|
||||
id: MoveUp
|
||||
anchors.right: prev.left
|
||||
anchors.bottom: parent.bottom
|
||||
margin-bottom: 2
|
||||
margin-right: 5
|
||||
text: Move Up
|
||||
size: 55 17
|
||||
font: cipsoftFont
|
||||
|
||||
Button
|
||||
id: MoveDown
|
||||
anchors.right: prev.left
|
||||
anchors.bottom: parent.bottom
|
||||
margin-bottom: 2
|
||||
margin-right: 5
|
||||
text: Move Down
|
||||
size: 55 17
|
||||
font: cipsoftFont
|
||||
|
||||
ItemHealing < Panel
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 6
|
||||
padding: 3
|
||||
size: 460 130
|
||||
|
||||
Label
|
||||
id: whenItem
|
||||
anchors.left: itemList.right
|
||||
anchors.top: parent.top
|
||||
text: When
|
||||
margin-top: 10
|
||||
margin-left: 7
|
||||
|
||||
SpellSourceBox
|
||||
id: itemSource
|
||||
anchors.top: parent.top
|
||||
anchors.left: whenItem.right
|
||||
margin-top: 5
|
||||
margin-left: 35
|
||||
width: 128
|
||||
|
||||
Label
|
||||
id: isItem
|
||||
anchors.left: itemList.right
|
||||
anchors.top: whenItem.bottom
|
||||
text: Is
|
||||
margin-top: 9
|
||||
margin-left: 7
|
||||
|
||||
SpellConditionBox
|
||||
id: itemCondition
|
||||
anchors.left: itemSource.left
|
||||
anchors.top: itemSource.bottom
|
||||
marin-top: 15
|
||||
width: 80
|
||||
|
||||
TextEdit
|
||||
id: itemValue
|
||||
anchors.left: itemCondition.right
|
||||
anchors.top: itemCondition.top
|
||||
anchors.bottom: itemCondition.bottom
|
||||
width: 49
|
||||
|
||||
Label
|
||||
id: useItem
|
||||
anchors.left: isItem.left
|
||||
anchors.top: isItem.bottom
|
||||
text: Use
|
||||
margin-top: 15
|
||||
|
||||
BotItem
|
||||
id: itemId
|
||||
anchors.left: itemCondition.left
|
||||
anchors.top: itemCondition.bottom
|
||||
|
||||
TextList
|
||||
id: itemList
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
padding: 1
|
||||
size: 240 116
|
||||
margin-top: 3
|
||||
margin-bottom: 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
|
||||
|
||||
Button
|
||||
id: addItem
|
||||
anchors.right: itemValue.right
|
||||
anchors.bottom: parent.bottom
|
||||
margin-bottom: 2
|
||||
margin-right: 10
|
||||
text: Add
|
||||
size: 40 17
|
||||
font: cipsoftFont
|
||||
|
||||
Button
|
||||
id: MoveUp
|
||||
anchors.right: prev.left
|
||||
anchors.bottom: parent.bottom
|
||||
margin-bottom: 2
|
||||
margin-right: 5
|
||||
text: Move Up
|
||||
size: 55 17
|
||||
font: cipsoftFont
|
||||
|
||||
Button
|
||||
id: MoveDown
|
||||
anchors.right: prev.left
|
||||
anchors.bottom: parent.bottom
|
||||
margin-bottom: 2
|
||||
margin-right: 5
|
||||
text: Move Down
|
||||
size: 55 17
|
||||
font: cipsoftFont
|
||||
|
||||
HealWindow < MainWindow
|
||||
!text: tr('Self Healer')
|
||||
size: 490 350
|
||||
@onEscape: self:hide()
|
||||
|
||||
SpellHealing
|
||||
id: spells
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
||||
ItemHealing
|
||||
id: items
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
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
|
16
modules/game_bot/default_configs/vithrax_1.1/Title.lua
Normal file
16
modules/game_bot/default_configs/vithrax_1.1/Title.lua
Normal file
@ -0,0 +1,16 @@
|
||||
local vocation = player:getVocation()
|
||||
local vocText = nil
|
||||
|
||||
if vocation == 1 or vocation == 11 then
|
||||
vocText = "EK"
|
||||
elseif vocation == 2 or vocation == 12 then
|
||||
vocText = "RP"
|
||||
elseif vocation == 3 or vocation == 13 then
|
||||
vocText = "MS"
|
||||
elseif vocation == 4 or vocation == 14 then
|
||||
vocText = "ED"
|
||||
end
|
||||
|
||||
macro(10000, function()
|
||||
g_window.setTitle("Tibia - " .. player:getName() .. " - " .. lvl() .. "lvl - " .. vocText)
|
||||
end, batTab)
|
105
modules/game_bot/default_configs/vithrax_1.1/alarms.otui
Normal file
105
modules/game_bot/default_configs/vithrax_1.1/alarms.otui
Normal file
@ -0,0 +1,105 @@
|
||||
AlarmsWindow < MainWindow
|
||||
!text: tr('Alarms')
|
||||
size: 270 200
|
||||
@onEscape: self:hide()
|
||||
|
||||
BotSwitch
|
||||
id: playerAttack
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
text-align: center
|
||||
text: Player Attack
|
||||
|
||||
BotSwitch
|
||||
id: playerDetected
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 4
|
||||
text-align: center
|
||||
text: Player Detected
|
||||
|
||||
CheckBox
|
||||
id: playerDetectedLogout
|
||||
anchors.top: playerDetected.top
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
margin-top: 3
|
||||
margin-left: 4
|
||||
text: Logout
|
||||
|
||||
BotSwitch
|
||||
id: creatureDetected
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: playerDetected.bottom
|
||||
margin-top: 4
|
||||
text-align: center
|
||||
text: Creature Detected
|
||||
|
||||
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
|
||||
|
||||
BotSwitch
|
||||
id: privateMessage
|
||||
anchors.left: parent.left
|
||||
anchors.top: manaBelow.bottom
|
||||
anchors.right: parent.right
|
||||
text-align: center
|
||||
margin-top: 4
|
||||
text: Private Message
|
||||
|
||||
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
|
375
modules/game_bot/default_configs/vithrax_1.1/analyzers.lua
Normal file
375
modules/game_bot/default_configs/vithrax_1.1/analyzers.lua
Normal file
@ -0,0 +1,375 @@
|
||||
local analyserPanelName = "AnalysersPanel"
|
||||
local ui = setupUI([[
|
||||
Panel
|
||||
height: 18
|
||||
|
||||
Button
|
||||
id: analyzersMain
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 18
|
||||
text: Hunt Analysers
|
||||
]], parent)
|
||||
ui:setId(analyserPanelName)
|
||||
|
||||
if not storage[analyserPanelName] then
|
||||
storage[analyserPanelName] = {
|
||||
bestHit = 0,
|
||||
bestHeal = 0,
|
||||
lootItems = {}
|
||||
}
|
||||
end
|
||||
|
||||
analyzersWindow = g_ui.createWidget('MainAnalyzer', modules.game_interface.getRightPanel())
|
||||
huntWindow = g_ui.createWidget('HuntAnalyser', modules.game_interface.getRightPanel())
|
||||
impactWindow = g_ui.createWidget('ImpactAnalyser', modules.game_interface.getRightPanel())
|
||||
lootWindow = g_ui.createWidget('LootAnalyser', modules.game_interface.getRightPanel())
|
||||
xpWindow = g_ui.createWidget('XpAnalyser', modules.game_interface.getRightPanel())
|
||||
analyzersWindow:setup()
|
||||
huntWindow:setup()
|
||||
impactWindow:setup()
|
||||
lootWindow:setup()
|
||||
xpWindow:setup()
|
||||
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
lootListWindow = g_ui.createWidget('LootWindow', rootWidget)
|
||||
lootListWindow:hide()
|
||||
|
||||
function refresh()
|
||||
analyzersWindow:setContentMinimumHeight(105)
|
||||
analyzersWindow:setContentMaximumHeight(105)
|
||||
huntWindow:setContentMinimumHeight(30)
|
||||
impactWindow:setContentMinimumHeight(30)
|
||||
impactWindow:setContentMaximumHeight(185)
|
||||
lootWindow:setContentMinimumHeight(30)
|
||||
xpWindow:setContentMinimumHeight(30)
|
||||
xpWindow:setContentMaximumHeight(65)
|
||||
end
|
||||
refresh()
|
||||
|
||||
function huntWindowToggle()
|
||||
if huntWindow:isVisible() then
|
||||
huntWindow:close()
|
||||
else
|
||||
huntWindow:open()
|
||||
end
|
||||
end
|
||||
|
||||
function impactWindowToggle()
|
||||
if impactWindow:isVisible() then
|
||||
impactWindow:close()
|
||||
else
|
||||
impactWindow:open()
|
||||
end
|
||||
end
|
||||
|
||||
function lootWindowToggle()
|
||||
if lootWindow:isVisible() then
|
||||
lootWindow:close()
|
||||
else
|
||||
lootWindow:open()
|
||||
end
|
||||
end
|
||||
|
||||
function xpWindowToggle()
|
||||
if xpWindow:isVisible() then
|
||||
xpWindow:close()
|
||||
else
|
||||
xpWindow:open()
|
||||
end
|
||||
end
|
||||
|
||||
ui.analyzersMain.onClick = function(widget)
|
||||
if analyzersWindow:isVisible() then
|
||||
analyzersWindow:close()
|
||||
else
|
||||
analyzersWindow:open()
|
||||
end
|
||||
end
|
||||
lootWindow.contentsPanel.LootEdit.onClick = function(widget)
|
||||
lootListWindow:show()
|
||||
lootListWindow:raise()
|
||||
lootListWindow:focus()
|
||||
end
|
||||
|
||||
if storage[analyserPanelName].lootItems and #storage[analyserPanelName].lootItems > 0 then
|
||||
for _, name in ipairs(storage[analyserPanelName].lootItems) do
|
||||
local label = g_ui.createWidget("LootItemName", lootListWindow.LootList)
|
||||
label.remove.onClick = function(widget)
|
||||
table.removevalue(storage[analyserPanelName].lootItems, label:getText())
|
||||
label:destroy()
|
||||
end
|
||||
label:setText(name)
|
||||
end
|
||||
end
|
||||
|
||||
lootListWindow.AddLoot.onClick = function(widget)
|
||||
local lootName = lootListWindow.LootName:getText()
|
||||
if lootName:len() > 0 and not table.contains(storage[analyserPanelName].lootItems, lootName, true) then
|
||||
table.insert(storage[analyserPanelName].lootItems, lootName)
|
||||
local label = g_ui.createWidget("LootItemName", lootListWindow.LootList)
|
||||
label.remove.onClick = function(widget)
|
||||
table.removevalue(storage[analyserPanelName].lootItems, label:getText())
|
||||
label:destroy()
|
||||
end
|
||||
label:setText(lootName)
|
||||
lootListWindow.LootName:setText('')
|
||||
end
|
||||
end
|
||||
|
||||
lootListWindow.closeButton.onClick = function(widget)
|
||||
lootListWindow:hide()
|
||||
end
|
||||
|
||||
analyzersWindow.contentsPanel.HuntButton.onClick = function(widget)
|
||||
huntWindowToggle()
|
||||
end
|
||||
analyzersWindow.contentsPanel.lootSupplyButton.onClick = function(widget)
|
||||
lootWindowToggle()
|
||||
end
|
||||
analyzersWindow.contentsPanel.impactButton.onClick = function(widget)
|
||||
impactWindowToggle()
|
||||
end
|
||||
analyzersWindow.contentsPanel.xpButton.onClick = function(widget)
|
||||
xpWindowToggle()
|
||||
end
|
||||
|
||||
local uptime
|
||||
local launchTime = now
|
||||
local startTime = now
|
||||
function sessionTime()
|
||||
uptime = math.floor((now - launchTime)/1000)
|
||||
local hours = string.format("%02.f", math.floor(uptime/3600))
|
||||
local mins = string.format("%02.f", math.floor(uptime/60 - (hours*60)))
|
||||
|
||||
return hours .. ":" .. mins .. "h"
|
||||
end
|
||||
|
||||
local startExp = exp()
|
||||
function expGained()
|
||||
return exp() - startExp
|
||||
end
|
||||
|
||||
function expForLevel(level)
|
||||
return math.floor((50*level*level*level)/3 - 100*level*level + (850*level)/3 - 200)
|
||||
end
|
||||
|
||||
function expH()
|
||||
return (expGained() / (now - startTime))
|
||||
end
|
||||
|
||||
function format_thousand(v)
|
||||
if not v then return 0 end
|
||||
local s = string.format("%d", math.floor(v))
|
||||
local pos = string.len(s) % 3
|
||||
if pos == 0 then pos = 3 end
|
||||
return string.sub(s, 1, pos)
|
||||
.. string.gsub(string.sub(s, pos+1), "(...)", ".%1")
|
||||
end
|
||||
|
||||
function checkExpSpeed()
|
||||
local player = g_game.getLocalPlayer()
|
||||
if not player then return end
|
||||
|
||||
local currentExp = player:getExperience()
|
||||
local currentTime = now/1000
|
||||
if player.lastExps ~= nil then
|
||||
player.expSpeed = (currentExp - player.lastExps[1][1])/(currentTime - player.lastExps[1][2])
|
||||
else
|
||||
player.lastExps = {}
|
||||
end
|
||||
table.insert(player.lastExps, {currentExp, currentTime})
|
||||
if #player.lastExps > 30 then
|
||||
table.remove(player.lastExps, 1)
|
||||
end
|
||||
|
||||
return player.expSpeed
|
||||
end
|
||||
|
||||
function nextLevelData(time)
|
||||
|
||||
if checkExpSpeed() ~= nil then
|
||||
expPerHour = math.floor(checkExpSpeed() * 3600)
|
||||
if expPerHour > 0 then
|
||||
nextLevelExp = expForLevel(player:getLevel()+1)
|
||||
hoursLeft = (nextLevelExp - player:getExperience()) / expPerHour
|
||||
minutesLeft = math.floor((hoursLeft - math.floor(hoursLeft))*60)
|
||||
hoursLeft = math.floor(hoursLeft)
|
||||
timeLeft = tostring(hoursLeft .. ":" .. minutesLeft .. "h")
|
||||
end
|
||||
end
|
||||
|
||||
if time then
|
||||
return expPerHour
|
||||
else
|
||||
return timeLeft
|
||||
end
|
||||
end
|
||||
|
||||
function sum(t)
|
||||
local sum = 0
|
||||
for k,v in pairs(t) do
|
||||
sum = sum + v
|
||||
end
|
||||
|
||||
return sum
|
||||
end
|
||||
|
||||
local cumulatedDamage = 0
|
||||
local cumulatedHealing = 0
|
||||
local allHits = {}
|
||||
local allHeals = {}
|
||||
local dps
|
||||
local hps
|
||||
local kills = {}
|
||||
local droppedItems = {}
|
||||
onTextMessage(function(mode, text)
|
||||
-- [[ kill counter ]] --
|
||||
if string.find(text, "Loot of") then
|
||||
local split = string.split(text, ":")
|
||||
local mobName = string.split(split[1], "of ")[2]:trim()
|
||||
table.insert(kills, mobName)
|
||||
|
||||
local killCount = {}
|
||||
for i, entry in pairs(kills) do
|
||||
if killCount[entry] then
|
||||
killCount[entry] = killCount[entry] + 1
|
||||
else
|
||||
killCount[entry] = 1
|
||||
end
|
||||
end
|
||||
|
||||
for i, child in pairs(huntWindow.contentsPanel.MessagePanel:getChildren()) do
|
||||
child:destroy()
|
||||
end
|
||||
|
||||
for k,v in pairs(killCount) do
|
||||
local label = g_ui.createWidget("MonsterLabel", huntWindow.contentsPanel.MessagePanel)
|
||||
label:setText(v .. "x " .. k)
|
||||
end
|
||||
|
||||
-- [[ loot counter ]] --
|
||||
local monsterDrop = string.split(split[2], ",")
|
||||
|
||||
if #monsterDrop > 0 then
|
||||
for i=1,#monsterDrop do
|
||||
local drop = monsterDrop[i]:trim()
|
||||
for i, entry in pairs(storage[analyserPanelName].lootItems) do
|
||||
if string.match(drop, entry) then
|
||||
local entryCount
|
||||
if tonumber(string.match(drop, "%d+")) then
|
||||
entryCount = tonumber(string.match(drop, "%d+"))
|
||||
else
|
||||
entryCount = 1
|
||||
end
|
||||
if droppedItems[entry] then
|
||||
droppedItems[entry] = droppedItems[entry] + entryCount
|
||||
else
|
||||
droppedItems[entry] = entryCount
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for i, child in pairs(lootWindow.contentsPanel.MessagePanel:getChildren()) do
|
||||
child:destroy()
|
||||
end
|
||||
for k,v in pairs(droppedItems) do
|
||||
local label = g_ui.createWidget("MonsterLabel", lootWindow.contentsPanel.MessagePanel)
|
||||
label:setText(v .. "x " .. k)
|
||||
end
|
||||
end
|
||||
|
||||
-- damage
|
||||
if string.find(text, "hitpoints due to your attack") then
|
||||
table.insert(allHits, tonumber(string.match(text, "%d+")))
|
||||
if dps then
|
||||
if now - startTime > 1000 then
|
||||
local dmgSum = sum(allHits)
|
||||
dps = dmgSum
|
||||
allHits = {}
|
||||
startTime = now
|
||||
end
|
||||
else
|
||||
dps = 0
|
||||
end
|
||||
|
||||
local dmgValue = tonumber(string.match(text, "%d+"))
|
||||
cumulatedDamage = cumulatedDamage + dmgValue
|
||||
if storage[analyserPanelName].bestHit < dmgValue then
|
||||
storage[analyserPanelName].bestHit = dmgValue
|
||||
end
|
||||
end
|
||||
-- healing
|
||||
if string.find(text, "You heal") then
|
||||
table.insert(allHeals, tonumber(string.match(text, "%d+")))
|
||||
if hps then
|
||||
if now - startTime > 1000 then
|
||||
local healSum = sum(allHeals)
|
||||
hps = healSum
|
||||
allHeals = {}
|
||||
startTime = now
|
||||
end
|
||||
else
|
||||
hps = 0
|
||||
end
|
||||
local healValue = tonumber(string.match(text, "%d+"))
|
||||
cumulatedHealing = cumulatedHealing + healValue
|
||||
if storage[analyserPanelName].bestHeal < healValue then
|
||||
storage[analyserPanelName].bestHeal = healValue
|
||||
end
|
||||
end
|
||||
|
||||
-- [[ waste]] --
|
||||
if string.find(text, "Using one of") then
|
||||
local splitTwo = string.split(text, "Using one of")
|
||||
if #splitTwo == 1 then
|
||||
local itemAmount = string.match(splitTwo[1], "%d+")
|
||||
end
|
||||
|
||||
end
|
||||
end)
|
||||
|
||||
function hourVal(v)
|
||||
if not v then return end
|
||||
return (v/uptime)*3600
|
||||
end
|
||||
|
||||
function expH()
|
||||
return (expGained()/uptime)*3600
|
||||
end
|
||||
|
||||
local lootWorth
|
||||
macro(1000, function()
|
||||
-- [[ profit ]] --
|
||||
lootWorth = 0
|
||||
for k, v in pairs(droppedItems) do
|
||||
if lootitems[k] then
|
||||
lootWorth = lootWorth + (lootitems[k]*v)
|
||||
end
|
||||
end
|
||||
-- [[ Hunt Window ]] --
|
||||
huntWindow.contentsPanel.sessionValue:setText(sessionTime())
|
||||
huntWindow.contentsPanel.xpGainValue:setText(format_thousand(expGained()))
|
||||
huntWindow.contentsPanel.xpHourValue:setText(format_thousand(expH()))
|
||||
if cumulatedDamage then huntWindow.contentsPanel.damageValue:setText(format_thousand(cumulatedDamage)) end
|
||||
if cumulatedHealing then huntWindow.contentsPanel.healingValue:setText(format_thousand(cumulatedHealing)) end
|
||||
huntWindow.contentsPanel.damageHourValue:setText(format_thousand(hourVal(cumulatedDamage)))
|
||||
huntWindow.contentsPanel.healingHourValue:setText(format_thousand(hourVal(cumulatedHealing)))
|
||||
huntWindow.contentsPanel.lootValue:setText(format_thousand(lootWorth))
|
||||
-- [[ XP Window ]] --
|
||||
xpWindow.contentsPanel.xpValue:setText(format_thousand(expGained()))
|
||||
xpWindow.contentsPanel.hourValue:setText(format_thousand(expH()))
|
||||
if not nextLevelData() then xpWindow.contentsPanel.ttnlValue:setText("-") else xpWindow.contentsPanel.ttnlValue:setText(nextLevelData()) end
|
||||
-- [[ Impact Window ]] --
|
||||
if cumulatedDamage then impactWindow.contentsPanel.damageValue:setText(format_thousand(cumulatedDamage)) end
|
||||
if dps then impactWindow.contentsPanel.maxDpsValue:setText(format_thousand(dps)) end
|
||||
impactWindow.contentsPanel.allTimeHighValue:setText(format_thousand(storage[analyserPanelName].bestHit))
|
||||
if cumulatedHealing then impactWindow.contentsPanel.healingValue:setText(format_thousand(cumulatedHealing)) end
|
||||
if hps then impactWindow.contentsPanel.maxHpsValue:setText(format_thousand(hps)) end
|
||||
impactWindow.contentsPanel.allTimeHighHealValue:setText(format_thousand(storage[analyserPanelName].bestHeal))
|
||||
-- [[ Loot Window ]] --
|
||||
lootWindow.contentsPanel.lootValue:setText(format_thousand(lootWorth))
|
||||
lootWindow.contentsPanel.lootHourValue:setText(format_thousand(hourVal(lootWorth)))
|
||||
end)
|
47
modules/game_bot/default_configs/vithrax_1.1/analyzers.otui
Normal file
47
modules/game_bot/default_configs/vithrax_1.1/analyzers.otui
Normal file
@ -0,0 +1,47 @@
|
||||
MainAnalyzer < MiniWindow
|
||||
!text: tr('Analytics Selector')
|
||||
height: 125
|
||||
icon: /images/topbuttons/analyzers
|
||||
&autoOpen: false
|
||||
|
||||
|
||||
MiniWindowContents
|
||||
Button
|
||||
id: HuntButton
|
||||
!text: tr('Hunting Session Analyser')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Button
|
||||
id: lootSupplyButton
|
||||
!text: tr('Loot & Supplies Analyser')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Button
|
||||
id: impactButton
|
||||
!text: tr('Impact Analyser')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Button
|
||||
id: xpButton
|
||||
!text: tr('XP Analyser')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
margin-right: 3
|
@ -0,0 +1,3 @@
|
||||
macro(60000, function()
|
||||
turn(math.random(0,3))
|
||||
end)
|
76
modules/game_bot/default_configs/vithrax_1.1/antipush.lua
Normal file
76
modules/game_bot/default_configs/vithrax_1.1/antipush.lua
Normal file
@ -0,0 +1,76 @@
|
||||
AntiPush = function(parent)
|
||||
if not parent then
|
||||
parent = panel
|
||||
end
|
||||
|
||||
local panelName = "antiPushPanel"
|
||||
local ui = g_ui.createWidget("ItemsPanel", parent)
|
||||
ui:setId(panelName)
|
||||
|
||||
if not storage[panelName] then
|
||||
storage[panelName] = {}
|
||||
end
|
||||
|
||||
ui.title:setText("Anti-Push Items")
|
||||
ui.title:setOn(storage[panelName].enabled)
|
||||
ui.title.onClick = function(widget)
|
||||
storage[panelName].enabled = not storage[panelName].enabled
|
||||
widget:setOn(storage[panelName].enabled)
|
||||
end
|
||||
|
||||
if type(storage[panelName].items) ~= 'table' then
|
||||
storage[panelName].items = {3031, 3035, 0, 0, 0}
|
||||
end
|
||||
|
||||
for i=1,5 do
|
||||
ui.items:getChildByIndex(i).onItemChange = function(widget)
|
||||
storage[panelName].items[i] = widget:getItemId()
|
||||
end
|
||||
ui.items:getChildByIndex(i):setItemId(storage[panelName].items[i])
|
||||
end
|
||||
|
||||
macro(100, function()
|
||||
if not storage[panelName].enabled then
|
||||
return
|
||||
end
|
||||
local tile = g_map.getTile(player:getPosition())
|
||||
if not tile then
|
||||
return
|
||||
end
|
||||
local topItem = tile:getTopUseThing()
|
||||
if topItem and topItem:isStackable() then
|
||||
topItem = topItem:getId()
|
||||
else
|
||||
topItem = 0
|
||||
end
|
||||
local candidates = {}
|
||||
for i, item in pairs(storage[panelName].items) do
|
||||
if item >= 100 and item ~= topItem and findItem(item) then
|
||||
table.insert(candidates, item)
|
||||
end
|
||||
end
|
||||
if #candidates == 0 then
|
||||
return
|
||||
end
|
||||
if type(storage[panelName].lastItem) ~= 'number' or storage[panelName].lastItem > #candidates then
|
||||
storage[panelName].lastItem = 1
|
||||
end
|
||||
local item = findItem(candidates[storage[panelName].lastItem])
|
||||
g_game.move(item, player:getPosition(), 1)
|
||||
storage[panelName].lastItem = storage[panelName].lastItem + 1
|
||||
end)
|
||||
|
||||
macro(175, "Pull Nearby Items", function()
|
||||
local trashitem = nil
|
||||
for _, tile in pairs(g_map.getTiles(posz())) do
|
||||
if distanceFromPlayer(tile:getPosition()) == 1 and #tile:getItems() ~= 0 and not tile:getTopUseThing():isNotMoveable() then
|
||||
trashitem = tile:getTopUseThing()
|
||||
g_game.move(trashitem, pos(), trashitem:getCount())
|
||||
return
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
AntiPush(setDefaultTab("Tools"))
|
||||
addSeparator()
|
@ -0,0 +1,8 @@
|
||||
if player:getBlessings() == 0 then
|
||||
say("!bless")
|
||||
schedule(2000, function()
|
||||
if player:getBlessings() == 0 then
|
||||
error("!! Blessings not bought !!")
|
||||
end
|
||||
end)
|
||||
end
|
315
modules/game_bot/default_configs/vithrax_1.1/cavebot/actions.lua
Normal file
315
modules/game_bot/default_configs/vithrax_1.1/cavebot/actions.lua
Normal file
@ -0,0 +1,315 @@
|
||||
CaveBot.Actions = {}
|
||||
|
||||
-- it adds an action widget to list
|
||||
CaveBot.addAction = function(action, value, focus)
|
||||
action = action:lower()
|
||||
local raction = CaveBot.Actions[action]
|
||||
if not raction then
|
||||
return error("Invalid cavebot action: " .. action)
|
||||
end
|
||||
if type(value) == 'number' then
|
||||
value = tostring(value)
|
||||
end
|
||||
local widget = UI.createWidget("CaveBotAction", CaveBot.actionList)
|
||||
widget:setText(action .. ":" .. value:split("\n")[1])
|
||||
widget.action = action
|
||||
widget.value = value
|
||||
if raction.color then
|
||||
widget:setColor(raction.color)
|
||||
end
|
||||
widget.onDoubleClick = function(cwidget) -- edit on double click
|
||||
if CaveBot.Editor then
|
||||
schedule(20, function() -- schedule to have correct focus
|
||||
CaveBot.Editor.edit(cwidget.action, cwidget.value, function(action, value)
|
||||
CaveBot.editAction(cwidget, action, value)
|
||||
CaveBot.save()
|
||||
end)
|
||||
end)
|
||||
end
|
||||
end
|
||||
if focus then
|
||||
widget:focus()
|
||||
CaveBot.actionList:ensureChildVisible(widget)
|
||||
end
|
||||
return widget
|
||||
end
|
||||
|
||||
-- it updates existing widget, you should call CaveBot.save() later
|
||||
CaveBot.editAction = function(widget, action, value)
|
||||
action = action:lower()
|
||||
local raction = CaveBot.Actions[action]
|
||||
if not raction then
|
||||
return error("Invalid cavebot action: " .. action)
|
||||
end
|
||||
|
||||
if not widget.action or not widget.value then
|
||||
return error("Invalid cavebot action widget, has missing action or value")
|
||||
end
|
||||
|
||||
widget:setText(action .. ":" .. value:split("\n")[1])
|
||||
widget.action = action
|
||||
widget.value = value
|
||||
if raction.color then
|
||||
widget:setColor(raction.color)
|
||||
end
|
||||
return widget
|
||||
end
|
||||
|
||||
--[[
|
||||
registerAction:
|
||||
action - string, color - string, callback = function(value, retries, prev)
|
||||
value is a string value of action, retries is number which will grow by 1 if return is "retry"
|
||||
prev is a true when previuos action was executed succesfully, false otherwise
|
||||
it must return true if executed correctly, false otherwise
|
||||
it can also return string "retry", then the function will be called again in 20 ms
|
||||
]]--
|
||||
CaveBot.registerAction = function(action, color, callback)
|
||||
action = action:lower()
|
||||
if CaveBot.Actions[action] then
|
||||
return error("Duplicated acction: " .. action)
|
||||
end
|
||||
CaveBot.Actions[action] = {
|
||||
color=color,
|
||||
callback=callback
|
||||
}
|
||||
end
|
||||
|
||||
CaveBot.registerAction("label", "yellow", function(value, retries, prev)
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("gotolabel", "#FFFF55", function(value, retries, prev)
|
||||
return CaveBot.gotoLabel(value)
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("delay", "#AAAAAA", function(value, retries, prev)
|
||||
if retries == 0 then
|
||||
CaveBot.delay(tonumber(value))
|
||||
return "retry"
|
||||
end
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("function", "red", function(value, retries, prev)
|
||||
local prefix = "local retries = " .. retries .. "\nlocal prev = " .. tostring(prev) .. "\nlocal delay = CaveBot.delay\nlocal gotoLabel = CaveBot.gotoLabel\n"
|
||||
prefix = prefix .. "local macro = function() error('Macros inside cavebot functions are not allowed') end\n"
|
||||
for extension, callbacks in pairs(CaveBot.Extensions) do
|
||||
prefix = prefix .. "local " .. extension .. " = CaveBot.Extensions." .. extension .. "\n"
|
||||
end
|
||||
local status, result = pcall(function()
|
||||
return assert(load(prefix .. value, "cavebot_function"))()
|
||||
end)
|
||||
if not status then
|
||||
error("Error in cavebot function:\n" .. result)
|
||||
return false
|
||||
end
|
||||
return result
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("goto", "green", function(value, retries, prev)
|
||||
local pos = regexMatch(value, "\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+),?\\s*([0-9]?)")
|
||||
if not pos[1] then
|
||||
error("Invalid cavebot goto action value. It should be position (x,y,z), is: " .. value)
|
||||
return false
|
||||
end
|
||||
|
||||
if CaveBot.Config.get("mapClick") then
|
||||
if retries >= 5 then
|
||||
return false -- tried 5 times, can't get there
|
||||
end
|
||||
else
|
||||
if retries >= 100 then
|
||||
return false -- tried 100 times, can't get there
|
||||
end
|
||||
end
|
||||
|
||||
local precision = tonumber(pos[1][5])
|
||||
pos = {x=tonumber(pos[1][2]), y=tonumber(pos[1][3]), z=tonumber(pos[1][4])}
|
||||
local playerPos = player:getPosition()
|
||||
if pos.z ~= playerPos.z then
|
||||
return false -- different floor
|
||||
end
|
||||
|
||||
if math.abs(pos.x-playerPos.x) + math.abs(pos.y-playerPos.y) > 40 then
|
||||
return false -- too far way
|
||||
end
|
||||
|
||||
local minimapColor = g_map.getMinimapColor(pos)
|
||||
local stairs = (minimapColor >= 210 and minimapColor <= 213)
|
||||
|
||||
if stairs then
|
||||
if math.abs(pos.x-playerPos.x) == 0 and math.abs(pos.y-playerPos.y) <= 0 then
|
||||
return true -- already at position
|
||||
end
|
||||
elseif math.abs(pos.x-playerPos.x) == 0 and math.abs(pos.y-playerPos.y) <= (precision or 1) then
|
||||
return true -- already at position
|
||||
end
|
||||
-- check if there's a path to that place, ignore creatures and fields
|
||||
local path = findPath(playerPos, pos, 40, { ignoreNonPathable = true, precision = 1, ignoreCreatures = true })
|
||||
if not path then
|
||||
return false -- there's no way
|
||||
end
|
||||
|
||||
-- check if there's a path to destination but consider Creatures (attack only if trapped)
|
||||
local path2 = findPath(playerPos, pos, 40, { ignoreNonPathable = true, precision = 1 })
|
||||
if not path2 then
|
||||
local monsters = {}
|
||||
for i, spec in pairs(getSpectators()) do
|
||||
if spec:isMonster() and spec:canShoot() and findPath(playerPos, spec:getPosition(), 20, {ignoreNonPathable = true, precision = 1}) then
|
||||
table.insert(monsters, {mob = spec, dist = getDistanceBetween(pos, spec:getPosition())})
|
||||
end
|
||||
end
|
||||
table.sort(monsters, function(a,b) return a.dist < b.dist end)
|
||||
if monsters[1] then
|
||||
g_game.attack(monsters[1].mob)
|
||||
storage.blockMonster = monsters[1].mob
|
||||
autoWalk(storage.blockMonster, 10, {precision = 1})
|
||||
storage.clearing = true
|
||||
CaveBot.setOff()
|
||||
g_game.setChaseMode(1)
|
||||
schedule(10000, function() CaveBot.setOn() end) -- just in case callback trigger fails
|
||||
return "retry"
|
||||
else
|
||||
return false -- there's no way
|
||||
end
|
||||
end
|
||||
|
||||
-- try to find path, don't ignore creatures, don't ignore fields
|
||||
if not CaveBot.Config.get("ignoreFields") and CaveBot.walkTo(pos, 40) then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
-- try to find path, don't ignore creatures, ignore fields
|
||||
if CaveBot.walkTo(pos, 40, { ignoreNonPathable = true }) then
|
||||
return "retry"
|
||||
end
|
||||
|
||||
if retries >= 3 then
|
||||
-- try to lower precision, find something close to final position
|
||||
local precison = retries - 1
|
||||
if stairs then
|
||||
precison = 0
|
||||
end
|
||||
if CaveBot.walkTo(pos, 50, { ignoreNonPathable = true, precision = precison }) then
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
|
||||
if not CaveBot.Config.get("mapClick") and retries >= 5 then
|
||||
return false
|
||||
end
|
||||
|
||||
if CaveBot.Config.get("skipBlocked") then
|
||||
return false
|
||||
end
|
||||
|
||||
-- everything else failed, try to walk ignoring creatures, maybe will work
|
||||
CaveBot.walkTo(pos, 40, { ignoreNonPathable = true, precision = 1, ignoreCreatures = true })
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
onCreatureDisappear(function(creature)
|
||||
if creature ~= storage.blockMonster then return end
|
||||
if storage.clearing then
|
||||
CaveBot.setOn()
|
||||
storage.blockMonster = nil
|
||||
storage.clearing = false
|
||||
end
|
||||
end)
|
||||
|
||||
onCreaturePositionChange(function(creature, newPos, oldPos)
|
||||
if creature ~= storage.blockMonster and creature ~= player then return end
|
||||
if storage.clearing then
|
||||
if creature == storage.blockMonster and not findPath(player:getPosition(), newPos, 20, {ignoreNonPathable = true, precision = 1}) then
|
||||
CaveBot.setOn()
|
||||
storage.blockMonster = nil
|
||||
storage.clearing = false
|
||||
end
|
||||
if creature == player then
|
||||
if oldPos.z ~= newPos.z then
|
||||
CaveBot.setOn()
|
||||
storage.blockMonster = nil
|
||||
storage.clearing = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("use", "#FFB272", function(value, retries, prev)
|
||||
local pos = regexMatch(value, "\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)")
|
||||
if not pos[1] then
|
||||
local itemid = tonumber(value)
|
||||
if not itemid then
|
||||
error("Invalid cavebot use action value. It should be (x,y,z) or item id, is: " .. value)
|
||||
return false
|
||||
end
|
||||
use(itemid)
|
||||
return true
|
||||
end
|
||||
|
||||
pos = {x=tonumber(pos[1][2]), y=tonumber(pos[1][3]), z=tonumber(pos[1][4])}
|
||||
local playerPos = player:getPosition()
|
||||
if pos.z ~= playerPos.z then
|
||||
return false -- different floor
|
||||
end
|
||||
|
||||
if math.max(math.abs(pos.x-playerPos.x), math.abs(pos.y-playerPos.y)) > 7 then
|
||||
return false -- too far way
|
||||
end
|
||||
|
||||
local tile = g_map.getTile(pos)
|
||||
if not tile then
|
||||
return false
|
||||
end
|
||||
|
||||
local topThing = tile:getTopUseThing()
|
||||
if not topThing then
|
||||
return false
|
||||
end
|
||||
|
||||
use(topThing)
|
||||
CaveBot.delay(CaveBot.Config.get("useDelay") + CaveBot.Config.get("ping"))
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("usewith", "#EEB292", function(value, retries, prev)
|
||||
local pos = regexMatch(value, "\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)")
|
||||
if not pos[1] then
|
||||
if not itemid then
|
||||
error("Invalid cavebot usewith action value. It should be (itemid,x,y,z) or item id, is: " .. value)
|
||||
return false
|
||||
end
|
||||
use(itemid)
|
||||
return true
|
||||
end
|
||||
|
||||
local itemid = tonumber(pos[1][2])
|
||||
pos = {x=tonumber(pos[1][3]), y=tonumber(pos[1][4]), z=tonumber(pos[1][5])}
|
||||
local playerPos = player:getPosition()
|
||||
if pos.z ~= playerPos.z then
|
||||
return false -- different floor
|
||||
end
|
||||
|
||||
if math.max(math.abs(pos.x-playerPos.x), math.abs(pos.y-playerPos.y)) > 7 then
|
||||
return false -- too far way
|
||||
end
|
||||
|
||||
local tile = g_map.getTile(pos)
|
||||
if not tile then
|
||||
return false
|
||||
end
|
||||
|
||||
local topThing = tile:getTopUseThing()
|
||||
if not topThing then
|
||||
return false
|
||||
end
|
||||
|
||||
usewith(itemid, topThing)
|
||||
CaveBot.delay(CaveBot.Config.get("useDelay") + CaveBot.Config.get("ping"))
|
||||
return true
|
||||
end)
|
||||
|
||||
CaveBot.registerAction("say", "#FF55FF", function(value, retries, prev)
|
||||
say(value)
|
||||
return true
|
||||
end)
|
@ -0,0 +1,72 @@
|
||||
CaveBot.Extensions.Bank = {}
|
||||
|
||||
CaveBot.Extensions.Bank.setup = function()
|
||||
CaveBot.registerAction("bank", "#00FFFF", function(value, retries)
|
||||
local data = string.split(value, ",")
|
||||
local waitVal = 300
|
||||
local amount = 0
|
||||
local actionType
|
||||
local npcName
|
||||
if #data ~= 3 and #data ~= 2 then
|
||||
warn("CaveBot[Bank]: incorrect value!")
|
||||
return false
|
||||
else
|
||||
actionType = data[1]:trim():lower()
|
||||
npcName = data[2]:trim()
|
||||
if #data == 3 then
|
||||
amount = tonumber(data[3]:trim())
|
||||
end
|
||||
end
|
||||
|
||||
if actionType ~= "withdraw" and actionType ~= "deposit" then
|
||||
warn("CaveBot[Bank]: incorrect action type! should be withdraw/deposit, is: " .. actionType)
|
||||
return false
|
||||
elseif actionType == "withdraw" then
|
||||
local value = tonumber(amount)
|
||||
if not value then
|
||||
warn("CaveBot[Bank]: incorrect amount value! should be number, is: " .. amount)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if retries > 5 then
|
||||
print("CaveBot[Bank]: too many tries, skipping")
|
||||
return false
|
||||
end
|
||||
|
||||
local npc = getCreatureByName(npcName)
|
||||
if not npc then
|
||||
print("CaveBot[Bank]: NPC not found, skipping")
|
||||
return false
|
||||
end
|
||||
|
||||
local pos = player:getPosition()
|
||||
local npcPos = npc:getPosition()
|
||||
if math.max(math.abs(pos.x - npcPos.x), math.abs(pos.y - npcPos.y)) > 3 then
|
||||
autoWalk(npcPos, 20, {ignoreNonPathable = true, precision=3})
|
||||
delay(300)
|
||||
return "retry"
|
||||
end
|
||||
|
||||
if actionType == "deposit" then
|
||||
NPC.say("hi")
|
||||
schedule(waitVal, function() NPC.say("deposit all") end)
|
||||
schedule(waitVal*2, function() NPC.say("yes") end)
|
||||
CaveBot.delay(waitVal*3)
|
||||
return true
|
||||
else
|
||||
NPC.say("hi")
|
||||
schedule(waitVal, function() NPC.say("withdraw") end)
|
||||
schedule(waitVal*2, function() NPC.say(value) end)
|
||||
schedule(waitVal*3, function() NPC.say("yes") end)
|
||||
CaveBot.delay(waitVal*4)
|
||||
return true
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("bank", "bank", {
|
||||
value="action, NPC name",
|
||||
title="Banker",
|
||||
description="action type(withdraw/deposit), NPC name, if withdraw: amount",
|
||||
})
|
||||
end
|
@ -0,0 +1,116 @@
|
||||
CaveBot.Extensions.BuySupplies = {}
|
||||
|
||||
storage.buySuppliesCap = 0
|
||||
CaveBot.Extensions.BuySupplies.setup = function()
|
||||
CaveBot.registerAction("BuySupplies", "#00FFFF", function(value, retries)
|
||||
local item1Count = 0
|
||||
local item2Count = 0
|
||||
local item3Count = 0
|
||||
local item4Count = 0
|
||||
local item5Count = 0
|
||||
|
||||
local val = string.split(value, ",")
|
||||
local waitVal
|
||||
if #val == 0 or #val > 2 then
|
||||
warn("CaveBot[BuySupplies]: incorrect BuySupplies value")
|
||||
return false
|
||||
elseif #val == 2 then
|
||||
waitVal = tonumber(val[2]:trim())
|
||||
end
|
||||
|
||||
local npc = getCreatureByName(val[1]:trim())
|
||||
if not npc then
|
||||
print("CaveBot[BuySupplies]: NPC not found")
|
||||
return false
|
||||
end
|
||||
|
||||
if not waitVal and #val == 2 then
|
||||
warn("CaveBot[BuySupplies]: incorrect delay values!")
|
||||
elseif waitVal and #val == 2 then
|
||||
delay(waitVal)
|
||||
end
|
||||
|
||||
if retries > 30 then
|
||||
print("CaveBot[BuySupplies]: Too many tries, can't buy")
|
||||
return false
|
||||
end
|
||||
|
||||
if freecap() == storage.buySuppliesCap then
|
||||
storage.buySuppliesCap = 0
|
||||
print("CaveBot[BuySupplies]: Bought Everything, proceeding")
|
||||
return true
|
||||
end
|
||||
|
||||
delay(800)
|
||||
|
||||
local pos = player:getPosition()
|
||||
local npcPos = npc:getPosition()
|
||||
if math.max(math.abs(pos.x - npcPos.x), math.abs(pos.y - npcPos.y)) > 3 then
|
||||
autoWalk(npcPos, 20, {ignoreNonPathable = true, precision=3})
|
||||
delay(300)
|
||||
return "retry"
|
||||
end
|
||||
|
||||
for _, container in pairs(getContainers()) do
|
||||
for _, item in ipairs(container:getItems()) do
|
||||
if (storage[suppliesPanelName].item1 > 100) and (item:getId() == storage[suppliesPanelName].item1) then
|
||||
item1Count = item1Count + item:getCount()
|
||||
end
|
||||
if (storage[suppliesPanelName].item2 > 100) and (item:getId() == storage[suppliesPanelName].item2) then
|
||||
item2Count = item2Count + item:getCount()
|
||||
end
|
||||
if (storage[suppliesPanelName].item3 > 100) and (item:getId() == storage[suppliesPanelName].item3) then
|
||||
item3Count = item3Count + item:getCount()
|
||||
end
|
||||
if (storage[suppliesPanelName].item4 > 100) and (item:getId() == storage[suppliesPanelName].item4) then
|
||||
item4Count = item4Count + item:getCount()
|
||||
end
|
||||
if (storage[suppliesPanelName].item5 > 100) and (item:getId() == storage[suppliesPanelName].item5) then
|
||||
item5Count = item5Count + item:getCount()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local itemList = {
|
||||
item1 = {ID = storage[suppliesPanelName].item1, maxAmount = storage[suppliesPanelName].item1Max, currentAmount = item1Count},
|
||||
item2 = {ID = storage[suppliesPanelName].item2, maxAmount = storage[suppliesPanelName].item2Max, currentAmount = item2Count},
|
||||
item3 = {ID = storage[suppliesPanelName].item3, maxAmount = storage[suppliesPanelName].item3Max, currentAmount = item3Count},
|
||||
item4 = {ID = storage[suppliesPanelName].item4, maxAmount = storage[suppliesPanelName].item4Max, currentAmount = item4Count},
|
||||
item5 = {ID = storage[suppliesPanelName].item5, maxAmount = storage[suppliesPanelName].item5Max, currentAmount = item5Count}
|
||||
}
|
||||
|
||||
if not NPC.isTrading() then
|
||||
NPC.say("hi")
|
||||
schedule(500, function() NPC.say("trade") end)
|
||||
else
|
||||
storage.buySuppliesCap = freecap()
|
||||
end
|
||||
|
||||
for i, item in pairs(itemList) do
|
||||
if item["ID"] > 100 then
|
||||
local amountToBuy = item["maxAmount"] - item["currentAmount"]
|
||||
if amountToBuy > 100 then
|
||||
for i=1, math.ceil(amountToBuy/100), 1 do
|
||||
NPC.buy(item["ID"], math.min(100, amountToBuy))
|
||||
amountToBuy = amountToBuy - math.min(100, amountToBuy)
|
||||
print("CaveBot[BuySupplies]: bought " .. amountToBuy .. "x " .. item["ID"])
|
||||
return "retry"
|
||||
end
|
||||
else
|
||||
if amountToBuy > 0 then
|
||||
NPC.buy(item["ID"], amountToBuy)
|
||||
print("CaveBot[BuySupplies]: bought " .. amountToBuy .. "x " .. item["ID"])
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("buysupplies", "buy supplies", {
|
||||
value="NPC name",
|
||||
title="Buy Supplies",
|
||||
description="NPC Name, delay(in ms, optional)",
|
||||
})
|
||||
end
|
224
modules/game_bot/default_configs/vithrax_1.1/cavebot/cavebot.lua
Normal file
224
modules/game_bot/default_configs/vithrax_1.1/cavebot/cavebot.lua
Normal file
@ -0,0 +1,224 @@
|
||||
local cavebotMacro = nil
|
||||
local config = nil
|
||||
|
||||
-- ui
|
||||
local configWidget = UI.Config()
|
||||
local ui = UI.createWidget("CaveBotPanel")
|
||||
|
||||
ui.list = ui.listPanel.list -- shortcut
|
||||
CaveBot.actionList = ui.list
|
||||
|
||||
if CaveBot.Editor then
|
||||
CaveBot.Editor.setup()
|
||||
end
|
||||
if CaveBot.Config then
|
||||
CaveBot.Config.setup()
|
||||
end
|
||||
for extension, callbacks in pairs(CaveBot.Extensions) do
|
||||
if callbacks.setup then
|
||||
callbacks.setup()
|
||||
end
|
||||
end
|
||||
|
||||
-- main loop, controlled by config
|
||||
local actionRetries = 0
|
||||
local prevActionResult = true
|
||||
cavebotMacro = macro(20, function()
|
||||
if TargetBot and TargetBot.isActive() and not TargetBot.isCaveBotActionAllowed() then
|
||||
CaveBot.resetWalking()
|
||||
return -- target bot or looting is working, wait
|
||||
end
|
||||
|
||||
if CaveBot.doWalking() then
|
||||
return -- executing walking
|
||||
end
|
||||
|
||||
local actions = ui.list:getChildCount()
|
||||
if actions == 0 then return end
|
||||
local currentAction = ui.list:getFocusedChild()
|
||||
if not currentAction then
|
||||
currentAction = ui.list:getFirstChild()
|
||||
end
|
||||
local action = CaveBot.Actions[currentAction.action]
|
||||
local value = currentAction.value
|
||||
local retry = false
|
||||
if action then
|
||||
local status, result = pcall(function()
|
||||
CaveBot.resetWalking()
|
||||
return action.callback(value, actionRetries, prevActionResult)
|
||||
end)
|
||||
if status then
|
||||
if result == "retry" then
|
||||
actionRetries = actionRetries + 1
|
||||
retry = true
|
||||
elseif type(result) == 'boolean' then
|
||||
actionRetries = 0
|
||||
prevActionResult = result
|
||||
else
|
||||
error("Invalid return from cavebot action (" .. currentAction.action .. "), should be \"retry\", false or true, is: " .. tostring(result))
|
||||
end
|
||||
else
|
||||
error("Error while executing cavebot action (" .. currentAction.action .. "):\n" .. result)
|
||||
end
|
||||
else
|
||||
error("Invalid cavebot action: " .. currentAction.action)
|
||||
end
|
||||
|
||||
if retry then
|
||||
return
|
||||
end
|
||||
|
||||
if currentAction ~= ui.list:getFocusedChild() then
|
||||
-- focused child can change durring action, get it again and reset state
|
||||
currentAction = ui.list:getFocusedChild() or ui.list:getFirstChild()
|
||||
actionRetries = 0
|
||||
prevActionResult = true
|
||||
end
|
||||
local nextAction = ui.list:getChildIndex(currentAction) + 1
|
||||
if nextAction > actions then
|
||||
nextAction = 1
|
||||
end
|
||||
ui.list:focusChild(ui.list:getChildByIndex(nextAction))
|
||||
end)
|
||||
|
||||
-- config, its callback is called immediately, data can be nil
|
||||
local lastConfig = ""
|
||||
config = Config.setup("cavebot_configs", configWidget, "cfg", function(name, enabled, data)
|
||||
if enabled and CaveBot.Recorder.isOn() then
|
||||
CaveBot.Recorder.disable()
|
||||
CaveBot.setOff()
|
||||
return
|
||||
end
|
||||
|
||||
local currentActionIndex = ui.list:getChildIndex(ui.list:getFocusedChild())
|
||||
ui.list:destroyChildren()
|
||||
if not data then return cavebotMacro.setOff() end
|
||||
|
||||
local cavebotConfig = nil
|
||||
for k,v in ipairs(data) do
|
||||
if type(v) == "table" and #v == 2 then
|
||||
if v[1] == "config" then
|
||||
local status, result = pcall(function()
|
||||
return json.decode(v[2])
|
||||
end)
|
||||
if not status then
|
||||
error("Error while parsing CaveBot extensions from config:\n" .. result)
|
||||
else
|
||||
cavebotConfig = result
|
||||
end
|
||||
elseif v[1] == "extensions" then
|
||||
local status, result = pcall(function()
|
||||
return json.decode(v[2])
|
||||
end)
|
||||
if not status then
|
||||
error("Error while parsing CaveBot extensions from config:\n" .. result)
|
||||
else
|
||||
for extension, callbacks in pairs(CaveBot.Extensions) do
|
||||
if callbacks.onConfigChange then
|
||||
callbacks.onConfigChange(name, enabled, result[extension])
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
CaveBot.addAction(v[1], v[2])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CaveBot.Config.onConfigChange(name, enabled, cavebotConfig)
|
||||
|
||||
actionRetries = 0
|
||||
CaveBot.resetWalking()
|
||||
prevActionResult = true
|
||||
cavebotMacro.setOn(enabled)
|
||||
cavebotMacro.delay = nil
|
||||
if lastConfig == name then
|
||||
-- restore focused child on the action list
|
||||
ui.list:focusChild(ui.list:getChildByIndex(currentActionIndex))
|
||||
end
|
||||
lastConfig = name
|
||||
end)
|
||||
|
||||
-- ui callbacks
|
||||
ui.showEditor.onClick = function()
|
||||
if not CaveBot.Editor then return end
|
||||
if ui.showEditor:isOn() then
|
||||
CaveBot.Editor.hide()
|
||||
ui.showEditor:setOn(false)
|
||||
else
|
||||
CaveBot.Editor.show()
|
||||
ui.showEditor:setOn(true)
|
||||
end
|
||||
end
|
||||
|
||||
ui.showConfig.onClick = function()
|
||||
if not CaveBot.Config then return end
|
||||
if ui.showConfig:isOn() then
|
||||
CaveBot.Config.hide()
|
||||
ui.showConfig:setOn(false)
|
||||
else
|
||||
CaveBot.Config.show()
|
||||
ui.showConfig:setOn(true)
|
||||
end
|
||||
end
|
||||
|
||||
-- public function, you can use them in your scripts
|
||||
CaveBot.isOn = function()
|
||||
return config.isOn()
|
||||
end
|
||||
|
||||
CaveBot.isOff = function()
|
||||
return config.isOff()
|
||||
end
|
||||
|
||||
CaveBot.setOn = function(val)
|
||||
if val == false then
|
||||
return CaveBot.setOff(true)
|
||||
end
|
||||
config.setOn()
|
||||
end
|
||||
|
||||
CaveBot.setOff = function(val)
|
||||
if val == false then
|
||||
return CaveBot.setOn(true)
|
||||
end
|
||||
config.setOff()
|
||||
end
|
||||
|
||||
CaveBot.delay = function(value)
|
||||
cavebotMacro.delay = math.max(cavebotMacro.delay or 0, now + value)
|
||||
end
|
||||
|
||||
CaveBot.gotoLabel = function(label)
|
||||
label = label:lower()
|
||||
for index, child in ipairs(ui.list:getChildren()) do
|
||||
if child.action == "label" and child.value:lower() == label then
|
||||
ui.list:focusChild(child)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
CaveBot.save = function()
|
||||
local data = {}
|
||||
for index, child in ipairs(ui.list:getChildren()) do
|
||||
table.insert(data, {child.action, child.value})
|
||||
end
|
||||
|
||||
if CaveBot.Config then
|
||||
table.insert(data, {"config", json.encode(CaveBot.Config.save())})
|
||||
end
|
||||
|
||||
local extension_data = {}
|
||||
for extension, callbacks in pairs(CaveBot.Extensions) do
|
||||
if callbacks.onSave then
|
||||
local ext_data = callbacks.onSave()
|
||||
if type(ext_data) == "table" then
|
||||
extension_data[extension] = ext_data
|
||||
end
|
||||
end
|
||||
end
|
||||
table.insert(data, {"extensions", json.encode(extension_data, 2)})
|
||||
config.save(data)
|
||||
end
|
@ -0,0 +1,58 @@
|
||||
CaveBotAction < Label
|
||||
background-color: alpha
|
||||
text-offset: 2 0
|
||||
focusable: true
|
||||
|
||||
$focus:
|
||||
background-color: #00000055
|
||||
|
||||
|
||||
CaveBotPanel < Panel
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
HorizontalSeparator
|
||||
margin-top: 2
|
||||
margin-bottom: 5
|
||||
|
||||
Panel
|
||||
id: listPanel
|
||||
height: 100
|
||||
margin-top: 2
|
||||
|
||||
TextList
|
||||
id: list
|
||||
anchors.fill: parent
|
||||
vertical-scrollbar: listScrollbar
|
||||
margin-right: 15
|
||||
focusable: false
|
||||
auto-focus: first
|
||||
|
||||
VerticalScrollBar
|
||||
id: listScrollbar
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
pixels-scroll: true
|
||||
step: 10
|
||||
|
||||
BotSwitch
|
||||
id: showEditor
|
||||
margin-top: 2
|
||||
|
||||
$on:
|
||||
text: Hide waypoints editor
|
||||
|
||||
$!on:
|
||||
text: Show waypoints editor
|
||||
|
||||
BotSwitch
|
||||
id: showConfig
|
||||
margin-top: 2
|
||||
|
||||
$on:
|
||||
text: Hide config
|
||||
|
||||
$!on:
|
||||
text: Show config
|
@ -0,0 +1,94 @@
|
||||
-- config for bot
|
||||
CaveBot.Config = {}
|
||||
CaveBot.Config.values = {}
|
||||
CaveBot.Config.default_values = {}
|
||||
CaveBot.Config.value_setters = {}
|
||||
|
||||
CaveBot.Config.setup = function()
|
||||
CaveBot.Config.ui = UI.createWidget("CaveBotConfigPanel")
|
||||
local ui = CaveBot.Config.ui
|
||||
local add = CaveBot.Config.add
|
||||
|
||||
add("ping", "Server ping", 100)
|
||||
add("walkDelay", "Walk delay", 10)
|
||||
add("mapClick", "Use map click", false)
|
||||
add("mapClickDelay", "Map click delay", 100)
|
||||
add("ignoreFields", "Ignore fields", false)
|
||||
add("skipBlocked", "Skip blocked path", false)
|
||||
add("useDelay", "Delay after use", 400)
|
||||
end
|
||||
|
||||
CaveBot.Config.show = function()
|
||||
CaveBot.Config.ui:show()
|
||||
end
|
||||
|
||||
CaveBot.Config.hide = function()
|
||||
CaveBot.Config.ui:hide()
|
||||
end
|
||||
|
||||
CaveBot.Config.onConfigChange = function(configName, isEnabled, configData)
|
||||
for k, v in pairs(CaveBot.Config.default_values) do
|
||||
CaveBot.Config.value_setters[k](v)
|
||||
end
|
||||
if not configData then return end
|
||||
for k, v in pairs(configData) do
|
||||
if CaveBot.Config.value_setters[k] then
|
||||
CaveBot.Config.value_setters[k](v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CaveBot.Config.save = function()
|
||||
return CaveBot.Config.values
|
||||
end
|
||||
|
||||
CaveBot.Config.add = function(id, title, defaultValue)
|
||||
if CaveBot.Config.values[id] then
|
||||
return error("Duplicated config key: " .. id)
|
||||
end
|
||||
|
||||
local panel
|
||||
local setter -- sets value
|
||||
if type(defaultValue) == "number" then
|
||||
panel = UI.createWidget("CaveBotConfigNumberValuePanel", CaveBot.Config.ui)
|
||||
setter = function(value)
|
||||
CaveBot.Config.values[id] = value
|
||||
panel.value:setText(value, true)
|
||||
end
|
||||
setter(defaultValue)
|
||||
panel.value.onTextChange = function(widget, newValue)
|
||||
newValue = tonumber(newValue)
|
||||
if newValue then
|
||||
CaveBot.Config.values[id] = newValue
|
||||
CaveBot.save()
|
||||
end
|
||||
end
|
||||
elseif type(defaultValue) == "boolean" then
|
||||
panel = UI.createWidget("CaveBotConfigBooleanValuePanel", CaveBot.Config.ui)
|
||||
setter = function(value)
|
||||
CaveBot.Config.values[id] = value
|
||||
panel.value:setOn(value, true)
|
||||
end
|
||||
setter(defaultValue)
|
||||
panel.value.onClick = function(widget)
|
||||
widget:setOn(not widget:isOn())
|
||||
CaveBot.Config.values[id] = widget:isOn()
|
||||
CaveBot.save()
|
||||
end
|
||||
else
|
||||
return error("Invalid default value of config for key " .. id .. ", should be number or boolean")
|
||||
end
|
||||
|
||||
panel.title:setText(tr(title) .. ":")
|
||||
|
||||
CaveBot.Config.value_setters[id] = setter
|
||||
CaveBot.Config.values[id] = defaultValue
|
||||
CaveBot.Config.default_values[id] = defaultValue
|
||||
end
|
||||
|
||||
CaveBot.Config.get = function(id)
|
||||
if CaveBot.Config.values[id] == nil then
|
||||
return error("Invalid CaveBot.Config.get, id: " .. id)
|
||||
end
|
||||
return CaveBot.Config.values[id]
|
||||
end
|
@ -0,0 +1,57 @@
|
||||
CaveBotConfigPanel < Panel
|
||||
id: cavebotEditor
|
||||
visible: false
|
||||
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
HorizontalSeparator
|
||||
margin-top: 5
|
||||
|
||||
Label
|
||||
text-align: center
|
||||
text: CaveBot Config
|
||||
margin-top: 5
|
||||
|
||||
CaveBotConfigNumberValuePanel < Panel
|
||||
height: 20
|
||||
margin-top: 5
|
||||
|
||||
BotTextEdit
|
||||
id: value
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 5
|
||||
width: 50
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
margin-left: 5
|
||||
|
||||
CaveBotConfigBooleanValuePanel < Panel
|
||||
height: 20
|
||||
margin-top: 5
|
||||
|
||||
BotSwitch
|
||||
id: value
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 5
|
||||
width: 50
|
||||
|
||||
$on:
|
||||
text: On
|
||||
|
||||
$!on:
|
||||
text: Off
|
||||
|
||||
Label
|
||||
id: title
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: prev.verticalCenter
|
||||
margin-left: 5
|
@ -0,0 +1,179 @@
|
||||
CaveBot.Extensions.DWithdraw = {}
|
||||
|
||||
comparePosition = function(pPos, tPos)
|
||||
return (getDistanceBetween(pPos, tPos) <= 1)
|
||||
end
|
||||
|
||||
local depotIDs = {3497, 3498, 3499, 3500}
|
||||
storage.stopSearch = false
|
||||
storage.lootContainerOpen = false
|
||||
local i = 1
|
||||
|
||||
|
||||
CaveBot.Extensions.DWithdraw.setup = function()
|
||||
CaveBot.registerAction("dpwithdraw", "#00FFFF", function(value, retries)
|
||||
if freecap() < 200 then
|
||||
print("CaveBot[DepotWithdraw]: cap limit reached, proceeding")
|
||||
return true
|
||||
end
|
||||
if retries > 600 then
|
||||
print("CaveBot[DepotWithdraw]: actions limit reached, proceeding")
|
||||
return true
|
||||
end
|
||||
delay(50)
|
||||
if not value or #string.split(value, ",") ~= 2 then return end
|
||||
local destName = string.split(value, ",")[1]:trim()
|
||||
local destId = tonumber(string.split(value, ",")[2]:trim())
|
||||
local destContainer
|
||||
|
||||
for i, container in pairs(getContainers()) do
|
||||
if container:getName():lower() == destName:lower() then
|
||||
destContainer = container
|
||||
end
|
||||
if string.find(container:getName():lower(), "depot box") then
|
||||
if #container:getItems() == 0 then
|
||||
print("CaveBot[DepotWithdraw]: all items withdrawn")
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
if not destContainer then
|
||||
print("CaveBot[DepotWithdraw]: container not found!")
|
||||
return false
|
||||
end
|
||||
|
||||
if destContainer:getCapacity() == destContainer:getSize() then
|
||||
for j, item in pairs(destContainer:getItems()) do
|
||||
if item:getId() == destId then
|
||||
g_game.open(item, destContainer)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
print("CaveBot[DepotWithdraw]: loot containers full!")
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
local tileList = {}
|
||||
local tPos
|
||||
local depotClear = false
|
||||
local depotOpen = false
|
||||
local depotBoxOpen = false
|
||||
for _,tile in pairs(g_map.getTiles(posz())) do
|
||||
for i,thing in pairs(tile:getThings()) do
|
||||
if table.find(depotIDs, thing:getId()) then
|
||||
table.insert(tileList, {tileObj = tile, distance = getDistanceBetween(pos(), tile:getPosition()), depotID = thing:getId()})
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(tileList, function(a,b) return a.distance < b.distance end)
|
||||
::findEmptyDP::
|
||||
if tileList[i] and not storage.stopSearch then
|
||||
if tileList[i].depotID == 3498 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x + 1, y = tileList[i].tileObj:getPosition().y, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3499 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x, y = tileList[i].tileObj:getPosition().y + 1, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3500 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x - 1, y = tileList[i].tileObj:getPosition().y, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3497 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x, y = tileList[i].tileObj:getPosition().y - 1, z = tileList[i].tileObj:getPosition().z}
|
||||
end
|
||||
if tPos then
|
||||
local dest = g_map.getTile(tPos)
|
||||
if not comparePosition(pos(), dest:getPosition()) then
|
||||
if not dest:getCreatures()[1] and dest:isWalkable() then
|
||||
if autoWalk(dest:getPosition(), {ignoreNonPathable=true}) then
|
||||
storage.stopSearch = true
|
||||
delay(100)
|
||||
end
|
||||
else
|
||||
i = i + 1
|
||||
goto findEmptyDP
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if tileList[i].tileObj and not table.find(depotIDs, tileList[i].tileObj:getTopLookThing():getId()) and comparePosition(pos(), tileList[i].tileObj:getPosition()) then
|
||||
for j=1,table.getn(tileList[i].tileObj:getThings()),1 do
|
||||
if not tileList[i].tileObj:getThings()[j]:isNotMoveable() then
|
||||
delay(500)
|
||||
g_game.move(tileList[i].tileObj:getThings()[j], pos(), tileList[i].tileObj:getThings()[j]:getCount())
|
||||
end
|
||||
end
|
||||
if table.find(depotIDs, tileList[i].tileObj:getTopLookThing():getId()) then
|
||||
depotClear = true
|
||||
end
|
||||
else
|
||||
depotClear = true
|
||||
end
|
||||
if depotClear then
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
if container:getName():lower() == "locker" then
|
||||
depotOpen = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if tileList[i].tileObj and depotClear and not depotOpen and not storage.lootContainerOpen then
|
||||
delay(500)
|
||||
g_game.use(tileList[i].tileObj:getTopUseThing())
|
||||
depotOpen = true
|
||||
end
|
||||
i = 1
|
||||
--Version Check to know what to do with the depot--
|
||||
if g_game.getClientVersion() > 910 then
|
||||
if depotOpen then
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
if container:getName():lower() == "depot chest" then
|
||||
depotBoxOpen = true
|
||||
end
|
||||
end
|
||||
if findItem(3502) and not depotBoxOpen then
|
||||
delay(500)
|
||||
g_game.use(findItem(3502))
|
||||
depotBoxOpen = true
|
||||
end
|
||||
end
|
||||
if depotBoxOpen and not storage.lootContainerOpen then
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
if container:getName():lower() == "depot chest" then
|
||||
for _, item in ipairs(container:getItems()) do
|
||||
if item:isContainer() and table.find({22797, 22798}, item:getId()) then
|
||||
g_game.open(findItem(22797), container)
|
||||
delay(500)
|
||||
for _, cont in pairs(g_game.getContainers()) do
|
||||
if string.find(cont:getName():lower(), "depot box") then
|
||||
storage.lootContainerOpen = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i, container in pairs(g_game.getContainers()) do
|
||||
if string.find(container:getName():lower(), "depot box") then
|
||||
for j, item in ipairs(container:getItems()) do
|
||||
g_game.move(item, destContainer:getSlotPosition(destContainer:getItemsCount()), item:getCount())
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("dpwithdraw", "dpwithdraw", {
|
||||
value="shopping bag, 21411",
|
||||
title="Loot Withdraw",
|
||||
description="insert destination container name and it's ID",
|
||||
})
|
||||
end
|
||||
|
||||
onPlayerPositionChange(function(newPos, oldPos)
|
||||
storage.lootContainerOpen = false
|
||||
storage.stopSearch = false
|
||||
end)
|
@ -0,0 +1,27 @@
|
||||
CaveBot.Extensions.Depositer = {}
|
||||
|
||||
local ui
|
||||
|
||||
-- first function called, here you should setup your UI
|
||||
CaveBot.Extensions.Depositer.setup = function()
|
||||
--ui = UI.createWidget('Label')
|
||||
--ui:setText("Depositer UI")
|
||||
end
|
||||
|
||||
-- called when cavebot config changes, configData is a table but it can be nil
|
||||
CaveBot.Extensions.Depositer.onConfigChange = function(configName, isEnabled, configData)
|
||||
if not configData then return end
|
||||
|
||||
end
|
||||
|
||||
-- called when cavebot is saving config, should return table or nil
|
||||
CaveBot.Extensions.Depositer.onSave = function()
|
||||
return {}
|
||||
end
|
||||
|
||||
-- bellow add you custom functions
|
||||
-- this function can be used in cavebot function waypoint as: return Depositer.run(retries, prev)
|
||||
-- there are 2 useful parameters - retries (number) and prev (true/false), check actions.lua to learn more
|
||||
CaveBot.Extensions.Depositer.run = function(retries, prev)
|
||||
return true
|
||||
end
|
@ -0,0 +1,376 @@
|
||||
CaveBot.Extensions.Depositor = {}
|
||||
|
||||
local depotIDs = {3497, 3498, 3499, 3500}
|
||||
local reset = function()
|
||||
storage.stopSearch = false
|
||||
storage.lootContainerOpen = false
|
||||
storage.containersClosed = false
|
||||
storage.containersReset = false
|
||||
storage.currentStack = 0
|
||||
storage.currentNonStack = nonStackMin
|
||||
storage.lastTry = nil
|
||||
storage.lootItemsCount = 0
|
||||
storage.depositDone = false
|
||||
end
|
||||
local i = 1
|
||||
|
||||
CaveBot.Extensions.Depositor.setup = function()
|
||||
CaveBot.registerAction("depositor", "#00FFFF", function(value, retries)
|
||||
if retries > 400 then
|
||||
print("CaveBot[Depositor]: Depositor actions limit reached, proceeding")
|
||||
reset()
|
||||
return true
|
||||
end
|
||||
|
||||
local name = storage["_configs"]["targetbot_configs"]["selected"]
|
||||
local file = configDir .. "/targetbot_configs/" .. name .. ".json"
|
||||
local data = g_resources.readFileContents(file)
|
||||
local lootList = Config.parse(data)['looting']['items']
|
||||
local lootContainers = Config.parse(data)['looting']['containers']
|
||||
local mainBp
|
||||
local stackBp
|
||||
local nonStackBp
|
||||
|
||||
local valueString = string.split(value, ",") -- if 3 then it's old tibia
|
||||
|
||||
-- if old tibia then setup backpacks
|
||||
if #valueString == 3 then
|
||||
mainBp = tonumber(valueString[1]:trim())
|
||||
stackBp = tonumber(valueString[2]:trim()) -- non-stack bp count
|
||||
nonStackBp = tonumber(valueString[3]:trim()) -- stack bp count
|
||||
|
||||
if not mainBp or not stackBp or not nonStackBp then
|
||||
warn("CaveBot[Depositor]: incorrect values! should be 3x ID of containers!")
|
||||
reset()
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- start with checking the containers
|
||||
local lootDestination = {}
|
||||
for _, container in pairs(lootContainers) do
|
||||
if not table.find(lootDestination, container['id']) then
|
||||
table.insert(lootDestination, container['id'])
|
||||
end
|
||||
end
|
||||
|
||||
-- pretty much every container action is needed only if you want to work with containers
|
||||
if (value:lower() == "yes" or #valueString == 3) and not storage.containersReset then
|
||||
|
||||
-- what is open and what's not
|
||||
local currentContainers = {}
|
||||
for i, container in pairs(getContainers()) do
|
||||
if not table.find(currentContainers, container:getContainerItem():getId()) then
|
||||
table.insert(currentContainers, container:getContainerItem():getId())
|
||||
end
|
||||
end
|
||||
|
||||
delay(500) -- slow down this function until containers reset
|
||||
if #lootDestination > 0 then
|
||||
-- first closing all that are opened
|
||||
if not storage.containersClosed then
|
||||
for i, container in pairs(getContainers()) do
|
||||
if table.find(lootDestination, container:getContainerItem():getId()) then
|
||||
g_game.close(container)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
storage.containersClosed = true
|
||||
end
|
||||
-- now reopen them
|
||||
if not storage.containersReset and storage.containersClosed then
|
||||
for i, container in pairs(getContainers()) do
|
||||
for j, item in pairs(container:getItems()) do
|
||||
if table.find(lootDestination, item:getId()) and not table.find(currentContainers, item:getId()) then
|
||||
g_game.open(item)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
storage.containersReset = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if storage.depositDone then
|
||||
reset()
|
||||
print("CaveBot[Depositor]: Deposit finished, proceeding")
|
||||
return true
|
||||
end
|
||||
|
||||
local tileList = {}
|
||||
local tPos
|
||||
local depotClear = false
|
||||
local depotOpen = false
|
||||
local depotBoxOpen = false
|
||||
for _,tile in pairs(g_map.getTiles(posz())) do
|
||||
for i,thing in pairs(tile:getThings()) do
|
||||
if table.find(depotIDs, thing:getId()) then
|
||||
table.insert(tileList, {tileObj = tile, distance = getDistanceBetween(pos(), tile:getPosition()), depotID = thing:getId()})
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(tileList, function(a,b) return a.distance < b.distance end)
|
||||
::findEmptyDP::
|
||||
if tileList[i] and not storage.stopSearch then
|
||||
if tileList[i].depotID == 3498 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x + 1, y = tileList[i].tileObj:getPosition().y, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3499 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x, y = tileList[i].tileObj:getPosition().y + 1, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3500 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x - 1, y = tileList[i].tileObj:getPosition().y, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3497 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x, y = tileList[i].tileObj:getPosition().y - 1, z = tileList[i].tileObj:getPosition().z}
|
||||
end
|
||||
if tPos then
|
||||
local dest = g_map.getTile(tPos)
|
||||
if not (getDistanceBetween(pos(), dest:getPosition()) <= 1) then
|
||||
if not dest:getCreatures()[1] and dest:isWalkable() then
|
||||
if autoWalk(dest:getPosition(), {ignoreNonPathable=true}) then
|
||||
storage.stopSearch = true
|
||||
delay(100)
|
||||
end
|
||||
else
|
||||
i = i + 1
|
||||
goto findEmptyDP
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if tileList[i] and not table.find(depotIDs, tileList[i].tileObj:getTopLookThing():getId()) and (getDistanceBetween(pos(), tileList[i].tileObj:getPosition()) <= 1) then
|
||||
for j=1,table.getn(tileList[i].tileObj:getThings()),1 do
|
||||
if not tileList[i].tileObj:getThings()[j]:isNotMoveable() then
|
||||
delay(500)
|
||||
g_game.move(tileList[i].tileObj:getThings()[j], pos(), tileList[i].tileObj:getThings()[j]:getCount())
|
||||
end
|
||||
end
|
||||
if table.find(depotIDs, tileList[i].tileObj:getTopLookThing():getId()) then
|
||||
depotClear = true
|
||||
end
|
||||
else
|
||||
depotClear = true
|
||||
end
|
||||
if depotClear then
|
||||
for _, container in pairs(getContainers()) do
|
||||
if container:getName():lower() == "locker" then
|
||||
depotOpen = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if tileList[i] and depotClear and not depotOpen and not storage.lootContainerOpen then
|
||||
delay(500)
|
||||
g_game.use(tileList[i].tileObj:getTopUseThing())
|
||||
depotOpen = true
|
||||
end
|
||||
i = 1
|
||||
|
||||
-- finding depot
|
||||
if depotOpen then
|
||||
for _, container in pairs(getContainers()) do
|
||||
if container:getName():lower() == "depot chest" then
|
||||
depotBoxOpen = true
|
||||
end
|
||||
end
|
||||
if findItem(3502) and not depotBoxOpen then
|
||||
delay(500)
|
||||
g_game.use(findItem(3502))
|
||||
depotBoxOpen = true
|
||||
end
|
||||
end
|
||||
if depotBoxOpen and not storage.lootContainerOpen then
|
||||
for _, container in pairs(getContainers()) do
|
||||
if container:getName():lower() == "depot chest" then
|
||||
for _, item in ipairs(container:getItems()) do
|
||||
if #valueString ~= 3 then -- new depot
|
||||
if item:isContainer() and table.find({22797, 22798}, item:getId()) then
|
||||
delay(500)
|
||||
storage.lootContainerOpen = true
|
||||
break
|
||||
end
|
||||
else
|
||||
if item:isContainer() and item:getId() == mainBp then
|
||||
delay(500)
|
||||
g_game.use(item, container)
|
||||
storage.lootContainerOpen = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #valueString == 3 then
|
||||
delay(150)
|
||||
for _, container in pairs(getContainers()) do
|
||||
if container:getContainerItem():getId() == mainBp then
|
||||
storage.lootContainerOpen = true
|
||||
storage.isDepositing = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local looting = {}
|
||||
for _, lootItem in pairs(lootList) do
|
||||
if not table.find(looting, lootItem['id']) and not table.find({3031, 3035, 3043}, lootItem['id']) then
|
||||
table.insert(looting, lootItem['id'])
|
||||
end
|
||||
end
|
||||
delay(200)
|
||||
local currentItems = 0
|
||||
for _, container in pairs(getContainers()) do
|
||||
for _, item in ipairs(container:getItems()) do
|
||||
if table.find(looting, item:getId()) then
|
||||
currentItems = currentItems + item:getCount()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if currentItems == 0 then
|
||||
if value:lower() ~= "yes" and #valueString ~= 3 then
|
||||
storage.containersClosed = false
|
||||
storage.containersReset = false
|
||||
storage.depositDone = true
|
||||
return "retry"
|
||||
end
|
||||
|
||||
for i, container in pairs(getContainers()) do
|
||||
for j, item in pairs(container:getItems()) do
|
||||
if table.find(lootDestination, container:getContainerItem():getId()) and table.find(lootDestination, item:getId()) then
|
||||
g_game.open(item, container)
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
storage.containersClosed = false
|
||||
storage.containersReset = false
|
||||
storage.depositDone = true
|
||||
return "retry"
|
||||
end
|
||||
|
||||
-- only if old depot
|
||||
local stackMin
|
||||
local stackMax
|
||||
local nonStackMin
|
||||
local nonStackMax
|
||||
if #valueString == 3 then
|
||||
-- backpacks setup
|
||||
local stack = 0
|
||||
local nonStack = 0
|
||||
for i, container in pairs(getContainers()) do
|
||||
if container:getContainerItem():getId() == mainBp then
|
||||
for i, item in pairs(container:getItems()) do
|
||||
if item:getId() == stackBp then
|
||||
stack = stack + 1
|
||||
elseif item:getId() == nonStackBp then
|
||||
nonStack = nonStack + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
stackMax = stack - 1
|
||||
nonStackMin = stack
|
||||
nonStackMax = (stack + nonStack) - 1
|
||||
|
||||
storage.currentStack = 0
|
||||
storage.currentNonStack = nonStackMin
|
||||
|
||||
if storage.lootItemsCount == currentItems then
|
||||
if storage.lastTry == 1 then
|
||||
if storage.currentStack < stackMax then
|
||||
storage.currentStack = storage.currentStack + 1
|
||||
else
|
||||
warn("CaveBot[Depositer]: Stack Backpack full! Proceeding.")
|
||||
reset()
|
||||
return true
|
||||
end
|
||||
elseif storage.lastTry == 2 then
|
||||
if storage.currentNonStack < nonStackMax then
|
||||
storage.currentNonStack = storage.currentNonStack + 1
|
||||
else
|
||||
warn("CaveBot[Depositer]: Non-Stack Backpack full! Proceeding.")
|
||||
reset()
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
storage.lootItemsCount = currentItems
|
||||
end
|
||||
|
||||
if #looting > 0 then
|
||||
if #valueString ~= 3 then -- version check, if value is set of 3 i
|
||||
for i, depotcontainer in pairs(getContainers()) do
|
||||
containerItemId = depotcontainer:getContainerItem():getId()
|
||||
--check if open depot
|
||||
if containerItemId == 3502 then
|
||||
-- check all containers and items
|
||||
for l, lootcontainer in pairs(getContainers()) do
|
||||
for j, item in ipairs(lootcontainer:getItems()) do
|
||||
-- now the criteria
|
||||
if table.find(looting, item:getId()) then
|
||||
-- move the item
|
||||
if item:isStackable() then
|
||||
g_game.move(item, depotcontainer:getSlotPosition(1), item:getCount())
|
||||
return "retry"
|
||||
else
|
||||
g_game.move(item, depotcontainer:getSlotPosition(0), item:getCount())
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else -- to be written, last part missing is stashing items for old depots
|
||||
for i, depotcontainer in pairs(getContainers()) do
|
||||
containerItemId = depotcontainer:getContainerItem():getId()
|
||||
--check if open depot
|
||||
if containerItemId == mainBp then
|
||||
-- check all containers and items
|
||||
for l, lootcontainer in pairs(getContainers()) do
|
||||
for j, item in ipairs(lootcontainer:getItems()) do
|
||||
-- now the criteria
|
||||
if table.find(looting, item:getId()) then
|
||||
-- move the item
|
||||
if item:isStackable() then
|
||||
g_game.move(item, depotcontainer:getSlotPosition(storage.currentStack), item:getCount())
|
||||
storage.lastTry = 1
|
||||
return "retry"
|
||||
else
|
||||
g_game.move(item, depotcontainer:getSlotPosition(storage.currentNonStack), item:getCount())
|
||||
storage.lastTry = 2
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
else
|
||||
warn("no items in looting list!")
|
||||
reset()
|
||||
return false
|
||||
end
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("depositor", "depositor", {
|
||||
value="no",
|
||||
title="Depositor",
|
||||
description="No - just deposit \n Yes - also reopen loot containers \n mainID, stackId, nonStackId - for older tibia",
|
||||
})
|
||||
end
|
||||
|
||||
onPlayerPositionChange(function(newPos, oldPos)
|
||||
if CaveBot.isOn() then
|
||||
reset()
|
||||
end
|
||||
end)
|
@ -0,0 +1,47 @@
|
||||
CaveBot.Extensions.OpenDoors = {}
|
||||
|
||||
CaveBot.Extensions.OpenDoors.setup = function()
|
||||
CaveBot.registerAction("OpenDoors", "#00FFFF", function(value, retries)
|
||||
local pos = regexMatch(value, "\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)")
|
||||
if not pos[1] then
|
||||
error("CaveBot[OpenDoors]: invalid value. It should be position (x,y,z), is: " .. value)
|
||||
return false
|
||||
end
|
||||
|
||||
if retries >= 5 then
|
||||
print("CaveBot[OpenDoors]: too many tries, can't open doors")
|
||||
return false -- tried 5 times, can't open
|
||||
end
|
||||
|
||||
pos = {x=tonumber(pos[1][2]), y=tonumber(pos[1][3]), z=tonumber(pos[1][4])}
|
||||
|
||||
local doorTile
|
||||
if not doorTile then
|
||||
for i, tile in ipairs(g_map.getTiles(posz())) do
|
||||
if tile:getPosition().x == pos.x and tile:getPosition().y == pos.y and tile:getPosition().z == pos.z then
|
||||
doorTile = tile
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not doorTile then
|
||||
return false
|
||||
end
|
||||
|
||||
if not doorTile:isWalkable() then
|
||||
use(doorTile:getTopUseThing())
|
||||
return "retry"
|
||||
else
|
||||
print("CaveBot[OpenDoors]: possible to cross, proceeding")
|
||||
return true
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("opendoors", "open doors", {
|
||||
value=function() return posx() .. "," .. posy() .. "," .. posz() end,
|
||||
title="Door position",
|
||||
description="doors position (x,y,z)",
|
||||
multiline=false,
|
||||
validation="^\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)$"
|
||||
})
|
||||
end
|
174
modules/game_bot/default_configs/vithrax_1.1/cavebot/editor.lua
Normal file
174
modules/game_bot/default_configs/vithrax_1.1/cavebot/editor.lua
Normal file
@ -0,0 +1,174 @@
|
||||
CaveBot.Editor = {}
|
||||
CaveBot.Editor.Actions = {}
|
||||
|
||||
-- also works as registerAction(action, params), then text == action
|
||||
-- params are options for text editor or function to be executed when clicked
|
||||
-- you have many examples how to use it bellow
|
||||
CaveBot.Editor.registerAction = function(action, text, params)
|
||||
if type(text) ~= 'string' then
|
||||
params = text
|
||||
text = action
|
||||
end
|
||||
|
||||
local color = nil
|
||||
if type(params) ~= 'function' then
|
||||
local raction = CaveBot.Actions[action]
|
||||
if not raction then
|
||||
return error("CaveBot editor error: action " .. action .. " doesn't exist")
|
||||
end
|
||||
CaveBot.Editor.Actions[action] = params
|
||||
color = raction.color
|
||||
end
|
||||
|
||||
local button = UI.createWidget('CaveBotEditorButton', CaveBot.Editor.ui.buttons)
|
||||
button:setText(text)
|
||||
if color then
|
||||
button:setColor(color)
|
||||
end
|
||||
button.onClick = function()
|
||||
if type(params) == 'function' then
|
||||
params()
|
||||
return
|
||||
end
|
||||
CaveBot.Editor.edit(action, nil, function(action, value)
|
||||
local focusedAction = CaveBot.actionList:getFocusedChild()
|
||||
local index = CaveBot.actionList:getChildCount()
|
||||
if focusedAction then
|
||||
index = CaveBot.actionList:getChildIndex(focusedAction)
|
||||
end
|
||||
local widget = CaveBot.addAction(action, value)
|
||||
CaveBot.actionList:moveChildToIndex(widget, index + 1)
|
||||
CaveBot.actionList:focusChild(widget)
|
||||
CaveBot.save()
|
||||
end)
|
||||
end
|
||||
return button
|
||||
end
|
||||
|
||||
CaveBot.Editor.setup = function()
|
||||
CaveBot.Editor.ui = UI.createWidget("CaveBotEditorPanel")
|
||||
local ui = CaveBot.Editor.ui
|
||||
local registerAction = CaveBot.Editor.registerAction
|
||||
|
||||
registerAction("move up", function()
|
||||
local action = CaveBot.actionList:getFocusedChild()
|
||||
if not action then return end
|
||||
local index = CaveBot.actionList:getChildIndex(action)
|
||||
if index < 2 then return end
|
||||
CaveBot.actionList:moveChildToIndex(action, index - 1)
|
||||
CaveBot.actionList:ensureChildVisible(action)
|
||||
CaveBot.save()
|
||||
end)
|
||||
registerAction("edit", function()
|
||||
local action = CaveBot.actionList:getFocusedChild()
|
||||
if not action or not action.onDoubleClick then return end
|
||||
action.onDoubleClick(action)
|
||||
end)
|
||||
registerAction("move down", function()
|
||||
local action = CaveBot.actionList:getFocusedChild()
|
||||
if not action then return end
|
||||
local index = CaveBot.actionList:getChildIndex(action)
|
||||
if index >= CaveBot.actionList:getChildCount() then return end
|
||||
CaveBot.actionList:moveChildToIndex(action, index + 1)
|
||||
CaveBot.actionList:ensureChildVisible(action)
|
||||
CaveBot.save()
|
||||
end)
|
||||
registerAction("remove", function()
|
||||
local action = CaveBot.actionList:getFocusedChild()
|
||||
if not action then return end
|
||||
action:destroy()
|
||||
CaveBot.save()
|
||||
end)
|
||||
|
||||
registerAction("label", {
|
||||
value="labelName",
|
||||
title="Label",
|
||||
description="Add label",
|
||||
multiline=false
|
||||
})
|
||||
registerAction("delay", {
|
||||
value="500",
|
||||
title="Delay",
|
||||
description="Delay next action (in milliseconds)",
|
||||
multiline=false,
|
||||
validation="^\\s*[0-9]{1,10}\\s*$"
|
||||
})
|
||||
registerAction("gotolabel", "go to label", {
|
||||
value="labelName",
|
||||
title="Go to label",
|
||||
description="Go to label",
|
||||
multiline=false
|
||||
})
|
||||
registerAction("goto", "go to", {
|
||||
value=function() return posx() .. "," .. posy() .. "," .. posz() end,
|
||||
title="Go to position",
|
||||
description="Go to position (x,y,z)",
|
||||
multiline=false,
|
||||
validation="^\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+),?\\s*([0-9]?)$"
|
||||
})
|
||||
registerAction("use", {
|
||||
value=function() return posx() .. "," .. posy() .. "," .. posz() end,
|
||||
title="Use",
|
||||
description="Use item from position (x,y,z) or from inventory (itemId)",
|
||||
multiline=false
|
||||
})
|
||||
registerAction("usewith", "use with", {
|
||||
value=function() return "itemId," .. posx() .. "," .. posy() .. "," .. posz() end,
|
||||
title="Use with",
|
||||
description="Use item at position (itemid,x,y,z)",
|
||||
multiline=false,
|
||||
validation="^\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)$"
|
||||
})
|
||||
registerAction("say", {
|
||||
value="text",
|
||||
title="Say",
|
||||
description="Enter text to say",
|
||||
multiline=false
|
||||
})
|
||||
registerAction("function", {
|
||||
title="Edit bot function",
|
||||
multiline=true,
|
||||
value=CaveBot.Editor.ExampleFunctions[1][2],
|
||||
examples=CaveBot.Editor.ExampleFunctions,
|
||||
width=650
|
||||
})
|
||||
|
||||
ui.autoRecording.onClick = function()
|
||||
if ui.autoRecording:isOn() then
|
||||
CaveBot.Recorder.disable()
|
||||
else
|
||||
CaveBot.Recorder.enable()
|
||||
end
|
||||
end
|
||||
|
||||
-- callbacks
|
||||
onPlayerPositionChange(function(pos)
|
||||
ui.pos:setText("Position: " .. pos.x .. ", " .. pos.y .. ", " .. pos.z)
|
||||
end)
|
||||
ui.pos:setText("Position: " .. posx() .. ", " .. posy() .. ", " .. posz())
|
||||
end
|
||||
|
||||
CaveBot.Editor.show = function()
|
||||
CaveBot.Editor.ui:show()
|
||||
end
|
||||
|
||||
|
||||
CaveBot.Editor.hide = function()
|
||||
CaveBot.Editor.ui:hide()
|
||||
end
|
||||
|
||||
CaveBot.Editor.edit = function(action, value, callback) -- callback = function(action, value)
|
||||
local params = CaveBot.Editor.Actions[action]
|
||||
if not params then return end
|
||||
if not value then
|
||||
if type(params.value) == 'function' then
|
||||
value = params.value()
|
||||
elseif type(params.value) == 'string' then
|
||||
value = params.value
|
||||
end
|
||||
end
|
||||
|
||||
UI.EditorWindow(value, params, function(newText)
|
||||
callback(action, newText)
|
||||
end)
|
||||
end
|
@ -0,0 +1,44 @@
|
||||
CaveBotEditorButton < Button
|
||||
|
||||
|
||||
CaveBotEditorPanel < Panel
|
||||
id: cavebotEditor
|
||||
visible: false
|
||||
layout:
|
||||
type: verticalBox
|
||||
fit-children: true
|
||||
|
||||
Label
|
||||
id: pos
|
||||
text-align: center
|
||||
text: -
|
||||
|
||||
Panel
|
||||
id: buttons
|
||||
margin-top: 2
|
||||
layout:
|
||||
type: grid
|
||||
cell-size: 86 20
|
||||
cell-spacing: 1
|
||||
flow: true
|
||||
fit-children: true
|
||||
|
||||
Label
|
||||
text: Double click on action from action list to edit it
|
||||
text-align: center
|
||||
text-auto-resize: true
|
||||
text-wrap: true
|
||||
margin-top: 3
|
||||
margin-left: 2
|
||||
margin-right: 2
|
||||
|
||||
BotSwitch
|
||||
id: autoRecording
|
||||
text: Auto Recording
|
||||
margin-top: 3
|
||||
|
||||
BotButton
|
||||
margin-top: 3
|
||||
margin-bottom: 3
|
||||
text: Documentation
|
||||
@onClick: g_platform.openUrl("http://bot.otclient.ovh/")
|
@ -0,0 +1,90 @@
|
||||
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("buy 200 mana potion from npc Eryn", [[
|
||||
--buy 200 mana potions
|
||||
local npc = getCreatureByName("Eryn")
|
||||
if not npc then
|
||||
return false
|
||||
end
|
||||
if retries > 10 then
|
||||
return false
|
||||
end
|
||||
local pos = player:getPosition()
|
||||
local npcPos = npc:getPosition()
|
||||
if math.max(math.abs(pos.x - npcPos.x), math.abs(pos.y - npcPos.y)) > 3 then
|
||||
autoWalk(npcPos, {precision=3})
|
||||
delay(300)
|
||||
return "retry"
|
||||
end
|
||||
if not NPC.isTrading() then
|
||||
NPC.say("hi")
|
||||
NPC.say("trade")
|
||||
delay(200)
|
||||
return "retry"
|
||||
end
|
||||
NPC.buy(268, 100)
|
||||
schedule(1000, function()
|
||||
-- buy again in 1s
|
||||
NPC.buy(268, 100)
|
||||
NPC.closeTrade()
|
||||
NPC.say("bye")
|
||||
end)
|
||||
delay(1200)
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Say hello 5 times with some delay", [[
|
||||
--say hello
|
||||
if retries > 5 then
|
||||
return true -- finish
|
||||
end
|
||||
say("hello")
|
||||
delay(100 + retries * 100)
|
||||
return "retry"
|
||||
]])
|
||||
|
||||
addExampleFunction("Disable TargetBot", [[
|
||||
TargetBot.setOff()
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Enable TargetBot", [[
|
||||
TargetBot.setOn()
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Enable TargetBot luring", [[
|
||||
TargetBot.enableLuring()
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Disable TargetBot luring", [[
|
||||
TargetBot.disableLuring()
|
||||
return true
|
||||
]])
|
||||
|
||||
addExampleFunction("Logout", [[
|
||||
g_game.safeLogout()
|
||||
delay(1000)
|
||||
return "retry"
|
||||
]])
|
@ -0,0 +1,58 @@
|
||||
-- example cavebot extension (remember to add this file to ../cavebot.lua)
|
||||
CaveBot.Extensions.Example = {}
|
||||
|
||||
local ui
|
||||
|
||||
-- setup is called automaticly when cavebot is ready
|
||||
CaveBot.Extensions.Example.setup = function()
|
||||
ui = UI.createWidget('BotTextEdit')
|
||||
ui:setText("Hello")
|
||||
ui.onTextChange = function()
|
||||
CaveBot.save() -- save new config when you change something
|
||||
end
|
||||
|
||||
-- add custom cavebot action (check out actions.lua)
|
||||
CaveBot.registerAction("sayhello", "orange", function(value, retries, prev)
|
||||
local how_many_times = tonumber(value)
|
||||
if retries >= how_many_times then
|
||||
return true
|
||||
end
|
||||
say("hello " .. (retries + 1))
|
||||
delay(250)
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
-- add this custom action to editor (check out editor.lua)
|
||||
CaveBot.Editor.registerAction("sayhello", "say hello", {
|
||||
value="5",
|
||||
title="Say hello",
|
||||
description="Says hello x times",
|
||||
validation="[0-9]{1,5}" -- regex, optional
|
||||
})
|
||||
end
|
||||
|
||||
-- called when cavebot config changes, configData is a table but it can also be nil
|
||||
CaveBot.Extensions.Example.onConfigChange = function(configName, isEnabled, configData)
|
||||
if not configData then return end
|
||||
if configData["text"] then
|
||||
ui:setText(configData["text"])
|
||||
end
|
||||
end
|
||||
|
||||
-- called when cavebot is saving config (so when CaveBot.save() is called), should return table or nil
|
||||
CaveBot.Extensions.Example.onSave = function()
|
||||
return {text=ui:getText()}
|
||||
end
|
||||
|
||||
-- bellow add you custom functions to be used in cavebot function action
|
||||
-- an example: return Example.run(retries, prev)
|
||||
-- there are 2 useful parameters - retries (number) and prev (true/false), check actions.lua and example_functions.lua to learn more
|
||||
CaveBot.Extensions.Example.run = function(retries, prev)
|
||||
-- it will say text 10 times with some delay and then continue
|
||||
if retries > 10 then
|
||||
return true
|
||||
end
|
||||
say(ui:getText() .. " x" .. retries)
|
||||
delay(100 + retries * 100)
|
||||
return "retry"
|
||||
end
|
@ -0,0 +1,184 @@
|
||||
CaveBot.Extensions.InWithdraw = {}
|
||||
|
||||
comparePosition = function(pPos, tPos)
|
||||
return (getDistanceBetween(pPos, tPos) <= 1)
|
||||
end
|
||||
|
||||
local depotIDs = {3497, 3498, 3499, 3500}
|
||||
storage.stopSearch = false
|
||||
storage.inboxContainerOpen = false
|
||||
local i = 1
|
||||
|
||||
|
||||
CaveBot.Extensions.InWithdraw.setup = function()
|
||||
CaveBot.registerAction("inwithdraw", "#00FFFF", function(value, retries)
|
||||
local data = string.split(value, ",")
|
||||
local withdrawId
|
||||
local count
|
||||
local itemCount = 0
|
||||
local depotAmount = 0
|
||||
if #data ~= 2 then
|
||||
error("CaveBot[InboxWithdraw]: incorrect withdraw value")
|
||||
return false
|
||||
else
|
||||
withdrawId = tonumber(data[1])
|
||||
count = tonumber(data[2])
|
||||
end
|
||||
|
||||
for i, container in pairs(getContainers()) do
|
||||
if not string.find(container:getName():lower(), "inbox") then
|
||||
for j, item in pairs(container:getItems()) do
|
||||
if item:getId() == withdrawId then
|
||||
itemCount = itemCount + item:getCount()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if itemCount >= count then
|
||||
for i, container in pairs(getContainers()) do
|
||||
if string.find(container:getName():lower(), "your inbox") then
|
||||
g_game.close(container)
|
||||
end
|
||||
end
|
||||
print("CaveBot[InboxWithdraw]: enough items, proceeding")
|
||||
return true
|
||||
end
|
||||
|
||||
if retries > 400 then
|
||||
print("CaveBot[InboxWithdraw]: actions limit reached, proceeding")
|
||||
return true
|
||||
end
|
||||
|
||||
delay(200)
|
||||
local tileList = {}
|
||||
local tPos
|
||||
local depotClear = false
|
||||
local depotOpen = false
|
||||
local depotBoxOpen = false
|
||||
for _,tile in pairs(g_map.getTiles(posz())) do
|
||||
for i,thing in pairs(tile:getThings()) do
|
||||
if table.find(depotIDs, thing:getId()) then
|
||||
table.insert(tileList, {tileObj = tile, distance = getDistanceBetween(pos(), tile:getPosition()), depotID = thing:getId()})
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(tileList, function(a,b) return a.distance < b.distance end)
|
||||
::findEmptyDP::
|
||||
if tileList[i] and not storage.stopSearch then
|
||||
if tileList[i].depotID == 3498 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x + 1, y = tileList[i].tileObj:getPosition().y, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3499 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x, y = tileList[i].tileObj:getPosition().y + 1, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3500 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x - 1, y = tileList[i].tileObj:getPosition().y, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3497 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x, y = tileList[i].tileObj:getPosition().y - 1, z = tileList[i].tileObj:getPosition().z}
|
||||
end
|
||||
if tPos then
|
||||
local dest = g_map.getTile(tPos)
|
||||
if not comparePosition(pos(), dest:getPosition()) then
|
||||
if not dest:getCreatures()[1] and dest:isWalkable() then
|
||||
if autoWalk(dest:getPosition(), {ignoreNonPathable=true}) then
|
||||
storage.stopSearch = true
|
||||
delay(100)
|
||||
end
|
||||
else
|
||||
i = i + 1
|
||||
goto findEmptyDP
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if tileList[i].tileObj and not table.find(depotIDs, tileList[i].tileObj:getTopLookThing():getId()) and comparePosition(pos(), tileList[i].tileObj:getPosition()) then
|
||||
for j=1,table.getn(tileList[i].tileObj:getThings()),1 do
|
||||
if not tileList[i].tileObj:getThings()[j]:isNotMoveable() then
|
||||
delay(500)
|
||||
g_game.move(tileList[i].tileObj:getThings()[j], pos(), tileList[i].tileObj:getThings()[j]:getCount())
|
||||
end
|
||||
end
|
||||
if table.find(depotIDs, tileList[i].tileObj:getTopLookThing():getId()) then
|
||||
depotClear = true
|
||||
end
|
||||
else
|
||||
depotClear = true
|
||||
end
|
||||
if depotClear then
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
if container:getName():lower() == "locker" then
|
||||
depotOpen = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if tileList[i].tileObj and depotClear and not depotOpen and not storage.inboxContainerOpen then
|
||||
delay(500)
|
||||
g_game.use(tileList[i].tileObj:getTopUseThing())
|
||||
depotOpen = true
|
||||
end
|
||||
i = 1
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
if container:getName():lower() == "your inbox" then
|
||||
depotBoxOpen = true
|
||||
end
|
||||
end
|
||||
if depotOpen and not depotBoxOpen then
|
||||
if findItem(12902) then
|
||||
delay(500)
|
||||
g_game.use(findItem(12902))
|
||||
depotBoxOpen = true
|
||||
end
|
||||
end
|
||||
|
||||
if depotBoxOpen and not storage.inboxContainerOpen then
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
if container:getName():lower() == "your" then
|
||||
storage.inboxContainerOpen = true
|
||||
end
|
||||
end
|
||||
end
|
||||
delay(500)
|
||||
for i, container in pairs(getContainers()) do
|
||||
if string.find(container:getName():lower(), "your") then
|
||||
for j, item in pairs(container:getItems()) do
|
||||
if item:getId() == withdrawId then
|
||||
depotAmount = depotAmount + item:getCount()
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local destination
|
||||
for i, container in pairs(getContainers()) do
|
||||
if container:getCapacity() > container:getSize() and not string.find(container:getName():lower(), "depot") and not string.find(container:getName():lower(), "loot") and not string.find(container:getName():lower(), "inbox") then
|
||||
destination = container
|
||||
end
|
||||
end
|
||||
|
||||
if itemCount < count and destination then
|
||||
for i, container in pairs(getContainers()) do
|
||||
if string.find(container:getName():lower(), "your inbox") then
|
||||
for j, item in pairs(container:getItems()) do
|
||||
if item:getId() == withdrawId then
|
||||
if item:isStackable() then
|
||||
g_game.move(item, destination:getSlotPosition(destination:getItemsCount()), math.min(item:getCount(), (count - itemCount)))
|
||||
return "retry"
|
||||
else
|
||||
g_game.move(item, destination:getSlotPosition(destination:getItemsCount()), 1)
|
||||
return "retry"
|
||||
end
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("inwithdraw", "in withdraw", {
|
||||
value="id,amount",
|
||||
title="Withdraw Items",
|
||||
description="insert item id and amount",
|
||||
})
|
||||
end
|
@ -0,0 +1,23 @@
|
||||
CaveBot.Extensions.Lure = {}
|
||||
|
||||
CaveBot.Extensions.Lure.setup = function()
|
||||
CaveBot.registerAction("lure", "#00FFFF", function(value, retries)
|
||||
if value == "start" then
|
||||
TargetBot.enableLuring()
|
||||
return true
|
||||
elseif value == "stop" then
|
||||
TargetBot.disableLuring()
|
||||
return true
|
||||
else
|
||||
warn("incorrect lure value!")
|
||||
return false
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("lure", "lure", {
|
||||
value="start",
|
||||
title="Lure",
|
||||
description="start/stop",
|
||||
multiline=false,
|
||||
})
|
||||
end
|
@ -0,0 +1,44 @@
|
||||
CaveBot.Extensions.PosCheck = {}
|
||||
|
||||
|
||||
storage.posCheckRetries = 0
|
||||
CaveBot.Extensions.PosCheck.setup = function()
|
||||
CaveBot.registerAction("PosCheck", "#00FFFF", function(value, retries)
|
||||
local tilePos
|
||||
local data = string.split(value, ",")
|
||||
if #data ~= 5 then
|
||||
error("wrong travel format, should be: label, distance, x, y, z")
|
||||
return false
|
||||
end
|
||||
|
||||
local tilePos = player:getPosition()
|
||||
|
||||
tilePos.x = tonumber(data[3])
|
||||
tilePos.y = tonumber(data[4])
|
||||
tilePos.z = tonumber(data[5])
|
||||
|
||||
if storage.posCheckRetries > 10 then
|
||||
storage.posCheckRetries = 0
|
||||
print("CaveBot[CheckPos]: waypoints locked, too many tries, unclogging cavebot and proceeding")
|
||||
return false
|
||||
elseif (tilePos.z == player:getPosition().z) and (getDistanceBetween(player:getPosition(), tilePos) <= tonumber(data[2])) then
|
||||
storage.posCheckRetries = 0
|
||||
print("CaveBot[CheckPos]: position reached, proceeding")
|
||||
return true
|
||||
else
|
||||
storage.posCheckRetries = storage.posCheckRetries + 1
|
||||
CaveBot.gotoLabel(data[1])
|
||||
print("CaveBot[CheckPos]: position not-reached, going back to label: " .. data[1])
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("poscheck", "pos check", {
|
||||
value=function() return "label" .. "," .. "distance" .. "," .. posx() .. "," .. posy() .. "," .. posz() end,
|
||||
title="Location Check",
|
||||
description="label name, accepted dist from coordinates, x, y, z",
|
||||
multiline=false,
|
||||
})
|
||||
end
|
@ -0,0 +1,65 @@
|
||||
-- auto recording for cavebot
|
||||
CaveBot.Recorder = {}
|
||||
|
||||
local isEnabled = nil
|
||||
local lastPos = nil
|
||||
|
||||
local function setup()
|
||||
local function addPosition(pos)
|
||||
CaveBot.addAction("goto", pos.x .. "," .. pos.y .. "," .. pos.z, true)
|
||||
lastPos = pos
|
||||
end
|
||||
|
||||
onPlayerPositionChange(function(newPos, oldPos)
|
||||
if CaveBot.isOn() or not isEnabled then return end
|
||||
if not lastPos then
|
||||
-- first step
|
||||
addPosition(oldPos)
|
||||
elseif newPos.z ~= oldPos.z or math.abs(oldPos.x - newPos.x) > 1 or math.abs(oldPos.y - newPos.y) > 1 then
|
||||
-- stairs/teleport
|
||||
addPosition(oldPos)
|
||||
elseif math.max(math.abs(lastPos.x - newPos.x), math.abs(lastPos.y - newPos.y)) > 5 then
|
||||
-- 5 steps from last pos
|
||||
addPosition(newPos)
|
||||
end
|
||||
end)
|
||||
|
||||
onUse(function(pos, itemId, stackPos, subType)
|
||||
if CaveBot.isOn() or not isEnabled then return end
|
||||
if pos.x ~= 0xFFFF then
|
||||
lastPos = pos
|
||||
CaveBot.addAction("use", pos.x .. "," .. pos.y .. "," .. pos.z, true)
|
||||
end
|
||||
end)
|
||||
|
||||
onUseWith(function(pos, itemId, target, subType)
|
||||
if CaveBot.isOn() or not isEnabled then return end
|
||||
if not target:isItem() then return end
|
||||
local targetPos = target:getPosition()
|
||||
if targetPos.x == 0xFFFF then return end
|
||||
lastPos = pos
|
||||
CaveBot.addAction("usewith", itemId .. "," .. targetPos.x .. "," .. targetPos.y .. "," .. targetPos.z, true)
|
||||
end)
|
||||
end
|
||||
|
||||
CaveBot.Recorder.isOn = function()
|
||||
return isEnabled
|
||||
end
|
||||
|
||||
CaveBot.Recorder.enable = function()
|
||||
CaveBot.setOff()
|
||||
if isEnabled == nil then
|
||||
setup()
|
||||
end
|
||||
CaveBot.Editor.ui.autoRecording:setOn(true)
|
||||
isEnabled = true
|
||||
lastPos = nil
|
||||
end
|
||||
|
||||
CaveBot.Recorder.disable = function()
|
||||
if isEnabled == true then
|
||||
isEnabled = false
|
||||
end
|
||||
CaveBot.Editor.ui.autoRecording:setOn(false)
|
||||
CaveBot.save()
|
||||
end
|
@ -0,0 +1,68 @@
|
||||
CaveBot.Extensions.SellAll = {}
|
||||
|
||||
storage.sellAllCap = 0
|
||||
CaveBot.Extensions.SellAll.setup = function()
|
||||
CaveBot.registerAction("SellAll", "#00FFFF", function(value, retries)
|
||||
local val = string.split(value, ",")
|
||||
local wait
|
||||
if #val > 2 then
|
||||
warn("CaveBot[SellAll]: incorrect sell all value!")
|
||||
return false
|
||||
end
|
||||
|
||||
if #val == 2 then
|
||||
wait = true
|
||||
else
|
||||
wait = false
|
||||
end
|
||||
|
||||
local npc = getCreatureByName(value)
|
||||
if not npc then
|
||||
print("CaveBot[SellAll]: NPC not found! skipping")
|
||||
return false
|
||||
end
|
||||
|
||||
if retries > 10 then
|
||||
print("CaveBot[SellAll]: can't sell, skipping")
|
||||
return false
|
||||
end
|
||||
|
||||
if freecap() == storage.sellAllCap then
|
||||
storage.sellAllCap = 0
|
||||
print("CaveBot[SellAll]: Sold everything, proceeding")
|
||||
return true
|
||||
end
|
||||
|
||||
delay(800)
|
||||
|
||||
local pos = player:getPosition()
|
||||
local npcPos = npc:getPosition()
|
||||
if math.max(math.abs(pos.x - npcPos.x), math.abs(pos.y - npcPos.y)) > 3 then
|
||||
autoWalk(npcPos, 20, {ignoreNonPathable = true, precision=3})
|
||||
delay(300)
|
||||
return "retry"
|
||||
end
|
||||
|
||||
if not NPC.isTrading() then
|
||||
NPC.say("hi")
|
||||
schedule(500, function() NPC.say("trade") end)
|
||||
else
|
||||
storage.sellAllCap = freecap()
|
||||
end
|
||||
|
||||
NPC.sellAll(wait)
|
||||
if #val == 2 then
|
||||
print("CaveBot[SellAll]: Sold All with delay")
|
||||
else
|
||||
print("CaveBot[SellAll]: Sold All without delay")
|
||||
end
|
||||
|
||||
return "retry"
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("sellall", "sell all", {
|
||||
value="NPC",
|
||||
title="Sell All",
|
||||
description="Insert NPC name, and 'yes' if sell with delay ",
|
||||
})
|
||||
end
|
@ -0,0 +1,30 @@
|
||||
CaveBot.Extensions.Supply = {}
|
||||
|
||||
local ui
|
||||
|
||||
-- first function called, here you should setup your UI
|
||||
CaveBot.Extensions.Supply.setup = function()
|
||||
--ui = UI.createWidget('SupplyItemList')
|
||||
--local widget = UI.createWidget('SupplyItem', ui.list)
|
||||
--widget.item.onItemChange = function(newItem)
|
||||
--widget.fields.min.onTextChange = function(newText)
|
||||
-- make it similar to UI.Container, so if there are no free slots, add another one, keep min 4 slots, check if value min/max is number after edit
|
||||
end
|
||||
|
||||
-- called when cavebot config changes, configData is a table but it can be nil
|
||||
CaveBot.Extensions.Supply.onConfigChange = function(configName, isEnabled, configData)
|
||||
if not configData then return end
|
||||
|
||||
end
|
||||
|
||||
-- called when cavebot is saving config, should return table or nil
|
||||
CaveBot.Extensions.Supply.onSave = function()
|
||||
return {}
|
||||
end
|
||||
|
||||
-- bellow add you custom functions
|
||||
-- this function can be used in cavebot function waypoint as: return Supply.run(retries, prev)
|
||||
-- there are 2 useful parameters - retries (number) and prev (true/false), check actions.lua to learn more
|
||||
CaveBot.Extensions.Supply.run = function(retries, prev)
|
||||
return true
|
||||
end
|
@ -0,0 +1,72 @@
|
||||
SupplyItem < Panel
|
||||
height: 34
|
||||
|
||||
BotItem
|
||||
id: item
|
||||
size: 32 32
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
margin-top: 1
|
||||
|
||||
Panel
|
||||
id: fields
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-left: 2
|
||||
margin-right: 2
|
||||
|
||||
Label
|
||||
id: minLabel
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
margin-right: 2
|
||||
text-align: center
|
||||
text: "Min"
|
||||
|
||||
Label
|
||||
id: maxLabel
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.right: parent.right
|
||||
margin-left: 2
|
||||
text-align: center
|
||||
text: "Max"
|
||||
|
||||
BotTextEdit
|
||||
id: min
|
||||
anchors.top: minLabel.bottom
|
||||
anchors.left: minLabel.left
|
||||
anchors.right: minLabel.right
|
||||
text-align: center
|
||||
text: 1
|
||||
|
||||
BotTextEdit
|
||||
id: max
|
||||
anchors.top: maxLabel.bottom
|
||||
anchors.left: maxLabel.left
|
||||
anchors.right: maxLabel.right
|
||||
text-align: center
|
||||
text: 100
|
||||
|
||||
SupplyItemList < Panel
|
||||
height: 102
|
||||
|
||||
ScrollablePanel
|
||||
id: list
|
||||
anchors.fill: parent
|
||||
vertical-scrollbar: scroll
|
||||
margin-right: 7
|
||||
layout:
|
||||
type: verticalBox
|
||||
cell-height: 34
|
||||
|
||||
BotSmallScrollBar
|
||||
id: scroll
|
||||
anchors.top: prev.top
|
||||
anchors.bottom: prev.bottom
|
||||
anchors.right: parent.right
|
||||
step: 10
|
||||
pixels-scroll: true
|
@ -0,0 +1,65 @@
|
||||
CaveBot.Extensions.SupplyCheck = {}
|
||||
|
||||
storage.supplyRetries = 0
|
||||
CaveBot.Extensions.SupplyCheck.setup = function()
|
||||
CaveBot.registerAction("supplyCheck", "#00FFFF", function(value)
|
||||
local softCount = itemAmount(6529) + itemAmount(3549)
|
||||
local totalItem1 = itemAmount(storage[suppliesPanelName].item1)
|
||||
local totalItem2 = itemAmount(storage[suppliesPanelName].item2)
|
||||
local totalItem3 = itemAmount(storage[suppliesPanelName].item3)
|
||||
local totalItem4 = itemAmount(storage[suppliesPanelName].item4)
|
||||
local totalItem5 = itemAmount(storage[suppliesPanelName].item5)
|
||||
|
||||
if storage.supplyRetries > 50 then
|
||||
print("CaveBot[SupplyCheck]: Round limit reached, going back on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return true
|
||||
elseif (storage[suppliesPanelName].imbues and player:getSkillLevel(11) ~= 100) then
|
||||
print("CaveBot[SupplyCheck]: Imbues ran out. Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return true
|
||||
elseif (storage[suppliesPanelName].staminaSwitch and stamina() < tonumber(storage[suppliesPanelName].staminaValue)) then
|
||||
print("CaveBot[SupplyCheck]: Stamina ran out. Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return true
|
||||
elseif (softCount < 1 and storage[suppliesPanelName].SoftBoots) then
|
||||
print("CaveBot[SupplyCheck]: No soft boots left. Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return true
|
||||
elseif (totalItem1 < tonumber(storage[suppliesPanelName].item1Min) and storage[suppliesPanelName].item1 > 100) then
|
||||
print("CaveBot[SupplyCheck]: Not enough item: " .. storage[suppliesPanelName].item1 .. "(only " .. totalItem1 .. " left). Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return true
|
||||
elseif (totalItem2 < tonumber(storage[suppliesPanelName].item2Min) and storage[suppliesPanelName].item2 > 100) then
|
||||
print("CaveBot[SupplyCheck]: Not enough item: " .. storage[suppliesPanelName].item2 .. "(only " .. totalItem2 .. " left). Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return true
|
||||
elseif (totalItem3 < tonumber(storage[suppliesPanelName].item3Min) and storage[suppliesPanelName].item3 > 100) then
|
||||
print("CaveBot[SupplyCheck]: Not enough item: " .. storage[suppliesPanelName].item3 .. "(only " .. totalItem3 .. " left). Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return true
|
||||
elseif (totalItem4 < tonumber(storage[suppliesPanelName].item4Min) and storage[suppliesPanelName].item4 > 100) then
|
||||
print("CaveBot[SupplyCheck]: Not enough item: " .. storage[suppliesPanelName].item4 .. "(only " .. totalItem4 .. " left). Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return true
|
||||
elseif (totalItem5 < tonumber(storage[suppliesPanelName].item5Min) and storage[suppliesPanelName].item5 > 100) then
|
||||
print("CaveBot[SupplyCheck]: Not enough item: " .. storage[suppliesPanelName].item5 .. "(only " .. totalItem5 .. " left). Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return true
|
||||
elseif (freecap() < tonumber(storage[suppliesPanelName].capValue) and storage[suppliesPanelName].capSwitch) then
|
||||
print("CaveBot[SupplyCheck]: Not enough capacity. Going on refill.")
|
||||
storage.supplyRetries = 0
|
||||
return true
|
||||
else
|
||||
print("CaveBot[SupplyCheck]: Enough supplies. Hunting. Round (" .. storage.supplyRetries .. "/50)")
|
||||
storage.supplyRetries = storage.supplyRetries + 1
|
||||
return CaveBot.gotoLabel(value)
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("supplycheck", "supply check", {
|
||||
value="startHunt",
|
||||
title="Supply check label",
|
||||
description="Insert here hunting start label",
|
||||
})
|
||||
end
|
@ -0,0 +1,52 @@
|
||||
CaveBot.Extensions.Travel = {}
|
||||
|
||||
CaveBot.Extensions.Travel.setup = function()
|
||||
CaveBot.registerAction("Travel", "#00FFFF", function(value, retries)
|
||||
local data = string.split(value, ",")
|
||||
local waitVal = 0
|
||||
if #data < 2 or #data > 3 then
|
||||
warn("CaveBot[Travel]: incorrect travel value!")
|
||||
return false
|
||||
elseif #data == 3 then
|
||||
waitVal = tonumber(data[3]:trim())
|
||||
end
|
||||
|
||||
if not waitVal then
|
||||
warn("CaveBot[Travel]: incorrect travel delay value!")
|
||||
return false
|
||||
end
|
||||
|
||||
if retries > 5 then
|
||||
print("CaveBot[Travel]: too many tries, can't travel")
|
||||
return false
|
||||
end
|
||||
|
||||
local npc = getCreatureByName(data[1]:trim())
|
||||
if not npc then
|
||||
print("CaveBot[Travel]: NPC not found, can't travel")
|
||||
return false
|
||||
end
|
||||
|
||||
local pos = player:getPosition()
|
||||
local npcPos = npc:getPosition()
|
||||
if math.max(math.abs(pos.x - npcPos.x), math.abs(pos.y - npcPos.y)) > 3 then
|
||||
autoWalk(npcPos, 20, {ignoreNonPathable = true, precision=3})
|
||||
delay(300)
|
||||
return "retry"
|
||||
end
|
||||
|
||||
NPC.say("hi")
|
||||
schedule(waitVal, function() NPC.say(data[2]:trim()) end)
|
||||
schedule(2*waitVal, function() NPC.say("yes") end)
|
||||
delay(3*waitVal)
|
||||
print("CaveBot[Travel]: travel action finished")
|
||||
return true
|
||||
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("travel", "travel", {
|
||||
value="NPC name, city",
|
||||
title="Travel",
|
||||
description="NPC name, City name, delay in ms(optional)",
|
||||
})
|
||||
end
|
@ -0,0 +1,93 @@
|
||||
-- walking
|
||||
local expectedDirs = {}
|
||||
local isWalking = {}
|
||||
local walkPath = {}
|
||||
local walkPathIter = 0
|
||||
|
||||
CaveBot.resetWalking = function()
|
||||
expectedDirs = {}
|
||||
walkPath = {}
|
||||
isWalking = false
|
||||
end
|
||||
|
||||
CaveBot.doWalking = function()
|
||||
if CaveBot.Config.get("mapClick") then
|
||||
return false
|
||||
end
|
||||
if #expectedDirs == 0 then
|
||||
return false
|
||||
end
|
||||
if #expectedDirs >= 3 then
|
||||
CaveBot.resetWalking()
|
||||
end
|
||||
local dir = walkPath[walkPathIter]
|
||||
if dir then
|
||||
g_game.walk(dir, false)
|
||||
table.insert(expectedDirs, dir)
|
||||
walkPathIter = walkPathIter + 1
|
||||
CaveBot.delay(CaveBot.Config.get("walkDelay") + player:getStepDuration(false, dir))
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- called when player position has been changed (step has been confirmed by server)
|
||||
onPlayerPositionChange(function(newPos, oldPos)
|
||||
if not oldPos or not newPos then return end
|
||||
|
||||
local dirs = {{NorthWest, North, NorthEast}, {West, 8, East}, {SouthWest, South, SouthEast}}
|
||||
local dir = dirs[newPos.y - oldPos.y + 2]
|
||||
if dir then
|
||||
dir = dir[newPos.x - oldPos.x + 2]
|
||||
end
|
||||
if not dir then
|
||||
dir = 8 -- 8 is invalid dir, it's fine
|
||||
end
|
||||
|
||||
if not isWalking or not expectedDirs[1] then
|
||||
-- some other walk action is taking place (for example use on ladder), wait
|
||||
walkPath = {}
|
||||
CaveBot.delay(CaveBot.Config.get("ping") + player:getStepDuration(false, dir) + 150)
|
||||
return
|
||||
end
|
||||
|
||||
if expectedDirs[1] ~= dir then
|
||||
if CaveBot.Config.get("mapClick") then
|
||||
CaveBot.delay(CaveBot.Config.get("walkDelay") + player:getStepDuration(false, dir))
|
||||
else
|
||||
CaveBot.delay(CaveBot.Config.get("mapClickDelay") + player:getStepDuration(false, dir))
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
table.remove(expectedDirs, 1)
|
||||
if CaveBot.Config.get("mapClick") and #expectedDirs > 0 then
|
||||
CaveBot.delay(CaveBot.Config.get("mapClickDelay") + player:getStepDuration(false, dir))
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.walkTo = function(dest, maxDist, params)
|
||||
local path = getPath(player:getPosition(), dest, maxDist, params)
|
||||
if not path or not path[1] then
|
||||
return false
|
||||
end
|
||||
local dir = path[1]
|
||||
|
||||
if CaveBot.Config.get("mapClick") then
|
||||
local ret = autoWalk(path)
|
||||
if ret then
|
||||
isWalking = true
|
||||
expectedDirs = path
|
||||
CaveBot.delay(CaveBot.Config.get("mapClickDelay") + math.max(CaveBot.Config.get("ping") + player:getStepDuration(false, dir), player:getStepDuration(false, dir) * 2))
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
g_game.walk(dir, false)
|
||||
isWalking = true
|
||||
walkPath = path
|
||||
walkPathIter = 2
|
||||
expectedDirs = { dir }
|
||||
CaveBot.delay(CaveBot.Config.get("walkDelay") + player:getStepDuration(false, dir))
|
||||
return true
|
||||
end
|
@ -0,0 +1,221 @@
|
||||
CaveBot.Extensions.Withdraw = {}
|
||||
|
||||
comparePosition = function(pPos, tPos)
|
||||
return (getDistanceBetween(pPos, tPos) <= 1)
|
||||
end
|
||||
|
||||
local depotContainers = {22797, 22798, 22799, 22800, 22801, 22802, 22803, 22804, 22805, 22806, 22807, 22808, 22809, 22810, 22811, 22812, 22813}
|
||||
local depotIDs = {3497, 3498, 3499, 3500}
|
||||
storage.stopSearch = false
|
||||
storage.lootContainerOpen = false
|
||||
local i = 1
|
||||
|
||||
|
||||
CaveBot.Extensions.Withdraw.setup = function()
|
||||
CaveBot.registerAction("withdraw", "#00FFFF", function(value, retries)
|
||||
local data = string.split(value, ",")
|
||||
local stashIndex
|
||||
local withdrawId
|
||||
local count
|
||||
local itemCount = 0
|
||||
local depotAmount
|
||||
if #data ~= 3 then
|
||||
warn("incorrect withdraw value")
|
||||
return false
|
||||
else
|
||||
stashIndex = tonumber(data[1])
|
||||
withdrawId = tonumber(data[2])
|
||||
count = tonumber(data[3])
|
||||
end
|
||||
local withdrawSource = depotContainers[stashIndex]
|
||||
|
||||
for i, container in pairs(getContainers()) do
|
||||
if not string.find(container:getName():lower(), "depot") then
|
||||
for j, item in pairs(container:getItems()) do
|
||||
if item:getId() == withdrawId then
|
||||
itemCount = itemCount + item:getCount()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if itemCount >= count then
|
||||
for i, container in pairs(getContainers()) do
|
||||
if string.find(container:getName():lower(), "depot box") then
|
||||
g_game.close(container)
|
||||
end
|
||||
end
|
||||
print("enough items")
|
||||
return true
|
||||
end
|
||||
|
||||
if retries > 400 then
|
||||
return true
|
||||
end
|
||||
|
||||
delay(200)
|
||||
local tileList = {}
|
||||
local tPos
|
||||
local depotClear = false
|
||||
local depotOpen = false
|
||||
local depotBoxOpen = false
|
||||
for _,tile in pairs(g_map.getTiles(posz())) do
|
||||
for i,thing in pairs(tile:getThings()) do
|
||||
if table.find(depotIDs, thing:getId()) then
|
||||
table.insert(tileList, {tileObj = tile, distance = getDistanceBetween(pos(), tile:getPosition()), depotID = thing:getId()})
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(tileList, function(a,b) return a.distance < b.distance end)
|
||||
::findEmptyDP::
|
||||
if tileList[i] and not storage.stopSearch then
|
||||
if tileList[i].depotID == 3498 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x + 1, y = tileList[i].tileObj:getPosition().y, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3499 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x, y = tileList[i].tileObj:getPosition().y + 1, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3500 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x - 1, y = tileList[i].tileObj:getPosition().y, z = tileList[i].tileObj:getPosition().z}
|
||||
elseif tileList[i].depotID == 3497 then
|
||||
tPos = {x = tileList[i].tileObj:getPosition().x, y = tileList[i].tileObj:getPosition().y - 1, z = tileList[i].tileObj:getPosition().z}
|
||||
end
|
||||
if tPos then
|
||||
local dest = g_map.getTile(tPos)
|
||||
if not comparePosition(pos(), dest:getPosition()) then
|
||||
if not dest:getCreatures()[1] and dest:isWalkable() then
|
||||
if autoWalk(dest:getPosition(), {ignoreNonPathable=true}) then
|
||||
storage.stopSearch = true
|
||||
delay(100)
|
||||
end
|
||||
else
|
||||
i = i + 1
|
||||
goto findEmptyDP
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if tileList[i].tileObj and not table.find(depotIDs, tileList[i].tileObj:getTopLookThing():getId()) and comparePosition(pos(), tileList[i].tileObj:getPosition()) then
|
||||
for j=1,table.getn(tileList[i].tileObj:getThings()),1 do
|
||||
if not tileList[i].tileObj:getThings()[j]:isNotMoveable() then
|
||||
delay(500)
|
||||
g_game.move(tileList[i].tileObj:getThings()[j], pos(), tileList[i].tileObj:getThings()[j]:getCount())
|
||||
end
|
||||
end
|
||||
if table.find(depotIDs, tileList[i].tileObj:getTopLookThing():getId()) then
|
||||
depotClear = true
|
||||
end
|
||||
else
|
||||
depotClear = true
|
||||
end
|
||||
if depotClear then
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
if container:getName():lower() == "locker" then
|
||||
depotOpen = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if tileList[i].tileObj and depotClear and not depotOpen and not storage.lootContainerOpen then
|
||||
delay(500)
|
||||
g_game.use(tileList[i].tileObj:getTopUseThing())
|
||||
depotOpen = true
|
||||
end
|
||||
i = 1
|
||||
--Version Check to know what to do with the depot--
|
||||
if g_game.getClientVersion() > 910 then
|
||||
if depotOpen then
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
if container:getName():lower() == "depot chest" then
|
||||
depotBoxOpen = true
|
||||
end
|
||||
end
|
||||
if findItem(3502) and not depotBoxOpen then
|
||||
delay(500)
|
||||
g_game.use(findItem(3502))
|
||||
depotBoxOpen = true
|
||||
end
|
||||
end
|
||||
if depotBoxOpen and not storage.lootContainerOpen then
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
if container:getName():lower() == "depot chest" then
|
||||
for _, item in ipairs(container:getItems()) do
|
||||
if item:isContainer() and table.find({22797, 22798}, item:getId()) then
|
||||
delay(500)
|
||||
storage.lootContainerOpen = true
|
||||
break
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local boxOpened = false
|
||||
for _, container in pairs(getContainers()) do
|
||||
if string.find(container:getName():lower(), "depot box") then
|
||||
boxOpened = true
|
||||
end
|
||||
end
|
||||
|
||||
if not boxOpened then
|
||||
for _, container in pairs(getContainers()) do
|
||||
if container:getName():lower() == "depot chest" then
|
||||
for _, item in pairs(container:getItems()) do
|
||||
if item:getId() == withdrawSource then
|
||||
g_game.open(item)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i, container in pairs(getContainers()) do
|
||||
if string.find(container:getName():lower(), "depot") then
|
||||
for j, item in pairs(container:getItems()) do
|
||||
if item:getId() == withdrawId then
|
||||
depotAmount = depotAmount + item:getCount()
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if depotAmount == 0 then
|
||||
print("lack of withdraw items!")
|
||||
return false
|
||||
end
|
||||
|
||||
local destination
|
||||
for i, container in pairs(getContainers()) do
|
||||
if container:getCapacity() > container:getSize() and not string.find(container:getName():lower(), "depot") and not string.find(container:getName():lower(), "loot") and not string.find(container:getName():lower(), "inbox") then
|
||||
destination = container
|
||||
end
|
||||
end
|
||||
|
||||
if itemCount < count and destination then
|
||||
for i, container in pairs(getContainers()) do
|
||||
if string.find(container:getName():lower(), "depot box") then
|
||||
for j, item in pairs(container:getItems()) do
|
||||
if item:getId() == withdrawId then
|
||||
if item:isStackable() then
|
||||
g_game.move(item, destination:getSlotPosition(destination:getItemsCount()), math.min(item:getCount(), (count - itemCount)))
|
||||
return "retry"
|
||||
else
|
||||
g_game.move(item, destination:getSlotPosition(destination:getItemsCount()), 1)
|
||||
return "retry"
|
||||
end
|
||||
return "retry"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return "retry"
|
||||
end
|
||||
end)
|
||||
|
||||
CaveBot.Editor.registerAction("withdraw", "withdraw", {
|
||||
value="index,id,amount",
|
||||
title="Withdraw Items",
|
||||
description="insert source index, item id and amount",
|
||||
})
|
||||
end
|
391
modules/game_bot/default_configs/vithrax_1.1/combo.otui
Normal file
391
modules/game_bot/default_configs/vithrax_1.1/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")
|
29
modules/game_bot/default_configs/vithrax_1.1/drop items.lua
Normal file
29
modules/game_bot/default_configs/vithrax_1.1/drop items.lua
Normal file
@ -0,0 +1,29 @@
|
||||
setDefaultTab("Cave")
|
||||
|
||||
UI.Separator()
|
||||
|
||||
UI.Label("Trash items:")
|
||||
if type(storage.trashItems) ~= "table" or not storage.trashItems then
|
||||
storage.trashItems = {283, 284, 285}
|
||||
end
|
||||
|
||||
local dropContainer = UI.Container(function(widget, items)
|
||||
storage.trashItems = items
|
||||
end, true)
|
||||
dropContainer:setHeight(35)
|
||||
dropContainer:setItems(storage.trashItems)
|
||||
|
||||
macro(200, "Drop Items", function()
|
||||
if not storage.trashItems[1] then return end
|
||||
for _, container in pairs(g_game.getContainers()) do
|
||||
for __, item in ipairs(container:getItems()) do
|
||||
for i, trashItem in ipairs(storage.trashItems) do
|
||||
if item:getId() == trashItem.id then
|
||||
return g_game.move(item, pos(), item:getCount())
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
UI.Separator()
|
29
modules/game_bot/default_configs/vithrax_1.1/eat food.lua
Normal file
29
modules/game_bot/default_configs/vithrax_1.1/eat food.lua
Normal file
@ -0,0 +1,29 @@
|
||||
setDefaultTab("HP")
|
||||
|
||||
UI.Separator()
|
||||
|
||||
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)
|
296
modules/game_bot/default_configs/vithrax_1.1/hunt.otui
Normal file
296
modules/game_bot/default_configs/vithrax_1.1/hunt.otui
Normal file
@ -0,0 +1,296 @@
|
||||
MonsterLabel < Label
|
||||
opacity: 0.87
|
||||
text-offset: 2 0
|
||||
focusable: false
|
||||
height: 16
|
||||
|
||||
HuntAnalyser < MiniWindow
|
||||
!text: tr('Hunt Analyser')
|
||||
height: 222
|
||||
icon: /images/topbuttons/analyzers
|
||||
&save: true
|
||||
&autoOpen: false
|
||||
|
||||
MiniWindowContents
|
||||
Label
|
||||
id: session
|
||||
!text: tr('Session:')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
BotLabel
|
||||
id: sessionValue
|
||||
!text: tr('00:00h')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: session.verticalCenter
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: xpGain
|
||||
!text: tr('XP Gain:')
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
|
||||
Label
|
||||
id: xpGainValue
|
||||
!text: tr('0')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: xpGain.verticalCenter
|
||||
margin-right: 3
|
||||
width: 110
|
||||
text-align: right
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: xpHour
|
||||
!text: tr('XP/h:')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Label
|
||||
id: xpHourValue
|
||||
!text: tr('0')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: xpHour.verticalCenter
|
||||
margin-left: 3
|
||||
width: 100
|
||||
text-align: right
|
||||
margin-right: 3
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: loot
|
||||
!text: tr('Loot:')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Label
|
||||
id: lootValue
|
||||
!text: tr('0')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: loot.verticalCenter
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
width: 100
|
||||
text-align: right
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: supplies
|
||||
!text: tr('Supplies:')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Label
|
||||
id: suppliesValue
|
||||
!text: tr('0')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: supplies.verticalCenter
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
width: 110
|
||||
text-align: right
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: balance
|
||||
!text: tr('Balance:')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Label
|
||||
id: balanceValue
|
||||
!text: tr('0')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: balance.verticalCenter
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
width: 110
|
||||
text-align: right
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: damage
|
||||
!text: tr('Damage:')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Label
|
||||
id: damageValue
|
||||
!text: tr('0')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: damage.verticalCenter
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
width: 100
|
||||
text-align: right
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: damageHour
|
||||
!text: tr('Damage/h:')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Label
|
||||
id: damageHourValue
|
||||
!text: tr('0')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: damageHour.verticalCenter
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
width: 100
|
||||
text-align: right
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: healing
|
||||
!text: tr('Healing:')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Label
|
||||
id: healingValue
|
||||
!text: tr('0')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: healing.verticalCenter
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
width: 100
|
||||
text-align: right
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: healingHour
|
||||
!text: tr('Healing/h:')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Label
|
||||
id: healingHourValue
|
||||
!text: tr('0')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: healingHour.verticalCenter
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
width: 100
|
||||
text-align: right
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: Label
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
margin-top: 10
|
||||
margin-left: 3
|
||||
!text: tr('Monsters Killed:')
|
||||
|
||||
TextList
|
||||
id: MessagePanel
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
height: 400
|
195
modules/game_bot/default_configs/vithrax_1.1/impact.otui
Normal file
195
modules/game_bot/default_configs/vithrax_1.1/impact.otui
Normal file
@ -0,0 +1,195 @@
|
||||
ImpactAnalyser < MiniWindow
|
||||
!text: tr('Impact Analyser')
|
||||
height: 205
|
||||
icon: /images/topbuttons/analyzers
|
||||
&save: true
|
||||
&autoOpen: false
|
||||
|
||||
MiniWindowContents
|
||||
Label
|
||||
id: damageCategory
|
||||
!text: tr('Damage')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
margin-top: 5
|
||||
height: 20
|
||||
font: sans-bold-16px
|
||||
text-align: center
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Label
|
||||
id: damageTotal
|
||||
!text: tr('Total:')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Label
|
||||
id: damageValue
|
||||
!text: tr('0')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: damageTotal.verticalCenter
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
width: 100
|
||||
text-align: right
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: maxDps
|
||||
!text: tr('DPS:')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Label
|
||||
id: maxDpsValue
|
||||
!text: tr('0')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: maxDps.verticalCenter
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
width: 100
|
||||
text-align: right
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: allTimeHigh
|
||||
!text: tr('All-Time High:')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Label
|
||||
id: allTimeHighValue
|
||||
!text: tr('0')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: allTimeHigh.verticalCenter
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
width: 100
|
||||
text-align: right
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: healingCategory
|
||||
!text: tr('Healing')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 15
|
||||
height: 20
|
||||
font: sans-bold-16px
|
||||
text-align: center
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Label
|
||||
id: healingTotal
|
||||
!text: tr('Total:')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 5
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Label
|
||||
id: healingValue
|
||||
!text: tr('0')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: healingTotal.verticalCenter
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
width: 100
|
||||
text-align: right
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: maxHps
|
||||
!text: tr('HPS:')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Label
|
||||
id: maxHpsValue
|
||||
!text: tr('0')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: maxHps.verticalCenter
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
width: 100
|
||||
text-align: right
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
|
||||
Label
|
||||
id: allTimeHighHeal
|
||||
!text: tr('All-Time High:')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
|
||||
Label
|
||||
id: allTimeHighHealValue
|
||||
!text: tr('0')
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: allTimeHighHeal.verticalCenter
|
||||
margin-left: 3
|
||||
margin-right: 3
|
||||
width: 100
|
||||
text-align: right
|
||||
|
||||
HorizontalSeparator
|
||||
id: separator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 3
|
1234
modules/game_bot/default_configs/vithrax_1.1/items.lua
Normal file
1234
modules/game_bot/default_configs/vithrax_1.1/items.lua
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user