Implement aoe pickup

This commit is contained in:
2025-03-31 03:37:25 +02:00
parent f07a1fe593
commit 5e33806c92
2 changed files with 151 additions and 0 deletions

View File

@@ -21,6 +21,7 @@ MyModGlobal = {
STACK_TO_CURSOR = Keys.G, STACK_TO_CURSOR = Keys.G,
LOOT = Keys.L, LOOT = Keys.L,
SONAR = Keys.X, SONAR = Keys.X,
AOEPICKUP = Keys.Y,
NESTED_CONTAINERS = true, NESTED_CONTAINERS = true,
DEBUG_MODE = true, DEBUG_MODE = true,
}, },
@@ -65,6 +66,7 @@ local quickunload = require("Cyka.quickunload")
local quickreload= require("Cyka.quickreload") local quickreload= require("Cyka.quickreload")
local quickloot = require("Cyka.quickloot") local quickloot = require("Cyka.quickloot")
local sonarpinger = require("Cyka.sonarpinger") local sonarpinger = require("Cyka.sonarpinger")
local aoepickup = require("Cyka.aoepickup")
require("Cyka.xpticker") require("Cyka.xpticker")
require("Cyka.zoom") require("Cyka.zoom")
@@ -151,3 +153,8 @@ Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptab
if not PlayerInput.KeyHit(MyModGlobal.CONFIG.SONAR) then return end if not PlayerInput.KeyHit(MyModGlobal.CONFIG.SONAR) then return end
sonarpinger.tryPing() sonarpinger.tryPing()
end, Hook.HookMethodType.After) end, Hook.HookMethodType.After)
Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable)
if not PlayerInput.KeyHit(MyModGlobal.CONFIG.AOEPICKUP) then return end
aoepickup.tryAoePickup()
end, Hook.HookMethodType.After)

View File

@@ -0,0 +1,144 @@
-- luacheck: globals Item Vector2 Character MyModGlobal
-- luacheck: max line length 420
local dump = require("Cyka.dump")
local quickstack = require("Cyka.quickstack")
---@class ItemLocation
---@field item Barotrauma.Item
---@field distance number
---@param A Vector2
---@param B Vector2
---@return number
local function getDistanceQuick(A, B)
return math.abs(A.X - B.X) + math.abs(A.Y - B.Y)
end
---@param source Vector2
---@param distanceThreshold number
---@return ItemLocation[]
local function getNearbyItems(source, distanceThreshold)
-- local log = {}
---@type ItemLocation[]
local items = {}
local whitelistedComponents = "Holdable,Pickable,Wearable"
local blacklistedComponents = "ConnectionPanel"
for item in Item.ItemList do
-- log[#log + 1] = string.format("Checking item %s", tostring(item))
local distance, tags, hasAnyOfComponent
---@cast item Barotrauma.Item
local parentInventory = item.ParentInventory
if parentInventory then
-- log[#log + 1] = string.format("Item %s is in an inventory", tostring(item))
goto continue
end
tags = tostring(item.Tags)
if not string.find(tags, "item") then
-- log[#log + 1] = string.format("Item %s is not an item (but a structure) - %s", tostring(item), tags)
goto continue
end
for component in item.Components do
-- For some God forsaken reason this does not work
-- Not that it classifies the incorrect items
-- But it just literally does not work
-- The code does not execute
-- Some of the items vanish into thin air, as if they never existed
-- I have no idea why
-- So we'll do this in 2 steps...
-- if string.find(blacklistedComponents, component.Name) then
-- log[#log + 1] = string.format("Item %s has blacklisted component %s - %s", tostring(item), component.Name, component.Name)
-- goto continue
-- end
if string.find(whitelistedComponents, component.Name) then
hasAnyOfComponent = true
break
end
end
if not hasAnyOfComponent then
-- log[#log + 1] = string.format("Item %s is not %s", tostring(item), whitelistedComponents)
goto continue
end
distance = getDistanceQuick(item.WorldPosition, source)
if distance > distanceThreshold then
-- log[#log + 1] = string.format("Item %s is too far away - %s", tostring(item), distance)
goto continue
end
items[#items + 1] = {
item = item,
distance = distance,
}
::continue::
end
-- print(table.concat(log, "\n"))
table.sort(items, function(a, b)
return a.distance < b.distance
end)
-- local str = ""
-- for _, item in pairs(items) do
-- str = str .. tostring(item.item) .. " " .. item.distance .. " "
-- local tags = tostring(item.item.Tags)
-- str = str .. tags .. " "
-- for component in item.item.Components do
-- str = str .. component.Name .. " "
-- end
-- str = str .. "---" .. "\n"
-- end
-- print(str)
local filteredItems = {}
for _, item in pairs(items) do
for component in item.item.Components do
if string.find(blacklistedComponents, component.Name) then
goto continue
end
end
filteredItems[#filteredItems + 1] = item.item
::continue::
end
dump(filteredItems)
-- str = ""
-- for _, item in pairs(filteredItems) do
-- str = str .. tostring(item) .. " "
-- local tags = tostring(item.Tags)
-- str = str .. tags .. " "
-- for component in item.Components do
-- str = str .. component.Name .. " "
-- end
-- str = str .. "---" .. "\n"
-- end
-- print(str)
return filteredItems
end
local function tryAoePickup()
MyModGlobal.debugPrint("tryAoePickup")
local character = Character.Controlled
if not character then
MyModGlobal.debugPrint("No controlled character")
return
end
local itemTree, err = quickstack.tryBuildCharacterItemTree(character)
if err then
MyModGlobal.debugPrint(err)
return
end
local distanceThreshold = 500
local characterPos = character.WorldPosition
local nearbyItems = getNearbyItems(characterPos, distanceThreshold)
local errors = quickstack.tryMoveItems(nearbyItems, itemTree, true)
for _, error in pairs(errors) do
MyModGlobal.debugPrint(string.format("Error moving items: %s", error))
end
end
return {
tryAoePickup = tryAoePickup,
}