From f7788581fd946e37aa4e052ba7d2557a4b12faaf Mon Sep 17 00:00:00 2001 From: BlackDog86 <122568778+BlackDog86@users.noreply.github.com> Date: Fri, 27 Dec 2024 10:16:41 +0000 Subject: [PATCH] Fix issues with stacking behaviour --- X2WOTCCommunityHighlander/Config/XComGame.ini | 24 +++++ .../Src/XComGame/Classes/CHHelpers.uc | 6 ++ .../Classes/XComGameState_HeadquartersXCom.uc | 90 +++++++++++++++++-- .../XComGame/Classes/XComGameState_Item.uc | 4 +- 4 files changed, 114 insertions(+), 10 deletions(-) diff --git a/X2WOTCCommunityHighlander/Config/XComGame.ini b/X2WOTCCommunityHighlander/Config/XComGame.ini index 8c32dbe5b..7887420eb 100644 --- a/X2WOTCCommunityHighlander/Config/XComGame.ini +++ b/X2WOTCCommunityHighlander/Config/XComGame.ini @@ -297,3 +297,27 @@ iMixedCharacterPoolChance = 50 ;;; Issue #1398 - Change to adjust the delay of the 'Squad member dead' voiceline after a unit is killed fSquadMemberDeadVoicelineDelay = 3.0f + +; Issue #1429 - Add items to this array to run the item's onAcquired function each time they are equipped +; (this prevents a bug where stackable items with fixed attachments would strip the attachments when equipped) ++OnEquipFix=TLE_AssaultRifle_CV ++OnEquipFix=TLE_SniperRifle_CV ++OnEquipFix=TLE_Shotgun_CV ++OnEquipFix=TLE_Cannon_CV ++OnEquipFix=TLE_Pistol_CV ++OnEquipFix=TLE_Sword_CV ++OnEquipFix=TLE_AssaultRifle_MG ++OnEquipFix=TLE_SniperRifle_MG ++OnEquipFix=TLE_Shotgun_MG ++OnEquipFix=TLE_Cannon_MG ++OnEquipFix=TLE_Pistol_MG ++OnEquipFix=TLE_Sword_MG ++OnEquipFix=TLE_AssaultRifle_BM ++OnEquipFix=TLE_SniperRifle_BM ++OnEquipFix=TLE_Shotgun_BM ++OnEquipFix=TLE_Cannon_BM ++OnEquipFix=TLE_Pistol_BM ++OnEquipFix=TLE_Sword_BM ++OnEquipFix=ChosenSniperRifle_XCOM ++OnEquipFix=ChosenRifle_XCOM ++OnEquipFix=ChosenShotgun_XCOM diff --git a/X2WOTCCommunityHighlander/Src/XComGame/Classes/CHHelpers.uc b/X2WOTCCommunityHighlander/Src/XComGame/Classes/CHHelpers.uc index f5ca4e042..fe24a80e8 100644 --- a/X2WOTCCommunityHighlander/Src/XComGame/Classes/CHHelpers.uc +++ b/X2WOTCCommunityHighlander/Src/XComGame/Classes/CHHelpers.uc @@ -267,6 +267,12 @@ var config bool bForce24hclockLeadingZero; // Variable for Issue #1398 - Number of seconds to wait after a unit is killed before playing the 'OnSquadMemberDead' voiceline var config float fSquadMemberDeadVoicelineDelay; +/// HL-Docs: ref:Bugfixes; issue:1429 +// When certain items with fixed attachments (e.g. TLE Weapons) are stacked in the inventory by mods, equipping such items +// on a soldier will strip the attachments. Adding items to the configurable array below will ensure the item's onAcquired +// function will be called when equipping the item on the soldier, ensuring the attachments are re-added. +var config array OnEquipFix; + // Start Issue #885 enum EHLDelegateReturn { diff --git a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComGameState_HeadquartersXCom.uc b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComGameState_HeadquartersXCom.uc index 32c7fb58e..b4a424838 100644 --- a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComGameState_HeadquartersXCom.uc +++ b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComGameState_HeadquartersXCom.uc @@ -4101,6 +4101,12 @@ function bool HasItemInInventoryOrLoadout(X2ItemTemplate ItemTemplate, optional function bool HasUnModifiedItem(XComGameState AddToGameState, X2ItemTemplate ItemTemplate, out XComGameState_Item ItemState, optional bool bLoot = false, optional XComGameState_Item CombatSimTest) { local int idx; + // Start Issue #1429 - New variables to improve stacking behaviour + local int idxAttach, idxStatBoost; + local bool isIdenticalToInventoryItem, hasIdenticalStatBoosts; + local array inventoryWeaponUpgrades; + local array selectedWeaponUpgrades; + // End Issue #1429 if(bLoot) { @@ -4134,25 +4140,80 @@ function bool HasUnModifiedItem(XComGameState AddToGameState, X2ItemTemplate Ite } else { + // Start Issue #1429 - Get the list of weapon upgrades from the itemsstate which is passed in + if(CombatSimTest != none) + { + selectedWeaponUpgrades = CombatSimTest.GetMyWeaponUpgradeTemplateNames(); + } for(idx = 0; idx < Inventory.Length; idx++) { ItemState = XComGameState_Item(`XCOMHISTORY.GetGameStateForObjectID(Inventory[idx].ObjectID)); + inventoryWeaponUpgrades = ItemState.GetMyWeaponUpgradeTemplateNames(); + isIdenticalToInventoryItem = false; + hasIdenticalStatBoosts = false; if(ItemState == none) { ItemState = XComGameState_Item(AddToGameState.GetGameStateForObjectID(Inventory[idx].ObjectID)); } + // Issue #1429 - If the item we're putting back into the inventory matches something which is already there, + // has the same array of attachments and the same appearence, we can allow the items to stack (i.e. return true) if(ItemState != none) { - if (ItemState.GetMyTemplateName() == ItemTemplate.DataName && (ItemState.Quantity > 0 || ItemState.GetMyTemplate().ItemCat == 'resource') && !ItemState.HasBeenModified()) + if (ItemState.GetMyTemplateName() == ItemTemplate.DataName) { - if(ItemState.GetMyTemplate().ItemCat == 'combatsim') + If (selectedWeaponUpgrades.Length == 0) { - if(ItemState.StatBoosts.Length > 0 && CombatSimTest.StatBoosts.Length > 0 && ItemState.StatBoosts[0].Boost == CombatSimTest.StatBoosts[0].Boost && ItemState.StatBoosts[0].StatType == CombatSimTest.StatBoosts[0].StatType) + isIdenticalToInventoryItem = true; + } + else if(inventoryWeaponUpgrades.Length != 0) + { + isIdenticalToInventoryItem = true; + for(idxAttach = 0; idxAttach < inventoryWeaponUpgrades.Length; idxAttach++) + { + If(inventoryWeaponUpgrades[idxAttach] != selectedWeaponUpgrades[idxAttach]) + { + isIdenticalToInventoryItem = false; + break; + } + } + // Issue #1429 - Test to see if the item we're planning to put back in the inventory has the same apperance + // as an item which is already there + if(CombatSimTest.WeaponAppearance != ItemState.WeaponAppearance) + { + isIdenticalToInventoryItem = false; + } + } + } + // Issue #1429 - Removed check for !HasBeenModified as it's now handled by isIdenticalToInventoryItem + if (isIdenticalToInventoryItem && (ItemState.Quantity > 0 || ItemState.GetMyTemplate().ItemCat == 'resource')) + // End Issue #1429 + { + if(ItemState.GetMyTemplate().ItemCat == 'combatsim') + { + /// HL-Docs: ref:Bugfixes; issue:1352 + // Mod-added PCS items which did not provide exactly 1 stat boost were not being properly checked by HasUnModifiedItem + // New checks added here mean that PCS items with no stat boosts, or more than one stat boost, are properly checked + // for stacking behaviour + // Begin Issue #1352 + hasIdenticalStatBoosts = true; + if(CombatSimTest.StatBoosts.Length != 0) + { + for(idxStatBoost = 0; idxStatBoost < ItemState.StatBoosts.Length; idxStatBoost++) + { + If(ItemState.StatBoosts[idxStatBoost].Boost != CombatSimTest.StatBoosts[idxStatBoost].Boost || ItemState.StatBoosts[idxStatBoost].StatType != CombatSimTest.StatBoosts[idxStatBoost].StatType) + { + hasIdenticalStatBoosts = false; + break; + } + } + } + if(hasIdenticalStatBoosts) { return true; } + // End Issue #1352 } else { @@ -4162,7 +4223,7 @@ function bool HasUnModifiedItem(XComGameState AddToGameState, X2ItemTemplate Ite } } } - + return false; } @@ -4176,7 +4237,9 @@ function bool PutItemInInventory(XComGameState AddToGameState, XComGameState_Ite ItemTemplate = ItemState.GetMyTemplate(); - if( ItemState.HasBeenModified() || ItemTemplate.bAlwaysUnique ) + // Issue #1429 - HasBeenModifiedCheck moved later in the function to prevent short-circuiting new stacking logic + // for modified items which have the same attachments (this is handled by HasUnModifiedItem) + if( ItemTemplate.bAlwaysUnique ) { HQModified = true; @@ -4191,12 +4254,12 @@ function bool PutItemInInventory(XComGameState AddToGameState, XComGameState_Ite } else { - if(!ItemState.GetMyTemplate().bInfiniteItem) + if(!ItemState.GetMyTemplate().bInfiniteItem || ItemState.HasBeenModified()) { if( HasUnModifiedItem(AddToGameState, ItemTemplate, InventoryItemState, bLoot, ItemState) ) { HQModified = false; - + if(InventoryItemState.ObjectID != ItemState.ObjectID) { NewInventoryItemState = XComGameState_Item(AddToGameState.ModifyStateObject(class'XComGameState_Item', InventoryItemState.ObjectID)); @@ -4363,9 +4426,18 @@ function bool GetItemFromInventory(XComGameState AddToGameState, StateObjectRefe if(InventoryItemState.Quantity > 1) { HQModified = false; - InventoryItemState = XComGameState_Item(AddToGameState.ModifyStateObject(class'XComGameState_Item', InventoryItemState.ObjectID)); InventoryItemState.Quantity--; - ItemState = XComGameState_Item(AddToGameState.CreateNewStateObject(class'XComGameState_Item', InventoryItemState.GetMyTemplate())); + // Begin Issue #1429 - If the item being fetched from inventory is one with attachments added via onAcquiredFn + // Use CreateInstanceFromTemplate instead of CreateNewStateObject + If(class'CHHelpers'.default.OnEquipFix.Find(ItemState.GetMyTemplateName()) != INDEX_NONE) + { + ItemState = InventoryItemState.GetMyTemplate().CreateInstanceFromTemplate(AddToGameState); + } + Else + { + ItemState = XComGameState_Item(AddToGameState.CreateNewStateObject(class'XComGameState_Item', InventoryItemState.GetMyTemplate())); + } + // End Issue #1429 ItemState.StatBoosts = InventoryItemState.StatBoosts; // Make sure the stat boosts are the same. Used for PCS. } else diff --git a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComGameState_Item.uc b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComGameState_Item.uc index cb5191a7f..2772acf30 100644 --- a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComGameState_Item.uc +++ b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComGameState_Item.uc @@ -795,7 +795,9 @@ simulated function bool HasBeenModified() WeaponTemplate = X2WeaponTemplate( m_ItemTemplate ); // Single line for Issues #93 and #306 - if ((WeaponTemplate != none) && (GetNumUpgradeSlots() > 0) && (GetMyWeaponUpgradeCount() > 0)) + // Issue #1429 - Remove the check for GetNumUpgradeSlots - this causes an incorrect response for weapons with + // fixed attachments and no slots on the template (e.g. if the attachments are added by an onAcquired function) + if ((WeaponTemplate != none) /* && (GetNumUpgradeSlots() > 0)*/ && (GetMyWeaponUpgradeCount() > 0)) return true; return false;