NEO-93: Fix delta cap LastAdvancedUtc to preserve gradual catch-up.
When simulation is capped, advance LastAdvancedUtc to windowEnd instead of nowUtc so subsequent polls do not burst through missed NPC cycles. Co-authored-by: Cursor <cursoragent@cursor.com>pull/131/head
parent
4fcbb99881
commit
056b0e77f0
|
|
@ -61,7 +61,7 @@
|
||||||
- Holder-only idle→aggro sync from **`IThreatStateStore`**; no proximity auto-aggro.
|
- Holder-only idle→aggro sync from **`IThreatStateStore`**; no proximity auto-aggro.
|
||||||
- **`attack_execute`** chains instantly to **`recover`** within the same advance step (no player damage — NEO-95).
|
- **`attack_execute`** chains instantly to **`recover`** within the same advance step (no player damage — NEO-95).
|
||||||
- Dev **`combat-targets-fixture`** resets runtime rows alongside HP + threat.
|
- Dev **`combat-targets-fixture`** resets runtime rows alongside HP + threat.
|
||||||
- **22** NEO-93-focused tests green (`NpcRuntimeOperationsTests`, `InMemoryNpcRuntimeStateStoreTests`, fixture extension).
|
- **23** NEO-93-focused tests green (`NpcRuntimeOperationsTests`, `InMemoryNpcRuntimeStateStoreTests`, fixture extension).
|
||||||
|
|
||||||
## Technical approach
|
## Technical approach
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -239,5 +239,23 @@ public sealed class NpcRuntimeOperationsTests
|
||||||
runtime.TryGet(PrototypeNpcRegistry.PrototypeNpcMeleeId, out var snapshot);
|
runtime.TryGet(PrototypeNpcRegistry.PrototypeNpcMeleeId, out var snapshot);
|
||||||
Assert.Equal(NpcBehaviorState.Recover, snapshot.BehaviorState);
|
Assert.Equal(NpcBehaviorState.Recover, snapshot.BehaviorState);
|
||||||
Assert.Equal(T0.AddSeconds(4.5), snapshot.PhaseStartedUtc);
|
Assert.Equal(T0.AddSeconds(4.5), snapshot.PhaseStartedUtc);
|
||||||
|
Assert.Equal(T0.AddSeconds(5), runtime.LastAdvancedUtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AdvanceAll_ShouldPreserveGradualCatchUp_AfterLongGapWithDeltaCap()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var (runtime, threat, behavior) = CreateFixture();
|
||||||
|
SetHolder(threat, PrototypeNpcRegistry.PrototypeNpcMeleeId);
|
||||||
|
Advance(T0, runtime, threat, behavior);
|
||||||
|
Advance(T0.AddSeconds(100), runtime, threat, behavior, maxDeltaSeconds: 5);
|
||||||
|
// Act
|
||||||
|
Advance(T0.AddSeconds(100.5), runtime, threat, behavior, maxDeltaSeconds: 5);
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(T0.AddSeconds(10), runtime.LastAdvancedUtc);
|
||||||
|
runtime.TryGet(PrototypeNpcRegistry.PrototypeNpcMeleeId, out var snapshot);
|
||||||
|
Assert.Equal(NpcBehaviorState.Recover, snapshot.BehaviorState);
|
||||||
|
Assert.Equal(T0.AddSeconds(9), snapshot.PhaseStartedUtc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ public static class NpcRuntimeOperations
|
||||||
behaviorRegistry);
|
behaviorRegistry);
|
||||||
}
|
}
|
||||||
|
|
||||||
runtimeStore.LastAdvancedUtc = nowUtc;
|
runtimeStore.LastAdvancedUtc = windowEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Resets all prototype NPC runtime rows to idle (dev fixture).</summary>
|
/// <summary>Resets all prototype NPC runtime rows to idle (dev fixture).</summary>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue