Further match vanilla moon phases and visiblity times
Related to #8375 (closed)
With !4616 (merged) last year, moon phases and visibility times matched Morrowind.exe for all Vanilla and "reasonable" moon settings, but with two flaws:
- Extremely-high increment amounts (+- >12.0) broke the rise hours because of multiple rise hours per day.
- Negative increments mostly matched Vanilla, but cycle offsets were desynced.
I also wasn't happy with the cycle offset concept in general, because I couldn't find an explanation for its existence. It made the long-term calendar work, but it quickly fell apart in edge cases.
This time, I used my MWSE mod to produce CSV dumps (32 datasets for 64 different moons) and ran them through an LLM. I remember attempting to use AI after the last MR, but it was less than helpful. Now, better models were able to find patterns in some of the more extreme edge cases, and they stayed consistent with my research and unit tests.
This MR rewrites the moon logic with improvements:
- Instead of a cycle offset, the moons use a "handover hour", which represents the point in a day where the moon logic switches to the next day. I could see the pattern in the last MR, but couldn't find an algorithm for it because of other assumptions.
- The 24-day loop's handover and rise hours are calculated at moon creation, which saves a bit of math every frame.
- All daily increments both positive and negative are testing correctly.
- Negative speed results in no moon rise for Morrowind.exe parity.
- Moon speed is now affected by day length for Morrowind.exe parity.
- Moon size increases. Looks like 74260a9a was either wrong or became wrong over time. Dividing by 115 looks much closer than 125 with FOV set equally between games. I verified by overlaying screenshots in Gimp.
- New unit tests around some of the edge cases.
Otherwise, I didn't recreate Vanilla bugs mentioned in the previous MR for the same reasons. Notably, frozen phases when the moon is stuck in a visible state. It's also clear from the screenshots that the sky texture orientation is wrong in OpenMW, but that's not really in scope for this MR handled by !5636 (merged).
Screenshots
Taken by fast-forwarding Morrowind.exe several days to avoid the save-load and Day 1 bugs, then importing the saves with my launcher -> ESS Importer fork.
Vanilla
Morrowind 112 Horizontal FOV with MGEXE:
OpenMW (divided by 115) 90 Vertical FOV:
OpenMW (divided by 125, the size in master) 90 Vertical FOV:
Morrowind 91 Horizontal FOV with MGEXE:
OpenMW (divided by 115) 60 Vertical FOV:
Secunda_Speed,5.6 Masser_Daily_Increment,5
Secunda_Speed,2.6 Secunda_Daily_Increment,-2.1 Masser_Speed,2.5 Masser_Daily_Increment,-1
Sunrise_Time,11 Sunset_Time,12
Secunda_Speed,2.6 Secunda_Daily_Increment,12.1 Masser_Speed,2.5 Masser_Daily_Increment,12
Morrowind Dumps
I took these with my MWSE mod: MoonChecker.zip.
For each dataset I'd:
- Start a new game
tclinto the sky above the tutorial ship- Fast-forward time at 24000 scale and average ~360fps
This gave accuracy within +1-3 minutes of actual times. It's possible to get exact numbers by slowing the timescale just before the transition, but for large datasets I had the modeling take the threshold into account when validating the results.
Mapping:
- moonWithHalfDayIncrementShouldRiseAtTheSameHourEveryDay, moonWithHalfDayIncrementShouldSetAtTheSameHourEveryDay : File 1 Masser
- moonWithNegativeNonZeroIncrementRisesEarlierEachDay, moonWithNegativeNonZeroIncrementRisesEarlierEachDay, moonWithNegativeIncrementPhasesWaxingCrescentToFirstQuarter : File 1 Secunda
- moonWithNegativeIncrementPhasesThirdQuarterToWaningCrescent : File 2 Secunda
- moonWithLargeIncrementSkipsTheDayItsRiseHourReachesMidnight : File 2 Masser
- moonHandsOverBehindTheDaytimeFadeBeforeSunrise : File 7 Masser
- moonWaitsToHandOverUntilItSetsAfterSunrise : File 7 Secunda
- moonPhaseTurnsOverWithTheRiseHour : File 6 Masser
- moonCrossesTheSkyAtAMultipleOfDayLength : File 13 Secunda
- moonHandsOverBehindTheDaytimeFadeBeforeALaterSunrise : File 14 Masser
- moonSlowerThanTheMinimumCrossesTheSkyAtTheMinimumRate : File 12 Masser
- moonWithNegativeSpeedNeverRises : File 19 Secunda
- moonWithZeroSpeedRisesAtMinimumButNegativeZeroSpeedDoesNot : File 21 and 23 Masser
- moonWithEarlyFadeAngleGreaterThanFadeEndAngleIsNeverInvisible : File 24 Secunda
- moonAtTheHorizonIsInvisibleWithEarlyFadeAngleEqualToFadeEndAngle : File 22 Masser- I have read the CONTRIBUTING guidelines
- My code runs locally
- My code passes CI on my fork












