Advance standalone admission, finite artillery and native validation

This commit is contained in:
2026-09-19 09:02:31 +02:00
parent af5146a317
commit 40a474934c
532 changed files with 56456 additions and 199 deletions
+44 -14
View File
@@ -36,12 +36,14 @@ class ERR_MortarSystem
if (!gun || !group)
{
ERR_Actors.DeleteSpawned(gun);
ERR_MortarReadiness.RetireGroup(group);
ERR_Actors.DeleteSpawned(group);
return false;
}
if (group.GetFaction() != ERR_GameMode.Get().EnemyFaction())
{
ERR_Actors.DeleteSpawned(gun);
ERR_MortarReadiness.RetireGroup(group);
ERR_Actors.DeleteSpawned(group);
return false;
}
@@ -125,13 +127,19 @@ class ERR_MortarSystem
bool AllowShot(ERR_MortarBattery battery)
{
float now = GetGame().GetWorld().GetWorldTime();
if (!ERR_HQ.MissionActive()) return Withhold(battery, "mission inactive");
if (m_Stopped || !ERR_HQ.MissionActive()) return Withhold(battery, "mission inactive or HQ stopped");
if (!battery.Operational()) return Withhold(battery, battery.OperationalReason());
if (!battery.CommandOpen || battery.OrderShots >= ERR_MortarSalvo.ROUNDS) return Withhold(battery, "salvo complete or order closed");
if (battery.Released) return Withhold(battery, "waiting for committed projectile");
if (battery.AimedShot != battery.OrderShots || battery.AimedAt < 0 || now - battery.AimedAt > 10000) return Withhold(battery, "fresh aim solution required");
if (battery.AimedShot != battery.OrderShots || battery.AimedAt < 0 || now < battery.AimedAt) return Withhold(battery, "fresh aim solution required");
ERR_HQReport report = Latest(battery, now);
if (!report) return Withhold(battery, ContactFailure(battery));
if (!battery.AimSolution || !battery.AimSolution.Matches(battery, report)) return Withhold(battery, "aim command does not match delivered order");
if (now - battery.AimedAt > 10000)
{
if (!battery.AimSolver) return Withhold(battery, "original native aim solver no longer available");
if (!battery.AimSolver.ERR_RevalidateAim(battery, this, report, now)) return false;
}
vector updated;
if (!ERR_MortarPrediction.Predict(report, now, battery.FlightTime, updated)) return Withhold(battery, ERR_MortarPrediction.FailureReason);
updated += battery.AimOffset;
@@ -142,20 +150,41 @@ class ERR_MortarSystem
}
protected void AdvanceOrder(ERR_MortarBattery battery, float now)
{
if (!battery.RadioOrder) return;
int state = battery.RadioOrder.Advance(now, m_HQ.Journal());
if (state == 0) return;
ERR_HQReport delivered = battery.PendingRadioReport;
battery.RadioOrder = null;
battery.PendingRadioReport = null;
if (state < 0 || !ERR_MortarPrediction.Fresh(delivered, now) || !battery.Operational() || battery.Activity || !battery.SupplyGunner())
if (battery.RadioOrder)
{
battery.Cancel("radio delivery, report freshness or gunner availability failed");
int deliveredState = battery.RadioOrder.Advance(now, m_HQ.Journal());
if (deliveredState == 0) return;
ERR_HQReport delivered = battery.PendingRadioReport;
battery.RadioOrder = null;
battery.PendingRadioReport = null;
if (deliveredState < 0 || !ERR_MortarPrediction.Fresh(delivered, now) || !battery.Operational() || battery.Activity || !battery.CommandOpen)
{
battery.Cancel("radio delivery, report freshness or battery availability failed");
battery.NextOrder = now + 10000;
return;
}
battery.PendingSupplyReport = delivered;
}
if (!battery.PendingSupplyReport) return;
if (!battery.CommandOpen || !ERR_MortarPrediction.Fresh(battery.PendingSupplyReport, now) || !battery.Operational() || battery.Activity)
{
battery.Cancel("delivered order expired or became unavailable while awaiting physical ammunition");
battery.NextOrder = now + 10000;
return;
}
battery.Order(delivered, now);
ERR_MortarSupplyState supply = battery.SupplyState(now);
if (supply == ERR_MortarSupplyState.PENDING) return;
if (supply == ERR_MortarSupplyState.FAILED)
{
battery.Cancel("physical gunner ammunition unavailable or transfer failed");
battery.NextOrder = now + 10000;
return;
}
ERR_HQReport ready = battery.PendingSupplyReport;
battery.PendingSupplyReport = null;
battery.Order(ready, now);
}
void Tick(float now)
{
if (m_Stopped || !Replication.IsServer()) return;
@@ -179,9 +208,10 @@ class ERR_MortarSystem
float distance = float.MAX;
foreach (ERR_MortarBattery battery : m_Batteries)
{
if (!battery.StartupActivated || !battery.Operational() || battery.Activity || battery.RadioOrder || now < battery.NextOrder || battery.CountShells() == 0) continue;
if (!battery.StartupActivated || !battery.Operational() || battery.Activity || battery.RadioOrder || battery.PendingSupplyReport || battery.SupplyPending() || now < battery.NextOrder || battery.CountShells() == 0) continue;
foreach (ERR_HQReport report : reports)
{
if (!battery.CanRequest(report, now)) continue;
float candidate = vector.DistanceXZ(battery.Position, report.Position);
if (candidate < 350 || candidate > 4000 || candidate >= distance || !OutsideSettlements(report.Position)) continue;
selected = battery;
@@ -192,7 +222,7 @@ class ERR_MortarSystem
if (!selected || !target) return;
ERR_HQRoute route = m_HQ.Downlink(selected.Group, "MORTAR ORDER", target.Description(now), target.MessageId);
if (!route) return;
selected.BeginRequest(target, now);
if (!selected.BeginRequest(target, now)) return;
selected.RadioId = route.MessageId;
selected.RadioOrder = route;
selected.PendingRadioReport = target.Snapshot();
@@ -216,6 +246,6 @@ class ERR_MortarSystem
void Stop()
{
m_Stopped = true;
foreach (ERR_MortarBattery battery : m_Batteries) battery.Cancel("HQ stopped");
foreach (ERR_MortarBattery battery : m_Batteries) battery.Stop();
}
}