Proofs
On this page8
A proof is an automatic snapshot of what an attacker knew about their victim at
the moment they acted. Aim, damage, kill, cuff, uncuff, rob, search, escort,
kidnap, and anything a script logs itself (custom).
Every proof stores both numbers:
- What the actor's character actually remembered at that moment.
- What they could have reached right now — worked out from the scene, even when a live result exists.
That second number is what turns "I recognised him" into something checkable.
Master switches
| Key | Default | Allowed | What it does |
|---|---|---|---|
Config.Proof.Enabled | true | true / false | The whole feature. |
Discord | true | true / false | Also send proofs to the Proofs webhook. |
LogJobs | true | true / false | Write the actor's job, so admins can tell police from robbers. |
EstimateNow | true | true / false | Whether the cue breakdown of "could reach right now" is stored with the proof. Both numbers themselves are always stored. |
What triggers a proof
| Key | Default | Allowed | What it does |
|---|---|---|---|
AimMinMs | 750 | ms | How long you must aim at someone before it counts. |
AimCooldown | 60 | seconds | Between two aim proofs for the same pair. |
AimGapMs | 500 | ms | Gap that breaks one aim into two. |
AimMaxDistance | 150.0 | metres | Furthest an aim proof is taken. |
AimVehicleOccupants | true | true / false | Aiming at a car counts for the players inside, up to four. |
AimIgnoreWeapons | unarmed, flashlight, petrol can, extinguisher, ball, snowball, parachute, digiscanner, hazard can, fertilizer can, metal detector | weapon names | Weapons that never produce an aim proof. |
DamageCooldown | 10 | seconds | Between two damage proofs for the same pair. |
DamageMaxDistance | 300.0 | metres | Furthest a damage proof is taken. |
ClientDamageWaitMs | 1000 | ms | How long to wait for the client side of a damage event. |
KillWindowMs | 3000 | ms | How long a kill may be matched to the last damage. |
ActionAttemptWindowMs | 3000 | ms | How long a cuff or rob attempt has to be confirmed. |
ActionMaxDistance | 5.0 | metres | Furthest an action proof is taken. |
RobGatherSeconds | 5 | seconds | How long a robbery is gathered into one proof. |
Per-action cooldowns
Cooldowns = { cuff = 10, uncuff = 10, rob = 30, search = 30,
escort = 30, kidnap = 30, custom = 0 },Seconds between two proofs of that action for the same pair. custom = 0 means
anything logged through the LogAction export has no per-pair wait — only the
limits below apply.
Reading actions from other scripts
| Key | Default | Allowed | What it does |
|---|---|---|---|
CuffStateKeys | { 'ishandcuffed', 'isHandcuffed', 'isCuffed', 'cuffed', 'cuffs' } | state-bag keys | Player state keys other scripts use for "handcuffed". |
OxInventoryHooks | true | true / false | Use ox_inventory hooks to see robberies (openInventory, swapItems). |
InferActorRadius | 2.5 | metres | When no script named an actor, the nearest facing player is logged as likely. |
Limits
| Key | Default | Allowed | What it does |
|---|---|---|---|
MaxPerActorPerMinute | 60 | count | Most proofs one actor can produce per minute. |
ExportCallsPerMinute | 120 | count | LogAction calls per minute, per calling resource. |
IncidentGapSeconds | 120 | seconds | Gap that separates one incident from the next in the timeline. |
VerifyOnBootRows | 1000 | rows | How many of the newest proof rows are checked for tampering at every start. |
Discord
| Key | Default | Allowed | What it does |
|---|---|---|---|
DiscordCauses | all true | per-cause true / false | Which causes are sent: aim, damage, kill, cuff, uncuff, rob, search, escort, kidnap, custom. |
DiscordOnlyBelow | false | true / false | true = only proofs below the act line go to Discord. |
DiscordSkipOnDutyJobs | {} | e.g. { 'police' } | Jobs whose on-duty actions skip Discord. The database still logs them. |
DiscordBatchSeconds | 5 | seconds | How long proofs are batched before sending. |
Webhook setup: Discord Webhooks.
Tamper-evident log
The proof log is tamper-evident: if someone edits or deletes a row in the database by hand, the check finds it. Run the check at any time with:
recognition:verifyproofs [fromId]It checks the proof log and the admin log and prints the result. A check value is
also posted to the Proofs webhook every ServerConfig.Discord.AnchorEveryRows proofs
(default 100) and at shutdown, so you have an outside copy to compare with.
Lab ID
A fingerprint or DNA match from your evidence script produces a separate Lab ID record for the investigator — not a memory, and not a recognition.
| Key | Default | Allowed | What it does |
|---|---|---|---|
Config.Lab.Enabled | true | true / false | |
Seconds | 604800 (7 days) | seconds | How long a Lab ID lasts. |
RequireCorrectLink | true | true / false | Grant only when the police link points at the real owner. A wrong link grants nothing. |
Recipients | 'officer' | 'officer' · 'onduty' · 'officer_mdt' · 'none' | Who gets it. none = admin log only. |
RepeatWindowSeconds | 600 | seconds | The same lab event again within this time only refreshes the timer. |
PerTargetPerDay | 3 | count | Most lab IDs one officer can get on the same person per day. |
Trust checks
Strictest for evidence data that comes from a player's own game.
| Key | Default | Allowed | What it does |
|---|---|---|---|
ClientTrust.RequireJob | true | true / false | Must have a Config.Jobs.Police job. |
ClientTrust.RequireDuty | true | true / false | Must be on duty. |
ClientTrust.Zones | {} | { { coords = vector3(x,y,z), radius = 10.0 }, … } | Lab rooms. Empty = anywhere. |
ClientTrust.RatePerHour | 10 | count | Most lab IDs one officer can get per hour. |
ClientTrust.CountsForAct | false | true / false | Whether a lab ID from player-side evidence also counts for "may act" and for proofs. false = stored and shown to admins only, unless the server can confirm it. |
Any evidence script can grant one without an adapter:
exports['5code-recognition']:GrantLabIdentification(officerSrc, targetCharKey, opts)Add your resource to ServerConfig.Api.TrustedResources first. See
Police, MDT & Evidence.
Permissions
Report.* and Lab.* both need the extra edit level on top of settings to be
changed from the in-game panel (Config.Admin.SettingPerms).