546 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			546 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
---@alias tire { index: integer, distance: number, coords: vector3, name: string, vehicle: integer }
 | 
						|
 | 
						|
-- Variables --
 | 
						|
local isSlashing = false
 | 
						|
 | 
						|
 | 
						|
-- Functions --
 | 
						|
 | 
						|
---Requests and waits for a animation dictionary to be loaded
 | 
						|
---@param dict string
 | 
						|
local function loadAnimDict(dict)
 | 
						|
    RequestAnimDict(dict)
 | 
						|
    while not HasAnimDictLoaded(dict) do
 | 
						|
        Wait(0)
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
---Async function that waits until anim is played or timeout is passed
 | 
						|
---@param ped integer
 | 
						|
---@param animDict string
 | 
						|
---@param animName string
 | 
						|
---@param timeout integer|nil Deciseconds, defualts to 30 (3000ms)
 | 
						|
---@return boolean playedAnim
 | 
						|
local function waitUntilPedIsPlayingAnim(ped, animDict, animName, timeout)
 | 
						|
    if not timeout then
 | 
						|
        timeout = 30
 | 
						|
    end
 | 
						|
 | 
						|
    while not IsEntityPlayingAnim(ped, animDict, animName, 3) do
 | 
						|
        timeout = timeout - 1
 | 
						|
        if timeout <= 0 then
 | 
						|
            return false
 | 
						|
        end
 | 
						|
 | 
						|
        Wait(100)
 | 
						|
    end
 | 
						|
 | 
						|
    return true
 | 
						|
end
 | 
						|
 | 
						|
---Returns if the vehicle's model is blacklisted from getting slashed
 | 
						|
---@param vehicle integer
 | 
						|
---@return boolean isBlacklisted
 | 
						|
---@return string|nil blacklistReason
 | 
						|
local function isVehicleModelBlacklisted(vehicle)
 | 
						|
    local blacklistReason = Config.VehicleBlacklist[GetEntityModel(vehicle)]
 | 
						|
    if blacklistReason == nil then
 | 
						|
        if not Config.CanSlashEmergencyVehicles and GetVehicleClass(vehicle) == 18 then
 | 
						|
            blacklistReason = 3
 | 
						|
        end
 | 
						|
    end
 | 
						|
 | 
						|
    return blacklistReason ~= nil, VEHICLE_BLACKLIST_REASONS[blacklistReason]
 | 
						|
end
 | 
						|
 | 
						|
---Returns if the weapon can slash a tire
 | 
						|
---@return boolean canSlash
 | 
						|
local function canWeaponSlashTires(weaponHash)
 | 
						|
    return Config.AllowedWeapons[weaponHash] ~= nil
 | 
						|
end
 | 
						|
 | 
						|
---Returns if the current player weapon can slash a tire
 | 
						|
---@return boolean canSlash
 | 
						|
local function canCurrentWeaponSlashTires()
 | 
						|
    local weaponHash = GetSelectedPedWeapon(PlayerPedId())
 | 
						|
    return canWeaponSlashTires(weaponHash)
 | 
						|
end
 | 
						|
 | 
						|
---Gets the heading from coords A to coords B
 | 
						|
---@param initialCoords vector2
 | 
						|
---@param targetCoords vector2
 | 
						|
---@return number heading
 | 
						|
local function getHeadingBetweenCoords(initialCoords, targetCoords)
 | 
						|
    local x = targetCoords.x - initialCoords.x
 | 
						|
    local y = targetCoords.y - initialCoords.y
 | 
						|
 | 
						|
    local heading = GetHeadingFromVector_2d(x, y)
 | 
						|
    return heading
 | 
						|
end
 | 
						|
 | 
						|
---Burst a vehicles tire
 | 
						|
---@param vehicle integer
 | 
						|
---@param tireIndex integer
 | 
						|
local function burstVehicleTire(vehicle, tireIndex)
 | 
						|
    local bulletproof = not GetVehicleTyresCanBurst(vehicle)
 | 
						|
    if bulletproof then
 | 
						|
        SetVehicleTyresCanBurst(vehicle, true)
 | 
						|
    end
 | 
						|
 | 
						|
    -- This is to give it a sound effect
 | 
						|
    SetVehicleTyreBurst(vehicle, tireIndex, true, 1000.0)
 | 
						|
    SetVehicleTyreFixed(vehicle, tireIndex)
 | 
						|
 | 
						|
    -- Actuall tire deflation
 | 
						|
    SetVehicleTyreBurst(vehicle, tireIndex, false, 100.0)
 | 
						|
 | 
						|
    if bulletproof then
 | 
						|
        SetVehicleTyresCanBurst(vehicle, false)
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
---Gets data for the vehicle tire
 | 
						|
---@param vehicle integer
 | 
						|
---@param boneName string
 | 
						|
---@param coords vector3|nil
 | 
						|
---@return tire tire
 | 
						|
local function getVehicleTireByBone(vehicle, boneName, coords)
 | 
						|
    local boneIndex = GetEntityBoneIndexByName(vehicle, boneName)
 | 
						|
    if boneIndex == -1 then
 | 
						|
        return {}
 | 
						|
    end
 | 
						|
 | 
						|
    local boneCoords = GetWorldPositionOfEntityBone(vehicle, boneIndex)
 | 
						|
    if not coords then
 | 
						|
        coords = GetEntityCoords(PlayerPedId())
 | 
						|
    end
 | 
						|
 | 
						|
    return {
 | 
						|
        index = WHEEL_BONES[boneName],
 | 
						|
        distance = #(coords - boneCoords),
 | 
						|
        coords = boneCoords,
 | 
						|
        name = boneName,
 | 
						|
        vehicle = vehicle
 | 
						|
    }
 | 
						|
end
 | 
						|
 | 
						|
---Returns the closest tire of a vehicle
 | 
						|
---@param vehicle integer
 | 
						|
---@param coords vector3|nil|false
 | 
						|
---@return table closestVehicle
 | 
						|
local function getClosestVehicleTire(vehicle, coords)
 | 
						|
    local closest = {
 | 
						|
        distance = Config.MaxTireDetectionDist,
 | 
						|
    }
 | 
						|
 | 
						|
    if not coords then
 | 
						|
        coords = GetEntityCoords(PlayerPedId())
 | 
						|
    end
 | 
						|
 | 
						|
    for boneName, _index in pairs(WHEEL_BONES) do
 | 
						|
        local tire = getVehicleTireByBone(vehicle, boneName, coords)
 | 
						|
 | 
						|
        if tire.index ~= nil and tire.distance < closest.distance then
 | 
						|
            closest = tire
 | 
						|
        end
 | 
						|
    end
 | 
						|
 | 
						|
    return closest
 | 
						|
end
 | 
						|
 | 
						|
---Makes the ped face the spesifed coords
 | 
						|
---@param ped integer
 | 
						|
---@param coords vector3
 | 
						|
local function makePedFaceCoords(ped, coords)
 | 
						|
    local headingDifference = math.abs(GetEntityHeading(ped) - getHeadingBetweenCoords(GetEntityCoords(ped), coords))
 | 
						|
    if headingDifference < 40.0 then
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    local duration = math.min(math.floor(headingDifference*6), 1000)
 | 
						|
    TaskTurnPedToFaceCoord(ped, coords.x, coords.y, coords.z, duration)
 | 
						|
    Wait(duration)
 | 
						|
end
 | 
						|
 | 
						|
---Checks if the ped should be given the flee task from the spesifed coords
 | 
						|
---@param ped integer
 | 
						|
---@param coords vector3
 | 
						|
---@param vehicle integer
 | 
						|
---@param playerPed integer
 | 
						|
---@return boolean canFleePed
 | 
						|
local function canGivePedFleeTask(ped, coords, vehicle, playerPed)
 | 
						|
    local dist = #(coords - GetEntityCoords(ped))
 | 
						|
    if dist > Config.AIReactionDistance then
 | 
						|
        return false
 | 
						|
    end
 | 
						|
 | 
						|
    if IsPedAPlayer(ped) then
 | 
						|
        return false
 | 
						|
    end
 | 
						|
 | 
						|
    -- Frozen peds can't flee anyway, and they are most likley a script handled ped (for stores and robberies for example)
 | 
						|
    if IsEntityPositionFrozen(ped) then
 | 
						|
        return false
 | 
						|
    end
 | 
						|
 | 
						|
    -- If the ped has the CPED_CONFIG_FLAG_DisableShockingEvents flag
 | 
						|
    if GetPedConfigFlag(ped, 294, true) then
 | 
						|
        return false
 | 
						|
    end
 | 
						|
 | 
						|
    -- Ignore dead peds
 | 
						|
    if IsPedDeadOrDying(ped, true) then
 | 
						|
        return false
 | 
						|
    end
 | 
						|
 | 
						|
    if not IsEntityVisible(ped) then
 | 
						|
        return false
 | 
						|
    end
 | 
						|
 | 
						|
    if not IsPedHuman(ped) then
 | 
						|
        return false
 | 
						|
    end
 | 
						|
 | 
						|
    -- This is cpu demanding, so it should be left as the last check
 | 
						|
    if GetVehiclePedIsIn(ped, false) ~= vehicle and not HasEntityClearLosToEntityInFront(ped, playerPed) then
 | 
						|
        return false
 | 
						|
    end
 | 
						|
 | 
						|
    return true
 | 
						|
end
 | 
						|
 | 
						|
---Gets the peds that we want to react and flee after we have slashed a tire
 | 
						|
---@param coords vector3
 | 
						|
---@param vehicle integer The vehicle of the tire getting slashed
 | 
						|
---@return table <integer, integer>
 | 
						|
