fix(world): match retail portal passage and exit warp

This commit is contained in:
Erik 2026-07-15 22:14:21 +02:00
parent eab23cbdd1
commit 842bd89c16
11 changed files with 355 additions and 28 deletions

View file

@ -6922,6 +6922,7 @@ public sealed class GameWindow : IDisposable
// fires Place (materialize) and FireLoginComplete (regain control + ack the server).
// Replaces the old TeleportArrivalController hold/place machine.
private readonly AcDream.Core.World.TeleportAnimSequencer _teleportAnim = new();
private readonly TeleportViewPlaneController _teleportViewPlane = new();
private bool _teleportInProgress;
private System.Numerics.Vector3 _pendingTeleportPos;
private uint _pendingTeleportCell;
@ -7022,11 +7023,12 @@ public sealed class GameWindow : IDisposable
_playerController.Yaw = AcQuaternionToYaw(_pendingTeleportRot);
_chaseCamera?.Update(snappedPos, _playerController.Yaw);
_retailChaseCamera?.Update(snappedPos, _playerController.Yaw,
playerVelocity: System.Numerics.Vector3.Zero,
isOnGround: true,
contactPlaneNormal: System.Numerics.Vector3.UnitZ,
dt: 1f / 60f);
// SmartBox::PlayerPositionUpdated (0x00453870) calls
// set_viewer(player_pos, reset_sought=1): the viewer and sought
// position both restart at the player, then the ordinary per-frame
// camera path re-extends the boom. Updating directly from the stale
// source-world viewer made the destination bend across the reveal.
_retailChaseCamera?.ResetViewerToPlayer(snappedPos, _playerController.Yaw);
AcDream.Core.Physics.PhysicsDiagnostics.LogTeleport(
"PLACED", resolved.CellId, $"forced={forced}");
@ -7055,6 +7057,8 @@ public sealed class GameWindow : IDisposable
_teleportInProgress = true;
_teleportHoldSeconds = 0f;
_teleportForced = false;
_teleportViewPlane.Begin(
_cameraController?.Active.Projection ?? System.Numerics.Matrix4x4.Identity);
_teleportAnim.Begin(AcDream.Core.World.TeleportEntryKind.Portal);
Console.WriteLine($"live: teleport started (seq={sequence})");
}
@ -8900,6 +8904,7 @@ public sealed class GameWindow : IDisposable
int tunnelFrame = _portalTunnel?.CurrentAnimationFrame ?? 0;
var (snap, evts) = _teleportAnim.Tick((float)dt, ready, tunnelFrame);
_teleportViewPlane.Update(snap);
// The fade is a viewport transition below retained UI. If the
// installed DATs are corrupt and the retail portal scene could
// not be built, retain an opaque world cover during transit.
@ -8934,6 +8939,7 @@ public sealed class GameWindow : IDisposable
AcDream.Core.Net.Messages.GameActionLoginComplete.Build());
_teleportInProgress = false;
_pendingTeleportCell = 0u;
_teleportViewPlane.Reset();
_teleportFadeAlpha = 0f;
break;
default:
@ -9570,7 +9576,8 @@ public sealed class GameWindow : IDisposable
if (_cameraController is not null)
{
var camera = _cameraController.Active;
var frustum = AcDream.App.Rendering.FrustumPlanes.FromViewProjection(camera.View * camera.Projection);
var worldProjection = _teleportViewPlane.Apply(camera.Projection);
var frustum = AcDream.App.Rendering.FrustumPlanes.FromViewProjection(camera.View * worldProjection);
// Extract camera world position from the inverse of the view
// matrix — needed by the scene-lighting UBO (for fog distance)
@ -9799,7 +9806,7 @@ public sealed class GameWindow : IDisposable
// Phase A8: update EnvCellRenderer's frustum. The per-frame shell snapshot
// is prepared after the portal-visible cell filter is known.
var envCellViewProj = camera.View * camera.Projection;
var envCellViewProj = camera.View * worldProjection;
_envCellFrustum?.Update(envCellViewProj);
// MP-Alloc: reuse _animatedIdsScratch instead of `new`ing a
@ -10422,7 +10429,7 @@ public sealed class GameWindow : IDisposable
}
_debugDrawLogOnce++;
}
_debugLines.Flush(camera.View, camera.Projection);
_debugLines.Flush(camera.View, worldProjection);
}
// Count visible vs total for the perf overlay.
@ -10484,10 +10491,12 @@ public sealed class GameWindow : IDisposable
// CreatureMode portal-space viewport. This replacement scene and
// its black transition draw BEFORE retained UI, so chat, windows,
// cursor, and toolbar remain visible and interactive in transit.
var portalProjection = _teleportViewPlane.Apply(
_cameraController!.Active.Projection);
_portalTunnel?.Draw(
_window!.Size.X,
_window.Size.Y,
_cameraController!.Active.Projection);
portalProjection);
_fadeOverlay?.Draw(_teleportFadeAlpha);
// Phase D.2b Sub-phase C Slice 2 — paperdoll 3-D doll: render the re-dressed player clone into the