Browse docs
Exports
Call these exports from a server script in your own resource, with sky_firejob started. They create or remove an incident when called. Automatic oil leaks after collisions or from wear need Sky Mechanic or another resource that detects the condition and calls Firejob.
The return formats and IDs differ between fire and oil exports:
| Operation | Return value on success | ID to keep |
|---|---|---|
CreateFire | One table: { success = true, fireId = ..., type = ..., label = ... } | result.fireId, a numeric fire ID |
CreateVehicleFire | One table: { success = true, fireId = ... } | Keep the vehicle network ID you supplied for RemoveVehicleFire; result.fireId identifies the fire |
CreateOilSpill | Two values: true, spill | spill.id, a string such as "17", for RemoveOilSpill |
GetOilSpills | An array of spill tables | Each entry's spill.id; the array index is not the spill ID |
creator, where accepted, is a player's current server ID (source). Use 0 or omit it for server-created incidents. It is separate from the vehicle network ID, fire ID, and oil spill ID.
Server Exports
CreateFire(payload, creator)
Creates a regular synchronized fire with Firejob's normal spread, extinguishing, dispatch, effects, and lifecycle behavior.
| Argument / payload field | Type | Required / default | Meaning |
|---|---|---|---|
payload | table | Required | Fire creation data |
payload.coords | { x, y, z } or vector3 | Required | World position with numeric coordinates |
payload.type | string | "trash" | A configured fire profile or alias |
payload.metadata | table | Optional | Overrides for this fire, described below |
creator | number | 0 | Player server ID for creation/dispatch context, or 0 for a scripted incident |
Common metadata fields are locationType ("interior" or "exterior"), sourceScale (scale multiplier), smokeDensity (0.0–1.0), material, scenePropsEnabled, and reignitable. Reignition overrides include reignitionEnabled, reignitionChancePercent, and reignitionDelaySeconds. Omitted settings follow the fire profile and Firejob configuration.
The export returns one table:
- Success:
success = true,fireId(number),type(string), andlabel(string). - Failure:
success = falseanderror(string). Possible errors areinvalid_payload,invalid_coords,invalid_fire_type, andcreate_failed.
-- server.lua; choose coordinates appropriate for your incident.
local result = exports["sky_firejob"]:CreateFire({
type = "trash",
coords = { x = 215.0, y = -810.0, z = 30.0 },
metadata = {
locationType = "exterior",
sourceScale = 1.0,
smokeDensity = 0.8,
scenePropsEnabled = false
}
}, 0)
if not result.success then
print(("Could not create fire: %s"):format(result.error))
return
end
local fire_id = result.fireId
print(("Created fire %s (%s)"):format(fire_id, result.type))
Creation notifications are silent by default. Set metadata.silent = false and supply a player creator to send the normal creation notification. fireId identifies a Firejob fire; it is not a vehicle network ID or an oil spill ID. Regular fires follow Firejob's extinguishing and configured expiry lifecycle; this page does not provide a RemoveFire export.
CreateVehicleFire(payload, creator, options)
Creates a fire associated with a vehicle, using Firejob's configured fire progression, vehicle state, and explosion behavior.
| Argument / payload field | Type | Required / default | Meaning |
|---|---|---|---|
payload | table | Required | Vehicle fire creation data |
payload.netId | number | Supply for an attached vehicle fire | Network ID of the existing vehicle, obtained by your vehicle integration; not an entity handle or plate |
payload.coords | { x, y, z } or vector3 | Optional when netId resolves to an existing vehicle | Fire position; otherwise the vehicle position is used |
payload.plate | string | Optional | Vehicle plate metadata; does not find or select a vehicle |
payload.source | string | Optional | Description of the origin, such as your resource name |
payload.initialStage | string | "smoke" | "smoke", "smallFire", or "fullFire", when progression is enabled |
payload.smokeDensity | number | Config/profile default | Smoke density; the selected progression stage can override it |
payload.explosionDelaySeconds | number | Config default | Explosion delay in seconds when explosions are enabled; progression can delay the start of this timer |
payload.engineHealth, bodyHealth, petrolTankHealth | number | Config defaults | Optional vehicle health overrides |
payload.effects | table | Profile defaults | Optional flame and smoke catalog IDs; unknown IDs return invalid_effect |
creator | number | 0 | Player server ID, or 0 for a server-created incident |
options | table | Optional | Creation context, described below |
For a normal integration, omit options or pass { reason = "my_resource" }. The reason is recorded as the fire's origin. When creator > 0, normal external creation checks the external-fire enable setting and player distance.
The optional context flags change behavior: manual = true applies manual ignition checks; accident = true uses accident scaling and context; scenario = true uses scenario context and permits payload.sourceScale, progressionEnabled, and explosionEnabled overrides. These are trusted server-side integration options, not permissions to forward from client input.
The export returns one table:
- Success:
{ success = true, fireId = <number> }. - Failure:
{ success = false, error = <string> }. Errors includedisabled,invalid_coords,already_burning,limit,external_disabled,too_far,invalid_effect, andcreate_failed. already_burningcan include the existingfireIdwhen the vehicle is already registered. A nearby-fire rejection need not include an ID.- Manual ignition can additionally return
not_on_duty,required_jobs,missing_item,invalid_player, orcooldown; a cooldown response includesremainingseconds.
-- server.lua; replace 123 with the existing vehicle's real network ID.
local vehicle_net_id = 123
local result = exports["sky_firejob"]:CreateVehicleFire({
netId = vehicle_net_id,
source = "my_incident_resource",
initialStage = "smoke"
}, 0)
if not result.success then
print(("Could not create vehicle fire: %s"):format(result.error))
return
end
print(("Created fire %s on vehicle %s"):format(result.fireId, vehicle_net_id))
-- Keep vehicle_net_id in your incident state for RemoveVehicleFire.
Creation accepts coordinates without a resolvable vehicle, but such a fire is not necessarily tied to an existing vehicle. Supply a valid vehicle network ID when you need vehicle attachment and later removal with RemoveVehicleFire.
RemoveVehicleFire(netId, reason)
Removes the active Firejob fire associated with a vehicle and clears its Firejob burning state.
| Argument | Type | Required / default | Meaning |
|---|---|---|---|
netId | number | Required | The same vehicle network ID supplied to CreateVehicleFire, not its returned fireId |
reason | string | "external_repair" | Reason recorded for removal |
The export returns one table:
{ success = true, removed = true, fireId = <number> }: an active vehicle fire was removed.{ success = true, removed = false }: no active Firejob vehicle fire was registered for that ID; its burning state is still cleared.{ success = false, error = "invalid_vehicle" }: the supplied ID is not a positive network ID.
-- Use the real vehicle network ID stored by your incident/repair workflow.
local vehicle_net_id = 123
local result = exports["sky_firejob"]:RemoveVehicleFire(vehicle_net_id, "external_repair")
if not result.success then
print(("Could not remove vehicle fire: %s"):format(result.error))
elseif result.removed then
print(("Removed fire %s"):format(result.fireId))
else
print("No active Firejob vehicle fire remained for this vehicle.")
end
CreateOilSpill(payload, creator, options)
Creates an active oil spill and synchronizes it to clients. Firejob assigns the spill ID; you do not generate or supply it.
This export returns two values. On success, the second value is a table containing the new ID at spill.id. On failure, the second value is an error string.
| Argument / payload field | Type | Required / default | Meaning |
|---|---|---|---|
payload | table | Required | Spill creation data |
payload.coords | { x, y, z } or vector3 | Required | World position with numeric coordinates |
payload.radius | number | Configured slip radius, normally 1.25 | Spill radius; clamped to 0.25–5.0 |
payload.intensity | number | Configured default, normally 1.0 | Intensity from 0.0 to 1.0; 1.0 is full intensity |
payload.source | string | "vehicle" in the spill record | Origin tag, such as "my_incident_resource"; useful when finding your spills later |
payload.sourcePart | string | "engine_oil" | Originating fluid/component, for example "engine_oil" or "transmission_fluid" |
payload.sourceVehicleNetId | number | 0 | Optional originating vehicle network ID; separate from the new spill ID |
payload.sourcePlate | string | "" | Optional plate metadata |
payload.canSpread | boolean | true | Whether vehicles may spread this spill |
payload.state | string | "fresh" | Use "bound" to create a spill that is already treated with absorbent |
creator | number | Optional | Player server ID associated with the request; use 0 for a scripted incident |
options | table | Optional | Source grouping and explicit limit overrides, described below |
Create, keep the ID, and remove the spill later
This complete server-side example creates a spill, saves its ID, and removes that same spill after one minute. Replace the coordinates with your incident location. In a real incident system, keep the ID in your own incident state and remove it when that incident ends.
-- server.lua
local ok, spill_or_error = exports["sky_firejob"]:CreateOilSpill({
coords = { x = 215.0, y = -810.0, z = 30.0 },
source = "my_incident_resource",
radius = 1.5,
intensity = 0.9
}, 0)
if not ok then
print(("Could not create oil spill: %s"):format(spill_or_error))
return
end
local spill_id = spill_or_error.id -- e.g. "17"; this is the ID to save.
print(("Created oil spill %s"):format(spill_id))
SetTimeout(60000, function()
local removed = exports["sky_firejob"]:RemoveOilSpill(spill_id, "incident_finished")
if removed then
print(("Removed oil spill %s"):format(spill_id))
else
print(("Oil spill %s could not be removed; it may already be gone."):format(spill_id))
end
end)
For example, a successful call returns true followed by a table with these fields:
| Field | Type | Meaning |
|---|---|---|
id | string | Assigned spill ID, for example "17"; pass this to RemoveOilSpill |
coords | { x, y, z } | Spill position |
radius, intensity | number | Effective values after defaults and clamping |
state | string | "fresh" or "bound" |
source, sourcePart, sourcePlate | string | Origin metadata |
sourceVehicleNetId | number | Originating vehicle network ID, or 0 |
canSpread | boolean | Whether the spill may spread |
boundBy | number or absent | Player server ID associated with binding, if recorded |
createdAtMs | number | Creation time relative to the current server runtime; not a Unix timestamp |
A failed call returns false, error:
| Error | Meaning |
|---|---|
disabled | The oil spill system is disabled |
invalid_payload | payload is not a table |
invalid_coords | Coordinates are missing or invalid |
cooldown | The same source group created a spill too recently |
too_close | The position is too close to the last spill created by that source group |
vehicle_limit | The originating vehicle has reached its active-spill limit |
resetting_ids | An oil-spill ID reset is currently in progress |
Only read .id after checking ok. local spill = CreateOilSpill(...) would capture the first return value, a boolean, instead of the spill table.
Source grouping and limits
By default, calls from the same calling resource and the same payload.source share a cooldown and minimum-distance record. When payload.source is omitted, the export uses "external" for this grouping. Changing creator or sourceVehicleNetId alone does not create a separate source group.
For independent vehicle trails, set options.sourceKey to a stable key unique to your resource and that vehicle, such as "my_incident_resource:vehicle:123" for vehicle network ID 123. sourceKey groups creation limits; it is not a spill ID and is not included in GetOilSpills() results.
The shipped defaults are a 5-second cooldown, 6-metre spacing, 12 active spills per vehicle, and 80 active spills overall. Exceeding the overall limit removes the oldest spill to make room. The effective configuration can change these limits. Removing a spill does not clear its source group's last creation time or position, so immediately repeating the example may return cooldown or too_close.
options field | Type / default | Effect |
|---|---|---|
sourceKey | string, automatic grouping | Explicit shared key for cooldown and spacing |
ignoreSourceCooldown | boolean, false | Skip the source cooldown check for this creation |
ignoreSourceMinDistance | boolean, false | Skip minimum spacing for this creation |
ignoreVehicleLimit | boolean, false | Skip the per-vehicle limit for this creation |
ignoreEnabled | boolean, false | Allow this creation even when the oil spill system is disabled |
Use overrides deliberately for scripted scenes that need them. These server exports do not run cleanup job, duty, or item checks for the calling resource.
Lifetime and saved IDs
Spills can disappear through cleanup, expiry, spreading, capacity limits, or explicit removal. The shipped lifetime is 90 minutes. Firejob attempts to save spills to its database; a successful creation return confirms an active synchronized spill, not a database-write acknowledgement. Database failures are logged separately.
Delete on restart is enabled by default. Disable it to restore unexpired saved spills after a resource restart. An explicit ID reset renumbers active spills, and cleared IDs may be reused later. Treat saved IDs as references to the current incident, not permanent identifiers. Use GetOilSpills() and your origin metadata when rebuilding an integration's state.
RemoveOilSpill(spillId, reason)
Immediately removes an active spill and synchronizes the removal. Get spillId from the second return value of CreateOilSpill (spill.id), or from an entry returned by GetOilSpills().
| Argument | Type | Required / default | Meaning |
|---|---|---|---|
spillId | string or number | Required | The spill's id, such as "17"; not a vehicle ID, plate, or array index |
reason | string | "export_removed" | Removal reason, for example "incident_finished" or "scene_reset" |
Returns one boolean: true when an active spill was removed, or false if no spill exists for that ID or an ID reset is in progress. There is no second error string. Removing the same spill twice normally returns true and then false.
The complete creation example above shows where the ID comes from. If your resource needs to find its active spills again, use their origin tag:
-- server.lua; matches the source tag used in the creation example.
for _, spill in ipairs(exports["sky_firejob"]:GetOilSpills()) do
if spill.source == "my_incident_resource" then
local removed = exports["sky_firejob"]:RemoveOilSpill(spill.id, "scene_reset")
print(("Remove oil spill %s: %s"):format(spill.id, tostring(removed)))
end
end
This example removes all active spills with that tag. Use the individual saved ID to remove only one. Direct export removal does not perform the absorbent/broom interaction or consume cleanup items. Reserve "cleaned" for normal cleanup completion: that reason can trigger configured rewards and scenario completion.
GetOilSpills()
Takes no arguments and returns an array of all currently active server-side spills, including both fresh and bound spills. Each entry has the same fields documented under CreateOilSpill. When there are no active spills, the result is an empty table {}.
-- server.lua
local spills = exports["sky_firejob"]:GetOilSpills()
for _, spill in ipairs(spills) do
print(("Spill %s: state=%s, source=%s, position=%.2f, %.2f, %.2f"):format(
spill.id,
spill.state,
spill.source,
spill.coords.x,
spill.coords.y,
spill.coords.z
))
end
Use spill.id as the removal ID. The position of an entry in this array can change as spills are added or removed. Re-query when you need current state; editing a returned table is not a supported update API.
Related shared integrations
The firejob also depends heavily on sky_jobs_base and inherits its shared systems for:
- Job registration
- Duty handling
- Storage
- Garages
- Dispatch
- Boss permissions
Support
Need help? Our support team is always ready to assist.
Join Discord