Reconcile radio-delivered body and status casualties by original roster identity
This commit is contained in:
@@ -14,6 +14,30 @@ class ERR_HQStatusSampler
|
||||
protected ref array<bool> m_Released = {};
|
||||
protected ref array<AIAgent> m_Agents = {};
|
||||
bool Bound() { return m_Bound; }
|
||||
string InitialSourceId() { return m_SourceId; }
|
||||
int InitialStrength() { return m_Strength; }
|
||||
bool OwnsRoster(SCR_AIGroup group) { return m_Bound && group && group == m_Group; }
|
||||
IEntity InitialMember(int slot)
|
||||
{
|
||||
if (!m_Bound || slot < 0 || slot >= m_Members.Count()) return null;
|
||||
return m_Members[slot];
|
||||
}
|
||||
// Attribution retains the original slot even when native death detaches its agent.
|
||||
// A known transfer/player conversion permanently releases that slot, never rebinds it.
|
||||
bool CanAttribute(int slot, IEntity actor)
|
||||
{
|
||||
if (!Replication.IsServer() || !actor || InitialMember(slot) != actor || m_Released[slot]) return false;
|
||||
if (ERR_Actors.Player(actor) || SCR_FactionManager.SGetFaction(actor) != m_Faction)
|
||||
{ m_Released[slot] = true; return false; }
|
||||
DamageManagerComponent damage = DamageManagerComponent.Cast(actor.FindComponent(DamageManagerComponent));
|
||||
if (!damage) return false;
|
||||
SCR_AIGroup actorGroup = ERR_Actors.Group(actor);
|
||||
// A retained foreign group proves transfer even if death preceded this tick.
|
||||
// A null group on a destroyed actor remains normal native corpse detachment.
|
||||
if ((actorGroup && actorGroup != m_Group) || (!damage.IsDestroyed() && actorGroup != m_Group))
|
||||
{ m_Released[slot] = true; return false; }
|
||||
return true;
|
||||
}
|
||||
protected bool Eligible()
|
||||
{
|
||||
return Replication.IsServer() && m_Bound && m_Group && m_Faction
|
||||
@@ -59,10 +83,12 @@ class ERR_HQStatusSampler
|
||||
{ m_Released[i] = true; continue; }
|
||||
DamageManagerComponent damage = DamageManagerComponent.Cast(actor.FindComponent(DamageManagerComponent));
|
||||
if (!damage) continue;
|
||||
SCR_AIGroup actorGroup = ERR_Actors.Group(actor);
|
||||
if (actorGroup && actorGroup != m_Group) { m_Released[i] = true; continue; }
|
||||
if (damage.IsDestroyed()) { m_Dead[i] = true; m_Deaths++; continue; }
|
||||
// A living member who left this group is no longer ours to account for.
|
||||
// Native death may detach a corpse, so group identity is checked after death.
|
||||
if (ERR_Actors.Group(actor) != m_Group) m_Released[i] = true;
|
||||
// A living detached member is no longer ours. A destroyed detached actor
|
||||
// was handled above without mistaking native corpse cleanup for transfer.
|
||||
if (actorGroup != m_Group) m_Released[i] = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -79,6 +105,8 @@ class ERR_HQStatusSampler
|
||||
ERR_HQStatusReport report = new ERR_HQStatusReport();
|
||||
report.SourceId = m_SourceId; report.MessageId = messageId; report.Position = position;
|
||||
report.Strength = m_Strength; report.ConfirmedLosses = m_Deaths; report.ObservedAt = now;
|
||||
for (int slot = 0; slot < m_Dead.Count(); slot++)
|
||||
if (m_Dead[slot]) report.DeathSlots.Insert(slot);
|
||||
for (int i = 0; i < m_Members.Count(); i++)
|
||||
{
|
||||
if (m_Dead[i] || m_Released[i]) continue;
|
||||
|
||||
Reference in New Issue
Block a user