mirror of
https://github.com/OTCv8/otclientv8.git
synced 2025-04-29 18:59:20 +02:00
432 lines
13 KiB
Lua
432 lines
13 KiB
Lua
local context = G.botContext
|
|
local Panels = context.Panels
|
|
|
|
Panels.Looting = function(parent)
|
|
local ui = context.setupUI([[
|
|
Panel
|
|
id: looting
|
|
height: 180
|
|
|
|
BotLabel
|
|
anchors.top: parent.top
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
text: Looting
|
|
|
|
ComboBox
|
|
id: config
|
|
anchors.top: prev.bottom
|
|
anchors.left: parent.left
|
|
margin-top: 5
|
|
text-offset: 3 0
|
|
width: 130
|
|
|
|
Button
|
|
id: enableButton
|
|
anchors.top: prev.top
|
|
anchors.left: prev.right
|
|
anchors.right: parent.right
|
|
margin-left: 5
|
|
|
|
Button
|
|
margin-top: 1
|
|
id: add
|
|
anchors.top: prev.bottom
|
|
anchors.left: parent.left
|
|
text: Add
|
|
width: 60
|
|
height: 17
|
|
|
|
Button
|
|
id: edit
|
|
anchors.top: prev.top
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
text: Edit
|
|
width: 60
|
|
height: 17
|
|
|
|
Button
|
|
id: remove
|
|
anchors.top: prev.top
|
|
anchors.right: parent.right
|
|
text: Remove
|
|
width: 60
|
|
height: 17
|
|
|
|
ScrollablePanel
|
|
id: items
|
|
anchors.top: prev.bottom
|
|
anchors.right: parent.right
|
|
anchors.left: parent.left
|
|
vertical-scrollbar: scrollBar
|
|
margin-right: 5
|
|
margin-top: 2
|
|
height: 70
|
|
layout:
|
|
type: grid
|
|
cell-size: 34 34
|
|
flow: true
|
|
|
|
BotSmallScrollBar
|
|
id: scrollBar
|
|
anchors.top: prev.top
|
|
anchors.bottom: prev.bottom
|
|
anchors.right: parent.right
|
|
step: 10
|
|
pixels-scroll: true
|
|
|
|
BotLabel
|
|
anchors.top: prev.bottom
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
margin-top: 4
|
|
text: Loot Containers
|
|
|
|
ItemsRow
|
|
id: containers
|
|
anchors.top: prev.bottom
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
height: 33
|
|
margin-top: 2
|
|
|
|
]], parent)
|
|
|
|
local lootContainers = { ui.containers.item1, ui.containers.item2, ui.containers.item3, ui.containers.item4, ui.containers.item5 }
|
|
|
|
if type(context.storage.looting) ~= "table" then
|
|
context.storage.looting = {}
|
|
end
|
|
if type(context.storage.looting.configs) ~= "table" then
|
|
context.storage.looting.configs = {}
|
|
end
|
|
|
|
local getConfigName = function(config)
|
|
local matches = regexMatch(config, [[name:\s*([^\n]*)$]])
|
|
if matches[1] and matches[1][2] then
|
|
return matches[1][2]:trim()
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local items = {}
|
|
local itemsByKey = {}
|
|
local containers = {}
|
|
local commands = {}
|
|
local refreshConfig = nil -- declared later
|
|
|
|
local createNewConfig = function(focusedWidget)
|
|
if not context.storage.looting.activeConfig or not context.storage.looting.configs[context.storage.looting.activeConfig] then
|
|
return
|
|
end
|
|
|
|
local tmpItems = {}
|
|
local tmpContainers = {}
|
|
local focusIndex = 0
|
|
|
|
local newConfig = ""
|
|
for i, text in ipairs(commands) do
|
|
newConfig = newConfig .. text .. "\n"
|
|
end
|
|
for i=1,ui.items:getChildCount() do
|
|
local widget = ui.items:getChildByIndex(i)
|
|
if widget and widget:getItemId() >= 100 then
|
|
if tmpItems[widget:getItemId()] == nil then
|
|
tmpItems[widget:getItemId()] = 1
|
|
newConfig = newConfig .. "\n" .. widget:getItemId()
|
|
end
|
|
end
|
|
if widget == focusedWidget then
|
|
focusIndex = i
|
|
end
|
|
end
|
|
for i, widget in ipairs(lootContainers) do
|
|
if widget:getItemId() >= 100 then
|
|
if tmpContainers[widget:getItemId()] == nil then
|
|
tmpContainers[widget:getItemId()] = 1 -- remove duplicates
|
|
newConfig = newConfig .. "\ncontainer:" .. widget:getItemId()
|
|
end
|
|
end
|
|
end
|
|
|
|
context.storage.looting.configs[context.storage.looting.activeConfig] = newConfig
|
|
refreshConfig(focusIndex)
|
|
end
|
|
|
|
local parseConfig = function(config)
|
|
items = {}
|
|
itemsByKey = {}
|
|
containers = {}
|
|
commands = {}
|
|
local matches = regexMatch(config, [[([^:^\n^\s]+)(:?)([^\n]*)]])
|
|
for i=1,#matches do
|
|
local command = matches[i][2]
|
|
local validation = (matches[i][3] == ":")
|
|
local text = matches[i][4]
|
|
local commandAsNumber = tonumber(command)
|
|
local textAsNumber = tonumber(text)
|
|
if commandAsNumber and commandAsNumber >= 100 then
|
|
table.insert(items, commandAsNumber)
|
|
itemsByKey[commandAsNumber] = 1
|
|
elseif command == "container" and validation and textAsNumber and textAsNumber >= 100 then
|
|
containers[textAsNumber] = 1
|
|
elseif validation then
|
|
table.insert(commands, command .. ":" .. text)
|
|
end
|
|
end
|
|
|
|
local itemsToShow = #items + 2
|
|
if itemsToShow % 5 ~= 0 then
|
|
itemsToShow = itemsToShow + 5 - itemsToShow % 5
|
|
end
|
|
if itemsToShow < 10 then
|
|
itemsToShow = 10
|
|
end
|
|
|
|
for i=1,itemsToShow do
|
|
local widget = g_ui.createWidget("BotItem", ui.items)
|
|
local itemId = 0
|
|
if i <= #items then
|
|
itemId = items[i]
|
|
end
|
|
widget:setItemId(itemId)
|
|
widget.onItemChange = createNewConfig
|
|
end
|
|
|
|
for i, widget in ipairs(lootContainers) do
|
|
widget:setItemId(0)
|
|
end
|
|
local containerIndex = 1
|
|
for containerId, i in pairs(containers) do
|
|
if lootContainers[containerIndex] then
|
|
lootContainers[containerIndex]:setItemId(containerId)
|
|
end
|
|
containerIndex = containerIndex + 1
|
|
end
|
|
for i, widget in ipairs(lootContainers) do
|
|
widget.onItemChange = createNewConfig
|
|
end
|
|
end
|
|
|
|
local ignoreOnOptionChange = true
|
|
refreshConfig = function(focusIndex)
|
|
ignoreOnOptionChange = true
|
|
if context.storage.looting.enabled then
|
|
ui.enableButton:setText("On")
|
|
ui.enableButton:setColor('#00AA00FF')
|
|
else
|
|
ui.enableButton:setText("Off")
|
|
ui.enableButton:setColor('#FF0000FF')
|
|
end
|
|
|
|
ui.config:clear()
|
|
for i, config in ipairs(context.storage.looting.configs) do
|
|
local name = getConfigName(config)
|
|
if not name then
|
|
name = "Unnamed config"
|
|
end
|
|
ui.config:addOption(name)
|
|
end
|
|
|
|
if (not context.storage.looting.activeConfig or context.storage.looting.activeConfig == 0) and #context.storage.looting.configs > 0 then
|
|
context.storage.looting.activeConfig = 1
|
|
end
|
|
|
|
ui.items:destroyChildren()
|
|
for i, widget in ipairs(lootContainers) do
|
|
widget.onItemChange = nil
|
|
widget:setItemId(0)
|
|
widget:setItemCount(0)
|
|
end
|
|
|
|
if context.storage.looting.activeConfig and context.storage.looting.configs[context.storage.looting.activeConfig] then
|
|
ui.config:setCurrentIndex(context.storage.looting.activeConfig)
|
|
parseConfig(context.storage.looting.configs[context.storage.looting.activeConfig])
|
|
end
|
|
|
|
context.saveConfig()
|
|
if focusIndex and focusIndex > 0 and ui.items:getChildByIndex(focusIndex) then
|
|
ui.items:focusChild(ui.items:getChildByIndex(focusIndex))
|
|
end
|
|
|
|
ignoreOnOptionChange = false
|
|
end
|
|
|
|
ui.config.onOptionChange = function(widget)
|
|
if not ignoreOnOptionChange then
|
|
context.storage.looting.activeConfig = widget.currentIndex
|
|
refreshConfig()
|
|
end
|
|
end
|
|
ui.enableButton.onClick = function()
|
|
if not context.storage.looting.activeConfig or not context.storage.looting.configs[context.storage.looting.activeConfig] then
|
|
return
|
|
end
|
|
context.storage.looting.enabled = not context.storage.looting.enabled
|
|
refreshConfig()
|
|
end
|
|
ui.add.onClick = function()
|
|
modules.game_textedit.multilineEditor("Looting editor", "name:Config name", function(newText)
|
|
table.insert(context.storage.looting.configs, newText)
|
|
context.storage.looting.activeConfig = #context.storage.looting.configs
|
|
refreshConfig()
|
|
end)
|
|
end
|
|
ui.edit.onClick = function()
|
|
if not context.storage.looting.activeConfig or not context.storage.looting.configs[context.storage.looting.activeConfig] then
|
|
return
|
|
end
|
|
modules.game_textedit.multilineEditor("Looting editor", context.storage.looting.configs[context.storage.looting.activeConfig], function(newText)
|
|
context.storage.looting.configs[context.storage.looting.activeConfig] = newText
|
|
refreshConfig()
|
|
end)
|
|
end
|
|
ui.remove.onClick = function()
|
|
if not context.storage.looting.activeConfig or not context.storage.looting.configs[context.storage.looting.activeConfig] then
|
|
return
|
|
end
|
|
local questionWindow = nil
|
|
local closeWindow = function()
|
|
questionWindow:destroy()
|
|
end
|
|
local removeConfig = function()
|
|
closeWindow()
|
|
if not context.storage.looting.activeConfig or not context.storage.looting.configs[context.storage.looting.activeConfig] then
|
|
return
|
|
end
|
|
context.storage.looting.enabled = false
|
|
table.remove(context.storage.looting.configs, context.storage.looting.activeConfig)
|
|
context.storage.looting.activeConfig = 0
|
|
refreshConfig()
|
|
end
|
|
questionWindow = context.displayGeneralBox(tr('Remove config'), tr('Do you want to remove current looting config?'), {
|
|
{ text=tr('Yes'), callback=removeConfig },
|
|
{ text=tr('No'), callback=closeWindow },
|
|
anchor=AnchorHorizontalCenter}, removeConfig, closeWindow)
|
|
end
|
|
refreshConfig()
|
|
|
|
context.onContainerOpen(function(container, prevContainer)
|
|
if context.storage.attacking.enabled then
|
|
return
|
|
end
|
|
if prevContainer then
|
|
container.autoLooting = prevContainer.autoLooting
|
|
else
|
|
container.autoLooting = true
|
|
end
|
|
end)
|
|
|
|
context.macro(200, function()
|
|
if not context.storage.looting.enabled then
|
|
return
|
|
end
|
|
local candidates = {}
|
|
local lootContainersCandidates = {}
|
|
for containerId, container in pairs(g_game.getContainers()) do
|
|
local containerItem = container:getContainerItem()
|
|
if container.autoLooting and container:getItemsCount() > 0 and (not containerItem or containers[containerItem:getId()] == nil) then
|
|
table.insert(candidates, container)
|
|
elseif containerItem and containers[containerItem:getId()] ~= nil then
|
|
table.insert(lootContainersCandidates, container)
|
|
end
|
|
end
|
|
if #lootContainersCandidates == 0 then
|
|
for slot = InventorySlotFirst, InventorySlotLast do
|
|
local item = context.getInventoryItem(slot)
|
|
if item and item:isContainer() and containers[item:getId()] ~= nil then
|
|
table.insert(lootContainersCandidates, item)
|
|
end
|
|
end
|
|
if #lootContainersCandidates > 0 then
|
|
-- try to open inventory backpack
|
|
local target = lootContainersCandidates[math.random(1,#lootContainersCandidates)]
|
|
g_game.open(target, nil)
|
|
context.delay(200)
|
|
end
|
|
return
|
|
end
|
|
|
|
if #candidates == 0 then
|
|
return
|
|
end
|
|
|
|
local container = candidates[math.random(1,#candidates)]
|
|
local nextContainers = {}
|
|
local foundItem = nil
|
|
for i, item in ipairs(container:getItems()) do
|
|
if item:isContainer() then
|
|
table.insert(nextContainers, item)
|
|
elseif itemsByKey[item:getId()] ~= nil then
|
|
foundItem = item
|
|
break
|
|
end
|
|
end
|
|
|
|
-- found item to loot
|
|
if foundItem then
|
|
-- find backpack for it, first backpack with same items
|
|
for i, container in ipairs(lootContainersCandidates) do
|
|
if container:getItemsCount() < container:getCapacity() or foundItem:isStackable() then -- has space
|
|
for j, item in ipairs(container:getItems()) do
|
|
if item:getId() == foundItem:getId() then
|
|
if foundItem:isStackable() then
|
|
if item:getCount() ~= 100 then
|
|
g_game.move(foundItem, container:getSlotPosition(j - 1), foundItem:getCount())
|
|
return
|
|
end
|
|
else
|
|
g_game.move(foundItem, container:getSlotPosition(container:getItemsCount()), foundItem:getCount())
|
|
return
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
-- now any backpack with empty slot
|
|
for i, container in ipairs(lootContainersCandidates) do
|
|
if container:getItemsCount() < container:getCapacity() then -- has space
|
|
g_game.move(foundItem, container:getSlotPosition(container:getItemsCount()), foundItem:getCount())
|
|
return
|
|
end
|
|
end
|
|
|
|
-- can't find backpack, try to open new
|
|
for i, container in ipairs(lootContainersCandidates) do
|
|
local candidates = {}
|
|
for j, item in ipairs(container:getItems()) do
|
|
if item:isContainer() and containers[item:getId()] ~= nil then
|
|
table.insert(candidates, item)
|
|
end
|
|
end
|
|
if #candidates > 0 then
|
|
g_game.open(candidates[math.random(1,#candidates)], container)
|
|
return
|
|
end
|
|
-- full, close it
|
|
g_game.close(container)
|
|
return
|
|
end
|
|
return
|
|
end
|
|
|
|
-- open remaining containers
|
|
if #nextContainers == 0 then
|
|
return
|
|
end
|
|
local delay = 1
|
|
for i=2,#nextContainers do
|
|
-- if more than 1 container, open them in new window
|
|
context.schedule(delay, function()
|
|
g_game.open(nextContainers[i], nil)
|
|
end)
|
|
delay = delay + 250
|
|
end
|
|
context.schedule(delay, function()
|
|
g_game.open(nextContainers[1], container)
|
|
end)
|
|
context.delay(150 + delay)
|
|
end)
|
|
end
|
|
|