Kartik Scripts

Exports

All exports are server side:

exports['kartik-dojjob']:ExportName(...)

Staff & permissions

exports['kartik-dojjob']:IsDojStaff(src, ignoreDuty)       -- true when the player is DOJ staff (on duty unless ignoreDuty)
exports['kartik-dojjob']:HasPermission(src, 'warrantSign') -- see Permissions for every key
exports['kartik-dojjob']:GetOnDutyStaff()                  -- staff on duty

Bar & lawyers

exports['kartik-dojjob']:GetBarStatus(identifier)  -- 'active' | 'pending' | 'denied' | 'suspended' | 'disbarred' | nil
exports['kartik-dojjob']:IsLawyer(src)
exports['kartik-dojjob']:RequestLawyer(src, reason, byPoliceName) -- request id, or false, err

Sentences & mail

-- 'jail' | 'fine' | 'payout' | 'charge' | 'release'. Offline citizens get it when they next load in.
exports['kartik-dojjob']:Sentence(identifier, 'jail', 20, 'Contempt of court')

-- court mail to the phone, now or when they next load in
exports['kartik-dojjob']:Message(identifier, text, subject)

Courtroom & security

exports['kartik-dojjob']:GetSessions()          -- running court sessions
exports['kartik-dojjob']:IsLockdown(courtId)
exports['kartik-dojjob']:IsInHoldingCell(src)
exports['kartik-dojjob']:IsRemanded(src)        -- waiting for a prisoner transport after sentencing

Cases

exports['kartik-dojjob']:AddCaseNote(caseId, text, author)
exports['kartik-dojjob']:FileAppeal(caseId, reason, byName)     -- new case linked to a decided one
exports['kartik-dojjob']:GetCaseCounsel(caseId)                 -- active and requested counsel
exports['kartik-dojjob']:GetCaseRole(src, caseId)               -- 'court' | 'prosecution' | 'defense' | nil
exports['kartik-dojjob']:ShareRecord(src, caseId, recordRef, note) -- a department member gives an MDT record to a case: exhibit label, or false, err
exports['kartik-dojjob']:CreateDocument(src, templateId, fields, { title = 'Order', caseId = 12 })

Orders, supervision & permits

exports['kartik-dojjob']:GetActiveOrders(citizenid)   -- restraining / protective / court orders on (or protecting) a citizen
exports['kartik-dojjob']:GetSupervision(identifier)   -- active probation / parole / community service
exports['kartik-dojjob']:IsOnProbation(identifier)    -- true, row while on probation or parole
exports['kartik-dojjob']:GetPermits(identifier)       -- active permits { number, title, slug, expiresAt, details }
exports['kartik-dojjob']:HasPermit(identifier, 'event_permit')

Tablet extensions

Add your own panels, pages and actions to the DOJ tablet (for example a licensing or permits script). See Tablet Extensions.

exports['kartik-dojjob']:RegisterExtension(id, definition) -- true, or false, err
exports['kartik-dojjob']:RefreshExtension()                -- open tablets reload extension panels
exports['kartik-dojjob']:UnregisterExtension(id)

For other MDTs

With Config.CaseStore = 'standalone' the court keeps cases, records and warrants in its own tables. Other MDTs read them here:

exports['kartik-dojjob']:GetCaseStore()                 -- 'mdt' | 'standalone'
exports['kartik-dojjob']:GetActiveWarrants(citizenid)   -- { id, warrant_type, reason, is_dangerous, author_name, created_at }[]
exports['kartik-dojjob']:GetCriminalRecords(citizenid)  -- { id, offense, sentence, fine, date, officer_name }[]
exports['kartik-dojjob']:GetCases(citizenid)            -- cases where they are defendant or plaintiff

Verdict hook (event)

kartik-dojjob:server:onVerdictFinalized fires on the server once for every finished case, so district, economy or stats scripts can react to court outcomes:

  • a courtroom verdict from the judge
  • a plea agreement accepted by the defendant

It fires right after the verdict is saved. Jail time and a fine in the same ruling count as one event. It never fires again for the same ruling: not after a restart, not when an offline defendant logs in, and not when the sentence is served.

AddEventHandler('kartik-dojjob:server:onVerdictFinalized', function(data)
    if GetInvokingResource() ~= 'kartik-dojjob' then return end -- only accept it from the DOJ script
    if data.jailDuration > 0 or data.fineAmount > 0 then
        -- the case ended with a sentence
    end
end)

Use AddEventHandler, not RegisterNetEvent, so players can never trigger it.

FieldTypeNotes
caseIdnumberCase id
resolutionIdstringUnique per resolution, safe to store for your own duplicate checks
kindstring'verdict' or 'plea'
statusstring'guilty', 'not_guilty', 'liable', 'dismissed' or 'plea_accepted'
jailDurationnumber0 when there is no jail time
jailUnitstring'minutes'
fineAmountnumber0 when there is no fine
judgeCitizenIdstring / nilJudge who gave the verdict
judgeSourcenumber / nilJudge's server id when online
judgeNamestring / nilJudge on the case
prosecutorCitizenIdstring / nilProsecutor who offered the plea (plea only)
defendantCitizenIdstring / nilDefendant
resolvedAtnumberUnix time

To call your own script directly instead, fill in Hook.Custom in bridge/integrations/server/verdict_hook.lua (open file). Hook.Enabled = false in the same file turns the hook off.

function Hook.Custom(data)
    exports.my_district_script:CaseResolved(data)
end

On this page