XCGS_Analytics::AddTacticalGameEnd uses XGPlayer::GetOriginalUnits to populate the array of units which are valid for the "UNITS_LOST" analytics object, which counts the number of XCom units killed in a mission / throughout the game.
Battle.GetHumanPlayer( ).GetOriginalUnits( MissionUnits, true );
bFlawless = true;
foreach MissionUnits( Unit )
{
UnitRef.ObjectID = Unit.ObjectID;
if (Unit.kAppearance.bGhostPawn)
continue;
AnalyticsObject.AddValue( "ACC_UNIT_MISSIONS", 1, UnitRef );
if (Unit.IsDead( ))
{
bFlawless = false;
AnalyticsObject.AddValue( "UNITS_LOST", 1 );
}
else if (Unit.IsBleedingOut() && !BattleData.AllTacticalObjectivesCompleted())
{
bFlawless = false;
AnalyticsObject.AddValue( "UNITS_LOST", 1 );
}
if (Unit.WasInjuredOnMission( ))
{
bFlawless = false;
}
}
This function is not particulaly robust in what it counts & allows through certain types of non-XCom units (Psi-zombies, additional advent / resistance soldiers added by the resistance cards and likely some other edge-cases).
// Checks for mind control and hands back all units that originally belonged to this player.
// Hands back the CURRENT state of the unit (e.g. mind controlled units will reflect that they are on another team)
simulated function GetOriginalUnits(out array<XComGameState_Unit> Units, bool bSkipTurrets=false, bool bSkipCosmetic=true, bool bSkipMindControlledUnits=false)
{
local XComGameStateHistory History;
local XComGameState_Unit CurrentUnitState, OldUnitState;
local XComGameState_Effect MindControlEffect, OriginalEffect;
local array<StateObjectReference> UnitRefs;
History = `XCOMHISTORY;
foreach History.IterateByClassType(class'XComGameState_Unit', CurrentUnitState, eReturnType_Reference)
{
if (CurrentUnitState.GetMyTemplate().bIsCosmetic && bSkipCosmetic)
continue;
if (CurrentUnitState.GetMyTemplateName() == 'MimicBeacon')
continue;
if (CurrentUnitState.IsTurret() && bSkipTurrets)
continue;
MindControlEffect = CurrentUnitState.GetUnitAffectedByEffectState(class'X2Effect_MindControl'.default.EffectName);
if (MindControlEffect != none && bSkipMindControlledUnits)
continue;
if (MindControlEffect != none)
{
OriginalEffect = XComGameState_Effect(History.GetOriginalGameStateRevision(MindControlEffect.ObjectID));
OldUnitState = XComGameState_Unit(History.GetGameStateForObjectID(CurrentUnitState.ObjectID,,OriginalEffect.GetParentGameState().HistoryIndex - 1));
if(OldUnitState.ControllingPlayer.ObjectID == ObjectID && UnitRefs.Find('ObjectID', CurrentUnitState.ObjectID) == INDEX_NONE)
{
Units.AddItem(CurrentUnitState);
UnitRefs.AddItem(CurrentUnitState.GetReference());
}
}
else if(CurrentUnitState.ControllingPlayer.ObjectID == ObjectID && UnitRefs.Find('ObjectID', CurrentUnitState.ObjectID) == INDEX_NONE)
{
Units.AddItem(CurrentUnitState);
UnitRefs.AddItem(CurrentUnitState.GetReference());
}
}
}
Additional guards should be added, either to the analytics object, or to GetOriginalUnits (probably preferred in the analytics object) so that the UNITS_LOST statistic accurately tracks XCom soldiers, friendly VIPs, soldiers which have been rescued by XCom but not psi-zombies and additional units awarded through resistance cards.
XCGS_Analytics::AddTacticalGameEnd uses XGPlayer::GetOriginalUnits to populate the array of units which are valid for the "UNITS_LOST" analytics object, which counts the number of XCom units killed in a mission / throughout the game.
This function is not particulaly robust in what it counts & allows through certain types of non-XCom units (Psi-zombies, additional advent / resistance soldiers added by the resistance cards and likely some other edge-cases).
Additional guards should be added, either to the analytics object, or to GetOriginalUnits (probably preferred in the analytics object) so that the UNITS_LOST statistic accurately tracks XCom soldiers, friendly VIPs, soldiers which have been rescued by XCom but not psi-zombies and additional units awarded through resistance cards.