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

View File

@ -32,6 +32,10 @@ MiniWindow
MiniWindowContents
ComboBox
id: config
&menuScroll: true
&menuHeight: 450
&menuScrollStep: 100
&parentWidth: true
anchors.top: parent.top
anchors.left: parent.left
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 = {}
vBot.lastLabel = ""
local oldTibia = g_game.getClientVersion() < 960
local nextTile = nil
local noPath = 0
-- antistuck f()
local nextPos = nil
local nextPos = nil -- creature
local nextPosF = nil -- furniture
local function modPos(dir)
local y = 0
local x = 0
@ -34,6 +37,103 @@ local function modPos(dir)
return {x, y}
end
-- stack-covered antystuck, in & out pz
local lastMoved = now - 200
onTextMessage(function(mode, text)
if text ~= 'There is not enough room.' then return end
if CaveBot.isOff() then return end
local tiles = getNearTiles(pos())
for i, tile in ipairs(tiles) do
if not tile:hasCreature() and tile:isWalkable() and #tile:getItems() > 9 then
local topThing = tile:getTopThing()
if not isInPz() then
return useWith(3197, tile:getTopThing()) -- disintegrate
else
if now < lastMoved + 200 then return end -- delay to prevent clogging
local nearTiles = getNearTiles(tile:getPosition())
for i, tile in ipairs(nearTiles) do
local tpos = tile:getPosition()
if pos() ~= tpos then
if tile:isWalkable() then
lastMoved = now
return g_game.move(topThing, tpos) -- move item
end
end
end
end
end
end
end)
local furnitureIgnore = { 2986 }
local function breakFurniture(destPos)
if isInPz() then return false end
local candidate = {thing=nil, dist=100}
for i, tile in ipairs(g_map.getTiles(posz())) do
local walkable = tile:isWalkable()
local topThing = tile:getTopThing()
local isWg = topThing and topThing:getId() == 2130
if topThing and (isWg or not table.find(furnitureIgnore, topThing:getId()) and topThing:isItem()) then
local moveable = not topThing:isNotMoveable()
local tpos = tile:getPosition()
local path = findPath(player:getPosition(), tpos, 7, { ignoreNonPathable = true, precision = 1 })
if path then
if isWg or (not walkable and moveable) then
local distance = getDistanceBetween(destPos, tpos)
if distance < candidate.dist then
candidate = {thing=topThing, dist=distance}
end
end
end
end
end
local thing = candidate.thing
if thing then
useWith(3197, thing)
return true
end
return false
end
local function pushPlayer(creature)
local cpos = creature:getPosition()
local tiles = getNearTiles(cpos)
for i, tile in ipairs(tiles) do
local pos = tile:getPosition()
local minimapColor = g_map.getMinimapColor(pos)
local stairs = (minimapColor >= 210 and minimapColor <= 213)
if not stairs and tile:isWalkable() then
g_game.move(creature, pos)
end
end
end
local function pathfinder()
if not storage.extras.pathfinding then return end
if noPath < 10 then return end
if not CaveBot.gotoNextWaypointInRange() then
if getConfigFromName and getConfigFromName() then
local profile = CaveBot.getCurrentProfile()
local config = getConfigFromName()
local newProfile = profile == '#Unibase' and config or '#Unibase'
CaveBot.setCurrentProfile(newProfile)
end
end
noPath = 0
return true
end
-- it adds an action widget to list
CaveBot.addAction = function(action, value, focus)
action = action:lower()
@ -119,7 +219,25 @@ end)
CaveBot.registerAction("delay", "#AAAAAA", function(value, retries, prev)
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"
end
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)
return false
end
-- reset pathfinder
nextPosF = nil
nextPos = nil
if CaveBot.Config.get("mapClick") then
if retries >= 5 then
noPath = noPath + 1
pathfinder()
return false -- tried 5 times, can't get there
end
else
if retries >= 100 then
noPath = noPath + 1
pathfinder()
return false -- tried 100 times, can't get there
end
end
@ -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])}
local playerPos = player:getPosition()
if pos.z ~= playerPos.z then
noPath = noPath + 1
pathfinder()
return false -- different floor
end
local maxDist = storage.extras.gotoMaxDistance or 40
if math.abs(pos.x-playerPos.x) + math.abs(pos.y-playerPos.y) > maxDist then
noPath = noPath + 1
pathfinder()
return false -- too far way
end
@ -194,14 +324,23 @@ CaveBot.registerAction("goto", "green", function(value, retries, prev)
if stairs then
if math.abs(pos.x-playerPos.x) == 0 and math.abs(pos.y-playerPos.y) <= 0 then
noPath = 0
return true -- already at position
end
elseif math.abs(pos.x-playerPos.x) == 0 and math.abs(pos.y-playerPos.y) <= (precision or 1) then
noPath = 0
return true -- already at position
end
-- check if there's a path to that place, ignore creatures and fields
local path = findPath(playerPos, pos, maxDist, { ignoreNonPathable = true, precision = 1, ignoreCreatures = true, allowUnseen = true, allowOnlyVisibleTiles = false })
if not path then
if breakFurniture(pos, storage.extras.machete) then
CaveBot.delay(1000)
retries = 0
return "retry"
end
noPath = noPath + 1
pathfinder()
return false -- there's no way
end
@ -222,27 +361,28 @@ CaveBot.registerAction("goto", "green", function(value, retries, prev)
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(), 20, { ignoreNonPathable = true, precision = 1 })
local path = findPath(playerPos, creature:getPosition(), 7, { ignoreNonPathable = true, precision = 1 })
if path then
foundMonster = true
attack(creature)
if g_game.getAttackingCreature() ~= creature then
attack(creature)
end
g_game.setChaseMode(1)
CaveBot.setOff()
CaveBot.delay(1000)
schedule(1000, function() CaveBot.setOn() end)
CaveBot.delay(100)
retries = 0 -- reset retries, we are trying to unclog the cavebot
break
end
end
end
end
end
nextPos = nil -- reset path
if not foundMonster then
foundMonster = false
return false -- no other way
end
end
-- try to find path, don't ignore creatures, don't ignore fields
if not CaveBot.Config.get("ignoreFields") and CaveBot.walkTo(pos, 40) then
return "retry"
@ -265,10 +405,14 @@ CaveBot.registerAction("goto", "green", function(value, retries, prev)
end
if not CaveBot.Config.get("mapClick") and retries >= 5 then
noPath = noPath + 1
pathfinder()
return false
end
if CaveBot.Config.get("skipBlocked") then
noPath = noPath + 1
pathfinder()
return false
end
@ -358,4 +502,4 @@ end)
CaveBot.registerAction("npcsay", "#FF55FF", function(value, retries, prev)
NPC.say(value)
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])}
if posz() == pos.z then
if distanceFromPlayer(pos) <= storage.extras.gotoMaxDistance/2 then
return ui.list:focusChild(child)
local maxDist = storage.extras.gotoMaxDistance
if distanceFromPlayer(pos) <= maxDist then
if findPath(player:getPosition(), pos, maxDist, { ignoreNonPathable = true }) then
ui.list:focusChild(ui.list:getChildByIndex(i-1))
return true
end
end
end
end
@ -224,8 +228,12 @@ CaveBot.gotoNextWaypointInRange = function()
local pos = {x = tonumber(re[1][2]), y = tonumber(re[1][3]), z = tonumber(re[1][4])}
if posz() == pos.z then
if distanceFromPlayer(pos) <= storage.extras.gotoMaxDistance/2 then
return ui.list:focusChild(child)
local maxDist = storage.extras.gotoMaxDistance
if distanceFromPlayer(pos) <= maxDist then
if findPath(player:getPosition(), pos, maxDist, { ignoreNonPathable = true }) then
ui.list:focusChild(ui.list:getChildByIndex(i-1))
return true
end
end
end
end
@ -433,3 +441,7 @@ CaveBot.save = function()
table.insert(data, {"extensions", json.encode(extension_data, 2)})
config.save(data)
end
CaveBotList = function()
return ui.list
end

