Terminals and Missions
Porters take missions at terminals. data/terminals.json lists every terminal, and each terminal lists the missions it offers. Every terminal has the same fields, and so has every mission.
Restart the resource after editing the file. A terminal or a mission that is not written correctly is left out, and the server console says which one and why.
[
{
"id": "paleto_bay",
"label": "Paleto Bay Depot",
"coords": { "x": -73.0, "y": 6436.84, "z": 31.44 },
"heading": 311.0,
"blip": {
"enabled": true,
"label": "Porter Depot",
"sprite": 478,
"color": 5,
"scale": 0.8,
"short_range": true
},
"cabinets": [
{ "coords": { "x": -70.86, "y": 6434.85, "z": 31.44 }, "heading": 311.0 }
],
"missions": [
{
"id": "mountain_hermit",
"title": "Food for the Mountain Hermit",
"description": "An old man has lived on the summit of Mount Chiliad for years...",
"load": [
{ "cargo": "cooler", "count": 1 },
{ "cargo": "cardboard", "count": 2 }
],
"destination": {
"type": "ped",
"label": "Mount Chiliad",
"coords": { "x": 499.0, "y": 5604.9, "z": 797.9 },
"ped": {
"model": "a_m_o_tramp_01",
"heading": 180.0,
"animation": { "dict": "rcmcollect_paperleadinout@", "clip": "meditiate_idle" }
}
},
"time_limit_minutes": 25,
"pay": 1800
}
]
}
]Every coords is the position of a player standing on the spot: stand there in game and copy your position. With Config.debug on, /portercoords copies it to the clipboard, already written for this file.
A terminal
| Field | What it is |
|---|---|
id |
A name for the scripts. Any text without spaces; no two terminals may share one. |
label |
The name of the place. |
coords, heading |
Where the terminal stands. heading is the way a porter faces while using it. |
blip |
The terminal on the map. enabled shows or hides it, label is its name in the map legend, sprite, color and scale are the usual blip numbers, and short_range shows it on the minimap only when the player is near. |
cabinets |
The cargo cabinets beside the terminal, each with coords and heading (the way a porter faces while loading from it). A cabinet serves one porter at a time, so a busy terminal wants two or three. |
missions |
The missions this terminal offers. |
A mission
| Field | What it is |
|---|---|
id |
A name for the scripts. Any text without spaces; no two missions may share one, not even at different terminals. |
title |
The name porters see on the terminal, on the map and on the result screen. |
description |
Shown to the porter when they take the mission. |
load |
The cargo, in the order it goes on the shelves. cargo is a type from shared/cargo.lua (pizza, cooler, fishtank...), count is how many. The whole load has to fit on one porter's back and in one cabinet. |
destination.type |
"ped": someone waits there and the porter hands the cargo to them. "dropoff": a marked spot where the porter leaves it. |
destination.label |
The name of the place, shown on the result screen. |
destination.coords |
Where it is. |
destination.ped |
Only for "ped". model is the ped model and heading the way it faces. Give it either an animation (dict and clip, played on a loop) or a scenario (such as "WORLD_HUMAN_CLIPBOARD"), or neither to have it stand there. |
time_limit_minutes |
When this runs out the delivery fails wherever the porter is, like a cancelled one. Leave it out, or set it to 0, for a delivery without a time limit. |
pay |
What a delivery in perfect condition pays. Lower ranks earn a share of it (Config.missions.pay_by_rank). |
always |
true keeps the mission on every board of its terminal. Leave it out for a mission that comes and goes. |
danger |
Optional armed encounters, see below. Dying during a dangerous delivery fails it. |
The distance shown for a mission is the straight line from its terminal to its destination.
Dangerous missions
A danger section contains zones. Each zone has coords, a radius in metres and a hunters count from 1 to 12. Optional models and weapons arrays on danger override Config.missions.danger.models and Config.missions.danger.weapons for that mission.
"danger": {
"zones": [
{
"coords": { "x": 61.0, "y": 3711.5, "z": 39.75 },
"radius": 100.0,
"hunters": 4
}
]
}The carrier's client spawns networked hunters as it approaches a zone and despawns them after it gets clear. Their AI and relationship groups target only that carrier, not other players. Other players can still fight them or be hit by stray fire.
The server owns the mission and its cleanup: dying, cancelling, delivery, disconnecting and stopping the resource all remove its hunters.
A death is a failed delivery with the result tag KILLED. Being downed counts as a death: medical scripts revive the ped straight away, so the framework's own flag is read too (isdead and inlaststand on QBCore and Qbox, dead on ESX with the isDead state esx_ambulancejob sets, the isDead state on ox_core). On another framework, edit isDown in bridge/client/player.lua and bridge/server/player.lua.
stab_city_contraband in the default file is a working example.
Cargo types
Every item stands on the same footprint, so anything stacks on anything. Only the height differs by size.
| Size | Height |
|---|---|
| S | 0.075 m |
| M | 0.15 m |
| L | 0.30 m |
| XL | 0.60 m |
| XXL | 1.80 m, a porter's whole carry height. It stands on the floor beside the cabinet. |
The full list of types, with their weight and traits, is in shared/cargo.lua.