Developer
Overview
Server and client exports plus open event hooks for integrating with ML HealthSystem. The integration surface lives in the open/ folder: open/server/handlers.lua, open/client/handlers.lua, and the radiation_connector.lua files. These are escrow-ignored (plain source) and can be edited without touching the core system.
Live medical state (death state, diseases, injuries, life points) replicates to clients in real time. Persistence uses three database tables: ml_healthsystem (per-identifier JSON health blob), ml_lifepoints (life points), ml_health_tents (placed respawn tents). All three are created automatically on first start.
The death, last stand, and respawn events only fire when enabled in shared/config/open.lua (Config.OpenHandlers). All three default to true.
Server Exports
Disease Management
1exports.ml_healthsystem:AddDisease(source, diseaseName)AddDisease(source, diseaseName): Infects a player with a disease defined inConfig.Diseases. Returnstrueon success,falseif the disease key does not exist or is already active.
1exports.ml_healthsystem:CureDiseaseForce(source, diseaseName)CureDiseaseForce(source, diseaseName): Force-cures a specific disease, bypassingmaxCurableStagechecks. Returnstrueif cured.
1exports.ml_healthsystem:CureAllDiseases(source)CureAllDiseases(source): Removes all active diseases from a player.
Pass the disease key, not the label. The six shipped defaults are influenza, patogeno_vx_9, radiazioni, infezione, intossicazione, tetano (defined in shared/config/diseases.lua). Keys change if the list is edited.
Revive and Death
1exports.ml_healthsystem:RevivePlayer(source)RevivePlayer(source): Fully revives a player and resets medical stats. Returnstrueon success.
1exports.ml_healthsystem:SetDeathSystemDisabled(source, isDisabled)SetDeathSystemDisabled(source, isDisabled): Disables or re-enables the death system for one player. Use for cutscenes or safe zones.
1exports.ml_healthsystem:SetDeathReason(source, reason)SetDeathReason(source, reason): Sets a custom death reason string (max 64 chars) consumed on the player's next death. The reason feedsConfig.LifePoints.ExternalReasonspenalty matching. Calls from outside the resource are gated to an allowlist (ml_radiation,ml_climaticvitals); foreign resources are rejected.
Field Treatment
1exports.ml_healthsystem:ApplyTempBandage(source)ApplyTempBandage(source, duration, previousBleedLevel): Applies a temporary bandage that stops bleeding for duration seconds, then restores the previous bleed level.
1exports.ml_healthsystem:AddBloodRegenBuff(source)AddBloodRegenBuff(source, durationSeconds): Applies a blood regeneration boost.
Life Points
Life points only respond when Config.LifePoints.Enabled = true (server/config_server.lua). When disabled, the getters return -1 and the mutators return false.
1exports.ml_healthsystem:GetLifePoints(source)GetLifePoints(source): Returns the player's current life points (reads/creates theml_lifepointsrow). Returns-1if the system is disabled.
1exports.ml_healthsystem:GetLifePointsMax(source)GetLifePointsMax(): Returns the maximum (Config.LifePoints.StartingPoints). Returns-1if disabled.
1exports.ml_healthsystem:IsLifePointsEnabled()IsLifePointsEnabled(): Returnstrueif the life points system is active.
1exports.ml_healthsystem:SetLifePoints(source, value)SetLifePoints(source, value): Sets a player's life points to an exact value, clamped to[MinPoints, StartingPoints]. Returnstrueon success.
1exports.ml_healthsystem:AddLifePoints(source, amount)AddLifePoints(source, amount): Adds life points (clamped to max). Returnstrueon success.
1exports.ml_healthsystem:RemoveLifePoints(source, amount)RemoveLifePoints(source, amount): Removes life points (clamped to min). Returnstrueon success.
SetLifePoints, AddLifePoints, and RemoveLifePoints are gated by CanMutateLifePoints. Internal calls pass. External resources pass only if listed in Config.LifePoints.ExportAllowlist; if that list is empty, a non-staff player context is blocked. Add the calling resource to the allowlist before relying on these from another script.
Spawn Points and Tents
1exports.ml_healthsystem:GetSpawnPoints()GetSpawnPoints(): Returns the configured spawn table (Config.StartSpawnfromshared/config/respawn.lua).
1exports.ml_healthsystem:GetTentCoordsById(tentId)GetTentCoordsById(tentId): Returnsx, y, z, heading, ownerfor a placed tent fromml_health_tents.
Buffs
1exports.ml_healthsystem:GetActiveBuffs(source)GetActiveBuffs(source): Returns the active temporary buffs (regen boosts, temp bandages) for a player.
Client Exports
Disease Management
1exports.ml_healthsystem:HasDisease(diseaseName)HasDisease(diseaseName): Returnstrueif the local player has the disease (reads themedical:diseaseslive state).
1exports.ml_healthsystem:GetActiveDiseases()GetActiveDiseases(): Returns the table of active diseases on the local player.
1exports.ml_healthsystem:AddDisease(diseaseName)AddDisease(diseaseName): Requests the server to infect the local player.
The client AddDisease and Revive exports are staff-only. To infect or revive a player from a server resource, call exports.ml_healthsystem:AddDisease(src, name) and exports.ml_healthsystem:RevivePlayer(src). Curing is handled by the cure item.
Death and Revive
1exports.ml_healthsystem:isDead()isDead(): Returnstrueif the local player is dead or in last stand.
1exports.ml_healthsystem:Revive()Revive(): Requests a self-revive from the server (staff-gated server-side).
1exports.ml_healthsystem:SetDeathDisabled(disabled)SetDeathDisabled(disabled): Sets the localdisableDeathSystemlive state.
System State
1exports.ml_healthsystem:isSystemReady()isSystemReady(): Returnstrueonce the medical system has initialized.
Damage and Combat
1exports.ml_healthsystem:GetLastDamageData()GetLastDamageData(): Returns the last damage context:weaponHash,weaponClass,attackerId,bodyPart,attackerModel,timestamp.weaponClassdefaults to'UNKNOWN'andbodyPartto'chest'when no context exists.
1exports.ml_healthsystem:BuildDeathData()BuildDeathData(): Builds a death object from the last damage event:weaponHash,weaponClass,attackerId,isPlayerKill,bodyPart,cause,timestamp.causeis derived fromweaponClass(gunshot, explosion, stabbing, fall, burn, etc.).
1exports.ml_healthsystem:ApplyWound(part, amount, weaponClass)ApplyWound(part?, amount?, weaponClass?): applies a body-part wound to the calling player through the full damage pipeline, so bleeding, severity and the scan panel all react.partis a body zone like'left_leg', or'random'to pick one.amountdefaults to15,weaponClassoverrides the wound type. Returnstruewhen a wound landed. Call it on the victim's client from an external damage source such as a zombie script.
Life Points (Client)
1exports.ml_healthsystem:GetLifePoints()GetLifePoints(): Returns the local player's life points from thelifepointslive state. Returns-1if disabled.
1exports.ml_healthsystem:GetLifePointsMax()GetLifePointsMax(): ReturnsConfig.LifePoints.StartingPoints. Returns-1if disabled.
1exports.ml_healthsystem:IsLifePointsEnabled()IsLifePointsEnabled(): Returnstrueif the life points system is active.
Tent (Client)
1exports.ml_healthsystem:GetPlayerTentClient()GetPlayerTentClient(): Returns the local player's tracked tent data on the client.
Server Handlers
Located in open/server/handlers.lua. The death and respawn events fire only when the matching Config.OpenHandlers toggle is enabled in shared/config/open.lua.
Death Handler
1RegisterNetEvent('ml_healthsystem:server:onPlayerDeath', function(_clientData)
2 if GetInvokingResource() then return end
3 local src = source
4 -- deathData rebuilt server-side, NOT taken from _clientData
5end)The original client payload is discarded. deathData is rebuilt from PlayerDeathContext (populated server-side with strict validation) plus the deathState live state. Fields weaponHash, weaponClass, bodyPart, isPlayerKill, attackerId, attackerModel, deathReason, deathZone, cause, and coords are all server-validated and safe for authoritative actions (permadeath, money, database logging). The event is rate-limited and rejects foreign-resource triggers.
Respawn Handler
1RegisterNetEvent('ml_healthsystem:server:onPlayerRespawned', function(_clientCoords, _clientSpawnType)
2 if GetInvokingResource() then return end
3 local src = source
4 -- spawnType is whitelisted; coords recalculated from the server ped
5end)spawnType is validated against hospital, bed, tent, random, last_position (anything else becomes 'unknown'). Coordinates are recomputed server-side from GetEntityCoords(GetPlayerPed(src)), so the client-sent coords cannot teleport-spoof.
Hunger/Thirst Reset
1RegisterNetEvent('ml_healthsystem:server:ResetHungerThirst', function()
2 -- Uses Bridge.SetHunger, Bridge.SetThirst, Bridge.RemoveStress
3end)Fired automatically on revive. Permission is granted one-time per revive cycle (reviveResetAllowed) with a 5-second cooldown, and only applies while deathState == 'alive'. Uses the ml_bridge API for cross-framework compatibility.
Item-to-Disease Wiring
open/server/handlers.lua also listens to ox_inventory:usedItem and rolls the infection chance defined in shared/config/item_diseases.lua (Config.ItemDiseases). Add a "this food makes you sick" entry there; no handler edits needed. Downed and dead players are skipped.
Client Handlers
Located in open/client/handlers.lua.
Death Event
1AddEventHandler('ml_healthsystem:onPlayerDeath', function(deathData)
2 -- Fires when the local player dies (if Config.OpenHandlers.EnableDeathEvent)
3end)Last Stand Event
1AddEventHandler('ml_healthsystem:onPlayerLastStand', function(damageData)
2 -- Fires when the local player enters last stand (if EnableLastStandEvent)
3end)The radiation bridge lives in open/client/radiation_connector.lua and open/server/radiation_connector.lua; both early-return unless Config.RadiationIntegration.Enabled and ml_radiation are present. The client connector is passive (debug logging only); all infect/cure logic is server-side.
Configuration
The configuration is split by domain across shared/config/*.lua plus server/config_server.lua. The shared/config.lua file is only the index header; the real values live in the per-domain files below.
core.lua:Config.Debug,Config.Locale,Config.Theme,Config.DisableHealthRegenvitals.lua: blood, bandages, armor, wound levels, blood trails, cast durationbodyparts.lua: the nine body parts (armor, fracture, cast)diseases.lua: diseases and stages (customer-editable)items.lua:Config.MedicalItems(customer-editable) andConfig.XpCooldownSecondsanim_presets.lua: animation presets reused by itemsmasks.lua: protective masks (customer-editable)fractures.lua: fracture model wiringweapons.lua: weapon-class wound profiles, weapon→class map, body-part health thresholdsrespawn.lua:Config.RespawnSettings,Config.StartSpawn,Config.HrsBase,Config.RespawnTentlifecycle.lua: last stand and death tuningeffects.lua: visual effects, voice,Config.Flare, vehicle crash, NPC interactionui.lua: scan UI, medical jobs, commandsintegrations.lua: radiation integration, contact infection, andConfig.LifePoints.Zonesitem_diseases.lua:Config.ItemDiseases(food/item → disease wiring)security.lua:Config.AntiBunnyHopopen.lua:Config.OpenHandlersevent togglesserver/config_server.lua: server-only settings: Discord logging,Config.LifePoints(enabled, penalties, allowlist), inventory wipe, revive/hospital reset
Diseases, items, and masks are shipped as defaults and are fully customer-editable: add, remove, or modify entries in their config file freely. The escrowed internal/balance/*.lua files (performance throttles, damage control, blood-group probabilities, weapon penalties, anti-bunny-hop sensitivity presets, body-part balance) are encrypted and cannot be edited; the customer-facing anti-bunny-hop knob is in security.lua:
1Config.AntiBunnyHop = {
2 Enabled = true,
3 Sensitivity = 'medium', -- 'low' | 'medium' | 'high' | 'extreme'
4 Notify = true,
5 Message = "Slow down! Don't jump so often.",
6}Enabled: master switch for the anti-bunny-hop ragdoll.Sensitivity: selects an escrowed preset:low(extreme hops only),medium(recommended),high(aggressive),extreme(ragdoll almost always).Notify: show a notification when a hop is blocked.Message: notification text.
Examples
1RegisterNetEvent('ml_healthsystem:server:onPlayerRespawned', function(_clientCoords, spawnType)
2 if GetInvokingResource() then return end
3 local src = source
4 if spawnType == 'hospital' then
5 Bridge.RemoveMoney(src, 'bank', 500)
6 end
7end)1RegisterNetEvent('ml_healthsystem:server:onPlayerDeath', function()
2 if GetInvokingResource() then return end
3 local src = source
4 -- deathData is rebuilt server-side; read it from PlayerDeathContext or
5 -- log straight from the validated fields the handler already computes.
6 MySQL.insert('INSERT INTO death_logs (identifier, cause, killer) VALUES (?, ?, ?)', {
7 Bridge.GetLicense(src),
8 PlayerDeathContext[src] and PlayerDeathContext[src].deathReason or 'unknown',
9 PlayerDeathContext[src] and PlayerDeathContext[src].attackerServerId or 'environment'
10 })
11end)1-- Server side (authoritative): block safe-zone entry while infected
2if exports.ml_healthsystem:HasDisease and exports.ml_healthsystem:GetActiveDiseases then
3 -- prefer the server disease state; HasDisease here reads the player's diseases
4end
5
6-- Client side: show a cough notification for the local player
7if exports.ml_healthsystem:HasDisease('influenza') then
8 -- ...
9end1RegisterNetEvent('ml_healthsystem:server:onPlayerDeath', function()
2 if GetInvokingResource() then return end
3 local src = source
4 local ctx = PlayerDeathContext[src]
5 if ctx and ctx.killedByPlayer then
6 -- Add this resource to Config.LifePoints.ExportAllowlist first.
7 exports.ml_healthsystem:RemoveLifePoints(src, 15)
8 end
9end)The respawn flow already applies a life-point penalty internally via CalculatePenalty (highest-matching zone / external reason / NPC+weapon / player-kill / weapon penalty wins, no stacking). Use the export above only for extra, custom deductions.