Deliver local sighting handoffs and preserve unsubmitted resupply attempts

This commit is contained in:
2026-09-20 10:18:18 +02:00
parent d8ec0de765
commit 81c0f060fd
48 changed files with 6994 additions and 30 deletions
+37 -4
View File
@@ -8,6 +8,7 @@ class ERR_HQUnit
ref ERR_HQRoute Uplink;
ref ERR_HQReport PendingReport;
ref ERR_HQReportSelection ReportSelection = new ERR_HQReportSelection();
ref ERR_HQObservationHistory SentObservations = new ERR_HQObservationHistory();
ref ERR_HQRoute Downlink;
ref ERR_HQReport PendingOrder;
ref ERR_HQReport Assignment;
@@ -248,7 +249,7 @@ class ERR_HQ : ERR_CommandService
if (!Replication.IsServer() || !MissionActive() || !battery || !battery.StartupActivated || !battery.Operational() || !m_Logistics.CanSample(battery) || !ERR_MortarLogisticsRules.Need(battery.CountShells())) return false;
foreach (ERR_HQUnit unit : m_Units)
{
if (unit.Group != battery.Group || unit.Uplink || !unit.Radio || unit.Radio != battery.RadioOperator) continue;
if (unit.Group != battery.Group || unit.Uplink || !unit.Radio || unit.Radio != battery.RadioOperator || OriginOccupied(unit.Radio, unit)) continue;
ERR_HQRoute route = m_Network.Route(unit.Radio);
if (!route) return false;
ERR_MortarSupplyStatus report = new ERR_MortarSupplyStatus();
@@ -410,16 +411,45 @@ class ERR_HQ : ERR_CommandService
m_Network.Build();
}
protected bool OriginOccupied(IEntity caller, ERR_HQUnit owner)
{
if (!caller) return false;
foreach (ERR_HQUnit other : m_Units)
{
if (other == owner || !other.Uplink || other.Uplink.Failed || other.Uplink.Originated || other.Uplink.Nodes.IsEmpty()) continue;
if (other.Uplink.Nodes[0].Carrier == caller) return true;
}
return false;
}
protected ERR_HQRoute ObservationRoute(ERR_HQUnit unit)
{
ERR_HQRoute own;
if (unit.Radio && !OriginOccupied(unit.Radio, unit)) own = m_Network.Route(unit.Radio);
if (own && !own.Nodes.IsEmpty() && own.Nodes[0].Valid(own.Nodes.Count() == 1)) return own;
array<IEntity> busy = {};
foreach (ERR_HQUnit other : m_Units)
{
if (!other.Uplink || other.Uplink.Failed) continue;
if (other.Radio && !busy.Contains(other.Radio)) busy.Insert(other.Radio);
if (!other.Uplink.Originated && !other.Uplink.Nodes.IsEmpty())
{
IEntity caller = other.Uplink.Nodes[0].Carrier;
if (caller && !busy.Contains(caller)) busy.Insert(caller);
}
}
return m_Network.LocalRoute(unit.Group, unit.StatusSampler, busy);
}
protected void Observe(ERR_HQUnit unit, float now)
{
if (!unit.Utility || !unit.Radio || unit.Uplink || now < unit.NextReport) return;
if (!unit.Utility || unit.Uplink || now < unit.NextReport) return;
unit.NextReport = now + m_Mode.Settings().Get("reportIntervalSeconds") * 1000;
array<ref ERR_HQVisualContact> samples = {};
ERR_HQObservation.Gather(unit.Utility, now, samples);
if (samples.IsEmpty()) return;
ERR_HQVisualContact seen = unit.ReportSelection.Select(samples);
if (!seen) return;
ERR_HQRoute route = m_Network.Route(unit.Radio);
if (!seen || !unit.SentObservations.CanQueue(seen.Entity, seen.ObservedAt, now)) return;
ERR_HQRoute route = ObservationRoute(unit);
if (!route) return;
ERR_HQReport report = new ERR_HQReport();
report.MessageId = m_Journal.Message();
@@ -433,6 +463,8 @@ class ERR_HQ : ERR_CommandService
unit.PendingReport = report;
unit.Uplink = route;
unit.ReportSelection.Queued(seen.Entity);
unit.SentObservations.Queued(seen.Entity, seen.ObservedAt, now);
if (route.LocalSource) m_Journal.Write("LOCAL HANDOFF", "original squad sighting queued for nearby physical radio caller; three-second origin hold required", report.MessageId);
m_Journal.Write("REPORT", route.Payload, report.MessageId);
}
@@ -474,6 +506,7 @@ class ERR_HQ : ERR_CommandService
// Positive observations precede a negative search report.
protected void QueueReports(ERR_HQUnit unit, float now)
{
if (OriginOccupied(unit.Radio, unit)) { if (unit.Task) unit.Task.ArrivedAt = -1; return; }
StatusReport(unit, now);
Observe(unit, now);
ObserveBody(unit, now);