local function getPedsToFlee(coords, vehicle, playerPed)
 | 
						|
    local peds = {}
 | 
						|
    local pedPool = GetGamePool('CPed')
 | 
						|
 | 
						|
    for i = 1, #pedPool do
 | 
						|
        local ped = pedPool[i]
 | 
						|
        if canGivePedFleeTask(ped, coords, vehicle, playerPed) then
 | 
						|
            peds[#peds+1] = PedToNet(ped)
 | 
						|
        end
 | 
						|
    end
 | 
						|
 | 
						|
    return peds
 | 
						|
end
 | 
						|
 | 
						|
---Displays a message and sets isSlashing to false
 | 
						|
---@param notifMessage string
 | 
						|
local function slashTireEnded(notifMessage)
 | 
						|
    DisplayNotification(notifMessage)
 | 
						|
    isSlashing = false
 | 
						|
end
 | 
						|
 | 
						|
---Slashes a vehicles tire
 | 
						|
---@param tire tire
 | 
						|
local function slashTire(tire)
 | 
						|
    isSlashing = true
 | 
						|
    local playerPed = PlayerPedId()
 | 
						|
    local vehicle = tire.vehicle
 | 
						|
 | 
						|
    if Config.DoFaceCoordTask then
 | 
						|
        makePedFaceCoords(playerPed, tire.coords)
 | 
						|
    end
 | 
						|
 | 
						|
    loadAnimDict(Config.SlashTireAnimation.Dict)
 | 
						|
    TaskPlayAnim(playerPed, Config.SlashTireAnimation.Dict, Config.SlashTireAnimation.Name, 2.0, 1.0, 700, 0, 0, false, false, false)
 | 
						|
    RemoveAnimDict(Config.SlashTireAnimation.Dict)
 | 
						|
 | 
						|
    if Config.DoAnimationCheckLoop then
 | 
						|
        local playedAnim = waitUntilPedIsPlayingAnim(playerPed, Config.SlashTireAnimation.Dict, Config.SlashTireAnimation.Name, 30)
 | 
						|
        if not playedAnim then
 | 
						|
            slashTireEnded(GetLocalization('slash_timeout'))
 | 
						|
            return
 | 
						|
        end
 | 
						|
    end
 | 
						|
 | 
						|
    Wait(450)
 | 
						|
 | 
						|
    local weaponHash = GetSelectedPedWeapon(playerPed)
 | 
						|
    local canSlash = canWeaponSlashTires(weaponHash)
 | 
						|
    if not canSlash then
 | 
						|
        slashTireEnded(GetLocalization('invalid_weapon'))
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    -- Get the data for the same tire again and check the new distance in case it has changed
 | 
						|
    local updatedTire = getVehicleTireByBone(vehicle, tire.name)
 | 
						|
    if updatedTire.distance > Config.MaxTireDetectionDist then
 | 
						|
        slashTireEnded(GetLocalization('slash_timeout'))
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    local isBulletproof = not GetVehicleTyresCanBurst(vehicle)
 | 
						|
    if isBulletproof and (Config.BulletproofSetting == 'proof' or Config.BulletproofSetting == 'limit' and not Config.AllowedWeapons[weaponHash]?.canSlashBulletProof) then
 | 
						|
        slashTireEnded(GetLocalization('tire_is_bulletproof'))
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    -- If we have network control over the vehicle then just burst the tire, if not we send the event to the server
 | 
						|
    local hasNetworkControlOverVehicle = NetworkHasControlOfEntity(vehicle)
 | 
						|
    if hasNetworkControlOverVehicle then
 | 
						|
        burstVehicleTire(vehicle, tire.index)
 | 
						|
    end
 | 
						|
 | 
						|
    local peds = getPedsToFlee(tire.coords, tire.vehicle, playerPed)
 | 
						|
 | 
						|
    -- Send event to server (for logging + tire burst if we did not have network control)
 | 
						|
    TriggerServerEvent('slashtires:slashTire', NetworkGetNetworkIdFromEntity(vehicle), tire.index, peds, hasNetworkControlOverVehicle)
 | 
						|
 | 
						|
    -- Event for other scripts to listen to
 | 
						|
    TriggerEvent('slashtires:slashedTire', vehicle, tire.index)
 | 
						|
 | 
						|
    Wait(1000)
 | 
						|
    isSlashing = false
 | 
						|
end
 | 
						|
 | 
						|
---Does a raycast check to get the current target vehicle
 | 
						|
---@return integer|nil
 | 
						|
local function getTargetVehicle()
 | 
						|
    local playerPed = PlayerPedId()
 | 
						|
    local coords = GetEntityCoords(playerPed)
 | 
						|
    local coordTo = GetOffsetFromEntityInWorldCoords(playerPed, 0.0, 2.0, 0.0)
 | 
						|
 | 
						|
    local rayHandle = StartShapeTestCapsule(coords.x, coords.y, coords.z, coordTo.x, coordTo.y, coordTo.z, 1.0, 6, playerPed, 7)
 | 
						|
    local _retval, hit, _endCoords, _surfaceNormal, entityHit = GetShapeTestResult(rayHandle)
 | 
						|
 | 
						|
    if hit and IsEntityAVehicle(entityHit) then
 | 
						|
        return entityHit
 | 
						|
    else
 | 
						|
        return nil
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
---Returns if the player can slash the vehicle tire
 | 
						|
---@param tire tire
 | 
						|
---@return boolean canSlash
 | 
						|
---@return string|nil reason
 | 
						|
local function canSlashVehicleTire(tire)
 | 
						|
    if isSlashing then
 | 
						|
        return false, 'is_slashing'
 | 
						|
    end
 | 
						|
 | 
						|
    local canSlash, reason = CanPlayerSlashTires()
 | 
						|
    if not canSlash then
 | 
						|
        return false, reason
 | 
						|
    end
 | 
						|
 | 
						|
    local playerPed = PlayerPedId()
 | 
						|
    if IsPedRagdoll(playerPed) then
 | 
						|
        return false, 'in_ragdoll'
 | 
						|
    end
 | 
						|
 | 
						|
    if not canCurrentWeaponSlashTires() then
 | 
						|
        return false, 'invalid_weapon'
 | 
						|
    end
 | 
						|
 | 
						|
    local isBlacklisted, blacklistReason = isVehicleModelBlacklisted(tire.vehicle)
 | 
						|
    if isBlacklisted then
 | 
						|
        return false, blacklistReason
 | 
						|
    end
 | 
						|
 | 
						|
    if tire.distance > Config.MaxTireInteractionDist then
 | 
						|
        return false, 'too_far_away'
 | 
						|
    end
 | 
						|
 | 
						|
    if IsVehicleTyreBurst(tire.vehicle, tire.index, false) then
 | 
						|
        return false, 'tire_is_punctured'
 | 
						|
    end
 | 
						|
 | 
						|
    return true
 | 
						|
end
 | 
						|
 | 
						|
---Attempts to slash the vehicles tire
 | 
						|
---@param tire tire
 | 
						|
local function attemptToSlashTire(tire)
 | 
						|
    local canSlash, reason = canSlashVehicleTire(tire)
 | 
						|
    if not canSlash and reason then
 | 
						|
        DisplayNotification(GetLocalization(reason))
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    slashTire(tire)
 | 
						|
end
 | 
						|
 | 
						|
---Returns if we can interact with the tires of a vehicle
 | 
						|
---@param vehicle integer
 | 
						|
---@return boolean canInteract
 | 
						|
local function canInteractWithVehicleTires(vehicle)
 | 
						|
    local isBlacklisted, blacklistReason = isVehicleModelBlacklisted(vehicle)
 | 
						|
    if not isBlacklisted then
 | 
						|
        return true
 | 
						|
    end
 | 
						|
 | 
						|
    if blacklistReason == 'vehicle_is_blacklisted' or blacklistReason == 'tire_is_indestructible' or blacklistReason == 'vehicle_is_emergency' then
 | 
						|
        return true
 | 
						|
    end
 | 
						|
 | 
						|
    return false
 | 
						|
end
 | 
						|
 | 
						|
---Gets the closest vehicle and tire and calls the attemptToSlashTire function
 | 
						|
local function slashTireCommand()
 | 
						|
    if IsPedInAnyVehicle(PlayerPedId(), false) then
 | 
						|
        DisplayNotification(GetLocalization('in_a_vehicle'))
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    local vehicle = getTargetVehicle()
 | 
						|
    if vehicle == nil then
 | 
						|
        DisplayNotification(GetLocalization('no_vehicle_nearby'))
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    local tire = getClosestVehicleTire(vehicle)
 | 
						|
    if tire.index == nil then
 | 
						|
        DisplayNotification(GetLocalization('no_tire_nearby'))
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    attemptToSlashTire(tire)
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
-- Targeting / 3rd Eye --
 | 
						|
---Returns if a target script should show the slash tire option
 | 
						|
---@param vehicle integer
 | 
						|
---@return boolean canInteract
 | 
						|
function TargetCanInteract(vehicle)
 | 
						|
    if not canCurrentWeaponSlashTires() then
 | 
						|
        return false
 | 
						|
    end
 | 
						|
 | 
						|
    if not canInteractWithVehicleTires(vehicle) then
 | 
						|
        return false
 | 
						|
    end
 | 
						|
 | 
						|
    return true
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
-- Commands, Key Mapping & Threads --
 | 
						|
if Config.HelpText then
 | 
						|
    local isShowingHelpText = false
 | 
						|
 | 
						|
    ---If the slashtire key mapping press should be blocked 
 | 
						|
    ---@return boolean block
 | 
						|
    local function shouldSlashKeyPressBeBlocked()
 | 
						|
        return not isShowingHelpText or IsPauseMenuActive()
 | 
						|
    end
 | 
						|
 | 
						|
    RegisterKeyMapping('+slashtire', GetLocalization('keymapping_desc_keyboard'), 'keyboard', Config.DefaultKey)
 | 
						|
    RegisterCommand('+slashtire', function()
 | 
						|
        if not shouldSlashKeyPressBeBlocked() then
 | 
						|
            slashTireCommand()
 | 
						|
        end
 | 
						|
    end, false)
 | 
						|
    RegisterCommand('-slashtire', function()
 | 
						|
        -- Do nothing
 | 
						|
    end, false)
 | 
						|
 | 
						|
    -- For controller users
 | 
						|
    RegisterKeyMapping('stc', GetLocalization('keymapping_desc_controller'), 'PAD_ANALOGBUTTON', Config.DefaultPadAnalogButton)
 | 
						|
    RegisterCommand('stc', function()
 | 
						|
        if not shouldSlashKeyPressBeBlocked() then
 | 
						|
            slashTireCommand()
 | 
						|
        end
 | 
						|
    end, false)
 | 
						|
 | 
						|
    ---Does all the prompt checks and shows the help text if successful, returns the time that the script should wait until next check
 | 
						|
    ---@return integer waitMs
 | 
						|
    ---@return boolean showHelpText
 | 
						|
    local function promptTick()
 | 
						|
        if isSlashing or IsPedInAnyVehicle(PlayerPedId(), false) then
 | 
						|
            return 1000, false
 | 
						|
        end
 | 
						|
 | 
						|
        local vehicle = getTargetVehicle()
 | 
						|
        if vehicle == nil or not canInteractWithVehicleTires(vehicle) then
 | 
						|
            return 500, false
 | 
						|
        end
 | 
						|
 | 
						|
        local tire = getClosestVehicleTire(vehicle)
 | 
						|
        if tire.index == nil or tire.distance > Config.MaxTireInteractionDist or IsVehicleTyreBurst(vehicle, tire.index, false) then
 | 
						|
            return 250, false
 | 
						|
        end
 | 
						|
 | 
						|
        return 100, true
 | 
						|
    end
 | 
						|
 | 
						|
    local threadIsActive = false
 | 
						|
    local slashWeaponEquipped = false
 | 
						|
 | 
						|
    local function weaponEquippedThread()
 | 
						|
        threadIsActive = true
 | 
						|
 | 
						|
        while slashWeaponEquipped do
 | 
						|
            local wait, showHelpText = promptTick()
 | 
						|
            if showHelpText then
 | 
						|
                if not isShowingHelpText then
 | 
						|
                    StartHelpText()
 | 
						|
                    isShowingHelpText = true
 | 
						|
                end
 | 
						|
            elseif isShowingHelpText then
 | 
						|
                StopHelpText()
 | 
						|
                isShowingHelpText = false
 | 
						|
            end
 | 
						|
 | 
						|
            Wait(wait)
 | 
						|
        end
 | 
						|
 | 
						|
        -- Hide the help text if the weapon was de-equipped
 | 
						|
        if isShowingHelpText then
 | 
						|
            StopHelpText()
 | 
						|
            isShowingHelpText = false
 | 
						|
        end
 | 
						|
 | 
						|
        threadIsActive = false
 | 
						|
    end
 | 
						|
 | 
						|
    AddEventHandler('slashtires:slashWeaponEquipped', function(state)
 | 
						|
        slashWeaponEquipped = state
 | 
						|
 | 
						|
        if not state or threadIsActive then
 | 
						|
            return
 | 
						|
        end
 | 
						|
 | 
						|
        CreateThread(weaponEquippedThread)
 | 
						|
    end)
 | 
						|
end
 | 
						|
 | 
						|
RegisterCommand('slashtire', function()
 | 
						|
    slashTireCommand()
 | 
						|
end, false)
 | 
						|
 | 
						|
if Config.AddChatSuggestion then
 | 
						|
    TriggerEvent('chat:addSuggestion', '/slashtire', GetLocalization('chat_suggestion'))
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
-- Events --
 | 
						|
RegisterNetEvent('slashtires:burstTire', function(netId, tireIndex)
 | 
						|
    local vehicle = NetworkGetEntityFromNetworkId(netId)
 | 
						|
    burstVehicleTire(vehicle, tireIndex)
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNetEvent('slashtires:displayNotification', function(message)
 | 
						|
    DisplayNotification(message)
 | 
						|
end)
 | 
						|
 | 
						|
 | 
						|
-- Exports --
 | 
						|
local function getIsSlashing()
 | 
						|
    return isSlashing
 | 
						|
end
 | 
						|
 | 
						|
exports('isSlashing', getIsSlashing)
 | 
						|
exports('canCurrentWeaponSlashTires', canCurrentWeaponSlashTires)
 | 
						|
exports('burstVehicleTire', burstVehicleTire)
 | 
						|
exports('getVehicleTireByBone', getVehicleTireByBone)
 | 
						|
exports('getClosestVehicleTire', getClosestVehicleTire)
 | 
						|
exports('slashTire', slashTire)
 | 
						|
exports('canSlashVehicleTire', canSlashVehicleTire)
 | 
						|
exports('attemptToSlashTire', attemptToSlashTire)
 |