Indoor lighting DONE this session (#142/#143 closed). Per user: do NOT merge to main; start fresh next session. NEXT-session order set in the handoff: 1. #145 — portals only work once per session (run in/out/re-enter repeatedly). Machinery: 0xF751 PlayerTeleport -> PortalSpace -> TeleportArrivalController -> streaming collapse/expand. Likely overlaps #138. Instrument a 2nd teleport first. 2. #144 — dungeon interiors still too dim vs retail (cdb side-by-side first). Handoff: docs/research/2026-06-20-indoor-lighting-done-next-portal-reuse-handoff.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.9 KiB
Handoff — indoor lighting DONE; NEXT: #145 portal re-use, then #144 dungeon dimness
Date: 2026-06-20
Branch: claude/thirsty-goldberg-51bb9b — committed, NOT merged to main, NOT pushed (user's call)
Milestone: M1.5 "Indoor world feels right"
What shipped this session (on the branch, not pushed)
The entire indoor-lighting saga. #142 + #143 CLOSED, user-confirmed.
| Commit | What |
|---|---|
ef5049f |
#142 per-instance sun gate (indoor objects skip the sun, per-draw like retail) |
0d8b827 |
THE root-cause fix — EnvCellRenderer landblock-key bug + viewer light + weenie fixture lights |
57c2ab7 |
#143 dynamic-light D3D 1/d attenuation (portal + viewer spread softly) |
653e7f3 |
docs: close #142/#143, file #144 |
| (this) | docs: file #145 + this handoff |
One-line story: interiors were dark NOT because of the sun/ambient (those were
already retail-faithful — the 0.2-flat/sky split == CellManager::ChangePosition
0x004559B0). The real bug was a landblock-key lookup in
EnvCellRenderer.GetCellLightSet: it keyed _landblocks by cellId & 0xFFFF0000
(0xXXYY0000) instead of the streaming key 0xXXYYFFFF, so the lookup missed
for EVERY cell → SelectForObject never ran → every interior wall got ZERO point
lights, always. Fix: (cellId & 0xFFFF0000) | 0xFFFF. Found by a [cell-light]
probe (inBounds=False selected=0 → True selected=3-4) after 3+ speculative fixes.
Retail mechanisms ported alongside it (all faithful, decomp-cited):
- Viewer light —
SmartBox::set_viewer0x00452c40: white fill pinned to the player every frame;1/datt, range 15.LightManager.UpdateViewerLight. - Weenie fixture lights (AP-44) — server-object
Setup.Lightsregistered on spawn (OnLiveEntitySpawnedLocked); the meeting-hall portal's magenta light rides this → #143 lit "for free." - Dynamic vs static attenuation —
config_hardware_light0x0059ad30: dynamic =1/d+ range×1.5; static =1/d³+ range×1.3. Per-lightIsDynamicflag packed intoGlobalLight.coneAngleEtc.y.
Register: AP-43 (#142 sun gate), AP-44 (weenie lights), AP-47 (acdream's always-lit
interiors vs retail's 40-light pop-in — INTENTIONAL). Full lighting detail:
memory reference_retail_ambient_values.md (2026-06-20 resolution note).
Suites: Core 1505 / App 476 green.
NEXT SESSION — in this order
1. FIRST — #145: portals only work once per session (HIGH)
User wants: run into a portal, run out, re-enter — repeatedly. Currently only the FIRST teleport works; the second portal use does nothing.
- Machinery:
WorldSession.cs:999(0xF751 PlayerTeleport) →PlayerMovementControllerPlayerState.PortalSpace(:75/:840) →TeleportArrivalController(PhaseIdle/Holding; the placement delegate flips PortalSpace back to InWorld) →GameWindow.cs:4903/5332/5362(PortalSpace observer + arrival placement) → streaming collapse↔expand (#133/#135 machinery). - First step (don't guess): instrument a SECOND teleport and find WHERE it stalls —
does the 2nd 0xF751 arrive? does PortalSpace toggle back to InWorld? does
TeleportArrivalController.Tickplace viaPlaceTeleportArrival? does the streaming window re-expand? One probe across those four points pins it. - Likely overlaps #138 (teleport OUT of a dungeon loads the outdoor world incompletely) — may be the same root or a sibling; check together.
2. THEN — #144: dungeon interiors still too dim vs retail (MEDIUM)
Dungeons improved (torch cells light up now — the landblock-key fix + viewer fill), but torch-sparse stretches + overall brightness still trail retail (user: "better but not good enough").
- Approach: side-by-side cdb capture of retail's dungeon —
world_lightsactive set +world_lights.ambient_color+ the viewer-light intensity at the SAME spot — vs acdream's[light]/[light-detail]there. Do NOT guess. - Candidates: per-vertex Gouraud bake under-lights low-poly dungeon walls (AP-35 residual); the sealed-dungeon flat 0.2 ambient too dark; retail leans harder on the viewer light / carries more dynamics.
Launch / probes
testaccount2 / testpassword2 (character Horan, spawns near Holtburg; reaches the
0x0007 Town Network dungeon). Canonical launch + ACDREAM_PROBE_LIGHT=1 +
ACDREAM_PROBE_CELL=1 → [light] / [light-detail] / [cell-transit]. The
[cell-light] per-cell probe was STRIPPED (the bug it found is fixed) — re-add a
per-cell light probe in EnvCellRenderer.GetCellLightSet if #144 needs it.
Pointers
- memory
reference_retail_ambient_values.md— lighting resolution + the cdb toolchain. docs/architecture/retail-divergence-register.md— AP-43 / AP-44 / AP-47.docs/ISSUES.md— #144, #145, #138 (related), #137 (dungeon collision).- cdb toolchain: CLAUDE.md "Retail debugger toolchain" (binary matches
refs/acclient.pdb).