mirror of
https://github.com/OTCv8/otclientv8.git
synced 2025-10-18 05:33:27 +02:00
Version 2.6 - http://otclient.net/showthread.php?tid=552
This commit is contained in:
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
Reference in New Issue
Block a user