Crime System¶
Three services work together to track crime, coordinate NPC responses, and clear the player's wanted level.
Services at a Glance¶
| Service | Responsibility |
|---|---|
PlayerService |
Owns the CrimeRecord per player and the advisories cops share |
CentralService |
NPC-to-NPC coordination (unit caps, patrol slots, advisories) |
DispatchService |
Spawning units, search timers, vision checks, car assignment |
Crime Record¶
Every player has a CrimeRecord table in their runtime session (managed by PlayerService). Key fields:
| Field | Meaning |
|---|---|
Score |
Cumulative crime score, drives the star level |
Identified |
True once a cop has made a positive ID on the suspect |
LastPosition |
Last confirmed world position when unidentified, used by NPCs to route to |
RecognitionProgress |
0–1 fill; when it reaches 1 the player is identified |
ClientSearchTick |
Timestamp when a search order was issued; NPCs use it to switch into Search state |
PlayerService:AddCrime(player, score, label) increments the score and attaches a label for the HUD. PlayerService:ClearCrimeRecord resets everything (called on respawn to suppress signals, and by the cashout/jail flow to actually clear it).
Wanted Flow¶
Player commits a crime
└── PlayerService:AddCrime(player, score, label)
└── CrimeRecord.Score += score
└── client Score property updated → star display
Cop spots player
└── PoliceNPCService:CanSeeTarget (line-of-sight check)
└── PlayerService:Identify(player, true, position)
└── CrimeRecord.Identified = true
└── client Identified property updated
Cop spots player carrying weapon
└── CentralService:Advise(player, "HAS_GUN")
└── adds "HAS_GUN" to CrimeRecord.CopAdvise
Wanted level clears
└── player arrested OR cashout OR score decays to 0
└── PlayerService:ClearCrimeRecord
└── CrimeScoreClearedSignal fires
Dispatch Loop¶
DispatchService.dispatchNewNPCs runs every few seconds. It:
- Skips if the world already has more than 7 police vehicles or 10 foot NPCs
- For each player with
Score > 0, checks how many units are already assigned - If below the star-level minimum (
Star.minGroundUnits), picks a spawn point: - Moving suspect — tries to spawn ahead (70% of the time) or behind (30%) along the path, outside the player's vision cone
- Stationary / fallback — random node at least 350–500 studs away, also outside vision
- Spawns a police car (
Ford Crown Victoria PoliceorDodge Charger Police) plus two NPCs, assigns them driver + passenger seats, and attaches them to the player viaCentralService.Attach - At high crime scores (>400) the NPCs receive a police vest and 150/135 HP
A minimum of 2 patrol vehicles always exist in the world regardless of active crimes.
Search System¶
DispatchService.searchLoop tracks whether any cop currently has line-of-sight to the wanted player. If the player breaks line-of-sight and stays hidden:
- After
SEARCH_START_DELAYseconds (5 s),ClientSearchTickis set on the crime record - If the player was near their last-seen position, the delay extends to
SEARCH_START_DELAY_NEAR_LAST_SEEN(20 s) - First sighting gets an extra grace period of
SEARCH_FIRST_SIGHTING_GRACE(30 s)
When ClientSearchTick > 0, NPCs switch to the G_Search group. If the player stays hidden long enough for the search timer to expire, the wanted level clears.
CentralService — NPC Coordination¶
CentralService is the message bus between cops. It does not talk to the client.
Unit Caps¶
CentralService.RequestTarget(Entity, Target) returns true only if the number of already-assigned units is below Star.maxGroundUnits. NPCs check this before targeting a player.
Advisories¶
Advise(suspect, message) appends a message string to the player's CopAdvise set. IsAdvised(suspect, message) checks it. Current messages:
| Advisory | Meaning |
|---|---|
HAS_GUN |
Player is or was seen with an equipped weapon |
SEEN_WITH_GUN |
Player was spotted carrying a duffel bag (legacy name — not an actual gun sighting) |
Patrol Slots¶
Only 2 cars can be in patrol mode at the same time (to avoid every idle car driving around). CanPatrol and RemovePatrolIfApplicable manage the PatrolUnits list.
Car Assignment¶
When a police NPC enters a patrol car, DispatchService:AssignCopCar transfers the car's network ownership to the pursuing player's client and adds a ReplicationFocus so the car stays in that client's replication bubble. UnassignCopCar reverses this. The client's PoliceCarController then runs the driving AI each frame.