Fuse fixes: arming holds for every burst, no-lock rounds stop on the first hull, settle before user code
Operator ruling 2026-09-30: a no-lock round of any fuse stops at the first hull on its aim line and detonates there (bomb fishing still bursts at max range on a clear line). CommitBurst no longer special-cases Contact. Soul's findings on 14f66634..7e620ff9: - Arming (HIGH): a contact or delayed blast on a hull nearer the muzzle than the blast radius detonated at the hull. Armed is now the one owner of the arming rule; Solve plans its burst point through it and ApplyBlastHit pushes the hull point through it. - A refused beam never starts (ConstantWeapon.Activate asks Refuses), so OnStartFiring no longer flashes visuals and audio for a beam that fires nothing. - Step removes a shot from the queue before Apply runs damage observers, so a throwing observer cannot make the blast repeat every tick. - AgentFires consults Solve for a fused weapon: a refused weapon is never fired and Combat's group pick no longer counts its damage. - SingleAmmoBurst pays at its first unrefused round in Execute, judged with the Range that round flies with, instead of at the trigger on the previous tick's. - Inspect reads Designated from Solve (FireSolution.Designated) instead of recomputing visible, in-range and locked; FireControlDiagnostic drops those three fields and the debug HUD shows the one. Combat's group range test is FireControl.InReach, the range half of Designated (a LockWeapon must be activated to acquire its lock, so Combat cannot ask Designated itself). Tests pin each rule, plus the two surviving gaps: a pushed-out targeted round's arrival at the arming distance, and the AgentMinHitProbability boundary. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
63a2fcdaa4
commit
57c2560fc0
8 changed files with 325 additions and 69 deletions
|
|
@ -194,7 +194,9 @@ public class ConstantWeapon : Weapon, IProgressBehavior, IEventBehavior, IPowerC
|
|||
|
||||
public override void Activate()
|
||||
{
|
||||
if(!_firing && !_reloading)
|
||||
// A refused beam never starts (operator ruling 2026-09-30): OnStartFiring drives the beam's visuals and
|
||||
// audio, so starting it only for Execute to stop it a tick later would flash a beam that fires nothing.
|
||||
if(!_firing && !_reloading && !FireControl.Refuses(this, Entity))
|
||||
{
|
||||
_firing = true;
|
||||
OnStartFiring?.Invoke();
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior, IPowerCo
|
|||
protected readonly InputCapacitor _capacitor = new InputCapacitor();
|
||||
|
||||
protected int _burstRemaining;
|
||||
private bool _burstPaid;
|
||||
private float _burstTimer;
|
||||
private float _burstInterval;
|
||||
protected float _cooldown; // Normalized
|
||||
|
|
@ -107,10 +108,10 @@ public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior, IPowerCo
|
|||
// whose first round FireControl would refuse.
|
||||
if (FireControl.Refuses(this, Entity)) return;
|
||||
|
||||
// If 1 ammo is consumed per burst, perform ammo and energy consumption here
|
||||
// UseAmmo returns false when triggering reload; cancel firing if that is the case
|
||||
if(_data.SingleAmmoBurst && (!TrySpendActivationEnergy() || !UseAmmo())) return;
|
||||
|
||||
// A burst that pays once (SingleAmmoBurst) pays at its first round that is not refused, in Execute, judged
|
||||
// with the Range that round flies with: paying here would judge with the Range of the previous tick, and a
|
||||
// Range that fell in between would spend the ammo on rounds Fire then refuses.
|
||||
_burstPaid = false;
|
||||
_burstRemaining = (int) BurstCount;
|
||||
_burstInterval = BurstTime / _burstRemaining;
|
||||
_burstTimer = 0;
|
||||
|
|
@ -234,13 +235,14 @@ public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior, IPowerCo
|
|||
// spent (operator ruling 2026-09-30): it costs no ammo, energy, sound, heat, wear or visibility.
|
||||
// The decision is FireControl's; Fire makes the same one.
|
||||
var refused = FireControl.Refuses(this, Entity);
|
||||
// If multiple ammo is consumed per burst, perform ammo and energy consumption here
|
||||
// UseAmmo returns false when triggering reload; cancel firing if that is the case
|
||||
if (!refused && !_data.SingleAmmoBurst && (!TrySpendActivationEnergy() || !UseAmmo()))
|
||||
// Ammo and energy are consumed here, per round, or once per burst at its first unrefused round
|
||||
// (SingleAmmoBurst). UseAmmo returns false when triggering reload; cancel firing if that is the case
|
||||
if (!refused && !_burstPaid && (!TrySpendActivationEnergy() || !UseAmmo()))
|
||||
{
|
||||
_burstRemaining = 0;
|
||||
return false;
|
||||
}
|
||||
if (!refused) _burstPaid = _data.SingleAmmoBurst;
|
||||
|
||||
_burstRemaining--;
|
||||
_burstTimer -= _burstInterval;
|
||||
|
|
|
|||
Loading…
Reference in a new issue