# Developer > Developer API reference for ML Camps Category: CAMPS · Source: https://miciomods.it/docs/ml-camps-developer · Last updated: 2026-07-05 ## Overview Integration runs through three server exports, replicated GlobalState keys any resource can read, and handler hooks in the `open/` folder (shipped unescrowed). ## Server Exports - `GetCampStatus(campId)`: Returns the runtime status string, or nil for an unknown camp: 'idle' | 'active' | 'combat' | 'cleared' | 'cooldown' | 'depleted' - `IsCampCleared(campId)`: Returns true while the camp status is 'cleared' or 'cooldown'. Spawn-once camps report 'depleted' instead; check `GetCampStatus` for those - `GetCampAliveCount(campId)`: Number of hostiles still alive ```lua local status = exports.ml_camps:GetCampStatus('bandit_grapeseed') local cleared = exports.ml_camps:IsCampCleared('bandit_grapeseed') local alive = exports.ml_camps:GetCampAliveCount('bandit_grapeseed') ``` ## GlobalState Every camp replicates a live snapshot under `mlcamp_`, readable on both sides: ```lua local snap = GlobalState['mlcamp_bandit_grapeseed'] -- { -- status = 'combat', -- idle | active | combat | cleared | cooldown | depleted -- alive = 3, -- hostiles alive -- total = 6, -- hostiles spawned -- nextRespawn = 0, -- unix timestamp when the cooldown ends, 0 otherwise -- } ``` The active raid HUD settings are replicated under `mlcampcfg` as `{ enabled, position, resetVisibilityDefault }`. Camp NPCs carry `mlCampPed = true` and `mlCampId` on their entity state bag, so other scripts can recognize them. ## Server Handlers Located in `open/handlers_server.lua`. **open/handlers_server.lua** ```lua Handlers.HasCreatorPermission = function(source) -- return true to allow the admin panel end Handlers.HasLivePermission = function(source) -- return true to allow force clear / force reset / teleport end Handlers.OnCampActivated = function(campId, campData) end Handlers.OnCampCleared = function(campId, campData, raiders) -- raiders: array of credited server ids, entry order end Handlers.ModifyLoot = function(campId, items, money) return items, money end ``` - `HasCreatorPermission` / `HasLivePermission`: Permission gates for the two staff tiers. The default implementation checks `Config.Permissions` through ml_bridge; replace it to plug in any permission system - `OnCampActivated`: Fires when a camp spawns its NPCs - `OnCampCleared`: Fires when the last hostile dies. `raiders` holds the credited player ids - `ModifyLoot`: Called before every loot payout (direct and per crate). Return the modified `items` array (`{ name, count, metadata? }`) and `money` table (`{ account, amount }` or nil) ## Client Handlers Located in `open/handlers_client.lua`. **open/handlers_client.lua** ```lua Handlers.CanShowCampBlip = function(campId, campData) return true -- return false to hide this camp's blip for the local player end Handlers.OnCampEntered = function(campId, campData) end ``` - `CanShowCampBlip`: Per-player blip filter, evaluated when camps load - `OnCampEntered`: Fires when the local player crosses into a camp radius ## Examples **Reward every raider on clear** **open/handlers_server.lua** ```lua Handlers.OnCampCleared = function(campId, campData, raiders) for _, src in ipairs(raiders) do Bridge.GiveItem(src, 'water', 1) end end ``` **Scale loot by camp type** **open/handlers_server.lua** ```lua Handlers.ModifyLoot = function(campId, items, money) local camp = Config.Camps[campId] if camp and camp.type == 'military' and money then money.amount = math.floor(money.amount * 1.5) end return items, money end ``` **Gate content behind a cleared camp** **your_script/server.lua** ```lua RegisterNetEvent('myscript:enterBunker', function() local src = source if not exports.ml_camps:IsCampCleared('military_zancudo') then Bridge.NotifyPlayer(src, 'error', 'Clear the outpost first.') return end -- open the bunker end) ``` **React to camp status changes (client)** **your_script/client.lua** ```lua AddStateBagChangeHandler(nil, 'global', function(_, key, value) if type(key) ~= 'string' or key:sub(1, 7) ~= 'mlcamp_' then return end local campId = key:sub(8) if value and value.status == 'cleared' then print(('camp %s cleared near %s'):format(campId, tostring(cache.ped))) end end) ``` **Detect camp NPCs from another script (client)** **your_script/client.lua** ```lua local function isCampNpc(ped) return Entity(ped).state.mlCampPed == true end -- e.g. skip camp NPCs in a ped-scanning loop for _, ped in ipairs(GetGamePool('CPed')) do if ped ~= cache.ped and not isCampNpc(ped) then -- safe to process end end ```