Skip to the content
Docs

Devices & Reports

On this page8

Three devices, one battery, one paper. Item names and definitions: Items. The voice changer has its own page: Voice & Voice Changer.

Hidden camera

A camera worn on the clothes. While it is on, scans run faster, the memory lasts far longer, and the camera keeps a recording that you can print as a paper report from the F3 menu.

KeyDefaultAllowedWhat it does
BatterySeconds1800 (30 min)secondsRecording time per full battery.
SpeedMultiplier2.01.0–4.0Scan speed while the camera is on.
MinOnShare0.50.0–1.0Share of the look the camera must have been on. Below it the result is no camera memory, and the recording cannot be printed ("camera on too short").
Phototruetrue / falseTry to add a photo of the person to the report. Needs Config.ScreenshotSystem.
PhotoWindowSeconds5secondsHow long to wait for the person to be on screen for the photo.
PrintReporttruetrue / falseKeep a printable recording when a camera look ends. false = finished looks leave no recording (the 30-day camera memory still works).
ReportPairCooldownMinutes30minutesOne recording per camera owner and person in this time. A new look at the same person shows "(printed recently)".
ReportOnWeakScansfalsetrue / falseAlso keep recordings of looks that ended below Config.Scan.MinSavePct.
SkipEmotetruetrue / falseSkip the thinking pose while your own camera is on — camera scans are silent.
CheckpointPct101–50Save the battery level to the database every N % of drain.
FailedRecognitionMemory'none''none' · 'camera'See below.

A camera scan also extends the learning range: Config.Scan.CameraDistance (7 m) instead of the usual 5 m.

Printing camera recordings

No paper drops into your pockets by itself. A camera recording waits in the F3 menu until you print it.

  1. Switch the hidden camera on (use the item). While it records, the HUD shows REC with the camera's own % next to it, for example REC 25%. The number turns green at Config.Scan.MinSavePct (50 %): from then on the recording can be printed.
  2. Press F3 → Camera recordings. The list shows your recordings of the last 24 hours, newest first, without names — only the scene line, for example "Saw him on camera on Vinewood Blvd in the evening". Looks that are still running are at the top as Recording now · n%.
  3. Choose one with UP / DOWN and press Enter. A 3-second Printing... bar runs and you get the paper. Each recording prints once.
The REC % next to the memory ring on the HUD
The ring shows the memory (80 %); REC shows what the camera saw and turns green at 50 %.

You do not have to stop the look or walk away: a look that is still running can be printed as soon as the camera has seen 50 %. The look keeps running after the print, and its end does not make a second paper.

Gray rows in the list (the list refreshes by itself every few seconds):

RowMeans
Recording now · 25% (needs 50%)The camera has not seen enough yet. Keep the person in view.
(camera on too short)The camera was off for too much of this look (MinOnShare).
(printed recently)You already have a recording of this person from the last ReportPairCooldownMinutes.

What players can see:

MessageWhen
Camera recording saved. Print it from the Recognition menu (Camera recordings).A camera look ended with a recording.
The camera saw only 25% - not enough for a recording (needs 50%).A camera look ended below 50 %.
You need your hidden camera with you to print.The hidden camera is not in the inventory.
No room for the report. You will get it when you have space.The inventory is full; the paper waits (Config.Report.PendingMax).

F3 → Stop looking ends every scan and quiet look at once, the camera look included. What the camera saw up to then is kept as usual.

Player view of the whole flow: Hidden Camera & Reports.

FailedRecognitionMemory

A recognise scan that stayed below the act line — the person is in a look you already know, and you still did not place them:

ValueBehaviour
'none' (default)Your memory stays as it is.
'camera'Also write or refresh a 30-day camera memory of the look recorded now.

A disguised person is no longer this case: that scan is a stranger scan and lands on the disguise memory it matches best, or starts a new one. See Memory & Familiarity.

Magnetic scanner

A hand wand that beeps near hidden electronics on people around you.

KeyDefaultAllowedWhat it does
Radius2.0metresArea searched around the user.
SweepSeconds4secondsLength of one sweep.
DetectCarriedOfftruetrue / falseA camera that is carried but switched off gives a weak signal.
DetectVoiceChanger'off''off' · 'on' · 'carried'Whether voice changers are detected at all. on = only while active. carried = active or not.
SampleMs500msTime between samples during a sweep.
CooldownSeconds10secondsBefore the same player can sweep again.
MaxMoveMeters1.5metresHow far the user may move during a sweep before it stops.

