fix(render): rain draws only while the player stands outside

The owner''s seam report (rain in the 0xF4180104/0xF4180101 crossing
strip where retail has none) led straight to retail''s actual rain
confinement, which is neither depth nor view clipping:
GameSky::Draw @0x00506ff0 gates its WEATHER pass (arg2==1) on
SmartBox::is_player_outside @0x00451e80 - Ghidra-arbitrated (BN''s
body was flag-idiom mush): (player objcell_id & 0xFFFF) < 0x100. The
sky pass always draws; rain draws ONLY while the PLAYER is in an
outdoor cell. One boolean - rain on the ledges, none the instant the
player crosses into an interior cell. Retail also runs the sky/weather
draw at DEPTHTEST_ALWAYS write-off (pc 0x00507063), confirming our
depth-disabled weather port; the missing piece was only this gate,
now applied at the executor''s weather site from the frame''s
PlayerCellId.

Hermetic 6,762/0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-30 21:39:28 +02:00
parent 24477896bf
commit 75eab42f3c

View file

@ -470,7 +470,16 @@ internal sealed partial class RetailPViewPassExecutor :
// DrawLandscapeStaticParticles after the slice loop (retail: one
// unclipped alpha-list insertion per emitter), not per slice here.
EnableClipDistances();
if (frame.RenderSky && frame.RenderWeather)
// Retail GameSky::Draw @0x00506ff0 gates the WEATHER pass (arg2==1)
// on SmartBox::is_player_outside @0x00451e80 — Ghidra-arbitrated:
// (player objcell_id & 0xFFFF) < 0x100. The sky pass always draws;
// the rain draws ONLY while the PLAYER stands in an outdoor cell.
// That one boolean is retail's entire rain confinement (the
// owner-reported indoor/seam rain at the cathedral: rain on the
// ledges, none the instant the player crosses into an interior
// cell) — no depth or view-clip mechanism is involved.
bool playerOutside = (frame.PlayerCellId & 0xFFFFu) < 0x100u;
if (frame.RenderSky && frame.RenderWeather && playerOutside)
{
_sky?.RenderWeather(
frame.Camera,