STG ScriptsDocumentation
MDT + CAD System

Configuration

Every option in STG MDT shared/config.lua, from jobs, opening and the CAD to dispatch, permissions, evidence, forensics, ALPR, CCTV, billing and the EMS terminal.

All settings live in stg-mdt/shared/config.lua. The file stays editable in the escrow version, together with locales/ and integrations/. Restart the resource after a change.

Language

Config.Language = 'en'

Available: en, de, fr, es, pt, it, nl, pl, sv, no, fi, cs, ar, he, jp, ko, zh. Messages live in stg-mdt/locales/<language>.lua and the tablet interface in stg-mdt/locales/ui/<language>.lua. In the interface files the key is the English text and the value is what the tablet shows, so you can also change the English wording in locales/ui/en.lua.

Jobs

Config.Jobs = {
    police = { App = 'police', Label = 'Mission Row PD', CallsignPrefix = '1-A-' },
    bcso = { App = 'police', Label = 'Blaine County SO', CallsignPrefix = '2-S-' },
    sasp = { App = 'police', Label = 'San Andreas SP', CallsignPrefix = '3-H-' },
    ambulance = { App = 'ems', Label = 'Pillbox Medical', CallsignPrefix = 'MED-' },
}

Config.RequireOnDuty = true
Config.RosterCheckInterval = 60

Prop

Type

Opening the MDT

Config.Open = {
    Command = { Enabled = true, Name = 'mdt' },
    Keybind = { Enabled = true, Key = 'F6' },
    Item = { Enabled = true, Name = 'stg_mdt_tablet', Required = false },
    StationOnly = false,
    Stations = {
        { App = 'police', Label = 'Mission Row PD', Coords = vec3(441.0, -982.0, 30.7), Radius = 60.0 },
        { App = 'ems', Label = 'Pillbox Medical', Coords = vec3(307.0, -595.0, 43.3), Radius = 60.0 },
        -- more stations in the file
    },
}

Prop

Type

In-vehicle CAD

Config.Cad = {
    Enabled = true,
    Command = 'cad',
    Keybind = '',
    VehicleClasses = { 18 },
    Models = {},
    RefreshInterval = 500,
    Laptop = {
        Enabled = true,
        Offset = vec3(0.12, 0.35, 0.3),
        Turn = 30.0,
    },
}

Prop

Type

Tablet

Config.Tablet = {
    Enabled = true,
    Prop = 'stg_mdt_tablet',
    Bone = 28422,
    Offset = vec3(-0.05, 0.0, 0.0),
    Rotation = vec3(0.0, 0.0, 0.0),
    Dict = 'amb@code_human_in_bus_passenger_idles@female@tablet@idle_a',
    Anim = 'idle_b',
    Phase = 0.0,
    Zoom = true,
}

The tablet prop and animation used on foot. With Zoom = true the camera moves in and the MDT is drawn on the tablet's screen. Zoom only works with the included stg_mdt_tablet prop.

Callsigns and photos

Config.Callsign = { MaxLength = 10 }

Config.Mugshot = {
    Enabled = true,
    StartDelay = 20,
    RefreshMinutes = 30,
    MaxBytes = 80000,
    Debug = false,
}

Players change their own callsign by clicking the unit chip. Every player's game takes a headshot of their own character for citizen, warrant and patient profiles. Turn on Debug if photos do not show up, it prints each step in the F8 console.

Booking photos

Config.Booking = {
    Enabled = true,
    MaxDistance = 6.0,
    CameraDistance = 1.0,
    Fov = 32.0,
    Width = 300,
    Height = 375,
    Quality = 0.8,
    MaxBytes = 120000,
}

Right, front and left photos of the suspect, taken from the arrest report. Needs screencapture or screenshot-basic. MaxDistance is how close the officer has to stand.

Phone trace

Config.PhoneTrace = {
    Enabled = true,
    Phone = 'auto',
    Minutes = 30,
    SelfApprove = true,
    ViewAll = false,
    HistoryHours = 48,
    Accuracy = 60.0,
    RefreshSeconds = 20,
    PhoneItems = { 'phone', 'black_phone', 'blue_phone' },
}

Prop

Type

The supported phones and their database queries are in integrations/phones.lua. See Integrations.

Permissions

Config.Permissions = {
    AssignUnits = 0,
    ApproveReports = 2,
    SignWarrants = 2,
    CancelWarrants = 3,
    DeleteEvidence = 3,
    Impound = 0,
    ManageLicenses = 1,
    DeleteRecords = 2,
    DeleteReports = 3,
    RequestPhoneTrace = 0,
    ApprovePhoneTrace = 3,
    Broadcast = 1,
}

