ScriptsM Airbags

ScriptsM Airbags

A lot of FiveM vehicle crashes still feel empty and forgettable.

SM AirBags is built to fix that.

It adds animated driver and passenger airbags, smart crash detection, smooth deflation, seatbelt integration, and real player protection after serious impacts. The goal is simple: make crashes feel more immersive without turning them into annoying gameplay restrictions.

Installation

Download a resource (opens in a new tab) from keymaster or buy it by buttons at the top

Resource start order

It's important for your resources to start in a logical order to prevent errors from missing dependencies.

start [your framework]
start SM-AirBags

Config

There you can find an config of resource with description for all params

Config = {}
 
Config.Debug = false -- Enables debug prints for crash detection and deployment flow.
Config.Locale = 'en' -- Active locale key from Config.Locales.
Config.CrashPreset = 'balanced' -- Preset name: cinematic, balanced, realistic, hardcore, manual.
Config.DeploymentCooldownMs = 45000 -- Prevents repeated airbag deployment on the same vehicle for this long.
 
local function toLookup(list)
    local lookup = {}
    for _, value in ipairs(list) do
        lookup[value] = true
    end
    return lookup
end
 
local function merge(base, override)
    local result = {}
    for key, value in pairs(base or {}) do
        result[key] = value
    end
    for key, value in pairs(override or {}) do
        result[key] = value
    end
    return result
end
 
Config.EnabledVehicleClasses = toLookup({ -- GTA vehicle classes allowed to use the airbag system. https://wiki.rage.mp/wiki/Vehicle_Classes
    0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12
})
 
local crashDefaults = {
    useMinimumVehicleSpeed = false, -- If true, deployment can be blocked below minVehicleSpeedKmh unless the impact is severe enough.
    minVehicleSpeedKmh = 0.0, -- Minimum vehicle speed required when useMinimumVehicleSpeed is enabled.
    maxRollDegrees = 52.0, -- Blocks deployment when vehicle roll is above this angle.
    maxPitchDegrees = 32.0, -- Blocks deployment when vehicle pitch is above this angle.
    suppressIfAirborne = true, -- Prevents deployment while the vehicle is not on all wheels.
    suppressIfRearImpact = true, -- Prevents deployment for obvious rear impacts.
}
 
Config.CrashPresets = {
    cinematic = merge(crashDefaults, {
        minDeltaVKmh = 16.0, -- Minimum total speed drop to consider own crash severity.
        minForwardDeltaVKmh = 10.0, -- Minimum forward speed drop to consider frontal severity.
        minImpactDeltaVKmh = 14.0, -- Minimum raw impact delta-v to catch external hits.
        minBodyHealthLoss = 2.0, -- Minimum body damage usually required for deployment.
        severeDeltaVKmhBypassDamage = 28.0, -- Severe impact threshold that can bypass some damage checks.
        collisionGraceMs = 550, -- Time window after collision flag is seen.
        severeDeltaVNoCollisionKmh = 22.0, -- Emergency threshold when GTA collision flag is unreliable.
        emergencyBodyHealthLoss = 14.0, -- Emergency body damage fallback for missed collision flags.
        frontalDotThreshold = 0.45, -- Direction threshold for forward crash validation.
        frontalImpactDotThreshold = 0.10, -- Impact vector threshold for front-heavy collisions.
        severeImpactDeltaVKmhBypassDirection = 22.0, -- Severe impact threshold that can bypass direction checks.
    }),
    balanced = merge(crashDefaults, {
        minDeltaVKmh = 22.0,
        minForwardDeltaVKmh = 15.0,
        minImpactDeltaVKmh = 18.0,
        minBodyHealthLoss = 4.0,
        severeDeltaVKmhBypassDamage = 34.0,
        collisionGraceMs = 450,
        severeDeltaVNoCollisionKmh = 26.0,
        emergencyBodyHealthLoss = 18.0,
        frontalDotThreshold = 0.55,
        frontalImpactDotThreshold = 0.20,
        severeImpactDeltaVKmhBypassDirection = 26.0,
    }),
    realistic = merge(crashDefaults, {
        minDeltaVKmh = 26.0,
        minForwardDeltaVKmh = 18.0,
        minImpactDeltaVKmh = 22.0,
        minBodyHealthLoss = 6.0,
        severeDeltaVKmhBypassDamage = 38.0,
        collisionGraceMs = 400,
        severeDeltaVNoCollisionKmh = 30.0,
        emergencyBodyHealthLoss = 22.0,
        maxRollDegrees = 48.0,
        maxPitchDegrees = 28.0,
        frontalDotThreshold = 0.62,
        frontalImpactDotThreshold = 0.28,
        severeImpactDeltaVKmhBypassDirection = 30.0,
    }),
    hardcore = merge(crashDefaults, {
        minDeltaVKmh = 30.0,
        minForwardDeltaVKmh = 22.0,
        minImpactDeltaVKmh = 26.0,
        minBodyHealthLoss = 8.0,
        severeDeltaVKmhBypassDamage = 42.0,
        collisionGraceMs = 350,
        severeDeltaVNoCollisionKmh = 34.0,
        emergencyBodyHealthLoss = 28.0,
        maxRollDegrees = 45.0,
        maxPitchDegrees = 24.0,
        frontalDotThreshold = 0.70,
        frontalImpactDotThreshold = 0.35,
        severeImpactDeltaVKmhBypassDirection = 34.0,
    })
}
 
