Validate independent packed addons and complete physical mortar salvos

This commit is contained in:
2026-09-19 11:42:13 +02:00
parent 7c53b4bb81
commit dfd7cc49e2
532 changed files with 63902 additions and 96 deletions
+34 -3
View File
@@ -36,6 +36,7 @@ modded class SCR_AIGetArtilleryAimDistanceCompensation
if (!battery)
return super.EOnTaskSimulate(owner, dt);
battery.AimedAt = -1;
battery.AimValidatedAt = -1;
battery.AimSolver = null;
battery.AimSolution = null;
float now = GetGame().GetWorld().GetWorldTime();
@@ -54,6 +55,7 @@ modded class SCR_AIGetArtilleryAimDistanceCompensation
battery.AimSolution = solution;
battery.AimSolver = this; // weak: do not retain a destroyed native behavior tree
battery.AimedAt = now;
battery.AimValidatedAt = now;
battery.LastFailure = "";
battery.Trace("AIM SOLUTION", "ready", string.Format("predicted impact=%1 flight=%2s charge index=%3 aim target=%4 latest source=M%5", solution.Impact, solution.FlightTime, solution.Charge, solution.AimTarget, report.MessageId));
SetVariableOut(PORT_AIM_POS, solution.AimTarget);
@@ -79,11 +81,39 @@ modded class SCR_AIGetArtilleryAimDistanceCompensation
return system.Withhold(battery, "new ballistic solution requires native re-aim", string.Format("gun drift=%1m impact drift=%2m aim drift=%3m charge=%4/%5 flight=%6/%7s", vector.Distance(commanded.GunOrigin, updated.GunOrigin), vector.Distance(commanded.Impact, updated.Impact), vector.Distance(commanded.AimTarget, updated.AimTarget), commanded.Charge, updated.Charge, commanded.FlightTime, updated.FlightTime));
// Keep the ORIGINAL command/impact/flight. Comparing successive refreshed
// solutions would allow a moving target to drift away in small increments.
battery.AimedAt = now;
battery.AimValidatedAt = now;
battery.Trace("AIM REVALIDATED", "same native command", string.Format("fresh ballistic solve matched original; source=M%1 observed age=%2s", report.MessageId, (now - report.ObservedAt) / 1000));
return true;
}
// The report may change only after a real HQ downlink. Re-solve against the
// ORIGINAL geometry; never replace the commanded solution with an
// approximately equivalent successor (which would permit tolerance creep).
bool ERR_AdoptReport(ERR_MortarBattery battery, ERR_MortarSystem system, ERR_HQReport report, float now)
{
IEntity gun;
ResourceName ammo;
GetVariableIn(PORT_ARTILLERY_ENTITY, gun);
GetVariableIn(PORT_AMMO_PREFAB, ammo);
ERR_MortarAimSolution commanded = battery.AimSolution;
if (battery.Released || battery.RefreshRejected || !battery.CommandOpen || !battery.Refresh || !battery.Refresh.DeliveredFor(battery, report))
return system.Withhold(battery, "target update lacks completed delivery for this uncommitted order");
if (battery.AimSolver != this || !commanded || !commanded.Matches(battery, battery.Report) || gun != battery.Gun || ammo != ERR_MortarBattery.SHELL)
return system.Withhold(battery, "target update lost its original native aim owner");
if (battery.AimedAt < 0 || now < battery.AimedAt) return system.Withhold(battery, "original native aim timestamp invalid");
if (!ERR_MortarRefreshRules.Newer(battery.Report, report, now)) return system.Withhold(battery, "target update is not a newer fresh same-target observation");
ERR_MortarAimSolution updated = ERR_Solve(battery, system, report, now);
if (!updated) return false;
if (!ERR_MortarAimRules.Equivalent(commanded.Charge, updated.Charge, commanded.GunOrigin, updated.GunOrigin, commanded.Impact, updated.Impact, commanded.AimTarget, updated.AimTarget, commanded.FlightTime, updated.FlightTime))
return system.Withhold(battery, "target update requires a different native aim command");
// Synchronous adoption changes accepted observation identity together.
// Original command time/geometry, order deadline and shot count survive.
commanded.Report = report;
battery.Report = report;
battery.AimValidatedAt = now;
return true;
}
protected ERR_MortarAimSolution ERR_Solve(ERR_MortarBattery battery, ERR_MortarSystem system, ERR_HQReport report, float now)
{
IEntity gun = battery.Gun;
@@ -257,12 +287,13 @@ modded class SCR_AIStaticArtilleryBehavior_ShootingLogic
// so repeated pending ticks cannot count the same projectile twice.
if (battery.OrderShots < ERR_MortarSalvo.ROUNDS)
{
ERR_MortarSupplyState supply = battery.SupplyState(GetGame().GetWorld().GetWorldTime());
float now = GetGame().GetWorld().GetWorldTime();
ERR_MortarSupplyState supply = battery.SupplyState(now);
if (supply == ERR_MortarSupplyState.PENDING) return ENodeResult.RUNNING;
if (supply == ERR_MortarSupplyState.FAILED)
{
ERR_MortarSystem system = ERR_MortarSystem.Get();
if (system) system.Withhold(battery, "next native load lacks confirmed physical gunner ammunition");
if (system) system.Withhold(battery, system.SupplyFailure(battery, now));
return ENodeResult.FAIL;
}
}