Integrate startup optics and supply vehicle lock picking

This commit is contained in:
2026-09-20 05:34:30 +02:00
parent 9205e2129a
commit 963cab50c0
104 changed files with 16171 additions and 25 deletions
@@ -0,0 +1,251 @@
#ifdef WORKBENCH
// Opt-in controlled arrangement of the existing local prisoner only. Production
// perception, radio intake, planning and downlink execution remain unchanged.
modded class ERR_HQ
{
protected override void Observe(ERR_HQUnit unit, float now)
{
ERR_HQReport before = unit.PendingReport;
super.Observe(unit, now);
ERR_NativeConvoyCoverProbe proof = ERR_NativeConvoyCoverProbe.Active();
if (proof && unit.PendingReport && unit.PendingReport != before) proof.Observed(unit, now);
}
protected override void Accept(ERR_HQReport report, float now)
{
super.Accept(report, now);
ERR_NativeConvoyCoverProbe proof = ERR_NativeConvoyCoverProbe.Active();
if (!proof || !report) return;
foreach (ERR_HQReport accepted : m_Contacts)
if (accepted.MessageId == report.MessageId) { proof.Accepted(accepted, now); break; }
}
protected override void DeliverConvoyOrder(ERR_HQUnit unit, float now)
{
ERR_ConvoyCombatOrder order = unit.PendingConvoyOrder;
ERR_HQRoute route = unit.Downlink;
bool hadWaypoint;
ERR_ConvoyTask task = ConvoyTask();
if (task && !task.Vehicles.IsEmpty()) hadWaypoint = task.Vehicles[0].Waypoint != null;
super.DeliverConvoyOrder(unit, now);
ERR_NativeConvoyCoverProbe proof = ERR_NativeConvoyCoverProbe.Active();
if (proof && order && route) proof.Delivered(order, route, hadWaypoint, now);
}
}
class ERR_NativeConvoyCoverReport
{
ref ERR_HQReport Report;
ref ERR_HQRoute Uplink;
bool Accepted;
}
class ERR_NativeConvoyCoverProbe
{
protected static ERR_NativeConvoyCoverProbe s_Active;
protected ERR_GameMode m_Mode;
protected ERR_HQ m_HQ;
protected ERR_ConvoyTask m_Task;
protected ERR_ConvoyVehicle m_Lead;
protected IEntity m_Player;
protected SCR_PlayerController m_Controller;
protected ERR_PlayerLife m_Life;
protected DamageManagerComponent m_Damage;
protected bool m_DamageWasEnabled;
protected bool m_Protected;
protected bool m_Stopped;
protected bool m_Failed;
protected bool m_Held;
protected bool m_Resumed;
protected int m_RouteIndex;
protected int m_LedgerCount;
protected float m_Deadline;
protected float m_HeldAt;
protected float m_ResumedAt;
protected float m_NextLog;
protected vector m_HoldPosition;
protected vector m_ResumePosition;
protected vector m_HidePosition;
protected ref array<IEntity> m_Forces = {};
protected ref array<ref ERR_NativeConvoyCoverReport> m_Reports = {};
protected int m_Step;
static bool Enabled()
{
string flag;
return ERR_NativeConvoyProbe.Enabled() && System.GetCLIParam("errConvoyCover", flag) && flag == "1";
}
static ERR_NativeConvoyCoverProbe Active() { return s_Active; }
void ERR_NativeConvoyCoverProbe(ERR_GameMode mode) { m_Mode = mode; }
protected bool Check(bool condition, string detail)
{
if (condition) { Print("ERR SMOKE PASS: convoy cover " + detail); return true; }
m_Failed = true; Print("ERR SMOKE FAIL: convoy cover " + detail, LogLevel.ERROR); Stop(); return false;
}
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 UnchangedState()
{
if (!Canonical() || !m_Task || m_Task.Stopped || m_Task.Vehicles.Count() != 6
|| m_Mode.Forces().Count() != m_LedgerCount || m_Task.Cargo.Count() != 56) return false;
foreach (ERR_ConvoyVehicle vehicle : m_Task.Vehicles)
if (!vehicle || vehicle.Released || !vehicle.CrewValid(m_Mode)) return false;
array<IEntity> current = {}; m_HQ.PhysicalForces(current);
if (current.Count() != m_Forces.Count()) return false;
foreach (IEntity entity : current) if (!m_Forces.Contains(entity)) return false;
return true;
}
protected bool Unchanged()
{
if (UnchangedState()) return true;
// Read-only, failure-only evidence. Preserve the original invariant result.
PrintFormat("ERR CONVOY COVER INVARIANT: canonical=%1 player=%2 controller=%3 life=%4 ledger=%5 expectedLedger=%6",
Canonical(), m_Player != null, m_Controller != null, m_Life != null, m_Mode.Forces().Count(), m_LedgerCount);
if (!m_Task) { Print("ERR CONVOY COVER INVARIANT: missing original task"); return false; }
PrintFormat("ERR CONVOY COVER INVARIANT: stopped=%1 reason=%2 ready=%3 vehicles=%4 cargoCallbacks=%5",
m_Task.Stopped, m_Task.Reason, m_Task.Ready, m_Task.Vehicles.Count(), m_Task.Cargo.Count());
for (int index = 0; index < m_Task.Vehicles.Count() && index < 6; index++)
{
ERR_ConvoyVehicle vehicle = m_Task.Vehicles[index];
if (!vehicle) { PrintFormat("ERR CONVOY COVER INVARIANT: missing vehicle record=%1", index); continue; }
bool crewValid = vehicle.CrewValid(m_Mode);
PrintFormat("ERR CONVOY COVER INVARIANT: vehicle=%1 released=%2 arrived=%3 crewValid=%4 entityAlive=%5 group=%6 routeIndex=%7 waypoint=%8",
index, vehicle.Released, vehicle.Arrived, crewValid, ERR_Actors.Alive(vehicle.Entity), vehicle.Group, vehicle.RouteIndex, vehicle.Waypoint != null);
if (crewValid) continue;
IEntity driverVehicle;
if (vehicle.Driver) driverVehicle = CompartmentAccessComponent.GetVehicleIn(vehicle.Driver);
PrintFormat("ERR CONVOY COVER INVARIANT: vehicle=%1 driverConscious=%2 driverPlayer=%3 driverAboardOriginal=%4",
index, ERR_Actors.CanFight(vehicle.Driver), ERR_Actors.Player(vehicle.Driver),
ERR_ConvoyRules.PartOf(driverVehicle, vehicle.Entity));
for (int memberIndex = 0; memberIndex < vehicle.Members.Count() && memberIndex < 19; memberIndex++)
{
IEntity member = vehicle.Members[memberIndex];
PrintFormat("ERR CONVOY COVER INVARIANT: vehicle=%1 member=%2 actor=%3 alive=%4 player=%5 sameGroup=%6",
index, memberIndex, member, ERR_Actors.Alive(member), ERR_Actors.Player(member), ERR_Actors.Group(member) == vehicle.Group);
}
}
array<IEntity> current = {}; m_HQ.PhysicalForces(current);
PrintFormat("ERR CONVOY COVER INVARIANT: currentForces=%1 initialForces=%2", current.Count(), m_Forces.Count());
int differences;
foreach (IEntity added : current)
if (!m_Forces.Contains(added) && differences++ < 8) PrintFormat("ERR CONVOY COVER INVARIANT: newly listed physical entity=%1", added);
differences = 0;
foreach (IEntity missing : m_Forces)
if (!current.Contains(missing) && differences++ < 8) PrintFormat("ERR CONVOY COVER INVARIANT: no longer listed physical entity=%1", missing);
return false;
}
protected void MovePrisoner(vector position)
{
vector transform[4]; m_Player.GetWorldTransform(transform);
transform[3] = ERR_Actors.Ground(position);
ChimeraCharacter.Cast(m_Player).Teleport(transform);
}
protected ERR_NativeConvoyCoverReport Find(int id)
{
foreach (ERR_NativeConvoyCoverReport entry : m_Reports)
if (entry.Report.MessageId == id) return entry;
return null;
}
void Observed(ERR_HQUnit unit, float now)
{
if (m_Stopped || !unit.PendingReport || unit.PendingReport.Target != m_Player || !unit.Uplink) return;
IEntity observer = unit.Utility.ERR_ResponseVisualObserver(unit.PendingReport, now);
if (!observer || !m_Forces.Contains(observer) || m_Reports.Count() >= 64) return;
ERR_NativeConvoyCoverReport entry = new ERR_NativeConvoyCoverReport();
entry.Report = unit.PendingReport.Snapshot(); entry.Uplink = unit.Uplink; m_Reports.Insert(entry);
}
void Accepted(ERR_HQReport report, float now)
{
if (m_Stopped) return;
ERR_NativeConvoyCoverReport entry = Find(report.MessageId);
if (!entry) return;
entry.Accepted = !entry.Uplink.Failed && entry.Uplink.StartedAt >= 0
&& entry.Uplink.Cursor >= entry.Uplink.Nodes.Count();
}
void Delivered(ERR_ConvoyCombatOrder order, ERR_HQRoute route, bool hadWaypoint, float now)
{
if (m_Stopped || !m_Lead || order.Group != m_Lead.Group
|| m_Lead.Combat.LastCommandId != order.CommandId || route.Failed) return;
if (!Check(route.Downlink && route.StartedAt >= 0 && route.Cursor == route.Nodes.Count() - 1,
"original crew received its real completed downlink")) return;
if (order.Hold)
{
ERR_NativeConvoyCoverReport entry = Find(order.ReportId);
if (!Check(entry && entry.Accepted && entry.Report.Target == m_Player,
"HOLD traces to actual original observer perception and delivered sighting")) return;
if (m_Held) return;
if (!Check(hadWaypoint && m_Lead.Combat.Held && !m_Lead.Waypoint,
"delivered HOLD removed the owned native road waypoint")) return;
m_Held = true; m_HeldAt = now; m_RouteIndex = m_Lead.RouteIndex;
m_HoldPosition = m_Lead.Entity.GetOrigin();
}
else
{
if (!Check(m_Held && !hadWaypoint && !m_Lead.Combat.Held && m_Lead.Waypoint
&& m_Lead.RouteIndex == m_RouteIndex && now - order.ObservedAt >= 60000,
"delivered RESUME restores one road waypoint at the preserved index after quiet evidence")) return;
m_Resumed = true; m_ResumedAt = now; m_ResumePosition = m_Lead.Entity.GetOrigin();
}
}
int Tick(ERR_HQ hq, float now)
{
if (!Enabled() || !hq || m_Failed || m_Stopped) return -1;
if (m_Step == 0)
{
m_HQ = hq; m_Task = hq.ConvoyTask();
m_Controller = SCR_PlayerController.Cast(GetGame().GetPlayerController());
if (m_Controller) m_Player = m_Controller.GetControlledEntity();
m_Life = m_Mode.Players().CurrentActor(m_Player);
if (!Check(Canonical() && m_Task && m_Task.Ready && m_Task.Vehicles.Count() == 6,
"canonical local prisoner and previously proven physical convoy selected")) return -1;
m_Lead = m_Task.Vehicles[0];
ERR_SiteRuntime hide = m_Mode.Sites().Find("everon-extraction-1");
if (!Check(hide && hide.Definition && !m_Lead.Combat.Held && m_Lead.Waypoint
&& vector.DistanceXZ(hide.Definition.Position, m_Lead.Entity.GetOrigin()) >= 800,
"lead has a live road order and authored distant concealment destination")) return -1;
m_HidePosition = hide.Definition.Position;
m_Damage = DamageManagerComponent.Cast(m_Player.FindComponent(DamageManagerComponent));
if (!Check(m_Damage != null, "existing prisoner native damage component found")) return -1;
m_DamageWasEnabled = m_Damage.IsDamageHandlingEnabled(); m_Damage.EnableDamageHandling(false); m_Protected = true;
m_HQ.PhysicalForces(m_Forces); m_LedgerCount = m_Mode.Forces().Count();
vector vehicleTransform[4]; m_Lead.Entity.GetWorldTransform(vehicleTransform);
s_Active = this; m_Deadline = now + 300000; m_Step = 1;
MovePrisoner(m_Lead.Entity.GetOrigin() + vehicleTransform[0] * 20);
Print("ERR CONVOY COVER arrangement: existing prisoner moved beside original lead; temporary damage protection; no AI, inventory, reports, timers or radio routes changed.");
}
if (!Unchanged()) { Check(false, "original physical forces or canonical player changed"); return -1; }
if (now >= m_Deadline) { Check(false, "bounded sighting/hold/resume deadline"); return -1; }
if (now >= m_NextLog)
{
m_NextLog = now + 10000;
PrintFormat("ERR CONVOY COVER: step=%1 held=%2 resumed=%3 report=%4 observed=%5 routeIndex=%6 waypoint=%7 reports=%8",
m_Step, m_Lead.Combat.Held, m_Resumed, m_Lead.Combat.ReportId, m_Lead.Combat.ObservedAt, m_Lead.RouteIndex, m_Lead.Waypoint != null, m_Reports.Count());
}
if (m_Step == 1 && m_Held)
{
if (m_Lead.Waypoint || m_Lead.RouteIndex != m_RouteIndex) { Check(false, "held native road order unexpectedly advanced"); return -1; }
if (now - m_HeldAt < 5000) return 0;
if (!Check(true, "owned road waypoint stayed absent and route index stable for five seconds")) return -1;
PrintFormat("ERR CONVOY COVER held native movement=%1m (native combat movement is not suppressed)", vector.DistanceXZ(m_HoldPosition, m_Lead.Entity.GetOrigin()));
MovePrisoner(m_HidePosition); m_Step = 2;
Print("ERR CONVOY COVER arrangement: same prisoner moved to distant authored extraction site; native visibility and radio must expire nearby evidence.");
}
if (m_Step == 2 && m_Resumed)
{
if (vector.DistanceXZ(m_ResumePosition, m_Lead.Entity.GetOrigin()) < 20) return 0;
if (!Check(!m_Lead.Combat.Held && now > m_ResumedAt && Unchanged(),
"same native lead vehicle drove twenty metres after delivered RESUME; forces and cargo unchanged")) 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_NativeConvoyCoverProbe() { Stop(); }
}
#endif
@@ -59,6 +59,7 @@ class ERR_NativeConvoyRoadSurvey
class ERR_NativeConvoyProbe
{
protected ERR_GameMode m_Mode;
protected ref ERR_NativeConvoyCoverProbe m_Cover;
protected ref ERR_ConvoyTask m_Task;
protected ref array<vector> m_Origins = {};
protected ref array<IEntity> m_OriginalVehicles = {};
@@ -165,6 +166,38 @@ class ERR_NativeConvoyProbe
PrintFormat("ERR CONVOY MOTION: vehicle=%1 groupAction=%2 driverBehavior=%3", i, groupAction, driverBehavior);
}
}
// Failure-only readout distinguishes incapacitation, ownership, native seat
// switching and dismounts without changing the exact original-seat assertion.
protected void SeatDiagnostic(ERR_ConvoyVehicle vehicle, int index, IEntity actor, BaseCompartmentSlot intended, bool duplicateActor, bool duplicateSeat)
{
IEntity aboard, occupant;
SCR_AIGroup actualGroup;
BaseCompartmentSlot actual;
ChimeraCharacter character = ChimeraCharacter.Cast(actor);
if (actor) { aboard = CompartmentAccessComponent.GetVehicleIn(actor); actualGroup = ERR_Actors.Group(actor); }
if (intended) occupant = intended.GetOccupant();
if (character && character.GetCompartmentAccessComponent()) actual = character.GetCompartmentAccessComponent().GetCompartment();
int intendedType = -1, actualType = -1, actualManager = -1, actualSlot = -1;
if (intended) intendedType = intended.GetType();
if (actual) { actualType = actual.GetType(); actualManager = actual.GetCompartmentMgrID(); actualSlot = actual.GetCompartmentSlotID(); }
PrintFormat("ERR CONVOY SEAT: vehicle=%1 member=%2 actor=%3 alive=%4 conscious=%5 groupMatches=%6 duplicateActor=%7 duplicateSeat=%8",
vehicle.Index, index, actor, ERR_Actors.Alive(actor), ERR_Actors.CanFight(actor), actualGroup == vehicle.Group, duplicateActor, duplicateSeat);
PrintFormat("ERR CONVOY SEAT: intended=%1 occupant=%2 type=%3 actual=%4 actualType=%5 manager=%6 slot=%7 sameSeat=%8",
intended, occupant, intendedType, actual, actualType, actualManager, actualSlot, actual == intended);
PrintFormat("ERR CONVOY SEAT: aboard=%1 originalVehicle=%2 originalVehicleTree=%3",
aboard, vehicle.Entity, ERR_ConvoyRules.PartOf(aboard, vehicle.Entity));
AIControlComponent control;
AIAgent agent;
SCR_AIUtilityComponent utility;
if (actor) control = AIControlComponent.Cast(actor.FindComponent(AIControlComponent));
if (control) agent = control.GetControlAIAgent();
if (agent) utility = SCR_AIUtilityComponent.Cast(agent.FindComponent(SCR_AIUtilityComponent));
string behavior = "no actor utility", groupAction = "no group utility";
if (utility) behavior = MovementAction(utility.GetCurrentBehavior());
SCR_AIGroupUtilityComponent groupUtility = vehicle.Group.GetGroupUtilityComponent();
if (groupUtility) groupAction = MovementAction(groupUtility.GetCurrentAction());
PrintFormat("ERR CONVOY SEAT: actorBehavior=%1 groupAction=%2", behavior, groupAction);
}
protected bool Population(ERR_HQ hq)
{
if (!Check(m_Task.Vehicles.Count() == 6, "six original vehicles remain tracked")) return false;
@@ -191,10 +224,11 @@ class ERR_NativeConvoyProbe
{
IEntity actor = vehicle.Members[seatIndex];
BaseCompartmentSlot seat = vehicle.Seats[seatIndex];
if (!Check(actor && ERR_Actors.CanFight(actor) && !crew.Contains(actor)
bool occupied = actor && ERR_Actors.CanFight(actor) && !crew.Contains(actor)
&& ERR_Actors.Group(actor) == vehicle.Group && seat && !slots.Contains(seat) && seat.GetOccupant() == actor
&& ERR_ConvoyRules.PartOf(CompartmentAccessComponent.GetVehicleIn(actor), vehicle.Entity),
"original crew occupies intended native compartment " + crew.Count().ToString())) return false;
&& ERR_ConvoyRules.PartOf(CompartmentAccessComponent.GetVehicleIn(actor), vehicle.Entity);
if (!occupied) SeatDiagnostic(vehicle, seatIndex, actor, seat, crew.Contains(actor), slots.Contains(seat));
if (!Check(occupied, "original crew occupies intended native compartment " + crew.Count().ToString())) return false;
crew.Insert(actor); slots.Insert(seat);
bool nativeMember;
foreach (AIAgent agent : agents) if (agent && agent.GetControlledEntity() == actor) nativeMember = true;
@@ -247,6 +281,7 @@ class ERR_NativeConvoyProbe
int Tick(ERR_HQ hq, float now)
{
if (!Enabled() || !hq || !m_Mode || m_Mode != ERR_GameMode.Get() || m_Failed) return -1;
if (m_Step == 4) return m_Cover.Tick(hq, now);
if (m_Deadline == 0) m_Deadline = now + 480000;
if (now >= m_Deadline) { Check(false, "native fixture deadline"); return -1; }
if (m_Step == 0)
@@ -340,7 +375,13 @@ class ERR_NativeConvoyProbe
&& m_Mode.Forces().Count() == m_InitialLedger + 6 && m_Task.Cargo.Count() == 56,
"later repeated dispatch preserves exact task, force and cargo counts")) return -1;
Check(true, "all six native vehicles drove at least 20m and leader at least 100m without fixture movement");
if (ERR_NativeConvoyCoverProbe.Enabled())
{
m_Cover = new ERR_NativeConvoyCoverProbe(m_Mode); m_Step = 4;
return 0;
}
return 1;
}
void Stop() { if (m_Cover) m_Cover.Stop(); }
}
#endif
@@ -78,6 +78,7 @@ modded class ERR_GameMode
m_ERRTestPlayerDeath = outcome == "player-death" || m_ERRTestRadioNetwork || m_ERRTestHQResponse || m_ERRTestMortar || m_ERRTestHQMemory || m_ERRTestHQBody || m_ERRTestConvoy;
m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 150000;
if (m_ERRTestConvoy) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 540000;
if (ERR_NativeConvoyCoverProbe.Enabled()) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 840000;
if (m_ERRTestHQMemory || m_ERRTestHQBody) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 240000;
if (m_ERRTestAircraftControl || m_ERRTestAircraftRoute || m_ERRTestAircraftField) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 330000;
if (m_ERRTestMortarCourier) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 450000;
@@ -169,6 +170,7 @@ modded class ERR_GameMode
if (m_ERRAircraftRoute) m_ERRAircraftRoute.Stop();
if (m_ERRAircraftField) m_ERRAircraftField.Stop();
if (m_ERRHQResponseProof) m_ERRHQResponseProof.Stop();
if (m_ERRConvoyProbe) m_ERRConvoyProbe.Stop();
if (m_ERRMortarSalvo) m_ERRMortarSalvo.Stop();
if (m_ERRMortarCourier) m_ERRMortarCourier.Stop();
if (m_ERRMortarTransfer) m_ERRMortarTransfer.Stop();