Config.CrashManual = merge(crashDefaults, {
    minDeltaVKmh = 22.0,
    minForwardDeltaVKmh = 15.0,
    minImpactDeltaVKmh = 18.0,
    minBodyHealthLoss = 4.0,
    severeDeltaVKmhBypassDamage = 34.0,
    collisionGraceMs = 450,
    severeDeltaVNoCollisionKmh = 26.0,
    emergencyBodyHealthLoss = 18.0,
    frontalDotThreshold = 0.55,
    frontalImpactDotThreshold = 0.20,
    severeImpactDeltaVKmhBypassDirection = 26.0,
})
 
Config.Crash = Config.CrashPreset == 'manual'
    and merge({}, Config.CrashManual)
    or merge({}, Config.CrashPresets[Config.CrashPreset] or Config.CrashPresets.balanced)
 
Config.Features = {
    damageProtection = true, -- Restores part of crash damage after airbag deployment.
    seatbeltBonus = true, -- Applies stronger protection when your seatbelt integration returns true.
    adaptiveDeployment = true, -- Uses direction-aware checks instead of simple severity only.
    manualRemoval = true, -- Allows players to hold E and remove a deflated airbag manually.
 
    hazardLights = false, -- Blinks vehicle indicators after deployment while crash state is active.
    engineCutoff = false, -- Cuts the engine when airbags deploy.
    persistentSRS = false, -- Keeps SRS state active even after the visual airbag is gone.
    mechanicReset = false, -- Requires an approved mechanic to fully clear SRS state.
    crashDiagnostics = false, -- Shows mechanic-only crash diagnostics in the 3D prompt.
}
 
Config.Mechanic = {
    framework = 'auto', -- auto, esx, qbcore, qbox, standalone.
    jobs = toLookup({
        'mechanic',
        'bennys'
    }), -- Job names allowed to perform mechanic-only SRS actions.
    acePermission = 'sm-airbags.mechanic', -- Optional ACE fallback for mechanic access.
    getJobName = function(_source) -- Optional custom job resolver. Return a job name string or nil.
        return nil
    end,
    isMechanic = function(_source, _jobName) -- Optional final override. Return true, false, or nil to fall back.
        return nil
    end,
}
 
Config.Safety = {
    airbagOnlyProtection = 0.35, -- Health restore multiplier when only the airbag protects the player.
    seatbeltAndAirbagProtection = 0.65, -- Health restore multiplier when both seatbelt and airbag are active.
    reduceRagdoll = true, -- Temporarily disables ragdoll right after deployment.
    reduceEjectionChance = true, -- Temporarily tries to keep the player inside the vehicle after deployment.
}
 
Config.Feedback = {
    shake = {
        enabled = true, -- Enables camera shake on deployment.
        intensity = 0.28, -- Camera shake strength.
        durationMs = 650, -- Camera shake duration.
    },
    blur = {
        enabled = true, -- Enables short post-impact blur.
        effect = 'hud_def_blur', -- Timecycle modifier used for blur.
        durationMs = 1600, -- Blur duration.
    },
}
 
Config.ManualRemoval = {
    holdKey = 38, -- Control index for the hold action, default E.
    seatedPrompt = true, -- Allows the prompt to appear while seated inside the crashed vehicle.
}
 
Config.Seats = {
    driver = true, -- Enables driver airbag deployment.
    frontPassenger = true, -- Enables front passenger airbag deployment when a passenger exists.
}
 
Config.IsSeatbeltOn = function(_ped, _vehicle) -- Return true, false, or nil from your seatbelt script.
    return nil
end
 
Config.Locales = {
    en = {
        manual_remove_prompt = 'Hold [E] to remove deployed airbag',
        manual_remove_progress = 'Hold [E] to remove deployed airbag (%s%%)',
        mechanic_reset_prompt = 'Hold [E] to service SRS',
        mechanic_reset_progress = 'Hold [E] to service SRS (%s%%)',
        diagnostic_title = 'SRS DEPLOYED',
        diagnostic_impact = 'Impact: %s km/h',
        diagnostic_seatbelt = 'Seatbelt: %s',
        diagnostic_driver = 'Driver airbag: %s',
        diagnostic_passenger = 'Passenger airbag: %s',
        diagnostic_status_on = 'ON',
        diagnostic_status_off = 'OFF',
        diagnostic_status_deployed = 'DEPLOYED',
        diagnostic_status_not_deployed = 'NOT DEPLOYED',
    }
}