if SERVER then return end -- Register necessary types and make fields accessible LuaUserData.RegisterType("Barotrauma.PurchasedItem") LuaUserData.RegisterType("Barotrauma.GUIButton") LuaUserData.RegisterType("Barotrauma.GUINumberInput") LuaUserData.RegisterType("Barotrauma.GUIComponent") LuaUserData.RegisterType("Barotrauma.GUIFrame") LuaUserData.RegisterType("Barotrauma.GUILayoutGroup") LuaUserData.RegisterType("Barotrauma.Store") LuaUserData.RegisterType("Barotrauma.RectTransform") LuaUserData.RegisterType("Barotrauma.TextManager") LuaUserData.RegisterType("Barotrauma.LocalizedString") -- Configuration local CONFIG = { DEBUG_MODE = true, -- Print debug messages BUTTON_TEXT = "BUY ALL", -- Text to display on the button KEY_CODE = Keys.V -- Key to press for quick buying all } -- MOD INFO local MOD_NAME = "Buy All Items" local MOD_VERSION = "1.2.2" -- Global state tracking local createdButton = false print(MOD_NAME .. " v" .. MOD_VERSION .. " loaded!") -- Debugging helper function local function debugPrint(message) if CONFIG.DEBUG_MODE then print("[" .. MOD_NAME .. "] " .. message) end end -- Show notification to player local function showNotification(message) -- Method 1: Print to console (always works) print("[" .. MOD_NAME .. "] " .. message) -- Method 2: Try to use Game.ShowChatMessage if available pcall(function() if Game and Game.ShowChatMessage then Game.ShowChatMessage(message, ChatMessageType.Server) end end) end -- Function to set all items in shopping cart to maximum value local function buyAllItems() debugPrint("Attempting to buy all items...") local itemsUpdated = 0 local numberInputsFound = 0 pcall(function() -- Get the Game Session and CargoManager if not Game or not Game.GameSession or not Game.GameSession.Campaign then debugPrint("No game session or campaign found") return end local cargoManager = Game.GameSession.Campaign.CargoManager if not cargoManager then debugPrint("No cargo manager found") return end debugPrint("Found cargo manager") -- Try to directly access the ItemsInBuyCrate field local storesWithItems = {} if cargoManager.ItemsInBuyCrate then debugPrint("ItemsInBuyCrate field found, checking contents") local anyItems = false for storeId, items in pairs(cargoManager.ItemsInBuyCrate) do if #items > 0 then debugPrint("Found store ID: " .. storeId.Value .. " with " .. #items .. " items") anyItems = true table.insert(storesWithItems, storeId) end end if not anyItems then debugPrint("ItemsInBuyCrate exists but contains no items") end else debugPrint("ItemsInBuyCrate field not found") end -- Process items from all stores that have items in the buy crate if #storesWithItems > 0 then debugPrint("Found " .. #storesWithItems .. " stores with items") -- Try to get stores either from current location or directly local validStores = {} -- First try: Get current store if cargoManager.CurrentStore then table.insert(validStores, cargoManager.CurrentStore) debugPrint("Added current store: " .. cargoManager.CurrentStore.Name.Value) end -- Second try: Get stores from current location if Game.GameSession.Campaign.Map and Game.GameSession.Campaign.Map.CurrentLocation then local currentLocation = Game.GameSession.Campaign.Map.CurrentLocation if currentLocation.Stores then for storeId, store in pairs(currentLocation.Stores) do local alreadyAdded = false for _, existingStore in ipairs(validStores) do if existingStore.Identifier.Value == storeId.Value then alreadyAdded = true break end end if not alreadyAdded then table.insert(validStores, store) debugPrint("Added store from location: " .. store.Name.Value) end end end end -- If we don't have any valid stores, create a dummy store for direct access if #validStores == 0 and #storesWithItems > 0 then debugPrint("No valid stores found, creating dummy store") -- Create a basic store-like object with minimal functionality local dummyStore = { Identifier = storesWithItems[1], Name = { Value = "Dummy Store" }, Stock = {} -- Empty stock, will use default maxQuantity } table.insert(validStores, dummyStore) end local totalItemsProcessed = 0 local totalItemsUpdated = 0 -- Process items from each store with items in the buy crate for _, storeId in ipairs(storesWithItems) do debugPrint("Processing items for store ID: " .. storeId.Value) -- Find the store object for this ID local storeToUse = nil for _, store in ipairs(validStores) do if store.Identifier and store.Identifier.Value == storeId.Value then storeToUse = store debugPrint("Found matching store object: " .. store.Name.Value) break end end -- DIRECT ACCESS: If no store object found, use the first available store for reference if not storeToUse and #validStores > 0 then storeToUse = validStores[1] debugPrint("Using " .. storeToUse.Name.Value .. " as reference for direct access") end -- Check if we can access items directly from the buy crate if cargoManager.ItemsInBuyCrate and cargoManager.ItemsInBuyCrate[storeId] then local items = cargoManager.ItemsInBuyCrate[storeId] debugPrint("Found " .. #items .. " items via direct access for " .. storeId.Value) if #items > 0 then -- Dump item info for debugging for i, item in ipairs(items) do debugPrint("Item " .. i .. ": " .. (item.ItemPrefab and item.ItemPrefab.Name.Value or "Unknown") .. ", Quantity: " .. (item.Quantity or "Unknown")) end if storeToUse then local itemsProcessed, itemsUpdated = processItems(cargoManager, storeToUse, items) totalItemsProcessed = totalItemsProcessed + itemsProcessed totalItemsUpdated = totalItemsUpdated + itemsUpdated if itemsProcessed > 0 then debugPrint("Successfully processed " .. itemsProcessed .. " items for store " .. storeId.Value) else debugPrint("WARNING: Found items but processed 0 for store " .. storeId.Value) end else debugPrint("ERROR: No store to use as reference, cannot process items") end else debugPrint("WARNING: Items array exists but is empty") end else debugPrint("WARNING: Cannot access items directly for store " .. storeId.Value) end end numberInputsFound = totalItemsProcessed itemsUpdated = totalItemsUpdated if totalItemsProcessed > 0 then debugPrint("Successfully processed " .. totalItemsProcessed .. " items across all stores") else debugPrint("Failed to process any items despite finding stores with items") end else -- Fallback to regular approach with current store local currentStore = cargoManager.CurrentStore if not currentStore then debugPrint("No current store found and no stores with items detected") return end debugPrint("Using current store: " .. currentStore.Name.Value .. " (ID: " .. currentStore.Identifier.Value .. ")") -- Get items in buy crate using the proper method local buyCrateItems = cargoManager:GetBuyCrateItems(currentStore) if not buyCrateItems then debugPrint("GetBuyCrateItems returned nil") return end if #buyCrateItems == 0 then debugPrint("Buy crate is empty - you need to add at least one of each item you want to purchase") return end debugPrint("Found " .. #buyCrateItems .. " items in buy crate") local itemsProcessed, itemsUpdated = processItems(cargoManager, currentStore, buyCrateItems) numberInputsFound = itemsProcessed itemsUpdated = itemsUpdated end end) -- Play sound pcall(function() Game.PlaySound("buttonclick") end) -- Notify user if numberInputsFound == 0 then showNotification("No items found in cart") elseif itemsUpdated > 0 then showNotification("Set " .. itemsUpdated .. " items to maximum quantity") else showNotification("All items already at maximum quantity") end end -- Helper function to process buy crate items function processItems(cargoManager, currentStore, buyCrateItems) local itemsUpdated = 0 local numberInputsFound = 0 debugPrint("Processing " .. #buyCrateItems .. " items for store: " .. (currentStore.Name and currentStore.Name.Value or "Unknown")) -- Update each item to maximum quantity for i, item in ipairs(buyCrateItems) do local maxQuantity = 100 -- Default - moved this declaration to the start of the loop if not item then debugPrint("ERROR: Item at index " .. i .. " is nil") goto continue end if not item.ItemPrefab then debugPrint("ERROR: Item has no ItemPrefab") goto continue end if not item.ItemPrefab.Name then debugPrint("ERROR: Item prefab has no Name") goto continue end -- Find the maximum quantity available if currentStore.Stock then local foundStock = false for _, stockItem in ipairs(currentStore.Stock) do if stockItem.ItemPrefab == item.ItemPrefab then foundStock = true -- Calculate max available local purchased = 0 pcall(function() purchased = cargoManager:GetPurchasedItemCount(currentStore, item.ItemPrefab) end) maxQuantity = stockItem.Quantity - purchased debugPrint("Item " .. i .. ": " .. item.ItemPrefab.Name.Value .. ", Max available: " .. maxQuantity .. ", Current quantity: " .. item.Quantity) break end end if not foundStock then debugPrint("No stock info found for " .. item.ItemPrefab.Name.Value .. ", using default max: 100") end else debugPrint("No stock info available for store, using default max: 100") end -- Update quantity if needed if maxQuantity > 0 and item.Quantity < maxQuantity then local oldQuantity = item.Quantity item.Quantity = maxQuantity debugPrint("Set " .. item.ItemPrefab.Name.Value .. " from " .. oldQuantity .. " to " .. maxQuantity) itemsUpdated = itemsUpdated + 1 else debugPrint("Not updating " .. item.ItemPrefab.Name.Value .. " (current: " .. item.Quantity .. ", max: " .. maxQuantity .. ")") end numberInputsFound = numberInputsFound + 1 ::continue:: end debugPrint("Processed " .. numberInputsFound .. " items, updated " .. itemsUpdated) return numberInputsFound, itemsUpdated end -- Simple key detection - when B is pressed, buy all items Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable) if PlayerInput.KeyHit(CONFIG.KEY_CODE) then buyAllItems() end end, Hook.HookMethodType.After) -- Hook into GUI creation for the store interface -- We'll use a different approach that doesn't rely on GUI.Components Hook.Add("gui.storeinterface.created", "addBuyAllButton", function(storeInterface) debugPrint("Store interface created, attempting to add button...") -- Don't create button if we already have one if createdButton then return end -- The Store interface was just created, now we can add our button pcall(function() -- Try to find the button container local confirmButton = storeInterface:FindChild("confirmbutton", true) if confirmButton then local buttonContainer = confirmButton.Parent -- If we found the container with buttons if buttonContainer then -- Create our button local buyAllButton = GUIButton( RectTransform(confirmButton.RectTransform.RelativeSize, buttonContainer.RectTransform), CONFIG.BUTTON_TEXT) buyAllButton.OnClicked = buyAllItems buyAllButton.ClickSound = "buttonclick" -- Position it appropriately between existing buttons local clearAllButton = nil for _, child in pairs(buttonContainer.Children) do if child.GetType and child:GetType().Name == "GUIButton" and child ~= confirmButton then clearAllButton = child break end end if clearAllButton then -- Position between confirm and clear all local midX = (confirmButton.RectTransform.RelativeOffset.X + clearAllButton.RectTransform.RelativeOffset.X) / 2 buyAllButton.RectTransform.RelativeOffset = Vector2(midX, confirmButton.RectTransform.RelativeOffset.Y) else -- Position next to confirm buyAllButton.RectTransform.RelativeOffset = Vector2( confirmButton.RectTransform.RelativeOffset.X - confirmButton.RectTransform.RelativeSize.X - 0.05, confirmButton.RectTransform.RelativeOffset.Y ) end debugPrint("Buy All button created successfully!") createdButton = true end end end) end) -- Show a small message to the user when the mod loads Timer.Wait(function() showNotification(MOD_NAME .. " loaded! Press V to buy all items at maximum quantity.") end, 2000)