Integrate radio-delivered convoy cover and conservative squad ammunition reports
This commit is contained in:
@@ -100,6 +100,7 @@ class ERR_NativeHQBodyProbe
|
||||
protected ref ERR_HQReport m_Report;
|
||||
protected ref ERR_HQRoute m_Route;
|
||||
protected ref ERR_HQStatusReport m_Status;
|
||||
protected ref ERR_HQAmmoSnapshot m_AmmoAtQueue;
|
||||
protected ref ERR_HQRoute m_StatusRoute;
|
||||
protected float m_Deadline;
|
||||
protected float m_StableUntil;
|
||||
@@ -129,6 +130,77 @@ class ERR_NativeHQBodyProbe
|
||||
}
|
||||
return null;
|
||||
}
|
||||
protected bool SameAmmo(ERR_HQAmmoSnapshot a, ERR_HQAmmoSnapshot b)
|
||||
{
|
||||
if (!a || !b || a.Complete != b.Complete || a.LauncherComplete != b.LauncherComplete) return false;
|
||||
if (a.Members != b.Members || a.SmallArmsMuzzles != b.SmallArmsMuzzles) return false;
|
||||
if (a.SmallArmsRounds != b.SmallArmsRounds || a.SmallArmsMagazines != b.SmallArmsMagazines) return false;
|
||||
if (a.SmallArmsChambers != b.SmallArmsChambers || a.LauncherRounds != b.LauncherRounds) return false;
|
||||
return a.LauncherMagazines == b.LauncherMagazines && a.LauncherChambers == b.LauncherChambers;
|
||||
}
|
||||
// Read-only independent observation of original living members. Nothing here is
|
||||
// assigned to PendingStatus or delivered to Watch; the real production sender did that.
|
||||
protected bool NativeAmmo(ERR_HQUnit unit, ERR_HQAmmoSnapshot queued)
|
||||
{
|
||||
if (!unit || !unit.Group || !queued) return false;
|
||||
ERR_HQAmmoSnapshot inspected = new ERR_HQAmmoSnapshot();
|
||||
inspected.Complete = true; inspected.LauncherComplete = true;
|
||||
array<IEntity> loadedIdentities = {};
|
||||
int nativeLoadedRounds;
|
||||
int nativeLoadedMagazines;
|
||||
for (int slot = 0; slot < unit.StatusSampler.InitialStrength(); slot++)
|
||||
{
|
||||
IEntity actor = unit.StatusSampler.InitialMember(slot);
|
||||
if (!ERR_Actors.Alive(actor) || ERR_Actors.Player(actor) || ERR_Actors.Group(actor) != unit.Group
|
||||
|| SCR_FactionManager.SGetFaction(actor) != m_Mode.EnemyFaction()
|
||||
|| !unit.StatusSampler.CanAttribute(slot, actor)) continue;
|
||||
ERR_HQAmmoSampler.Inspect(actor, unit.Group, inspected);
|
||||
Print(string.Format("ERR HQ BODY AMMO slot=%1 complete=%2 launcherComplete=%3 members=%4 rounds=%5",
|
||||
slot, inspected.Complete, inspected.LauncherComplete, inspected.Members, inspected.SmallArmsRounds));
|
||||
BaseWeaponManagerComponent manager;
|
||||
manager = BaseWeaponManagerComponent.Cast(actor.FindComponent(BaseWeaponManagerComponent));
|
||||
if (!manager) return false;
|
||||
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(actor.FindComponent(InventoryStorageManagerComponent));
|
||||
array<IEntity> inventoryItems = {};
|
||||
if (inventory) inventory.GetItems(inventoryItems);
|
||||
foreach (IEntity inventoryItem : inventoryItems)
|
||||
{
|
||||
if (!inventoryItem) { Print("ERR HQ BODY AMMO null inventory entry"); continue; }
|
||||
BaseMagazineComponent magazineItem = BaseMagazineComponent.Cast(inventoryItem.FindComponent(BaseMagazineComponent));
|
||||
if (magazineItem && !magazineItem.GetMagazineWell()) Print(string.Format("ERR HQ BODY AMMO no-well item=%1", inventoryItem.GetPrefabData().GetPrefabName()));
|
||||
}
|
||||
array<IEntity> weapons = {}; manager.GetWeaponsList(weapons);
|
||||
if (weapons.Count() > 8) return false;
|
||||
foreach (IEntity entity : weapons)
|
||||
{
|
||||
if (!entity) continue;
|
||||
BaseWeaponComponent weapon = BaseWeaponComponent.Cast(entity.FindComponent(BaseWeaponComponent));
|
||||
if (!weapon) return false;
|
||||
EWeaponType kind = weapon.GetWeaponType();
|
||||
Print(string.Format("ERR HQ BODY AMMO weapon kind=%1 prefab=%2", kind, entity.GetPrefabData().GetPrefabName()));
|
||||
bool smallArms = kind == EWeaponType.WT_RIFLE || kind == EWeaponType.WT_SNIPERRIFLE
|
||||
|| kind == EWeaponType.WT_MACHINEGUN || kind == EWeaponType.WT_HANDGUN;
|
||||
array<BaseMuzzleComponent> muzzles = {}; weapon.GetMuzzlesList(muzzles);
|
||||
Print(string.Format("ERR HQ BODY AMMO muzzle count=%1", muzzles.Count()));
|
||||
if (muzzles.Count() > 4) return false;
|
||||
foreach (BaseMuzzleComponent muzzle : muzzles)
|
||||
{
|
||||
if (muzzle) Print(string.Format("ERR HQ BODY AMMO muzzle kind=%1 barrels=%2 magazineWell=%3", muzzle.GetMuzzleType(), muzzle.GetBarrelsCount(), muzzle.GetMagazineWell() != null));
|
||||
if (!smallArms || !muzzle || muzzle.GetMuzzleType() != EMuzzleType.MT_BaseMuzzle) continue;
|
||||
BaseMagazineComponent loaded = muzzle.GetMagazine();
|
||||
if (!loaded || !loaded.GetOwner() || loadedIdentities.Contains(loaded.GetOwner())) continue;
|
||||
loadedIdentities.Insert(loaded.GetOwner());
|
||||
nativeLoadedRounds += loaded.GetAmmoCount(); nativeLoadedMagazines++;
|
||||
}
|
||||
}
|
||||
}
|
||||
Print(string.Format("ERR HQ BODY AMMO native members=%1 loaded-rounds=%2 loaded-mags=%3; queued rounds=%4 mags=%5 chambers=%6",
|
||||
inspected.Members, nativeLoadedRounds, nativeLoadedMagazines, queued.SmallArmsRounds,
|
||||
queued.SmallArmsMagazines, queued.SmallArmsChambers));
|
||||
return inspected.Valid(queued.Members) && SameAmmo(queued, inspected) && nativeLoadedRounds > 0
|
||||
&& nativeLoadedMagazines > 0 && queued.SmallArmsRounds >= nativeLoadedRounds
|
||||
&& queued.SmallArmsMagazines >= nativeLoadedMagazines && !queued.KnownSmallArmsEmpty();
|
||||
}
|
||||
protected bool NoLoss(ERR_HQ hq)
|
||||
{
|
||||
ERR_HQWatchEntry status = hq.ERR_BodyFixtureWatch(m_Setup.SourceId);
|
||||
@@ -205,6 +277,14 @@ class ERR_NativeHQBodyProbe
|
||||
if (!Check(m_Status.SourceId == m_Setup.SourceId && m_Status.ConfirmedLosses == 1
|
||||
&& m_Status.DeathSlots.Count() == 1 && m_Status.DeathSlots[0] == m_Setup.InitialSlot,
|
||||
"real surviving caller independently reports the same original casualty slot")) return -1;
|
||||
bool nativeAmmo = NativeAmmo(victim, m_Status.AmmoState);
|
||||
if (!Check(m_Status.AmmoState && m_Status.AmmoState.Complete && m_Status.AmmoState.Valid(m_Status.Count)
|
||||
&& m_Status.AmmoState.Members == m_Setup.InitialStrength - 1 && nativeAmmo,
|
||||
"real pending status matches original living native inventories and positive loaded small-arms ammunition"))
|
||||
return -1;
|
||||
m_AmmoAtQueue = m_Status.AmmoState.Snapshot();
|
||||
if (!Check(m_AmmoAtQueue != m_Status.AmmoState && SameAmmo(m_AmmoAtQueue, m_Status.AmmoState),
|
||||
"captured pending ammunition evidence is a detached unchanged scalar snapshot")) return -1;
|
||||
m_Step = 4; return 0;
|
||||
}
|
||||
if (m_Step == 4)
|
||||
@@ -215,12 +295,18 @@ class ERR_NativeHQBodyProbe
|
||||
if (!Check(status && status.MessageId == m_Status.MessageId && status.ConfirmedLosses == 1
|
||||
&& status.Count == m_Setup.InitialStrength - 1,
|
||||
"delivered cumulative status overlaps body evidence without double-counting")) return -1;
|
||||
if (!Check(status.AmmoState && status.AmmoState != m_Status.AmmoState
|
||||
&& status.AmmoState != m_AmmoAtQueue && SameAmmo(status.AmmoState, m_AmmoAtQueue)
|
||||
&& SameAmmo(m_Status.AmmoState, m_AmmoAtQueue) && !status.AmmoState.KnownSmallArmsEmpty(),
|
||||
"actual radio delivery stores an independent Watch ammunition snapshot equal to the pending evidence")) return -1;
|
||||
m_StableUntil = now + 20000; m_Step = 5; return 0;
|
||||
}
|
||||
ERR_HQWatchEntry stable = hq.ERR_BodyFixtureWatch(m_Setup.SourceId);
|
||||
if (!stable || stable.ConfirmedLosses != 1 || hq.ERR_BodyFixtureContact(m_Setup.Actor))
|
||||
{ Check(false, "confirmed corpse lost idempotence or became a firing contact"); return -1; }
|
||||
if (now < m_StableUntil) return 0;
|
||||
if (!Check(SameAmmo(stable.AmmoState, m_AmmoAtQueue) && SameAmmo(m_Status.AmmoState, m_AmmoAtQueue),
|
||||
"delivered and pending ammunition snapshots remain unchanged after twenty further seconds")) return -1;
|
||||
Check(true, "confirmed corpse remains one loss with no firing contact after twenty further seconds");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user