docs(issues): #36 sky-PES dispatch port — live trace consolidates #2/#28/#29

A 2026-04-30 cdb live trace of retail acclient.exe attached during
sky observation revealed the missing infrastructure behind acdream's
three open sky bugs (#2 lightning, #28 aurora, #29 cloud density).

Live trace over 24,576 GameSky::Draw frames:

  GameSky::Draw                       = 24,576  (60 Hz render rate)
  GameSky::UseTime                    = 12,288  (30 Hz — half rate)
  GameSky::CreateDeletePhysicsObjects = 12,288  (30 Hz, MinQuantum gate)
  CPhysicsObj::CallPES                = 372     (~150/min average)
  CallPESHook::Execute                = 372     (1:1 with CallPES)
  CreateParticleHook::Execute         = 62      (15 initial + 47 burst)
  CPhysicsObj::create_particle_emitter = 62     (matches CreateParticleHook)

Three concrete findings:

1. Retail HAS persistent particle emitters on celestial / sky objects.
   15 created at cell load; dynamically spawned on region/weather/time
   transitions (the trace caught a +47 burst on one such transition).

2. The PES script-hook system drives existing emitters periodically.
   `CallPESHook::Execute` fires script-scheduled actions which call
   `CPhysicsObj::CallPES` 1:1, ~150 times per minute.

3. Earlier research saying "GameSky doesn't read pes_id" was correct
   in scope but missed that the dispatch chain runs through the
   script-hook system (not from inside GameSky directly).
   `CelestialPosition.pes_id` is consumed downstream.

Files a new issue #36 that consolidates implementation work for
all three sky bugs into one porting effort. Adds cross-references
in #2, #28, #29 pointing at #36.

Decomp anchors for next session:
  CallPESHook::Execute              @ 0x00526e20
  CreateParticleHook::Execute       @ 0x00526ec0
  CPhysicsObj::CallPES              @ 0x00511af0
  CPhysicsObj::create_particle_emitter @ 0x0050f360
  GameSky::CreateDeletePhysicsObjects  @ 0x005073c0
  CelestialPosition.pes_id          @ struct offset +0x004

Memory file `project_retail_debugger.md` updated separately with the
sky-PES breakthrough so future sessions inherit the context.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-04-30 22:57:37 +02:00
parent 235de3322a
commit 86e2a4dc90

View file

@ -293,6 +293,93 @@ in under 5 minutes by following the CLAUDE.md workflow.
--- ---
## #36 — Sky-PES dispatch port (consolidates #2 / #28 / #29 visual gaps)
**Status:** OPEN
**Severity:** MEDIUM (aesthetic feature-parity, but addresses a cluster of bugs)
**Filed:** 2026-04-30
**Component:** sky / weather / particles
**Description:** Three open sky bugs (#2 lightning, #28 aurora, #29 cloud
density) all trace back to the same missing infrastructure: retail's
sky-PES (Particle Effect Script) dispatch chain. We have it now from a
2026-04-30 cdb live trace.
**What retail does (live trace evidence):**
```
Trace over 24,576 GameSky::Draw frames:
GameSky::Draw = 24,576 (60 Hz render rate)
GameSky::UseTime = 12,288 (30 Hz — half rate, MinQuantum)
GameSky::CreateDeletePhysicsObjects = 12,288 (also 30 Hz)
CPhysicsObj::CallPES = 372 (~150/min average)
CallPESHook::Execute = 372 (1:1 with CallPES)
CreateParticleHook::Execute = 62 (15 at cell load + 47 burst at transition)
CPhysicsObj::create_particle_emitter = 62 (matches CreateParticleHook)
```
**Three findings:**
1. Retail has **persistent particle emitters** on celestial / sky objects.
Created at cell load (15 initial) and dynamically as conditions change
(the trace caught a +47 burst on a region/weather/time transition).
2. The PES script-hook system (`CallPESHook::Execute`
`CPhysicsObj::CallPES`) drives those emitters periodically, ~150
times per minute on average.
3. Earlier research said "GameSky doesn't read pes_id" — correct in
scope, but missed that the dispatch chain runs through the script-
hook system, not from inside GameSky directly. Cell/region/weather
handlers schedule PES script hooks; those hooks call into CallPES.
**Decomp anchors:**
- `CallPESHook::Execute` @ `0x00526e20` — script-hook action that fires CallPES
- `CreateParticleHook::Execute` @ `0x00526ec0` — particle-creation hook
- `CPhysicsObj::CallPES` @ `0x00511af0`
- `CPhysicsObj::create_particle_emitter` @ `0x0050f360`
- `GameSky::CreateDeletePhysicsObjects` @ `0x005073c0`
- `LongNIHash<ParticleEmitter>` instance — emitter registry
- `CelestialPosition.pes_id` @ struct offset +0x004 — populated by
`SkyDesc::GetSky` but consumed downstream of `GameSky` (via the
hook system, not GameSky itself)
**Implementation outline:**
1. Decomp dive: read `CallPESHook::Execute`, `CreateParticleHook::Execute`,
`CPhysicsObj::CallPES`, and `GameSky::CreateDeletePhysicsObjects`
(and any cell/region weather handlers that spawn the dynamic 47).
2. Identify what triggers `CreateParticleHook` for sky objects — is it
inside `CreateDeletePhysicsObjects`, the region/weather change handler,
or somewhere else?
3. Port the persistent-emitter creation path: when a cell loads or
weather/time changes, instantiate the appropriate ParticleEmitters
on celestial objects.
4. Port the PES timeline driver — periodic dispatch from a script
timeline into our equivalent `CallPES`.
5. Port the actual PES script execution (rate of emission, particle
parameters, etc.) into our particle system.
6. Live verify with cdb during specific weather windows: aurora at dusk
on Rainy DayGroup, lightning during storm.
**Files** (likely):
- `src/AcDream.App/Rendering/Sky/SkyRenderer.cs` — emitter wiring
- `src/AcDream.Core/World/SkyDescLoader.cs` — already parses pes_id
- `src/AcDream.Core/Particles/*` — particle system foundation
- `src/AcDream.App/Rendering/ParticleRenderer.cs` — visual layer
**Live-trace verification plan (next cdb session):** Reattach to retail
during a specific aurora moment, log `this` pointer + `pes_id` arg on
every `CallPES` invocation, log the GfxObj being attached on every
`create_particle_emitter`. That tells us EXACTLY which celestial
objects retail PES-drives and with which IDs.
**Acceptance:** During the same in-game time/weather where retail shows
aurora-style light play (Rainy DayGroup, dusk/dawn windows), acdream
shows comparable colored sky effects. Cloud sheets look as dense /
purple as retail. Lightning flashes appear during storm windows.
**Closes-when-done:** #28, #29, partially #2 (lightning may need
additional flash-shader work).
---
## #33 — Live entity collision shape collapses to one cylinder ## #33 — Live entity collision shape collapses to one cylinder
**Status:** OPEN **Status:** OPEN
@ -347,6 +434,8 @@ one live creature case no longer use the single-cylinder fallback.
**Acceptance:** During a Rainy DayGroup's storm window, visible flashes appear in the sky at the dat-scripted moments, the fragment-shader flash bump briefly brightens the scene, and (later, once thunder audio is wired) a thunder clap plays with a short propagation delay. **Acceptance:** During a Rainy DayGroup's storm window, visible flashes appear in the sky at the dat-scripted moments, the fragment-shader flash bump briefly brightens the scene, and (later, once thunder audio is wired) a thunder clap plays with a short propagation delay.
**See also #36** (Sky-PES dispatch port) — the lightning visuals likely route through the same PES-hook chain that drives aurora and cloud-density. Most of #2's storm-flash visuals will be unblocked by the #36 port.
--- ---
## #3 — Client clock drifts from retail after ~10 minutes (periodic TimeSync missing) ## #3 — Client clock drifts from retail after ~10 minutes (periodic TimeSync missing)
@ -470,6 +559,8 @@ acdream's geometry half is now wired (commit landing 2026-04-27 — `EnsureSetup
**Acceptance:** When retail shows aurora-style light play at a specific in-game time / weather, acdream shows a visually-comparable effect at the same time. **Acceptance:** When retail shows aurora-style light play at a specific in-game time / weather, acdream shows a visually-comparable effect at the same time.
**See #36 (filed 2026-04-30)** — a live cdb trace confirmed retail's aurora rendering uses the script-hook PES dispatch chain (`CallPESHook::Execute``CPhysicsObj::CallPES`) on persistent particle emitters, with a cell-load population (15 initial emitters) plus dynamic spawning on region/weather/time transitions (caught a +47 burst). Implementation work consolidated under #36.
--- ---
## #29 — Cloud surface 0x08000023 still appears thinner than retail despite blend-mode + Setup fixes ## #29 — Cloud surface 0x08000023 still appears thinner than retail despite blend-mode + Setup fixes
@ -497,6 +588,8 @@ If hypothesis (a) is correct, this issue effectively rolls into **#28** — the
**Acceptance:** Cloud sheets look as dense/purple as retail in dual-client side-by-side. May require #28 (PES) to land first. **Acceptance:** Cloud sheets look as dense/purple as retail in dual-client side-by-side. May require #28 (PES) to land first.
**See #36 (filed 2026-04-30)** — confirmed via live cdb trace: retail's cloud density comes from the same PES-driven particle-emitter chain as aurora. Implementation consolidated there.
--- ---
--- ---