Configuration for the npc-robbery addon is defined in shared/npc-robbery/default.lua.
The addon lets players rob ambient NPCs at gunpoint using voice commands. Point a weapon at an NPC for 500ms to trigger the robbery. The NPC reacts based on personality traits (brave, cowardly, wealthy, etc.), voice commands progress through demand/threaten phases, and witnesses nearby may react or call the police.
Controls how aim detection works.
| Type | number (ms) |
| Default | 200 |
How often the aim detection raycast runs. Lower values are more responsive but slightly more CPU-intensive.
| Type | number (metres) |
| Default | 30.0 |
Maximum distance the camera raycast checks for a valid NPC target.
| Type | number (ms) |
| Default | 500 |
How long the player must continuously aim at the same NPC before the robbery triggers.
| Type | number (metres) |
| Default | 15.0 |
Maximum distance between player and NPC for a robbery to be valid. The raycast range is intentionally wider to allow detection; this clamps the actual trigger range.
detection = { pollInterval = 200, raycastDistance = 30.0, targetingDuration = 500, maxDistance = 15.0, }
| Type | string[] |
Array of weapon hash names that are considered valid robbery weapons. Only weapons in this list can trigger a robbery. Includes pistols, SMGs, and shotguns by default. Rifles and explosives are intentionally excluded.
Default weapon categories:
weapons = { "WEAPON_PISTOL", "WEAPON_SMG", -- add or remove weapon hashes here }
| Type | string[] |
NPC model hashes that cannot be robbed. Police, military, security, FIB/IAA, and prison guard models are excluded by default (19 models total). Add any model hash string to prevent it from being targeted.
excludeModels = { "s_m_y_cop_01", "s_m_y_swat_01", "s_m_y_armymech_01", -- add custom exclusions here }
Core NPC behavior settings during a robbery.
| Type | number (ms) |
| Default | 30000 |
How long an NPC stays in the hands-up state before the robbery auto-times out (30 seconds).
| Type | number (ms) |
| Default | 0 |
Delay before the NPC plays their initial fear TTS phrase after being threatened. 0 plays it immediately.
| Type | boolean |
| Default | true |
Whether the NPC continuously looks at the player while held at gunpoint.
| Type | number (ms) |
| Default | 8000 / 15000 |
Random range for how long the NPC waits after the player lowers their gun before attempting to flee. The actual per-behavior timers in behaviors override these when applicable.
| Type | number (metres) |
| Default | 100.0 |
Distance the NPC flees when escaping.
| Type | number (metres) |
| Default | 10.0 |
If the player moves further than this distance from the NPC while the robbery is active, the NPC immediately flees.
behavior = { handsUpDuration = 30000, fearSpeakDelay = 0, lookAtPlayerWhileThreatened = true, escapeTimerMin = 8000, escapeTimerMax = 15000, escapeFleeDistance = 100.0, escapeLookAroundChance = 30, escapeIfPlayerFarDistance = 10.0, }
| Type | number (ms) |
| Default | 300000 (5 minutes) |
Per-NPC cooldown. The same NPC cannot be robbed again for 5 minutes after a completed robbery.
| Type | number (ms) |
| Default | 30000 (30 seconds) |
Global cooldown between any two robberies by the same player.
cooldowns = { perNpc = 300000, global = 30000, }
NPC behavior types are determined by personality traits. Each type has its own config block.
When an NPC has no relevant traits, a random behavior is assigned using these weights:
behaviorFallback = { enabled = true, weights = { passive = 55, cowardly = 25, tough = 12, wealthy = 8, } }
Default behavior for most NPCs with no special traits. Complies after enough pressure; may attempt to flee after gunpoint is lost.
behaviors.passive = { escapeChance = 60, -- % chance to flee when gun is lowered fightBackChance = 0, -- never fights back }
Triggered by traits: brave, hostile, criminal_mindset. Will warn the player, potentially fight back, and escalates as the player re-aims.
behaviors.tough = { enabled = true, fightBackChance = 35, -- % chance to fight back when gun lowered fightBackDelay = 2000, -- ms before fight-back decision warningChance = 60, -- % chance to warn before fighting escalation = { fightBackBonus = 15, -- % added per re-aim cycle maxFightBackChance = 90, -- cap reaimEffectivenessLoss = 20, -- % lost per re-aim cycle defianceInterval = 5000, -- ms between defiance outbursts at gunpoint } }
Triggered by traits: coward, paranoid. May faint, freeze, or panic instead of complying normally.
behaviors.cowardly = { enabled = true, faintChance = 15, -- % chance to pass out freezeChance = 25, -- % chance to freeze up panicChance = 35, -- % chance to panic/scream faintDuration = 15000, -- ms spent fainted before recovering and fleeing }
Triggered by the economic trait tag. Carries more money and higher-value items; may offer a bribe or negotiate instead of complying.
behaviors.wealthy = { enabled = true, -- reward multipliers defined in rewards section(2.5x money, 2.5x items) }
| Type | boolean |
| Default | true |
Use gender-aware animation variants for hands-up and fear poses.
| Type | boolean / number (%) |
| Default | true / 30 |
Whether kneeling animations are eligible, and the percentage chance one is chosen over a standing pose.
| Type | boolean |
| Default | true |
Cycles through the animation pool instead of repeating the same pose.
| Type | boolean |
| Default | true |
Enables mid-robbery animation shifts (flinch, cower, beg) at random intervals while the player holds the NPC at gunpoint.
| Type | number (ms) / number (%) |
| Default | 4000 / 30 |
How often a dynamic reaction is checked for and the chance it triggers.
Fidget animations are disabled (fidgetEnabled = false). Upper-body fidget loops caused animation conflicts. Do not enable without testing.
animations = { useVariants = true, kneelingEnabled = true, kneelingChance = 30, cycleAnimations = true, dynamicReactions = true, reactionInterval = 4000, reactionChance = 30, fidgetEnabled = false, -- do not enable }
Controls NPC speech responses during the robbery.
| Type | boolean |
| Default | true |
Master toggle for NPC TTS speech during robberies.
| Type | number (metres) |
| Default | 15.0 |
3D audio hearing range for robbery TTS speech.
Individual toggles for each response category:
feedback.responseToggles = { fearInitial = true, -- initial fear phrase on robbery trigger compliance = true, -- compliance phrase after demand/threaten toughDefiance = true, -- tough NPC taunts at gunpoint }
feedbackTiming = { responseCooldown = 2000, -- ms minimum between TTS responses duplicatePrevention = 10000, -- ms before the same phrase can repeat }
Server-side reward calculation. Framework and inventory are auto-detected.
rewards.money = { enabled = true, base = { min = 50, max = 200 }, -- base cash range multipliers = { passive = 1.0, cowardly = 0.8, tough = 1.5, wealthy = 2.5, }, emptyChance = 25, -- % chance the NPC has nothing }
rewards.items = { enabled = true, maxItems = 2, -- max items per robbery pool = { { item = "phone", chance = 25 }, { item = "wallet", chance = 35 }, { item = "goldchain", chance = 5 }, { item = "rolex", chance = 3 }, }, chanceMultipliers = { passive = 1.0, cowardly = 0.7, tough = 1.2, wealthy = 2.5, }, cooldown = 60000, -- server-side per-player cooldown(ms) }
Wealthy NPCs have an additional exclusive item pool:
behaviors.wealthy.items = { { item = "rolex", chance = 20 }, { item = "diamond_ring", chance = 10 }, }
Item names must match your inventory system. For ox_inventory, use the item names defined in your items.lua. For QBCore/ESX, use the item names registered in your shared items table.
| Type | boolean |
| Default | true |
Enable voice commands during robberies. When disabled, the player cannot use voice to demand money, threaten, or give permission.
| Type | string / number |
| Default | "npc_robbery" / 70 |
Voice layer identifier and priority. At priority 70 this overrides npc_interact (55), ambient_npc (40), and shops (60).
The robbery progresses through demand and threaten phases based on voice commands:
voiceInteraction.phases = { demand = { maxRefusals = 2, -- NPC can refuse this many times before forced comply refuseChance = 50, -- % initial chance NPC refuses the demand lieChance = 30, -- % chance NPC lies about having nothing }, threaten = { complyChance = 65, -- % chance NPC complies after being threatened cowerChance = 40, -- % chance NPC plays cower animation during threat }, }
Five command slots are registered. The default trigger phrases:
| Command | Example phrases |
|---|---|
robbery_demand | "give me what you have", "empty your pockets", "hand over the money" |
robbery_threaten | "I will shoot you", "last chance", "don't make me do this" |
robbery_hurry | "hurry up", "faster", "come on" |
robbery_permission_yes | "yes go", "you can leave", "get out of here" |
robbery_permission_wait | "wait", "stay there", "don't move" |
witnesses.detection = { enabled = true, radius = 25.0, -- outer detection range(metres) innerRadius = 10.0, -- guaranteed detection within this range(no LOS required) requireLineOfSight = true, scanInterval = 1000, -- ms between witness scans maxWitnesses = 5, -- performance cap }
witnesses.timing = { reactionDelay = { min = 500, max = 2000 }, policeCallDelay = { min = 5000, max = 15000 }, freezeDuration = { min = 3000, max = 8000 }, cooldownPerWitness = 30000, }
| Type | Flee | Freeze | Call Police | Scream | Notes |
|---|---|---|---|---|---|
cowardly | 70% | 25% | 30% | 80% | Default for most NPCs |
paranoid | 40% | 50% | 60% | 40% | Nervous types |
brave | 20% | — | 80% | 10% | May confront player (25%) |
criminal | 10% | — | 10% | 0% | Mostly ignores robbery (70%) |
neutral | 50% | 20% | 40% | 50% | Mixed reaction |
witnesses.police = { enabled = true, wantedLevelIncrease = 1, -- stars added per witness police call maxWantedFromWitnesses = 2, -- max stars added by witnesses dispatchDelay = 3000, -- ms after call before wanted level applies -- Optional custom event(disabled by default) onPoliceCall = { enabled = false, type = "server", event = "your:policeDispatch", } }
Set onPoliceCall.enabled = true and provide an event name to integrate with custom police dispatch systems (e.g. ps-dispatch, cd_dispatch). The event receives the witness ped's position.
The server script (addons/npc-robbery/server.lua) auto-detects the active framework and inventory system. No manual configuration is required.
Supported frameworks: QBCore, QBx, ESX
Supported inventories: ox_inventory (preferred), QBCore inventory, ESX inventory
Server events:
| Event | Direction | Description |
|---|---|---|
npc-robbery:giveReward | Client → Server | Request reward after successful robbery |
npc-robbery:rewardResult | Server → Client | Delivers reward summary (money amount, items, empty flag) |
Server-side cooldown: 60 seconds per player (independent of client cooldowns) to prevent exploit via resource restart.
Two client-side exports are available for other resources:
-- Check if the addon is initialized and running local active = exports['onex-voiceInteraction']:isRobberyActive() -- Get list of currently threatened NPC entity handles local npcs = exports['onex-voiceInteraction']:getThreatenedNPCs()
Last updated 14 days ago