fix #28: port retail's sky default-script playback (aurora) and the particle facing law
The aurora was never missing data — it was a missing mechanism plus a misread. New decompile evidence closes the April-2026 contradiction: retail plays the sky carriers' PES through the Setup's own DefaultScript (GameSky::MakeObject @0x00506EE0 -> CPhysicsObj::makeObject @0x00513970 sets state|=0x80000; animate_static_object @0x00513DF0 ticks ScriptManager + ParticleManager). The pes_id column stays dead — that half of the April finding stands; the ids are byte-equal mirrors. - SkyPesFrameController is now the production owner (ACDREAM_ENABLE_SKY_PES deleted): script ids resolve from the Setup DefaultScript (SkyObjectData.DefaultScriptId; the pes_id column is a one-time-logged cross-check), slots persist by (index, gfx id, properties) per CreateDeletePhysicsObjects @0x005073C0 — a day-group swap keeping the carrier no longer restarts its emitters — and stale slots stop before replacements claim the slot-derived owner id. - RetailParticleFacing ports calc_draw_frame @0x0050DFA0: degrade mode 2 faces the viewer roll-free (set_vector_heading) instead of the camera plane; modes 3/4/5 spin the authored frame around one local axis (rotate_around_axis_to_vector) — Dereth authors 54 mode-5 emitters that previously got no facing at all; 1,583 mode-2 emitters get the exact law; authored/mode-1 paths are unchanged. - The 2026-08-23 'whole-sky tint' was the Rainy-group lightning/thunder PES playing at the debug anchor inside their 0.03-0.19 window, not the aurora: the aurora is nine faint viewer-facing glows pulsing on 6.7/15/55-minute rebirth cycles, in every day group, all day. Research: docs/research/2026-08-23-sky-default-script-port.md. Register: AD-112 filed (camera-anchored synthetic owners vs sky-cell physics objects). ISSUES #2 corrected (the playback ban is lifted by the new evidence); #28 fix landed pending the connected night gate. Tests: RetailParticleFacingTests (16), SkyPesFrameControllerTests (6); hermetic suites App 6,076/0, Core 4,905/0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
6f47740af0
commit
18fce7bb5a
13 changed files with 906 additions and 113 deletions
|
|
@ -38,6 +38,22 @@ public sealed class SkyObjectData
|
|||
public uint PesObjectId;
|
||||
public uint Properties;
|
||||
|
||||
/// <summary>
|
||||
/// The carrier Setup's own <c>DefaultScript</c> PES id (zero when the
|
||||
/// gfx id is not a Setup or the Setup has none). This — not
|
||||
/// <see cref="PesObjectId"/> — is what retail plays: a Setup with a
|
||||
/// default script marks its physics object <c>state |= 0x80000</c>
|
||||
/// (<c>CPhysicsObj::makeObject @0x00513970</c> →
|
||||
/// <c>InitPartArrayObject</c>) and the static-animating tick
|
||||
/// (<c>CPhysicsObj::animate_static_object @0x00513DF0</c>) drives
|
||||
/// <c>ScriptManager::UpdateScripts</c> + the object's ParticleManager.
|
||||
/// In Dereth's Region DAT the two ids are byte-equal for every sky
|
||||
/// carrier (verified 2026-08-23); the dead <c>pes_id</c> column stays
|
||||
/// parsed as a cross-check only. Full chain:
|
||||
/// <c>docs/research/2026-08-23-sky-default-script-port.md</c>.
|
||||
/// </summary>
|
||||
public uint DefaultScriptId;
|
||||
|
||||
/// <summary>
|
||||
/// Source GfxObj sort centre. Celestial billboards are authored at their
|
||||
/// apparent direction from the camera, so transforming and normalizing
|
||||
|
|
@ -525,11 +541,40 @@ public static class SkyDescLoader
|
|||
GfxObjId = s.DefaultGfxObjectId?.DataId ?? 0u,
|
||||
PesObjectId = s.DefaultPesObjectId?.DataId ?? 0u,
|
||||
Properties = s.Properties,
|
||||
DefaultScriptId = ResolveSetupDefaultScript(
|
||||
s.DefaultGfxObjectId?.DataId ?? 0u,
|
||||
dats),
|
||||
AuthoredSortCenter = ResolveSortCenter(
|
||||
s.DefaultGfxObjectId?.DataId ?? 0u,
|
||||
dats),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Fetches a sky carrier Setup's <c>DefaultScript</c> id (the retail
|
||||
/// sky-PES source — see <see cref="SkyObjectData.DefaultScriptId"/>).
|
||||
/// Non-Setup ids (the dome, star layers, cloud sheets are raw GfxObjs)
|
||||
/// and missing DATs resolve to zero.
|
||||
/// </summary>
|
||||
private static uint ResolveSetupDefaultScript(
|
||||
uint gfxObjId,
|
||||
IDatObjectSource? dats)
|
||||
{
|
||||
if (dats is null || (gfxObjId & 0xFF000000u) != 0x02000000u)
|
||||
return 0u;
|
||||
|
||||
try
|
||||
{
|
||||
return dats.TryGet<Setup>(gfxObjId, out var setup) && setup is not null
|
||||
? setup.DefaultScript.DataId
|
||||
: 0u;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Enhancement metadata cannot make authoritative sky loading fail.
|
||||
return 0u;
|
||||
}
|
||||
}
|
||||
|
||||
private static DatSkyKeyframeData ConvertTimeOfDay(
|
||||
SkyTimeOfDay s,
|
||||
IDatObjectSource? dats)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue