Browse docs

Exports

Fire Job server exports with argument types, return values, incident IDs, error handling, and complete oil spill examples.

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:

OperationReturn value on successID to keep
CreateFireOne table: { success = true, fireId = ..., type = ..., label = ... }result.fireId, a numeric fire ID
CreateVehicleFireOne table: { success = true, fireId = ... }Keep the vehicle network ID you supplied for RemoveVehicleFire; result.fireId identifies the fire
CreateOilSpillTwo values: true, spillspill.id, a string such as "17", for RemoveOilSpill
GetOilSpillsAn array of spill tablesEach 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 fieldTypeRequired / defaultMeaning
payloadtableRequiredFire creation data
payload.coords{ x, y, z } or vector3RequiredWorld position with numeric coordinates
payload.typestring"trash"A configured fire profile or alias
payload.metadatatableOptionalOverrides for this fire, described below
creatornumber0Player 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), and label (string).
  • Failure: success = false and error (string). Possible errors are invalid_payload, invalid_coords, invalid_fire_type, and create_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 fieldTypeRequired / defaultMeaning
payloadtableRequiredVehicle fire creation data
payload.netIdnumberSupply for an attached vehicle fireNetwork ID of the existing vehicle, obtained by your vehicle integration; not an entity handle or plate
payload.coords{ x, y, z } or vector3Optional when netId resolves to an existing vehicleFire position; otherwise the vehicle position is used
payload.platestringOptionalVehicle plate metadata; does not find or select a vehicle
payload.sourcestringOptionalDescription of the origin, such as your resource name
payload.initialStagestring"smoke""smoke", "smallFire", or "fullFire", when progression is enabled
payload.smokeDensitynumberConfig/profile defaultSmoke density; the selected progression stage can override it
payload.explosionDelaySecondsnumberConfig defaultExplosion delay in seconds when explosions are enabled; progression can delay the start of this timer
payload.engineHealth, bodyHealth, petrolTankHealthnumberConfig defaultsOptional vehicle health overrides
payload.effectstableProfile defaultsOptional flame and smoke catalog IDs; unknown IDs return invalid_effect
creatornumber0Player server ID, or 0 for a server-created incident
optionstableOptionalCreation 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 include disabled, invalid_coords, already_burning, limit, external_disabled, too_far, invalid_effect, and create_failed.
  • already_burning can include the existing fireId when 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, or cooldown; a cooldown response includes remaining seconds.
-- 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.

ArgumentTypeRequired / defaultMeaning
netIdnumberRequiredThe same vehicle network ID supplied to CreateVehicleFire, not its returned fireId
reasonstring"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 fieldTypeRequired / defaultMeaning
payloadtableRequiredSpill creation data
payload.coords{ x, y, z } or vector3RequiredWorld position with numeric coordinates
payload.radiusnumberConfigured slip radius, normally 1.25Spill radius; clamped to 0.25–5.0
payload.intensitynumberConfigured default, normally 1.0Intensity from 0.0 to 1.0; 1.0 is full intensity
payload.sourcestring"vehicle" in the spill recordOrigin tag, such as "my_incident_resource"; useful when finding your spills later
payload.sourcePartstring"engine_oil"Originating fluid/component, for example "engine_oil" or "transmission_fluid"
payload.sourceVehicleNetIdnumber0Optional originating vehicle network ID; separate from the new spill ID
payload.sourcePlatestring""Optional plate metadata
payload.canSpreadbooleantrueWhether vehicles may spread this spill
payload.statestring"fresh"Use "bound" to create a spill that is already treated with absorbent
creatornumberOptionalPlayer server ID associated with the request; use 0 for a scripted incident
optionstableOptionalSource 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:

FieldTypeMeaning
idstringAssigned spill ID, for example "17"; pass this to RemoveOilSpill
coords{ x, y, z }Spill position
radius, intensitynumberEffective values after defaults and clamping
statestring"fresh" or "bound"
source, sourcePart, sourcePlatestringOrigin metadata
sourceVehicleNetIdnumberOriginating vehicle network ID, or 0
canSpreadbooleanWhether the spill may spread
boundBynumber or absentPlayer server ID associated with binding, if recorded
createdAtMsnumberCreation time relative to the current server runtime; not a Unix timestamp

A failed call returns false, error:

ErrorMeaning
disabledThe oil spill system is disabled
invalid_payloadpayload is not a table
invalid_coordsCoordinates are missing or invalid
cooldownThe same source group created a spill too recently
too_closeThe position is too close to the last spill created by that source group
vehicle_limitThe originating vehicle has reached its active-spill limit
resetting_idsAn 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 fieldType / defaultEffect
sourceKeystring, automatic groupingExplicit shared key for cooldown and spacing
ignoreSourceCooldownboolean, falseSkip the source cooldown check for this creation
ignoreSourceMinDistanceboolean, falseSkip minimum spacing for this creation
ignoreVehicleLimitboolean, falseSkip the per-vehicle limit for this creation
ignoreEnabledboolean, falseAllow 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().

ArgumentTypeRequired / defaultMeaning
spillIdstring or numberRequiredThe spill's id, such as "17"; not a vehicle ID, plate, or array index
reasonstring"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.

The firejob also depends heavily on sky_jobs_base and inherits its shared systems for:

  • Job registration
  • Duty handling
  • Storage
  • Garages
  • Dispatch
  • Boss permissions
See the Sky Jobs Base Server Exports page for shared integrations like dispatch creation, external garage registration, and storage helpers.

Support

Need help? Our support team is always ready to assist.

Join Discord