fix(world): remove non-retail portal exit fade
This commit is contained in:
parent
842bd89c16
commit
dded9e6b17
21 changed files with 919 additions and 347 deletions
|
|
@ -599,7 +599,7 @@ This is the asynchronous adapter for retail's direct full-`Position` placement
|
|||
|
||||
`TeleportAnimSequencer` is the pure Core owner of retail's seven-state
|
||||
teleport lifecycle, exact 1/2/5-second thresholds, frame-aligned exit window,
|
||||
and 100-sample `UIGlobals::GetAnimLevel` fade curve. App-layer
|
||||
and 100-sample `UIGlobals::GetAnimLevel` view-plane curve. App-layer
|
||||
`PortalTunnelPresentation` owns the synthetic DAT Setup (`0x02000306`), its
|
||||
40-frame/s animation (`0x030005AC`), `CSequence`, SmartBox-FOV camera, distant light, mesh
|
||||
references, and animation-hook delivery. It renders through the existing
|
||||
|
|
@ -613,12 +613,32 @@ enters `LiveEntityRuntime`, collision, picking, radar, or server GUID state.
|
|||
`SmartBox::SetOverrideFovDistance` / `Render::set_vdst`. It captures the active
|
||||
game projection at teleport begin, then applies the same table-eased
|
||||
view-plane distance and near plane to the portal and world viewports through
|
||||
the four fade states. Portal camera direction is a roll around its local AC
|
||||
the four retail `FADE` states. Those states do not drive a black alpha layer:
|
||||
the portal and world 3-D viewports switch directly at the transition view
|
||||
distance, while retained UI remains independently composed. Portal camera
|
||||
direction is a roll around its local AC
|
||||
`+Y` forward axis, so the animated scene remains a passage rather than yawing
|
||||
away from it. Destination placement also calls the retail chase camera's
|
||||
`set_viewer(player, reset_sought=1)` equivalent; the normal damped/swept camera
|
||||
path then re-extends from the arriving player.
|
||||
|
||||
One reset seam ends a logical transit on successful completion, replacement
|
||||
by a newer teleport sequence, or session teardown. It clears the destination,
|
||||
streaming priority, sequencer edges, projection override, and portal scene
|
||||
together, preventing transition state from crossing destination or session
|
||||
lifetimes. `TeleportTransitCoordinator` correlates each fresh F751 sequence
|
||||
with exactly one accepted `UpdatePosition`. Because the Position can arrive on
|
||||
either side of F751, a pre-notification packet is buffered only when it advances
|
||||
retail's `TELEPORT_TS`; after notification, the first accepted matching packet
|
||||
is consumed even if that timestamp already advanced. Duplicate/older F751
|
||||
notifications are rejected with wrap-safe ordering. Canonical physics remains
|
||||
independent, and streaming recentering compares destination identity with the
|
||||
actual current streaming center rather than the player's still-unplaced source
|
||||
cell. A live teleport received while acdream's developer fly/orbit camera is
|
||||
active re-enters the existing player-mode lifecycle first; retail has no
|
||||
detached camera mode, and destination placement therefore always retains the
|
||||
canonical local physics controller and chase-camera handoff.
|
||||
|
||||
The destination residency gate supplies retail's `EndTeleportAnimation` edge
|
||||
once asynchronous streaming is ready. Player placement remains authoritative
|
||||
and separate from presentation; arrival resets camera viewer state but does
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ accepted-divergence entries (#96, #49, #50).
|
|||
| # | Divergence | Where (file:line) | Why it is safe / justified | Risk if assumption breaks | Retail oracle |
|
||||
|---|---|---|---|---|---|
|
||||
| AD-1 | Lost-cell machinery replaced by recoverable outdoor demote (**#107** safety net) + outdoor-restore `max(terrainZ, z)` under-terrain lift; retail goes `GotoLostCell` | `src/AcDream.Core/Physics/PhysicsEngine.cs:553` (+ :808) | acdream has no lost-cell state machine; outdoor landcell is the recoverable equivalent; the #107 auto-entry hold should make the demote branch unreachable | Gap in the hold → player committed to outdoor terrain inside/under a building (fake-grounded spawn, fall-through); a legit below-heightmap server restore is silently lifted — upward warp vs server | `GotoLostCell` pc:283418; `SetPositionInternal` 0x00515bd0, pc:283892-283945 |
|
||||
| AD-2 | Async spawn gates replacing retail's synchronous cell load. **#135 refinement:** an INDOOR spawn/teleport (cell ≥ 0x0100, hydratable) gates ONLY on the EnvCell floor (`IsSpawnCellReady`), NOT the terrain heightmap; an OUTDOOR spawn (or an unhydratable indoor claim that demotes outdoor) gates on the terrain-ready hold (**#106**). A dungeon's negative-offset cells can place the spawn's WORLD position in a neighbour terrain landblock the #135 dungeon collapse doesn't load, so a terrain requirement would hang indoor login/teleport forever (cellReady true, terrain null) — the player lands on the cell floor, terrain is irrelevant indoors. Claims beyond NumCells skip the gate (demoted). **#145 refinement (2026-06-22):** an OUTDOOR teleport additionally requires the destination's OWN landblock terrain to be resident (`PhysicsEngine.IsLandblockTerrainResident(destCell)`, which `StreamingController` priority-applies so it flips in ~hundreds of ms) before placing — and `SampleTerrainZ` is short-circuited behind it. On a teleport OUT of a dungeon the collapsed SOURCE dungeon stays resident at the same streaming-local coords and answers `SampleTerrainZ` (terrain 0), so without the load check the resolve ran against the dungeon's cells and rooted the player at a dungeon-frame cell id (ACE then rejected all movement as "failed transition"). Decision in `TeleportWorldReady`; the hold→materialize→regain-control transit is driven by `TeleportAnimSequencer` (the retail fade cover, ticked in `OnUpdate`), which replaced the retired `TeleportArrivalController` | `src/AcDream.App/Rendering/GameWindow.cs` (`isSpawnGroundReady` lambda ~1010 + `TeleportWorldReady` ~5512 + the TAS transit tick in `OnUpdate`) (+ `src/AcDream.App/Input/PlayerModeAutoEntry.cs:69`, `src/AcDream.Core/Physics/PhysicsEngine.cs:468`) | Entering earlier integrates gravity against an empty world (free-fall into void); the gate is the async-streaming equivalent of retail's blocking load; a looser "any struct present" version reproduced the transparent-interior wedge. Indoor-on-cellReady is the faithful equivalent of retail's synchronous cell load + place-on-floor (terrain under a dungeon is meaningless; the pre-#135 terrain hold only passed because the 25×25 window streamed the neighbour terrain) | Gate opens early → raw claim commit → outdoor demote mid-building; predicate never satisfied (streamer stall, dat edge case) → login wedges in pre-player mode; an indoor spawn whose cell never hydrates now holds on cellReady alone (no terrain backstop) — but that path is exactly the #107 hold | retail synchronous cell load before SetPosition (no gate exists) |
|
||||
| AD-2 | Async spawn gates replacing retail's synchronous cell load. **#135 refinement:** an INDOOR spawn/teleport (cell ≥ 0x0100, hydratable) gates ONLY on the EnvCell floor (`IsSpawnCellReady`), NOT the terrain heightmap; an OUTDOOR spawn (or an unhydratable indoor claim that demotes outdoor) gates on the terrain-ready hold (**#106**). A dungeon's negative-offset cells can place the spawn's WORLD position in a neighbour terrain landblock the #135 dungeon collapse doesn't load, so a terrain requirement would hang indoor login/teleport forever (cellReady true, terrain null) — the player lands on the cell floor, terrain is irrelevant indoors. Claims beyond NumCells skip the gate (demoted). **#145 refinement (2026-06-22):** an OUTDOOR teleport additionally requires the destination's OWN landblock terrain to be resident (`PhysicsEngine.IsLandblockTerrainResident(destCell)`, which `StreamingController` priority-applies so it flips in ~hundreds of ms) before placing — and `SampleTerrainZ` is short-circuited behind it. On a teleport OUT of a dungeon the collapsed SOURCE dungeon stays resident at the same streaming-local coords and answers `SampleTerrainZ` (terrain 0), so without the load check the resolve ran against the dungeon's cells and rooted the player at a dungeon-frame cell id (ACE then rejected all movement as "failed transition"). Decision in `TeleportWorldReady`; the hold→materialize→regain-control transit is driven by `TeleportAnimSequencer` (the retail portal/view-plane lifecycle, ticked in `OnUpdate`), which replaced the retired `TeleportArrivalController` | `src/AcDream.App/Rendering/GameWindow.cs` (`isSpawnGroundReady` lambda ~1010 + `TeleportWorldReady` ~5512 + the TAS transit tick in `OnUpdate`) (+ `src/AcDream.App/Input/PlayerModeAutoEntry.cs:69`, `src/AcDream.Core/Physics/PhysicsEngine.cs:468`) | Entering earlier integrates gravity against an empty world (free-fall into void); the gate is the async-streaming equivalent of retail's blocking load; a looser "any struct present" version reproduced the transparent-interior wedge. Indoor-on-cellReady is the faithful equivalent of retail's synchronous cell load + place-on-floor (terrain under a dungeon is meaningless; the pre-#135 terrain hold only passed because the 25×25 window streamed the neighbour terrain) | Gate opens early → raw claim commit → outdoor demote mid-building; predicate never satisfied (streamer stall, dat edge case) → login wedges in pre-player mode; an indoor spawn whose cell never hydrates now holds on cellReady alone (no terrain backstop) — but that path is exactly the #107 hold | retail synchronous cell load before SetPosition (no gate exists) |
|
||||
| AD-3 | Outdoor seeds always walk the transit array (retail skips the walk when the seed CLandCell is null/unloaded); per-cell lookups no-op on unhydrated data | `src/AcDream.Core/Physics/CellTransit.cs:503` | Equivalence argument: with nothing hydrated every lookup inside the walk no-ops, so the result matches retail's skipped walk | Near partially-streamed landblocks, building-transit promotion silently can't fire until structs hydrate — membership stays outdoor while the player is inside a building | `CObjCell::find_cell_list` 0052b535-0052b56c (null-CLandCell case) |
|
||||
| AD-4 | `point_in_cell` against an unhydrated CellBSP returns false (skip) rather than the null-node "inside" default; retail never queries unloaded cells | `src/AcDream.Core/Physics/CellTransit.cs:588` | The null-node default would make an unhydrated cell spuriously claim every point; skipping is the conservative streaming-safe choice | During hydration, a point genuinely inside a not-yet-loaded cell resolves outdoor/stale — transient membership misclassification driving wrong collision set and render root | `CEnvCell::find_visible_child_cell` :311397; cell-BSP vtable[0x84] |
|
||||
| AD-5 | Outdoor `point_in_cell` is an identity compare against the global XY-column cell from `LandDefs.AdjustToOutside` (no per-cell containment test) | `src/AcDream.Core/Physics/CellTransit.cs:865` | Landcells are disjoint 24 m columns — identity-compare against the column under the sphere centre is exactly equivalent to retail's per-candidate test | If block-origin/lcoord math is wrong at a landblock seam, the compare silently never matches — outdoor membership freezes at boundaries (the pre-#106 symptom) | `find_cell_list` pick pc:308788-308825; `CLandCell::point_in_cell` (get_block_offset pc:308804) |
|
||||
|
|
@ -212,7 +212,7 @@ AP-94..AP-112 for the confirmed retail-UI completion gaps.
|
|||
| AP-113 | Invalid lifestone-command arguments display the local text `Usage: /lifestone`; retail definitely emits a local usage/error line but Binary Ninja misidentifies the referenced wide-string address, so its exact wording is not yet recovered | `src/AcDream.UI.Abstractions/Panels/Chat/ChatCommandRouter.cs`; `RetailClientCommandCatalog.cs` | The behavior boundary is exact (handled locally, no chat and no game action); only a low-impact diagnostic sentence differs | `/ls now` can show different wording/color from retail while still refusing the invalid request correctly | `ClientCommunicationSystem::DoLifestone @ 0x0056FC70` |
|
||||
|
||||
| ~~AP-114~~ | **RETIRED 2026-07-14 (protection-effect corrective gate)** — the particle renderer no longer replaces every authored GfxObj with one bounding-box quad. Retail `Always2D` classification preserves mode-1/no-degrade full meshes through the modern shared mesh buffer and leaves only other degrade modes on the billboard path; stable emitter handles balance mesh ownership. | `src/AcDream.App/Rendering/ParticleRenderer.cs`; `RetailParticleGeometryClassifier.cs`; `particle_mesh.vert/.frag` | — | — | `CPhysicsPart::Draw @ 0x0050D7A0`; `CPhysicsPart::Always2D @ 0x0050D8A0`; `ParticleEmitter::SetInfo @ 0x0051CE90`; `docs/research/2026-07-13-retail-projectile-vfx-pseudocode.md` |
|
||||
| AP-115 | The DAT-authored portal-space viewport and its animation `SoundTweakedHook` are live, but the separate `ClientUISystem` enter/exit sound enums and centered repeating `"In Portal Space - Please Wait..."` display string are not yet presented. | `src/AcDream.App/Rendering/PortalTunnelPresentation.cs`; teleport event switch in `GameWindow.cs` | acdream has no retained cross-stack centered display-string owner or ClientUISystem sound-table-enum resolver yet; routing the line into chat or inventing direct wave IDs would be less faithful | Portal travel has the correct animated wormhole, timing, fades, and animation-authored sound, but lacks retail's short UI cue sounds and center notice | `gmSmartBoxUI::BeginTeleportAnimation @ 0x004D6300`; `gmSmartBoxUI::UseTime @ 0x004D6E30` |
|
||||
| AP-115 | The DAT-authored portal-space viewport and its animation `SoundTweakedHook` are live, but the separate `ClientUISystem` enter/exit sound enums and centered repeating `"In Portal Space - Please Wait..."` display string are not yet presented. | `src/AcDream.App/Rendering/PortalTunnelPresentation.cs`; teleport event switch in `GameWindow.cs` | acdream has no retained cross-stack centered display-string owner or ClientUISystem sound-table-enum resolver yet; routing the line into chat or inventing direct wave IDs would be less faithful | Portal travel has the correct animated wormhole, timing, direct viewport switch, view-plane transitions, and animation-authored sound, but lacks retail's short UI cue sounds and center notice | `gmSmartBoxUI::BeginTeleportAnimation @ 0x004D6300`; `gmSmartBoxUI::UseTime @ 0x004D6E30` |
|
||||
|
||||
## 4. Temporary stopgap (TS) — 34 active rows (TS-37 is a retired-row historical note, not an active count; TS-39 retired R5-V3 — sticky seams bound to the ported PositionManager/StickyManager, radii threaded; TS-45 retired 2026-07-07 — hand-rolled `SphereCollision` replaced by the faithful CSphere family port, fixing the player-vs-monster crowd wedge; TS-3 retired 2026-07-07 — `frames_stationary_fall` accounting ported in the #182 verbatim UpdateObjectInternal rebuild, fixing the airborne falling-animation wedge; TS-41 retired 2026-07-07 — SERVERVEL synth-velocity remote body-drive replaced by the retail interp catch-up + unconditional MovementManager::UseTime, the remote-creature de-overlap #184; TS-44 narrowed same day — NPC UP unified onto the interp queue, gate retained for orientation)
|
||||
|
||||
|
|
|
|||
|
|
@ -593,7 +593,7 @@ Research: R9 + R12 + R13.
|
|||
- **✓ SHIPPED — G.1 — Sky + weather + day-night.** Deterministic client-side from Portal Year time. Sky dome geometry + keyframe gradients + rain/snow particles. See `r12-weather-daynight.md`. Full data + visual stack shipped: Region dat loader, keyframe interp, WeatherSystem with 5-kind PDF + transitions + storm flashes, WorldSession→WorldTimeService sync via ConnectRequest+TimeSync, SkyRenderer with sky-object arcs + UV scroll, rain/snow billboard renderer, F7/F10 debug cycle keys.
|
||||
- **✓ SHIPPED — G.2 — Dynamic lighting.** 8-light D3D-style fixed pipeline. Hard-cutoff at Range, no attenuation inside. Cell ambient. Shader UBO per frame. See `r13-dynamic-lighting.md`. SceneLightingUbo std140 at binding=1 feeds terrain + mesh + mesh_instanced + sky shaders. LightingHookSink auto-registers Setup.Lights at entity stream-in, flips IsLit on SetLightHook, unregisters on landblock unload.
|
||||
- **Indoor portal-based cell tracking (follow-up to Indoor walking Phase 1 / issue #87).** Replace `PhysicsDataCache.TryFindContainingCell` AABB containment with retail's `CObjMaint::HandleObjectEnterCell` portal traversal. When the player crosses a cell portal boundary, `CellId` propagates through the `CEnvCell` portal connectivity graph. Prerequisite for wall collision from outside (#85) and the remaining #84 threshold symptom. PDB symbols and `acclient.h` `CCellStructure` refs are in place (see #87). **Unblocks G.3.**
|
||||
- **✓ SHIPPED — G.3 — Dungeon streaming + portal space.** `EnvCellStreamer`, portal-visibility BFS, `PlayerTeleport (0xF751)` handling with post-transition `LoginComplete`, and the retail DAT-authored portal-space CreatureMode viewport (Setup `0x02000306`, animation `0x030005AC`, exact camera/light/timing/fades, forward-axis roll, projection warp, and destination viewer reset; corrective visual gate pending 2026-07-15). Dungeons render, stream, teleport-in, collide, light, and their doors work — see the shipped-table rows (G.3, G.3a, #137 collision, A7.L1 lighting) below and the M1.5 section of `docs/plans/2026-05-12-milestones.md` for current gate status (one recorded end-to-end round-trip user gate outstanding; live residual = far-town teleport-OUT arrival cascade, #145-residual REOPENED). See `r09-dungeon-portal-space.md` and `docs/research/2026-07-15-retail-portal-space-pseudocode.md`.
|
||||
- **✓ SHIPPED — G.3 — Dungeon streaming + portal space.** `EnvCellStreamer`, portal-visibility BFS, `PlayerTeleport (0xF751)` handling with post-transition `LoginComplete`, and the retail DAT-authored portal-space CreatureMode viewport (Setup `0x02000306`, animation `0x030005AC`, exact camera/light/timing/view-plane transitions, forward-axis roll, direct portal→world viewport switch, projection warp, and destination viewer reset; corrective visual gate pending 2026-07-15). Dungeons render, stream, teleport-in, collide, light, and their doors work — see the shipped-table rows (G.3, G.3a, #137 collision, A7.L1 lighting) below and the M1.5 section of `docs/plans/2026-05-12-milestones.md` for current gate status (one recorded end-to-end round-trip user gate outstanding; live residual = far-town teleport-OUT arrival cascade, #145-residual REOPENED). See `r09-dungeon-portal-space.md` and `docs/research/2026-07-15-retail-portal-space-pseudocode.md`.
|
||||
|
||||
**Acceptance:** walk outside at dusk, see the sky gradient + sun moving; enter a torch-lit dungeon via portal; leave back to daylight.
|
||||
|
||||
|
|
|
|||
|
|
@ -306,8 +306,9 @@ temporary black tunnel cover is retired. F751 transit now renders retail's
|
|||
client-enum-resolved DAT Setup `0x02000306` with animation `0x030005AC` at
|
||||
40 frames/s in a dedicated CreatureMode-equivalent viewport, using retail's
|
||||
camera, distant light, random eased forward-axis roll, frame-aligned exit
|
||||
window, exact 100-sample fade curve, view-plane/FOV warp, and destination
|
||||
viewer reset. The viewport and fades compose below retained UI, so
|
||||
window, exact 100-sample view-plane curve, projection warp, and destination
|
||||
viewer reset. Retail switches the portal and world viewports directly without
|
||||
a black alpha fade; both compose below retained UI, so
|
||||
chat, panels, toolbar, cursor, and input remain live throughout travel. See
|
||||
`docs/research/2026-07-15-retail-portal-space-pseudocode.md`.
|
||||
|
||||
|
|
|
|||
|
|
@ -91,9 +91,10 @@ show portal viewport
|
|||
hide world SmartBox viewport
|
||||
```
|
||||
|
||||
At the end of `TunnelFadeOut`, retail restores the world view distance, hides
|
||||
the portal viewport, shows the world viewport, clears the teleport object's
|
||||
sequence animations, plays `Sound_UI_ExitPortal`, and enters `WorldFadeIn`.
|
||||
At the end of `TunnelFadeOut`, retail commits the current transition view
|
||||
distance, hides the portal viewport, shows the world viewport, clears the
|
||||
teleport object's sequence animations, plays `Sound_UI_ExitPortal`, and enters
|
||||
`WorldFadeIn`. That following state restores the ordinary game view distance.
|
||||
|
||||
## Camera motion
|
||||
|
||||
|
|
@ -185,31 +186,35 @@ WorldFadeIn:
|
|||
-> Off
|
||||
```
|
||||
|
||||
The narrow remaining-time window makes the one-second tunnel fade finish at
|
||||
The narrow remaining-time window makes the one-second tunnel projection transition finish at
|
||||
the end of the 120-frame animation. The five-second ceiling is retail's escape
|
||||
for a missed window.
|
||||
|
||||
World/tunnel fades use `GetAnimLevel(elapsed / FadeTime)`. The fade belongs
|
||||
between the 3-D viewport and the retained UI. It must never cover or disable
|
||||
the retained UI.
|
||||
The four states whose retail enum names contain `FADE` use
|
||||
`GetAnimLevel(elapsed / FadeTime)`. Instruction-level x86 inspection of
|
||||
`gmSmartBoxUI::UseTime` (`0x004D7133..0x004D725F`) shows that this value feeds
|
||||
only `SmartBox::SetOverrideFovDistance`. The function performs no alpha or
|
||||
black-quad draw; `FADE` names the view-plane transition, not a transparency
|
||||
compositor. The retained UI remains independent because only the two 3-D
|
||||
viewports are switched.
|
||||
|
||||
## View-plane warp
|
||||
|
||||
Retail couples every fade state to a projection transition. On begin it
|
||||
Retail couples every `FADE` state to a projection transition. On begin it
|
||||
captures the current SmartBox view-plane distance; for a perspective
|
||||
projection this is `cot(verticalFov / 2)`. The transition endpoint is the
|
||||
named constant `TRANSITION_VIEW_PLANE_DISTANCE = 0.001` at `0x007BD260`.
|
||||
|
||||
```text
|
||||
fadeLevel = GetAnimLevel(elapsed / FadeTime) / 1024
|
||||
viewPlaneLevel = GetAnimLevel(elapsed / FadeTime) / 1024
|
||||
|
||||
WorldFadeOut or TunnelFadeOut:
|
||||
currentDistance = gameDistance
|
||||
+ (0.001 - gameDistance) * fadeLevel
|
||||
+ (0.001 - gameDistance) * viewPlaneLevel
|
||||
|
||||
TunnelFadeIn or WorldFadeIn:
|
||||
currentDistance = 0.001
|
||||
+ (gameDistance - 0.001) * fadeLevel
|
||||
+ (gameDistance - 0.001) * viewPlaneLevel
|
||||
|
||||
SmartBox.SetOverrideFovDistance(true, currentDistance)
|
||||
```
|
||||
|
|
@ -221,10 +226,22 @@ verticalFov = 2 * atan(1 / currentDistance)
|
|||
znear = max(0.1, currentDistance * 0.25)
|
||||
```
|
||||
|
||||
At `0.001`, the view is nearly 180 degrees wide. Black covers the singular
|
||||
endpoint; as `WorldFadeIn` clears, the FOV eases back to the captured game
|
||||
projection. This is retail's characteristic destination-world warp, separate
|
||||
from both the alpha fade and chase-camera movement.
|
||||
At `0.001`, the view is nearly 180 degrees wide. Retail does not cover that
|
||||
endpoint with black: it switches directly from the tunnel viewport to the
|
||||
destination world at this projection, then `WorldFadeIn` expands the world
|
||||
from the center as the captured game projection is restored. This is retail's
|
||||
characteristic destination-world warp, independent of chase-camera movement.
|
||||
|
||||
Instruction-level checks that disambiguate the Binary Ninja x87 output:
|
||||
|
||||
- `SmartBox::GetOverrideFovDistance` `0x00451BE0`: when no override is active,
|
||||
returns `cot(activeVerticalFov / 2)` (`0x00798088 = 0.5`,
|
||||
`0x007928C0 = 1.0`).
|
||||
- `gmSmartBoxUI::UseTime` `0x004D7199` and `0x004D722E`: converts the signed
|
||||
table result with `0x007BD6A0 = 1/1024` and performs the two lerps above.
|
||||
- `Render::set_vdst` `0x0054B240`: x87 `fpatan` computes
|
||||
`atan(1 / distance)`, doubles it, and sets
|
||||
`znear = max(0.1, distance * 0.25)`.
|
||||
|
||||
## Player placement boundary
|
||||
|
||||
|
|
@ -261,7 +278,7 @@ collision. Reusing the source-world viewer is not retail behavior.
|
|||
|
||||
The retail teleport hook does not clear the character's animation sequence.
|
||||
The arrival presentation is instead hidden by the portal scene and its final
|
||||
world fade while the normal motion/update stream settles. Therefore acdream
|
||||
world view-plane transition while the normal motion/update stream settles. Therefore acdream
|
||||
must not add an arrival-only animation reset.
|
||||
|
||||
## acdream integration translation
|
||||
|
|
@ -272,11 +289,18 @@ must not add an arrival-only animation reset.
|
|||
consumes the portal object's current frame for retail exit timing and uses
|
||||
the exact table-driven easing curve.
|
||||
- During tunnel states the portal scene replaces world pixels before retained
|
||||
UI draws. The black fade also draws before retained UI. Input dispatch and
|
||||
UI draws. There is no black compositor. Input dispatch and
|
||||
`RetailUiRuntime.Tick` continue unchanged.
|
||||
- The projection owner captures the active camera's M22 view-plane distance at
|
||||
teleport begin and applies `Render::set_vdst` semantics to both the tunnel
|
||||
and world viewport during the four fade states.
|
||||
and world viewport during the four `FADE` states.
|
||||
- F751 remains a notification gate and does not itself advance `TELEPORT_TS`.
|
||||
Presentation correlates its sequence with exactly one accepted destination
|
||||
Position. A Position that arrives before F751 is buffered only when it
|
||||
advances that timestamp; after F751, the first accepted matching Position is
|
||||
consumed even if the channel already advanced. Thus reordered delivery and
|
||||
retransmitted notifications cannot materialize the wrong destination or
|
||||
strand the transit, while canonical physics retains its own retail gates.
|
||||
- Destination placement resets the retail chase camera's published and sought
|
||||
positions to the player before the normal update path resumes.
|
||||
- Destination residency remains acdream's asynchronous adaptation. It supplies
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
# Retail Teleport Flow Implementation Plan
|
||||
|
||||
> **Historical presentation plan.** Superseded 2026-07-15 by the DAT-authored
|
||||
> portal viewport and retail view-plane port. `FadeAlpha` and the black overlay
|
||||
> below are not current behavior. See
|
||||
> `docs/research/2026-07-15-retail-portal-space-pseudocode.md`.
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Build the retail-faithful unified teleport flow — a `TeleportAnimState` (TAS) animation state machine + arrival hold that covers **login, logout, death, and portal** with a fade-to-black cover, **holds until the destination landblock is actually loaded** (folding in the #145 unstreamed-arrival cascade fix), and **locks input + camera for the whole transition**.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
# Retail Teleport — Priority Residency + Fade Cover — Implementation Plan
|
||||
|
||||
> **Historical presentation plan.** Superseded 2026-07-15 by the DAT-authored
|
||||
> portal viewport and retail view-plane port. `FadeAlpha`/`FadeOverlay` below
|
||||
> describe the retired temporary adaptation, not current behavior. See
|
||||
> `docs/research/2026-07-15-retail-portal-space-pseudocode.md`.
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Make a teleport materialize the player onto a resident, grounded destination within ~1 s (was 10–14 s) with no movement desync, covered by a retail fade — fixing "long transition," "dropped at the wrong position," and "stops at the portal" in one coherent change.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
# Design — Retail teleport flow (the unified `TeleportAnimState` controller)
|
||||
|
||||
> **Presentation semantics corrected 2026-07-15.** The unified lifecycle and
|
||||
> residency gate remain, but the proposed alpha-black cover was an adaptation.
|
||||
> Retail's `FADE` states ease only SmartBox view-plane distance and switch the
|
||||
> portal/world viewports directly. Current oracle:
|
||||
> `docs/research/2026-07-15-retail-portal-space-pseudocode.md`.
|
||||
|
||||
**Date:** 2026-06-21
|
||||
**Feature:** Work item B from `docs/research/2026-06-21-teleport-issues-handoff.md` — the keystone of the
|
||||
teleport-issues cluster (#138, #145 residual, the floating-camera / input-not-locked / "takes too long"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
# Retail-faithful teleport — priority residency + fade cover — design (2026-06-22)
|
||||
|
||||
> **Presentation superseded 2026-07-15.** The residency and placement design
|
||||
> remains historical context, but the black-cover interpretation does not.
|
||||
> The installed DAT-authored portal viewport is now live, and instruction-level
|
||||
> retail x86 proves the TAS `FADE` states drive only view-plane distance; retail
|
||||
> draws no alpha-black overlay. Current oracle:
|
||||
> `docs/research/2026-07-15-retail-portal-space-pseudocode.md`.
|
||||
|
||||
**Status:** approved design, pre-implementation.
|
||||
**Branch:** `claude/thirsty-goldberg-51bb9b`. **Baseline:** `dd2eb8b` (+ the uncommitted `tp-probe` diagnostic).
|
||||
**Supersedes the framing of:** `docs/research/2026-06-21-teleport-foundation-handoff.md` (the `_datLock`-starvation
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue