Random world pedestrians respond to players who speak near them. No scripted NPCs required — the addon hooks into GTA's existing pedestrian population. Optionally, LLM-powered conversation generates unique, contextual responses.
Config file: shared/ambient-npc/default.lua
| Type | boolean |
| Default | true |
Master toggle for the ambient NPC addon.
| Type | number |
| Default | 5.0 |
Distance in metres at which a player's voice triggers a response from nearby pedestrians.
| Type | number |
| Default | 10.0 |
Distance in metres the addon scans for eligible pedestrians to respond.
These are top-level fields on AmbientNPCConfig.
| Setting | Default | Purpose |
|---|---|---|
responseCooldown | 2000 ms | Minimum time between any ambient NPC response |
greetingCooldown | 30000 ms | Per-NPC cooldown before the same ped greets again |
perPedCooldown | 15000 ms | Per-pedestrian cooldown before the same ped responds again |
AmbientNPCConfig.responseCooldown = 2000 AmbientNPCConfig.greetingCooldown = 30000 AmbientNPCConfig.perPedCooldown = 15000
These are top-level fields on AmbientNPCConfig that control which pedestrians are eligible to respond.
| Setting | Default | Purpose |
|---|---|---|
excludeInVehicle | true | Skip pedestrians sitting in vehicles |
requireLineOfSight | true | Only respond if the ped has line of sight to the player |
excludeDeadOrDying | true | Skip dead or critically injured pedestrians |
excludePlayers | true | Skip other player characters |
excludeScriptPeds | true | Skip mission-critical or scripted peds |
allowMissionEntities | false | Allow peds flagged as mission entities |
populationTypeFilter | true | Filter by population group |
AmbientNPCConfig.excludeInVehicle = true AmbientNPCConfig.requireLineOfSight = true AmbientNPCConfig.excludeDeadOrDying = true AmbientNPCConfig.excludePlayers = true AmbientNPCConfig.excludeScriptPeds = true AmbientNPCConfig.allowMissionEntities = false AmbientNPCConfig.populationTypeFilter = true
When populationTypeFilter = true, only peds matching these GTA population type IDs are eligible. All five random population types are allowed by default.
AmbientNPCConfig.allowedPopulationTypes = { [1] = true, -- POPTYPE_RANDOM_PERMANENT [2] = true, -- POPTYPE_RANDOM_PARKED [3] = true, -- POPTYPE_RANDOM_PATROL [4] = true, -- POPTYPE_RANDOM_SCENARIO [5] = true, -- POPTYPE_RANDOM_AMBIENT }
Array of ped model hash strings to exclude from ambient interactions. Empty by default.
AmbientNPCConfig.excludeModels = { -- "s_m_y_cop_01", -- example: exclude police }
| Type | boolean |
| Default | true |
Prefer the NPC the player is facing over a slightly closer one behind them.
| Type | number |
| Default | 0.5 |
Blends distance and facing direction when selecting the target NPC. 0 = pure distance, 1 = strong facing preference.
AmbientNPCConfig.useFacingAngle = true AmbientNPCConfig.facingAngleWeight = 0.5
| Type | string |
| Default | "3d" |
| Values | "3d" | "2d" | "icon" |
Controls where voice hint phrases are displayed.
"3d" — floating bubble above the targeted NPC's head"2d" — screen overlay (always visible)"icon" — icon only, no phrase suggestionsAmbientNPCConfig.hintMode = "3d"
Voice layer configuration for the addon.
AmbientNPCConfig.layer = { name = "ambient_npc", priority = 45, }
| Type | boolean |
| Default | true |
Master toggle for NPC TTS speech during ambient interactions.
| Type | number |
| Default | 10.0 |
3D audio hearing range for ambient NPC TTS speech (metres).
Individual toggles for each response category:
AmbientNPCConfig.feedback.responseToggles = { greeting = true, -- initial acknowledgment farewell = true, -- goodbye response askTime = true, -- "what time is it?" smallTalk = true, -- general conversation askLocation = true, -- directions / location questions call911 = true, -- calling police responses callDoctor = true, -- calling EMS responses follow = true, -- follow me responses navigation = true, -- take me there / waypoint responses }
AmbientNPCConfig.feedbackTiming = { responseCooldown = 1500, -- ms between any TTS responses duplicatePrevention = 5000, -- ms before the same phrase can repeat }
| Setting | Default | Purpose |
|---|---|---|
stopToTalkChance | 90 | % chance the NPC stops walking to respond (LLM mode always stops) |
resumeWanderDelay | 5000 ms | Time before the NPC resumes their original state after no interaction |
wanderRadius | 20.0 m | Fallback wander radius when restoreState = false |
restoreState | true | Restore the NPC's original task/animation after the conversation ends |
AmbientNPCConfig.behavior = { stopToTalkChance = 90, resumeWanderDelay = 5000, wanderRadius = 20.0, restoreState = true, }
When a pedestrian is playing a phone animation, they can be configured to ignore or deflect player voice input.
| Type | boolean |
| Default | true |
| Type | number (%) |
| Default | 70 |
Percentage chance that a phone-busy pedestrian refuses to respond.
AmbientNPCConfig.phoneDetection = { enabled = true, refuseChance = 70, }
Pedestrians can call 911 or the doctor in response to player voice input or nearby events.
| Type | boolean |
| Default | true |
Master toggle for the emergency call system.
Both share the same structure:
| Field | Default | Purpose |
|---|---|---|
enabled | true | Enable this call type |
callDuration | 5000 ms | Time the NPC stays on the phone before dispatch triggers |
refuseChance | 15 % | Chance the NPC refuses to call (hostile NPCs may override) |
onDispatch.type | "client" | "client" or "server" for the dispatch event |
onDispatch.event | nil | Custom event to fire on dispatch — nil disables |
onDispatch.cb | function | Optional Lua callback fired on dispatch (default prints debug info) |
AmbientNPCConfig.emergencyCall = { enabled = true, call911 = { enabled = true, callDuration = 5000, refuseChance = 15, onDispatch = { type = "client", event = nil, -- e.g. "ps-dispatch:911call" cb = function(data) print(('[911 Dispatch] callType=%s player=%s'):format(data.callType, data.playerServerId)) end, }, }, callDoctor = { enabled = true, callDuration = 5000, refuseChance = 15, onDispatch = { type = "client", event = nil, -- e.g. "ems-dispatch:callout" cb = function(data) print(('[Doctor Dispatch] callType=%s player=%s'):format(data.callType, data.playerServerId)) end, }, }, }
Set onDispatch.event to integrate with custom dispatch resources such as ps-dispatch or cd_dispatch. Set type = "server" if your dispatch resource listens for server events. cb and event can be used independently or together.
Players can ask a pedestrian to follow them. The NPC follows until the duration expires, the player gets too far ahead, or the player dismisses them.
| Type | number (seconds) |
| Default | 45 |
How long the NPC will follow before stopping on their own.
| Type | number (metres) |
| Default | 20.0 |
If the player moves further than this distance ahead, the NPC gives up and stops following.
Percentage chance the NPC agrees to follow, by personality type:
| Type | Default | Notes |
|---|---|---|
hostile | 40 % | Hostile NPCs may refuse |
shy | 100 % | Always accepts (with hesitant flavor line) |
default | 100 % | All other NPCs always accept |
AmbientNPCConfig.follow = { maxDuration = 45, breakDistance = 20.0, acceptChance = { hostile = 40, shy = 100, default = 100, }, }
Players can ask a pedestrian for directions. The NPC sets a GPS waypoint to a nearby location. Trait-based behaviors affect accuracy and willingness.
| Type | boolean |
| Default | true |
Per-trait overrides for navigation responses:
| Trait | Effect |
|---|---|
hostile | refuseChance = 40 — may refuse even if they know the place |
deceptive | wrongLocationChance = 25 — 25% chance of setting a wrong waypoint |
alcoholic | wrongLocationChance = 40 — 40% chance of giving wrong directions |
street_smart | alwaysAccepts = true — always helps with a detailed flavor response |
AmbientNPCConfig.navigation = { enabled = true, traitBehavior = { hostile = { refuseChance = 40 }, deceptive = { wrongLocationChance = 25 }, alcoholic = { wrongLocationChance = 40 }, street_smart = { alwaysAccepts = true }, }, }
When gunshots or violence occur nearby, ambient NPCs react based on their personality traits — fleeing, freezing, calling police, or ignoring.
| Type | boolean |
| Default | true |
crimeReaction.detection = { radius = 30.0, -- how far NPCs can "hear" gunshots(metres) innerRadius = 15.0, -- guaranteed reaction range(no LOS needed) requireLineOfSight = false, -- gunshots are audible without LOS combatCheckInterval = 500, -- ms between combat state checks(when armed) scanInterval = 1000, -- ms between NPC scans during active crime crimeWindowDuration = 15000, -- ms crime state stays active after last shot/kill maxReactivePeds = 8, -- performance cap on simultaneously reacting NPCs }
crimeReaction.timing = { reactionDelay = { min = 300, max = 1500 }, -- delay before NPC reacts policeCallDelay = { min = 8000, max = 20000 }, -- delay before witness calls police freezeDuration = { min = 2000, max = 6000 }, -- how long frozen NPCs stay frozen cooldownPerPed = 30000, -- cooldown before same NPC can react again }
| Type | Flee | Freeze | Call Police | Scream | Notes |
|---|---|---|---|---|---|
cowardly | 70% | 20% | 20% | 80% | Default for most NPCs |
paranoid | 40% | 50% | 60% | 40% | Nervous types |
brave | 30% | — | 80% | 10% | May confront nearby threat |
criminal | 10% | — | 5% | 0% | Mostly ignores (80%) |
neutral | 60% | 15% | 30% | 50% | Mixed reaction |
crimeReaction.police = { enabled = true, wantedLevelIncrease = 1, -- stars added per witness police call maxWantedFromWitnesses = 2, -- cap on witness-triggered wanted level dispatchDelay = 3000, -- ms after call before wanted level applies -- Uses emergencyCall.call911.onDispatch callback from main config }
Crime reaction police dispatch reuses the emergencyCall.call911.onDispatch callback configured in the main config. Set that callback's event field to route crime-triggered 911 calls to your dispatch resource.
When LLM is available (BYOK configured and Config.LLM.enableAddonLLM = true), ambient NPCs generate unique conversational responses instead of using predefined phrase pools.
| Type | number |
| Default | 10 |
Number of previous message turns to include in the LLM context for each conversation.
| Type | number |
| Default | 200 |
Maximum character length for LLM-generated responses.
| Type | string |
| Default | "" |
Optional additional instructions appended to the system prompt for all ambient NPC LLM conversations. Use to customize personality or restrict topics.
AmbientNPCConfig.llm = { maxHistoryMessages = 10, maxResponseLength = 200, systemPromptExtra = "", }
Last updated about 9 hours ago