Updated to OTCv8 3.1 rev 224

This commit is contained in:
OTCv8 2022-06-06 22:04:52 +00:00
parent 00ca45bd62
commit 9cfff63e16
111 changed files with 2292 additions and 1465 deletions

View File

@ -522,7 +522,8 @@ function initCallbacks()
onTurn = botCreatureTurn, onTurn = botCreatureTurn,
onWalk = botCreatureWalk, onWalk = botCreatureWalk,
onManaChange = botManaChange, onManaChange = botManaChange,
onStatesChange = botStatesChange onStatesChange = botStatesChange,
onInventoryChange = botInventoryChange
}) })
connect(Container, { connect(Container, {
@ -587,7 +588,8 @@ function terminateCallbacks()
onTurn = botCreatureTurn, onTurn = botCreatureTurn,
onWalk = botCreatureWalk, onWalk = botCreatureWalk,
onManaChange = botManaChange, onManaChange = botManaChange,
onStatesChange = botStatesChange onStatesChange = botStatesChange,
onInventoryChange = botInventoryChange
}) })
disconnect(Container, { disconnect(Container, {
@ -770,9 +772,9 @@ function botManaChange(player, mana, maxMana, oldMana, oldMaxMana)
safeBotCall(function() botExecutor.callbacks.onManaChange(player, mana, maxMana, oldMana, oldMaxMana) end) safeBotCall(function() botExecutor.callbacks.onManaChange(player, mana, maxMana, oldMana, oldMaxMana) end)
end end
function botStatesChange(states, oldStates) function botStatesChange(player, states, oldStates)
if botExecutor == nil then return false end if botExecutor == nil then return false end
safeBotCall(function() botExecutor.callbacks.onStatesChange(states, oldStates) end) safeBotCall(function() botExecutor.callbacks.onStatesChange(player, states, oldStates) end)
end end
function botContainerAddItem(container, slot, item, oldItem) function botContainerAddItem(container, slot, item, oldItem)
@ -795,6 +797,11 @@ function botGroupSpellCooldown(iconId, duration)
safeBotCall(function() botExecutor.callbacks.onGroupSpellCooldown(iconId, duration) end) safeBotCall(function() botExecutor.callbacks.onGroupSpellCooldown(iconId, duration) end)
end end
function botInventoryChange(player, slot, item, oldItem)
if botExecutor == nil then return false end
safeBotCall(function() botExecutor.callbacks.onInventoryChange(player, slot, item, oldItem) end)
end
function botGameQuestLog(quests) function botGameQuestLog(quests)
if botExecutor == nil then return false end if botExecutor == nil then return false end
safeBotCall(function() botExecutor.callbacks.onGameQuestLog(quests) end) safeBotCall(function() botExecutor.callbacks.onGameQuestLog(quests) end)

View File

@ -32,6 +32,10 @@ MiniWindow
MiniWindowContents MiniWindowContents
ComboBox ComboBox
id: config id: config
&menuScroll: true
&menuHeight: 450
&menuScrollStep: 100
&parentWidth: true
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right

View File

@ -1,88 +0,0 @@
CaveBot.Extensions.BuySupplies = {}
CaveBot.Extensions.BuySupplies.setup = function()
CaveBot.registerAction("BuySupplies", "#C300FF", function(value, retries)
local supplies = SuppliesConfig.supplies
supplies = supplies[supplies.currentProfile]
local item1Count = itemAmount(supplies.item1)
local item2Count = itemAmount(supplies.item2)
local item3Count = itemAmount(supplies.item3)
local item4Count = itemAmount(supplies.item4)
local item5Count = itemAmount(supplies.item5)
local item6Count = itemAmount(supplies.item6)
local item7Count = itemAmount(supplies.item7)
local possibleItems = {}
local val = string.split(value, ",")
local waitVal
if #val == 0 or #val > 2 then
warn("CaveBot[BuySupplies]: incorrect BuySupplies value")
return false
elseif #val == 2 then
waitVal = tonumber(val[2]:trim())
end
local npcName = val[1]:trim()
local npc = getCreatureByName(npcName)
if not npc then
print("CaveBot[BuySupplies]: NPC not found")
return false
end
if not waitVal and #val == 2 then
warn("CaveBot[BuySupplies]: incorrect delay values!")
elseif waitVal and #val == 2 then
delay(waitVal)
end
if retries > 50 then
print("CaveBot[BuySupplies]: Too many tries, can't buy")
return false
end
if not CaveBot.ReachNPC(npcName) then
return "retry"
end
local itemList = {
item1 = {ID = supplies.item1, maxAmount = supplies.item1Max, currentAmount = item1Count},
item2 = {ID = supplies.item2, maxAmount = supplies.item2Max, currentAmount = item2Count},
item3 = {ID = supplies.item3, maxAmount = supplies.item3Max, currentAmount = item3Count},
item4 = {ID = supplies.item4, maxAmount = supplies.item4Max, currentAmount = item4Count},
item5 = {ID = supplies.item5, maxAmount = supplies.item5Max, currentAmount = item5Count},
item6 = {ID = supplies.item6, maxAmount = supplies.item6Max, currentAmount = item6Count},
item7 = {ID = supplies.item7, maxAmount = supplies.item7Max, currentAmount = item7Count}
}
if not NPC.isTrading() then
CaveBot.OpenNpcTrade()
CaveBot.delay(storage.extras.talkDelay*2)
return "retry"
end
-- get items from npc
local npcItems = NPC.getBuyItems()
for i,v in pairs(npcItems) do
table.insert(possibleItems, v.id)
end
for i, item in pairs(itemList) do
if item["ID"] and item["ID"] > 100 and table.find(possibleItems, item["ID"]) then
local amountToBuy = item["maxAmount"] - item["currentAmount"]
if amountToBuy > 0 then
NPC.buy(item["ID"], math.min(100, amountToBuy))
print("CaveBot[BuySupplies]: bought " .. math.min(100, amountToBuy) .. "x " .. item["ID"])
return "retry"
end
end
end
print("CaveBot[BuySupplies]: bought everything, proceeding")
return true
end)
CaveBot.Editor.registerAction("buysupplies", "buy supplies", {
value="NPC name",
title="Buy Supplies",
description="NPC Name, delay(in ms, optional)",
})
end

View File

@ -1,142 +0,0 @@
CaveBot.Extensions.SupplyCheck = {}
local supplyRetries = 0
local missedChecks = 0
local time = nil
CaveBot.Extensions.SupplyCheck.setup = function()
CaveBot.registerAction("supplyCheck", "#db5a5a", function(value)
local data = string.split(value, ",")
local round = 0
local label = data[1]:trim()
local pos = nil
if #data == 4 then
pos = {x=tonumber(data[2]),y=tonumber(data[3]),z=tonumber(data[4])}
end
if pos then
if missedChecks >= 4 then
missedChecks = 0
supplyRetries = 0
print("CaveBot[SupplyCheck]: Missed 5 supply checks, proceeding with waypoints")
return true
end
if getDistanceBetween(player:getPosition(), pos) > 10 then
missedChecks = missedChecks + 1
print("CaveBot[SupplyCheck]: Missed supply check! ".. 5-missedChecks .. " tries left before skipping.")
return CaveBot.gotoLabel(label)
end
end
if time then
round = math.ceil((now - time)/1000) .. "s"
else
round = ""
end
time = now
local supplies = SuppliesConfig.supplies
supplies = supplies[supplies.currentProfile]
local softCount = itemAmount(6529) + itemAmount(3549)
local totalItem1 = itemAmount(supplies.item1)
local totalItem2 = itemAmount(supplies.item2)
local totalItem3 = itemAmount(supplies.item3)
local totalItem4 = itemAmount(supplies.item4)
local totalItem5 = itemAmount(supplies.item5)
local totalItem6 = itemAmount(supplies.item6)
if storage.caveBot.forceRefill then
print("CaveBot[SupplyCheck]: User forced, going back on refill. Last round took: " .. round)
storage.caveBot.forceRefill = false
supplyRetries = 0
missedChecks = 0
return false
elseif storage.caveBot.backStop then
print("CaveBot[SupplyCheck]: User forced, going back to city and turning off CaveBot. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif storage.caveBot.backTrainers then
print("CaveBot[SupplyCheck]: User forced, going back to city, then on trainers. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif storage.caveBot.backOffline then
print("CaveBot[SupplyCheck]: User forced, going back to city, then on offline training. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif supplyRetries > (storage.extras.huntRoutes or 50) then
print("CaveBot[SupplyCheck]: Round limit reached, going back on refill. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif (supplies.imbues and player:getSkillLevel(11) == 0) then
print("CaveBot[SupplyCheck]: Imbues ran out. Going on refill. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif (supplies.staminaSwitch and stamina() < tonumber(supplies.staminaValue)) then
print("CaveBot[SupplyCheck]: Stamina ran out. Going on refill. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif (softCount < 1 and supplies.SoftBoots) then
print("CaveBot[SupplyCheck]: No soft boots left. Going on refill. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif (totalItem1 < tonumber(supplies.item1Min) and supplies.item1 > 100) then
print("CaveBot[SupplyCheck]: Not enough item: " .. supplies.item1 .. "(only " .. totalItem1 .. " left). Going on refill. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif (totalItem2 < tonumber(supplies.item2Min) and supplies.item2 > 100) then
print("CaveBot[SupplyCheck]: Not enough item: " .. supplies.item2 .. "(only " .. totalItem2 .. " left). Going on refill. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif (totalItem3 < tonumber(supplies.item3Min) and supplies.item3 > 100) then
print("CaveBot[SupplyCheck]: Not enough item: " .. supplies.item3 .. "(only " .. totalItem3 .. " left). Going on refill. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif (totalItem4 < tonumber(supplies.item4Min) and supplies.item4 > 100) then
print("CaveBot[SupplyCheck]: Not enough item: " .. supplies.item4 .. "(only " .. totalItem4 .. " left). Going on refill. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif (totalItem5 < tonumber(supplies.item5Min) and supplies.item5 > 100) then
print("CaveBot[SupplyCheck]: Not enough item: " .. supplies.item5 .. "(only " .. totalItem5 .. " left). Going on refill. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif (totalItem6 < tonumber(supplies.item6Min) and supplies.item6 > 100) then
print("CaveBot[SupplyCheck]: Not enough item: " .. supplies.item6 .. "(only " .. totalItem6 .. " left). Going on refill. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif (freecap() < tonumber(supplies.capValue) and supplies.capSwitch) then
print("CaveBot[SupplyCheck]: Not enough capacity. Going on refill. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif ForcedRefill then
print("CaveBot[SupplyCheck]: Forced refill, going back to city. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
else
print("CaveBot[SupplyCheck]: Enough supplies. Hunting. Round (" .. supplyRetries .. "/" .. (storage.extras.huntRoutes or 50) .."). Last round took: " .. round)
supplyRetries = supplyRetries + 1
missedChecks = 0
return CaveBot.gotoLabel(label)
end
end)
CaveBot.Editor.registerAction("supplycheck", "supply check", {
value=function() return "startHunt," .. posx() .. "," .. posy() .. "," .. posz() end,
title="Supply check label",
description="Insert here hunting start label",
validation=[[[^,]+,\d{1,5},\d{1,5},\d{1,2}$]]
})
end

View File

@ -1,383 +0,0 @@
function SuppliesPanel(parent)
local panelName = "supplies"
if not parent then
parent = panel
end
local temp = nil
if SuppliesConfig[panelName] and SuppliesConfig[panelName].item1 then
temp = SuppliesConfig[panelName]
end
if not SuppliesConfig[panelName] or SuppliesConfig[panelName].item1 then
SuppliesConfig[panelName] = {
currentProfile = "Default",
["Default"] = {}
}
if temp then
SuppliesConfig[panelName].Default = temp
end
end
local currentProfile = SuppliesConfig[panelName].currentProfile
local config = SuppliesConfig[panelName][currentProfile]
if not config then
for k,v in pairs(SuppliesConfig[panelName]) do
if type(v) == "table" then
SuppliesConfig[panelName].currentProfile = k
config = SuppliesConfig[panelName][k]
break
end
end
end
rootWidget = g_ui.getRootWidget()
if rootWidget then
SuppliesWindow = UI.createWindow('SuppliesWindow', rootWidget)
SuppliesWindow:hide()
SuppliesWindow.onVisibilityChange = function(widget, visible)
if not visible then
vBotConfigSave("supply")
end
end
local function loadVariables()
config.item1 = config.item1 or 0
config.item2 = config.item2 or 0
config.item3 = config.item3 or 0
config.item4 = config.item4 or 0
config.item5 = config.item5 or 0
config.item6 = config.item6 or 0
config.item1Min = config.item1Min or 0
config.item1Max = config.item1Max or 0
config.item2Min = config.item2Min or 0
config.item2Max = config.item2Max or 0
config.item3Min = config.item3Min or 0
config.item3Max = config.item3Max or 0
config.item4Min = config.item4Min or 0
config.item4Max = config.item4Max or 0
config.item5Min = config.item5Min or 0
config.item5Max = config.item5Max or 0
config.item6Min = config.item6Min or 0
config.item6Max = config.item6Max or 0
config.capValue = config.capValue or 0
config.staminaValue = config.staminaValue or 0
end
loadVariables()
local function setValues()
SuppliesWindow.capSwitch:setOn(config.capSwitch)
SuppliesWindow.SoftBoots:setOn(config.SoftBoots)
SuppliesWindow.imbues:setOn(config.imbues)
SuppliesWindow.staminaSwitch:setOn(config.staminaSwitch)
SuppliesWindow.item1:setItemId(config.item1)
SuppliesWindow.item2:setItemId(config.item2)
SuppliesWindow.item3:setItemId(config.item3)
SuppliesWindow.item4:setItemId(config.item4)
SuppliesWindow.item5:setItemId(config.item5)
SuppliesWindow.capValue:setText(config.capValue)
SuppliesWindow.item1Min:setText(config.item1Min)
SuppliesWindow.item1Max:setText(config.item1Max)
SuppliesWindow.item2Min:setText(config.item2Min)
SuppliesWindow.item2Max:setText(config.item2Max)
SuppliesWindow.item3Min:setText(config.item3Min)
SuppliesWindow.item3Max:setText(config.item3Max)
SuppliesWindow.item4Min:setText(config.item4Min)
SuppliesWindow.staminaValue:setText(config.staminaValue)
SuppliesWindow.item4Max:setText(config.item4Max)
SuppliesWindow.item5Min:setText(config.item5Min)
SuppliesWindow.item5Max:setText(config.item5Max)
SuppliesWindow.item6Min:setText(config.item6Min)
SuppliesWindow.item6Max:setText(config.item6Max)
end
setValues()
local function refreshProfileList()
local profiles = SuppliesConfig[panelName]
SuppliesWindow.profiles:destroyChildren()
for k,v in pairs(profiles) do
if type(v) == "table" then
local label = UI.createWidget("ProfileLabel", SuppliesWindow.profiles)
label:setText(k)
label:setTooltip("Click to load this profile. \nDouble click to change the name.")
label.remove.onClick = function()
local childs = SuppliesWindow.profiles:getChildCount()
if childs == 1 then
return info("vBot[Supplies] You need at least one profile!")
end
profiles[k] = nil
label:destroy()
vBotConfigSave("supply")
end
label.onDoubleClick = function(widget)
local window = modules.client_textedit.show(widget, {title = "Set Profile Name", description = "Enter a new name for selected profile"})
schedule(50, function()
window:raise()
window:focus()
end)
end
label.onClick = function()
SuppliesConfig[panelName].currentProfile = label:getText()
config = SuppliesConfig[panelName][label:getText()]
loadVariables()
setValues()
vBotConfigSave("supply")
end
label.onTextChange = function(widget,text)
profiles[text] = profiles[k]
profiles[k] = nil
vBotConfigSave("supply")
end
end
end
end
refreshProfileList()
local function setProfileFocus()
for i,v in ipairs(SuppliesWindow.profiles:getChildren()) do
local name = v:getText()
if name == SuppliesConfig[panelName].currentProfile then
return v:focus()
end
end
end
setProfileFocus()
SuppliesWindow.newProfile.onClick = function()
local n = SuppliesWindow.profiles:getChildCount()
if n > 6 then
return info("vBot[Supplies] - max profile count reached!")
end
local name = "Profile #"..n+1
SuppliesConfig[panelName][name] = {}
refreshProfileList()
setProfileFocus()
vBotConfigSave("supply")
end
SuppliesWindow.capSwitch.onClick = function(widget)
config.capSwitch = not config.capSwitch
widget:setOn(config.capSwitch)
end
SuppliesWindow.SoftBoots.onClick = function(widget)
config.SoftBoots = not config.SoftBoots
widget:setOn(config.SoftBoots)
end
SuppliesWindow.imbues.onClick = function(widget)
config.imbues = not config.imbues
widget:setOn(config.imbues)
end
SuppliesWindow.staminaSwitch.onClick = function(widget)
config.staminaSwitch = not config.staminaSwitch
widget:setOn(config.staminaSwitch)
end
-- bot items
SuppliesWindow.item1.onItemChange = function(widget)
config.item1 = widget:getItemId()
end
SuppliesWindow.item2.onItemChange = function(widget)
config.item2 = widget:getItemId()
end
SuppliesWindow.item3.onItemChange = function(widget)
config.item3 = widget:getItemId()
end
SuppliesWindow.item4.onItemChange = function(widget)
config.item4 = widget:getItemId()
end
SuppliesWindow.item5.onItemChange = function(widget)
config.item5 = widget:getItemId()
end
SuppliesWindow.item6:setItemId(config.item6)
SuppliesWindow.item6.onItemChange = function(widget)
config.item6 = widget:getItemId()
end
-- text windows
SuppliesWindow.capValue.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.capValue:getText())
if not value then
SuppliesWindow.capValue:setText(0)
config.capValue = 0
else
text = text:match("0*(%d+)")
config.capValue = text
end
end
SuppliesWindow.item1Min.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item1Min:getText())
if not value then
SuppliesWindow.item1Min:setText(0)
config.item1Min = 0
else
text = text:match("0*(%d+)")
config.item1Min = text
end
end
SuppliesWindow.item1Max.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item1Max:getText())
if not value then
SuppliesWindow.item1Max:setText(0)
config.item1Max = 0
else
text = text:match("0*(%d+)")
config.item1Max = text
end
end
SuppliesWindow.item2Min.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item2Min:getText())
if not value then
SuppliesWindow.item2Min:setText(0)
config.item2Min = 0
else
text = text:match("0*(%d+)")
config.item2Min = text
end
end
SuppliesWindow.item2Max.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item2Max:getText())
if not value then
SuppliesWindow.item2Max:setText(0)
config.item2Max = 0
else
text = text:match("0*(%d+)")
config.item2Max = text
end
end
SuppliesWindow.item3Min.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item3Min:getText())
if not value then
SuppliesWindow.item3Min:setText(0)
config.item3Min = 0
else
text = text:match("0*(%d+)")
config.item3Min = text
end
end
SuppliesWindow.item3Max.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item3Max:getText())
if not value then
SuppliesWindow.item3Max:setText(0)
config.item3Max = 0
else
config.item3Max = text
end
end
SuppliesWindow.item4Min.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item4Min:getText())
if not value then
SuppliesWindow.item4Min:setText(0)
config.item4Min = 0
else
text = text:match("0*(%d+)")
config.item4Min = text
end
end
SuppliesWindow.staminaValue.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.staminaValue:getText())
if not value then
SuppliesWindow.staminaValue:setText(0)
config.staminaValue = 0
else
text = text:match("0*(%d+)")
config.staminaValue = text
end
end
SuppliesWindow.item4Max.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item4Max:getText())
if not value then
SuppliesWindow.item4Max:setText(0)
config.item4Max = 0
else
text = text:match("0*(%d+)")
config.item4Max = text
end
end
SuppliesWindow.item5Min.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item5Min:getText())
if not value then
SuppliesWindow.item5Min:setText(0)
config.item5Min = 0
else
text = text:match("0*(%d+)")
config.item5Min = text
end
end
SuppliesWindow.item5Max.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item5Max:getText())
if not value then
SuppliesWindow.item5Max:setText(0)
config.item5Max = 0
else
text = text:match("0*(%d+)")
config.item5Max = text
end
end
SuppliesWindow.item6Min.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item6Min:getText())
if not value then
SuppliesWindow.item6Min:setText(0)
config.item6Min = 0
else
text = text:match("0*(%d+)")
config.item6Min = text
end
end
SuppliesWindow.item6Max.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.item6Max:getText())
if not value then
SuppliesWindow.item6Max:setText(0)
config.item6Max = 0
else
text = text:match("0*(%d+)")
config.item6Max = text
end
end
Supplies = {}
Supplies.show = function()
SuppliesWindow:show()
SuppliesWindow:raise()
SuppliesWindow:focus()
end
end
UI.Button("Supplies", function()
SuppliesWindow:show()
SuppliesWindow:raise()
SuppliesWindow:focus()
end)
SuppliesWindow.close.onClick = function(widget)
SuppliesWindow:hide()
end
end
UI.Separator()
SuppliesPanel(setDefaultTab("Cave"))

View File

@ -1,361 +0,0 @@
ProfileLabel < UIWidget
background-color: alpha
text-offset: 3 1
focusable: true
height: 16
font: verdana-11px-rounded
text-align: left
$focus:
background-color: #00000055
Button
id: remove
!text: tr('X')
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
width: 14
height: 14
margin-right: 3
text-align: center
text-offset: 0 1
tooltip: Remove profile from the list.
SuppliesWindow < MainWindow
!text: tr('Supplies')
size: 430 310
@onEscape: self:hide()
VerticalSeparator
id: sep
anchors.top: parent.top
anchors.left: item1Max.right
anchors.bottom: parent.bottom
margin-top: 3
margin-bottom: 3
margin-left: 10
Label
anchors.left: sep.right
anchors.right: parent.right
anchors.top: parent.top
margin-left: 10
margin-top: 3
text-align: center
text: Additional Conditions:
HorizontalSeparator
anchors.top: prev.bottom
anchors.left: prev.left
anchors.right: prev.right
margin-top: 3
BotSwitch
id: SoftBoots
anchors.top: prev.bottom
anchors.left: sep.right
anchors.right: parent.right
margin-top: 5
margin-left: 10
text: No Soft
tooltip: Go refill if there's no more active soft boots.
BotSwitch
id: capSwitch
height: 20
anchors.left: SoftBoots.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
margin-right: 50
text-align: center
text: Cap Below:
tooltip: Go refill if capacity is below set value.
BotTextEdit
id: capValue
size: 40 20
anchors.left: prev.right
anchors.right: parent.right
anchors.top: prev.top
margin-left: 5
BotSwitch
id: staminaSwitch
height: 20
anchors.left: SoftBoots.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
margin-right: 50
text-align: center
text: Stamina:
tooltip: Go refill if stamina is below set value. (in minutes)
BotTextEdit
id: staminaValue
size: 40 20
anchors.left: prev.right
anchors.right: parent.right
anchors.top: prev.top
margin-left: 5
BotSwitch
id: imbues
anchors.top: prev.bottom
anchors.left: sep.right
anchors.right: parent.right
margin-top: 5
margin-left: 10
text: No Imbues
tooltip: Go refill when mana leech imbue has worn off.
TextList
id: profiles
anchors.top: prev.bottom
margin-top: 5
anchors.left: prev.left
anchors.right: prev.right
anchors.bottom: close.top
margin-bottom: 20
BotButton
id: newProfile
anchors.left: prev.left
anchors.top: prev.bottom
size: 35 15
text: New
font: cipsoftFont
tooltip: Create new supplies profile.
BotItem
id: item1
anchors.left: parent.left
anchors.top: parent.top
margin-top: 3
Label
id: MinLabel
!text: tr('Min Amount')
anchors.left: prev.right
anchors.top: prev.top
margin-left: 18
Label
id: MaxLabel
!text: tr('Max Amount')
anchors.left: prev.right
anchors.top: prev.top
margin-left: 35
BotTextEdit
id: item1Min
size: 100 20
anchors.left: parent.left
anchors.top: prev.top
margin-top: 15
margin-left: 40
text-align: center
BotTextEdit
id: item1Max
size: 100 20
anchors.left: prev.right
anchors.top: prev.top
margin-left: 5
text-align: center
BotItem
id: item2
anchors.left: parent.left
anchors.top: prev.top
margin-top: 30
Label
id: MinLabel
!text: tr('Min Amount')
anchors.left: prev.right
anchors.top: prev.top
margin-left: 18
Label
id: MaxLabel
!text: tr('Max Amount')
anchors.left: prev.right
anchors.top: prev.top
margin-left: 35
BotTextEdit
id: item2Min
size: 100 20
anchors.left: parent.left
anchors.top: prev.top
margin-top: 15
margin-left: 40
text-align: center
BotTextEdit
id: item2Max
size: 100 20
anchors.left: prev.right
anchors.top: prev.top
margin-left: 5
text-align: center
BotItem
id: item3
anchors.left: parent.left
anchors.top: prev.top
margin-top: 30
Label
id: MinLabel
!text: tr('Min Amount')
anchors.left: prev.right
anchors.top: prev.top
margin-left: 18
Label
id: MaxLabel
!text: tr('Max Amount')
anchors.left: prev.right
anchors.top: prev.top
margin-left: 35
BotTextEdit
id: item3Min
size: 100 20
anchors.left: parent.left
anchors.top: prev.top
margin-top: 15
margin-left: 40
text-align: center
BotTextEdit
id: item3Max
size: 100 20
anchors.left: prev.right
anchors.top: prev.top
margin-left: 5
text-align: center
BotItem
id: item4
anchors.left: parent.left
anchors.top: prev.top
margin-top: 30
Label
id: MinLabel
!text: tr('Min Amount')
anchors.left: prev.right
anchors.top: prev.top
margin-left: 18
Label
id: MaxLabel
!text: tr('Max Amount')
anchors.left: prev.right
anchors.top: prev.top
margin-left: 35
BotTextEdit
id: item4Min
size: 100 20
anchors.left: parent.left
anchors.top: prev.top
margin-top: 15
margin-left: 40
text-align: center
BotTextEdit
id: item4Max
size: 100 20
anchors.left: prev.right
anchors.top: prev.top
margin-left: 5
text-align: center
BotItem
id: item5
anchors.left: parent.left
anchors.top: prev.top
margin-top: 30
Label
id: MinLabel
!text: tr('Min Amount')
anchors.left: prev.right
anchors.top: prev.top
margin-left: 18
Label
id: MaxLabel
!text: tr('Max Amount')
anchors.left: prev.right
anchors.top: prev.top
margin-left: 35
BotTextEdit
id: item5Min
size: 100 20
anchors.left: parent.left
anchors.top: prev.top
margin-top: 15
margin-left: 40
text-align: center
BotTextEdit
id: item5Max
size: 100 20
anchors.left: prev.right
anchors.top: prev.top
margin-left: 5
text-align: center
BotItem
id: item6
anchors.left: parent.left
anchors.top: prev.top
margin-top: 30
Label
id: MinLabel
!text: tr('Min Amount')
anchors.left: prev.right
anchors.top: prev.top
margin-left: 18
Label
id: MaxLabel
!text: tr('Max Amount')
anchors.left: prev.right
anchors.top: prev.top
margin-left: 35
BotTextEdit
id: item6Min
size: 100 20
anchors.left: parent.left
anchors.top: prev.top
margin-top: 15
margin-left: 40
text-align: center
BotTextEdit
id: item6Max
size: 100 20
anchors.left: prev.right
anchors.top: prev.top
margin-left: 5
text-align: center
Button
id: close
!text: tr('Close')
font: cipsoftFont
anchors.right: parent.right
anchors.bottom: parent.bottom
size: 45 21
margin-top: 15
tooltip: Close supplies window and save settings.

View File

@ -1,10 +1,13 @@
CaveBot.Actions = {} CaveBot.Actions = {}
vBot.lastLabel = "" vBot.lastLabel = ""
local oldTibia = g_game.getClientVersion() < 960 local oldTibia = g_game.getClientVersion() < 960
local nextTile = nil
local noPath = 0
-- antistuck f() -- antistuck f()
local nextPos = nil local nextPos = nil -- creature
local nextPosF = nil -- furniture
local function modPos(dir) local function modPos(dir)
local y = 0 local y = 0
local x = 0 local x = 0
@ -34,6 +37,103 @@ local function modPos(dir)
return {x, y} return {x, y}
end end
-- stack-covered antystuck, in & out pz
local lastMoved = now - 200
onTextMessage(function(mode, text)
if text ~= 'There is not enough room.' then return end
if CaveBot.isOff() then return end
local tiles = getNearTiles(pos())
for i, tile in ipairs(tiles) do
if not tile:hasCreature() and tile:isWalkable() and #tile:getItems() > 9 then
local topThing = tile:getTopThing()
if not isInPz() then
return useWith(3197, tile:getTopThing()) -- disintegrate
else
if now < lastMoved + 200 then return end -- delay to prevent clogging
local nearTiles = getNearTiles(tile:getPosition())
for i, tile in ipairs(nearTiles) do
local tpos = tile:getPosition()
if pos() ~= tpos then
if tile:isWalkable() then
lastMoved = now
return g_game.move(topThing, tpos) -- move item
end
end
end
end
end
end
end)
local furnitureIgnore = { 2986 }
local function breakFurniture(destPos)
if isInPz() then return false end
local candidate = {thing=nil, dist=100}
for i, tile in ipairs(g_map.getTiles(posz())) do
local walkable = tile:isWalkable()
local topThing = tile:getTopThing()
local isWg = topThing and topThing:getId() == 2130
if topThing and (isWg or not table.find(furnitureIgnore, topThing:getId()) and topThing:isItem()) then
local moveable = not topThing:isNotMoveable()
local tpos = tile:getPosition()
local path = findPath(player:getPosition(), tpos, 7, { ignoreNonPathable = true, precision = 1 })
if path then
if isWg or (not walkable and moveable) then
local distance = getDistanceBetween(destPos, tpos)
if distance < candidate.dist then
candidate = {thing=topThing, dist=distance}
end
end
end
end
end
local thing = candidate.thing
if thing then
useWith(3197, thing)
return true
end
return false
end
local function pushPlayer(creature)
local cpos = creature:getPosition()
local tiles = getNearTiles(cpos)
for i, tile in ipairs(tiles) do
local pos = tile:getPosition()
local minimapColor = g_map.getMinimapColor(pos)
local stairs = (minimapColor >= 210 and minimapColor <= 213)
if not stairs and tile:isWalkable() then
g_game.move(creature, pos)
end
end
end
local function pathfinder()
if not storage.extras.pathfinding then return end
if noPath < 10 then return end
if not CaveBot.gotoNextWaypointInRange() then
if getConfigFromName and getConfigFromName() then
local profile = CaveBot.getCurrentProfile()
local config = getConfigFromName()
local newProfile = profile == '#Unibase' and config or '#Unibase'
CaveBot.setCurrentProfile(newProfile)
end
end
noPath = 0
return true
end
-- it adds an action widget to list -- it adds an action widget to list
CaveBot.addAction = function(action, value, focus) CaveBot.addAction = function(action, value, focus)
action = action:lower() action = action:lower()
@ -119,7 +219,25 @@ end)
CaveBot.registerAction("delay", "#AAAAAA", function(value, retries, prev) CaveBot.registerAction("delay", "#AAAAAA", function(value, retries, prev)
if retries == 0 then if retries == 0 then
CaveBot.delay(tonumber(value)) local data = string.split(value, ",")
local val = tonumber(data[1]:trim())
local random
local final
if #data == 2 then
random = tonumber(data[2]:trim())
end
if random then
local diff = (val/100) * random
local min = val - diff
local max = val + diff
final = math.random(min, max)
end
final = final or val
CaveBot.delay(final)
return "retry" return "retry"
end end
return true return true
@ -165,13 +283,21 @@ CaveBot.registerAction("goto", "green", function(value, retries, prev)
warn("Invalid cavebot goto action value. It should be position (x,y,z), is: " .. value) warn("Invalid cavebot goto action value. It should be position (x,y,z), is: " .. value)
return false return false
end end
-- reset pathfinder
nextPosF = nil
nextPos = nil
if CaveBot.Config.get("mapClick") then if CaveBot.Config.get("mapClick") then
if retries >= 5 then if retries >= 5 then
noPath = noPath + 1
pathfinder()
return false -- tried 5 times, can't get there return false -- tried 5 times, can't get there
end end
else else
if retries >= 100 then if retries >= 100 then
noPath = noPath + 1
pathfinder()
return false -- tried 100 times, can't get there return false -- tried 100 times, can't get there
end end
end end
@ -180,12 +306,16 @@ CaveBot.registerAction("goto", "green", function(value, retries, prev)
pos = {x=tonumber(pos[1][2]), y=tonumber(pos[1][3]), z=tonumber(pos[1][4])} pos = {x=tonumber(pos[1][2]), y=tonumber(pos[1][3]), z=tonumber(pos[1][4])}
local playerPos = player:getPosition() local playerPos = player:getPosition()
if pos.z ~= playerPos.z then if pos.z ~= playerPos.z then
noPath = noPath + 1
pathfinder()
return false -- different floor return false -- different floor
end end
local maxDist = storage.extras.gotoMaxDistance or 40 local maxDist = storage.extras.gotoMaxDistance or 40
if math.abs(pos.x-playerPos.x) + math.abs(pos.y-playerPos.y) > maxDist then if math.abs(pos.x-playerPos.x) + math.abs(pos.y-playerPos.y) > maxDist then
noPath = noPath + 1
pathfinder()
return false -- too far way return false -- too far way
end end
@ -194,14 +324,23 @@ CaveBot.registerAction("goto", "green", function(value, retries, prev)
if stairs then if stairs then
if math.abs(pos.x-playerPos.x) == 0 and math.abs(pos.y-playerPos.y) <= 0 then if math.abs(pos.x-playerPos.x) == 0 and math.abs(pos.y-playerPos.y) <= 0 then
noPath = 0
return true -- already at position return true -- already at position
end end
elseif math.abs(pos.x-playerPos.x) == 0 and math.abs(pos.y-playerPos.y) <= (precision or 1) then elseif math.abs(pos.x-playerPos.x) == 0 and math.abs(pos.y-playerPos.y) <= (precision or 1) then
noPath = 0
return true -- already at position return true -- already at position
end end
-- check if there's a path to that place, ignore creatures and fields -- check if there's a path to that place, ignore creatures and fields
local path = findPath(playerPos, pos, maxDist, { ignoreNonPathable = true, precision = 1, ignoreCreatures = true, allowUnseen = true, allowOnlyVisibleTiles = false }) local path = findPath(playerPos, pos, maxDist, { ignoreNonPathable = true, precision = 1, ignoreCreatures = true, allowUnseen = true, allowOnlyVisibleTiles = false })
if not path then if not path then
if breakFurniture(pos, storage.extras.machete) then
CaveBot.delay(1000)
retries = 0
return "retry"
end
noPath = noPath + 1
pathfinder()
return false -- there's no way return false -- there's no way
end end
@ -222,27 +361,28 @@ CaveBot.registerAction("goto", "green", function(value, retries, prev)
local hppc = creature:getHealthPercent() local hppc = creature:getHealthPercent()
if creature:isMonster() and (hppc and hppc > 0) and (oldTibia or creature:getType() < 3) then if creature:isMonster() and (hppc and hppc > 0) and (oldTibia or creature:getType() < 3) then
-- real blocking creature can not meet those conditions - ie. it could be player, so just in case check if the next creature is reachable -- real blocking creature can not meet those conditions - ie. it could be player, so just in case check if the next creature is reachable
local path = findPath(playerPos, creature:getPosition(), 20, { ignoreNonPathable = true, precision = 1 }) local path = findPath(playerPos, creature:getPosition(), 7, { ignoreNonPathable = true, precision = 1 })
if path then if path then
foundMonster = true foundMonster = true
attack(creature) if g_game.getAttackingCreature() ~= creature then
attack(creature)
end
g_game.setChaseMode(1) g_game.setChaseMode(1)
CaveBot.setOff() CaveBot.delay(100)
CaveBot.delay(1000) retries = 0 -- reset retries, we are trying to unclog the cavebot
schedule(1000, function() CaveBot.setOn() end) break
end end
end end
end end
end end
end end
nextPos = nil -- reset path
if not foundMonster then if not foundMonster then
foundMonster = false foundMonster = false
return false -- no other way return false -- no other way
end end
end end
-- try to find path, don't ignore creatures, don't ignore fields -- try to find path, don't ignore creatures, don't ignore fields
if not CaveBot.Config.get("ignoreFields") and CaveBot.walkTo(pos, 40) then if not CaveBot.Config.get("ignoreFields") and CaveBot.walkTo(pos, 40) then
return "retry" return "retry"
@ -265,10 +405,14 @@ CaveBot.registerAction("goto", "green", function(value, retries, prev)
end end
if not CaveBot.Config.get("mapClick") and retries >= 5 then if not CaveBot.Config.get("mapClick") and retries >= 5 then
noPath = noPath + 1
pathfinder()
return false return false
end end
if CaveBot.Config.get("skipBlocked") then if CaveBot.Config.get("skipBlocked") then
noPath = noPath + 1
pathfinder()
return false return false
end end
@ -358,4 +502,4 @@ end)
CaveBot.registerAction("npcsay", "#FF55FF", function(value, retries, prev) CaveBot.registerAction("npcsay", "#FF55FF", function(value, retries, prev)
NPC.say(value) NPC.say(value)
return true return true
end) end)

View File

@ -0,0 +1,76 @@
CaveBot.Extensions.BuySupplies = {}
CaveBot.Extensions.BuySupplies.setup = function()
CaveBot.registerAction("BuySupplies", "#C300FF", function(value, retries)
local possibleItems = {}
local val = string.split(value, ",")
local waitVal
if #val == 0 or #val > 2 then
warn("CaveBot[BuySupplies]: incorrect BuySupplies value")
return false
elseif #val == 2 then
waitVal = tonumber(val[2]:trim())
end
local npcName = val[1]:trim()
local npc = getCreatureByName(npcName)
if not npc then
print("CaveBot[BuySupplies]: NPC not found")
return false
end
if not waitVal and #val == 2 then
warn("CaveBot[BuySupplies]: incorrect delay values!")
elseif waitVal and #val == 2 then
delay(waitVal)
end
if retries > 50 then
print("CaveBot[BuySupplies]: Too many tries, can't buy")
return false
end
if not CaveBot.ReachNPC(npcName) then
return "retry"
end
if not NPC.isTrading() then
CaveBot.OpenNpcTrade()
CaveBot.delay(storage.extras.talkDelay*2)
return "retry"
end
-- get items from npc
local npcItems = NPC.getBuyItems()
for i,v in pairs(npcItems) do
table.insert(possibleItems, v.id)
end
for id, values in pairs(Supplies.getItemsData()) do
id = tonumber(id)
if table.find(possibleItems, id) then
local max = values.max
local current = player:getItemsCount(id)
local toBuy = max - current
if toBuy > 0 then
toBuy = math.min(100, toBuy)
NPC.buy(id, math.min(100, toBuy))
print("CaveBot[BuySupplies]: bought " .. toBuy .. "x " .. id)
return "retry"
end
end
end
print("CaveBot[BuySupplies]: bought everything, proceeding")
return true
end)
CaveBot.Editor.registerAction("buysupplies", "buy supplies", {
value="NPC name",
title="Buy Supplies",
description="NPC Name, delay(in ms, optional)",
})
end

View File

@ -207,8 +207,12 @@ CaveBot.gotoNextWaypointInRange = function()
local pos = {x = tonumber(re[1][2]), y = tonumber(re[1][3]), z = tonumber(re[1][4])} local pos = {x = tonumber(re[1][2]), y = tonumber(re[1][3]), z = tonumber(re[1][4])}
if posz() == pos.z then if posz() == pos.z then
if distanceFromPlayer(pos) <= storage.extras.gotoMaxDistance/2 then local maxDist = storage.extras.gotoMaxDistance
return ui.list:focusChild(child) if distanceFromPlayer(pos) <= maxDist then
if findPath(player:getPosition(), pos, maxDist, { ignoreNonPathable = true }) then
ui.list:focusChild(ui.list:getChildByIndex(i-1))
return true
end
end end
end end
end end
@ -224,8 +228,12 @@ CaveBot.gotoNextWaypointInRange = function()
local pos = {x = tonumber(re[1][2]), y = tonumber(re[1][3]), z = tonumber(re[1][4])} local pos = {x = tonumber(re[1][2]), y = tonumber(re[1][3]), z = tonumber(re[1][4])}
if posz() == pos.z then if posz() == pos.z then
if distanceFromPlayer(pos) <= storage.extras.gotoMaxDistance/2 then local maxDist = storage.extras.gotoMaxDistance
return ui.list:focusChild(child) if distanceFromPlayer(pos) <= maxDist then
if findPath(player:getPosition(), pos, maxDist, { ignoreNonPathable = true }) then
ui.list:focusChild(ui.list:getChildByIndex(i-1))
return true
end
end end
end end
end end
@ -433,3 +441,7 @@ CaveBot.save = function()
table.insert(data, {"extensions", json.encode(extension_data, 2)}) table.insert(data, {"extensions", json.encode(extension_data, 2)})
config.save(data) config.save(data)
end end
CaveBotList = function()
return ui.list
end

View File

@ -47,9 +47,9 @@ CaveBot.Extensions.ClearTile.setup = function()
CaveBot.GoTo(tPos, 0) CaveBot.GoTo(tPos, 0)
return "retry" return "retry"
end end
print("CaveBot[ClearTile]: tile clear, proceeding")
return true
end end
print("CaveBot[ClearTile]: tile clear, proceeding")
return true
end end
if not CaveBot.MatchPosition(tPos, 3) then if not CaveBot.MatchPosition(tPos, 3) then
@ -122,7 +122,7 @@ CaveBot.Extensions.ClearTile.setup = function()
CaveBot.Editor.registerAction("cleartile", "clear tile", { CaveBot.Editor.registerAction("cleartile", "clear tile", {
value=function() return posx() .. "," .. posy() .. "," .. posz() end, value=function() return posx() .. "," .. posy() .. "," .. posz() end,
title="position of tile to clear", title="position of tile to clear",
description="tile position (x,y,z), optional true if open doors", description="tile position (x,y,z), doors/stand - optional",
multiline=false multiline=false
}) })
end end

View File

@ -51,6 +51,7 @@ CaveBot.Config.add = function(id, title, defaultValue)
local setter -- sets value local setter -- sets value
if type(defaultValue) == "number" then if type(defaultValue) == "number" then
panel = UI.createWidget("CaveBotConfigNumberValuePanel", CaveBot.Config.ui) panel = UI.createWidget("CaveBotConfigNumberValuePanel", CaveBot.Config.ui)
panel:setId(id)
setter = function(value) setter = function(value)
CaveBot.Config.values[id] = value CaveBot.Config.values[id] = value
panel.value:setText(value, true) panel.value:setText(value, true)
@ -65,6 +66,7 @@ CaveBot.Config.add = function(id, title, defaultValue)
end end
elseif type(defaultValue) == "boolean" then elseif type(defaultValue) == "boolean" then
panel = UI.createWidget("CaveBotConfigBooleanValuePanel", CaveBot.Config.ui) panel = UI.createWidget("CaveBotConfigBooleanValuePanel", CaveBot.Config.ui)
panel:setId(id)
setter = function(value) setter = function(value)
CaveBot.Config.values[id] = value CaveBot.Config.values[id] = value
panel.value:setOn(value, true) panel.value:setOn(value, true)
@ -91,4 +93,19 @@ CaveBot.Config.get = function(id)
return warn("Invalid CaveBot.Config.get, id: " .. id) return warn("Invalid CaveBot.Config.get, id: " .. id)
end end
return CaveBot.Config.values[id] return CaveBot.Config.values[id]
end
CaveBot.Config.set = function(id, value)
local valueType = CaveBot.Config.get(id)
local panel = CaveBot.Config.ui[id]
if valueType == 'boolean' then
CaveBot.Config.values[id] = value
panel.value:setOn(value, true)
CaveBot.save()
else
CaveBot.Config.values[id] = value
panel.value:setText(value, true)
CaveBot.save()
end
end end

View File

@ -89,9 +89,9 @@ CaveBot.Editor.setup = function()
registerAction("delay", { registerAction("delay", {
value="500", value="500",
title="Delay", title="Delay",
description="Delay next action (in milliseconds)", description="Delay next action (in milliseconds),randomness (in percent-optional)",
multiline=false, multiline=false,
validation="^\\s*[0-9]{1,10}\\s*$" validation="^[0-9]{1,10}$|^[0-9]{1,10},[0-9]{1,4}$"
}) })
registerAction("gotolabel", "go to label", { registerAction("gotolabel", "go to label", {
value="labelName", value="labelName",

View File

@ -26,7 +26,7 @@ CaveBot.Extensions.Imbuing.setup = function()
local data = string.split(value, ",") local data = string.split(value, ",")
local ids = {} local ids = {}
if #data == 0 then if #data == 0 and value ~= 'name' then
warn("CaveBot[Imbuing] no items added, proceeding") warn("CaveBot[Imbuing] no items added, proceeding")
reset() reset()
return false return false
@ -35,12 +35,19 @@ CaveBot.Extensions.Imbuing.setup = function()
-- setting of equipment manager so it wont disturb imbuing process -- setting of equipment manager so it wont disturb imbuing process
EquipManager.setOff() EquipManager.setOff()
-- convert to number if value == 'name' then
for i, id in ipairs(data) do local imbuData = AutoImbueTable[player:getName()]
id = tonumber(id) for id, imbues in pairs(imbuData) do
if not table.find(ids, id) then
table.insert(ids, id) table.insert(ids, id)
end end
else
-- convert to number
for i, id in ipairs(data) do
id = tonumber(id)
if not table.find(ids, id) then
table.insert(ids, id)
end
end
end end
-- all items imbued, can proceed -- all items imbued, can proceed
@ -105,8 +112,8 @@ CaveBot.Extensions.Imbuing.setup = function()
end) end)
CaveBot.Editor.registerAction("imbuing", "imbuing", { CaveBot.Editor.registerAction("imbuing", "imbuing", {
value="item id 1, item id 2", value="name",
title="Auto Imbuing", title="Auto Imbuing",
description="insert below item ids to be imbued, separated by comma", description="insert below item ids to be imbued, separated by comma\nor 'name' to load from file",
}) })
end end

View File

@ -43,6 +43,7 @@ CaveBot.Extensions.SellAll.setup = function()
if not NPC.isTrading() then if not NPC.isTrading() then
CaveBot.OpenNpcTrade() CaveBot.OpenNpcTrade()
delay(storage.extras.talkDelay*2) delay(storage.extras.talkDelay*2)
return "retry"
else else
sellAllCap = freecap() sellAllCap = freecap()
end end

View File

@ -0,0 +1,186 @@
CaveBot.Extensions.StandLure = {}
local enable = nil
local function modPos(dir)
local y = 0
local x = 0
if dir == 0 then
y = -1
elseif dir == 1 then
x = 1
elseif dir == 2 then
y = 1
elseif dir == 3 then
x = -1
elseif dir == 4 then
y = -1
x = 1
elseif dir == 5 then
y = 1
x = 1
elseif dir == 6 then
y = 1
x = -1
elseif dir == 7 then
y = -1
x = -1
end
return {x, y}
end
local function reset(delay)
if type(Supplies.hasEnough()) == 'table' then
return
end
delay = delay or 0
CaveBot.delay(delay)
if delay == nil then
enable = nil
end
end
local resetRetries = false
CaveBot.Extensions.StandLure.setup = function()
CaveBot.registerAction(
"rushlure",
"#FF0090",
function(value, retries)
local nextPos = nil
local data = string.split(value, ",")
if not data[1] then
warn("Invalid cavebot lure action value. It should be position (x,y,z), delay(ms) is: " .. value)
return false
end
if type(Supplies.hasEnough()) == 'table' then -- do not execute if no supplies
return false
end
local pos = {x = tonumber(data[1]), y = tonumber(data[2]), z = tonumber(data[3])}
local delayTime = data[4] and tonumber(data[4]) or 1000
if not data[5] then
enable = nil
elseif data[5] == "yes" then
enable = true
else
enable = false
end
delay(100)
if retries > 50 and not resetRetries then
reset()
warn("[Rush Lure] Too many tries, can't reach position")
return false -- can't stand on tile
end
if resetRetries then
resetRetries = false
end
if distanceFromPlayer(pos) > 30 then
reset()
return false -- not reachable
end
local playerPos = player:getPosition()
local pathWithoutMonsters = findPath(playerPos, pos, 30, { ignoreFields = true, ignoreNonPathable = true, ignoreCreatures = true, precision = 0})
local pathWithMonsters = findPath(playerPos, pos, maxDist, { ignoreFields = true, ignoreNonPathable = true, ignoreCreatures = false, precision = 0 })
if not pathWithoutMonsters then
reset()
warn("[Rush Lure] No possible path to reach position, skipping.")
return false -- spot is unreachable
elseif pathWithoutMonsters and not pathWithMonsters then
local foundMonster = false
for i, dir in ipairs(pathWithoutMonsters) do
local dirs = modPos(dir)
nextPos = nextPos or playerPos
nextPos.x = nextPos.x + dirs[1]
nextPos.y = nextPos.y + dirs[2]
local tile = g_map.getTile(nextPos)
if tile then
if tile:hasCreature() then
local creature = tile:getCreatures()[1]
local hppc = creature:getHealthPercent()
if creature:isMonster() and (hppc and hppc > 0) and (oldTibia or creature:getType() < 3) then
-- real blocking creature can not meet those conditions - ie. it could be player, so just in case check if the next creature is reachable
local path = findPath(playerPos, creature:getPosition(), 7, { ignoreNonPathable = true, precision = 1 })
if path then
creature:setMarked('#00FF00')
if g_game.getAttackingCreature() ~= creature then
attack(creature)
end
g_game.setChaseMode(1)
resetRetries = true -- reset retries, we are trying to unclog the cavebot
delay(100)
return "retry"
end
end
end
end
end
if not g_game.getAttackingCreature() then
reset()
warn("[Rush Lure] No path, no blocking monster, skipping.")
return false -- no other way
end
end
-- reaching position, delay targetbot in process
if not CaveBot.MatchPosition(pos, 0) then
TargetBot.delay(300)
CaveBot.walkTo(pos, 30, { ignoreCreatures = false, ignoreFields = true, ignoreNonPathable = true, precision = 0})
delay(100)
resetRetries = true
return "retry"
end
TargetBot.setOn()
reset(delayTime)
return true
end
)
CaveBot.Editor.registerAction(
"rushlure",
"rush lure",
{
value = function()
return posx() .. "," .. posy() .. "," .. posz() .. ",1000"
end,
title = "Stand Lure",
description = "Run to position(x,y,z), delay(ms), targetbot on/off (yes/no)",
multiline = false,
validation = [[\d{1,5},\d{1,5},\d{1,2},\d{1,5}(?:,(yes|no)$|$)]]
}
)
end
local next = false
schedule(5, function() -- delay because cavebot.lua is loaded after this file
modules.game_bot.connect(CaveBotList(), {
onChildFocusChange = function(widget, newChild, oldChild)
if oldChild and oldChild.action == "rushlure" then
next = true
return
end
if next then
if enable then
TargetBot.setOn()
elseif enable == false then
TargetBot.setOff()
end
enable = nil -- reset
next = false
end
end})
end)

View File

@ -0,0 +1,137 @@
CaveBot.Extensions.SupplyCheck = {}
local supplyRetries = 0
local missedChecks = 0
local rawRound = 0
local time = now
vBot.CaveBotData =
vBot.CaveBotData or
{
refills = 0,
rounds = 0,
time = {},
lastRefill = os.time(),
refillTime = {}
}
local function setCaveBotData(hunting)
if hunting then
supplyRetries = supplyRetries + 1
else
supplyRetries = 0
table.insert(vBot.CaveBotData.refillTime, os.difftime(os.time() - vBot.CaveBotData.lastRefill))
vBot.CaveBotData.lastRefill = os.time()
vBot.CaveBotData.refills = vBot.CaveBotData.refills + 1
end
table.insert(vBot.CaveBotData.time, rawRound)
vBot.CaveBotData.rounds = vBot.CaveBotData.rounds + 1
missedChecks = 0
end
CaveBot.Extensions.SupplyCheck.setup = function()
CaveBot.registerAction(
"supplyCheck",
"#db5a5a",
function(value)
local data = string.split(value, ",")
local round = 0
rawRound = 0
local label = data[1]:trim()
local pos = nil
if #data == 4 then
pos = {x = tonumber(data[2]), y = tonumber(data[3]), z = tonumber(data[4])}
end
if pos then
if missedChecks >= 4 then
missedChecks = 0
supplyRetries = 0
print("CaveBot[SupplyCheck]: Missed 5 supply checks, proceeding with waypoints")
return true
end
if getDistanceBetween(player:getPosition(), pos) > 10 then
missedChecks = missedChecks + 1
print("CaveBot[SupplyCheck]: Missed supply check! " .. 5 - missedChecks .. " tries left before skipping.")
return CaveBot.gotoLabel(label)
end
end
if time then
rawRound = math.ceil((now - time) / 1000)
round = rawRound .. "s"
else
round = ""
end
time = now
local softCount = itemAmount(6529) + itemAmount(3549)
local supplyData = Supplies.hasEnough()
local supplyInfo = Supplies.getAdditionalData()
if storage.caveBot.forceRefill then
print("CaveBot[SupplyCheck]: User forced, going back on refill. Last round took: " .. round)
storage.caveBot.forceRefill = false
supplyRetries = 0
missedChecks = 0
return false
elseif storage.caveBot.backStop then
print("CaveBot[SupplyCheck]: User forced, going back to city and turning off CaveBot. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif storage.caveBot.backTrainers then
print("CaveBot[SupplyCheck]: User forced, going back to city, then on trainers. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif storage.caveBot.backOffline then
print("CaveBot[SupplyCheck]: User forced, going back to city, then on offline training. Last round took: " .. round)
supplyRetries = 0
missedChecks = 0
return false
elseif supplyRetries > (storage.extras.huntRoutes or 50) then
print("CaveBot[SupplyCheck]: Round limit reached, going back on refill. Last round took: " .. round)
setCaveBotData()
return false
elseif (supplyInfo.imbues.enabled and player:getSkillLevel(11) == 0) then
print("CaveBot[SupplyCheck]: Imbues ran out. Going on refill. Last round took: " .. round)
setCaveBotData()
return false
elseif (supplyInfo.stamina.enabled and stamina() < tonumber(supplyInfo.stamina.value)) then
print("CaveBot[SupplyCheck]: Stamina ran out. Going on refill. Last round took: " .. round)
setCaveBotData()
return false
elseif (supplyInfo.softBoots.enabled and softCount < 1) then
print("CaveBot[SupplyCheck]: No soft boots left. Going on refill. Last round took: " .. round)
setCaveBotData()
return false
elseif type(supplyData) == "table" then
print("CaveBot[SupplyCheck]: Not enough item: " .. supplyData.id .. "(only " .. supplyData.amount .. " left). Going on refill. Last round took: " .. round)
setCaveBotData()
return false
elseif (supplyInfo.capacity.enabled and freecap() < tonumber(supplyInfo.capacity.value)) then
print("CaveBot[SupplyCheck]: Not enough capacity. Going on refill. Last round took: " .. round)
setCaveBotData()
return false
else
print("CaveBot[SupplyCheck]: Enough supplies. Hunting. Round (" .. supplyRetries .. "/" .. (storage.extras.huntRoutes or 50) .. "). Last round took: " .. round)
setCaveBotData(true)
return CaveBot.gotoLabel(label)
end
end
)
CaveBot.Editor.registerAction(
"supplycheck",
"supply check",
{
value = function()
return "startHunt," .. posx() .. "," .. posy() .. "," .. posz()
end,
title = "Supply check label",
description = "Insert here hunting start label",
validation = [[[^,]+,\d{1,5},\d{1,5},\d{1,2}$]]
}
)
end

View File

@ -161,9 +161,8 @@ TargetBot.Looting.process = function(targets, dangerLevel)
end end
g_game.open(container) g_game.open(container)
waitTill = now + 1000 -- give it 1s to open waitTill = now + math.min(g_game.getPing(),100)
waitingForContainer = container:getId() waitingForContainer = container:getId()
loot.tries = loot.tries + 10
return true return true
end end

View File

@ -256,7 +256,7 @@ Panel
macro(50, function() macro(50, function()
if not config.enabled then return end if not config.enabled then return end
if (not config.ignoreInPz or not isInPz()) and config.holdUtamo and mana() >= config.utamoCost and not hasManaShield() then say("utamo vita") if (not config.ignoreInPz or not isInPz()) and config.holdUtamo and mana() >= config.utamoCost and not hasManaShield() then say("utamo vita")
elseif (not config.ignoreInPz or not isInPz()) and standTime() < 5000 and config.holdHaste and mana() >= config.hasteCost and not hasHaste() and not getSpellCoolDown(config.hasteSpell) and (not target() or not config.stopHaste or TargetBot.isCaveBotActionAllowed()) then say(config.hasteSpell) elseif ((not config.ignoreInPz or not isInPz()) and standTime() < 5000 and config.holdHaste and mana() >= config.hasteCost and not hasHaste() and not getSpellCoolDown(config.hasteSpell) and (not target() or not config.stopHaste or TargetBot.isCaveBotActionAllowed())) and standTime() < 3000 then say(config.hasteSpell)
elseif config.cureParalyse and mana() >= config.paralyseCost and isParalyzed() and not getSpellCoolDown(config.paralyseSpell) then say(config.paralyseSpell) elseif config.cureParalyse and mana() >= config.paralyseCost and isParalyzed() and not getSpellCoolDown(config.paralyseSpell) then say(config.paralyseSpell)
end end
end) end)

View File

@ -40,17 +40,27 @@ end
local config = storage[panelName] local config = storage[panelName]
UI.Separator()
local renameContui = setupUI([[ local renameContui = setupUI([[
Panel Panel
height: 38 height: 50
Label
text-align: center
text: Container Panel
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
font: verdana-11px-rounded
BotSwitch BotSwitch
id: title id: title
anchors.top: parent.top anchors.top: prev.bottom
anchors.left: parent.left anchors.left: parent.left
text-align: center text-align: center
width: 130 width: 130
!text: tr('Minimise Containers') !text: tr('Open Minimised')
font: verdana-11px-rounded
Button Button
id: editContList id: editContList
@ -60,16 +70,28 @@ Panel
margin-left: 3 margin-left: 3
height: 17 height: 17
text: Setup text: Setup
font: verdana-11px-rounded
Button Button
id: reopenCont id: reopenCont
!text: tr('Reopen Containers') !text: tr('Reopen All')
anchors.left: parent.left anchors.left: parent.left
anchors.top: prev.bottom anchors.top: prev.bottom
anchors.right: parent.right anchors.right: parent.horizontalCenter
margin-right: 2
height: 17 height: 17
margin-top: 3 margin-top: 3
font: verdana-11px-rounded
Button
id: minimiseCont
!text: tr('Minimise All')
anchors.top: prev.top
anchors.left: parent.horizontalCenter
anchors.right: parent.right
margin-right: 2
height: 17
font: verdana-11px-rounded
]]) ]])
renameContui:setId(panelName) renameContui:setId(panelName)
@ -378,6 +400,13 @@ if rootWidget then
reopenBackpacks() reopenBackpacks()
end end
renameContui.minimiseCont.onClick = function(widget)
for i, container in ipairs(getContainers()) do
local containerWindow = container.window
containerWindow:setContentHeight(34)
end
end
renameContui.title:setOn(config.enabled) renameContui.title:setOn(config.enabled)
renameContui.title.onClick = function(widget) renameContui.title.onClick = function(widget)
config.enabled = not config.enabled config.enabled = not config.enabled
@ -569,7 +598,7 @@ local function properTable(t)
return r return r
end end
macro(500, function() local mainLoop = macro(150, function(macro)
if not config.sort and not config.purse then return end if not config.sort and not config.purse then return end
local storageVal = config.list local storageVal = config.list
@ -622,5 +651,24 @@ macro(500, function()
return use(getPurse()) return use(getPurse())
end end
end end
delay(1500) macro:setOff()
end)
onContainerOpen(function(container, previousContainer)
mainLoop:setOn()
end)
onAddItem(function(container, slot, item, oldItem)
mainLoop:setOn()
end)
onPlayerInventoryChange(function(slot, item, oldItem)
mainLoop:setOn()
end)
onContainerClose(function(container)
if not container.lootContainer then
mainLoop:setOn()
end
end) end)

View File

@ -22,10 +22,11 @@ Panel
]]) ]])
ui:setId(panelName) ui:setId(panelName)
if not storage[panelName] then if not storage[panelName] or not storage[panelName].bosses then -- no bosses - old ver
storage[panelName] = { storage[panelName] = {
enabled = false, enabled = false,
rules = {} rules = {},
bosses = {}
} }
end end
@ -52,7 +53,8 @@ local conditions = { -- always add new conditions at the bottom
"Players around is more than:", -- spinbox 12 "Players around is more than:", -- spinbox 12
"Players around is less than:", -- spinbox 13 "Players around is less than:", -- spinbox 13
"TargetBot Danger is Above:", -- spinbox 14 "TargetBot Danger is Above:", -- spinbox 14
"Blacklist player in range (sqm)" -- spinbox 15 "Blacklist player in range (sqm)", -- spinbox 15
"Target is Boss" -- nothing
} }
local conditionNumber = 1 local conditionNumber = 1
@ -67,39 +69,13 @@ ui.setup.onClick = function()
mainWindow:focus() mainWindow:focus()
end end
mainWindow.closeButton.onClick = function()
mainWindow:hide()
resetFields()
end
local inputPanel = mainWindow.inputPanel local inputPanel = mainWindow.inputPanel
local listPanel = mainWindow.listPanel local listPanel = mainWindow.listPanel
local namePanel = mainWindow.profileName
local eqPanel = mainWindow.setup
local bossPanel = mainWindow.bossPanel
inputPanel.optionalCondition:hide() local slotWidgets = {eqPanel.head, eqPanel.body, eqPanel.legs, eqPanel.feet, eqPanel.neck, eqPanel["left-hand"], eqPanel["right-hand"], eqPanel.finger, eqPanel.ammo} -- back is disabled
inputPanel.useSecondCondition.onOptionChange = function(widget, option, data)
if option ~= "-" then
inputPanel.optionalCondition:show()
else
inputPanel.optionalCondition:hide()
end
end
inputPanel.unequip.onClick = function()
local value = 115
local panel = inputPanel.unequipPanel
local height = panel:getHeight()
if height == 0 then
panel:setHeight(value)
mainWindow:setHeight(mainWindow:getHeight()+value)
inputPanel:setHeight(inputPanel:getHeight()+value)
listPanel:setHeight(listPanel:getHeight()+value)
else
panel:setHeight(0)
mainWindow:setHeight(mainWindow:getHeight()-value)
inputPanel:setHeight(inputPanel:getHeight()-value)
listPanel:setHeight(listPanel:getHeight()-value)
end
end
local function setCondition(first, n) local function setCondition(first, n)
local widget local widget
@ -120,7 +96,7 @@ local function setCondition(first, n)
spinBox:setValue(0) spinBox:setValue(0)
textEdit:setText('') textEdit:setText('')
if n == 1 or n == 10 or n == 11 then if n == 1 or n == 10 or n == 11 or n == 16 then
spinBox:hide() spinBox:hide()
textEdit:hide() textEdit:hide()
elseif n == 9 or n == 8 then elseif n == 9 or n == 8 then
@ -138,6 +114,46 @@ local function setCondition(first, n)
widget:setText(conditions[n]) widget:setText(conditions[n])
end end
local function resetFields()
conditionNumber = 1
optionalConditionNumber = 2
setCondition(false, optionalConditionNumber)
setCondition(true, conditionNumber)
for i, widget in ipairs(slotWidgets) do
widget:setItemId(0)
widget:setChecked(false)
end
for i, child in ipairs(listPanel.list:getChildren()) do
child.display = false
end
namePanel.profileName:setText("")
inputPanel.condition.text:setText('')
inputPanel.condition.spinbox:setValue(0)
inputPanel.useSecondCondition:setText('-')
inputPanel.optionalCondition.text:setText('')
inputPanel.optionalCondition.spinbox:setValue(0)
inputPanel.optionalCondition:hide()
bossPanel:hide()
listPanel:show()
mainWindow.bossList:setText('Boss List')
bossPanel.name:setText('')
end
resetFields()
mainWindow.closeButton.onClick = function()
resetFields()
mainWindow:hide()
end
inputPanel.optionalCondition:hide()
inputPanel.useSecondCondition.onOptionChange = function(widget, option, data)
if option ~= "-" then
inputPanel.optionalCondition:show()
else
inputPanel.optionalCondition:hide()
end
end
-- add default text & windows -- add default text & windows
setCondition(true, 1) setCondition(true, 1)
setCondition(false, 2) setCondition(false, 2)
@ -253,100 +269,105 @@ listPanel.down.onClick = function(widget)
listPanel.up:setEnabled(true) listPanel.up:setEnabled(true)
listPanel.list:moveChildToIndex(focused, n+1) listPanel.list:moveChildToIndex(focused, n+1)
listPanel.list:ensureChildVisible(focused) listPanel.list:ensureChildVisible(focused)
end
function getItemsFromBox()
local t = {}
for i, child in ipairs(inputPanel.itemBox:getChildren()) do
local id = child:getItemId()
if id > 100 then
table.insert(t, id)
end
end
return t
end end
function refreshItemBox(reset) eqPanel.cloneEq.onClick = function(widget)
local max = 8 eqPanel.head:setItemId(getHead() and getHead():getId() or 0)
local box = inputPanel.itemBox eqPanel.body:setItemId(getBody() and getBody():getId() or 0)
local childAmount = box:getChildCount() eqPanel.legs:setItemId(getLeg() and getLeg():getId() or 0)
eqPanel.feet:setItemId(getFeet() and getFeet():getId() or 0)
--height eqPanel.neck:setItemId(getNeck() and getNeck():getId() or 0)
if #getItemsFromBox() < 7 then eqPanel["left-hand"]:setItemId(getLeft() and getLeft():getId() or 0)
mainWindow:setHeight(345) eqPanel["right-hand"]:setItemId(getRight() and getRight():getId() or 0)
inputPanel:setHeight(265) eqPanel.finger:setItemId(getFinger() and getFinger():getId() or 0)
listPanel:setHeight(265) eqPanel.ammo:setItemId(getAmmo() and getAmmo():getId() or 0)
box:setHeight(40)
else
mainWindow:setHeight(370)
inputPanel:setHeight(300)
listPanel:setHeight(300)
box:setHeight(80)
end
if reset then
box:destroyChildren()
local widget = UI.createWidget("BotItem", box)
widget.onItemChange = function(widget)
local id = widget:getItemId()
local index = box:getChildIndex(widget)
if id < 100 or (table.find(getItemsFromBox(), id) ~= index) then
widget:destroy()
end
refreshItemBox()
end
return
end
if childAmount == 0 then
local widget = UI.createWidget("BotItem", box)
widget.onItemChange = function(widget)
local id = widget:getItemId()
local index = box:getChildIndex(widget)
if id < 100 or (table.find(getItemsFromBox(), id) ~= index) then
widget:destroy()
end
refreshItemBox()
end
elseif box:getLastChild():getItemId() > 100 and childAmount <= max then
local widget = UI.createWidget("BotItem", box)
widget.onItemChange = function(widget)
local id = widget:getItemId()
local index = box:getChildIndex(widget)
if id < 100 or (table.find(getItemsFromBox(), id) ~= index) then
widget:destroy()
end
refreshItemBox()
end
end
end end
refreshItemBox()
local function resetFields() eqPanel.default.onClick = resetFields
refreshItemBox(true)
inputPanel.name:setText('')
conditionNumber = 1
optionalConditionNumber = 2
setCondition(false, optionalConditionNumber)
setCondition(true, conditionNumber)
inputPanel.useSecondCondition:setCurrentOption("-")
for i, child in pairs(inputPanel.unequipPanel:getChildren()) do
child:setChecked(false)
end
end
-- buttons disabled by default -- buttons disabled by default
listPanel.up:setEnabled(false) listPanel.up:setEnabled(false)
listPanel.down:setEnabled(false) listPanel.down:setEnabled(false)
function refreshRules()
-- correct background image
for i, widget in ipairs(slotWidgets) do
widget:setTooltip("Right click to set as slot to unequip")
widget.onItemChange = function(widget)
local selfId = widget:getItemId()
widget:setOn(selfId > 100)
if widget:isChecked() then
widget:setChecked(selfId < 100)
end
end
widget.onMouseRelease = function(widget, mousePos, mouseButton)
if mouseButton == 2 then
local clearItem = widget:isChecked() == false
widget:setChecked(not widget:isChecked())
if clearItem then
widget:setItemId(0)
end
end
end
end
inputPanel.condition.description.onMouseWheel = function(widget, mousePos, scroll)
if scroll == 1 then
inputPanel.condition.nex.onClick()
else
inputPanel.condition.pre.onClick()
end
end
inputPanel.optionalCondition.description.onMouseWheel = function(widget, mousePos, scroll)
if scroll == 1 then
inputPanel.optionalCondition.nex.onClick()
else
inputPanel.optionalCondition.pre.onClick()
end
end
namePanel.profileName.onTextChange = function(widget, text)
local button = inputPanel.add
text = text:lower()
for i, child in ipairs(listPanel.list:getChildren()) do
local name = child:getText():lower()
button:setText(name == text and "Overwrite" or "Add Rule")
button:setTooltip(name == text and "Overwrite existing rule named: "..name, "Add new rule to the list: "..name)
end
end
local function setupPreview(display, data)
namePanel.profileName:setText('')
if not display then
resetFields()
else
for i, value in ipairs(data) do
local widget = slotWidgets[i]
if value == false then
widget:setChecked(false)
widget:setItemId(0)
elseif value == true then
widget:setChecked(true)
widget:setItemId(0)
else
widget:setChecked(false)
widget:setItemId(value)
end
end
end
end
local function refreshRules()
local list = listPanel.list local list = listPanel.list
list:destroyChildren() list:destroyChildren()
for i,v in pairs(config.rules) do for i,v in ipairs(config.rules) do
local widget = UI.createWidget('Rule', list) local widget = UI.createWidget('Rule', list)
widget:setId(v.name) widget:setId(v.name)
widget:setText(v.name) widget:setText(v.name)
widget.ruleData = v
widget.remove.onClick = function() widget.remove.onClick = function()
widget:destroy() widget:destroy()
table.remove(config.rules, table.find(config.rules, v)) table.remove(config.rules, table.find(config.rules, v))
@ -364,15 +385,35 @@ function refreshRules()
v.enabled = not v.enabled v.enabled = not v.enabled
widget.enabled:setChecked(v.enabled) widget.enabled:setChecked(v.enabled)
end end
local desc widget.onHoverChange = function(widget, hover)
for i, v in ipairs(v.items) do for i, child in ipairs(list:getChildren()) do
if i == 1 then if child.display then return end
desc = "items: " .. v end
else setupPreview(hover, widget.ruleData.data)
desc = desc .. ", " .. v end
widget.onDoubleClick = function(widget)
local ruleData = widget.ruleData
widget.display = true
setupPreview(true, ruleData.data)
conditionNumber = ruleData.mainCondition
optionalConditionNumber = ruleData.optionalCondition
setCondition(false, optionalConditionNumber)
setCondition(true, conditionNumber)
inputPanel.useSecondCondition:setOption(ruleData.relation)
namePanel.profileName:setText(v.name)
if type(ruleData.mainValue) == "string" then
inputPanel.condition.text:setText(ruleData.mainValue)
elseif type(ruleData.mainValue) == "number" then
inputPanel.condition.spinbox:setValue(ruleData.mainValue)
end
if type(ruleData.optValue) == "string" then
inputPanel.optionalCondition.text:setText(ruleData.optValue)
elseif type(ruleData.optValue) == "number" then
inputPanel.optionalCondition.spinbox:setValue(ruleData.optValue)
end end
end end
widget:setTooltip(desc)
widget.onClick = function() widget.onClick = function()
local panel = listPanel local panel = listPanel
if #panel.list:getChildren() == 1 then if #panel.list:getChildren() == 1 then
@ -389,74 +430,30 @@ function refreshRules()
panel.down:setEnabled(true) panel.down:setEnabled(true)
end end
end end
widget.onDoubleClick = function()
-- main
conditionNumber = v.mainCondition
setCondition(true, conditionNumber)
if conditionNumber == 8 or conditionNumber == 9 then
inputPanel.condition.text:setText(v.mainValue)
elseif conditionNumber ~= 1 then
inputPanel.condition.spinbox:setValue(v.mainValue)
end
-- relation
inputPanel.useSecondCondition:setCurrentOption(v.relation)
-- optional
if v.relation ~= "-" then
optionalConditionNumber = v.optionalCondition
setCondition(false, optionalConditionNumber)
if optionalConditionNumber == 8 or optionalConditionNumber == 9 then
inputPanel.optionalCondition.text:setText(v.optValue)
elseif optionalConditionNumber ~= 1 then
inputPanel.optionalCondition.spinbox:setValue(v.optValue)
end
end
-- name
inputPanel.name:setText(v.name)
-- items
inputPanel.itemBox:destroyChildren()
for i, item in ipairs(v.items) do
local widget = UI.createWidget("BotItem", inputPanel.itemBox)
widget:setItemId(item)
widget.onItemChange = function(widget)
local id = widget:getItemId()
local index = box:getChildIndex(widget)
if id < 100 or (table.find(getItemsFromBox(), id) ~= index) then
widget:destroy()
end
refreshItemBox()
end
end
-- unequip
if type(v.unequip) == "table" then
for i, tick in ipairs(v.unequip) do
local checkbox = inputPanel.unequipPanel:getChildren()[i]
checkbox:setChecked(tick)
end
end
refreshItemBox()
-- remove value
table.remove(config.rules, table.find(config.rules, v))
refreshRules()
end
end end
end end
refreshRules() refreshRules()
inputPanel.addButton.onClick = function() inputPanel.add.onClick = function(widget)
local mainVal local mainVal
local optVal local optVal
local t = {}
local relation = inputPanel.useSecondCondition:getText() local relation = inputPanel.useSecondCondition:getText()
local name = inputPanel.name:getText() local profileName = namePanel.profileName:getText()
local items = getItemsFromBox() if profileName:len() == 0 then
local unequip = {} return warn("Please fill profile name!")
local hasUnequip = false end
for i, child in pairs(inputPanel.unequipPanel:getChildren()) do for i, widget in ipairs(slotWidgets) do
if child:isChecked() then local checked = widget:isChecked()
table.insert(unequip, true) local id = widget:getItemId()
hasUnequip = true
if checked then
table.insert(t, true) -- unequip selected slot
elseif id then
table.insert(t, id) -- equip selected item
else else
table.insert(unequip, false) table.insert(t, false) -- ignore slot
end end
end end
@ -494,21 +491,16 @@ inputPanel.addButton.onClick = function()
end end
end end
if #items == 0 and not hasUnequip then local index
return warn("[vBot Equipper] Please add items or select unequip slots.") for i, v in ipairs(config.rules) do
end if v.name == profileName then
index = i -- search if there's already rule with this name
if #name == 0 then
return warn("[vBot Equipper] Please fill name of the profile.")
end
for i, child in pairs(listPanel.list:getChildren()) do
if child:getText() == name then
return warn("[vBot Equipper] There is already rule with this name! Choose different or remove old one.")
end end
end end
-- add local ruleData = {
table.insert(config.rules, { name = profileName,
data = t,
enabled = true, enabled = true,
visible = true, visible = true,
mainCondition = conditionNumber, mainCondition = conditionNumber,
@ -516,37 +508,63 @@ inputPanel.addButton.onClick = function()
mainValue = mainVal, mainValue = mainVal,
optValue = optVal, optValue = optVal,
relation = relation, relation = relation,
items = items, }
name = name,
unequip = unequip
})
refreshRules() if index then
config.rules[index] = ruleData -- overwrite
else
table.insert(config.rules, ruleData) -- create new one
end
for i, child in ipairs(listPanel.list:getChildren()) do
child.display = false
end
resetFields() resetFields()
refreshRules()
end end
--"Item is available and not worn.", -- nothing 1 mainWindow.bossList.onClick = function(widget)
--"Monsters around is more than: ", -- spinbox 2 if bossPanel:isVisible() then
--"Monsters around is less than: ", -- spinbox 3 bossPanel:hide()
--"Health precent is below:", -- spinbox 4 listPanel:show()
--"Health precent is above:", -- spinbox 5 widget:setText('Boss List')
--"Mana precent is below:", -- spinbox 6 else
--"Mana precent is above:", -- spinbox 7 bossPanel:show()
--"Target name is:", -- BotTextEdit 8 listPanel:hide()
--"Hotkey is being pressed:", -- Button 9 widget:setText('Rule List')
--"Player is paralyzed", -- nothing 10
local pressedKey = "" end
local lastPress = now end
onKeyPress(function(keys)
pressedKey = keys -- create boss labels
lastPress = now for i, v in ipairs(config.bosses) do
schedule(100, function() local widget = UI.createWidget("BossLabel", bossPanel.list)
if now - lastPress > 20 then widget:setText(v)
pressedKey = "" widget.remove.onClick = function()
end table.remove(config.bosses, table.find(config.bosses, v))
end) widget:destroy()
end) end
end
bossPanel.add.onClick = function()
local name = bossPanel.name:getText()
if name:len() == 0 then
return warn("[Equipped] Please enter boss name!")
elseif table.find(config.bosses, name:lower(), true) then
return warn("[Equipper] Boss already added!")
end
local widget = UI.createWidget("BossLabel", bossPanel.list)
widget:setText(name)
widget.remove.onClick = function()
table.remove(config.bosses, table.find(config.bosses, name))
widget:destroy()
end
table.insert(config.bosses, name)
bossPanel.name:setText('')
end
local function interpreteCondition(n, v) local function interpreteCondition(n, v)
@ -567,7 +585,7 @@ local function interpreteCondition(n, v)
elseif n == 8 then elseif n == 8 then
return target() and target():getName():lower() == v:lower() or false return target() and target():getName():lower() == v:lower() or false
elseif n == 9 then elseif n == 9 then
return pressedKey == v return g_keyboard.isKeyPressed(v)
elseif n == 10 then elseif n == 10 then
return isParalyzed() return isParalyzed()
elseif n == 11 then elseif n == 11 then
@ -580,6 +598,8 @@ local function interpreteCondition(n, v)
return TargetBot.Danger() > v and TargetBot.isOn() return TargetBot.Danger() > v and TargetBot.isOn()
elseif n == 15 then elseif n == 15 then
return isBlackListedPlayerInRange(v) return isBlackListedPlayerInRange(v)
elseif n == 16 then
return target() and table.find(config.bosses, target():getName():lower(), true) and true or false
end end
end end
@ -607,73 +627,144 @@ local function isEquipped(id)
end end
local function unequipItem(table) local function unequipItem(table)
--[[ local slots = {getHead(), getBody(), getLeg(), getFeet(), getNeck(), getLeft(), getRight(), getFinger(), getAmmo()}
head
neck
torso
left
right
legs
finger
ammo slot
boots
]]
local slots = {getHead(), getNeck(), getBody(), getLeft(), getRight(), getLeg(), getFinger(), getAmmo(), getFeet()}
if type(table) ~= "table" then return end if type(table) ~= "table" then return end
for i, slot in pairs(table) do for i, slot in ipairs(table) do
local physicalSlot = slots[i] local physicalSlot = slots[i]
if slot and physicalSlot then if slot == true and physicalSlot then
g_game.equipItemId(physicalSlot:getId()) local id = physicalSlot:getId()
if g_game.getClientVersion() >= 910 then
-- new tibia
g_game.equipItemId(id)
else
-- old tibia
local dest
for i, container in ipairs(getContainers()) do
local cname = container:getName()
if not containerIsFull(container) then
if not cname:find("loot") and (cname:find("backpack") or cname:find("bag") or cname:find("chess")) then
dest = container
end
break
end
end
if not dest then return true end
local pos = dest:getSlotPosition(dest:getItemsCount())
g_game.move(physicalSlot, pos, physicalSlot:getCount())
end
return true return true
end end
end end
return false return false
end end
local function equipItem(id, slot)
-- need to correct slots...
if slot == 2 then
slot = 4
elseif slot == 3 then
slot = 7
elseif slot == 8 then
slot = 9
elseif slot == 5 then
slot = 2
elseif slot == 4 then
slot = 8
elseif slot == 9 then
slot = 10
elseif slot == 7 then
slot = 5
end
if g_game.getClientVersion() >= 910 then
-- new tibia
return g_game.equipItemId(id)
else
-- old tibia
local item = findItem(id)
return moveToSlot(item, slot)
end
end
local function markChild(child)
if mainWindow:isVisible() then
for i, child in ipairs(listPanel.list:getChildren()) do
if child ~= widget then
child:setColor('white')
end
end
widget:setColor('green')
end
end
local missingItem = false
local lastRule = false
local correctEq = false
EquipManager = macro(50, function() EquipManager = macro(50, function()
if not config.enabled then return end if not config.enabled then return end
if #config.rules == 0 then return end if #config.rules == 0 then return end
for i, rule in ipairs(config.rules) do for i, widget in ipairs(listPanel.list:getChildren()) do
local widget = listPanel.list:getChildById(rule.name) local rule = widget.ruleData
if mainWindow:isVisible() then
for i, child in ipairs(listPanel.list:getChildren()) do
if child ~= widget then
child:setColor('white')
end
end
end
if rule.enabled then if rule.enabled then
widget:setColor('green')
-- conditions
local firstCondition = interpreteCondition(rule.mainCondition, rule.mainValue) local firstCondition = interpreteCondition(rule.mainCondition, rule.mainValue)
local optionalCondition = nil local optionalCondition = nil
if rule.relation ~= "-" then if rule.relation ~= "-" then
optionalCondition = interpreteCondition(rule.optionalCondition, rule.optValue) optionalCondition = interpreteCondition(rule.optionalCondition, rule.optValue)
end end
-- checks
if finalCheck(firstCondition, rule.relation, optionalCondition) then if finalCheck(firstCondition, rule.relation, optionalCondition) then
if unequipItem(rule.unequip) == true then
-- performance edits, loop reset
local resetLoop = not missingItem and correctEq and lastRule == rule
if resetLoop then return end
-- reset executed rule
-- first check unequip
if unequipItem(rule.data) == true then
delay(200) delay(200)
return return
end end
for i, item in ipairs(rule.items) do
if not isEquipped(item) then -- equiploop
if rule.visible then for slot, item in ipairs(rule.data) do
if itemAmount(item) > 0 then if type(item) == "number" and item > 100 then
if not isEquipped(item) then
if rule.visible then
if findItem(item) then
missingItem = false
delay(200)
return equipItem(item, slot)
else
missingItem = true
end
else
missingItem = false
delay(200) delay(200)
return g_game.equipItemId(item) return equipItem(item, slot)
end end
else
delay(200)
return g_game.equipItemId(item)
end end
end end
end end
correctEq = not missingItem and true or false
-- even if nothing was done, exit function to hold rule
return return
end end
end end
end end
pressedKey = ""
end) end)

View File

@ -1,5 +1,5 @@
--[[ --[[
Bot-based Tibia 12 features v1.0 Bot-based Tibia 12 features v1.1
made by Vithrax made by Vithrax
Credits also to: Credits also to:
@ -11,7 +11,13 @@
br, Vithrax br, Vithrax
]] ]]
vBot.CaveBotData = vBot.CaveBotData or {
refills = 0,
rounds = 0,
time = {},
lastRefill = os.time(),
refillTime = {}
}
local lootWorth = 0 local lootWorth = 0
local wasteWorth = 0 local wasteWorth = 0
local balance = 0 local balance = 0
@ -58,8 +64,18 @@ storage.analyzers.trackedLoot = storage.analyzers.trackedLoot or {}
local trackedLoot = storage.analyzers.trackedLoot local trackedLoot = storage.analyzers.trackedLoot
--destroy old windows --destroy old windows
local windowsTable = {"MainAnalyzerWindow", "HuntingAnalyzerWindow", "LootAnalyzerWindow", "SupplyAnalyzerWindow", "ImpactAnalyzerWindow", "XPAnalyzerWindow", "PartyAnalyzerWindow", "DropTracker"} local windowsTable = {"MainAnalyzerWindow",
for i, window in ipairs(windowsTable) do "HuntingAnalyzerWindow",
"LootAnalyzerWindow",
"SupplyAnalyzerWindow",
"ImpactAnalyzerWindow",
"XPAnalyzerWindow",
"PartyAnalyzerWindow",
"DropTracker",
"CaveBotStats"
}
for i, window in ipairs(windowsTable) do
local element = g_ui.getRootWidget():recursiveGetChildById(window) local element = g_ui.getRootWidget():recursiveGetChildById(window)
if element then if element then
@ -69,7 +85,7 @@ end
local mainWindow = UI.createMiniWindow("MainAnalyzerWindow") local mainWindow = UI.createMiniWindow("MainAnalyzerWindow")
mainWindow:hide() mainWindow:hide()
mainWindow:setContentMaximumHeight(220) mainWindow:setContentMaximumHeight(240)
local huntingWindow = UI.createMiniWindow("HuntingAnalyzer") local huntingWindow = UI.createMiniWindow("HuntingAnalyzer")
huntingWindow:hide() huntingWindow:hide()
local lootWindow = UI.createMiniWindow("LootAnalyzer") local lootWindow = UI.createMiniWindow("LootAnalyzer")
@ -88,6 +104,8 @@ local partyHuntWindow = UI.createMiniWindow("PartyAnalyzerWindow")
partyHuntWindow:hide() partyHuntWindow:hide()
local dropTrackerWindow = UI.createMiniWindow("DropTracker") local dropTrackerWindow = UI.createMiniWindow("DropTracker")
dropTrackerWindow:hide() dropTrackerWindow:hide()
local statsWindow = UI.createMiniWindow("CaveBotStats")
statsWindow:hide()
--f --f
local toggle = function() local toggle = function()
@ -193,8 +211,29 @@ end
mainWindow.contentsPanel.DropTracker.onClick = function() mainWindow.contentsPanel.DropTracker.onClick = function()
toggleAnalyzer(dropTrackerWindow) toggleAnalyzer(dropTrackerWindow)
end end
mainWindow.contentsPanel.Stats.onClick = function()
toggleAnalyzer(statsWindow)
end
--hunting --stats window
local totalRounds = UI.DualLabel("Total Rounds:", "0", {}, statsWindow.contentsPanel).right
local avRoundTime = UI.DualLabel("Time by Round:", "00:00h", {}, statsWindow.contentsPanel).right
UI.Separator(statsWindow.contentsPanel)
local totalRefills = UI.DualLabel("Total Refills:", "0", {}, statsWindow.contentsPanel).right
local avRefillTime = UI.DualLabel("Time by Refill:", "00:00h", {}, statsWindow.contentsPanel).right
local lastRefill = UI.DualLabel("Time since Refill:", "00:00h", {maxWidth = 200}, statsWindow.contentsPanel).right
UI.Separator(statsWindow.contentsPanel)
local label = UI.DualLabel("Supplies by Round:", "", {maxWidth = 200}, statsWindow.contentsPanel).left
label:setColor('#EC9706')
local suppliesByRound = UI.createWidget("AnalyzerItemsPanel", statsWindow.contentsPanel)
UI.Separator(statsWindow.contentsPanel)
label = UI.DualLabel("Supplies by Refill:", "", {maxWidth = 200}, statsWindow.contentsPanel).left
label:setColor('#ED7117')
local suppliesByRefill = UI.createWidget("AnalyzerItemsPanel", statsWindow.contentsPanel)
UI.Separator(statsWindow.contentsPanel)
--huntig
local sessionTimeLabel = UI.DualLabel("Session:", "00:00h", {}, huntingWindow.contentsPanel).right local sessionTimeLabel = UI.DualLabel("Session:", "00:00h", {}, huntingWindow.contentsPanel).right
local xpGainLabel = UI.DualLabel("XP Gain:", "0", {}, huntingWindow.contentsPanel).right local xpGainLabel = UI.DualLabel("XP Gain:", "0", {}, huntingWindow.contentsPanel).right
local xpHourLabel = UI.DualLabel("XP/h:", "0", {}, huntingWindow.contentsPanel).right local xpHourLabel = UI.DualLabel("XP/h:", "0", {}, huntingWindow.contentsPanel).right
@ -464,7 +503,9 @@ local xpGraph = UI.createWidget("AnalyzerGraph", xpWindow.contentsPanel)
xpGraph:setTitle("XP/h") xpGraph:setTitle("XP/h")
drawGraph(xpGraph, 0) drawGraph(xpGraph, 0)
--############################################# --#############################################
--############################################# UI DONE --############################################# UI DONE
@ -567,10 +608,13 @@ local expLeft = function()
return math.floor((50*level*level*level)/3 - 100*level*level + (850*level)/3 - 200) - exp() return math.floor((50*level*level*level)/3 - 100*level*level + (850*level)/3 - 200) - exp()
end end
niceTimeFormat = function(v) -- v in seconds niceTimeFormat = function(v, seconds) -- v in seconds
local hours = string.format("%02.f", math.floor(v/3600)) local hours = string.format("%02.f", math.floor(v/3600))
local mins = string.format("%02.f", math.floor(v/60 - (hours*60))) local mins = string.format("%02.f", math.floor(v/60 - (hours*60)))
return hours .. ":" .. mins .. "h" local secs = string.format("%02.f", math.floor(math.mod(v, 60)))
local final = string.format('%s:%s%s',hours,mins,seconds and ":"..secs or "")
return final
end end
local uptime local uptime
sessionTime = function() sessionTime = function()
@ -860,6 +904,13 @@ local function niceFormat(v)
end end
resetAnalyzerSessionData = function() resetAnalyzerSessionData = function()
vBot.CaveBotData = vBot.CaveBotData or {
refills = 0,
rounds = 0,
time = {},
lastRefill = os.time(),
refillTime = {}
}
launchTime = now launchTime = now
startExp = exp() startExp = exp()
dmgTable = {} dmgTable = {}
@ -923,24 +974,39 @@ local function getFrame(v)
end end
end end
displayCondition = function(menuPosition, lookThing, useThing, creatureThing)
if lookThing and not lookThing:isCreature() and not lookThing:isNotMoveable() and lookThing:isPickupable() then
return true
end
end
local interface = modules.game_interface
local function setFrames() local function setFrames()
if not storage.analyzers.rarityFrames then return end if not storage.analyzers.rarityFrames then return end
for _, container in pairs(getContainers()) do for _, container in pairs(getContainers()) do
local window = container.itemsPanel local window = container.itemsPanel
for i, child in pairs(window:getChildren()) do for i, child in pairs(window:getChildren()) do
local id = child:getItemId() local id = child:getItemId()
local price = 0
if id ~= 0 then -- there's item if id ~= 0 then -- there's item
local item = Item.create(id) local item = Item.create(id)
local name = item:getMarketData().name:lower() local name = item:getMarketData().name:lower()
price = getPrice(name)
local price = getPrice(name)
-- set rarity frame -- set rarity frame
child:setImageSource(getFrame(price)) child:setImageSource(getFrame(price))
else -- empty widget else -- empty widget
-- revert any possible changes -- revert any possible changes
child:setImageSource("/images/ui/item") child:setImageSource("/images/ui/item")
end end
child.onHoverChange = function(widget, hovered)
if id == 0 or not hovered then
return interface.removeMenuHook('analyzer')
end
interface.addMenuHook('analyzer', 'Price:', function() end, displayCondition, price)
end
end end
end end
end end
@ -1178,20 +1244,21 @@ function refreshLoot()
lootList:destroyChildren() lootList:destroyChildren()
for k,v in pairs(lootedItems) do for k,v in pairs(lootedItems) do
local label1 = UI.createWidget("AnalyzerLootItem", lootItems) local label1 = UI.createWidget("AnalyzerLootItem", lootItems)
local price = v.count and getPrice(v.name) * v.count or getPrice(v.name) local price = v.count and getPrice(v.name) * v.count or getPrice(v.name)
label1:setItemId(k) label1:setItemId(k)
label1:setItemCount(50) label1:setItemCount(50)
label1:setShowCount(false) label1:setShowCount(false)
label1.count:setText(niceFormat(v.count)) label1.count:setText(niceFormat(v.count))
label1.count:setColor(getColor(price)) label1.count:setColor(getColor(price))
local tooltipName = v.count > 1 and v.name.."s" or v.name local tooltipName = v.count > 1 and v.name.."s" or v.name
label1:setTooltip(v.count .. "x " .. tooltipName .. " (Value: "..format_thousand(getPrice(v.name)).."gp, Sum: "..format_thousand(price).."gp)") label1:setTooltip(v.count .. "x " .. tooltipName .. " (Value: "..format_thousand(getPrice(v.name)).."gp, Sum: "..format_thousand(price).."gp)")
--hunting window loot list --hunting window loot list
local label2 = UI.createWidget("ListLabel", lootList) local label2 = UI.createWidget("ListLabel", lootList)
label2:setText(v.count .. "x " .. v.name) label2:setText(v.count .. "x " .. v.name)
end end
if lootItems:getChildCount() == 0 then if lootItems:getChildCount() == 0 then
local label = UI.createWidget("ListLabel", lootList) local label = UI.createWidget("ListLabel", lootList)
label:setText("None") label:setText("None")
@ -1218,17 +1285,28 @@ refreshKills()
function refreshWaste() function refreshWaste()
supplyItems:destroyChildren() supplyItems:destroyChildren()
for k,v in pairs(usedItems) do suppliesByRefill:destroyChildren()
local label1 = UI.createWidget("AnalyzerLootItem", supplyItems) suppliesByRound:destroyChildren()
local price = v.count and getPrice(v.name) * v.count or getPrice(v.name)
label1:setItemId(k) local parents = {supplyItems, suppliesByRound, suppliesByRefill}
label1:setItemCount(10023)
label1:setShowCount(false) for k,v in pairs(usedItems) do
label1.count:setText(niceFormat(v.count)) for i=1,#parents do
label1.count:setColor(getColor(price)) local amount = i == 1 and v.count or
local tooltipName = v.count > 1 and v.name.."s" or v.name i == 2 and v.count/(vBot.CaveBotData.rounds + 1) or
label1:setTooltip(v.count .. "x " .. tooltipName .. " (Value: "..format_thousand(getPrice(v.name)).."gp, Sum: "..format_thousand(price).."gp)") i == 3 and v.count/(vBot.CaveBotData.refills + 1)
amount = math.floor(amount)
local label1 = UI.createWidget("AnalyzerLootItem", parents[i])
local price = amount and getPrice(v.name) * amount or getPrice(v.name)
label1:setItemId(k)
label1:setItemCount(50)
label1:setShowCount(false)
label1.count:setText(niceFormat(amount))
label1.count:setColor(getColor(price))
local tooltipName = amount > 1 and v.name.."s" or v.name
label1:setTooltip(amount .. "x " .. tooltipName .. " (Value: "..format_thousand(getPrice(v.name)).."gp, Sum: "..format_thousand(price).."gp)")
end
end end
end end
@ -1296,6 +1374,7 @@ end)
-- waste -- waste
local regex3 = [[\d ([a-z A-Z]*)s...]] local regex3 = [[\d ([a-z A-Z]*)s...]]
local lackOfData = {}
onTextMessage(function(mode, text) onTextMessage(function(mode, text)
text = text:lower() text = text:lower()
if not text:find("using one of") then return end if not text:find("using one of") then return end
@ -1305,6 +1384,16 @@ onTextMessage(function(mode, text)
local name = re[1][2] local name = re[1][2]
local id = WasteItems[name] local id = WasteItems[name]
if not id then
if not lackOfData[name] then
lackOfData[name] = true
print("[Analyzer] no data for item: "..name.. "inside items.lua -> WasteItems")
end
return
end
if not useData[name] then if not useData[name] then
useData[name] = amount useData[name] = amount
else else
@ -1427,6 +1516,21 @@ function getHuntingData()
return totalDmg, totalHeal, lootWorth, wasteWorth, balance return totalDmg, totalHeal, lootWorth, wasteWorth, balance
end end
function avgTable(t)
if type(t) ~= 'table' then return 0 end
local val = 0
for i,v in pairs(t) do
val = val + v
end
if #t == 0 then
return 0
else
return val/#t
end
end
--bestdps/hps --bestdps/hps
local bestDPS = 0 local bestDPS = 0
local bestHPS = 0 local bestHPS = 0
@ -1489,6 +1593,15 @@ macro(500, function()
xpHourInXpLabel:setText(expPerHour()) xpHourInXpLabel:setText(expPerHour())
nextLevelLabel:setText(timeToLevel()) nextLevelLabel:setText(timeToLevel())
progressBar:setPercent(modules.game_skills.skillsWindow.contentsPanel.level.percent:getPercent()) progressBar:setPercent(modules.game_skills.skillsWindow.contentsPanel.level.percent:getPercent())
--stats
totalRounds:setText(vBot.CaveBotData.rounds)
avRoundTime:setText(niceTimeFormat(avgTable(vBot.CaveBotData.time),true))
totalRefills:setText(vBot.CaveBotData.refills)
avRefillTime:setText(niceTimeFormat(avgTable(vBot.CaveBotData.refillTime),true))
lastRefill:setText(niceTimeFormat(os.difftime(os.time()-vBot.CaveBotData.lastRefill),true))
end) end)
--graphs, draw each minute --graphs, draw each minute
@ -1576,4 +1689,33 @@ end
Analyzer.getTimeToNextLevel = function() Analyzer.getTimeToNextLevel = function()
return timeToLevel() return timeToLevel()
end
Analyzer.getCaveBotStats = function()
local parents = {suppliesByRound, suppliesByRefill}
local round = {}
local refill = {}
for i=1,2 do
local data = parents[i]
for j, child in ipairs(data:getChildren()) do
local id = child:getItemId()
local count = child.count
if i == 1 then
round[id] = count
else
refill[id] = count
end
end
end
return {
totalRounds = totalRounds:getText(),
avRoundTime = avRoundTime:getText(),
totalRefills = totalRefills:getText(),
avRefillTime = avRefillTime:getText(),
lastRefill = lastRefill:getText(),
roundSupplies = round, -- { [id] = amount, [id2] = amount ...}
refillSupplies = refill -- { [id] = amount, [id2] = amount ...}
}
end end

View File

@ -206,7 +206,7 @@ AnalyzerButton < Button
MainAnalyzerWindow < MiniWindow MainAnalyzerWindow < MiniWindow
id: MainAnalyzerWindow id: MainAnalyzerWindow
text: Analytics Selector text: Analytics Selector
height: 245 height: 266
icon: /images/topbuttons/analyzers icon: /images/topbuttons/analyzers
MiniWindowContents MiniWindowContents
@ -239,6 +239,11 @@ MainAnalyzerWindow < MiniWindow
id: DropTracker id: DropTracker
text: Drop Tracker text: Drop Tracker
AnalyzerButton
id: Stats
text: CaveBot Stats
color: #74B73E
AnalyzerButton AnalyzerButton
id: PartyHunt id: PartyHunt
text: Party Hunt text: Party Hunt
@ -324,6 +329,18 @@ DropTracker < MiniWindow
padding-top: 1 padding-top: 1
layout: verticalBox layout: verticalBox
CaveBotStats < MiniWindow
id: CaveBotStats
text: CaveBot Stats
height: 200
icon: /images/topbuttons/analyzers
MiniWindowContents
padding-left: 3
padding-right: 3
padding-top: 1
layout: verticalBox
FeaturesWindow < MainWindow FeaturesWindow < MainWindow
id: FeaturesWindow id: FeaturesWindow
size: 250 370 size: 250 370

View File

@ -33,6 +33,7 @@ dofile("/cavebot/bank.lua")
dofile("/cavebot/clear_tile.lua") dofile("/cavebot/clear_tile.lua")
dofile("/cavebot/tasker.lua") dofile("/cavebot/tasker.lua")
dofile("/cavebot/imbuing.lua") dofile("/cavebot/imbuing.lua")
dofile("/cavebot/stand_lure.lua")
-- main cavebot file, must be last -- main cavebot file, must be last
dofile("/cavebot/cavebot.lua") dofile("/cavebot/cavebot.lua")

View File

@ -1,3 +1,34 @@
SlotBotItem < BotItem
border-width: 0
$on:
image-source: /images/ui/item
$checked:
border-width: 1
border-color: #FF0000
BossLabel < UIWidget
background-color: alpha
text-offset: 3 1
focusable: true
height: 16
font: verdana-11px-rounded
text-align: left
$focus:
background-color: #00000055
Button
id: remove
!text: tr('X')
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
width: 14
height: 14
margin-right: 15
text-align: center
text-offset: 0 1
tooltip: Remove profile from the list.
ConditionBoxPopupMenu < ComboBoxPopupMenu ConditionBoxPopupMenu < ComboBoxPopupMenu
ConditionBoxPopupMenuButton < ComboBoxPopupMenuButton ConditionBoxPopupMenuButton < ComboBoxPopupMenuButton
ConditionBox < ComboBox ConditionBox < ComboBox
@ -70,7 +101,7 @@ Rule < UIWidget
ConditionPanel < Panel ConditionPanel < Panel
height: 53 height: 58
NexButton NexButton
id: nex id: nex
@ -96,7 +127,7 @@ ConditionPanel < Panel
SpinBox SpinBox
id: spinbox id: spinbox
anchors.top: description.bottom anchors.top: description.bottom
margin-top: 5 margin-top: 10
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
width: 100 width: 100
text-align: center text-align: center
@ -108,7 +139,7 @@ ConditionPanel < Panel
BotTextEdit BotTextEdit
id: text id: text
anchors.top: description.bottom anchors.top: description.bottom
margin-top: 5 margin-top: 10
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
width: 200 width: 200
text-align: center text-align: center
@ -166,6 +197,7 @@ ListPanel < FlatPanel
text-align: center text-align: center
font: cipsoftFont font: cipsoftFont
margin-top: 5 margin-top: 5
tooltip: Increase priority of selected rule.
Button Button
id: down id: down
@ -176,43 +208,7 @@ ListPanel < FlatPanel
text: Move Down text: Move Down
text-align: center text-align: center
font: cipsoftFont font: cipsoftFont
tooltip: Decrease priority of selected rule.
Unequip < Panel
height: 0
padding: 5
layout:
type: verticalBox
CheckBox
text: Head Slot
CheckBox
text: Neck Slot
CheckBox
text: Torso Slot
CheckBox
text: Left Hand Slot
CheckBox
text: Right Hand Slot
CheckBox
text: Legs Slot
CheckBox
text: Finger Slot
CheckBox
text: Ammo Slot
CheckBox
text: Feet Slot
InputPanel < FlatPanel InputPanel < FlatPanel
size: 270 300 size: 270 300
@ -224,49 +220,21 @@ InputPanel < FlatPanel
id: title id: title
anchors.verticalCenter: parent.top anchors.verticalCenter: parent.top
anchors.left: parent.left anchors.left: parent.left
text: Input Panel text: Condition Panel
font: verdana-11px-rounded font: verdana-11px-rounded
color: #FF0000 color: #FF0000
Panel
id: itemBox
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
margin-top: 10
height: 80
layout:
type: grid
cell-size: 34 34
cell-spacing: 2
num-columns: 7
Button
id: unequip
anchors.top: prev.bottom
anchors.left: parent.left
text: Unequip
height: 16
width: 70
Label Label
id: mainLabel id: mainLabel
anchors.left: prev.right anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
margin-top: 2 anchors.top: prev.bottom
anchors.verticalCenter: prev.verticalCenter margin-top: 10
margin-left: 2 text: Equip selected items when:
!text: tr('& Equip above item(s) when:')
text-align: center text-align: center
font: verdana-11px-rounded font: verdana-11px-rounded
color: #aeaeae color: #aeaeae
Unequip
id: unequipPanel
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
HorizontalSeparator HorizontalSeparator
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
@ -277,8 +245,8 @@ InputPanel < FlatPanel
id: condition id: condition
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: unequipPanel.bottom anchors.top: mainLabel.bottom
margin-top: 8 margin-top: 15
HorizontalSeparator HorizontalSeparator
anchors.verticalCenter: next.verticalCenter anchors.verticalCenter: next.verticalCenter
@ -288,7 +256,7 @@ InputPanel < FlatPanel
ConditionBox ConditionBox
id: useSecondCondition id: useSecondCondition
anchors.top: condition.bottom anchors.top: condition.bottom
margin-top: 3 margin-top: 10
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
width: 50 width: 50
@ -297,40 +265,210 @@ InputPanel < FlatPanel
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: prev.bottom anchors.top: prev.bottom
margin-top: 3 margin-top: 10
HorizontalSeparator HorizontalSeparator
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: prev.bottom anchors.top: prev.bottom
BotTextEdit BotButton
id: name id: add
anchors.left: parent.left anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
width: 175 margin-bottom: 10
text: Add Rule
EQPanel < FlatPanel
size: 160 230
padding-left: 10
padding-right: 10
padding-bottom: 10
Label Label
id: title
anchors.verticalCenter: parent.top
anchors.left: parent.left
text: Equipment Setup
font: verdana-11px-rounded
color: #03C04A
SlotBotItem
id: head
image-source: /images/game/slots/head
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: prev.bottom
margin-top: 15
$on:
image-source: /images/ui/item
SlotBotItem
id: body
image-source: /images/game/slots/body
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: prev.bottom
margin-top: 5
$on:
image-source: /images/ui/item
SlotBotItem
id: legs
image-source: /images/game/slots/legs
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: prev.bottom
margin-top: 5
$on:
image-source: /images/ui/item
SlotBotItem
id: feet
image-source: /images/game/slots/feet
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: prev.bottom
margin-top: 5
$on:
image-source: /images/ui/item
SlotBotItem
id: neck
image-source: /images/game/slots/neck
anchors.top: head.top
margin-top: 13
anchors.right: head.left
margin-right: 5
$on:
image-source: /images/ui/item
SlotBotItem
id: left-hand
image-source: /images/game/slots/left-hand
anchors.horizontalCenter: prev.horizontalCenter anchors.horizontalCenter: prev.horizontalCenter
anchors.bottom: prev.top anchors.top: prev.bottom
margin-bottom: 2 margin-top: 5
text-align: center $on:
image-source: /images/ui/item
SlotBotItem
id: finger
image-source: /images/game/slots/finger
anchors.horizontalCenter: prev.horizontalCenter
anchors.top: prev.bottom
margin-top: 5
$on:
image-source: /images/ui/item
Item
id: back
image-source: /images/game/slots/back-blessed
anchors.top: head.top
margin-top: 13
anchors.left: head.right
margin-left: 5
tooltip: Main back container modifications are unavailable.
SlotBotItem
id: right-hand
image-source: /images/game/slots/right-hand
anchors.horizontalCenter: prev.horizontalCenter
anchors.top: prev.bottom
margin-top: 5
$on:
image-source: /images/ui/item
SlotBotItem
id: ammo
image-source: /images/game/slots/ammo
anchors.horizontalCenter: prev.horizontalCenter
anchors.top: prev.bottom
margin-top: 5
BotButton
id: cloneEq
anchors.top: feet.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 15
text: Clone Current EQ
font: verdana-11px-rounded
tooltip: Copy currently equipped and non-equipped items.
BotButton
id: default
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 3
text: Reset fields
font: verdana-11px-rounded
tooltip: Reset all fields to the blank state
Profile < FlatPanel
size: 160 35
Label
id: title
anchors.verticalCenter: parent.top
anchors.left: parent.left
margin-left: 10
text: Profile Name text: Profile Name
font: verdana-11px-rounded font: verdana-11px-rounded
color: #aeaeae
BotTextEdit
id: profileName
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
margin: 5
BossList < FlatPanel
padding-left: 10
padding-right: 10
padding-bottom: 10
Label
id: title
anchors.verticalCenter: parent.top
anchors.left: parent.left
text: Boss List
font: verdana-11px-rounded
color: #FABD02
TextList
id: list
anchors.fill: parent
margin-top: 10
margin-bottom: 20
vertical-scrollbar: listScrollBar
padding: 2
VerticalScrollBar
id: listScrollBar
anchors.top: list.top
anchors.bottom: list.bottom
anchors.right: list.right
step: 14
pixels-scroll: true
BotTextEdit
id: name
anchors.left: list.left
anchors.top: list.bottom
margin-top: 4
anchors.right: next.left
Button Button
id: addButton id: add
anchors.top: name.top anchors.right: list.right
anchors.bottom: name.bottom anchors.top: list.bottom
anchors.left: name.right margin-top: 3
margin-left: 3 height: 21
anchors.right: parent.right text: Add Boss
text: Add text-align: center
tooltip: On add above rule will be listed as Profile name - use friendly one! font: verdana-11px-rounded
tooltip: Creature with given name will be considered as boss.
EquipWindow < MainWindow EquipWindow < MainWindow
size: 600 370 size: 750 350
text: Equipment Manager text: Equipment Manager
@onEscape: self:hide() @onEscape: self:hide()
@ -338,17 +476,44 @@ EquipWindow < MainWindow
id: listPanel id: listPanel
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.top anchors.top: parent.top
anchors.bottom: bottomSep.top
margin-bottom: 5
margin-left: -2
visible: false
BossList
id: bossPanel
anchors.fill: prev
visible: true
VerticalSeparator VerticalSeparator
anchors.top: parent.top anchors.top: parent.top
anchors.bottom: bottomSep.top anchors.bottom: bottomSep.top
margin-bottom: 5 margin-bottom: 5
anchors.horizontalCenter: parent.horizontalCenter anchors.left: prev.right
margin-left: 10
Profile
id: profileName
anchors.top: parent.top
anchors.left: prev.right
margin-left: 10
EQPanel
id: setup
anchors.left: prev.left
anchors.top: prev.bottom
anchors.bottom: bottomSep.top
margin-bottom: 5
margin-top: 10
InputPanel InputPanel
id: inputPanel id: inputPanel
anchors.right: parent.right anchors.left: prev.right
anchors.top: parent.top anchors.top: parent.top
anchors.bottom: bottomSep.top
margin-bottom: 5
margin-left: 5
HorizontalSeparator HorizontalSeparator
id: bottomSep id: bottomSep
@ -363,6 +528,12 @@ EquipWindow < MainWindow
font: cipsoftFont font: cipsoftFont
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
size: 45 21 size: 45 21
margin-top: 15
margin-right: 5 Button
id: bossList
!text: tr('Boss list')
font: cipsoftFont
anchors.left: parent.left
anchors.bottom: parent.bottom
size: 65 21

View File

@ -114,6 +114,7 @@ addItem("rope", "Rope Item", 9596, leftPanel, "This item will be used in various
addItem("shovel", "Shovel Item", 9596, leftPanel, "This item will be used in various bot related scripts as default shovel item.") addItem("shovel", "Shovel Item", 9596, leftPanel, "This item will be used in various bot related scripts as default shovel item.")
addItem("machete", "Machete Item", 9596, leftPanel, "This item will be used in various bot related scripts as default machete item.") addItem("machete", "Machete Item", 9596, leftPanel, "This item will be used in various bot related scripts as default machete item.")
addItem("scythe", "Scythe Item", 9596, leftPanel, "This item will be used in various bot related scripts as default scythe item.") addItem("scythe", "Scythe Item", 9596, leftPanel, "This item will be used in various bot related scripts as default scythe item.")
addCheckBox("pathfinding", "CaveBot Pathfinding", true, leftPanel, "Cavebot will automatically search for first reachable waypoint after missing 10 goto's.")
addScrollBar("talkDelay", "Global NPC Talk Delay", 0, 2000, 1000, leftPanel, "Breaks between each talk action in cavebot (time in miliseconds).") addScrollBar("talkDelay", "Global NPC Talk Delay", 0, 2000, 1000, leftPanel, "Breaks between each talk action in cavebot (time in miliseconds).")
addScrollBar("looting", "Max Loot Distance", 0, 50, 40, leftPanel, "Every loot corpse futher than set distance (in sqm) will be ignored and forgotten.") addScrollBar("looting", "Max Loot Distance", 0, 50, 40, leftPanel, "Every loot corpse futher than set distance (in sqm) will be ignored and forgotten.")
addScrollBar("huntRoutes", "Hunting Rounds Limit", 0, 300, 50, leftPanel, "Round limit for supply check, if character already made more rounds than set, on next supply check will return to city.") addScrollBar("huntRoutes", "Hunting Rounds Limit", 0, 300, 50, leftPanel, "Round limit for supply check, if character already made more rounds than set, on next supply check will return to city.")
@ -419,7 +420,7 @@ if true then
if not settings.suppliesControl then return end if not settings.suppliesControl then return end
if TargetBot.isOff() then return end if TargetBot.isOff() then return end
if CaveBot.isOff() then return end if CaveBot.isOff() then return end
if not hasSupplies() then if type(hasSupplies()) == 'table' then
TargetBot.setOff() TargetBot.setOff()
end end
end) end)
@ -553,7 +554,7 @@ if true then
end end
end) end)
local regex = [[You see ([a-z 'A-z-]*) \(Level ([0-9]*)\)((?:.)* of the ([\w ]*),|)]] local regex = [[You see ([^\(]*) \(Level ([0-9]*)\)((?:.)* of the ([\w ]*),|)]]
onTextMessage(function(mode, text) onTextMessage(function(mode, text)
if not settings.checkPlayer then return end if not settings.checkPlayer then return end

View File

@ -1,4 +1,4 @@
local version = "4.5" local version = "4.7"
local currentVersion local currentVersion
local available = false local available = false

View File

@ -1,3 +1,23 @@
--[[
configuration for check players
example made on server Gunzodus
example link for player overview:
https://www.gunzodus.net/character/show/Sir_Vithrax
*note that space in character name was replaced with underscore (_) - this character will be important
in this case:
link = "https://www.gunzodus.net/character/show/" -- everything with all the characters up to the start of the name
spacing = "_" -- space replacement in character name
]]
local link = "https://www.gunzodus.net/character/show/"
local spacing = "_"
-- do not edit below
setDefaultTab("Main") setDefaultTab("Main")
local tabs = {"Friends", "Enemies", "BlackList"} local tabs = {"Friends", "Enemies", "BlackList"}
local panelName = "playerList" local panelName = "playerList"
@ -191,8 +211,7 @@ if rootWidget then
menu:setId("blzMenu") menu:setId("blzMenu")
menu:setGameMenu(true) menu:setGameMenu(true)
menu:addOption('Check Player', function() menu:addOption('Check Player', function()
local name = widget:getText():gsub(" ", "_") local name = widget:getText():gsub(" ", spacing)
local link = "https://www.gunzodus.net/character/show/"
g_platform.openUrl(link..name) g_platform.openUrl(link..name)
end, "") end, "")
menu:addOption('Copy Name', function() menu:addOption('Copy Name', function()

View File

@ -33,7 +33,8 @@ if voc() == 2 or voc() == 12 then
local containers = getContainers() local containers = getContainers()
for i, container in ipairs(containers) do for i, container in ipairs(containers) do
if container ~= quiverContainer and not containerIsFull(container) then if container ~= quiverContainer and not containerIsFull(container) then
if container:getName():lower():find("backpack") or container:getName():lower():find("bag") or container:getName():lower():find("chess") then local cname = container:getName():lower()
if not cname:find("loot") and (cname:find("backpack") or cname:find("bag") or cname:find("chess")) then
dest = container dest = container
end end
end end

View File

@ -0,0 +1,473 @@
setDefaultTab("Cave")
local panelName = "supplies"
if not SuppliesConfig[panelName] or SuppliesConfig[panelName].item1 then
SuppliesConfig[panelName] = {
currentProfile = "Default",
["Default"] = {}
}
end
local function convertOldConfig(config)
if config and config.items then
return config
end -- config is new
local newConfig = {
items = {},
capSwitch = config.capSwitch,
SoftBoots = config.SoftBoots,
imbues = config.imbues,
staminaSwitch = config.staminaSwitch,
capValue = config.capValue,
staminaValue = config.staminaValue
}
local items = {
config.item1,
config.item2,
config.item3,
config.item4,
config.item5,
config.item6
}
local mins = {
config.item1Min,
config.item2Min,
config.item3Min,
config.item4Min,
config.item5Min,
config.item6Min
}
local maxes = {
config.item1Max,
config.item2Max,
config.item3Max,
config.item4Max,
config.item5Max,
config.item6Max
}
for i, item in ipairs(items) do
if item > 100 then
local min = mins[i]
local max = maxes[i]
newConfig.items[tostring(item)] = {
min = min,
max = max,
avg = 0
}
end
end
return newConfig
end
-- convert old configs
for k, profile in pairs(SuppliesConfig[panelName]) do
if type(profile) == 'table' then
SuppliesConfig[panelName][k] = convertOldConfig(profile)
end
end
local currentProfile = SuppliesConfig[panelName].currentProfile
local config = SuppliesConfig[panelName][currentProfile]
vBotConfigSave("supply")
if not config then
for k, v in pairs(SuppliesConfig[panelName]) do
if type(v) == "table" then
SuppliesConfig[panelName].currentProfile = k
config = SuppliesConfig[panelName][k]
break
end
end
end
function getEmptyItemPanels()
local panel = SuppliesWindow.items
local count = 0
for i, child in ipairs(panel:getChildren()) do
count = child:getId() == "blank" and count + 1 or count
end
return count
end
function deleteFirstEmptyPanel()
local panel = SuppliesWindow.items
for i, child in ipairs(panel:getChildren()) do
if child:getId() == "blank" then
child:destroy()
break
end
end
end
function clearEmptyPanels()
local panel = SuppliesWindow.items
if panel:getChildCount() > 1 then
if getEmptyItemPanels() > 1 then
deleteFirstEmptyPanel()
end
end
end
function addItemPanel()
local parent = SuppliesWindow.items
local childs = parent:getChildCount()
local panel = UI.createWidget("ItemPanel", parent)
local item = panel.id
local min = panel.min
local max = panel.max
local avg = panel.avg
panel:setId("blank")
item:setShowCount(false)
item.onItemChange = function(widget)
local id = widget:getItemId()
local panelId = panel:getId()
-- empty, verify
if id < 100 then
config.items[panelId] = nil
panel:setId("blank")
clearEmptyPanels() -- clear empty panels if any
return
end
-- itemId was not changed, ignore
if tonumber(panelId) == id then
return
end
-- check if isnt already added
if config[tostring(id)] then
warn("vBot[Drop Tracker]: Item already added!")
widget:setItemId(0)
return
end
-- new item id
config.items[tostring(id)] = config.items[tostring(id)] or {} -- min, max, avg
panel:setId(id)
addItemPanel() -- add new panel
end
return panel
end
SuppliesWindow = UI.createWindow("SuppliesWindow")
SuppliesWindow:hide()
UI.Button(
"Supply Settings",
function()
SuppliesWindow:setVisible(not SuppliesWindow:isVisible())
end
)
-- load settings
local function loadSettings()
-- panels
SuppliesWindow.items:destroyChildren()
for id, data in pairs(config.items) do
local widget = addItemPanel()
widget:setId(id)
widget.id:setItemId(tonumber(id))
widget.min:setText(data.min)
widget.max:setText(data.max)
widget.avg:setText(data.avg)
end
addItemPanel() -- add empty panel
-- switches and values
SuppliesWindow.capSwitch:setOn(config.capSwitch)
SuppliesWindow.SoftBoots:setOn(config.SoftBoots)
SuppliesWindow.imbues:setOn(config.imbues)
SuppliesWindow.staminaSwitch:setOn(config.staminaSwitch)
SuppliesWindow.capValue:setText(config.capValue or 0)
SuppliesWindow.staminaValue:setText(config.staminaValue or 0)
end
loadSettings()
-- save settings
SuppliesWindow.onVisibilityChange = function(widget, visible)
if not visible then
local currentProfile = SuppliesConfig[panelName].currentProfile
SuppliesConfig[panelName][currentProfile].items = {}
local parent = SuppliesWindow.items
-- items
for i, panel in ipairs(parent:getChildren()) do
if panel.id:getItemId() > 100 then
local id = tostring(panel.id:getItemId())
local min = panel.min:getValue()
local max = panel.max:getValue()
local avg = panel.avg:getValue()
SuppliesConfig[panelName][currentProfile].items[id] = {
min = min,
max = max,
avg = avg
}
end
end
vBotConfigSave("supply")
end
end
local function refreshProfileList()
local profiles = SuppliesConfig[panelName]
SuppliesWindow.profiles:destroyChildren()
for k, v in pairs(profiles) do
if type(v) == "table" then
local label = UI.createWidget("ProfileLabel", SuppliesWindow.profiles)
label:setText(k)
label:setTooltip("Click to load this profile. \nDouble click to change the name.")
label.remove.onClick = function()
local childs = SuppliesWindow.profiles:getChildCount()
if childs == 1 then
return info("vBot[Supplies] You need at least one profile!")
end
profiles[k] = nil
label:destroy()
vBotConfigSave("supply")
end
label.onDoubleClick = function(widget)
local window =
modules.client_textedit.show(
widget,
{title = "Set Profile Name", description = "Enter a new name for selected profile"}
)
schedule(
50,
function()
window:raise()
window:focus()
end
)
end
label.onClick = function()
SuppliesConfig[panelName].currentProfile = label:getText()
config = SuppliesConfig[panelName][label:getText()]
loadSettings()
vBotConfigSave("supply")
end
label.onTextChange = function(widget, text)
currentProfile = text
SuppliesConfig[panelName].currentProfile = text
profiles[text] = profiles[k]
profiles[k] = nil
vBotConfigSave("supply")
end
end
end
end
refreshProfileList()
local function setProfileFocus()
for i, v in ipairs(SuppliesWindow.profiles:getChildren()) do
local name = v:getText()
if name == SuppliesConfig[panelName].currentProfile then
return v:focus()
end
end
end
setProfileFocus()
SuppliesWindow.newProfile.onClick = function()
local n = SuppliesWindow.profiles:getChildCount()
if n > 6 then
return info("vBot[Supplies] - max profile count reached!")
end
local name = "Profile #" .. n + 1
SuppliesConfig[panelName][name] = {items = {}}
refreshProfileList()
setProfileFocus()
vBotConfigSave("supply")
end
SuppliesWindow.capSwitch.onClick = function(widget)
config.capSwitch = not config.capSwitch
widget:setOn(config.capSwitch)
end
SuppliesWindow.SoftBoots.onClick = function(widget)
config.SoftBoots = not config.SoftBoots
widget:setOn(config.SoftBoots)
end
SuppliesWindow.imbues.onClick = function(widget)
config.imbues = not config.imbues
widget:setOn(config.imbues)
end
SuppliesWindow.staminaSwitch.onClick = function(widget)
config.staminaSwitch = not config.staminaSwitch
widget:setOn(config.staminaSwitch)
end
SuppliesWindow.capValue.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.capValue:getText())
if not value then
SuppliesWindow.capValue:setText(0)
config.capValue = 0
else
text = text:match("0*(%d+)")
config.capValue = text
end
end
SuppliesWindow.staminaValue.onTextChange = function(widget, text)
local value = tonumber(SuppliesWindow.staminaValue:getText())
if not value then
SuppliesWindow.staminaValue:setText(0)
config.staminaValue = 0
else
text = text:match("0*(%d+)")
config.staminaValue = text
end
end
SuppliesWindow.increment.onClick = function(widget)
for i, panel in ipairs(SuppliesWindow.items:getChildren()) do
if panel.id:getItemId() > 100 then
local max = panel.max:getValue()
local avg = panel.avg:getValue()
if avg > 0 then
panel.max:setText(max + avg)
end
end
end
end
SuppliesWindow.decrement.onClick = function(widget)
for i, panel in ipairs(SuppliesWindow.items:getChildren()) do
if panel.id:getItemId() > 100 then
local max = panel.max:getValue()
local avg = panel.avg:getValue()
if avg > 0 then
panel.max:setText(math.max(0, max - avg)) -- dont go below 0
end
end
end
end
SuppliesWindow.increment.onMouseWheel = function(widget, mousePos, dir)
if dir == 1 then
SuppliesWindow.increment.onClick()
elseif dir == 2 then
SuppliesWindow.decrement.onClick()
end
end
SuppliesWindow.decrement.onMouseWheel = SuppliesWindow.increment.onMouseWheel
Supplies = {} -- public functions
Supplies.show = function()
SuppliesWindow:show()
SuppliesWindow:raise()
SuppliesWindow:focus()
end
Supplies.getItemsData = function()
local t = {}
-- items
for i, panel in ipairs(SuppliesWindow.items:getChildren()) do
if panel.id:getItemId() > 100 then
local id = tostring(panel.id:getItemId())
local min = panel.min:getValue()
local max = panel.max:getValue()
local avg = panel.avg:getValue()
t[id] = {
min = min,
max = max,
avg = avg
}
end
end
return t
end
Supplies.isSupplyItem = function(id)
local data = Supplies.getItemsData()
id = tostring(id)
if data[id] then
return data[id]
else
return false
end
end
Supplies.hasEnough = function()
local data = Supplies.getItemsData()
for id, values in pairs(data) do
id = tonumber(id)
local minimum = values.min
local current = player:getItemsCount(id) or 0
if current < minimum then
return {id=id, amount=current}
end
end
return true
end
hasSupplies = Supplies.hasEnough
Supplies.setAverageValues = function(data)
for id, amount in pairs(data) do
local widget = SuppliesWindow.items[id]
if widget then
widget.avg:setText(amount)
end
end
end
Supplies.addSupplyItem = function(id, min, max, avg)
if not id then
return
end
local widget = addItemPanel()
widget:setId(id)
widget.id:setItemId(tonumber(id))
widget.min:setText(min or 0)
widget.max:setText(max or 0)
widget.avg:setText(avg or 0)
end
Supplies.getAdditionalData = function()
local data = {
stamina = {enabled = config.staminaSwitch, value = config.staminaValue},
capacity = {enabled = config.capSwitch, value = config.capValue},
softBoots = {enabled = config.SoftBoots},
imbues = {enabled = config.imbues}
}
return data
end
Supplies.getFullData = function()
local data = {
items = Supplies.getItemsData(),
additional = Supplies.getAdditionalData()
}
return data
end

View File

@ -0,0 +1,244 @@
ProfileLabel < UIWidget
background-color: alpha
text-offset: 3 1
focusable: true
height: 16
font: verdana-11px-rounded
text-align: left
$focus:
background-color: #00000055
Button
id: remove
!text: tr('X')
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
width: 14
height: 14
margin-right: 3
text-align: center
text-offset: 0 1
tooltip: Remove profile from the list.
SupplySpinBox < SpinBox
height: 20
margin-left: 3
width: 75
minimum: 0
maximum: 9999
text-align: center
focusable: true
text: 0
ItemPanel < Panel
height: 38
BotItem
id: id
anchors.left: parent.left
anchors.bottom: parent.bottom
SupplySpinBox
id: min
anchors.left: prev.right
anchors.bottom: parent.bottom
SupplySpinBox
id: max
anchors.left: prev.right
anchors.bottom: parent.bottom
SupplySpinBox
id: avg
anchors.left: prev.right
anchors.bottom: parent.bottom
width: 50
UIWidget
anchors.left: min.left
anchors.bottom: min.top
width: 75
text-align: center
font: verdana-11px-rounded
text: Min
tooltip: Amount of given supplies for bot to leave the spawn.
UIWidget
anchors.left: max.left
anchors.bottom: max.top
width: 75
text-align: center
font: verdana-11px-rounded
text: Max
tooltip: Amount of given supplies to purchase
UIWidget
anchors.left: avg.left
anchors.bottom: avg.top
width: 55
text-align: center
font: verdana-11px-rounded
text: AVG
!tooltip: ("This is average consumption of supplies by round to help calculate the amount to purchase\n (info provided by CaveBot Stats)")
SuppliesWindow < MainWindow
!text: tr('Supplies')
size: 430 330
@onEscape: self:hide()
VerticalSeparator
id: sep
anchors.top: parent.top
anchors.right: parent.right
margin-right: 140
anchors.bottom: bottomSep.top
margin-bottom: 5
margin-left: 10
visible: false
Label
anchors.left: sep.right
anchors.right: parent.right
anchors.top: parent.top
margin-left: 10
margin-top: 3
text-align: center
text: Additional Conditions:
HorizontalSeparator
anchors.top: prev.bottom
anchors.left: prev.left
anchors.right: prev.right
margin-top: 3
BotSwitch
id: SoftBoots
anchors.top: prev.bottom
anchors.left: sep.right
anchors.right: parent.right
margin-top: 5
margin-left: 10
text: No Soft
tooltip: Go refill if there's no more active soft boots.
BotSwitch
id: capSwitch
height: 20
anchors.left: SoftBoots.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
margin-right: 50
text-align: center
text: Cap Below:
tooltip: Go refill if capacity is below set value.
BotTextEdit
id: capValue
size: 40 20
anchors.left: prev.right
anchors.right: parent.right
anchors.top: prev.top
margin-left: 5
BotSwitch
id: staminaSwitch
height: 20
anchors.left: SoftBoots.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
margin-right: 50
text-align: center
text: Stamina:
tooltip: Go refill if stamina is below set value. (in minutes)
BotTextEdit
id: staminaValue
size: 40 20
anchors.left: prev.right
anchors.right: parent.right
anchors.top: prev.top
margin-left: 5
BotSwitch
id: imbues
anchors.top: prev.bottom
anchors.left: sep.right
anchors.right: parent.right
margin-top: 5
margin-left: 10
text: No Imbues
tooltip: Go refill when mana leech imbue has worn off.
TextList
id: profiles
anchors.top: prev.bottom
margin-top: 5
anchors.left: prev.left
anchors.right: prev.right
anchors.bottom: bottomSep.top
margin-bottom: 25
BotButton
id: newProfile
anchors.left: prev.left
anchors.top: prev.bottom
size: 35 15
text: New
font: cipsoftFont
tooltip: Create new supplies profile.
VerticalScrollBar
id: itemsScrollBar
anchors.top: items.top
anchors.bottom: items.bottom
anchors.right: items.right
step: 14
pixels-scroll: true
ScrollablePanel
id: items
anchors.top: parent.top
anchors.left: parent.left
anchors.right: sep.left
anchors.bottom: bottomSep.top
margin-bottom: 8
vertical-scrollbar: itemsScrollBar
layout: verticalBox
HorizontalSeparator
id: bottomSep
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: closeButton.top
margin-bottom: 8
Button
id: closeButton
!text: tr('Close')
font: cipsoftFont
anchors.right: parent.right
anchors.bottom: parent.bottom
size: 45 21
margin-top: 15
tooltip: Close supplies window and save settings.
@onClick: self:getParent():hide()
Button
id: increment
anchors.verticalCenter: prev.verticalCenter
anchors.right: items.right
text: +
width: 50
tooltip: increase all max supplies amount by average
Button
id: decrement
anchors.verticalCenter: prev.verticalCenter
anchors.right: prev.left
margin-right: 3
text: -
width: 50
tooltip: decrease all max supplies amount by average

View File

@ -0,0 +1 @@
4.7

View File

@ -9,6 +9,14 @@ vBot.isUsingPotion = false
vBot.isUsing = false vBot.isUsing = false
vBot.customCooldowns = {} vBot.customCooldowns = {}
function logInfo(text)
local timestamp = os.date("%H:%M:%S")
text = tostring(text)
local start = timestamp.." [vBot]"
return modules.client_terminal.addLine(start..text, "orange")
end
-- scripts / functions -- scripts / functions
onPlayerPositionChange(function(x,y) onPlayerPositionChange(function(x,y)
vBot.standTime = now vBot.standTime = now
@ -300,7 +308,7 @@ end)
if onSpellCooldown and onGroupSpellCooldown then if onSpellCooldown and onGroupSpellCooldown then
onSpellCooldown(function(iconId, duration) onSpellCooldown(function(iconId, duration)
schedule(5, function() schedule(1, function()
if not vBot.customCooldowns[lastPhrase] then if not vBot.customCooldowns[lastPhrase] then
vBot.customCooldowns[lastPhrase] = {id = iconId} vBot.customCooldowns[lastPhrase] = {id = iconId}
end end
@ -308,7 +316,7 @@ if onSpellCooldown and onGroupSpellCooldown then
end) end)
onGroupSpellCooldown(function(iconId, duration) onGroupSpellCooldown(function(iconId, duration)
schedule(10, function() schedule(2, function()
if vBot.customCooldowns[lastPhrase] then if vBot.customCooldowns[lastPhrase] then
vBot.customCooldowns[lastPhrase] = {id = vBot.customCooldowns[lastPhrase].id, group = {[iconId] = duration}} vBot.customCooldowns[lastPhrase] = {id = vBot.customCooldowns[lastPhrase].id, group = {[iconId] = duration}}
end end
@ -655,9 +663,9 @@ function getPlayers(range, multifloor)
if not range then range = 10 end if not range then range = 10 end
local specs = 0; local specs = 0;
for _, spec in pairs(getSpectators(multifloor)) do for _, spec in pairs(getSpectators(multifloor)) do
specs = not spec:isLocalPlayer() and spec:isPlayer() and if not spec:isLocalPlayer() and spec:isPlayer() and distanceFromPlayer(spec:getPosition()) <= range and not ((spec:getShield() ~= 1 and spec:isPartyMember()) or spec:getEmblem() == 1) then
distanceFromPlayer(spec:getPosition()) <= range and specs = specs + 1
not (spec:isPartyMember() or spec:getEmblem() == 1) and specs + 1 or specs; end
end end
return specs; return specs;
end end
@ -750,21 +758,7 @@ end
-- also considers equipped items -- also considers equipped items
-- returns number -- returns number
function itemAmount(id) function itemAmount(id)
local totalItemCount = 0 return player:getItemsCount(id)
for _, container in pairs(getContainers()) do
if not container:getName():lower():find("depot") and not container:getName():lower():find("your inbox") then
for _, item in ipairs(container:getItems()) do
totalItemCount = item:getId() == id and totalItemCount +
item:getCount() or totalItemCount
end
end
end
local slots = {getHead(), getNeck(), getBack(), getBody(), getRight(), getLeft(), getLeg(), getFeet(), getFinger(), getAmmo()}
for i, slot in pairs(slots) do
totalItemCount = slot and slot:getId() == id and totalItemCount + 1 or totalItemCount
end
return totalItemCount
end end
-- self explanatory -- self explanatory
@ -777,35 +771,6 @@ function useOnInvertoryItem(a, b)
return useWith(a, item) return useWith(a, item)
end end
-- checks if player has at least 50% of minimal supplies given in Supplies window
-- returns boolean
function hasSupplies()
local supplies = SuppliesConfig.supplies
supplies = supplies[supplies.currentProfile]
local items = {
{ID = supplies.item1, minAmount = supplies.item1Min},
{ID = supplies.item2, minAmount = supplies.item2Min},
{ID = supplies.item3, minAmount = supplies.item3Min},
{ID = supplies.item4, minAmount = supplies.item4Min},
{ID = supplies.item5, minAmount = supplies.item5Min},
{ID = supplies.item6, minAmount = supplies.item6Min},
{ID = supplies.item7, minAmount = supplies.item7Min}
}
-- false = no supplies
-- true = supplies available
local hasSupplies = true
for i, supply in pairs(items) do
if supply.minAmount and supply.ID then
if supply.ID > 100 and itemAmount(supply.ID) <
(supply.minAmount / 2) then hasSupplies = false end
end
end
return hasSupplies
end
-- pos can be tile or position -- pos can be tile or position
-- returns table of tiles surrounding given POS/tile -- returns table of tiles surrounding given POS/tile
function getNearTiles(pos) function getNearTiles(pos)

Some files were not shown because too many files have changed in this diff Show More