sky(phase-5a): remove DayGroup-name rain hack, ship retail-only Overcast mapping

User-observed regression 2026-04-23: acdream spawned rain particles
when retail showed no rain at the same server tick. Root cause: my
Phase 3e shortcut mapped DayGroup.Name = "Rainy" → WeatherKind.Rain →
rain particle emitter. That's not what retail does.

Parallel decompile research confirms:
- Agent A (2026-04-23-physicsscript.md): PhysicsScript runtime lives
  at FUN_0051bed0 → FUN_0051bfb0, runs per PhysicsObj; sky calls it
  from NOWHERE.
- Agent B (2026-04-23-sky-pes-wiring.md): FUN_00508010 (sky render
  loop) never reads SkyObject.DefaultPesObjectId — the field is dead
  at render time. Rain/snow particles in retail come from a separate
  camera-attached weather subsystem that has NOT yet been located.

So the correct behavior is: DayGroup name should only drive
fog/ambient tone (via keyframes, already in the Snapshot path),
never spawn particle emitters. Any retail-faithful particle rain
belongs to a future phase once we find the camera-attached weather
subsystem driver.

Change: MapDayGroupNameToKind now maps all weathery substrings
(storm/snow/rain/cloud/overcast/dark/fog) → Overcast — fog-only
visuals, no particle spawn. Clear names stay Clear. The Rain, Snow,
Storm enum values remain and are still accessible via ForceWeather()
for debug overrides.

Tests updated (WeatherSystemTests): the name→kind theory now expects
Overcast for Rainy/Snowy/Stormy variants.

Also commits the four research docs from this session's parallel
hunt: PhysicsScript dat+runtime, sky↔PES wiring (negative finding),
lightning timer (negative finding — agent #3), fog on sky
(positive: retail applies fog to sky geometry).

NOTE on lightning: agent #3's research only ruled out the CLIENT-SIDE
RANDOM TIMER hypothesis for lightning. User confirms retail does have
visible lightning + thunder. A follow-up agent (#5, in flight as of
this commit) is hunting the real mechanism — PlayScript opcode,
SetLight PhysicsScript hooks, AdminEnvirons side effects, or the
weather-volume draw. This commit does NOT attempt to port lightning.

Build + 733 tests green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-04-24 11:04:36 +02:00
parent d5e37694ed
commit 53608e77e3
6 changed files with 1508 additions and 20 deletions

View file

@ -101,21 +101,26 @@ public sealed class WeatherSystemTests
}
[Theory]
[InlineData("Sunny", WeatherKind.Clear)]
[InlineData("SUNNY", WeatherKind.Clear)]
[InlineData("Clear", WeatherKind.Clear)]
[InlineData("Cloudy", WeatherKind.Overcast)]
[InlineData("Overcast", WeatherKind.Overcast)]
[InlineData("Dark skies", WeatherKind.Overcast)]
[InlineData("Fog", WeatherKind.Overcast)]
[InlineData("Rainy", WeatherKind.Rain)]
[InlineData("heavy rain", WeatherKind.Rain)]
[InlineData("Snowy", WeatherKind.Snow)]
[InlineData("Blizzard", WeatherKind.Clear)] // no matcher — default
[InlineData("Stormy", WeatherKind.Storm)]
[InlineData("Thunderstorm", WeatherKind.Storm)] // "storm" wins over no match
[InlineData("", WeatherKind.Clear)]
[InlineData(null, WeatherKind.Clear)]
[InlineData("Sunny", WeatherKind.Clear)]
[InlineData("SUNNY", WeatherKind.Clear)]
[InlineData("Clear", WeatherKind.Clear)]
[InlineData("", WeatherKind.Clear)]
[InlineData(null, WeatherKind.Clear)]
// All "weathery" names map to Overcast. Retail does NOT spawn rain /
// snow / lightning from the DayGroup name — verified by the 2026-04-23
// PhysicsScript + sky-PES decompile audits (see WeatherState.cs). Any
// future particle rain must come from the camera-attached weather
// subsystem, NOT from name string matching.
[InlineData("Cloudy", WeatherKind.Overcast)]
[InlineData("Overcast", WeatherKind.Overcast)]
[InlineData("Dark skies", WeatherKind.Overcast)]
[InlineData("Fog", WeatherKind.Overcast)]
[InlineData("Rainy", WeatherKind.Overcast)]
[InlineData("heavy rain", WeatherKind.Overcast)]
[InlineData("Snowy", WeatherKind.Overcast)]
[InlineData("Blizzard", WeatherKind.Clear)] // no matcher — default
[InlineData("Stormy", WeatherKind.Overcast)]
[InlineData("Thunderstorm", WeatherKind.Overcast)]
public void SetKindFromDayGroupName_MapsRetailNames(string? name, WeatherKind expected)
{
var sys = new WeatherSystem();