Developer
Overview
ml_climaticvitals has client exports for reading temperature data and toggling the system, plus open/ folder with empty OpenClient/OpenServer tables reserved for your own code. Vehicle climate state syncs via entity StateBags. Server-side: temperature calculation, weather sync, DB persistence, item confirmation (zero-trust, server computes all damage/stat values, never trusts client).
Client Exports
Temperature Data
GetPerceivedTemperature(): Returns the current perceived temperature (number, Celsius). Includes all modifiersGetCurrentTemperature(): Returns the current ambient/server temperature (number, Celsius). Raw weather-based valueGetState(): Returns a table with the full system state:
1{
2 perceived = 22.0, -- Perceived temperature (Celsius)
3 current = 20.0, -- Ambient temperature (Celsius)
4 weather = 'CLEAR', -- Current weather type string
5 nearHeat = false, -- Near a heat/cold source object
6 inVehicle = false, -- In a vehicle with insulation
7 inInterior = false, -- Inside an MLO/interior
8 wetness = 0.0, -- Wetness level (0.0 to 1.0)
9 itemBuff = 0.0, -- Active item buff modifier
10}UI Control
hideweatherhud(hide): Hide or show the temperature HUD widget.true= hide,false= show. Blocked whenConfig.ForceShowWidget = trueHideUi(shouldHide): Alias forhideweatherhudOpenClimateMenu(): Opens the vehicle climate control UI. Only works in a valid vehicle with the engine running
System Control
SetClimaticState(state): Enable or disable the entire system.true= active,false= paused. When paused: HUD hides, visual effects clear, damage stops, temperature updates stop
Buffs
ApplyBuff(buffAmount, durationMinutes): Apply a local temperature buff.buffAmountis degrees (positive = warm, negative = cool),durationMinutesis duration in minutes. Client-side only, does not sync to server
StateBags
Vehicle Climate State
Climate control state is stored on the vehicle entity:
1Entity(vehicle).state.climateState = {
2 on = true, -- Climate system on/off
3 temp = 21.0, -- Target temperature
4 fan = 1, -- Fan speed level (0-3)
5 mode = 'auto' -- 'auto', 'heat', or 'ac'
6}All vehicle occupants read this StateBag. The driver sends updates to the server via ml_climaticvitals:server:updateClimateState. The server validates: entity existence, player proximity (10 units), data types, and clamps temp/fan/mode to valid ranges before writing the StateBag.
Server Events
ml_climaticvitals:getInitialTemperature: Client requests current temperature on joinml_climaticvitals:server:setWeather: Weather reporter client sends the current weather name. Accepted only from the assigned reporterml_climaticvitals:server:updateClimateState: Client sends vehicle climate changes. Server validates before writing StateBagml_climaticvitals:server:ApplyStatusDamage: Client sends condition string ('hot'/'cold'). Server computes actual hunger/thirst values from config and applies them viaBridge.SetHunger/Bridge.SetThirst. Rate-limited to 10 seconds per playerml_climaticvitals:server:confirmItemUse: Client confirms item consumption after progress bar completes. Server verifies inventory, removes 1 item, applies buff via client event. Protected withGetInvokingResource()check
Client Events
ml_climaticvitals:updateTemperature: Server broadcasts ambient temperature and weather typeml_climaticvitals:client:setAsWeatherReporter: Server assigns a client as weather reporterml_climaticvitals:client:useItem: Server triggers item consumption flow. Client shows progress bar, then confirms back to serverml_climaticvitals:client:applyBuff: Server applies a buff after item confirmation. ReceivesbuffAmountanddurationMsml_climaticvitals:client:notifyItemBuff: Server sends item notification after confirmationml_climaticvitals:client:playerReady: Internal event fired when the player is fully loaded
All RegisterNetEvent handlers include GetInvokingResource() checks to prevent server-side event spoofing.
Temperature Calculation
The perceived temperature formula:
1basePerceived = ambient
2 + zoneModifier
3 + clothesThermalBonus
4 + temperatureObjectBonus
5 + vehicleClimateModifier
6 + vehicleInsulationBonus
7 + nightTimeMalus (-4 between 21:00-06:00)
8 + wetnessMalus (wetness * Config.Wetness.TemperatureMalus)
9 + waterMalus (Config.PlayerOnWater.TempMalus when swimming)
10 + itemBuff
11
12interiorMod = (Config.InteriorBonus.targetTemp - basePerceived) * Config.InteriorBonus.strength
13
14perceived = basePerceived + interiorModThe interior mod pulls perceived temp towards targetTemp: warms you if it's cold, cools you if it's hot.
Weather Reporter System
One client is designated as the weather reporter and polls GetPrevWeatherTypeHashName() every 5 seconds. When the reporter disconnects, the server reassigns after 1 second. Only the assigned reporter's weather updates are accepted.
Item Use Flow
- Server registers all
Config.ItemBuffsitems as usable viaBridge.BindUsableItem - Player uses item → server checks
Bridge.HasItem→ triggersml_climaticvitals:client:useItem - Client shows
lib.progressBarwith animation/prop - On progress bar completion → client triggers
ml_climaticvitals:server:confirmItemUse - Server re-checks
Bridge.HasItem, removes 1 item, triggers buff on client
Item is removed server-side only after client confirms progress bar completion. Cancelling the progress bar does not remove the item.
Examples
1-- Client-side
2local state = exports.ml_climaticvitals:GetState()
3print(('Perceived: %.1f, Weather: %s, Wetness: %.0f%%'):format(
4 state.perceived, state.weather, state.wetness * 100
5))1-- Client-side
2exports.ml_climaticvitals:hideweatherhud(true) -- hide
3exports.ml_climaticvitals:hideweatherhud(false) -- show1-- Client-side
2exports.ml_climaticvitals:SetClimaticState(false) -- pause
3-- ...minigame logic...
4exports.ml_climaticvitals:SetClimaticState(true) -- resume1-- Client-side: cool the local player by 10 degrees for 5 minutes
2exports.ml_climaticvitals:ApplyBuff(-10.0, 5)