Prison Escape
Prompt Prison Escape
Overview
This resource adds an immersive toilet-based escape minigame for prison cells.
Players must unscrew 4 screws from a toilet tank cover to reveal an escape route. The system includes:
Custom enter / work / exit animation sequences
Cursor-based screw removal minigame (hold LMB to progress)
Persistent progress (unscrewed screws stay unscrewed if player leaves)
Multiple interaction systems (ox_target, qb-target, or TextUI)
Optional inventory requirements (ox_inventory, qb-inventory)
Installation Instructions
If you skip the isPlayerInPrion(source) integration, the script will either allow everyone or deny everyone (depending on your config). This is the main control point for your prison system.
Additional Information
Dependencies
Required:
ox_lib
Optional (pick what your server uses):
Interaction:
ox_targetorqb-targetItem checks:
ox_inventoryorqb-inventory(only if you enablerequiredItem)
Configuration
Client: config/config_c.lua
return {
-- Interaction system: 'auto' | 'ox_target' | 'qb-target' | 'textUI' | 'custom'
interaction = 'auto',
-- Item required to start (empty string = no requirement)
-- Works with ox_inventory or qb-inventory
requiredItem = '',
-- UI location for screw selection:
-- 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
-- 'middle-left' | 'middle-right' | 'center'
uiLocation = 'middle-left',
-- TextUI functions (customize for your framework)
textUI = {
hide = function()
lib.hideTextUI()
end,
show = function(text)
lib.showTextUI(text)
end,
},
toilet = {
-- Screw positions (do not modify unless you know what you're doing)
screwOffsets = { ... },
screwModel = joaat('prompt_prison_screw'),
screwDriverModel = joaat('v_ind_cs_screwdrivr3'),
-- Set true if you are NOT using entity lockdown / need networked objects
useNetworkedObjects = false
}
}THIS I WHERE YOU WOULD WANT TO START YOUR INTEGRATION INTO OTHER SCRIPTS OR FRAMEWORKS
Server: config/config_s.lua
return {
debug = true, -- enable server logs
-- CRITICAL INTEGRATION POINT
-- Return true to allow, false to deny
--
-- NOTE: the function name is spelled "isPlayerInPrion" in this config.
isPlayerInPrion = function(source)
return true
end
}Jail Integration Examples
Generic framework (ESX/QBCore/Custom job check)
return {
debug = false,
isPlayerInPrion = function(source)
local Player = YourFramework.GetPlayer(source)
if not Player then return false end
local job = Player.job.name
return job == 'prisoner' or job == 'inmate'
end
}qb-prison style (metadata injail)
return {
debug = false,
isPlayerInPrion = function(source)
local Player = QBCore.Functions.GetPlayer(source)
if not Player then return false end
local jailTime = Player.PlayerData.metadata['injail']
return jailTime and jailTime > 0
end
}ESX jail style (jailTime value)
return {
debug = false,
isPlayerInPrion = function(source)
local xPlayer = ESX.GetPlayerFromId(source)
if not xPlayer then return false end
local jailTime = xPlayer.get('jailTime') or 0
return jailTime > 0
end
}ND_Jail style (export check)
return {
debug = false,
isPlayerInPrion = function(source)
return exports['ND_Jail']:isPlayerJailed(source)
end
}Custom DB check (example concept)
return {
debug = false,
isPlayerInPrion = function(source)
local identifier = GetPlayerIdentifier(source, 0)
local result = MySQL.Sync.fetchScalar(
'SELECT jail_time FROM players WHERE identifier = ?',
{ identifier }
)
return result and result > 0
end
}Callbacks & Events (Reference)
Server callbacks (lib.callback) used by the resource:
prompt_prison_escape:createToiletObjectprompt_prison_escape:unscrewProgressprompt_prison_escape:getUnscrewedStateprompt_prison_escape:completeEscapeprompt_prison_escape:stopSitting
Client event used by the resource:
prompt_prison_escape:toggleToiletVisibility
Customization
Require an item (optional)
-- config/config_c.lua
requiredItem = 'screwdriver'Force a specific interaction system (optional)
-- config/config_c.lua
interaction = 'ox_target' -- or 'qb-target' or 'textUI'Custom TextUI (optional)
-- config/config_c.lua
textUI = {
hide = function()
exports['your_ui']:HideTextUI()
end,
show = function(text)
exports['your_ui']:ShowTextUI(text)
end,
},Custom interaction mode (optional)
Implement inside client/editable/interaction.lua (custom mode must call onUse(entity) when interacted).
-- example concept
exports['your_interact_system']:AddInteraction({
model = toiletHash,
label = locale('interaction_label'),
action = function(entity)
onUse(entity)
end
})Troubleshooting
Interaction not showing
Set
interactionexplicitly instead ofautoConfirm the prison uses supported toilet models in the cell area
Confirm your
isPlayerInPrion(source)returnstruefor jailed players
Minigame starts but progress doesn’t save
Ensure
ox_libis runningCheck server console for callback errors
Confirm the resource isn’t restarting/crashing
Players can use it when they shouldn’t
Your
isPlayerInPrion(source)check is returningtrueincorrectlyAdd real jail-time / jailed-state validation from your prison script
File Structure (Reference)
prompt_prison_escape/
├── client/
│ ├── main.lua
│ ├── events.lua
│ ├── utils.lua
│ ├── editable/
│ │ └── interaction.lua
│ └── minigame/
│ ├── screw_game.lua
│ ├── camera_manager.lua
│ └── animation_controller.lua
├── config/
│ ├── config_c.lua
│ └── config_s.lua
├── server/
│ └── server.lua
├── locales/
│ ├── en.json
│ ├── de.json
│ ├── es.json
│ ├── fr.json
│ └── pl.json
├── stream/
│ └── *.ycd
├── web/
│ └── (NUI)
└── fxmanifest.luaNote: This resource handles cell escape only. Anything after escape (alerts, recapture, jail time changes, routes) should be handled by your prison system or additional scripts.
Last updated