Configuration

All gameplay configuration for legends_firefighter lives in two files:

  • config/config.lua — job-wide settings (NPC, depot, fire, loot, rewards, blips, leveling, mission tiers)
  • config/routes.lua — route definitions and per-location fire data

System behavior (notifications, progress bars, inventory, money, callbacks) is configured in:

  • client/editable.luaClientSystems and per-event client hooks
  • server/editable.luaServerSystems, CanStartJob, CalculateBonus, OnRewardGiven

All files above are outside the escrow block and fully editable.

General Settings

debug

debug = false,

Description: Enables in-game zone visualization and extra console prints — helpful when adding new routes or locations.

Type: boolean

Default: false


interactionType

interactionType = 'ox_target',

Description: Which interaction system to use for the NPC and depot return point.

Type: string'ox_target', 'qb-target', or 'textui'

Default: 'ox_target'

If the chosen system isn't running, the resource falls back to a native textui prompt so players are never locked out of the NPC.


NPC

npc

npc = {
    model = 's_m_y_fireman_01',
    coords = vec4(-1067.91, -2378.78, 14.08, 146.92),
    label = 'Fire Department',
    icon = 'fas fa-fire-extinguisher',
    blip = {
        enabled = true,
        sprite = 60,
        color = 1,
        scale = 0.8,
        label = 'Fire Station',
    },
},
PropertyTypeDescription
modelstringPed model name for the fire-station NPC
coordsvec4Spawn position and heading
labelstringLabel shown on the target/textui prompt
iconstringFont Awesome icon for the target prompt
blip.enabledbooleanWhether to show a map blip for the station
blip.spritenumberGTA V blip sprite ID
blip.colornumberGTA V blip color ID
blip.scalenumberBlip size multiplier
blip.labelstringBlip label on the pause map

Depot

depot

depot = {
    returnRadius = 8.0,
    label = 'Return Vehicle',
    icon = 'fas fa-truck',
},
PropertyTypeDescription
returnRadiusnumberRadius (meters) around the vehicle spawn point that counts as "returned"
labelstringLabel shown on the return-vehicle target prompt
iconstringFont Awesome icon for the return prompt

The depot return point is per-tier — it uses the tier's vehicle.spawnPoint. Tier 1 (on-foot rookie) doesn't require a vehicle return; it finishes at the NPC.


Fire

fire

fire = {
    spreadRadius = 5.0,
    blazeRadius = 1.0,
},

Description: Default fire behavior. Per-tier overrides live inside missionTiers[n].fire.

PropertyTypeDescription
spreadRadiusnumberRadius for fireType = 'spread' locations (fires spread outward over an area)
blazeRadiusnumberRadius for fireType = 'blaze' locations (concentrated point fire)

Loot / Salvage

loot

loot = {
    enabled = true,
    searchDuration = 5000,
    searchTimeLimit = 60000,
    searchRadius = 3.0,
    icon = 'fas fa-search',
    label = 'Search Area',
    tables = { ... },
},
PropertyTypeDescription
enabledbooleanMaster toggle for the salvage/loot system
searchDurationnumberProgress-bar duration per search (ms)
searchTimeLimitnumberTime window after a fire is extinguished in which the area can still be searched (ms). 0 = unlimited
searchRadiusnumberDistance (meters) a player must be within to trigger a search
iconstringFont Awesome icon for the search prompt
labelstringLabel shown on the search prompt

Loot Tables

Four built-in tables are used by route locations via lootTable = 'vehicle' | 'street' | 'dumpster' | 'yard':

tables = {
    vehicle = {
        { item = 'phone',      min = 1, max = 1, chance = 8 },
        { item = 'wallet',     min = 1, max = 1, chance = 15 },
        { item = 'lighter',    min = 1, max = 1, chance = 20 },
        { item = 'metalscrap', min = 1, max = 5, chance = 40 },
        { item = 'plastic',    min = 1, max = 3, chance = 35 },
    },
    street = { ... },
    dumpster = { ... },
    yard = { ... },
},
PropertyTypeDescription
itemstringItem name as it appears in your inventory system
min / maxnumberQuantity range (inclusive)
chancenumberPercentage chance (0–100) the item drops on a given search

Each roll is independent. You can tune drop frequency by lowering chances or by shortening searchTimeLimit.


Rewards

rewards

rewards = {
    moneyType = 'cash',
},
PropertyTypeDescription
moneyTypestring'cash' or 'bank' — which account payout goes into

Per-tier payout amounts live inside missionTiers[n].rewards.perLocation and missionTiers[n].rewards.completionBonus (see below).


Blips

blips