View File

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

View File

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

View File

@ -89,9 +89,9 @@ CaveBot.Editor.setup = function()
registerAction("delay", {
value="500",
title="Delay",
description="Delay next action (in milliseconds)",
description="Delay next action (in milliseconds),randomness (in percent-optional)",
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", {
value="labelName",

View File

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

View File

@ -43,6 +43,7 @@ CaveBot.Extensions.SellAll.setup = function()
if not NPC.isTrading() then
CaveBot.OpenNpcTrade()
delay(storage.extras.talkDelay*2)
return "retry"
else
sellAllCap = freecap()
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
g_game.open(container)
waitTill = now + 1000 -- give it 1s to open
waitTill = now + math.min(g_game.getPing(),100)
waitingForContainer = container:getId()
loot.tries = loot.tries + 10
return true
end

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
--[[
Bot-based Tibia 12 features v1.0
Bot-based Tibia 12 features v1.1
made by Vithrax
Credits also to:
@ -11,7 +11,13 @@
br, Vithrax
]]
vBot.CaveBotData = vBot.CaveBotData or {
refills = 0,
rounds = 0,
time = {},
lastRefill = os.time(),
refillTime = {}
}
local lootWorth = 0
local wasteWorth = 0
local balance = 0
@ -58,8 +64,18 @@ storage.analyzers.trackedLoot = storage.analyzers.trackedLoot or {}
local trackedLoot = storage.analyzers.trackedLoot
--destroy old windows
local windowsTable = {"MainAnalyzerWindow", "HuntingAnalyzerWindow", "LootAnalyzerWindow", "SupplyAnalyzerWindow", "ImpactAnalyzerWindow", "XPAnalyzerWindow", "PartyAnalyzerWindow", "DropTracker"}
for i, window in ipairs(windowsTable) do
local windowsTable = {"MainAnalyzerWindow",
"HuntingAnalyzerWindow",
"LootAnalyzerWindow",
"SupplyAnalyzerWindow",
"ImpactAnalyzerWindow",
"XPAnalyzerWindow",
"PartyAnalyzerWindow",
"DropTracker",
"CaveBotStats"
}
for i, window in ipairs(windowsTable) do
local element = g_ui.getRootWidget():recursiveGetChildById(window)
if element then
@ -69,7 +85,7 @@ end
local mainWindow = UI.createMiniWindow("MainAnalyzerWindow")
mainWindow:hide()
mainWindow:setContentMaximumHeight(220)
mainWindow:setContentMaximumHeight(240)
local huntingWindow = UI.createMiniWindow("HuntingAnalyzer")
huntingWindow:hide()
local lootWindow = UI.createMiniWindow("LootAnalyzer")
@ -88,6 +104,8 @@ local partyHuntWindow = UI.createMiniWindow("PartyAnalyzerWindow")
partyHuntWindow:hide()
local dropTrackerWindow = UI.createMiniWindow("DropTracker")
dropTrackerWindow:hide()
local statsWindow = UI.createMiniWindow("CaveBotStats")
statsWindow:hide()
--f
local toggle = function()
@ -193,8 +211,29 @@ end
mainWindow.contentsPanel.DropTracker.onClick = function()
toggleAnalyzer(dropTrackerWindow)
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 xpGainLabel = UI.DualLabel("XP Gain:", "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")
drawGraph(xpGraph, 0)
--#############################################
--############################################# 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()
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 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
local uptime
sessionTime = function()
@ -860,6 +904,13 @@ local function niceFormat(v)
end
resetAnalyzerSessionData = function()
vBot.CaveBotData = vBot.CaveBotData or {
refills = 0,
rounds = 0,
time = {},
lastRefill = os.time(),
refillTime = {}
}
launchTime = now
startExp = exp()
dmgTable = {}
@ -923,24 +974,39 @@ local function getFrame(v)
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()
if not storage.analyzers.rarityFrames then return end
for _, container in pairs(getContainers()) do
local window = container.itemsPanel
for i, child in pairs(window:getChildren()) do
local id = child:getItemId()
local price = 0
if id ~= 0 then -- there's item
local item = Item.create(id)
local name = item:getMarketData().name:lower()
price = getPrice(name)
local price = getPrice(name)
-- set rarity frame
child:setImageSource(getFrame(price))
else -- empty widget
-- revert any possible changes
child:setImageSource("/images/ui/item")
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
@ -1178,20 +1244,21 @@ function refreshLoot()
lootList:destroyChildren()
for k,v in pairs(lootedItems) do
local label1 = UI.createWidget("AnalyzerLootItem", lootItems)
local price = v.count and getPrice(v.name) * v.count or getPrice(v.name)
local label1 = UI.createWidget("AnalyzerLootItem", lootItems)
local price = v.count and getPrice(v.name) * v.count or getPrice(v.name)
label1:setItemId(k)
label1:setItemCount(50)
label1:setShowCount(false)
label1.count:setText(niceFormat(v.count))
label1.count:setColor(getColor(price))
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)")
--hunting window loot list
local label2 = UI.createWidget("ListLabel", lootList)
label2:setText(v.count .. "x " .. v.name)
label1:setItemId(k)
label1:setItemCount(50)
label1:setShowCount(false)
label1.count:setText(niceFormat(v.count))
label1.count:setColor(getColor(price))
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)")
--hunting window loot list
local label2 = UI.createWidget("ListLabel", lootList)
label2:setText(v.count .. "x " .. v.name)
end
if lootItems:getChildCount() == 0 then
local label = UI.createWidget("ListLabel", lootList)
label:setText("None")
@ -1218,17 +1285,28 @@ refreshKills()
function refreshWaste()
supplyItems:destroyChildren()
for k,v in pairs(usedItems) do
local label1 = UI.createWidget("AnalyzerLootItem", supplyItems)
local price = v.count and getPrice(v.name) * v.count or getPrice(v.name)
suppliesByRefill:destroyChildren()
suppliesByRound:destroyChildren()
label1:setItemId(k)
label1:setItemCount(10023)
label1:setShowCount(false)
label1.count:setText(niceFormat(v.count))
label1.count:setColor(getColor(price))
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)")
local parents = {supplyItems, suppliesByRound, suppliesByRefill}
for k,v in pairs(usedItems) do
for i=1,#parents do
local amount = i == 1 and v.count or
i == 2 and v.count/(vBot.CaveBotData.rounds + 1) or
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
@ -1296,6 +1374,7 @@ end)
-- waste
local regex3 = [[\d ([a-z A-Z]*)s...]]
local lackOfData = {}
onTextMessage(function(mode, text)
text = text:lower()
if not text:find("using one of") then return end
@ -1305,6 +1384,16 @@ onTextMessage(function(mode, text)
local name = re[1][2]
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
useData[name] = amount
else
@ -1427,6 +1516,21 @@ function getHuntingData()
return totalDmg, totalHeal, lootWorth, wasteWorth, balance
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
local bestDPS = 0
local bestHPS = 0
@ -1489,6 +1593,15 @@ macro(500, function()
xpHourInXpLabel:setText(expPerHour())
nextLevelLabel:setText(timeToLevel())
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)
--graphs, draw each minute
@ -1576,4 +1689,33 @@ end
Analyzer.getTimeToNextLevel = function()
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

View File

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

View File

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

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
ConditionBoxPopupMenuButton < ComboBoxPopupMenuButton
ConditionBox < ComboBox
@ -70,7 +101,7 @@ Rule < UIWidget
ConditionPanel < Panel
height: 53
height: 58
NexButton
id: nex
@ -96,7 +127,7 @@ ConditionPanel < Panel
SpinBox
id: spinbox
anchors.top: description.bottom
margin-top: 5
margin-top: 10
anchors.horizontalCenter: parent.horizontalCenter
width: 100
text-align: center
@ -108,7 +139,7 @@ ConditionPanel < Panel
BotTextEdit
id: text
anchors.top: description.bottom
margin-top: 5
margin-top: 10
anchors.horizontalCenter: parent.horizontalCenter
width: 200
text-align: center
@ -166,6 +197,7 @@ ListPanel < FlatPanel
text-align: center
font: cipsoftFont
margin-top: 5
tooltip: Increase priority of selected rule.
Button
id: down
@ -176,43 +208,7 @@ ListPanel < FlatPanel
text: Move Down
text-align: center
font: cipsoftFont
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
tooltip: Decrease priority of selected rule.
InputPanel < FlatPanel
size: 270 300
@ -224,49 +220,21 @@ InputPanel < FlatPanel
id: title
anchors.verticalCenter: parent.top
anchors.left: parent.left
text: Input Panel
text: Condition Panel
font: verdana-11px-rounded
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
id: mainLabel
anchors.left: prev.right
anchors.left: parent.left
anchors.right: parent.right
margin-top: 2
anchors.verticalCenter: prev.verticalCenter
margin-left: 2
!text: tr('& Equip above item(s) when:')
anchors.top: prev.bottom
margin-top: 10
text: Equip selected items when:
text-align: center
font: verdana-11px-rounded
color: #aeaeae
Unequip
id: unequipPanel
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
HorizontalSeparator
anchors.left: parent.left
anchors.right: parent.right
@ -277,8 +245,8 @@ InputPanel < FlatPanel
id: condition
anchors.left: parent.left
anchors.right: parent.right
anchors.top: unequipPanel.bottom
margin-top: 8
anchors.top: mainLabel.bottom
margin-top: 15
HorizontalSeparator
anchors.verticalCenter: next.verticalCenter
@ -288,7 +256,7 @@ InputPanel < FlatPanel
ConditionBox
id: useSecondCondition
anchors.top: condition.bottom
margin-top: 3
margin-top: 10
anchors.horizontalCenter: parent.horizontalCenter
width: 50
@ -297,40 +265,210 @@ InputPanel < FlatPanel
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
margin-top: 10
HorizontalSeparator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
BotTextEdit
id: name
anchors.left: parent.left
BotButton
id: add
anchors.horizontalCenter: parent.horizontalCenter
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
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.bottom: prev.top
margin-bottom: 2
text-align: center
anchors.top: prev.bottom
margin-top: 5
$on:
image-source: /images/ui/item
SlotBotItem
id: finger
image-source: /images/game/slots/finger
anchors.horizontalCenter: prev.horizontalCenter
anchors.top: prev.bottom
margin-top: 5
$on:
image-source: /images/ui/item
Item
id: back
image-source: /images/game/slots/back-blessed
anchors.top: head.top
margin-top: 13
anchors.left: head.right
margin-left: 5
tooltip: Main back container modifications are unavailable.
SlotBotItem
id: right-hand
image-source: /images/game/slots/right-hand
anchors.horizontalCenter: prev.horizontalCenter
anchors.top: prev.bottom
margin-top: 5
$on:
image-source: /images/ui/item
SlotBotItem
id: ammo
image-source: /images/game/slots/ammo
anchors.horizontalCenter: prev.horizontalCenter
anchors.top: prev.bottom
margin-top: 5
BotButton
id: cloneEq
anchors.top: feet.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 15
text: Clone Current EQ
font: verdana-11px-rounded
tooltip: Copy currently equipped and non-equipped items.
BotButton
id: default
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 3
text: Reset fields
font: verdana-11px-rounded
tooltip: Reset all fields to the blank state
Profile < FlatPanel
size: 160 35
Label
id: title
anchors.verticalCenter: parent.top
anchors.left: parent.left
margin-left: 10
text: Profile Name
font: verdana-11px-rounded
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
id: addButton
anchors.top: name.top
anchors.bottom: name.bottom
anchors.left: name.right
margin-left: 3
anchors.right: parent.right
text: Add
tooltip: On add above rule will be listed as Profile name - use friendly one!
id: add
anchors.right: list.right
anchors.top: list.bottom
margin-top: 3
height: 21
text: Add Boss
text-align: center
font: verdana-11px-rounded
tooltip: Creature with given name will be considered as boss.
EquipWindow < MainWindow
size: 600 370
size: 750 350
text: Equipment Manager
@onEscape: self:hide()
@ -338,17 +476,44 @@ EquipWindow < MainWindow
id: listPanel
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: bottomSep.top
margin-bottom: 5
margin-left: -2
visible: false
BossList
id: bossPanel
anchors.fill: prev
visible: true
VerticalSeparator
anchors.top: parent.top
anchors.bottom: bottomSep.top
margin-bottom: 5
anchors.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
id: inputPanel
anchors.right: parent.right
anchors.left: prev.right
anchors.top: parent.top
anchors.bottom: bottomSep.top
margin-bottom: 5
margin-left: 5
HorizontalSeparator
id: bottomSep
@ -363,6 +528,12 @@ EquipWindow < MainWindow
font: cipsoftFont
anchors.right: parent.right
anchors.bottom: parent.bottom
size: 45 21
margin-top: 15
margin-right: 5
size: 45 21
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("machete", "Machete Item", 9596, leftPanel, "This item will be used in various bot related scripts as default machete item.")
addItem("scythe", "Scythe Item", 9596, leftPanel, "This item will be used in various bot related scripts as default scythe item.")
addCheckBox("pathfinding", "CaveBot Pathfinding", true, leftPanel, "Cavebot will automatically search for first reachable waypoint after missing 10 goto's.")
addScrollBar("talkDelay", "Global NPC Talk Delay", 0, 2000, 1000, leftPanel, "Breaks between each talk action in cavebot (time in miliseconds).")
addScrollBar("looting", "Max Loot Distance", 0, 50, 40, leftPanel, "Every loot corpse futher than set distance (in sqm) will be ignored and forgotten.")
addScrollBar("huntRoutes", "Hunting Rounds Limit", 0, 300, 50, leftPanel, "Round limit for supply check, if character already made more rounds than set, on next supply check will return to city.")
@ -419,7 +420,7 @@ if true then
if not settings.suppliesControl then return end
if TargetBot.isOff() then return end
if CaveBot.isOff() then return end
if not hasSupplies() then
if type(hasSupplies()) == 'table' then
TargetBot.setOff()
end
end)
@ -553,7 +554,7 @@ if true then
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)
if not settings.checkPlayer then return end

