151 lines
5.2 KiB
Lua
151 lines
5.2 KiB
Lua
local config = require 'config.client'
|
|
|
|
local function getNPCPedsInVehicle(vehicle)
|
|
local otherPeds = {}
|
|
for seat = -1, GetVehicleModelNumberOfSeats(GetEntityModel(vehicle)) - 2 do
|
|
local pedInSeat = GetPedInVehicleSeat(vehicle, seat)
|
|
if pedInSeat ~= 0 and not IsPedAPlayer(pedInSeat) then
|
|
otherPeds[#otherPeds + 1] = pedInSeat
|
|
end
|
|
end
|
|
return otherPeds
|
|
end
|
|
|
|
local function makePedFlee(ped)
|
|
ClearPedTasks(ped)
|
|
SetPedFleeAttributes(ped, 0, false)
|
|
TaskReactAndFleePed(ped, cache.ped)
|
|
TaskSmartFleePed(ped, cache.ped, 100.0, -1, false, false)
|
|
ResetPedLastVehicle(ped) -- make ped forget about his last car, so he cant return to it
|
|
end
|
|
|
|
local function makePedsPutHandsUpAndScream(occupants, vehicle)
|
|
for p = 1, #occupants do
|
|
local occupant = occupants[p]
|
|
CreateThread(function()
|
|
Wait(math.random(100, 600)) --Random reaction time to increase realism
|
|
local anim = config.anims.holdup.model[GetEntityModel(vehicle)]
|
|
or config.anims.holdup.class[GetVehicleClass(vehicle)]
|
|
or config.anims.holdup.default
|
|
lib.playAnim(occupant, anim.dict, anim.clip, 8.0, -8.0, -1, 49, 0, false, false, false)
|
|
PlayPain(occupant, 6, 0)
|
|
end)
|
|
end
|
|
end
|
|
|
|
local function onCarjackSuccess(occupants, vehicle)
|
|
for p = 1, #occupants do
|
|
local ped = occupants[p]
|
|
CreateThread(function()
|
|
TaskLeaveVehicle(ped, vehicle, 256) -- flag 256 to leave door open
|
|
PlayPain(ped, 6, 0)
|
|
Wait(1250)
|
|
PlayPain(ped, math.random(7, 8), 0)
|
|
makePedFlee(ped)
|
|
end)
|
|
end
|
|
end
|
|
|
|
local function onCarjackFail(driver)
|
|
exports.qbx_core:Notify(locale('notify.carjack_failed'), 'error')
|
|
makePedFlee(driver)
|
|
end
|
|
|
|
local function carjackVehicle(driver, vehicle)
|
|
local isCarjacking = true
|
|
local occupants = getNPCPedsInVehicle(vehicle)
|
|
|
|
CreateThread(function()
|
|
while isCarjacking do
|
|
TaskVehicleTempAction(occupants[1], vehicle, 6, 1)
|
|
Wait(0)
|
|
end
|
|
end)
|
|
|
|
makePedsPutHandsUpAndScream(occupants, vehicle)
|
|
|
|
--Cancel progress bar if: Ped dies during robbery, car gets too far away
|
|
CreateThread(function()
|
|
while isCarjacking do
|
|
local distance = #(GetEntityCoords(cache.ped) - GetEntityCoords(driver))
|
|
if (IsPedDeadOrDying(driver, false) or distance > 7.5) and lib.progressActive() then
|
|
lib.cancelProgress()
|
|
end
|
|
Wait(100)
|
|
end
|
|
end)
|
|
|
|
if lib.progressCircle({
|
|
duration = config.carjackingTimeInMs,
|
|
label = locale('progress.attempting_carjack'),
|
|
position = 'bottom',
|
|
useWhileDead = false,
|
|
canCancel = true,
|
|
disable = {
|
|
car = true,
|
|
},
|
|
}) then
|
|
if cache.weapon and isCarjacking then
|
|
isCarjacking = false -- make this false to stop TaskVehicleTempAction from preventing ped to leave the car
|
|
local success = lib.callback.await('qbx_vehiclekeys:server:carjack', false, VehToNet(vehicle), GetWeapontypeGroup(cache.weapon))
|
|
if success then
|
|
onCarjackSuccess(occupants, vehicle)
|
|
else
|
|
onCarjackFail(driver)
|
|
end
|
|
TriggerServerEvent('hud:server:GainStress', math.random(1, 4))
|
|
Wait(2000)
|
|
SendPoliceAlertAttempt('carjack', vehicle)
|
|
end
|
|
else
|
|
makePedFlee(driver)
|
|
end
|
|
|
|
Wait(config.delayBetweenCarjackingsInMs)
|
|
isCarjacking = false
|
|
end
|
|
|
|
---Checks if the weapon cannot be used to steal keys from drivers.
|
|
---@param weaponHash number The current weapon hash.
|
|
---@return boolean `true` if the weapon cannot be used to carjacking, `false` otherwise.
|
|
local function getIsBlacklistedWeapon(weaponHash)
|
|
return qbx.array.contains(config.noCarjackWeapons, weaponHash)
|
|
end
|
|
|
|
local isWatchCarjackingAttemptRunning = false
|
|
local function watchCarjackingAttempts()
|
|
if isWatchCarjackingAttemptRunning then return end
|
|
isWatchCarjackingAttemptRunning = true
|
|
CreateThread(function()
|
|
while cache.weapon and not getIsBlacklistedWeapon(cache.weapon) do
|
|
local aiming, target = GetEntityPlayerIsFreeAimingAt(cache.playerId)
|
|
if aiming
|
|
and DoesEntityExist(target)
|
|
and IsPedInAnyVehicle(target, false)
|
|
and not IsEntityDead(target)
|
|
and not IsPedAPlayer(target)
|
|
then
|
|
local script = GetEntityScript(target)
|
|
if not script then
|
|
local targetveh = GetVehiclePedIsIn(target, false)
|
|
|
|
if GetPedInVehicleSeat(targetveh, -1) == target
|
|
and not GetVehicleConfig(targetveh).carjackingImmune
|
|
and #(GetEntityCoords(cache.ped) - GetEntityCoords(target)) < 5.0
|
|
then
|
|
carjackVehicle(target, targetveh)
|
|
end
|
|
end
|
|
end
|
|
Wait(100)
|
|
end
|
|
isWatchCarjackingAttemptRunning = false
|
|
end)
|
|
end
|
|
|
|
if config.carjackEnable then
|
|
AddEventHandler('ox_lib:cache:weapon', function()
|
|
watchCarjackingAttempts()
|
|
end)
|
|
watchCarjackingAttempts()
|
|
end |