fix(runtime): align portal and movement presentation
Port retail portal viewport projection and reveal behavior, preserve outbound combat style, drive remote and local grounded movement from authored CSequence root frames, and reuse the local prepared pose so animation hooks advance once. User-verified portal, observer movement, combat stance, and short-tap locomotion gates. Release build passed with 5,767 tests and five intentional skips. Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
e95f55f25b
commit
124e046976
30 changed files with 1362 additions and 348 deletions
|
|
@ -53,6 +53,7 @@ public sealed class TeleportAnimSequencer
|
|||
public const int TunnelEndFrame = 120;
|
||||
public const float ExitWindowLow = FadeTime + 0.1f;
|
||||
public const float ExitWindowHigh = FadeTime + 0.3f;
|
||||
private const short LastVisibleOutgoingAnimationLevel = 1022;
|
||||
|
||||
// UIGlobals::Init @ 0x004EE470. Retail integrates 100 integer sine
|
||||
// samples into a 0..1024 easing table.
|
||||
|
|
@ -119,7 +120,7 @@ public sealed class TeleportAnimSequencer
|
|||
switch (_state)
|
||||
{
|
||||
case TeleportAnimState.WorldFadeOut:
|
||||
if (_elapsed >= FadeTime)
|
||||
if (OutgoingViewportReachedTerminalProjection())
|
||||
// UseTime's viewport-visibility block precedes this state
|
||||
// transition, so retail shows portal space on the next tick.
|
||||
Advance(TeleportAnimState.TunnelFadeIn, enterTunnel: true);
|
||||
|
|
@ -157,7 +158,7 @@ public sealed class TeleportAnimSequencer
|
|||
break;
|
||||
|
||||
case TeleportAnimState.TunnelFadeOut:
|
||||
if (_elapsed >= FadeTime)
|
||||
if (OutgoingViewportReachedTerminalProjection())
|
||||
{
|
||||
Advance(TeleportAnimState.WorldFadeIn, enterTunnel: false);
|
||||
evts.Add(TeleportAnimEvent.PlayExitSound);
|
||||
|
|
@ -180,6 +181,17 @@ public sealed class TeleportAnimSequencer
|
|||
return (BuildSnapshot(), evts);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retire an outgoing viewport before the first quantized projection that
|
||||
/// exposes the finite tunnel boundary. Retail's whole-frame black clear and
|
||||
/// frame-paced D3D presentation show level 1022 as the last tunnel sample;
|
||||
/// paired captures show no 1023/1024 portal frame before the world swap.
|
||||
/// An uncapped modern loop can otherwise publish those sub-20 ms samples
|
||||
/// and let the desktop compositor hold one for a complete display refresh.
|
||||
/// </summary>
|
||||
private bool OutgoingViewportReachedTerminalProjection()
|
||||
=> GetRetailAnimationLevel(_elapsed / FadeTime) > LastVisibleOutgoingAnimationLevel;
|
||||
|
||||
private void Advance(TeleportAnimState next, bool enterTunnel)
|
||||
{
|
||||
_state = next;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue