Implement quick reload
This commit is contained in:
@@ -17,6 +17,7 @@ MyModGlobal = {
|
|||||||
MAX_BUY = Keys.B,
|
MAX_BUY = Keys.B,
|
||||||
FIX = Keys.R,
|
FIX = Keys.R,
|
||||||
UNLOAD = Keys.E,
|
UNLOAD = Keys.E,
|
||||||
|
RELOAD = Keys.R,
|
||||||
NESTED_CONTAINERS = true,
|
NESTED_CONTAINERS = true,
|
||||||
DEBUG_MODE = true,
|
DEBUG_MODE = true,
|
||||||
},
|
},
|
||||||
@@ -58,6 +59,7 @@ local quickbuy = require("Cyka.quickbuy")
|
|||||||
local hotkeyrepair = require("Cyka.hotkeyrepair")
|
local hotkeyrepair = require("Cyka.hotkeyrepair")
|
||||||
local cursormacroer = require("Cyka.cursormacroer")
|
local cursormacroer = require("Cyka.cursormacroer")
|
||||||
local quickunload = require("Cyka.quickunload")
|
local quickunload = require("Cyka.quickunload")
|
||||||
|
local quickreload= require("Cyka.quickreload")
|
||||||
require("Cyka.xpticker")
|
require("Cyka.xpticker")
|
||||||
|
|
||||||
print(MyModGlobal.MOD_NAME .. " v" .. MyModGlobal.MOD_VERSION .. " loaded!")
|
print(MyModGlobal.MOD_NAME .. " v" .. MyModGlobal.MOD_VERSION .. " loaded!")
|
||||||
@@ -119,3 +121,8 @@ Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptab
|
|||||||
if not PlayerInput.KeyHit(MyModGlobal.CONFIG.UNLOAD) then return end
|
if not PlayerInput.KeyHit(MyModGlobal.CONFIG.UNLOAD) then return end
|
||||||
quickunload.tryUnloadCursorItem()
|
quickunload.tryUnloadCursorItem()
|
||||||
end, Hook.HookMethodType.After)
|
end, Hook.HookMethodType.After)
|
||||||
|
|
||||||
|
Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable)
|
||||||
|
if not PlayerInput.KeyHit(MyModGlobal.CONFIG.RELOAD) then return end
|
||||||
|
quickreload.tryReloadCursorItem(PlayerInput.IsShiftDown())
|
||||||
|
end, Hook.HookMethodType.After)
|
||||||
|
210
QuickStackToBag/Lua/Cyka/quickreload.lua
Normal file
210
QuickStackToBag/Lua/Cyka/quickreload.lua
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
-- luacheck: globals Character MyModGlobal Timer
|
||||||
|
local cursormacroer = require("Cyka.cursormacroer")
|
||||||
|
local utils = require("Cyka.utils")
|
||||||
|
local dump = require("Cyka.dump")
|
||||||
|
|
||||||
|
---@param inventory Barotrauma.ItemInventory
|
||||||
|
---@param predicate fun(slot: InventorySlot): boolean
|
||||||
|
---@return InventorySlot[], string?
|
||||||
|
local function findSlotsThat(inventory, predicate)
|
||||||
|
local slots = {}
|
||||||
|
for i, slot in ipairs(inventory.slots) do
|
||||||
|
local inventorySlot = {
|
||||||
|
slot = slot,
|
||||||
|
inventory = inventory,
|
||||||
|
slotIndex = i - 1
|
||||||
|
}
|
||||||
|
if predicate(inventorySlot) then
|
||||||
|
slots[#slots + 1] = inventorySlot
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return slots
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param slot InventorySlot
|
||||||
|
---@param preferMinCondition boolean
|
||||||
|
local function tryReloadSlot(slot, preferMinCondition)
|
||||||
|
---@type Barotrauma.Item
|
||||||
|
local item = slot.slot.items[1]
|
||||||
|
if not item then
|
||||||
|
MyModGlobal.debugPrint("No item in slot")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local inventory = item.OwnInventory
|
||||||
|
if not inventory then
|
||||||
|
MyModGlobal.debugPrint("Item has no own inventory")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
---@type InventorySlot[]
|
||||||
|
local toLoad = {}
|
||||||
|
local inventorySlots = inventory.slots
|
||||||
|
for i, inventorySlot in ipairs(inventorySlots) do
|
||||||
|
toLoad[#toLoad + 1] = {
|
||||||
|
inventory = inventory,
|
||||||
|
slotIndex = i - 1,
|
||||||
|
slot = inventorySlot
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local character = Character.Controlled
|
||||||
|
if not character then
|
||||||
|
MyModGlobal.debugPrint("No character")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local characterInventory = character.Inventory
|
||||||
|
if not characterInventory then
|
||||||
|
MyModGlobal.debugPrint("No character inventory")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- How many items can we move to what slot
|
||||||
|
-- We don't yet know what can fit into what slot
|
||||||
|
---@type table<InventorySlot, Barotrauma.Item[]>
|
||||||
|
local movableBySlot = {}
|
||||||
|
-- Get all the items and then we will sort them by condition and shit
|
||||||
|
utils.enqueueInventory(characterInventory, {}, function(ititem)
|
||||||
|
for _, inventorySlot in ipairs(toLoad) do
|
||||||
|
local canMove = inventorySlot.inventory.CanBePutInSlot(ititem, inventorySlot.slotIndex)
|
||||||
|
if canMove then
|
||||||
|
movableBySlot[inventorySlot] = movableBySlot[inventorySlot] or {}
|
||||||
|
movableBySlot[inventorySlot][#movableBySlot[inventorySlot] + 1] = ititem
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end)
|
||||||
|
-- print("movableBySlot")
|
||||||
|
-- dump(movableBySlot)
|
||||||
|
|
||||||
|
-- The point of this exercise is to eliminate slots that can have
|
||||||
|
-- Multiple items
|
||||||
|
-- What do we put into those? Any? All?
|
||||||
|
-- What if those slots belong to a container?
|
||||||
|
-- Are we reloading 30 slot containers?
|
||||||
|
---@type table<InventorySlot, Barotrauma.ItemPrefab>
|
||||||
|
local permissibleItemsPerSlot = {}
|
||||||
|
for inventorySlot, items in pairs(movableBySlot) do
|
||||||
|
for _, ititem in ipairs(items) do
|
||||||
|
local existing = permissibleItemsPerSlot[inventorySlot]
|
||||||
|
local thisone = ititem.Prefab
|
||||||
|
if existing and not existing.Equals(thisone) then
|
||||||
|
print("Already have an item in this slot, can not have 2?")
|
||||||
|
movableBySlot[inventorySlot] = nil
|
||||||
|
end
|
||||||
|
permissibleItemsPerSlot[inventorySlot] = thisone
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- print("permissibleItemsPerSlot")
|
||||||
|
-- dump(permissibleItemsPerSlot)
|
||||||
|
-- print("movableBySlot")
|
||||||
|
-- dump(movableBySlot)
|
||||||
|
|
||||||
|
-- Sort items by condition (asc or desc) but also
|
||||||
|
-- Make sure items with 0 condition are at the end
|
||||||
|
-- We don't really want to load those
|
||||||
|
for _, items in pairs(movableBySlot) do
|
||||||
|
table.sort(items, function(a, b)
|
||||||
|
if a.ConditionPercentage == 0 and b.ConditionPercentage ~= 0 then
|
||||||
|
return false
|
||||||
|
elseif a.ConditionPercentage ~= 0 and b.ConditionPercentage == 0 then
|
||||||
|
return true
|
||||||
|
elseif preferMinCondition then
|
||||||
|
return a.ConditionPercentage < b.ConditionPercentage
|
||||||
|
else
|
||||||
|
return a.ConditionPercentage > b.ConditionPercentage
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
dump(movableBySlot)
|
||||||
|
|
||||||
|
for inventorySlot, items in pairs(movableBySlot) do
|
||||||
|
for _, ititem in ipairs(items) do
|
||||||
|
local moved = inventorySlot.inventory.TryPutItem(ititem, inventorySlot.slotIndex, false, true, nil)
|
||||||
|
-- When the slot is full no more will be able to be moved
|
||||||
|
-- And tat that point we're done with that slot
|
||||||
|
if not moved then break end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- -- Where can we put our toUnload items?
|
||||||
|
-- local nearbySlots = findSlotsThat(slot.inventory, function(islot)
|
||||||
|
-- local isEmpty = #islot.slot.items == 0
|
||||||
|
-- if isEmpty then return true end
|
||||||
|
|
||||||
|
-- for _, prefab in ipairs(toUnloadByPrefab) do
|
||||||
|
-- local canAccept = islot.inventory.CanBePutInSlot(prefab, islot.slotIndex)
|
||||||
|
-- if canAccept then return true end
|
||||||
|
-- end
|
||||||
|
-- return false
|
||||||
|
-- end)
|
||||||
|
-- -- print("Before sorting:")
|
||||||
|
-- -- dump(nearbySlots)
|
||||||
|
|
||||||
|
-- -- Some inventories don't have slots per row, like the player inventory
|
||||||
|
-- local slotsPerRow = 900
|
||||||
|
-- local ok, err = pcall(function()
|
||||||
|
-- slotsPerRow = slot.inventory.slotsPerRow
|
||||||
|
-- end)
|
||||||
|
-- if not ok then
|
||||||
|
-- MyModGlobal.debugPrint(string.format("Error getting slots per row: %s", err))
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- local getGridPos = function(slotIndex)
|
||||||
|
-- local x = slotIndex % slotsPerRow
|
||||||
|
-- local y = math.floor(slotIndex / slotsPerRow)
|
||||||
|
-- return x, y
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- -- We are offsetting here by 1 because the backend uses 0-indexed slots
|
||||||
|
-- -- And the lua uses 1-indexed slots
|
||||||
|
-- -- We are trying to match the backend behavior for sorting
|
||||||
|
-- local slotx, sloty = getGridPos(slot.slotIndex - 1)
|
||||||
|
-- -- print(string.format("Slot position %d: %d, %d", slot.slotIndex, slotx, sloty))
|
||||||
|
-- table.sort(nearbySlots, function(a, b)
|
||||||
|
-- local ax, ay = getGridPos(a.slotIndex)
|
||||||
|
-- local bx, by = getGridPos(b.slotIndex)
|
||||||
|
|
||||||
|
-- local distA = math.max(math.abs(ax - slotx), math.abs(ay - sloty))
|
||||||
|
-- local distB = math.max(math.abs(bx - slotx), math.abs(by - sloty))
|
||||||
|
|
||||||
|
-- if distA == distB then
|
||||||
|
-- return a.slotIndex < b.slotIndex
|
||||||
|
-- end
|
||||||
|
-- return distA < distB
|
||||||
|
-- end)
|
||||||
|
-- -- print(string.format("Current slot: %d at (%d, %d)", slot.slotIndex, slotx, sloty))
|
||||||
|
|
||||||
|
-- for _, iitem in ipairs(toUnload) do
|
||||||
|
-- for _, nearbySlot in ipairs(nearbySlots) do
|
||||||
|
-- local canAccept = nearbySlot.inventory.CanBePutInSlot(iitem.Prefab, nearbySlot.slotIndex)
|
||||||
|
-- if canAccept then
|
||||||
|
-- local moved = nearbySlot.inventory.TryPutItem(iitem, nearbySlot.slotIndex, true, false, nil)
|
||||||
|
-- -- print(string.format("Moved item %s to slot %d", iitem.Name, nearbySlot.slotIndex))
|
||||||
|
-- if moved then break end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param minCondition boolean Prefer items with lowest condition
|
||||||
|
local function tryReloadCursorItem(preferMinCondition)
|
||||||
|
local slots, err = cursormacroer.getInventorySlotsUnderCursor()
|
||||||
|
if err then
|
||||||
|
-- MyModGlobal.debugPrint(string.format("Error getting inventory slot: %s", err))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if not slots or #slots == 0 then
|
||||||
|
-- MyModGlobal.debugPrint("No items in slot")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, slot in ipairs(slots) do
|
||||||
|
tryReloadSlot(slot, preferMinCondition)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
tryReloadCursorItem = tryReloadCursorItem,
|
||||||
|
}
|
Reference in New Issue
Block a user