Skip to content

Day Night Cycle

widberg edited this page Jul 6, 2026 · 2 revisions

Time Progression

Under normal time progression, the formula is day_time_in_seconds = unpaused_time_ms * 0.001 * pp371 + 28800.0. unpaused_time_ms only ticks up when the game isn't paused. 28800 seconds is 8 hours; they add this offset so you don't spawn in at midnight every time you open the game. And pp371 is PutParameter 371, it's a timescale, which is 96. This means a full 24 hours of in-game time is 15 minutes of real time. You can tweak pp371 to make days longer or shorter. As a side note, day_time_in_seconds seems highly online play related and is stored in big endian for that reason, no idea what's up with that. I get that the host needs to share the day time to keep everyone's world looking the same, but they don't need to do all the weird stuff just for that.

Cycle

During the day, headlights are off, things cast shadows, and the sun is in the sky. Night is when it isn't day. At night, headlights are on, nothing casts shadows, and the moon is in the sky. They each have different shaders, and you may notice a frame hitch during the transition as the shaders load, especially if you are using the DisableShaderCompile command. During the transition, the sun is replaced with the moon, visually only; it is the same object. The sun basically bounces off the horizon when it becomes the moon. It moves east to west as expected. Whether it is nighttime or not is decided by the following function:

// 00640830
bool IsNightTime(float day_time_in_seconds)
{
    const float SECONDS_PER_DAY = 86400.0f;
    const float NIGHT_START = 77400.0f; // 21:30
    const float NIGHT_END = 23400.0f;   // 06:30

    // Convert to days and discard the whole-day portion.
    float days = day_time_in_seconds / SECONDS_PER_DAY;
    float timeOfDay = (days - (int)days) * SECONDS_PER_DAY;

    return (timeOfDay < NIGHT_END) ||
           (timeOfDay >= NIGHT_START);
}

Time Overrides

ForceDayTime sets an override time to use; it takes a time argument in the form of hours.minutes, confusing. The override time is stored at 00A022C0 as a u32 in seconds; if it's <= 86399 (0 to 86399 seconds is a full 24 hours) then that value is used over all other sources. MakeFlyVideo, known from the VIDGMPL.bik page, also sets this override time, but directly, not using the command. The Debug Tools HUD also exposes this override. The AddMissionParam time overrides seem to use a different mechanism. All the various time sources seem to get decided on in the function at 005B89E0. The precedence is basically normal time progression, race time, then override time.

Home
FAQ

For FMTK Users and Mod Developers

Read the Docs

For FMTK Developers

Asobo BigFile Format Specification
Asobo Classes
      Animation_Z
      Binary_Z
      Bitmap_Z
      Camera_Z
      CollisionVol_Z
      Fonts_Z
      GameObj_Z
      GenWorld_Z
      GwRoad_Z
      Keyframer*_Z
      Light_Z
      LightData_Z
      Lod_Z
      LodData_Z
      Material_Z
      MaterialAnim_Z
      MaterialObj_Z
      Mesh_Z
      MeshData_Z
      Node_Z
      Omni_Z
      Particles_Z
      ParticlesData_Z
      RotShape_Z
      RotShapeData_Z
      Rtc_Z
      Skel_Z
      Skin_Z
      Sound_Z
      Spline_Z
      SplineGraph_Z
      Surface_Z
      SurfaceDatas_Z
      UserDefine_Z
      Warp_Z
      World_Z
      WorldRef_Z
Asobo File Format Idioms
Asobo CRC32
Asobo LZ Compression
Asobo Arithmetic Coding Compression
Asobo Save Game File Format Specification
Asobo Audio Formats
TotemTech/ToonTech/Zouna/ACE/BSSTech/Opal Timeline
Zouna Modding Resources
Miscellaneous

Clone this wiki locally