Beeps use GTA frontend sounds:

lua
Sounds = {
    weak   = { name = 'Beep_Red', set = 'DLC_HEIST_HACKING_SNAKE_SOUNDS', count = 1 },
    strong = { name = 'Beep_Red', set = 'DLC_HEIST_HACKING_SNAKE_SOUNDS', count = 3 },
}

Device housekeeping

KeyDefaultAllowedWhat it does
Config.Devices.PresenceCheckSeconds5secondsHow often an active device is re-checked as still being in the player's inventory.
Config.Devices.TurnOffOnDownfalsetrue / falseSwitch devices off when the wearer goes down.

Police jobs

Who counts as police decides who gets a memory from a camera report, who can be sent statements, and who sees the "possible match" hint line.

KeyDefaultAllowedWhat it does
Config.Jobs.Police{ 'police' }your job namesJobs that count as police (add your sheriff or FIB jobs here).
Config.Jobs.RequireDutytruetrue / falseMust be on duty to count as police.
Config.Jobs.HintJobs{ 'police' }your job names, or {}The only jobs that see the "possible match" hint after a scan. {} turns the hint off for everyone.
Config.Jobs.HintRequireDutyfalsetrue / falseThe hint job must be on duty as well.
Config.Jobs.AcceptTypes{ 'leo' }list of type names, or {}A job whose framework type is in this list satisfies Police and HintJobs too. qb and qbx report a type.

Both lists ship with 'police' only, because that is the one police job stock QBCore, Qbox and ESX all have. config.lua keeps a commented example line under each list. Remove the -- to use it, or type your own departments:

lua
Police = { 'police' },
-- Police = { 'police', 'sheriff', 'fib' },   -- example: add your other departments

recognition:selftest checks both lists against your framework's jobs:

ResultWhen
PASS jobs.policeEvery listed job exists.
WARN jobs.policeA job in Police or HintJobs does not exist on your server. The line names it. An unknown job never matches anyone, so it breaks nothing. Remove it or create the job. Also a WARN when none of the Police jobs exists but jobs of a type in AcceptTypes do (for example lspd and bcso with type leo): those jobs are police, and the line names them.
FAIL jobs.policeConfig.Jobs.Police is empty, or not one of its jobs exists and no job gets in through AcceptTypes either (the list is empty, or no job on your server has one of its types). Police features cannot work then.
SKIP jobs.policeYour framework (ox_core, standalone or custom) cannot say whether a job exists, so the names were not checked. On standalone and custom, who is police comes from Hooks.GetCustomJob in bridge/hooks.lua.

Names are compared the way the police check compares them: upper and lower case do not matter, so 'Police' is the police job. When a row is a WARN and nothing failed, the last line reads self-test: no check failed (1 warning(s), see above).

Camera reports

KeyDefaultAllowedWhat it does
Config.Report.PoliceCap601–100Police who read a camera report get a memory of that person capped at this %.
Config.Report.PoliceSeconds604800 (7 days)secondsHow long that police memory lasts.
Config.Report.KeepDays60daysHow long a report stays readable. After that the paper turns blank.
Config.Report.PushToMDTtruetrue / falseAlso send camera reports to the MDT where one is supported.
Config.Report.MDTOnlyForPolicetruetrue / falseOnly camera owners with a police job push to the MDT.
Config.Report.ShowPhototruetrue / falseShow the photo on the paper when one exists.
Config.Report.PendingMax5countPapers held back per character when the inventory is full.
Config.Report.GiveDistance2.5metresRange of "hand over paper" on inventories without item metadata.

MDT options

Used only by the MDT selected in Config.MDTSystem. Names are case-sensitive.

lua
Config.MDT = {
    ['lb-tablet']     = { Mdt = 'Police', TabId = 'reports', TextFieldId = 'description' },
    ['tk_mdt']        = { Page = 'police' },
    ['redutzu-mdt']   = {},
    ['drx_mdt']       = {},
    ['origen_police'] = { Job = 'police' },
    ['wasabi_mdt']    = {},
}
MDTOptionMust match
lb-tabletMdt, TabId, TextFieldIdlb-tablet/config/mdts.json and your report tab's text field id.
tk_mdtPageIts page name.
origen_policeJobIts job name.

