acdream/docs/ISSUES.md
Erik 4d1b8b8aee docs(issues): #5 — VitalsPanel stam/mana null until LocalPlayerState lands
Filed as the one explicit post-D.2a follow-up. VitalsVM returns float?
null for Stamina/Mana because absolute values only arrive in
PlayerDescription (0x0013) today and we parse-then-discard. A small
LocalPlayerState Core class that retains the parsed fields unblocks
two more progress bars in the existing Vitals window — no new wire
work needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 00:44:17 +02:00

10 KiB
Raw Blame History

acdream — known issues + small deferred features

Rolling tactical list. What goes here:

  • Bugs: user-visible defects we've observed but haven't fixed yet.
  • Small deferred features: work that fits in one or two commits. Anything larger should be a named Phase in the roadmap.

What does NOT go here:

  • Large multi-commit work → add a Phase to the roadmap instead.
  • Ideas / wishlist → docs/plans/.
  • Design questions → open a docs/research/*.md note.

Conventions

  • Sequential integer IDs (#1, #2, …). Commits that close an issue reference the ID in the message (e.g. fix #3: periodic TimeSync parsing).
  • Status is OPEN, IN-PROGRESS, or DONE. DONE items move to the Recently closed section at the bottom with closed-date + commit SHA.
  • Every session: scan OPEN issues at start; promote/close anything we touched during the session before ending.
  • Promoting to a Phase: mark as DONE (promoted to Phase X) + commit SHA where the Phase entry landed.

Template

Copy this block when adding a new issue:

## #NN — Short title

**Status:** OPEN
**Severity:** HIGH | MEDIUM | LOW
**Filed:** YYYY-MM-DD
**Component:** e.g. sky, physics, net, ui

**Description:** One paragraph — what's wrong or what's missing.

**Root cause / status:** What we know so far. Empty if unknown.

**Files:** Path references with approximate line numbers.

**Research:** Links to `docs/research/*.md` if applicable.

**Acceptance:** How we'll know it's fixed.

Active issues

#1 — Rain falls only to horizon, not to the player's feet

Status: OPEN Severity: MEDIUM Filed: 2026-04-25 Component: weather / particles

Description: During Rainy DayGroups, rain particles are visible in the upper sky band but fade out before reaching the camera / ground level. Retail's rain falls all the way past the camera to the terrain.

Root cause / status: Unknown. Likely one of: (a) particle emitter volume too short in Z, (b) particle lifetime shorter than the time it takes to traverse emitter-top → ground, (c) emitter anchored in world-space so particles escape the player's reference frame as they fall, (d) camera-relative spawn origin is offset too high above the player.

Files:

  • src/AcDream.App/Rendering/GameWindow.csUpdateWeatherParticles (~line 4591)
  • src/AcDream.Core/Vfx/ParticleSystem.cs — emitter spawn config + lifetime integration

Research: docs/research/deepdives/r12-weather-daynight.md (rain mechanism — but does not pin volume / lifetime values).

Acceptance: Standing at 9,115 in Holtburg during a Rainy DayGroup, rain drops visibly fall all the way from the sky band past the camera to the ground level.


#2 — Lightning visual not wired (dat-baked PES triggers)

Status: OPEN Severity: MEDIUM Filed: 2026-04-25 Component: weather / sky / vfx

Description: Retail's Rainy DayGroup in the Dereth Region dat contains 12+ SkyObject entries with non-zero PesObjectId and narrow visibility windows (570 ms at keyframe-boundary moments) that drive PhysicsScript-authored flash + thunder effects. We render the sky meshes but ignore the PES path, so no lightning flashes appear during storms. The fragment-shader flash bump on uFogParams.z is already wired in sky.frag — only the CPU-side PES→runner wire is missing.

Root cause / status: Research complete. Implementation is: in SkyRenderer.Render, detect visibility-window entry on any SkyObject with obj.PesObjectId != 0, call PhysicsScriptRunner.Play(pesObjectId, ownerId: sky-owner, anchorPos: camera), and route any SetFlash / Sound hooks from the script into uFogParams.z + audio.

Files:

  • src/AcDream.App/Rendering/Sky/SkyRenderer.cs — add per-SkyObject PES dispatch inside the visibility loop
  • src/AcDream.Core/Vfx/PhysicsScriptRunner.cs — already shipped (Phase 6a); exposes Play(scriptId, entityId, anchorWorldPos)
  • src/AcDream.Core/Lighting/SceneLightingUbo.csFogParams.Z is the flash slot; needs a sink that bumps it and decays
  • src/AcDream.App/Rendering/Shaders/sky.frag — flash bump already wired (rgb += flash * vec3(1.5, 1.5, 1.8))

Research:

  • docs/research/2026-04-23-lightning-real.md (decompile trace + dat discovery)
  • docs/research/2026-04-23-physicsscript.md (runtime semantics)
  • docs/research/2026-04-23-lightning-crossfade.md (crossfade mechanism)

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.


#3 — Client clock drifts from retail after ~10 minutes (periodic TimeSync missing)

Status: OPEN Severity: MEDIUM Filed: 2026-04-25 Component: net / sky

Description: Our WorldTimeService.DayFraction syncs with the server once at login via ConnectRequest + TimeSync, then advances from the local wall-clock. Retail receives periodic TimeSync refreshes (header flag 0x1000000) carrying a fresh PortalYearTicks double and re-anchors its clock. Without those, acdream's keyframe state drifts from retail's over 10+ minutes — observed during the 2026-04-24 sky-color debug sessions where retail was at DayFraction 0.976 while acdream was at 0.634.

Root cause / status: Mechanism is well-understood (see research). WorldTimeService.SyncFromServer(double) already exists — we just need to detect the periodic flag in the packet header and call it whenever a fresh tick arrives.

Files:

  • src/AcDream.Core.Net/WorldSession.cs — header-flag parsing; currently only the initial sync is consumed
  • src/AcDream.Core/World/WorldTimeService.csSyncFromServer(double ticks) ready; needs caller wiring

Research: docs/research/deepdives/r12-weather-daynight.md §TimeSync (line ~563). References retail packet-header flag 0x1000000 carrying PortalYearTicks double.

Acceptance: Probe retail via tools/RetailTimeProbe and acdream's ACDREAM_DUMP_SKY log at the same wall-clock moment after a 20-minute session without re-login; abs(acdream.DayFraction - retail.DayFraction) < 0.01.


#4 — Sky horizon-glow disabled (fog-mix skipped on sky meshes)

Status: OPEN Severity: LOW (aesthetic feature-parity, not regression from pre-session state) Filed: 2026-04-25 Component: sky

Description: Phase 8.1 (commit 593b76f) disabled the fog-mix on sky meshes to fix the "entire dome swallowed by fog color" regression. Dereth's keyframe FogEnd values (02400 m) are calibrated for terrain; sky meshes are authored at radii 105014271 m so every sky pixel was past FogEnd, saturated to uFogColor, destroying stars / moon / dome texture. Disabling the mix restored visibility but we lost retail's horizon-glow effect (gradient from clear zenith to fog-tinted horizon band at dusk/dawn).

Root cause / status: Three competing hypotheses, none pinned down: (a) retail uses a different fog range for sky than terrain; (b) retail applies fog with an elevation-angle weighting rather than linear distance; (c) retail's sky meshes don't participate in the global fog and the "horizon glow" comes from a different atmospheric-scatter path. Need to identify retail's actual sky-fog behaviour before re-enabling with correct parameters.

Files:

  • src/AcDream.App/Rendering/Shaders/sky.frag — line ~55, rgb = mix(uFogColor.rgb, rgb, vFogFactor) currently commented out
  • src/AcDream.App/Rendering/Shaders/sky.vert — lines 109-114, vFogFactor computation

Research: docs/research/2026-04-23-sky-fog.md. Partial; doesn't pin the sky-specific fog path.

Acceptance: At dusk in Holtburg, the sky dome shows a clear zenith and a warm fog-tinted horizon band that matches retail's appearance, with stars / moon / sun / clouds all still visible at their correct brightnesses elsewhere in the frame.


#5 — VitalsPanel stamina/mana bars always null (absolute values not stored)

Status: OPEN Severity: LOW (cosmetic — HP bar already works; stam/mana would be a nice-to-have) Filed: 2026-04-25 Component: ui / net / player-state

Description: Phase D.2a shipped VitalsVM with StaminaPercent / ManaPercent returning float? null. VitalsPanel already renders an HP progress bar from CombatState.GetHealthPercent(localGuid) because per-entity health is tracked from combat notifications. Stamina and mana are absolute values and only arrive in PlayerDescription (0x0013) — which we currently parse then discard. Result: the Vitals window shows HP only.

Root cause / status: We need a LocalPlayerState Core class (analogous to CombatState but scoped to the local player) that retains parsed PlayerDescription fields — at minimum: CurrentStamina + MaxStamina + CurrentMana + MaxMana. AppraiseInfoParser.CreatureProfile already has the shape for these values; we just don't persist them.

Files:

  • src/AcDream.Core.Net/Parsers/PlayerDescriptionParser.cs — parses then discards (verify path)
  • src/AcDream.Core.Net/Parsers/AppraiseInfoParser.cs — has CreatureProfile with absolute values
  • src/AcDream.UI.Abstractions/Panels/Vitals/VitalsVM.csStaminaPercent / ManaPercent would divide LocalPlayerState.Current* by Max*
  • src/AcDream.App/Rendering/GameWindow.cs — construct LocalPlayerState, hand to VitalsVM, wire into event dispatch

Research: none needed — wire-level field positions are already decoded in PlayerDescriptionParser.

Acceptance: With ACDREAM_DEVTOOLS=1, the Vitals window shows three progress bars (HP / Stamina / Mana) that update when the server sends PlayerDescription or any delta event (UpdateHealth, UpdateStamina, UpdateMana).


Recently closed

(none yet — move DONE items here with closed-date + commit SHA)