EndCore Framework

en-weathersync

Server-owned time, weighted weather cycles and ambient temperature that pushes survivors' body temperature up or down.

en-weathersync owns the clock, the weather and the ambient temperature for the whole server. Time runs at GTA's pace by default (2 real seconds per in-game minute), but nights pass slower, and both time and weather survive restarts.

Weather follows a weighted cycle: each type lists what it can turn into. A weather lasts 15-35 real minutes with a 45 second blend, and snow is off by default. Each weather has a base temperature, and ambient temperature swings with time of day (warmest at 15:00, coldest at 03:00) and drops with altitude. On every survival tick, survivors outside the comfort band get colder or hotter: shelter (interiors and vehicles) cuts exposure, rain and water chill you, clothing warmth protects against cold but makes heat worse, and nearby heat sources warm you up.

At a glance

Depends on/onesync, en-core
Used byen-zombies (night multiplier, weather sight), en-admin (World tab), en-hud (temperature via en-core metadata)
Start beforeResources that read its GlobalState keys (they fall back gracefully if the keys are missing)
Database tablesNone. State is saved to server KVP key state every 60 s and on stop
Config filesconfig/shared.lua

How it works

Time

The server advances the clock by secondsPerMinute, scaled by nightPace during nightHours, and publishes GlobalState.gameHour and gameMinute. Clients apply the state bags through change handlers.

Weather

When a weather's duration ends, the next type is picked from its next weights. Snow types (SNOWLIGHT, SNOW, BLIZZARD, XMAS) only join the cycle when Config.weather.snow is true. Clients re-assert the current weather every 5 seconds.

Body temperature

Every Config.temperature.interval ms, for each loaded player:

  1. Ambient temperature is the weather's base temperature, plus the day swing, minus altitudeLapse per metre of height.
  2. Past the comfort band, body temperature is pulled by coldRate or heatRate per degree, capped at maxPull per tick.
  3. Shelter multiplies exposure by shelter. Being soaked in rain or in water removes extra degrees. nearHeat adds heatSource degrees.
  4. Clothing warmth (0-1, from en-clothing) protects against cold and makes heat worse.

The result is written with en-core's SetTemperature. See Survival system for what body temperature does to a player.

Configuration

config/shared.lua.

Time and weather

KeyDefaultWhat it does
Config.time.startHour / startMinute8 / 0Clock on a fresh server
Config.time.secondsPerMinute2.0Real seconds per game minute (a 48 minute day)
Config.time.nightPace0.8Night speed multiplier (below 1 = longer nights)
Config.time.nightHours{ from = 20, to = 6 }What counts as night
Config.time.persisttrueResume the clock after a restart
Config.weather.start'CLOUDS'Weather on a fresh server
Config.weather.persisttrueResume the weather after a restart
Config.weather.duration{ min = 15, max = 35 }Real minutes per weather
Config.weather.transition45.0 sBlend time
Config.weather.snowfalseAllow snow types in the cycle
Config.weather.types.<NAME>14 GTA weather types{ temp (°F), wind, wet?, snow?, next = { TYPE = weight } }

Example base temperatures: EXTRASUNNY 90°F, CLEAR 82, CLOUDS 72, OVERCAST 64, FOGGY 60, RAIN 56 (wet), THUNDER 52 (wet, wind 8), SNOW 22, BLIZZARD 6.

Temperature

KeyDefaultWhat it does
Config.temperature.enabledtrueBody temperature exposure on or off
Config.temperature.interval60000 msShould match en-core's survival tickInterval
Config.temperature.daySwing12 °FAfternoon high and pre-dawn low offset
Config.temperature.altitudeLapse0.012°F lost per metre of altitude
Config.temperature.comfort{ low = 58, high = 90 } °FAmbient band with no effect
Config.temperature.coldRate / heatRate0.03 / 0.025Body °F per ambient °F past the comfort band
Config.temperature.maxPull2.0Max body °F change per tick
Config.temperature.shelter0.2Exposure multiplier indoors or in a vehicle
Config.temperature.rain / water0.35 / 1.2Extra body °F lost per tick when soaked or in water
Config.temperature.heatSource1.2Body °F gained per tick with nearHeat

A winter server with long nights and snow in the cycle:

lua
-- config/shared.lua
Config.time.secondsPerMinute = 3.0
Config.time.nightPace = 0.6
Config.weather.start = 'SNOWLIGHT'
Config.weather.snow = true
Config.temperature.comfort = { low = 62, high = 90 }

Exports

Server

ExportArgumentsReturns
SetWeathername, minutes?boolean. Holds for minutes, otherwise a random duration
GetWeatherWeather name
SetTimehour, minute? (0-23, 0-59)boolean
GetTimehour, minute
FreezeTimefrozenStop or start the clock
FreezeWeatherfrozenStop or start the weather cycle
SetBlackoutonCity lights off or on
IsBlackoutboolean
IsNightboolean
GetAmbientTemperaturecoords?°F at coords.z (sea level if nil)

Client

ExportArgumentsReturns
SetSyncEnabledenabledStop or resume following the server (for scenes with their own lighting)
SetOverride{ weather?, hour?, minute? }Force weather or time for this client only; the local clock pauses while set
ClearOverride
GetWeatherGlobalState.weather
GetTimeGlobalState.gameHour, GlobalState.gameMinute
GetAmbientTemperatureGlobalState.ambientTemperature (sea level, rounded)

Commands

All restricted to group.admin.

CommandWhat it does
/weather <type> [minutes]Set the weather, optionally holding it
/time <hour> [minute]Set the clock
/freezetime [on|off]Freeze the clock; no argument toggles
/freezeweather [on|off]Freeze the weather cycle
/blackout [on|off]Turn city lights off or on

The same controls are in the World tab of en-admin.

Events

EventSidePayload
en-weathersync:server:weatherChangedServer localnewName, previousName
en-weathersync:server:blackoutChangedServer localon

State bags

Global state published by the server:

KeyValue
GlobalState.gameHour / gameMinuteCurrent game time
GlobalState.weatherWeather name
GlobalState.blackoutboolean
GlobalState.timeFrozenboolean
GlobalState.ambientTemperatureSea-level °F, updated every 30 s

Player state read by the temperature system:

KeySet byValue
exposureen-weathersync's own client, every 3 s on change{ sheltered, water }
warmthen-clothing0-1
nearHeatOther resources, such as a campfireboolean

Examples

A campfire that warms whoever stands near it:

lua
-- server
RegisterNetEvent('my-camp:nearFire', function(isNear)
    Player(source).state:set('nearHeat', isNear == true, true)
end)

A night storm event:

lua
-- server
exports['en-weathersync']:SetWeather('THUNDER', 20)
if exports['en-weathersync']:IsNight() then
    exports['en-weathersync']:SetBlackout(true)
end

AddEventHandler('en-weathersync:server:weatherChanged', function(newName, previousName)
    if previousName == 'THUNDER' then
        exports['en-weathersync']:SetBlackout(false)
    end
end)

A cutscene at noon in clear weather for one player:

lua
-- client
exports['en-weathersync']:SetOverride({ weather = 'EXTRASUNNY', hour = 12, minute = 0 })
-- ... scene ...
exports['en-weathersync']:ClearOverride()