View File

@ -1,4 +1,4 @@
local version = "4.5"
local version = "4.7"
local currentVersion
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")
local tabs = {"Friends", "Enemies", "BlackList"}
local panelName = "playerList"
@ -191,8 +211,7 @@ if rootWidget then
menu:setId("blzMenu")
menu:setGameMenu(true)
menu:addOption('Check Player', function()
local name = widget:getText():gsub(" ", "_")
local link = "https://www.gunzodus.net/character/show/"
local name = widget:getText():gsub(" ", spacing)
g_platform.openUrl(link..name)
end, "")
menu:addOption('Copy Name', function()

View File

@ -33,7 +33,8 @@ if voc() == 2 or voc() == 12 then
local containers = getContainers()
for i, container in ipairs(containers) do
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
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.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
onPlayerPositionChange(function(x,y)
vBot.standTime = now
@ -300,7 +308,7 @@ end)
if onSpellCooldown and onGroupSpellCooldown then
onSpellCooldown(function(iconId, duration)
schedule(5, function()
schedule(1, function()
if not vBot.customCooldowns[lastPhrase] then
vBot.customCooldowns[lastPhrase] = {id = iconId}
end
@ -308,7 +316,7 @@ if onSpellCooldown and onGroupSpellCooldown then
end)
onGroupSpellCooldown(function(iconId, duration)
schedule(10, function()
schedule(2, function()
if vBot.customCooldowns[lastPhrase] then
vBot.customCooldowns[lastPhrase] = {id = vBot.customCooldowns[lastPhrase].id, group = {[iconId] = duration}}
end
@ -655,9 +663,9 @@ function getPlayers(range, multifloor)
if not range then range = 10 end
local specs = 0;
for _, spec in pairs(getSpectators(multifloor)) do
specs = not spec:isLocalPlayer() and spec:isPlayer() and
distanceFromPlayer(spec:getPosition()) <= range and
not (spec:isPartyMember() or spec:getEmblem() == 1) and specs + 1 or specs;
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
specs = specs + 1
end
end
return specs;
end
@ -750,21 +758,7 @@ end
-- also considers equipped items
-- returns number
function itemAmount(id)
local totalItemCount = 0
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
return player:getItemsCount(id)
end
-- self explanatory
@ -777,35 +771,6 @@ function useOnInvertoryItem(a, b)
return useWith(a, item)
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
-- returns table of tiles surrounding given POS/tile
function getNearTiles(pos)

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