blips = {
    fire = {
        sprite = 436,
        color = 1,
        scale = 0.9,
        route = true,
        label = 'Fire Location',
    },
    depot = {
        sprite = 60,
        color = 2,
        scale = 0.8,
        route = true,
        label = 'Return Truck',
    },
},
PropertyTypeDescription
spritenumberGTA V blip sprite ID
colornumberGTA V blip color ID
scalenumberBlip size multiplier
routebooleanWhether the blip auto-draws a GPS route
labelstringBlip label on the pause map

Leveling

leveling

leveling = {
    enabled = true,
    levels = {
        [1] = { name = 'Rookie',            xpRequired = 0 },
        [2] = { name = 'Firefighter',       xpRequired = 500 },
        [3] = { name = 'Aerial Specialist', xpRequired = 3500 },
    },
},
PropertyTypeDescription
enabledbooleanMaster toggle for the leveling/rank system
levelstableArray of { name, xpRequired } entries, ordered by rank
⚠️

Levels gate mission tiers — each tier's unlockLevel (see below) must match a defined level. Adding a new level requires a new tier or a matching unlockLevel change.

Per-tier XP values live inside missionTiers[n].xp (see below).


Mission Tiers

missionTiers

Three tiers are included by default. Each tier is fully self-contained — its vehicle, fire behavior, required item, rewards, XP, and unlock level live together.

Tier 1 — Rookie (on foot)

[1] = {
    name = 'Rookie Mission',
    description = 'Use your fire extinguisher on small fires',
    icon = 'fas fa-fire-extinguisher',
    image = './assets/rookie.png',
    unlockLevel = 1,
    vehicle = nil,
    requiredItem = 'weapon_fireextinguisher',
    consumeItem = false,
    fire = {
        progressPerExtinguish = 1.2,
        extinguishRange = 5.0,
        countPerLocation = 5,
        size = 15,
    },
    requireOnFoot = true,
    anim = { dict = 'weapons@misc@jerrycan@', clip = 'fire' },
    rewards = { perLocation = 75, completionBonus = 500 },
    xp = { perLocation = 2, routeBonus = 8 },
},
PropertyTypeDescription
name / descriptionstringShown on the UI tier-select screen
icon / imagestringUI icon + preview image path
unlockLevelnumberLevel required to pick this tier
vehicletable or nilVehicle spawned for this tier (see below); nil = on foot
requiredItemstring or nilInventory item required to start (e.g. weapon_fireextinguisher)
consumeItembooleanWhether the item is removed on job start
fire.progressPerExtinguishnumberProgress added per spray tick (higher = fires die faster)
fire.extinguishRangenumberMeters from which a fire can be hit
fire.countPerLocationnumberDefault fire count per location (route can override)
fire.sizenumberDefault fire size per location (route can override)
requireOnFootbooleanIf true, player must exit the vehicle to extinguish
anim.dict / anim.clipstringAnimation played while extinguishing
rewards.perLocationnumberPayout per completed location
rewards.completionBonusnumberFull-route completion bonus
xp.perLocationnumberXP per completed location
xp.routeBonusnumberXP granted for completing the full route

Tier 2 — Standard (firetruck)

[2] = {
    name = 'Standard Mission',
    unlockLevel = 2,
    requiredItem = nil,
    fire = {
        progressPerExtinguish = 0.7,
        extinguishRange = 35.0,
        countPerLocation = 10,
        size = 25,
    },
    requireOnFoot = false,
    rewards = { perLocation = 150, completionBonus = 1500 },
    xp = { perLocation = 3, routeBonus = 13 },
    vehicle = {
        model = 'firetruk',
        spawnPoint = vec4(-1078.93, -2376.69, 14.01, 149.89),
        plate = 'FIRET',
        rental = { enabled = false, cost = 500 },
    },
},
PropertyTypeDescription
vehicle.modelstringGTA V vehicle model spawned for this tier
vehicle.spawnPointvec4Spawn position + heading (also the depot return point)
vehicle.platestringLicense plate text
vehicle.rental.enabledbooleanWhether players pay to rent the vehicle
vehicle.rental.costnumberRental cost if enabled

Tier 3 — Aerial (helicopter)

[3] = {
    name = 'Aerial Mission',
    unlockLevel = 3,
    fire = {
        progressPerExtinguish = 0.5,
        extinguishRange = 20.0,
        countPerLocation = 40,
        size = 25,
        spreadRadius = 15.0,
    },
    helicopter = {
        sprayControl = 38,
        minAltitude = 0.0,
        maxAltitude = 10.0,
        sprayInterval = 100,
        horizontalRange = 20.0,
    },
    rewards = { perLocation = 250, completionBonus = 3000 },
    xp = { perLocation = 5, routeBonus = 20 },
    vehicle = {
        model = 'conada',
        spawnPoint = vec4(-1092.41, -2378.12, 13.95, 236.28),
        plate = 'FIREH',
        rental = { enabled = false, cost = 1000 },
    },
},
PropertyTypeDescription
helicopter.sprayControlnumberInput control index to hold for spraying (default 38 = E key)
helicopter.minAltitudenumberMinimum altitude (meters) above the fire to spray
helicopter.maxAltitudenumberMaximum altitude (meters) above the fire to spray
helicopter.sprayIntervalnumberSpray tick interval (ms)
helicopter.horizontalRangenumberHorizontal distance (meters) within which the spray counts as "over" the fire

