From 7be7b37b8d2f98eeacf33b538694ea2568c99857 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Sep 2025 21:10:50 +0000 Subject: [PATCH] Fix skill slot assignment to use equipLocation instead of itemType - Add FindBehaviorSlotByEquipLocation method to map equipLocation strings to BehaviorSlot enum - Update AddItemSkills and RemoveItemSkills to use equipLocation instead of itemType - This fixes issue where items with same skill but different equipLocations would conflict - Add unit tests to verify the new behavior - Based on issue #1339: Server doesn't allow same skill in multiple slots Co-authored-by: aronwk-aaron <26027722+aronwk-aaron@users.noreply.github.com> --- dGame/dComponents/InventoryComponent.cpp | 18 ++++++++-- dGame/dComponents/InventoryComponent.h | 7 ++++ .../dComponentsTests/CMakeLists.txt | 1 + .../InventoryComponentTests.cpp | 33 +++++++++++++++++++ 4 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 tests/dGameTests/dComponentsTests/InventoryComponentTests.cpp diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index 4cc0a3de..aaa815a3 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -1168,7 +1168,7 @@ LOT InventoryComponent::GetConsumable() const { void InventoryComponent::AddItemSkills(const LOT lot) { const auto info = Inventory::FindItemComponent(lot); - const auto slot = FindBehaviorSlot(static_cast(info.itemType)); + const auto slot = FindBehaviorSlotByEquipLocation(info.equipLocation); if (slot == BehaviorSlot::Invalid) { return; @@ -1203,7 +1203,7 @@ void InventoryComponent::FixInvisibleItems() { void InventoryComponent::RemoveItemSkills(const LOT lot) { const auto info = Inventory::FindItemComponent(lot); - const auto slot = FindBehaviorSlot(static_cast(info.itemType)); + const auto slot = FindBehaviorSlotByEquipLocation(info.equipLocation); if (slot == BehaviorSlot::Invalid) { return; @@ -1332,6 +1332,20 @@ BehaviorSlot InventoryComponent::FindBehaviorSlot(const eItemType type) { } } +BehaviorSlot InventoryComponent::FindBehaviorSlotByEquipLocation(const std::string& equipLocation) { + if (equipLocation == "special_r") { + return BehaviorSlot::Primary; + } else if (equipLocation == "hair") { + return BehaviorSlot::Head; + } else if (equipLocation == "special_l") { + return BehaviorSlot::Offhand; + } else if (equipLocation == "clavicle") { + return BehaviorSlot::Neck; + } else { + return BehaviorSlot::Invalid; + } +} + bool InventoryComponent::IsTransferInventory(eInventoryType type, bool includeVault) { return type == VENDOR_BUYBACK || (includeVault && (type == VAULT_ITEMS || type == VAULT_MODELS)) || type == TEMP_ITEMS || type == TEMP_MODELS || type == MODELS_IN_BBB; } diff --git a/dGame/dComponents/InventoryComponent.h b/dGame/dComponents/InventoryComponent.h index 395dd5d6..5121f9a4 100644 --- a/dGame/dComponents/InventoryComponent.h +++ b/dGame/dComponents/InventoryComponent.h @@ -368,6 +368,13 @@ public: */ static BehaviorSlot FindBehaviorSlot(eItemType type); + /** + * Returns the behavior slot for the given equipment location + * @param equipLocation the equipment location to find the behavior slot for + * @return the behavior slot for the given equipment location + */ + static BehaviorSlot FindBehaviorSlotByEquipLocation(const std::string& equipLocation); + /** * Checks if the inventory type is a temp inventory * @param type the inventory type to check diff --git a/tests/dGameTests/dComponentsTests/CMakeLists.txt b/tests/dGameTests/dComponentsTests/CMakeLists.txt index f73f1214..b0eecdf9 100644 --- a/tests/dGameTests/dComponentsTests/CMakeLists.txt +++ b/tests/dGameTests/dComponentsTests/CMakeLists.txt @@ -1,5 +1,6 @@ set(DCOMPONENTS_TESTS "DestroyableComponentTests.cpp" + "InventoryComponentTests.cpp" "PetComponentTests.cpp" "SimplePhysicsComponentTests.cpp" "SavingTests.cpp" diff --git a/tests/dGameTests/dComponentsTests/InventoryComponentTests.cpp b/tests/dGameTests/dComponentsTests/InventoryComponentTests.cpp new file mode 100644 index 00000000..e34d0f07 --- /dev/null +++ b/tests/dGameTests/dComponentsTests/InventoryComponentTests.cpp @@ -0,0 +1,33 @@ +#include "GameDependencies.h" +#include + +#include "InventoryComponent.h" +#include "BehaviorSlot.h" + +class InventoryComponentTest : public GameDependenciesTest { +protected: + void SetUp() override { + SetUpDependencies(); + } + + void TearDown() override { + TearDownDependencies(); + } +}; + +/** + * Test that FindBehaviorSlotByEquipLocation correctly maps equipLocation strings to BehaviorSlot enum values + */ +TEST_F(InventoryComponentTest, FindBehaviorSlotByEquipLocationTest) { + // Test the mappings from the issue comments + EXPECT_EQ(InventoryComponent::FindBehaviorSlotByEquipLocation("special_r"), BehaviorSlot::Primary); + EXPECT_EQ(InventoryComponent::FindBehaviorSlotByEquipLocation("hair"), BehaviorSlot::Head); + EXPECT_EQ(InventoryComponent::FindBehaviorSlotByEquipLocation("special_l"), BehaviorSlot::Offhand); + EXPECT_EQ(InventoryComponent::FindBehaviorSlotByEquipLocation("clavicle"), BehaviorSlot::Neck); + + // Test that unknown equipLocations return Invalid + EXPECT_EQ(InventoryComponent::FindBehaviorSlotByEquipLocation("unknown"), BehaviorSlot::Invalid); + EXPECT_EQ(InventoryComponent::FindBehaviorSlotByEquipLocation(""), BehaviorSlot::Invalid); + EXPECT_EQ(InventoryComponent::FindBehaviorSlotByEquipLocation("root"), BehaviorSlot::Invalid); + EXPECT_EQ(InventoryComponent::FindBehaviorSlotByEquipLocation("leftHand"), BehaviorSlot::Invalid); +} \ No newline at end of file