Implement aoe pickup
This commit is contained in:
@@ -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)
|
||||||
|
144
QuickStackToBag/Lua/Cyka/aoepickup.lua
Normal file
144
QuickStackToBag/Lua/Cyka/aoepickup.lua
Normal 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,
|
||||||
|
}
|
Reference in New Issue
Block a user