#ifdef WORKBENCH // Read-only evidence hooks. Every production method delegates unchanged. modded class ERR_HQ { void ERR_ResponseUnits(out array units) { units.Clear(); if (!ERR_NativeHQResponseProof.Enabled()) return; foreach (ERR_HQUnit unit : m_Units) units.Insert(unit); } protected override void Observe(ERR_HQUnit unit, float now) { ERR_HQReport previous = unit.PendingReport; super.Observe(unit, now); ERR_NativeHQResponseProof proof = ERR_NativeHQResponseProof.Active(); if (proof && unit.PendingReport && unit.PendingReport != previous) proof.Observed(this, unit, now); } protected override void Accept(ERR_HQReport report, float now) { super.Accept(report, now); ERR_NativeHQResponseProof proof = ERR_NativeHQResponseProof.Active(); if (!proof || !report) return; foreach (ERR_HQReport accepted : m_Contacts) if (accepted.MessageId == report.MessageId) { proof.Accepted(this, accepted, now); break; } } protected override void DeliverOrder(ERR_HQUnit unit, float now) { ERR_HQReport order = unit.PendingOrder; ERR_HQRoute route = unit.Downlink; super.DeliverOrder(unit, now); ERR_NativeHQResponseProof proof = ERR_NativeHQResponseProof.Active(); if (proof && order && route && unit.Assignment == order && unit.Waypoint) proof.Delivered(this, unit, route, now); } } modded class ERR_HQJournal { override void Write(string kind, string message, int messageId = 0) { super.Write(kind, message, messageId); ERR_NativeHQResponseProof proof = ERR_NativeHQResponseProof.Active(); if (proof) proof.JournalEvent(this, kind, message, messageId); } } modded class SCR_AIGroupUtilityComponent { IEntity ERR_ResponseVisualObserver(ERR_HQReport report, float now) { foreach (SCR_AIInfoComponent info : m_aInfoComponents) { if (!info || !info.m_Perception) continue; AIAgent agent = AIAgent.Cast(info.GetOwner()); if (!agent || !ERR_Actors.CanFight(agent.GetControlledEntity())) continue; array targets = {}; info.m_Perception.GetTargetsList(targets, ETargetCategory.ENEMY); foreach (BaseTarget target : targets) { ERR_HQVisualContact sample = ERR_HQObservation.Capture(target, now); if (sample && sample.Entity == report.Target && sample.Escapist && Math.AbsFloat(sample.ObservedAt - report.ObservedAt) < 1 && vector.Distance(sample.Position, report.Position) < 0.1) return agent.GetControlledEntity(); } } return null; } } class ERR_NativeResponseUnit { ERR_HQUnit Unit; SCR_AIGroup Group; IEntity Radio; ref array Actors = {}; } class ERR_NativeResponseJournal { bool Report; bool Transmit; bool HQReceive; bool HQTransmit; bool UnitReceive; bool Delivered; } class ERR_NativeResponseLineage { ref ERR_HQReport Report; ERR_HQUnit Source; IEntity Observer; IEntity SourceRadio; ref ERR_HQRoute Uplink; bool Accepted; float AcceptedAt; ERR_HQUnit Recipient; IEntity RecipientRadio; int DeliveryId; AIWaypoint Waypoint; IEntity MovingActor; vector DeliveredOrigin; float DeliveredAt; } class ERR_NativeHQResponseProof { protected static ERR_NativeHQResponseProof s_Active; protected ERR_GameMode m_Mode; protected ERR_HQ m_HQ; protected IEntity m_Player; protected SCR_PlayerController m_Controller; protected ERR_PlayerLife m_Life; protected ERR_HQUnit m_Source; protected DamageManagerComponent m_Damage; protected bool m_DamageWasEnabled; protected bool m_Protected; protected bool m_Started; protected bool m_Stopped; protected bool m_Failed; protected string m_Failure; protected float m_Deadline; protected float m_NextDiagnostic; protected ref array m_Units = {}; protected ref array m_Forces = {}; protected ref array m_Reports = {}; protected ref map m_Journal = new map(); static bool Enabled() { string enabled, outcome; return Replication.IsServer() && System.GetCLIParam("errSmoke", enabled) && enabled == "1" && System.GetCLIParam("errSmokeOutcome", outcome) && outcome == "hq-response"; } static ERR_NativeHQResponseProof Active() { return s_Active; } void ERR_NativeHQResponseProof(ERR_GameMode mode, IEntity player) { m_Mode = mode; m_Player = player; m_HQ = ERR_HQ.Get(); m_Deadline = GetGame().GetWorld().GetWorldTime() + 140000; if (Enabled() && !s_Active) s_Active = this; } protected bool Fail(string reason) { m_Failed = true; m_Failure = reason; return false; } protected bool Check(bool condition, string detail) { if (condition) { Print("ERR SMOKE PASS: HQ response " + detail); return true; } Print("ERR SMOKE FAIL: HQ response " + detail, LogLevel.ERROR); Stop(); return false; } protected ERR_NativeResponseUnit Original(ERR_HQUnit unit) { foreach (ERR_NativeResponseUnit original : m_Units) if (original.Unit == unit && original.Group == unit.Group) return original; return null; } protected ERR_NativeResponseLineage Report(int id) { foreach (ERR_NativeResponseLineage report : m_Reports) if (report.Report.MessageId == id) return report; return null; } protected bool Canonical() { return m_Player && m_Controller && m_Life && m_Mode.Players().CurrentActor(m_Player) == m_Life && m_Controller == GetGame().GetPlayerController() && m_Controller.GetControlledEntity() == m_Player && m_Life.Actor == m_Player && m_Life.Connected && m_Life.UsedLife; } protected bool UnchangedForces() { array current = {}; m_HQ.ERR_ResponseUnits(current); if (current.Count() != m_Units.Count()) return false; foreach (ERR_HQUnit unit : current) { ERR_NativeResponseUnit original = Original(unit); if (!original) return false; array agents = {}; unit.Group.GetAgents(agents); if (agents.Count() != original.Actors.Count()) return false; foreach (AIAgent agent : agents) if (!agent || !original.Actors.Contains(agent.GetControlledEntity())) return false; } array forces = {}; m_HQ.PhysicalForces(forces); if (forces.Count() != m_Forces.Count()) return false; foreach (IEntity entity : forces) if (!m_Forces.Contains(entity)) return false; return true; } protected bool Arrange() { array units = {}; m_HQ.ERR_ResponseUnits(units); foreach (ERR_HQUnit unit : units) { if (!unit.Group || !unit.Utility || !unit.Radio || ERR_HQRadio.Capability(unit.Radio) != 2) return false; array agents = {}; unit.Group.GetAgents(agents); if (agents.IsEmpty() || !unit.Group.IsExpandComplete()) return false; ERR_NativeResponseUnit original = new ERR_NativeResponseUnit(); original.Unit = unit; original.Group = unit.Group; original.Radio = unit.Radio; foreach (AIAgent agent : agents) { if (!agent || !ERR_Actors.CanFight(agent.GetControlledEntity())) return false; original.Actors.Insert(agent.GetControlledEntity()); } m_Units.Insert(original); if (!m_Source && !unit.ReservedForSupport) m_Source = unit; } if (!m_Source || m_Units.Count() < 2) return false; m_HQ.PhysicalForces(m_Forces); m_Controller = SCR_PlayerController.Cast(GetGame().GetPlayerController()); m_Life = m_Mode.Players().CurrentActor(m_Player); if (!Canonical()) return false; m_Damage = DamageManagerComponent.Cast(m_Player.FindComponent(DamageManagerComponent)); if (!m_Damage) return false; m_DamageWasEnabled = m_Damage.IsDamageHandlingEnabled(); m_Damage.EnableDamageHandling(false); m_Protected = true; // Preserve the established fixture arrangement: move only the real prisoner. // Native perception must discover him; neither targets nor reports are seeded. vector position = ERR_Actors.Ground(m_Source.Group.GetOrigin() + "0 0 20"); vector transform[4]; m_Player.GetWorldTransform(transform); transform[3] = position; ChimeraCharacter.Cast(m_Player).Teleport(transform); m_Started = true; PrintFormat("ERR HQ RESPONSE ARRANGEMENT: canonical prisoner moved to=%1 near original source group=%2; temporary player damage protection=%3; no AI/report/radio cadence changes", position, m_Source.Id, m_Protected); return true; } void JournalEvent(ERR_HQJournal journal, string kind, string message, int messageId) { if (!m_Started || m_Stopped || !m_HQ || journal != m_HQ.Journal() || messageId <= 0) return; ERR_NativeResponseJournal entry = m_Journal.Get(messageId); if (!entry) { if (m_Journal.Count() >= 128) { Fail("bounded journal evidence map exhausted"); return; } entry = new ERR_NativeResponseJournal(); m_Journal.Insert(messageId, entry); } if (kind == "REPORT") entry.Report = true; if (kind == "TRANSMIT") { entry.Transmit = true; if (message.StartsWith("HQ -> ")) entry.HQTransmit = true; } if (kind == "RECEIVE") { if (message.StartsWith("HQ received from ")) entry.HQReceive = true; else if (message.StartsWith("unit ")) entry.UnitReceive = true; } if (kind == "ORDER DELIVERED") entry.Delivered = true; } void Observed(ERR_HQ hq, ERR_HQUnit unit, float now) { if (!m_Started || m_Stopped || hq != m_HQ || unit != m_Source || unit.PendingReport.Target != m_Player) return; ERR_HQReport report = unit.PendingReport; ERR_NativeResponseUnit original = Original(unit); IEntity observer = unit.Utility.ERR_ResponseVisualObserver(report, now); if (!Canonical() || !original || !original.Actors.Contains(observer) || !unit.Uplink || unit.Uplink.Nodes.IsEmpty() || unit.Uplink.Nodes[0].Carrier != unit.Radio || unit.Uplink.MessageId != report.MessageId || unit.Radio != original.Radio || !original.Actors.Contains(unit.Radio) || report.Source != original.Group || report.ObservedAt > now || Report(report.MessageId)) { Fail("real observed report lacks canonical original observer/radio/source lineage"); return; } if (m_Reports.Count() >= 32) { Fail("bounded report evidence exhausted"); return; } ERR_NativeResponseLineage proof = new ERR_NativeResponseLineage(); proof.Report = report.Snapshot(); proof.Source = unit; proof.Observer = observer; proof.SourceRadio = unit.Radio; proof.Uplink = unit.Uplink; m_Reports.Insert(proof); PrintFormat("ERR HQ RESPONSE SIGHTING: source=%1 report=M%2 observer=%3 radio=%4 target=%5 observedAt=%6; actual native visual sample", unit.Id, report.MessageId, observer, unit.Radio, m_Player, report.ObservedAt); } void Accepted(ERR_HQ hq, ERR_HQReport report, float now) { if (!m_Started || m_Stopped || hq != m_HQ) return; ERR_NativeResponseLineage proof = Report(report.MessageId); if (!proof) return; if (report.Target != m_Player || report.Source != proof.Report.Source || report.ObservedAt != proof.Report.ObservedAt || vector.Distance(report.Position, proof.Report.Position) > 0.01 || !proof.Uplink || proof.Uplink.Failed || proof.Uplink.Sending || proof.Uplink.Cursor < proof.Uplink.Nodes.Count()) { Fail("accepted report lacks completed actual uplink or immutable observed time"); return; } proof.Accepted = true; proof.AcceptedAt = now; } void Delivered(ERR_HQ hq, ERR_HQUnit unit, ERR_HQRoute route, float now) { if (!m_Started || m_Stopped || hq != m_HQ || !unit.Assignment) return; ERR_NativeResponseLineage proof = Report(unit.Assignment.MessageId); if (!proof || proof.Recipient) return; ERR_NativeResponseUnit original = Original(unit); if (!proof.Accepted || !original || unit == proof.Source || !unit.Assignment || unit.Assignment.Target != m_Player || unit.Assignment.Source != proof.Report.Source || unit.Assignment.ObservedAt != proof.Report.ObservedAt || vector.Distance(unit.Assignment.Position, proof.Report.Position) > 0.01 || unit.Radio != original.Radio || !original.Actors.Contains(unit.Radio) || !route.Downlink || route.Nodes.IsEmpty() || route.Nodes[route.Nodes.Count() - 1].Carrier != unit.Radio || route.Failed || route.Sending || route.Cursor != route.Nodes.Count() - 1 || !unit.Waypoint) { Fail("delivered response lacks immutable accepted report and original physical recipient/downlink"); return; } proof.Recipient = unit; proof.RecipientRadio = unit.Radio; proof.DeliveryId = route.MessageId; proof.Waypoint = unit.Waypoint; proof.DeliveredAt = now; foreach (IEntity actor : original.Actors) if (ERR_Actors.CanFight(actor)) { proof.MovingActor = actor; break; } if (proof.MovingActor) proof.DeliveredOrigin = proof.MovingActor.GetOrigin(); PrintFormat("ERR HQ RESPONSE DELIVERED: report=M%1 downlink=M%2 source=%3 recipient=%4 radio=%5 waypoint=%6 observedAt=%7", proof.Report.MessageId, route.MessageId, proof.Source.Id, unit.Id, unit.Radio, unit.Waypoint, unit.Assignment.ObservedAt); } int Tick(float now) { if (m_Stopped) return -1; if (!Enabled() || s_Active != this || !m_Mode || !m_Mode.Active() || !m_HQ || now > m_Deadline || m_Failed) { Check(false, "bounded active evidence context: " + m_Failure); return -1; } if (!m_Started) { if (!m_HQ.ERR_ProbeSquadsReady()) return 0; array guns = {}; m_HQ.Mortars().AppendGuns(guns); foreach (IEntity gun : guns) { ERR_MortarBattery battery = m_HQ.Mortars().FindGun(gun); if (!battery || !battery.StartupActivated || !battery.Operational() || !m_HQ.MortarConnected(battery.Group)) return 0; } if (!Check(Arrange(), "original physical force, RTOs and canonical prisoner captured before arranged sighting")) return -1; return 0; } if (!Canonical() || !UnchangedForces()) { Check(false, "canonical player and all original physical group/actor identities retained without added force"); return -1; } if (now >= m_NextDiagnostic) { PrintFormat("ERR HQ RESPONSE PROOF: observed source reports=%1; %2", m_Reports.Count(), m_HQ.ERR_ProbePerception()); m_NextDiagnostic = now + 10000; } foreach (ERR_NativeResponseLineage proof : m_Reports) { if (!proof.Recipient || !proof.MovingActor) continue; if (proof.Recipient.Waypoint != proof.Waypoint || !proof.Recipient.Assignment || proof.Recipient.Assignment.MessageId != proof.Report.MessageId) continue; ERR_NativeResponseJournal uplink = m_Journal.Get(proof.Report.MessageId); ERR_NativeResponseJournal downlink = m_Journal.Get(proof.DeliveryId); if (!uplink || !downlink || !uplink.Report || !uplink.Transmit || !uplink.HQReceive || !downlink.HQTransmit || !downlink.UnitReceive || !downlink.Delivered) continue; if (proof.Recipient.Group.GetCurrentWaypoint() != proof.Waypoint || vector.DistanceXZ(proof.MovingActor.GetOrigin(), proof.DeliveredOrigin) < 3) continue; if (vector.DistanceXZ(proof.MovingActor.GetOrigin(), proof.Report.Position) >= vector.DistanceXZ(proof.DeliveredOrigin, proof.Report.Position) - 1) continue; if (!Check(proof.SourceRadio && proof.RecipientRadio && m_HQ.ERR_ProbeUniqueAssignments(), "actual sighting/report/uplink/HQ receipt/downlink journal lineage reaches distinct original infantry with bounded unique waypoints")) return -1; if (!Check(UnchangedForces(), "original recipient physically moves toward its native Search waypoint with no replacement or additional force")) return -1; Stop(); return 1; } return 0; } void Stop() { if (m_Stopped) return; m_Stopped = true; if (m_Protected && m_Damage) m_Damage.EnableDamageHandling(m_DamageWasEnabled); m_Protected = false; if (s_Active == this) s_Active = null; } void ~ERR_NativeHQResponseProof() { Stop(); } } #endif