Customization
The settings are in config.lua. The two bridge files are open so you can adapt the framework side. The tablet itself is plain HTML in html/.
Which file decides what
Section titled “Which file decides what”| File | What it decides | Open? |
|---|---|---|
config.lua | Language, framework, photos, the creator command, the live grid, who can use the tablet, and camera props | Yes |
bridge/client_bridge.lua | Framework detection, the player’s job, notifications, and the help-text prompt | Yes |
bridge/server_bridge.lua | Framework detection, identifiers, jobs, usable items, adding and removing items, server notifications | Yes |
items/ | Item definitions for ox, qb and ESX, and the icons in items/images/ | Yes |
html/ | The tablet: index.html, app.js, app.css, the map (map.js, map.css) and its tiles in html/tiles/ | Not escrowed |
locales/*.lua | Every string, in game and on the tablet | Escrowed in this version |
client/, server/ | The script | Escrowed |
General — config.lua
Section titled “General — config.lua”| Option | What it does | Default |
|---|---|---|
Config.Locale | Which language is used | 'en' |
Config.Framework | esx, qbcore, or auto to detect it. On QBox, auto finds it as qbcore through its QBCore compatibility; to pin it, use qbcore | 'auto' |
Config.EvidenceEnabled | Photos on or off. Off, Space in a camera and the grid’s snapshot do nothing | true |
Config.CreatorCommand | The command that opens the admin creator | 'camcreator' |
Config.CreatorAce | The ACE permission the creator needs | 'mic_cctvcreator.open' |
Config.LiveGridFPS | How often the grid refreshes each second. 1 to 15; higher is smoother and heavier | 5 |
Config.BlackScreenBehindUI | Draws black behind the tablet so the jumps between cameras while the grid refreshes are hidden | true |
Config.AllowedJobs | Jobs allowed to open the tablet. Empty means everybody. See below | {} |
Config.SpawnDistance | How close you have to be for a camera prop to be spawned | 60.0 |
Config.BreakableCamera | Whether cameras can be broken at all | true |
Config.RepairDistance | How far the repair laser reaches | 20.0 |
Config.RepairTime | How long a repair takes, in milliseconds | 5000 |
Who sees which camera
Section titled “Who sees which camera”This is the part worth deciding before anybody places a camera.
Config.AllowedJobs empty (the default)
Section titled “Config.AllowedJobs empty (the default)”- Anybody with a
cctv_tabletcan open it. - A camera a player places is private: only they see it.
- The owner can then share it with their job — it becomes a job camera for everybody in that job — or give it an access name and password. Anybody who types those into their tablet adds the camera to it.
Config.AllowedJobs set, for example police and sheriff
Section titled “Config.AllowedJobs set, for example police and sheriff”- Only those jobs can open the tablet; anybody else is told they are not authorized.
- A camera a player places becomes a job camera for the job they are in at that moment.
Cameras from the admin creator
Section titled “Cameras from the admin creator”Always job cameras, visible to every job ticked in the creator. A creator camera with no job ticked is visible to nobody.
Evidence and logs
Section titled “Evidence and logs”- A photo taken from a private camera is private to whoever took it. A photo from a job camera belongs to the job. Either can be shared with your job from the gallery.
- Breach logs show for every camera you have access to — the 30 most recent. Repairing a camera clears its log.
Taking a camera down
Section titled “Taking a camera down”The owner can remove their camera from the tablet and gets the item back.
Breaking and repairing
Section titled “Breaking and repairing”With Config.BreakableCamera on, a camera goes offline when a bullet lands within about a metre of it, or when it is hit by melee, an explosion or a vehicle. The creator can mark individual cameras as unbreakable.
The repair kit, cctv_repair, turns on a laser. Aim it at a broken camera within Config.RepairDistance, press E, and wait Config.RepairTime. The kit is not used up. Backspace or ESC puts it away.
Controls
Section titled “Controls”Placing a camera (from an item)
| Key | What it does |
|---|---|
| Look around | Moves the preview to the surface you are looking at |
| Scroll wheel | Rotates it |
| E | Places it; you are asked for a name |
| Right click / ESC | Cancels |
Looking through a camera
| Key | What it does |
|---|---|
| W / S | Tilt up and down |
| A / D | Turn. Wall and pole cameras stop at 45° either way; 360° models go all the way round |
| Scroll wheel | Zoom |
| Enter | Cycle normal, night vision and thermal |
| Space | Take a photo for the evidence gallery |
| Backspace / ESC | Back to the tablet |
The admin creator (/camcreator)
Pick a model (wall, 360 wall, pole, 360 pole), a base name, the jobs that can see it and whether it can be broken, then enter placement mode:
| Key | What it does |
|---|---|
| ← / → | Switch model |
| Scroll wheel | Rotate |
| E | Place; you are asked for a name |
| Right click / ESC | Back to the creator menu |
Commands and permissions
Section titled “Commands and permissions”| Command | Who | What it does |
|---|---|---|
/camcreator | Players with the Config.CreatorAce permission | Opens the admin creator. Change the name with Config.CreatorCommand |
Grant the permission in server.cfg with an add_ace line for the group you want, for example giving mic_cctvcreator.open to group.admin. If you change Config.CreatorAce, grant the new name instead.
Exports
Section titled “Exports”Client-side, for other resources that need to know about the cameras:
| Export | Arguments | Returns |
|---|---|---|
GetCameraStatus | camera id | 'online', 'broken', or 'offline' if the id is unknown |
GetCameraIdFromEntity | entity handle | The camera id of a spawned camera prop, or nothing |
IsPlacing | — | true while the player is placing a camera |
HideNearbyCamera | coords | Hides the nearest camera prop within 2 m and returns it |
UnhideCamera | prop | Shows a prop hidden with HideNearbyCamera again |
Languages
Section titled “Languages”Eleven ship: en, es, fr, de, it, pt, ar, ja, pl, ru, tr. Set Config.Locale to the code. The tablet and the in-game text use the same file.
In this version the files in locales/ are part of the protected code, so they cannot be edited. If you need a language that is not there, or different wording, ask on the Discord.
The bridge
Section titled “The bridge”| File | What it covers |
|---|---|
bridge/client_bridge.lua | Framework detection, Bridge.GetPlayerJob, Bridge.Notify, and Bridge.ShowTextUI / Bridge.HideTextUI for the repair prompt |
bridge/server_bridge.lua | Framework detection, Bridge.GetPlayerIdentifier, Bridge.GetPlayerJob, Bridge.RegisterUsableItem, Bridge.AddItem, Bridge.AddItemWithMetadata, Bridge.RemoveItem, Bridge.Notify |
A different notification resource: change Bridge.Notify in both files.
A different text UI (ox_lib, okok…): Bridge.ShowTextUI and Bridge.HideTextUI in the client file. On QBCore they use QBCore’s own DrawText; otherwise the game’s help text.
Inventory: when ox_inventory is running, items are added and removed through it on either framework. Otherwise the framework’s own functions are used.
A different framework: set Config.Framework and fill in the detection block and the identifier, job and item functions in both files. Without a framework the script falls back to the license: identifier and treats everybody as unemployed, but items — the tablet included — are only registered on ESX and QBCore (QBox included, through its QBCore compatibility).