The minimum job grade for each action, using your framework's job grades. Officers can always delete their own report drafts.

Units

Config.Units = {
    LocationInterval = 5000,
    PushInterval = 5000,
    Statuses = {
        ['10-8'] = { Label = 'Available', Tone = 'brand' },
        ['10-76'] = { Label = 'En route', Tone = 'hot' },
        -- more statuses in the file
    },
}

Statuses are the unit status codes, Tone colors them (brand, hot or empty).

Dispatch

Config.Dispatch = {
    ClosedRetention = 60,
    MaxCalls = 60,
    SelfDispatch = {
        { Code = '10-11', Title = 'Traffic stop' },
        { Code = '10-80', Title = 'Pursuit', Priority = true },
    },
    Backup = { Code = '10-78', Title = 'Officer needs backup' },
    Panic = { Code = '10-99', Title = 'Officer down' },
    Pursuit = { Code = '10-80', Title = 'Pursuit in progress' },
    Blips = { Enabled = true, Sprite = 161, Scale = 1.0, Color = 1, PriorityColor = 49, Duration = 300 },
    Sounds = true,
    CitizenCalls = {
        Enabled = true,
        Police = { Command = '911', Code = '911', Title = 'Citizen call' },
        Ems = { Command = '912', Code = 'MED-01', Title = 'Medical call' },
        Cooldown = 60,
        Zone = { Enabled = true, Radius = 120.0, Duration = 120, BlipColor = 1, BlipAlpha = 110 },
    },
}

Prop

Type

Other scripts can create calls too, see Integrations.

Penal code and citations

Config.PenalCode = {
    { Id = 't1', Title = 'Driving without a license', Description = 'Operating a vehicle without a valid license.', Fine = 500, Extra = '', Level = 2, Category = 'traffic' },
    -- more charges in the file
}

Config.Citations = {
    MaxCustomFine = 50000,
    MaxTotal = 100000,
}

Category is traffic or order, Level is 1 to 3. Extra is a short note shown on the charge. Officers can also write custom charges up to MaxCustomFine.

Billing

Config.Billing = {
    ConsentSeconds = 30,
    Mode = 'consent',
}
ModeWhat bills and citations do
consentThe citizen gets a pay or decline prompt, the money comes out of their bank
logOnly written on the MDT record, no money is taken
esx_billingAdded to the ESX billing table
customHanded to your billing script in integrations/billing.lua

Health plans always ask the citizen first. You can add any billing script as a new mode, see Integrations.

PDF

Config.Pdf = {
    Enabled = true,
    BaseUrl = '',
    LinkMinutes = 10,
    Header = 'San Andreas Public Records',
}

Reports download as PDF from the FXServer HTTP port. Leave BaseUrl empty to use the address players connected with. Set it when the server is behind a proxy, for example https://play.myserver.com.

Licenses and reports

Config.Licenses = { 'driver', 'weapon', 'pilot', 'hunting', 'business' }

Config.Reports = {
    Types = {
        { Name = 'Traffic stop', Fields = { 'Vehicle', 'Plate', 'Violation', 'Outcome' } },
        { Name = 'Arrest', Fields = { 'Charges', 'Rights read', 'Transported to', 'Booking number' } },
        { Name = 'Custom', Fields = {} },
    },
    MaxFields = 12,
    Roles = { 'Suspect', 'Victim', 'Witness' },
    Templates = {
        { Title = 'Arrest', Text = 'Subject [name] was arrested at [location] for [charges]...' },
    },
}

Config.Warrants = { ExpireDays = 14, DefaultBail = 25000 }

Licenses are read from metadata.licences on QBCore and QBOX, and from the user_licenses table on ESX. Report types start with their own detail fields, templates fill the narrative. Warrants written below the SignWarrants grade wait for a supervisor.

Evidence

Config.Evidence = {
    LabMinutes = 30,
    DefaultLocation = 'Intake shelf',
    ItemImages = 'nui://ox_inventory/web/images/%s.png',
    Locker = {
        Enabled = true,
        Slots = 30,
        Weight = 100000,
    },
}

Every report gets its own evidence locker, opened from the report. With ox_inventory items put in are logged on the report and tagged with their evidence number. ItemImages is where item images are loaded from, for qb-inventory use nui://qb-inventory/html/images/%s.png. LabMinutes is how long a lab request on an evidence item takes.

Forensics

Config.Forensics = {
    Enabled = true,
    Item = 'stg_blood_sample',
    DropMinutes = 30,
    LabMinutes = 60,
    Lab = {
        Label = 'Crime lab',
        Model = 's_m_m_scientist_01',
        Coords = vec4(441.0534, -995.2778, 30.6896, 44.2730),
    },
}

Players hit by a gun or a blade leave blood. Police collect it as a sealed sample item and hand it to the lab technician at Lab.Coords. After LabMinutes the evidence in the MDT shows whose blood it is. Blood dries up after DropMinutes.

Vehicles

Config.Vehicles = {
    ImpoundPrice = 500,
    Images = { gauntlet4 = 'gauntlet4', sultan = 'sultan' },
    ClassImages = { [0] = 'blista', [18] = 'ambulance' },
    DefaultImage = 'buffalo2',
}

ImpoundPrice is the cost to release an impounded vehicle. The images pick the vehicle picture from web/assets/img, by model first, then by class. How impounding is saved is set in integrations/garage.lua.

ALPR

Config.Alpr = {
    Enabled = true,
    Command = 'alpr',
    SettingsCommand = 'alprsettings',
    Keys = { Toggle = 'F11', Lock = 'F9', Reset = 'F10', Lane = 'NUMPAD5' },
    Radar = {
        Unit = 'kmh',
        DefaultLimit = 60,
        Limits = { ['Los Santos Freeway'] = 120 },
    },
    AlertSeconds = 12,
    CallCode = 'ALPR',
    LaneWidth = 4.0,
    ScanByDefault = true,
    Hud = { Position = 'bottom-right' },
    ShareHits = true,
    ShareCooldown = 120,
    ShareBlipSeconds = 90,
    Range = 30.0,
    Interval = 250,
    Cooldown = 30,
    MaxReads = 30,
}

Prop

Type

CCTV

Config.Cctv = {
    Cameras = {
        { Id = 'CAM-0418', Name = 'Legion Square', Coords = vec3(195.7, -933.6, 36.0), Rotation = vec3(-20.0, 0.0, 140.0), Facing = 'West', Online = true },
        -- more cameras in the file
    },
    MinFov = 20.0,
    MaxFov = 70.0,
    Timecycle = 'CAMERA_secuirity',
    TimecycleStrength = 1.0,
    ExtraTimecycle = 'scanline_cam_cheap',
    HideRadar = true,
    SnapshotToEvidence = true,
    Discord = {
        Webhook = '',
        Quality = 0.85,
    },
}

Add a camera with its position and starting rotation. Snapshots are logged as evidence. With a Discord Webhook, the photo is posted there and officers can open it from the evidence log. Set a Timecycle to '' to turn that screen effect off.

EMS

Config.Ems = {
    Hospital = 'Pillbox Medical',
    HospitalCoords = vec3(311.0, -590.0, 43.3),
    HospitalRadius = 80.0,
    Beds = { 'Trauma 1', 'Trauma 2', 'Bed 3', 'Bed 4' },
    Reception = {
        Enabled = true,
        Command = 'checkin',
        Coords = vec3(308.0, -595.0, 43.3),
        Radius = 6.0,
        Ped = {
            Model = 's_f_y_scrubs_01',
            Coords = vec4(305.3798, -597.4440, 43.2918, 20.4048),
        },
        Reasons = { 'Injury', 'Feeling sick', 'Check-up', 'Prescription refill', 'Visiting a patient' },
    },
    Plans = {
        { Name = 'BASIC', Price = 50, Ems = 50, Pharmacy = 15, Ambulance = 50, Surgery = 0 },
        { Name = 'PREMIUM', Price = 150, Ems = 100, Pharmacy = 50, Ambulance = 100, Surgery = 75, BestValue = true },
    },
    PlanDays = 7,
    MaxBill = 100000,
    Medications = { 'Morphine 10 mg', 'Saline 500 ml', 'Bandage kit' },
    SupplyUse = 10,
    InjuryTypes = { 'Gunshot wound', 'Stab wound', 'Fracture', 'Burn' },
    InjurySeverity = { 'Minor', 'Moderate', 'Serious', 'Critical' },
    MaxInjuries = 20,
}

Prop

Type

BodyMap and WoundLevels at the end of the block set up the injury body map, leave them as they are unless you change the image.

Next steps

Still having trouble?

Open a ticket on our Discord. Our team answers around 15 hours a day.

Get help on Discord

On this page