ScriptsM AirBags

ScriptsM Airbags

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

SM AirBags is built to fix that.

It adds a visual driver airbag, physics-based crash deployment, smooth inflate and deflate animation, crash protection, optional seatbelt bonus, and an optional mechanic-driven SRS workflow.

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 = true -- 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.Mode = 'simple' -- Feature mode: simple, immersive, rp, custom.
Config.DeploymentCooldownMs = 45000 -- Prevents repeated airbag deployment on the same vehicle for this long.
 
Config.AirbagTiming = {
    holdMs = 2000, -- How long the airbag stays fully inflated before it starts deflating.
    deflateTransitionMs = 950, -- How long the smooth transition from inflated to deflated airbag takes.
}
 
Config.EnabledVehicleClasses = { -- GTA vehicle classes allowed to use the airbag system. https://wiki.rage.mp/wiki/Vehicle_Classes
    [0] = true,
    [1] = true,
    [2] = true,
    [3] = true,
    [4] = true,
    [5] = true,
    [6] = true,
    [7] = true,
    [9] = true,
    [10] = true,
    [11] = true,
    [12] = true,
}
 
Config.CrashPresets = {
    cinematic = {
        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.
        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 = {
        useMinimumVehicleSpeed = false,
        minVehicleSpeedKmh = 0.0,
        maxRollDegrees = 52.0,
        maxPitchDegrees = 32.0,
        suppressIfAirborne = true,
        suppressIfRearImpact = true,
        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 = {
        useMinimumVehicleSpeed = false,
        minVehicleSpeedKmh = 0.0,
        maxRollDegrees = 48.0,
        maxPitchDegrees = 28.0,
        suppressIfAirborne = true,
        suppressIfRearImpact = true,
        minDeltaVKmh = 26.0,
        minForwardDeltaVKmh = 18.0,
        minImpactDeltaVKmh = 22.0,
        minBodyHealthLoss = 6.0,
        severeDeltaVKmhBypassDamage = 38.0,
        collisionGraceMs = 400,
        severeDeltaVNoCollisionKmh = 30.0,
        emergencyBodyHealthLoss = 22.0,
        frontalDotThreshold = 0.62,
        frontalImpactDotThreshold = 0.28,
        severeImpactDeltaVKmhBypassDirection = 30.0,
    },
    hardcore = {
        useMinimumVehicleSpeed = false,
        minVehicleSpeedKmh = 0.0,
        maxRollDegrees = 45.0,
        maxPitchDegrees = 24.0,
        suppressIfAirborne = true,
        suppressIfRearImpact = true,
        minDeltaVKmh = 30.0,
        minForwardDeltaVKmh = 22.0,
        minImpactDeltaVKmh = 26.0,
        minBodyHealthLoss = 8.0,
        severeDeltaVKmhBypassDamage = 42.0,
        collisionGraceMs = 350,
        severeDeltaVNoCollisionKmh = 34.0,
        emergencyBodyHealthLoss = 28.0,
        frontalDotThreshold = 0.70,
        frontalImpactDotThreshold = 0.35,
        severeImpactDeltaVKmhBypassDirection = 34.0,
    },
}
 
Config.CrashManual = {
    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.
    minDeltaVKmh = 22.0, -- Minimum total speed drop to consider own crash severity.
    minForwardDeltaVKmh = 15.0, -- Minimum forward speed drop to consider frontal severity.
    minImpactDeltaVKmh = 18.0, -- Minimum raw impact delta-v to catch external hits.
    minBodyHealthLoss = 4.0, -- Minimum body damage usually required for deployment.
    severeDeltaVKmhBypassDamage = 34.0, -- Severe impact threshold that can bypass some damage checks.
    collisionGraceMs = 450, -- Time window after collision flag is seen.
    severeDeltaVNoCollisionKmh = 26.0, -- Emergency threshold when GTA collision flag is unreliable.
    emergencyBodyHealthLoss = 18.0, -- Emergency body damage fallback for missed collision flags.
    frontalDotThreshold = 0.55, -- Direction threshold for forward crash validation.
    frontalImpactDotThreshold = 0.20, -- Impact vector threshold for front-heavy collisions.
    severeImpactDeltaVKmhBypassDirection = 26.0, -- Severe impact threshold that can bypass direction checks.
}
 
Config.Crash = Config.CrashPresets.balanced
 
if Config.CrashPreset == 'manual' then
    Config.Crash = Config.CrashManual
elseif Config.CrashPresets[Config.CrashPreset] then
    Config.Crash = Config.CrashPresets[Config.CrashPreset]
end
 
Config.FeaturePresets = {
    simple = {
        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.
    },
    immersive = {
        damageProtection = true,
        seatbeltBonus = true,
        adaptiveDeployment = true,
        manualRemoval = true,
        hazardLights = true,
        engineCutoff = false,
        persistentSRS = true,
        mechanicReset = true,
        crashDiagnostics = false,
    },
    rp = {
        damageProtection = true,
        seatbeltBonus = true,
        adaptiveDeployment = true,
        manualRemoval = false,
        hazardLights = true,
        engineCutoff = true,
        persistentSRS = true,
        mechanicReset = true,
        crashDiagnostics = true,
    },
}
 
Config.Features = {
    damageProtection = true, -- Used only when Config.Mode = 'custom'.
    seatbeltBonus = true, -- Used only when Config.Mode = 'custom'.
    adaptiveDeployment = true, -- Used only when Config.Mode = 'custom'.
    manualRemoval = true, -- Used only when Config.Mode = 'custom'.
    hazardLights = false, -- Used only when Config.Mode = 'custom'.
    engineCutoff = false, -- Used only when Config.Mode = 'custom'.
    persistentSRS = false, -- Used only when Config.Mode = 'custom'.
    mechanicReset = false, -- Used only when Config.Mode = 'custom'.
    crashDiagnostics = false, -- Used only when Config.Mode = 'custom'.
}
 
if Config.Mode ~= 'custom' and Config.FeaturePresets[Config.Mode] then
    Config.Features = Config.FeaturePresets[Config.Mode]
end
 
Config.Mechanic = {
    framework = 'auto', -- auto, esx, qbcore, qbox, standalone.
    jobs = {
        unemployed = true,
        bennys = true,
    }, -- 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 = 73, -- Control index for the hold action, default X.
    seatedPrompt = true, -- Shows an in-vehicle prompt telling the player to exit first before removing the airbag.
}
 
Config.Integrations = {
    useNotifications = false, -- Enables Config.Integrations.Notify hook.
    useProgressBars = false, -- Enables Config.Integrations.Progress hook.
    Notify = function(_data) -- Optional notification hook. Return true if your notification was shown.
        return false
    end,
    Progress = function(_data) -- Optional progress bar hook. Should block until done and return true on success.
        return false
    end,
}
 
Config.Seats = {
    driver = true, -- Enables driver airbag deployment.
}
 
Config.IsSeatbeltOn = function(_ped, _vehicle) -- Return true, false, or nil from your seatbelt script.
    return nil
end
 
Config.Locales = {
    en = {
        manual_remove_prompt = 'Hold [X] remove airbag',
        manual_remove_exit_vehicle = 'Exit vehicle first to remove airbag',
        manual_remove_progress = 'Removing airbag (%s%%)',
        mechanic_inspect_prompt = 'Hold [X] inspect SRS',
        mechanic_inspect_progress = 'Inspecting SRS (%s%%)',
        mechanic_reset_prompt = 'Hold [X] service SRS',
        mechanic_reset_progress = 'Servicing SRS (%s%%)',
        mechanic_required_prompt = 'SRS deployed~n~Mechanic required',
        manual_remove_done = 'Airbag removed',
        mechanic_inspect_done = 'SRS inspection complete',
        mechanic_reset_done = 'SRS service complete',
        diagnostic_title = 'SRS DEPLOYED',
        diagnostic_impact = 'Impact: %s km/h',
        diagnostic_seatbelt = 'Seatbelt: %s',
        diagnostic_driver = 'Driver: %s',
        diagnostic_status_on = 'ON',
        diagnostic_status_off = 'OFF',
        diagnostic_status_deployed = 'DEPLOYED',
        diagnostic_status_not_deployed = 'NOT DEPLOYED',
    }
}