Skip to content

CODE3RESPONSE

Exports and events

Everything another resource may rely on. The MDT and voice dispatch use only what's listed here, so it's safe to build on.

Records

Events and exports pass these tables. They're the public record: what a plate or name check shows.

Person

{
    id = 12, first = 'John', last = 'Smith', dob = '01/02/1990', gender = 'Male', address = '12 Grove St',
    dl = 'Valid', -- 'Valid' | 'Suspended' | 'Revoked' | 'Expired' | 'None'
    dl_valid = true,
    flags = { 'ARMED AND DANGEROUS' },
    warrant = 'Failure to appear', -- or nil
}

A name a driver made up comes as { first, last, dob, gender, unverified = true } with no id: nobody by that name is on file.

Vehicle

{
    id = 7, plate = '4ABC123', make = 'Bravado', model = 'Buffalo S', color = 'Black', year = '2015',
    owner = 'John Smith', owner_id = 12, reg_valid = true, ins_valid = false,
    stolen = false, bolo = true, bolo_reason = 'Armed robbery suspect',
}

model is the display name ("Buffalo S"), not the spawn name.

Callout

{ id = 'domestic_01', name = 'Domestic disturbance', street = 'Grove Street', coords = vector3(...),
  priority = 2, description = 'Neighbours report shouting.' }

Truth

Only c3r knows it, and it only comes out through the server export getPedSubject.

{
    secret = 'drunk',   -- 'clean' | 'nervous' | 'unlicensed' | 'suspended' | 'expired' | 'drunk' | 'drugs' | 'warrant' | 'stolen'
    demeanor = 'polite', -- 'polite' | 'nervous' | 'rude' | 'chatty'
    id = 'hands',        -- asked for a licence: 'hands' it over, 'forgot' it, or gives an 'alias'
    alias = nil,         -- { first, last, dob }: the false name (id = 'alias')
    bac = 0.12,          -- secret = 'drunk' only
}

Server events

Fired with TriggerEvent on the server. Listen with AddEventHandler. The first argument is always the officer's server id. These are never net events, so a client can't fake them.

EventArgumentsWhen
c3r:dutysrc, onAn officer goes on or off duty
c3r:contactsrc, personThey identify someone (licence handed over, or a name given)
c3r:vehicleContactsrc, vehicleA vehicle comes into a stop or a check
c3r:stopStartedsrc, person, vehicleA traffic stop starts. person is nil: the driver isn't known until they're identified, then c3r:contact fires
c3r:stopEndedsrc, outcome'cited', 'warning', 'released', 'arrested', 'fled' or 'cancelled'
c3r:dialoguesrc, who, textEvery line of a conversation. who is 'Officer' or 'Subject'
c3r:notesrc, textA line for the open incident's timeline, e.g. "Breathalyzer, Driver: 0.120 BAC (over the limit)"
c3r:pursuitStartedsrc, person, vehicleA driver runs instead of pulling over
c3r:pursuitEndedsrcCaught or lost (before c3r:stopEnded)
c3r:calloutOfferedsrc, calloutA call offered to this officer
c3r:calloutAcceptedsrc, calloutThey responded
c3r:calloutArrivedsrcOn scene
c3r:calloutEndedsrc, completedThe call ended for them
AddEventHandler('c3r:stopEnded', function(src, outcome)
    print(('%s ended a stop: %s'):format(GetPlayerName(src), outcome))
end)

Server exports

The SQL-backed exports answer through a callback, because a call from another resource can't wait on SQL inside c3r.

ExportReturnsDoes
isOnDuty(src)boolean
setDuty(src, on)ok, reasonPuts them on or off duty
getPerson(id, cb)cb(person | nil)
getVehicle(id, cb)cb(vehicle | nil)
findVehicle(plate, cb)cb(vehicle | nil)A plate on file
lookupPlate(src, plate, cb)cb(vehicle | nil)Like findVehicle, but a plate not on file is looked for near that officer: if the car is there, it gets papers, an owner and a driver on the spot, and c3r:vehicleContact fires
createPerson(p, cb)cb(person)An existing name + date of birth comes back unchanged
createVehicle(v, cb)cb(vehicle)
getPedSubject(netId)person, vehicle | nil, items, truthEverything c3r knows about a ped it made; nil if it didn't make it. Returns directly
endStop(src, netId, outcome)booleanEnds that officer's stop on that ped. true when it did
setCalloutOffers(src, on)Callout offers on or off for that officer
offerCallout(src)ok, reasonOffer them a call now
exports.c3r:lookupPlate(src, '4ABC123', function(vehicle)
    if vehicle and vehicle.stolen then print('Stolen!') end
end)

Client exports

ExportReturnsDoes
isOnDuty()booleanReads the c3rDuty state bag
getService()'police' | nilThe service they're on duty in
setDuty(on)trueAbsolute, never a toggle
isOnCallout()boolean
isOfferedCallout()boolean
acceptCallout()ok, reason
completeCallout()ok, reason
requestService(kind)ok, reasonSends an AI unit (kinds below)
cancelService(kind)ok, reason
requestPursuitBackup(level)ok, reason'light', 'medium', 'heavy' or 'air'. With no chase on, light to heavy sends a cover unit
cancelPursuitBackup()ok, reasonCover units leave too
towTarget()vehicle | nilThe car a tow would be sent for now: the stop's car, else the nearest empty one within 15 m
pa(cmds)booleanGives PA orders: a command or a list, in the order said. true when an order went out
getStop()table | nilThe officer's traffic stop: { veh_net, ped_net, stopped, mode, people = { { net, seat, role, out } } }. mode is 'front', 'behind', 'steer' or nil

Service kinds: ambulance, police (prisoner transport), tow, coroner, fire, mechanic, roadservice, animalrescue, taxi, cover.

PA commands: pull_over, felony, driver_out, passenger_out, everyone_out, walk_back, kneel, hands_up, back_in, engine_off. On a felony stop only the first runs.

Reasons (the second value when the first is false): off_duty, not_available (unknown kind or its models missing), already_en_route, no_route, no_prisoner, no_vehicle, nobody_to_collect, too_far, no_pursuit, enough_units, not_en_route, already_dispatched, no_backup.

local ok, why = exports.c3r:requestService('ambulance')
if not ok then print('No ambulance: ' .. why) end

State bags

BagOnValue
c3rDutyPlayertrue while on duty (set by the server, replicated)
if LocalPlayer.state.c3rDuty then --[[ on duty ]] end