Per-MDT behaviour and what each one supports: Police, MDT & Evidence.

Inventory fallbacks

Not every inventory can store item metadata. Where one cannot, the script keeps the device identity in its own table and the item is just a token:

SituationWhat happens
Inventory with metadata (ox, qs, qb v2, jaksam, tgiann, ak47, origen, codem, core)Serial, battery and report id ride on the item. Hand it over normally.
ESX default inventory, or any inventory without metadataDevice identity lives in recognition_devices, paper identity in recognition_reports. Use /recognition:handover <item> to give one to the person in front of you (within Config.Report.GiveDistance).
Standalone, no inventory at allThe script keeps the items. /recognition:items, /recognition:use <item>, /recognition:handover <item>.

Introduce, describe, statements, mirror

These are not devices, but they share the paper item.

Introduce

KeyDefaultAllowedWhat it does
Config.Introduce.Enabledtruetrue / falseTurn it on or off.
.Distance3.0metresFace to face.
.MinLength / .MaxLength2 / 32charactersName length.
.PendingHours2hoursA name that could not be attached yet waits this long for the next scan.
.SameEncounterOnlytruetrue / falseA waiting name is dropped when the two part before a scan.
.Mode'one''one' · 'nearby'Who hears it: the person you face, or everyone close who faces you.
.NotifyListenertruetrue / falseThe listener gets a short line.
.PairCooldownSeconds60secondsBefore the same person can introduce again to the same listener.
.MaxPending321–256Most waiting names one listener can hold. Over the cap, their oldest is dropped.

The picker

The small list of remembered people (labels only — no percentages, no timers) used by Describe and Statement.

KeyDefaultAllowedWhat it does
Config.Picker.TokenSeconds120secondsHow long the list stays valid.
Config.Picker.MaxItems20countThe 20 most recently seen people, shown A–Z.

Describe

Tell a friend what someone looked like. They get a weak memory — never enough to act.

KeyDefaultAllowedWhat it does
Config.Describe.Enabledtruetrue / false
.Cap501–100Maximum % for the friend. Keep it below Config.Scoring.ActThreshold.
.Seconds86400 (24 h)secondsHow long it lasts.
.Distance3.0metres
.AllowedSources{ 'memory', 'camera' }'memory' · 'camera'Which of your memories can be passed on. Second-hand memories never can.
.TalkSeconds8secondsTalking before the description is given.
.CooldownSeconds60secondsBetween two descriptions, counted from opening the list.
.Hinttruetrue / falseAfter any scan, show "Looks like someone you were told about" when a report or description fits.
.HintMinPct251–100The hint shows from this %. It can never reach the act line.
.HintPoliceOnlytruetrue / falseThe hint line only goes to Config.Jobs.HintJobs. false = everyone holding a report or a description sees it.

Witness statements

KeyDefaultAllowedWhat it does
Config.Statement.Enabledtruetrue / false
.AllowedSources{ 'memory', 'camera' }as above
.Delivery'both''paper' · 'mdt' · 'both' · 'choice'Where the statement goes. choice = the player picks.
.AllowAnonymoustruetrue / falseThe writer may stay anonymous, where the MDT can hide the author.
.MaxNotes500charactersFree-text notes.
.WriteSeconds10secondsWriting time.
.CooldownSeconds60secondsBetween two statements, from opening the list.
.DetailPct601–100Cue % from which the paper gives full detail — colours, pattern codes.
.MinCuePct251–100Below this %, a cue is written as "did not see clearly".
.MDTZones{}{ { coords = vector3(x,y,z), radius = 10.0 }, … }Places from which the MDT copy can be sent. Empty = anywhere.
.MdtPerDay5countMost MDT copies per author per day.
.MdtMaxAgeHours48hoursOnly memories seen in the last 48 h can be sent to the MDT.

Mirror check

KeyDefaultAllowedWhat it does
Config.Mirror.Enabledtruetrue / false
.UseEmotetruetrue / falsePlay the mirror emote. Skipped in a vehicle.
.LiveRefreshtruetrue / falseUpdate the card while it is open when your look changes.