Install & integrate
Everything you need to drop lrr_intel_npc into a FiveM QBox server — requirements, installation, the smallresources pre-step, exports, server events, callbacks and dev tooling.
Requirements
Intel NPC is a FiveM resource targeting the modern QBox stack. These are the same dependencies most QBox servers already run — no exotic stack required.
| Dependency | Used for |
|---|---|
qbx_core | Player identity (citizen ID, character name) and money transactions. |
ox_lib | Notifications, NUI callbacks, the points API for static persona spawn zones, model-request helpers. |
ox_target | The third-eye interaction surfacing Talk / Buy item / Open shop on persona NPCs. |
ox_inventory | The buy-item callbacks and in-dialogue shop catalogs. Falls back to lib.context if the catalog ID isn't registered as an ox shop. |
Installation
- Drop the resource. Place
lrr_intel_npcinto yourresources/folder. - Ensure it. Add
ensure lrr_intel_npcto yourserver.cfg. - Restart the server. You should see the boot lines below in the FiveM server console.
[lrr_intel_npc] loaded with 1 static persona(s)
[lrr_intel_npc police] module loaded — pedHit=true redlight=true speeding=true
[lrr_intel_npc dev_population] density boost on — ped=2.0 veh=2.0
By default Config.debug = false, so the dev menu, dev commands, 3D overlays and map blips are all off. To enable dev mode without editing files, add a convar to server.cfg:
setr lrr_intel_npc:debug 1
Pre-installation: defang qbx_smallresources
Several qbx_smallresources resources actively fight the police features — they suppress ambient cop spawning, clamp SetMaxWantedLevel to 0 and hide the wanted-stars HUD. Intel NPC keeps per-frame safety nets that re-assert each flag, so it works without these edits — it's just cleaner to disable the upstream interference once instead of racing it forever.
The edit is ~10 lines total across three files. Skipping it still works — you'll just see mild flicker in the millisecond windows where a competing resource momentarily wins the race.
1 — qbx_ignore/client.lua
Comment out the three cop-suppression lines, otherwise no cops appear in traffic.
-- SetCreateRandomCops(false)
-- SetCreateRandomCopsNotOnScenarios(false)
-- SetCreateRandomCopsOnScenarios(false)
2 — qbx_disableservices/config.lua
Lift the max-wanted clamp so the 1-star RP heat sticks. Keep police-related dispatch services off so native dispatch can't stack shooting cops on the scripted RP unit; emergency services and NPC-faction backup stay on.
return {
maxWantedLevel = 5, -- was 0
enabledServices = {
[1] = false, -- PoliceAutomobile
[3] = true, -- FireDepartment
[5] = true, -- AmbulanceDepartment
[11] = true, -- Gangs (faction backup)
[14] = false, -- ArmyVehicle
},
}
3 — qbx_hudcomponents/config.lua
Remove HUD component 1 (HUD_WANTED_STARS) from the disable list so players can see the heat building.
hudComponents = {2, 3, 4, 7, 9, 13, 19, 20, 21, 22} -- 1 removed
After the three edits, restart qbx_ignore, qbx_disableservices, qbx_hudcomponents and lrr_intel_npc.
Quick map of the resource
| File | What it does |
|---|---|
shared/config.lua | Every tunable knob. Read this first. |
data/personas.lua | Static persona definitions (Maggie). |
data/dialogue_lines.lua | Per-persona dialogue trees — greetings, topics, recursive followups. |
data/dialogue_ambient.lua | Ambient dialogue trees by category. |
data/character_archetypes.lua | Reaction to archetype mapping. |
client/dialogue.lua | The NUI session machinery — recursive topic rendering, post-actions, patience, mood. |
client/reactions.lua | All reaction handlers — scream_flee, get_out_and_fight, call_cops_at_scene, etc. |
client/police.lua | The police system — triggers, calm RP cop spawning, mid-call NUI, pay-damages. |
client/shop.lua | Persona shop catalogs, with a lib.context fallback. |
server/main.lua | Server callbacks — payDamages, preCallBribe, bribeRespondingCop, shopBuy. |
Adding a persona at runtime
From any external resource, register a persona on the fly. The trigger zone is registered immediately; the ped spawns the next time the player walks within Config.spawn_distance of the coords.
exports.lrr_intel_npc:AddPersona({
id = 'andrew',
name = 'Andrew',
model = 'a_m_y_business_03',
coords = vec4(123.0, 456.0, 78.0, 90.0),
scenario = 'WORLD_HUMAN_SMOKING',
dialogue_id = 'andrew',
archetype = 'compliant',
interactions = {
{ type = 'dialogue', label = 'Talk', icon = 'fa-solid fa-comments' },
},
})
To remove: exports.lrr_intel_npc:RemovePersona('andrew')
Exports
All client-side. Call from any other resource via exports.lrr_intel_npc:Name(args).
Dialogue & reputation
| Export | Description |
|---|---|
OpenStaticDialogue(id) | Open the NUI chat with a static persona. |
OpenAmbientDialogue(entity) | Open the NUI chat with any ped via ambient routing. |
IsDialogueOpen() | Bool — is the NUI panel currently open? |
GetReputation(id) | Number, default 0. |
SetReputation(id, v) | Sets reputation, clamped to [-10, +10]. |
AddReputation(id, d) | Adds a delta, same clamping. |
GetReputationTier(id) | trusted / friendly / familiar / neutral / wary / hostile. |
Personas, police & reactions
| Export | Description |
|---|---|
AddPersona(data) | Registers a persona; returns true, or false if the id is taken. |
RemovePersona(id) | Despawns and unregisters a persona. |
GetPersona(id) / ListPersonas() | Returns a persona table, or the live persona array. |
SetPoliceSystemEnabled(bool) | Runtime toggle for the police module. |
IsPoliceSystemEnabled() / IsInPoliceScene() | Police module state checks. |
TriggerReaction(ped, name) | Fires a named reaction directly. |
Server events you can hook
Every player action that involves the server fires a public event, so an external resource can listen.
-- Item purchase completed
RegisterNetEvent('lrr-intel-npc:server:itemBought', ...)
-- Job request (take_job interaction)
RegisterNetEvent('lrr-intel-npc:server:jobRequested', ...)
-- A witness saw a crime
RegisterNetEvent('lrr-intel-npc:server:witnessReported', ...)
-- An informant leaked an event to dispatch
RegisterNetEvent('lrr-intel-npc:server:informantReported', ...)
-- Cop bribery succeeded
RegisterNetEvent('lrr-intel-npc:server:copBribed', ...)
-- Prostitute service paid
RegisterNetEvent('lrr-intel-npc:server:prostituteServicePaid', ...)
-- Police trigger fired (red_light, speeding, ped_hit)
RegisterNetEvent('lrr-intel-npc:server:policeEvent', ...)
-- Dispatch requested (NPC called 911)
RegisterNetEvent('lrr-intel-npc:server:dispatchRequested', ...)
Server callbacks
Cash-validated, rate-limited, range-clamped and cooldown-gated. Each returns a structured success/failure object.
lib.callback('lrr-intel-npc:payDamages', source, { amount = 250 })
-- success: { success = true, amount = 250 }
-- failure: { success = false, reason = 'no_money' }
lib.callback('lrr-intel-npc:preCallBribe', source, { amount = 200, refuse_chance = 0.3 })
lib.callback('lrr-intel-npc:bribeRespondingCop', source, { amount = 500, refuse_chance = 0.3 })
lib.callback('lrr-intel-npc:shopBuy', source, persona_id, shop_id, item_name, count)
lib.callback('lrr-intel-npc:prostituteService', source, 'full_night', ctx)
Dev commands
/intel_talk is always available (also bound to G). All commands below are NO-OP unless Config.debug = true.
| Command | What it does |
|---|---|
/intel_dev | Open the dev menu (F7 keybind by default). |
/intel_status | Print persona / target / integration diagnostics. |
/intel_tp <id> | Teleport to a persona for testing. |
/intel_what | Print category / archetype / sex / model of the closest ped. |
/intel_hit_test light|moderate|severe | Simulate a car hit on the closest civilian. |
/intel_force_call | Force the closest NPC to call cops. |
/intel_force_fight / /intel_force_flee | Force a fight or flee reaction. |
/intel_police_spawn / /intel_police_clear | Force-spawn a patrol, or reset all police state. |
Compatibility notes
The script ships with per-frame safety nets that re-assert its required flags every tick, so it works out of the box even on a stock qbx_smallresources setup. For cleaner operation, apply the three-file edit in the pre-installation step above.
For ox_inventory native shop UI instead of the lib.context fallback, register persona catalogs in your ox_inventory/data/shops.lua:
['kati_neni_247'] = {
name = "Maggie's 24/7",
inventory = {
{ name = 'cigarette', price = 2 },
{ name = 'pack_cigs', price = 18 },
},
},
The shipped 600+ line README walks through every config knob, export, server event and callback. The Config reference page covers the key tunables.