Integrate finite infantry resupply with delivered low-ammunition reports

This commit is contained in:
2026-09-20 07:32:24 +02:00
parent 915476f709
commit 782c163c68
44 changed files with 5690 additions and 31 deletions
+29 -6
View File
@@ -17,6 +17,7 @@ class ERR_HQUnit
ref ERR_HQSearchReport PendingSweep;
ref ERR_HQStatusReport PendingStatus;
ref ERR_HQStatusSampler StatusSampler = new ERR_HQStatusSampler();
ref ERR_HQAmmoReporting AmmoReporting = new ERR_HQAmmoReporting();
string ForceSourceId;
float NextStatus;
bool PendingCheckin;
@@ -96,6 +97,7 @@ class ERR_HQ : ERR_CommandService
protected ref ERR_HQBodyObserver m_Bodies = new ERR_HQBodyObserver();
protected ref ERR_HQWatch m_Watch = new ERR_HQWatch();
protected ref ERR_MortarLogistics m_Logistics;
protected ref ERR_InfantryResupply m_Resupply;
protected ref array<ref ERR_HQUnit> m_Units = {};
protected ref array<ref ERR_HQReport> m_Contacts = {};
protected ref ERR_HQMemory m_Memory = new ERR_HQMemory();
@@ -109,7 +111,7 @@ class ERR_HQ : ERR_CommandService
protected float m_NextNetwork;
protected float m_NextAssignment;
void ERR_HQ(ERR_GameMode mode) { m_Mode = mode; m_Equipment = new ERR_EnemyEquipment(mode); m_ConvoyPool = new ERR_ConvoyPool(mode, 1); m_Convoys = new ERR_ConvoyService(mode, m_ConvoyPool); m_Mortars = new ERR_MortarSystem(this); m_Logistics = new ERR_MortarLogistics(this, mode); }
void ERR_HQ(ERR_GameMode mode) { m_Mode = mode; m_Equipment = new ERR_EnemyEquipment(mode); m_ConvoyPool = new ERR_ConvoyPool(mode, 1); m_Convoys = new ERR_ConvoyService(mode, m_ConvoyPool); m_Mortars = new ERR_MortarSystem(this); m_Logistics = new ERR_MortarLogistics(this, mode); m_Resupply = new ERR_InfantryResupply(this, mode); }
static ERR_HQ Get()
{
ERR_GameMode mode = ERR_GameMode.Get();
@@ -283,12 +285,14 @@ class ERR_HQ : ERR_CommandService
if (ERR_MortarPrediction.Fresh(contact, now)) contacts.Insert(contact.Snapshot());
}
ERR_HQWatch Watch() { return m_Watch; }
ERR_InfantryResupply Resupply() { return m_Resupply; }
ERR_HQMemory Memory() { return m_Memory; }
ERR_HQCoverage Coverage() { return m_Coverage; }
ERR_HQJournal Journal() { return m_Journal; }
string Status()
{
return string.Format("HQ: %1 groups, %2 delivered contacts, %3 assignments", m_Units.Count(), m_Contacts.Count(), Assigned()) + string.Format("; %1 remembered tracks, %2 swept cells", m_Memory.Count(), m_Coverage.Count()) + "; " + m_Mode.Forces().Status() + "; " + m_Mortars.Status() + "; " + m_Logistics.Status();
return string.Format("HQ: %1 groups, %2 delivered contacts, %3 assignments", m_Units.Count(), m_Contacts.Count(), Assigned()) + string.Format("; %1 remembered tracks, %2 swept cells", m_Memory.Count(), m_Coverage.Count()) + "; " + m_Mode.Forces().Status() + "; " + m_Mortars.Status() + "; " + m_Logistics.Status() + "; " + m_Resupply.Status();
}
protected void BindPhysical(ERR_HQUnit unit)
@@ -325,6 +329,7 @@ class ERR_HQ : ERR_CommandService
m_Equipment.RegisterGroup(group, unit.Id, !m_Mortars || !m_Mortars.FindGroup(group));
BindPhysical(unit);
unit.NextStatus = GetGame().GetWorld().GetWorldTime() + 10000 + phase * 1000;
unit.AmmoReporting.Initialize(unit.Id, GetGame().GetWorld().GetWorldTime());
m_Journal.Write("REGISTER", string.Format("group %1", unit.Id));
}
@@ -424,17 +429,22 @@ class ERR_HQ : ERR_CommandService
protected void StatusReport(ERR_HQUnit unit, float now)
{
unit.StatusSampler.ObserveDeaths();
if (unit.Uplink || !unit.Radio || now < unit.NextStatus) return;
if (unit.Uplink || !unit.Radio) return;
bool routine = now >= unit.NextStatus;
if (!routine && !unit.AmmoReporting.ScanDue(now)) return;
unit.AmmoReporting.Scanned(now);
ERR_HQRoute route = m_Network.Route(unit.Radio);
if (!route) return;
// A local sample reserves an identifier; a healthy early sample creates no frame.
ERR_HQStatusReport report = unit.StatusSampler.Sample(now, m_Journal.Message(), unit.Radio);
if (!report) return;
if (!report || (!routine && !unit.AmmoReporting.Urgent(report, now))) return;
route.MessageId = report.MessageId;
route.Payload = string.Format("status %1: %2 living, %3 fit, %4 confirmed losses; sampled=%5", report.SourceId, report.Count, report.Fit, report.ConfirmedLosses, report.ObservedAt);
string ammunition = "unknown";
if (report.AmmoState && report.AmmoState.Complete) ammunition = string.Format("%1 magazine rounds, %2 chambered", report.AmmoState.SmallArmsRounds, report.AmmoState.SmallArmsChambers);
route.Payload += "; small-arms ammunition=" + ammunition;
unit.PendingStatus = report; unit.Uplink = route; unit.NextStatus = now + 180000;
unit.AmmoReporting.Queued(now);
m_Journal.Write("STATUS REPORT", route.Payload, route.MessageId);
}
// Due routine status and requested check-ins get the next free uplink.
@@ -784,12 +794,23 @@ class ERR_HQ : ERR_CommandService
}
return best;
}
protected void PlanResupply(float now)
{
if (!m_Resupply || m_Resupply.State() != 1 || !m_ConvoyTask || m_ConvoyTask.Stopped
|| !m_ConvoyTask.Ready || m_ConvoyTask.Vehicles.Count() != 6) return;
ERR_HQUnit donor;
foreach (ERR_HQUnit unit : m_Units) if (unit.Group == m_ConvoyTask.Vehicles[1].Group) donor = unit;
if (!donor || ConvoyContact(donor, now)) return;
ERR_HQWatchEntry donorStatus = m_Watch.Find(donor.ForceSourceId);
foreach (ERR_HQUnit recipient : m_Units)
if (m_Resupply.TryPlan(recipient, donor, m_Watch.Find(recipient.ForceSourceId), donorStatus, now)) return;
}
protected void PlanConvoy(float now)
{
if (!m_ConvoyTask || m_ConvoyTask.Stopped || !m_ConvoyTask.Ready) return;
foreach (ERR_ConvoyVehicle vehicle : m_ConvoyTask.Vehicles)
{
if (vehicle.Released || vehicle.Arrived || !vehicle.Registered || !vehicle.Group) continue;
if (vehicle.Released || vehicle.Arrived || vehicle.SupplyToken > 0 || !vehicle.Registered || !vehicle.Group) continue;
foreach (ERR_HQUnit unit : m_Units)
{
if (unit.Group != vehicle.Group || !unit.ReservedForSupport || unit.Downlink || !unit.Radio) continue;
@@ -992,7 +1013,8 @@ class ERR_HQ : ERR_CommandService
if (!unit.Group && !unit.Uplink) { ReleaseUnit(unit, now); m_Units.Remove(i); continue; }
QueueReports(unit, now);
}
if (now >= m_NextAssignment) { PlanConvoy(now); Assign(now); m_NextAssignment = now + 5000; }
if (now >= m_NextAssignment) { PlanConvoy(now); PlanResupply(now); Assign(now); m_NextAssignment = now + 5000; }
m_Resupply.Tick(now);
m_Logistics.Tick(now);
m_Mortars.Tick(now);
m_Journal.Flush();
@@ -1000,6 +1022,7 @@ class ERR_HQ : ERR_CommandService
override void Stop()
{
m_Resupply.Stop();
m_Convoys.Stop();
m_Equipment.Stop();
m_Logistics.Stop();