Integrate owned Intel rerolls, discovery feedback and fair HQ reports

This commit is contained in:
2026-09-19 23:00:02 +02:00
parent 6cf989a060
commit 27989b85a3
46 changed files with 5756 additions and 15 deletions
@@ -39,6 +39,11 @@ modded class ERR_GameMode
protected ref ERR_NativeRadioProbe m_ERRRadioProbe;
protected ref ERR_NativeHQResponseProof m_ERRHQResponseProof;
protected ref array<IEntity> m_ERRCacheFolders = {};
protected int m_ERRIntelRerollStage;
protected float m_ERRIntelRerollDeadline;
protected ref array<IEntity> m_ERRIntelActors = {};
protected ref array<IEntity> m_ERRRetiredIntel = {};
protected override void EOnInit(IEntity owner)
{
@@ -75,6 +80,68 @@ modded class ERR_GameMode
Print("ERR SMOKE: scripted integration test enabled; gameplay acceptance remains separate");
}
// Ordinary victory fixture additionally exercises the actual administrator
// reroll against native enemy inventories. Scripted, not remote UI evidence.
protected bool ERR_CheckIntelReroll(float now)
{
if (m_ERRIntelRerollStage == 3) return true;
if (m_ERRIntelRerollStage == 0)
{
if (!ERR_Check(Sites() && Sites().Find("everon-supply-2") && Sites().Find("everon-supply-2").Group, "reroll cache group is ready")) return false;
array<AIAgent> guards = {};
Sites().Find("everon-supply-2").Group.GetAgents(guards);
foreach (AIAgent guard : guards)
{
if (!guard) continue;
IEntity actor = guard.GetControlledEntity();
if (ERR_Actors.Alive(actor) && !ERR_Actors.Player(actor)) m_ERRIntelActors.Insert(actor);
}
if (!ERR_Check(!m_ERRIntelActors.IsEmpty(), "reroll observes original living cache guards")) return false;
array<string> replies = {};
string before = m_Intel.RerollStatus();
m_Admin.Execute(this, false, "intel reroll", replies);
if (!ERR_Check(m_Intel.RerollStatus() == before && !m_Intel.RerollRunning(), "unauthorized reroll cannot start a batch")) return false;
if (!ERR_Check(m_Settings.Set("aiIntelChancePercent", 100), "native reroll captured chance configured")) return false;
m_Admin.Execute(this, true, "intel reroll", replies);
if (!ERR_Check(m_Intel.RerollRunning() && !m_Intel.BeginReroll(), "administrator starts one batch; overlapping reroll rejected")) return false;
if (!ERR_Check(m_Settings.Set("aiIntelChancePercent", 0), "live setting change does not alter captured batch chance")) return false;
m_ERRIntelRerollDeadline = now + 90000;
m_ERRIntelRerollStage = 1;
return false;
}
if (now >= m_ERRIntelRerollDeadline) return ERR_Check(false, "native reroll exceeded bounded fixture deadline");
if (m_Intel.RerollRunning()) return false;
Print("ERR INTEL REROLL: " + m_Intel.RerollStatus());
if (!ERR_Check(m_Intel.RerollStatus().IndexOf(", 0 failed,") >= 0, "native inventory reroll completes without failed operations")) return false;
foreach (IEntity actor : m_ERRIntelActors)
{
if (!ERR_Check(ERR_Actors.Alive(actor), "original cache guard survives the reroll fixture")) return false;
array<IEntity> folders = {};
ERR_DiscoveryService.Folders(InventoryStorageManagerComponent.Cast(actor.FindComponent(InventoryStorageManagerComponent)), folders);
if (m_ERRIntelRerollStage == 1)
{
if (!ERR_Check(folders.Count() == 1, "captured 100 percent batch assigns one native folder despite live zero setting")) return false;
m_ERRRetiredIntel.Insert(folders[0]);
}
else if (!ERR_Check(folders.IsEmpty(), "zero percent reroll removes original native AI folders without replacements")) return false;
}
array<IEntity> carried = {};
ERR_DiscoveryService.Folders(InventoryStorageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(InventoryStorageManagerComponent)), carried);
foreach (IEntity document : m_ERRCacheFolders)
if (!ERR_Check(carried.Contains(document), "reroll preserves player's exact collected clue documents")) return false;
if (!ERR_Check(m_ERRSmokeRadio.Knowledge() == 2, "reroll preserves already identified radio")) return false;
if (m_ERRIntelRerollStage == 1)
{
if (!ERR_Check(m_Intel.BeginReroll(), "next independent batch uses current zero probability")) return false;
m_ERRIntelRerollStage = 2;
return false;
}
foreach (IEntity retired : m_ERRRetiredIntel)
if (!ERR_Check(retired && Discovery().IsSpent(retired) && m_OwnedEntities.Contains(retired), "retired native document remains spent and owned for round cleanup")) return false;
m_ERRIntelRerollStage = 3;
return true;
}
protected bool ERR_Check(bool condition, string name)
{
if (condition) { Print("ERR SMOKE PASS: " + name); return true; }
@@ -499,6 +566,7 @@ modded class ERR_GameMode
}
else if (m_ERRSmokeStep == 3)
{
if (!ERR_CheckIntelReroll(now)) return;
if (!ERR_Check(m_ERRSmokeRadio.Knowledge() == 2, "carried intel identifies radio through intel service")) return;
if (!ERR_Check(!TuneRadio(m_ERRSmokePlayer, m_ERRSmokeRadio), "radio rejects distant player")) return;
ERR_MovePlayer(m_ERRSmokeRadio.Position() + "2 0 0");