[PAID] srz_npc_witness — Advanced NPC Witness & AI Dispatch System

[PAID] srz_npc_witness — Advanced NPC Witness & AI Dispatch System

You shot a guy. You thought nobody saw. But that grandma across the street? She’s already on the phone describing your car to the police. And she got the color wrong because she’s drunk.

NPCs actually notice your crimes, freak out, pull out a phone, and call the cops. Each caller has their own personality — some panic, some lie, some are just vibing. Reports stack when multiple witnesses call about the same thing.

:movie_camera: Showcase

:shopping_cart: Purchase

Price: €24.99
:link: Buy on Tebex

:book: Documentation

:link: Full Documentation


:speech_balloon: Join the Discord for support, updates, and feature requests.


:fire: Features

Core System

  • Heat-based detection — Criminal actions accumulate “heat”. When heat exceeds a threshold, nearby NPCs initiate a 911 call with a phone animation. Continued crime escalates into multiple simultaneous calls (up to 12 concurrent)
  • 17 crime types — Shooting, carjacking, fistfights, hit & run, explosions, aiming, car alarm, visible weapon, dead body, weapon threat, and more. Each individually toggleable
  • Immediate report events — Critical crimes (murder, explosion, dead body) bypass the heat system entirely and trigger instant NPC calls
  • NPC phone animation — Witnesses pull out a phone prop and play a call animation. The report is only sent when the call finishes
  • NPC reaction phase — Before calling, NPCs stop, turn toward the crime scene, and play a reaction animation (shock, disgust, facepalm). Gives players a visual cue and a short window to intervene
  • Intimidation system — Aim a weapon at a calling NPC to interrupt the call. They panic and flee. Kill them to cancel it permanently
  • Coward NPCs — Configurable per-event chance that an NPC flees instead of calling
  • Background calls — If an NPC goes out of range or despawns mid-call, the call continues in the background and cannot be stopped. Should’ve been faster

Witness Detection

  • Scanner-based detection — Dedicated client-side scanners for reliable detection, independent of GTA’s unreliable native events
  • Multi-method vehicle hit detection — 4 parallel methods ensure hits are always detected
  • Line of sight + hearing — NPCs with direct LOS contribute to heat. NPCs within 40m without LOS can hear events
  • Vehicle witnesses — NPCs in passing vehicles can witness crimes
  • Aiming detection — NPCs that see you free-aiming a weapon in public contribute to heat — no need to aim directly at them
  • Carjacking victims — The driver being pulled from a vehicle becomes a guaranteed witness with an immediate call
  • Player-only attribution — Only events where the player is directly involved are processed. NPC-vs-NPC crimes don’t falsely implicate the player
  • No-suspect calls — Distant events (random explosion, far car alarm) generate calls without suspect descriptions

Caller AI — 5 Personalities, 160+ Templates

  • 5 caller profilesCalm, Panic, Angry, Elderly, Drunk — each with unique speech patterns, accuracy levels, and behavioral traits
  • ~160 unique call templates — Per profile + event type, with 4-5 variants each. No two reports sound the same
  • Realistic confusion — Callers make mistakes based on their personality. The drunk caller will describe your red car as blue. An elderly caller confuses your pistol for a rifle. Not a bug — it’s a feature
  • Guaranteed useful data — Every caller provides at least 1 correct detail
  • Snapshot at crime time — Suspect appearance is captured instantly, not when the call finishes

Corroboration & Consensus

  • Report merging — Multiple calls for the same crime merge into a single report
  • Weighted consensus — Each caller’s vote is weighted by accuracy × distance × environment. Plate holders get bonus weight
  • VERIFIED / DISPUTED / UNCONFIRMED tags — Indicates consensus quality with confidence bars
  • Stacked transcripts — All call transcripts display in a single scrollable section

Environment & Disguise

  • Night vision reduction — NPCs see 50% as far at night (configurable hours)
  • Weather impact — Rain (65%), fog/smog (40%) reduce NPC vision range
  • Mask/disguise system — Masks reduce heat accumulation (65%) and fuzz the reported location by up to 100m. Crime responsibly

Built-in Dispatch UI

  • Full dispatch panel — Central map + sidebar layout with scrollable call list, severity badges, timestamps, caller profile, reliability score
  • Real-time interactive map — Leaflet map with GTA satellite image. Each report gets a unique color with markers for every witness position, connected with dashed lines
  • Unified transcripts — Primary + corroborating call transcripts merged in one section
  • Mini-HUD — Always-visible widget showing the latest report
  • Filter system — By severity (CODE 1/2/3) or crime type. Applies to sidebar and map
  • GPS integration — One-click waypoint from any report
  • Audio alerts — Distinct tones for CODE 2 and CODE 3. Optional auto-open on CODE 3
  • Report expiry — Configurable auto-cleanup (default 180s)
  • Reduced UI mode — Item-based access shows a limited view without debug data

Access Control

Mode Description
all Everyone can access the full dispatch
job Restrict to specific jobs (police, ambulance, sheriff, etc.)
ace ACE permission: srz_witness.dispatch
export External scripts control access via exports
Item-based Players with a specific item (e.g. radio) get reduced access

