Configuration
Every shared/config.lua option: bridge, police, evidence, casings, fingerprints, sampling, lab, camera, cases.
The file is shared/config.lua (clear text, editable). Field settings (laboratories) are done in game with /forensicgestion.
#Bridge
Config.Bridge = {
Framework = 'auto', -- 'auto' | 'vision' | 'qbox' | 'qbcore' | 'esx' | 'standalone'
Inventory = 'auto', -- 'auto' | 'ox_inventory' | 'qs-inventory' | 'qb-inventory' | 'framework' | 'none'
Target = 'auto', -- 'auto' | 'ox_target' | 'qb-target' | 'none'
Society = 'auto', -- not used by this script
Callbacks = 'auto', -- 'auto' (ox_lib > framework callbacks > built-in callbacks) | 'native'
Debug = false,
Admins = {}, -- staff identifiers, e.g. 'license:xxxx', 'discord:xxxx'
AdminAce = 'command', -- staff ACE permission
Standalone = {}, -- standalone hooks
}#Standalone mode
| Function | Returns |
|---|---|
getJob(src) | { name, label, grade, gradeName, onDuty } |
getCharacter(identifier) | character profile |
itemCount(src, name) | quantity |
addItem(src, name, count, metadata) | add |
removeItem(src, name, count, metadata) | remove |
#Integrations
Each integration is only used when the resource is started and enabled here.
Config.Integrations = {
logs = true, -- tc-logs: copy actions to Discord
screenshot = true, -- screenshot-basic: required by the camera
doorlock = true, -- ox_doorlock: fingerprints on doors
emotes = true, -- tablet in hands during /enquete (rpemotes or compatible)
}
Config.Logs = { webhook = 'forensic.default' } -- tc-logs channel key; the webhook itself is set in tc-logs
Config.TabletAnim = { command = 'e tablet2', cancel = { resource = 'rpemotes', export = 'EmoteCancel' } }#Staff and police jobs
Config.AdminDiscords = {} -- Discord IDs always staff (never ship real IDs in a distributed config)
Config.StaffPermissions = { 'gestion_features', 'staff_menu' } -- Vision only
Config.Police = { jobs = { 'police', 'sheriff' } }On Vision, police jobs come from the core (police type). Elsewhere, they are the ones in Config.Police.jobs. Only these jobs, on duty, can access investigations, the lab and seals.
#Evidence
Config.Evidence = {
backend = 'auto', -- 'auto' | 'core' (Vision) | 'internal' (tc_forensic_* tables)
hashSalt = 'change-me', -- ⚠ change it: salt for DNA / fingerprint codes (internal mode)
expireHours = { casing = 168, fingerprint = 72, blood = 72, gunpowder = 24, gsr = 6, fragment = 72, bullet_impact = 72 },
gsrOnShot = true, -- internal mode: gunshot residue is recorded on every shot
}expireHours: lifetime of a trace left on the ground, in hours (internal mode). 0 = unlimited.
#Items
Item names in your inventory:
Config.Items = {
casing = 'douille', camera = 'camera', photo = 'photo', folder = 'dossier_photo',
dnaSample = 'prelevement_adn', printCard = 'fiche_empreintes', gsrTest = 'test_gsr',
kit = 'forensic_kit', gloves = 'gloves', bag = 'evidence_bag',
uvLamp = 'lampe_uv', casingBag = 'sachet_douilles',
}Config.NewItems (Vision only) lists items created automatically at start-up if missing. Elsewhere, see Items.
#Casings
| Option | Default | Role |
|---|---|---|
models | w_pi_flaregun_shell, w_am_case | First model present in the game |
viewDistance | 35.0 | Prop spawn distance |
pickupRange | 1.6 | Pick-up distance |
needFlashlight | true | Light on required to see the prompt |
civilianFlashlight | false | true: the regular flashlight also works for civilians |
pickupTime | 1800 | Pick-up duration (ms) |
everyBullet | true | One casing per bullet, whoever fires |
npcShots / npcRange | true / 150.0 | Armed peds also leave casings |
maxPerSecond | 40 | Per-player anti-abuse cap |
maxProps | 200 | Props displayed at once (the closest ones) |
disableStateBags | { 'inPaintball' } | Player state bags that disable casings (e.g. a paintball mini-game) |
Switch off “Spawn casing on shot” in the core's evidence config menu, otherwise it adds its own duplicate casing.
#Fingerprints
Config.Prints = { vehicles = true, doors = true, cooldown = 300, vehicleScanRange = 3.0 }cooldown: seconds between two prints of the same player at the same place.
#Sampling
Config.Sampling = {
range = 2.5, duration = 6000, -- range (m) and duration (ms)
consentTimeout = 20, -- seconds to accept
forceIfRestrained = true, -- no consent needed if the target is cuffed, down or dead
gsrWindow = 45, -- minutes: a shot within this delay makes the test positive
}#Laboratory
Config.Lab = {
pointRange = 6.0,
atLab = { ballistics = true, dna = false, prints = false, paint = false, gsr = false }, -- analyses that can only start at a lab point
durations = { dna = 240, prints = 180, ballistics = 180, paint = 120, gsr = 90 }, -- seconds
}“Laboratory” points are placed in game (/forensicgestion). An analysed DNA / fingerprint trace always gives the identity, with no prior sampling of the person.
#Camera, cases, UV lamp, bag
Config.Camera = { traceRange = 120.0, quality = 0.72, width = 1280, maxPhotosPerFolder = 40 }
Config.Cases = { manageGrade = 3, categories = { 'Homicide', 'Vol', 'Autre' --[[ … ]] }, roles = { 'Suspect', 'Témoin' --[[ … ]] } }
Config.UvLamp = { prop = 'prop_cs_police_torch_02', color = { 140, 40, 255 }, range = 18.0 }
Config.CasingBag = { slots = 30, maxWeight = 3.0 }Config.Cases.manageGrade: minimum grade to delete a case that is not your own;categoriesandrolesare the lists offered in the interface.Config.CasingBag: each bag has its own chest (30 slots, 3 kg).
#Full file
Show config.lua (243 lines)
Config = {}
---------------------------------------------------------------------------
-- Compatibilité / Compatibility (voir bridge/*.lua)
-- FR : tc-forensic fonctionne avec Vision (core), ESX, QBCore, Qbox ou en standalone.
-- Tout est détecté automatiquement ('auto'). Ne force une valeur que si la détection se trompe.
-- EN : tc-forensic runs on Vision (core), ESX, QBCore, Qbox or standalone.
-- Everything is auto-detected ('auto'). Only force a value if detection is wrong.
---------------------------------------------------------------------------
Config.Bridge = {
Framework = 'auto', -- 'auto' | 'vision' | 'qbox' | 'qbcore' | 'esx' | 'standalone'
Inventory = 'auto', -- 'auto' | 'ox_inventory' | 'qs-inventory' | 'qb-inventory' | 'framework' | 'none'
Target = 'auto', -- 'auto' | 'ox_target' | 'qb-target' | 'none'
Society = 'auto', -- non utilisé par ce script / not used by this script
Callbacks = 'auto', -- 'auto' (ox_lib > callbacks du framework > callbacks internes) | 'native'
Debug = false, -- logs de diagnostic / diagnostic logs
-- FR : identifiants (ex. 'license:xxxx', 'discord:xxxx') considérés comme staff / admin du script.
-- EN : identifiers (e.g. 'license:xxxx') treated as script staff / admins.
Admins = {},
AdminAce = 'command', -- permission ACE pour le staff (add_ace group.admin command allow)
-- FR : crochets pour le mode standalone (sans framework), à remplir si besoin :
-- getJob(src) -> { name, label, grade, gradeName, onDuty }, getCharacter(identifier), itemCount(src, name),
-- addItem(src, name, count, metadata), removeItem(src, name, count, metadata)
-- EN : hooks for standalone mode (no framework), fill in if needed.
Standalone = {},
}
---------------------------------------------------------------------------
-- Intégrations optionnelles / Optional integrations
-- FR : chaque intégration n'est utilisée que si la ressource est démarrée ET si elle est activée ici.
-- EN : each integration is only used when the resource is started AND enabled here.
---------------------------------------------------------------------------
Config.Integrations = {
logs = true, -- tc-logs : copie des actions sur Discord / copies actions to Discord
screenshot = true, -- screenshot-basic : requis pour l'appareil photo / required by the camera
doorlock = true, -- ox_doorlock : empreintes sur les portes / fingerprints on doors
emotes = true, -- tablette en main pendant /enquete (rpemotes ou compatible)
}
-- tc-logs : clé du salon (webhook) utilisée pour les logs. Le webhook Discord lui-même se règle dans tc-logs.
-- tc-logs: channel key used for logs. The Discord webhook itself is configured in tc-logs.
Config.Logs = {
webhook = 'forensic.default',
}
-- Emote jouée avec /enquete (tablette en main) et export pour l'annuler.
-- Emote played with /enquete (tablet in hands) and the export to cancel it.
Config.TabletAnim = {
command = 'e tablet2',
cancel = { resource = 'rpemotes', export = 'EmoteCancel' },
}
-- FR : staff (accès /forensicgestion). Identifiants Discord toujours considérés staff, et permissions
-- globales du core Vision. Sur ESX / QBCore / Qbox : ACE joaat('command'), groupes admin ou Config.Bridge.Admins.
-- EN : staff (access to /forensicgestion). Discord IDs always treated as staff, and Vision core global
-- permissions. On ESX / QBCore / Qbox: ACE joaat('command'), admin groups or Config.Bridge.Admins.
-- ⚠ Ne mets aucun identifiant réel dans une config distribuée / never ship real IDs.
Config.AdminDiscords = {}
Config.StaffPermissions = { 'gestion_features', 'staff_menu' } -- Vision uniquement / Vision only
---------------------------------------------------------------------------
-- Police / Police jobs
-- FR : sur Vision, les jobs police viennent du core (type police). Ailleurs (ESX, QBCore, Qbox, standalone)
-- ce sont les jobs listés ici. Seuls ces jobs, EN SERVICE, accèdent aux enquêtes, au labo et aux scellés.
-- EN : on Vision, police jobs come from the core. Elsewhere they are the jobs listed here.
---------------------------------------------------------------------------
Config.Police = {
jobs = { 'police', 'sheriff' },
}
---------------------------------------------------------------------------
-- Preuves / Evidence
-- FR : sur Vision, les preuves (douilles, empreintes, sang…) sont gérées par le core.
-- Sans ce système, tc-forensic utilise ses propres tables (tc_forensic_evidence, tc_forensic_custody).
-- EN : on Vision, evidence is handled by the core. Without it, tc-forensic uses its own SQL tables.
---------------------------------------------------------------------------
Config.Evidence = {
backend = 'auto', -- 'auto' | 'core' (Vision) | 'internal' (tables tc_forensic_*)
hashSalt = 'change-me', -- ⚠ change cette valeur : sel des codes ADN / empreintes (mode internal)
-- Durée de vie d'une trace restée au sol, en heures (mode internal). 0 = illimité.
expireHours = { casing = 168, fingerprint = 72, blood = 72, gunpowder = 24, gsr = 6, fragment = 72, bullet_impact = 72 },
-- Mode internal : un résidu de tir (gsr) est enregistré à chaque tir d'un joueur (test GSR).
gsrOnShot = true,
}
-- Coffres des preuves (mode internal uniquement : sur Vision ils se placent dans /gestion du core).
-- Chaque entrée : { job = 'police', label = 'Coffre des preuves', coords = vec3(x, y, z), slots = 100, weight = 500 (kg) }
-- Internal mode only (on Vision they are placed in the core's /gestion).
Config.EvidenceLockers = {}
---------------------------------------------------------------------------
-- Objets / Items (noms des items dans ton inventaire). Voir install/ pour les créer.
-- FR : joaat('camera'), joaat('forensic_kit'), joaat('gloves'), joaat('evidence_bag') sont des items « externes » à créer aussi (install/).
-- EN : see install/ to create them (ox_inventory, QBCore, ESX).
---------------------------------------------------------------------------
Config.Items = {
casing = 'douille', -- douille ramassée au sol
camera = 'camera', -- appareil photo
photo = 'photo', -- photo développée
folder = 'dossier_photo', -- dossier qui contient des photos
dnaSample = 'prelevement_adn', -- prélèvement ADN scellé (sur personne)
printCard = 'fiche_empreintes', -- fiche d'empreintes (sur personne)
gsrTest = 'test_gsr', -- test de résidus de tir (consommé)
kit = 'forensic_kit', -- kit de prélèvement (requis pour ADN / empreintes)
gloves = 'gloves', -- gants : pas d'empreintes
bag = 'evidence_bag', -- sachet de preuve scellé (lu par le labo)
uvLamp = 'lampe_uv', -- lampe UV (illégal) : fait ressortir les douilles
casingBag = 'sachet_douilles', -- sachet de douilles : mini-inventaire de 30 places
}
-- Items créés au démarrage s'ils n'existent pas (poids en kg) : Vision uniquement (table joaat('items') du core).
-- Ailleurs, ajoute-les avec les fichiers de install/. / Auto-created on Vision only; elsewhere use install/.
Config.NewItems = {
{ name = 'photo', label = 'Photo', weight = 0.01, type = 'objects' },
{ name = 'dossier_photo', label = 'Dossier photos', weight = 0.2, type = 'objects' },
{ name = 'prelevement_adn', label = 'Prélèvement ADN', weight = 0.05, type = 'objects' },
{ name = 'fiche_empreintes', label = "Fiche d'empreintes", weight = 0.05, type = 'objects' },
{ name = 'test_gsr', label = 'Test de résidus de tir', weight = 0.1, type = 'consumable' },
{ name = 'lampe_uv', label = 'Lampe UV', weight = 0.3, type = 'objects' },
{ name = 'sachet_douilles', label = 'Sachet de douilles', weight = 0.05, type = 'objects' },
}
-- Vision uniquement : corrige la description (fausse) du kit de nettoyage du core.
Config.FixCleaningKitDescription = true
---------------------------------------------------------------------------
-- Douilles physiques au sol (visibles par tout le monde)
---------------------------------------------------------------------------
Config.Casings = {
-- Premier modèle présent dans le jeu (petite douille de laiton).
models = { 'w_pi_flaregun_shell', 'w_am_case' },
viewDistance = 35.0, -- distance d'apparition du prop
pickupRange = 1.6, -- distance pour ramasser
needFlashlight = true, -- lampe allumée obligatoire pour voir le prompt
-- Police en service : sa lampe torche. Les autres : la lampe UV (item).
-- true = la lampe torche classique marche aussi pour les civils.
civilianFlashlight = false,
pickupTime = 1800, -- ms
-- Une douille par balle tirée, quel que soit le tireur (joueur, police en
-- service, PNJ) et l'endroit. Vision : couper « Spawn douille au tir » dans le menu
-- config preuves du core, sinon il ajoute sa propre douille en double.
everyBullet = true,
npcShots = true, -- les PNJ armés laissent aussi leurs douilles
npcRange = 150.0, -- m autour du joueur pour suivre les PNJ qu'il contrôle
maxPerSecond = 40, -- plafond anti-abus par joueur (au-delà : balles ignorées)
maxProps = 200, -- props affichés en même temps (les plus proches)
-- State bags du joueur local qui coupent les douilles (ex. mini-jeu de paintball : tc-paintball).
-- Player state bags that disable casings (e.g. a paintball mini-game).
disableStateBags = { 'inPaintball' },
}
---------------------------------------------------------------------------
-- Empreintes digitales
---------------------------------------------------------------------------
Config.Prints = {
vehicles = true, -- monter dans un véhicule laisse une empreinte (portière)
doors = true, -- ouvrir/fermer une porte ox_doorlock
cooldown = 300, -- s entre deux empreintes du même joueur au même endroit
vehicleScanRange = 3.0, -- relevé des empreintes d'un véhicule (menu Alt)
}
---------------------------------------------------------------------------
-- Prélèvements sur une personne (menu Alt sur un joueur)
---------------------------------------------------------------------------
Config.Sampling = {
range = 2.5,
duration = 6000, -- ms
consentTimeout = 20, -- s pour accepter
-- Sans accord si la cible est menottée, à terre ou morte.
forceIfRestrained = true,
gsrWindow = 45, -- min : un tir dans ce délai rend le test positif
}
---------------------------------------------------------------------------
-- Laboratoire (analyses longues, résultats dans l'interface Enquêtes)
---------------------------------------------------------------------------
Config.Lab = {
-- Points « Laboratoire » : placés en jeu par le staff avec /forensicgestion
-- (Vision : aussi /gestion → Police scientifique) → page Laboratoires
-- (table tc_forensic_settings, clé 'labs').
pointRange = 6.0,
-- Analyses lançables seulement à un point Laboratoire (refusées partout
-- tant qu'aucun point n'est placé).
atLab = {
ballistics = true, -- douilles, poudre, impacts
dna = false,
prints = false,
paint = false,
gsr = false,
},
-- Une trace ADN / empreinte analysée donne toujours l'identité (nom, prénom),
-- sans prélèvement préalable sur la personne.
durations = { -- secondes
dna = 240,
prints = 180,
ballistics = 180,
paint = 120,
gsr = 90,
},
}
---------------------------------------------------------------------------
-- Appareil photo
---------------------------------------------------------------------------
Config.Camera = {
traceRange = 120.0, -- trajectoires visibles (police en service)
quality = 0.72, -- jpg après redimensionnement
width = 1280, -- largeur max de la photo stockée
maxPhotosPerFolder = 40,
}
---------------------------------------------------------------------------
-- Enquêtes
---------------------------------------------------------------------------
Config.Cases = {
manageGrade = 3, -- grade mini pour supprimer une enquête qui n'est pas la sienne
categories = {
'Homicide', 'Tentative de meurtre', 'Fusillade', 'Braquage', 'Vol', 'Cambriolage',
'Trafic de stupéfiants', 'Trafic d’armes', 'Délit de fuite', 'Agression', 'Enlèvement',
'Disparition', 'Fraude', 'Corruption', 'Autre',
},
roles = { 'Suspect', 'Témoin', 'Victime', 'Personne d’intérêt', 'Plaignant', 'Interpellé' },
}
---------------------------------------------------------------------------
-- Lampe UV (item illégal) : utilisée, elle sort une lampe en main qui fait
-- ressortir les douilles au sol. Réutiliser l'item pour la ranger.
---------------------------------------------------------------------------
Config.UvLamp = {
prop = 'prop_cs_police_torch_02',
color = { 140, 40, 255 }, -- violet UV
range = 18.0, -- portée du faisceau
}
---------------------------------------------------------------------------
-- Sachet de douilles : chaque sachet a son propre coffre (inventaire du framework),
-- ouvert à côté de l'inventaire quand on utilise l'item.
---------------------------------------------------------------------------
Config.CasingBag = {
slots = 30,
maxWeight = 3.0, -- kg : 30 douilles (0,1 kg) — les objets lourds n'y rentrent pas
}