Want to add a Tier 4 (e.g., a water-bomber plane)? Add a new missionTiers[4] block, a matching leveling.levels[4] entry, and tier-4 routes in config/routes.lua. The UI automatically picks up new tiers.


Routes

All route definitions live in config/routes.lua.

randomizeLocationOrder

randomizeLocationOrder = true,

Description: If true, locations within a route are visited in random order each run. If false, they're visited in the order they appear in the config.

Type: boolean

Default: true


routes

routes = {
    [101] = {
        name = 'Fire Training Route 1',
        tier = 1,
        locations = { ... },
    },
    [201] = { ... },
    [301] = { ... },
}
PropertyTypeDescription
[id]numberUnique numeric route ID. Convention: 1xx = tier 1, 2xx = tier 2, 3xx = tier 3
namestringRoute label shown in UI and blips
tiernumberMission tier this route belongs to (1, 2, or 3)
locationstableOrdered array of fire locations (see below)

Location format

{
    coords = vec3(1255.85, -2567.91, 41.72),
    label = 'Training Fire 1',
    fireType = 'blaze',
    fireCount = 3,
    fireSize = 10,
    spreadRadius = 2.0,
    lootTable = 'vehicle',
    searchable = true,
},
PropertyTypeDescription
coordsvec3Center of the fire scene
labelstringLocation label on blip and UI
fireTypestring'blaze' (concentrated) or 'spread' (spreads outward)
fireCountnumberNumber of fire instances at this location (overrides tier default)
fireSizenumberSize of each fire (overrides tier default)
spreadRadiusnumber (optional)Per-location spread radius override
lootTablestring or nilWhich config.loot.tables.* to roll against; nil disables search
searchablebooleanWhether the scene is searchable after fire extinguish

Editable Client Systems

In client/editable.lua:

ClientSystems

ClientSystems = {
    notifications = { system = 'auto', position = 'top-right', duration = 5000 },
    progress      = { system = 'auto', position = 'bottom', color = '#FF6B35' },
    menus         = { system = 'auto' },
    textui        = { system = 'auto', position = 'right-center' },
    callbacks     = { system = 'auto' },
}

Each subsystem accepts 'auto' (auto-detect best available) or a specific backend name ('ox_lib', 'qb-core', 'esx', 'native', 'simple', 'progressbar', 'cd_drawtextui', 'custom'). Set any to 'custom' to use your own implementation (templates are provided at the bottom of the file).

Client Event Hooks

function OnJobStart(routeId, routeData) end
function OnFireExtinguished(locationIndex, fireData) end
function OnJobComplete(completed, locationsCompleted, reward) end

Use these for custom sounds, chat messages, UI overlays, or analytics. Each is called at the obvious moment — no teardown required.


Editable Server Systems

In server/editable.lua:

ServerSystems

ServerSystems = {
    inventory = { system = 'auto' },  -- 'auto', 'ox_inventory', 'framework', 'custom'
    money     = { system = 'auto' },  -- 'auto', 'framework', 'custom'
    callbacks = { system = 'auto' },  -- 'auto', 'ox_lib', 'qb-core', 'esx', 'native', 'custom'
}

CanStartJob

function CanStartJob(source)
    -- return false to block job start
    return true
end

Gate job entry on items, jobs, cooldowns, whitelist, metadata — anything you can check server-side. Returning false blocks the NPC interaction with no side effects.

CalculateBonus

function CalculateBonus(source, locationsCompleted, totalLocations, defaultBonus)
    return defaultBonus
end

Tweak the completion bonus per-player. Common use cases: weekend double-pay, level-scaled bonuses, random "lucky" bonuses.

OnRewardGiven

function OnRewardGiven(source, totalReward, locationsCompleted, totalLocations, lootCollected)
    -- Post-payout hook
end

Fires after the player has been paid. Use for Discord webhooks, metadata updates (fires_extinguished), reputation systems, or database logging.


Localization

All player-facing text lives in locales/en.json. To add another language:

  1. Copy locales/en.json to locales/<lang>.json (e.g. locales/es.json)
  2. Translate the values, keep the keys
  3. If you use ox_lib's locale system, players on that locale will automatically see the translated strings

The resource declares ox_lib 'locale' in fxmanifest.lua — ox_lib picks the right file based on the server convar or client locale.

Need Help?

Join our Discord for support: discord.gg/lgnds (opens in a new tab)


Legends Store - Premium FiveM Scripts