# Developer > Developer API reference for ML LootZones Category: LOOT ZONES · Source: https://miciomods.it/docs/ml-lootzones-developer · Last updated: 2026-07-05 ## Overview Integration uses server exports for zone state, handler hooks in `open/handlers_server.lua` for loot flow and access control, and `open/handlers_client.lua` for interaction and UI customization. ## Server Exports ```lua local zoneData = exports['ml_lootzones']:GetZoneData(areaId) local allZones = exports['ml_lootzones']:GetAllZones() local inZone = exports['ml_lootzones']:IsPlayerInZone(source, areaId) local refreshed = exports['ml_lootzones']:RefreshZoneLoot(areaId) local toggled = exports['ml_lootzones']:SetZoneEnabled(areaId, enabled) ``` - `GetZoneData(areaId)`: Returns the zone's configuration data, or `nil` - `GetAllZones()`: Returns array of `{ id, name, category }` - `IsPlayerInZone(source, areaId)`: Returns `true` if the player is inside the zone - `RefreshZoneLoot(areaId)`: Forces a respawn of loot in a zone. Returns `true` on success - `SetZoneEnabled(areaId, enabled)`: Temporarily enable/disable a zone. Returns `true` on success ## Server Handlers Located in `open/handlers_server.lua`. ### Loot Flow **open/handlers_server.lua** ```lua function Handlers.OnBeforeClaim(source, areaId, lootIndex, lootConfig, areaData) return true -- return false to block end function Handlers.OnAfterClaim(source, areaId, lootIndex, itemsGiven, areaData) end function Handlers.GetLootMultiplier(source, areaId, areaData) return 1.0 -- 2.0 = double loot end function Handlers.ModifyLoot(source, areaId, fixedLoots, probabilityLoots, areaData) return fixedLoots, probabilityLoots end function Handlers.GetBonusLoot(source, areaId, areaData) return nil -- return { {name='item', amount=1} } for extra items end ``` - `OnBeforeClaim`: Called before loot is given. Return `false` to block. - `OnAfterClaim`: Called after items are distributed. `itemsGiven` contains the awarded items. - `GetLootMultiplier`: Multiply item amounts. `2.0` = double loot. - `ModifyLoot`: Intercept and modify loot tables before generation. - `GetBonusLoot`: Return extra items to add on top of normal loot. ### Access Control **open/handlers_server.lua** ```lua function Handlers.CanPlayerLootZone(source, areaId, areaData) return true, nil -- return false, 'reason' to block end function Handlers.CanPlayerClaimLoot(source, areaId, lootIndex, lootConfig) return true, nil end function Handlers.OnClaimBlocked(source, areaId, lootIndex, reason) end ``` - `CanPlayerLootZone`: Gate access to a zone. Return `false` + reason string to block. - `CanPlayerClaimLoot`: Gate access to a specific loot point. - `OnClaimBlocked`: Fires when a claim is blocked by cooldown, distance, or access hooks. ### Dispatch **open/handlers_server.lua** ```lua function Handlers.ShouldTriggerDispatch(source, areaId, areaData) return nil -- true/false to override, nil for default end function Handlers.ModifyDispatchData(source, areaId, dispatchData) return dispatchData end ``` - `ShouldTriggerDispatch`: Override dispatch trigger. `nil` = use default chance. - `ModifyDispatchData`: Modify dispatch data before sending. ### Tools **open/handlers_server.lua** ```lua function Handlers.ValidateTool(source, areaId, toolName, lootConfig) return nil -- true (allow), false (reject), nil (default) end function Handlers.GetToolDurabilityDrain(source, areaId, toolName, baseDrain) return nil -- return a number to override drain amount end ``` ### Regeneration **open/handlers_server.lua** ```lua function Handlers.GetRegenOverride(areaId, lootIndex, baseRegen, areaData) return nil -- return seconds to override regen time end function Handlers.OnLootRegenerated(areaId, lootIndex) end ``` - `GetRegenOverride`: Override the regeneration timer for a specific loot point. - `OnLootRegenerated`: Fires when a loot point regenerates. ### Configuration Events **open/handlers_server.lua** ```lua function Handlers.OnZoneSaved(source, areaId, areaData, isNew) end function Handlers.OnZoneDeleted(source, areaId) end function Handlers.OnCategorySaved(source, categoryId, categoryData, isNew) end ``` ## Client Handlers Located in `open/handlers_client.lua`. ### Interaction **open/handlers_client.lua** ```lua function Handlers.CanInteractWithLoot(areaId, lootIndex, lootConfig, entity) return true -- return false to hide target end function Handlers.GetCustomTargetLabel(areaId, lootIndex, lootConfig) return nil -- return string to override end function Handlers.GetCustomTargetIcon(areaId, lootIndex, lootConfig) return nil -- return string to override end function Handlers.AddCustomTargetOptions(areaId, lootIndex, lootConfig, entity) return {} -- return extra target options end ``` ### Loot Lifecycle **open/handlers_client.lua** ```lua function Handlers.CanLootFromZone(areaId, lootIndex, lootConfig) return true, nil end function Handlers.OnBeforeLoot(areaId, lootIndex, lootConfig) end function Handlers.OnAfterProgress(areaId, lootIndex, lootConfig) return true -- return false to cancel claim end function Handlers.OnLootClaimed(data) -- data = { zoneId, zoneName, category, propModel, propIndex, coords, isLootBox } end function Handlers.OnLootFailed(areaId, lootIndex, reason) end ``` ### Stash & Animation **open/handlers_client.lua** ```lua function Handlers.OnBeforeOpenStash(stashId, areaId, lootIndex) end function Handlers.OnAfterCloseStash(stashId, areaId) end function Handlers.GetCustomAnimation(areaId, lootConfig) return nil -- return animation table to override end ``` ### Zone Tracking **open/handlers_client.lua** ```lua function Handlers.OnZoneEnter(areaId, areaData) end function Handlers.OnZoneExit(areaId) end function Handlers.OnLootSpawned(areaId, lootTable) end function Handlers.OnLootDespawned(areaId) end ``` ## Examples **Block looting during events** **open/handlers_server.lua** ```lua local eventActive = false Handlers.CanPlayerLootZone = function(source, areaId, areaData) if eventActive then return false, 'Looting is disabled during an active event' end return true end ``` **Double loot for VIPs** **open/handlers_server.lua** ```lua Handlers.GetLootMultiplier = function(source, areaId, areaData) local job = Bridge.GetJob(source) if job and job.name == 'vip' then return 2.0 end return 1.0 end ``` **Custom target label per zone** **open/handlers_client.lua** ```lua Handlers.GetCustomTargetLabel = function(areaId, lootIndex, lootConfig) if areaId == 'military_zone' then return 'Search Military Crate' end return nil end ```