Developer
Overview
Other resources read and control zones through server exports and listen to the loot events. The loot flow itself is changed in open/handlers_server.lua and open/handlers_client.lua, which stay unencrypted.
Server Exports
lua
1local zone = exports['ml_lootzones']:GetZoneData(areaId)
2local zones = exports['ml_lootzones']:GetAllZones()
3local inside, zoneId = exports['ml_lootzones']:IsPlayerInZone(source, areaId)
4local refreshed = exports['ml_lootzones']:RefreshZoneLoot(areaId)
5local changed = exports['ml_lootzones']:SetZoneEnabled(areaId, enabled)GetZoneData(areaId): data of an active zone, ornilGetAllZones(): list of active zones as{ id, name, category }IsPlayerInZone(source, areaId?):truewhen the player stands inside that zone. WithoutareaIdit checks every active zone and also returns the ID of the zone foundRefreshZoneLoot(areaId): rolls the zone loot again. Returnstrueon successSetZoneEnabled(areaId, enabled): opens or closes a zone until the next restart or rotation. Returnstrueon success
RefreshZoneLoot and SetZoneEnabled only answer calls made from another resource.
Events
lua
1AddEventHandler('ml_lootzones:server:lootCollected', function(data)
2end)Fires on the server after a prop is looted or a lootbox stash is emptied. The same payload reaches the looting player as the client event ml_lootzones:client:lootCollected.
lua
1data = {
2 source = 1,
3 zoneId = 'zone_id',
4 zoneName = 'Zone name',
5 category = 'category_id',
6 propModel = 'prop_tool_box_02',
7 propIndex = 3,
8 coords = vector3(0.0, 0.0, 0.0),
9 isLootBox = false,
10 timestamp = 1760000000,
11}Server Handlers
Located in open/handlers_server.lua.
Loot Flow
open/handlers_server.lua
1Handlers.OnBeforeClaim = function(source, areaId, lootIndex, lootConfig, areaData)
2 return true
3end
4
5Handlers.OnAfterClaim = function(source, areaId, lootIndex, itemsGiven, areaData)
6end
7
8Handlers.GetLootMultiplier = function(source, areaId, areaData)
9 return 1.0
10end
11
12Handlers.ModifyLoot = function(source, areaId, fixedLoots, probabilityLoots, areaData)
13 return fixedLoots, probabilityLoots
14end
15
16Handlers.GetBonusLoot = function(source, areaId, areaData)
17 return nil
18endOnBeforeClaim: runs before the items are given. Returnfalseto stop the claimOnAfterClaim: runs after the items are given.itemsGivenlists themGetLootMultiplier: multiplies item amounts.2.0doubles themModifyLoot: edits the guaranteed and chance tables before the rollGetBonusLoot: extra items on top, as{ { name = 'item', amount = 1 } }
Access
open/handlers_server.lua
1Handlers.CanPlayerLootZone = function(source, areaId, areaData)
2 return true, nil
3end
4
5Handlers.CanPlayerClaimLoot = function(source, areaId, lootIndex, lootConfig)
6 return true, nil
7end
8
9Handlers.OnClaimBlocked = function(source, areaId, lootIndex, reason)
10endCanPlayerLootZone: returnfalse, 'reason'to close a whole zone to that playerCanPlayerClaimLoot: same check for a single propOnClaimBlocked: runs when a claim is refused by a cooldown, the distance check or one of the hooks above
Dispatch
open/handlers_server.lua
1Handlers.ShouldTriggerDispatch = function(source, areaId, areaData)
2 return nil
3end
4
5Handlers.ModifyDispatchData = function(source, areaId, dispatchData)
6 return dispatchData
7endShouldTriggerDispatch:trueorfalseforces the alert,nilkeeps the configured chanceModifyDispatchData: edits the alert before it is sent
Tools
open/handlers_server.lua
1Handlers.ValidateTool = function(source, areaId, toolName, lootConfig)
2 return nil
3end
4
5Handlers.GetToolDurabilityDrain = function(source, areaId, toolName, baseDrain)
6 return nil
7endValidateTool:trueaccepts the tool,falserefuses it,nilkeeps the normal checkGetToolDurabilityDrain: return a number to replace the durability taken from the tool
Regrowth
open/handlers_server.lua
1Handlers.GetRegenOverride = function(areaId, lootIndex, baseRegen, areaData)
2 return nil
3end
4
5Handlers.OnLootRegenerated = function(areaId, lootIndex)
6endGetRegenOverride: return seconds to replace the regrow time of a propOnLootRegenerated: runs when a looted prop comes back
Admin Changes
open/handlers_server.lua
1Handlers.OnZoneSaved = function(source, areaId, areaData, isNew)
2end
3
4Handlers.OnZoneDeleted = function(source, areaId)
5end
6
7Handlers.OnCategorySaved = function(source, categoryId, categoryData, isNew)
8endClient Handlers
Located in open/handlers_client.lua.
Interaction
open/handlers_client.lua
1Handlers.CanInteractWithLoot = function(areaId, lootIndex, lootConfig, entity)
2 return true
3end
4
5Handlers.GetCustomTargetLabel = function(areaId, lootIndex, lootConfig)
6 return nil
7end
8
9Handlers.GetCustomTargetIcon = function(areaId, lootIndex, lootConfig)
10 return nil
11end
12
13Handlers.AddCustomTargetOptions = function(areaId, lootIndex, lootConfig, entity)
14 return {}
15endCanInteractWithLoot: returnfalseto hide the target option or promptGetCustomTargetLabel,GetCustomTargetIcon: return a string to replace the label or iconAddCustomTargetOptions: extra target options on the same prop
Looting
open/handlers_client.lua
1Handlers.CanLootFromZone = function(areaId, lootIndex, lootConfig)
2 return true, nil
3end
4
5Handlers.OnBeforeLoot = function(areaId, lootIndex, lootConfig)
6end
7
8Handlers.OnAfterProgress = function(areaId, lootIndex, lootConfig)
9 return true
10end
11
12Handlers.OnLootClaimed = function(data)
13end
14
15Handlers.OnLootFailed = function(areaId, lootIndex, reason)
16endOnAfterProgress: runs when the progress bar ends. Returnfalseto cancel the claimOnLootClaimed: receives the same payload as thelootCollectedevent
Stash and Animation
open/handlers_client.lua
1Handlers.OnBeforeOpenStash = function(stashId, areaId, lootIndex)
2end
3
4Handlers.OnAfterCloseStash = function(stashId, areaId)
5end
6
7Handlers.GetCustomAnimation = function(areaId, lootConfig)
8 return nil
9endGetCustomAnimation: return an animation table to replace the one set on the prop
Zone Tracking
open/handlers_client.lua
1Handlers.OnZoneEnter = function(areaId, areaData)
2end
3
4Handlers.OnZoneExit = function(areaId)
5end
6
7Handlers.OnLootSpawned = function(areaId, lootTable)
8end
9
10Handlers.OnLootDespawned = function(areaId)
11endExamples
open/handlers_server.lua
1local eventActive = false
2
3Handlers.CanPlayerLootZone = function(source, areaId, areaData)
4 if eventActive then
5 return false, 'Looting is closed during the event'
6 end
7 return true
8endopen/handlers_server.lua
1Handlers.GetLootMultiplier = function(source, areaId, areaData)
2 local job = Bridge.GetJob(source)
3 if job and job.name == 'vip' then
4 return 2.0
5 end
6 return 1.0
7endopen/handlers_client.lua
1Handlers.GetCustomTargetLabel = function(areaId, lootIndex, lootConfig)
2 if areaId == 'military_zone' then
3 return 'Search Military Crate'
4 end
5 return nil
6endlua
1AddEventHandler('ml_lootzones:server:lootCollected', function(data)
2 if data.zoneId == 'military_zone' then
3 TriggerEvent('my_missions:server:progress', data.source, 'loot_military')
4 end
5end)