Developer
Overview
All integration hooks live in the open/ folder. These files are never escrowed and can be freely modified. The system also exposes server-side functions and custom events for external integrations.
Server Handlers
Located in open/server.lua.
Item Distribution
1function OpenServer.BeforeGiveItem(src, item, amount)
2 -- Return false to block the item from being given
3 return true
4endCalled before the system gives a reward item (from quiz profiles or crafting). Return false to block.
Action Completion
1function OpenServer.OnActionComplete(src, actionType, data)
2 -- actionType is the executed action's trigger type ('client' or 'server')
3 -- data = { terminalId, actionId, event, args }
4endFires after an action-panel button executes successfully. Use it for XP, battle-pass progress, or auditing.
Client Handlers
Located in open/client.lua.
UI Access Control
1function OpenClient.BeforeOpenUI(data)
2 -- Return false to prevent the terminal UI from opening
3 return true
4endAction Panel Integration
The actions app type triggers custom events on your server or client. Your external script just registers the handler:
1RegisterNetEvent('myScript:lockdown', function(args)
2 local level = args.level
3 -- Lock all doors, trigger alarm, etc.
4end)1RegisterNetEvent('myScript:triggerAlarm', function(args)
2 local zone = args.zone
3 -- Play alarm sound, flash screen, etc.
4end)Quiz Gating
Apps of type locked_folder can be gated behind quiz completion:
requireQuiz = true: Requires ANY quiz on this terminal to be completedrequireQuiz = 'quiz_id': Requires a SPECIFIC quiz to be completedrequiredProfile = 'tactician': Requires a specific profile result from the quiz
Quiz Rewards
When a player confirms their profile, rewards are distributed automatically:
money: Cash via Bridgeitems: Items via Bridge (array of{ name, amount })vehicle: Registers a vehicle ({ name = "model" }) to the player usingConfig.Vehiclessettingsjob: Sets the player's job via Bridge ({ name, grade })
Server Exports
GetGoatProfile(identifier, terminalId) returns the quiz profile id a player was assigned on a terminal, or nil if they have not completed it. Reads from cache, falls back to the database.
1local profile = exports.ml_terminal_system:GetGoatProfile(identifier, 'my_terminal')
2if profile == 'tactician' then
3 -- grant tactician perks
4endidentifier: the framework player identifier (fromBridge.GetPlayerId(src))terminalId: the base terminal ID (without any_locNsuffix)
Config Validation
All terminal configs are validated at startup via Config.ValidateAll(). A failure logs a descriptive [ERROR] for that terminal. Validated fields:
label: Requiredmodel: Requiredcoordsorlocations: At least one requiredapps[].nameandapps[].type: Required per app- Quiz questions/profiles are NOT validated here, they merge from
config_questions.luaby terminal ID at startup. kiosk.modeandkiosk.app: Required if kiosk section exists