55 lines
2.1 KiB
C
55 lines
2.1 KiB
C
// Delivered initial-roster slot identities only. No native actor/position access.
|
|
// One instance belongs to one immutable formation SourceId in the watch roster.
|
|
class ERR_HQDeliveredCasualties
|
|
{
|
|
protected int m_Strength;
|
|
protected ref array<int> m_StatusSlots = {};
|
|
protected ref array<int> m_KnownSlots = {};
|
|
bool Bind(int strength)
|
|
{
|
|
if (strength < 1 || strength > 32) return false;
|
|
if (m_Strength != 0) return m_Strength == strength;
|
|
m_Strength = strength;
|
|
return true;
|
|
}
|
|
int Count() { return m_KnownSlots.Count(); }
|
|
int StatusCount() { return m_StatusSlots.Count(); }
|
|
bool Closed() { return m_Strength > 0 && Count() == m_Strength; }
|
|
bool Known(int slot) { return m_KnownSlots.Contains(slot); }
|
|
protected bool ValidSlot(int slot) { return m_Strength > 0 && slot >= 0 && slot < m_Strength; }
|
|
bool AcceptBody(int slot)
|
|
{
|
|
if (!ValidSlot(slot)) return false;
|
|
if (!m_KnownSlots.Contains(slot)) m_KnownSlots.Insert(slot);
|
|
return true; // A repeated valid report is idempotent, including a status-known casualty.
|
|
}
|
|
bool AcceptStatus(array<int> slots, int reportedLosses, int reportedLiving)
|
|
{
|
|
if (m_Strength <= 0 || !slots || reportedLosses < 0 || reportedLosses > m_Strength
|
|
|| reportedLiving < 0 || reportedLiving > m_Strength - reportedLosses || slots.Count() != reportedLosses)
|
|
return false;
|
|
array<int> unique = {};
|
|
foreach (int slot : slots)
|
|
{
|
|
if (!ValidSlot(slot) || unique.Contains(slot)) return false;
|
|
unique.Insert(slot);
|
|
}
|
|
// A later local cumulative status cannot resurrect a previously status-confirmed member.
|
|
// Body-only knowledge is intentionally not required in an uninformed caller's status.
|
|
foreach (int previous : m_StatusSlots) if (!unique.Contains(previous)) return false;
|
|
m_StatusSlots.Clear();
|
|
foreach (int slot : unique)
|
|
{
|
|
m_StatusSlots.Insert(slot);
|
|
if (!m_KnownSlots.Contains(slot)) m_KnownSlots.Insert(slot);
|
|
}
|
|
return true;
|
|
}
|
|
int LivingUpperBound(int lastReportedLiving)
|
|
{
|
|
if (Closed()) return 0;
|
|
if (lastReportedLiving < 0 || lastReportedLiving > m_Strength) return -1;
|
|
return Math.Min(lastReportedLiving, m_Strength - Count());
|
|
}
|
|
}
|