From 2cc74d7b122ee32bdf55cc1c119823fcaf74c034 Mon Sep 17 00:00:00 2001 From: David Markowitz Date: Mon, 6 Oct 2025 01:50:03 -0700 Subject: [PATCH] feat: InventoryComponent debug info --- dGame/dComponents/InventoryComponent.cpp | 101 ++++++++++++++++++++++- dGame/dComponents/InventoryComponent.h | 2 + 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index 0b45a11e..5361eb6b 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -39,10 +39,13 @@ #include "CDObjectSkillsTable.h" #include "CDSkillBehaviorTable.h" #include "StringifiedEnum.h" +#include "Amf3.h" #include InventoryComponent::InventoryComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) { + using namespace GameMessages; + RegisterMsg(this, &InventoryComponent::OnGetObjectReportInfo); this->m_Dirty = true; this->m_Equipped = {}; this->m_Pushed = {}; @@ -626,7 +629,7 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument& document) { for (const auto& pair : this->m_Inventories) { auto* inventory = pair.second; - static const auto EXCLUDED_INVENTORIES = {VENDOR_BUYBACK, MODELS_IN_BBB, ITEM_SETS}; + static const auto EXCLUDED_INVENTORIES = { VENDOR_BUYBACK, MODELS_IN_BBB, ITEM_SETS }; if (std::ranges::find(EXCLUDED_INVENTORIES, inventory->GetType()) != EXCLUDED_INVENTORIES.end()) { continue; } @@ -1793,3 +1796,99 @@ void InventoryComponent::RegenerateItemIDs() { inventory->RegenerateItemIDs(); } } + +std::string DebugInvToString(const eInventoryType inv, bool verbose) { + switch (inv) { + case ITEMS: + return "Backpack"; + case VAULT_ITEMS: + return "Bank"; + case BRICKS: + return verbose ? "Bricks" : "Bricks (contents only shown in high-detail report)"; + case MODELS_IN_BBB: + return "Models in BBB"; + case TEMP_ITEMS: + return "Temp Equip"; + case MODELS: + return verbose ? "Model" : "Model (contents only shown in high-detail report)"; + case TEMP_MODELS: + return "Module"; + case BEHAVIORS: + return "B3 Behavior"; + case PROPERTY_DEEDS: + return "Property"; + case BRICKS_IN_BBB: + return "Brick In BBB"; + case VENDOR: + return "Vendor"; + case VENDOR_BUYBACK: + return "BuyBack"; + case QUEST: + return "Quest"; + case DONATION: + return "Donation"; + case VAULT_MODELS: + return "Bank Model"; + case ITEM_SETS: + return "Bank Behavior"; + case INVALID: + return "Invalid"; + case ALL: + return "All"; + } + + return ""; +} + +bool InventoryComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) { + auto& report = static_cast(msg); + auto& cmpt = report.info->PushDebug("Inventory"); + cmpt.PushDebug("Component ID") = GetComponentID(); + uint32_t numItems = 0; + for (auto* inventory : m_Inventories | std::views::values) numItems += inventory->GetItems().size(); + cmpt.PushDebug("Inventory Item Count") = numItems; + + auto& itemsInBags = cmpt.PushDebug("Items in bags"); + for (const auto& [id, inventoryMut] : m_Inventories) { + if (!inventoryMut) continue; + const auto* const inventory = inventoryMut; + auto& curInv = itemsInBags.PushDebug(DebugInvToString(id, report.bVerbose) + " - " + std::to_string(id)); + for (uint32_t i = 0; i < inventory->GetSize(); i++) { + const auto* const item = inventory->FindItemBySlot(i); + if (!item) continue; + + std::stringstream ss; + ss << "%[Objects_" << item->GetLot() << "_name] Slot " << item->GetSlot(); + auto& slot = curInv.PushDebug(ss.str()); + slot.PushDebug("Object ID") = std::to_string(item->GetId()); + slot.PushDebug("LOT") = item->GetLot(); + if (item->GetSubKey() != LWOOBJID_EMPTY) slot.PushDebug("Subkey") = std::to_string(item->GetSubKey()); + slot.PushDebug("Count") = item->GetCount(); + slot.PushDebug("Slot") = item->GetSlot(); + slot.PushDebug("Bind on pickup") = item->GetInfo().isBOP; + slot.PushDebug("Bind on equip") = item->GetInfo().isBOE; + slot.PushDebug("Is currently bound") = item->GetBound(); + auto& extra = slot.PushDebug("Extra Info"); + for (const auto* const setting : item->GetConfig()) { + if (setting) extra.PushDebug(GeneralUtils::UTF16ToWTF8(setting->GetKey())) = setting->GetValueAsString(); + } + } + } + + auto& equipped = cmpt.PushDebug("Equipped Items"); + for (const auto& [location, info] : GetEquippedItems()) { + std::stringstream ss; + ss << "%[Objects_" << info.lot << "_name]"; + auto& equipSlot = equipped.PushDebug(ss.str()); + equipSlot.PushDebug("Location") = location; + equipSlot.PushDebug("Object ID") = std::to_string(info.id); + equipSlot.PushDebug("Slot") = info.slot; + equipSlot.PushDebug("Count") = info.count; + auto& extra = equipSlot.PushDebug("Extra Info"); + for (const auto* const setting : info.config) { + if (setting) extra.PushDebug(GeneralUtils::UTF16ToWTF8(setting->GetKey())) = setting->GetValueAsString(); + } + } + + return true; +} diff --git a/dGame/dComponents/InventoryComponent.h b/dGame/dComponents/InventoryComponent.h index 88d9da2c..6e0fdba7 100644 --- a/dGame/dComponents/InventoryComponent.h +++ b/dGame/dComponents/InventoryComponent.h @@ -410,6 +410,8 @@ public: // Used to migrate a character version, no need to call outside of that context void RegenerateItemIDs(); + bool OnGetObjectReportInfo(GameMessages::GameMsg& msg); + ~InventoryComponent() override; private: