Re: PCS Dissapearing
Posted: Fri Feb 03, 2017 1:56 am
So my best guess at this point is that this is some sort of weird serialization/deserialization error. All of the reports indicate that the problem occurs when a save/load cycle is run, and that the PCS is no longer present after the load.
So here's some background on how the PCS slot works...
The PCS slot is handled pretty much like any other inventory slot (e.g. armor, primary weapon, secondary weapons, utility). However, it has its own slot type. The number of such inventory slots is also handled in a somewhat unusual way. Instead of being tied to equipment, there is a character stat which is used to determine the number of such slots available. If you look at any class (including the LW2 classes), you'll see that the squaddie rank always adds :
That is, the first rank always grants +1 to this eStat_CombatSims.
Making the situation stranger yet, the XCGS_Unit GetPCSRanks function has the following :
That is, it always checks only the base XCOM 2 Ranger class to determine when PCS availability should occur.
Even though in theory the stat could go above 1, in practice the code and the UI don't support multiple PCSs (we considered this, but it would have been a fair amount of work so we pushed more in other areas). Instead, this data is reduced to a boolean using the function :
This reduces all of the previous stuff to a simple yes/no as to whether the soldier can equip a PCS. And since it's basically hard-coded to only check one class, this means that all soldiers get ability to equip one PCS at squaddie.
This rank requirement gets combined with other requirements in the UIUtilities_Strategies class function
This static helper function determines whether or not a unit can equip a PCS. It checks several things :
1) How many PCS are currently equipped?:
2) How many PCS slots does the unit have to equip?:
3) Does the unit have a free PCS slot to equip a PCS?:
4) Are there any PCS in the XCOM inventory to be equipped?:
5) Has the unit reached sufficient rank to equip a PCS?: (note this is redundant with 3)
6) Has the player built a GTS facility?:
7) Are there even any available PCS slots to equip to?: (again, this is redundant info)
The results of this GetPCSAvailability is used in two places : in the Armory_MainMenu to determine whether the "Equip PCS" button should be enabled/disabled, and in UIArmory_Implants to determine whether a soldier can be cycled to when in that menu.
---------------------------------------------------------------------------------
The application/removal is almost entirely initiated within the class UIInventory_Implants.
This class has functions RemoveImplant and InstallImplant. Both of these functions appear (from code-read) to create and submit a changestate to the history (which would be the most other most likely case of items disappearing). In particular if a PCS is "disappearing", it would have to be applied to the unit, but not persist in the unit inventory through a save/load cycle. The addition of a new PCS to a unit inventory inside of UIInventory_Implants.InstallImplant is handled via :
This same AddItemToInventory function is used for every other type of item equipping -- armor, primary/secondary weapons, utility, grenade slot, heavy weapons and so on.
A unit's inventory is pretty much just an array of references to XComGameState_Item objects in the history. The class variable for unit inventory is :
This is protected write, so no class outside of XComGameState_Unit can change this list, BUT if the item is destroyed then the reference in the array will be no longer retrievable from the history, thus acting as if the item had been removed. The primarily line of code by which items are added to inventory is simply :
Since the basic inventory management by which PCS items are stored is common across all items equipped to a unit, it seems unlikely that this could be a problem with that, since there are no similar reports of randomly disappearing gear that I've seen. At the same time, the serialization/deserialization code seems an unlikely candidate. If it's the former, then it's possible to fix via mod. If it's the latter, that is all handled deep in native code and would require a fix from Firaxis.
So here's some background on how the PCS slot works...
The PCS slot is handled pretty much like any other inventory slot (e.g. armor, primary weapon, secondary weapons, utility). However, it has its own slot type
Code: Select all
eInvSlot_CombatSim
Code: Select all
StatType=eStat_CombatSims,StatAmount=1
Making the situation stranger yet, the XCGS_Unit GetPCSRanks function has the following :
Code: Select all
// Does not matter which class we grab, all should have same combat sim stats
SoldierClassTemplate = class'X2SoldierClassTemplateManager'.static.GetSoldierClassTemplateManager().FindSoldierClassTemplate('Ranger');
Even though in theory the stat could go above 1, in practice the code and the UI don't support multiple PCSs (we considered this, but it would have been a fair amount of work so we pushed more in other areas). Instead, this data is reduced to a boolean using the function :
Code: Select all
function bool IsSufficientRankToEquipPCS()
This rank requirement gets combined with other requirements in the UIUtilities_Strategies class function
Code: Select all
simulated static function GetPCSAvailability(XComGameState_Unit Unit, out TPCSAvailabilityData PCSAvailabilityData)
1) How many PCS are currently equipped?:
Code: Select all
EquippedImplants = Unit.GetAllItemsInSlot(eInvSlot_CombatSim);
Code: Select all
AvailableSlots = Unit.GetCurrentStat(eStat_CombatSims);
Code: Select all
PCSAvailabilityData.bHasCombatSimsSlotsAvailable = ( AvailableSlots > EquippedImplants.Length );
Code: Select all
PCSAvailabilityData.bHasNeurochipImplantsInInventory = XComHQ.HasCombatSimsInInventory();
Code: Select all
PCSAvailabilityData.bHasAchievedCombatSimsRank = Unit.IsSufficientRankToEquipPCS();
Code: Select all
PCSAvailabilityData.bHasGTS = XComHQ.HasFacilityByName('OfficerTrainingSchool');
Code: Select all
PCSAvailabilityData.bCanEquipCombatSims = (AvailableSlots > 0);
---------------------------------------------------------------------------------
The application/removal is almost entirely initiated within the class UIInventory_Implants.
This class has functions RemoveImplant and InstallImplant. Both of these functions appear (from code-read) to create and submit a changestate to the history (which would be the most other most likely case of items disappearing). In particular if a PCS is "disappearing", it would have to be applied to the unit, but not persist in the unit inventory through a save/load cycle. The addition of a new PCS to a unit inventory inside of UIInventory_Implants.InstallImplant is handled via :
Code: Select all
UpdatedUnit.AddItemToInventory(UpdatedImplant, eInvSlot_CombatSim, UpdatedState);
A unit's inventory is pretty much just an array of references to XComGameState_Item objects in the history. The class variable for unit inventory is :
Code: Select all
var() protectedwrite array<StateObjectReference> InventoryItems; //Items this units is carrying
Code: Select all
InventoryItems.AddItem(Item.GetReference());