:electric_plug: Full Export API

Plug it into whatever dispatch you already use, or use ours.

Server Exports

-- Query reports
exports.srz_npc_witness:GetRecentReports(10)
exports.srz_npc_witness:GetReportsByType('shooting', 20)
exports.srz_npc_witness:GetReportsBySeverity(3, 10)
exports.srz_npc_witness:GetReportById(42)
exports.srz_npc_witness:GetReportsByPlayer(serverId, 10)
exports.srz_npc_witness:GetReportsSince(600)
exports.srz_npc_witness:GetReportsByZone('Vinewood', 10)
exports.srz_npc_witness:GetReportsByStreet('Innocence Blvd', 10)
exports.srz_npc_witness:GetReportsInRadius(x, y, z, 200.0, 20)

-- Statistics
exports.srz_npc_witness:GetStats()
exports.srz_npc_witness:GetReportCount()

-- Inject custom reports from other scripts
exports.srz_npc_witness:PushReport({ ... })

-- Admin
exports.srz_npc_witness:ClearReports()
exports.srz_npc_witness:IsEventEnabled('shooting')
exports.srz_npc_witness:GetEnabledEvents()

Client Exports

exports.srz_npc_witness:GetCurrentHeat()
exports.srz_npc_witness:SetHeat(150)
exports.srz_npc_witness:ResetHeat()
exports.srz_npc_witness:GetWitnessCount()
exports.srz_npc_witness:GetActiveCallers()
exports.srz_npc_witness:IsPlayerDisguised()
exports.srz_npc_witness:OpenDispatchUI()
exports.srz_npc_witness:CloseDispatchUI()
exports.srz_npc_witness:ToggleDispatchUI()
exports.srz_npc_witness:IsDispatchOpen()
exports.srz_npc_witness:CanAccessDispatch()
exports.srz_npc_witness:SendWitnessReport('shooting', vector3(100, 200, 30))

Server Events

AddEventHandler('srz_npc_witness:onReport', function(report) end)
AddEventHandler('srz_npc_witness:onReport:shooting', function(report) end)
AddEventHandler('srz_npc_witness:onSeverity:3', function(report) end)
AddEventHandler('srz_npc_witness:onCorroborate', function(updatedReport) end)

Client Events

RegisterNetEvent('srz_npc_witness:dispatch', function(report) end)
RegisterNetEvent('srz_npc_witness:personalAlert', function(report) end)
RegisterNetEvent('srz_npc_witness:corroborate', function(updatedReport) end)

:jigsaw: Integration Examples

MDT Integration

AddEventHandler('srz_npc_witness:onReport', function(report)
    exports.your_mdt:AddDispatchCall({
        id       = report.id,
        title    = report.label,
        message  = report.callerData and report.callerData.callText or '',
        coords   = report.coords,
        severity = report.callerData and report.callerData.severity or 1,
    })
end)

Discord Webhook (CODE 3 only)

AddEventHandler('srz_npc_witness:onSeverity:3', function(report)
    PerformHttpRequest('https://discord.com/api/webhooks/...', function() end, 'POST',
        json.encode({
            embeds = {{
                title = 'CODE 3 — ' .. (report.label or '?'),
                description = report.callerData and report.callerData.callText or '',
                color = 16711680,
            }},
        }),
        { ['Content-Type'] = 'application/json' })
end)

Disable Built-in UI (External Dispatch Only)

Config.UI.enabled = false
-- Reports still flow through events and exports

:gear: Configuration

80+ configurable options in config.lua. If you can think of it, you can probably toggle it.

Section What it controls
Heat System Threshold, decay, per-crime values, witness multipliers
NPC Behavior Call duration, max simultaneous calls, flee chance, intimidation range, reaction phase
Per-Event Overrides Custom call duration + flee chance per crime type
Environment Night hours, weather vision multipliers
Disguise Heat reduction, position fuzzing distance
Corroboration Merge window, reliability boost, max witnesses
Caller AI Profile weight overrides, raw data toggle
Dispatch UI Command, keybind, access mode, sounds, report expiry, auto-open
Events Toggle each of 17 crime types on/off
Zone Blacklist Disable witness system in specific zones
Locale EN/IT included, add your own

:package: Installation

  1. Copy srz_npc_witness into your resources folder
  2. Add ensure srz_npc_witness to your server.cfg
  3. Configure config.lua
  4. Set EnableClientDebug = false and showDebugInfo = false for production

:globe_with_meridians: Framework Support

Works standalone out of the box. QBX/QBCore/ESX auto-detected if you want job-restricted dispatch access.

Dependency Required Notes
QBX Core / QBCore / ESX Optional Only needed if accessMode = 'job'
ox_inventory Optional Only needed if itemAccess.enabled = true

:earth_africa: Languages

English and Italian included. Add your own by copying locales/en.lua.


Code is accessible No (config, framework bridge, locales, full web UI are open)
Subscription-based No
Lines (approximately) ~6,400
Requirements None (standalone). Optional: QBX/QBCore/ESX, ox_inventory
Support Yes

This post was written with the help of AI.

3 Likes