Configuration
Every setting lives in cfg.lua. The file is a shared_script, so both client and server see the same table. Do not put secrets in it.
Hack points
cfg.hacks.textUI
cfg.hacks.textUI = '[E] Hack'The prompt shown to the player when they walk within range of a hack point. Rendered through lib.showTextUI, so anything ox_lib text supports works here.
cfg.hacks.pointRadius
cfg.hacks.pointRadius = 1.5Distance in metres at which the prompt starts showing. Small values feel snappy but frustrate players who round the prop slightly. 1.5 covers most cases.
cfg.hacks.pressKey
cfg.hacks.pressKey = 38 -- EFiveM control ID for the interact button. 38 is E. See the FiveM controls list for other values.
cfg.hacks.adminAce / adminWhitelist
cfg.hacks.adminAce = 'command.create_minigame'
cfg.hacks.adminWhitelist = {
'discord:123456789012345678',
'license:abcdef0123456789abcdef0123456789abcdef01',
}Gate for /create_minigame, /remove_minigame and /test_minigame.
The two mechanisms are OR'd. A player passes if the ACE matches or any of their identifiers is in the whitelist. Leave both empty and everyone can run the commands, which is fine for local testing and terrible for a live server.
Accepted identifier prefixes:
discord:
discord:123456789012345678
license:
license:abcdef0123456789abcdef0123456789abcdef01
license2:
license2:0011223344556677889900aabbccddeeff00112233
steam:
steam:110000112345678
fivem:
fivem:1234567
ip:
ip:203.0.113.42
Grab yours by opening F8 and running getplayeridentifiers, or from txAdmin's player list.
Client-side, only ACE is checked directly. The identifier whitelist is authoritative on the server, so a player without the ACE will fall through to a server callback the first time they run the command. That is fine, it just adds a single round-trip on the first call.
cfg.hacks.autoSave
When true, every /create_minigame and /remove_minigame rewrites data/saved_minigames.lua. Turn it off if you want to hand-edit that file and never have the server touch it. The commands still work, hack points just do not survive a restart.
Auto-save cannot serialise Lua functions. If a hack point has an onSuccess.fn or onFail.fn, the next auto-save drops the function and prints a warning. Use clientEvent or serverEvent instead if you need the hook to survive a restart. See Hooks.
cfg.hacks.types
The dictionary of hack types available to /create_minigame. Each key is a type name, each value is a preset. Six ship in. Adding a seventh is an entry, not a code change. Full walkthrough on Hack Types.
cfg.hacks.onSuccess / cfg.hacks.onFail
Global hooks fired on every hack, regardless of type. Per-point overrides in saved_minigames.lua replace these entirely (not merged). Full field list on Hooks.
Placement presets
cfg.monitorPresets
Camera + DUI settings for placement = 'monitor'. Each key is a preset name referenced from a hack type's monitorPreset field.
duiWidth/Height
DUI texture resolution. Higher = crisper, more VRAM
renderDistance
Metres beyond which the DUI stops being drawn
camOffsetX/Y/Z
Local offset from the prop, in metres
camPitch/Roll
Camera rotation in degrees
camFov
Field of view. Lower = tighter framing
camEaseMs
Time in ms for the cam to slide in and out
The tabletWall preset also carries renderMode = 'quad' and a bounding-box block. That switches the renderer from AddReplaceTexture to a quad draw, so the tablet stays untouched instead of overwriting a texture globally. See Placements.
cfg.propPresets.tablet
Settings for placement = 'prop'. Calibrated for the shipped rm_tablet_02. You should not need to touch these unless you swap the tablet model.
The bb* block controls where the DUI quad sits relative to the prop's local origin. If the minigame draws in front of, behind, or through the tablet, this is what to nudge.
Minigame difficulties
Every minigame lives in cfg under its own key with two shapes.
Shape 1: full difficulty table
default is used when the caller does not pass difficulty. Each difficulty value is passed straight to the React component as props, so the fields listed per minigame in Minigames are the ones the game reads.
Shape 2: difficulty-only
The React component owns its own tunables and only the difficulty string crosses the bridge. Change default to shift the baseline, or override at the callsite with opts.difficulty = 'hard'.
Overriding at the callsite
Every field in a difficulty preset can be overridden per-call:
Anything not listed in the preset that the React component reads also works, provided the component reads it. This is the escape hatch for one-off tuning without editing cfg.lua.
Last updated