Skip to content

Commit

Permalink
refactor(client): extract carjack code into its own file
Browse files Browse the repository at this point in the history
  • Loading branch information
Manason committed Sep 23, 2024
1 parent f83a711 commit c15d4f0
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 152 deletions.
154 changes: 154 additions & 0 deletions client/carjack.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
local config = require 'config.client'
local functions = require 'client.functions'
local sharedFunctions = require 'shared.functions'

local sendPoliceAlertAttempt = functions.sendPoliceAlertAttempt

local getIsCloseToCoords = sharedFunctions.getIsCloseToCoords
local getIsBlacklistedWeapon = sharedFunctions.getIsBlacklistedWeapon
local getIsVehicleCarjackingImmune = sharedFunctions.getIsVehicleCarjackingImmune

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.model[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)
local plate = qbx.getVehiclePlate(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
TriggerServerEvent('hud:server:GainStress', math.random(1, 4))
TriggerServerEvent('qb-vehiclekeys:server:setVehLockState', NetworkGetNetworkIdFromEntity(vehicle), 1)
TriggerServerEvent('qb-vehiclekeys:server:AcquireVehicleKeys', plate)
end

local function onCarjackFail(driver)
exports.qbx_core:Notify(locale('notify.carjack_failed'), 'error')
makePedFlee(driver)
TriggerServerEvent('hud:server:GainStress', math.random(1, 4))
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
local carjackChance = config.carjackChance[GetWeapontypeGroup(cache.weapon) --[[@as string]]] or 0.5
isCarjacking = false -- make this false to stop TaskVehicleTempAction from preventing ped to leave the car

if math.random() <= carjackChance then
onCarjackSuccess(occupants, vehicle)
else
onCarjackFail(driver)
end
Wait(2000)
sendPoliceAlertAttempt('carjack')
end
else
makePedFlee(driver)
end

Wait(config.delayBetweenCarjackingsInMs)
isCarjacking = false
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 targetveh = GetVehiclePedIsIn(target, false)

if GetPedInVehicleSeat(targetveh, -1) == target
and not getIsVehicleCarjackingImmune(targetveh)
and getIsCloseToCoords(GetEntityCoords(cache.ped), GetEntityCoords(target), 5.0)
then
carjackVehicle(target, targetveh)
end
end
Wait(100)
end
isWatchCarjackingAttemptRunning = false
end)
end

if config.carjackEnable then
AddEventHandler('ox_lib:cache:weapon', function()
watchCarjackingAttempts()
end)
watchCarjackingAttempts()
end
11 changes: 0 additions & 11 deletions client/functions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,6 @@ end

exports('ToggleEngine', public.toggleEngine)

function public.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 getVehicleInDirection(coordFromOffset, coordToOffset)
local coordFrom = GetOffsetFromEntityInWorldCoords(cache.ped, coordFromOffset.x, coordFromOffset.y, coordFromOffset.z)
local coordTo = GetOffsetFromEntityInWorldCoords(cache.ped, coordToOffset.x, coordToOffset.y, coordToOffset.z)
Expand Down
140 changes: 0 additions & 140 deletions client/main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,10 @@ local toggleEngine = functions.toggleEngine
local lockpickDoor = functions.lockpickDoor
local areKeysJobShared = functions.areKeysJobShared
local getVehicleInFront = functions.getVehicleInFront
local getNPCPedsInVehicle = functions.getNPCPedsInVehicle
local sendPoliceAlertAttempt = functions.sendPoliceAlertAttempt
local getIsVehicleAccessible = functions.getIsVehicleAccessible

local getIsVehicleShared = sharedFunctions.getIsVehicleShared
local getIsCloseToCoords = sharedFunctions.getIsCloseToCoords
local getIsBlacklistedWeapon = sharedFunctions.getIsBlacklistedWeapon
local getIsVehicleAlwaysUnlocked = sharedFunctions.getIsVehicleAlwaysUnlocked
local getIsVehicleCarjackingImmune = sharedFunctions.getIsVehicleCarjackingImmune

Expand Down Expand Up @@ -149,133 +146,6 @@ local function showHotwiringLabel(vehicle)
end)
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.model[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)
local plate = qbx.getVehiclePlate(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
TriggerServerEvent('hud:server:GainStress', math.random(1, 4))
TriggerServerEvent('qb-vehiclekeys:server:setVehLockState', NetworkGetNetworkIdFromEntity(vehicle), 1)
TriggerServerEvent('qb-vehiclekeys:server:AcquireVehicleKeys', plate)
end

local function onCarjackFail(driver)
exports.qbx_core:Notify(locale('notify.carjack_failed'), 'error')
makePedFlee(driver)
TriggerServerEvent('hud:server:GainStress', math.random(1, 4))
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
local carjackChance = config.carjackChance[GetWeapontypeGroup(cache.weapon) --[[@as string]]] or 0.5
isCarjacking = false -- make this false to stop TaskVehicleTempAction from preventing ped to leave the car

if math.random() <= carjackChance then
onCarjackSuccess(occupants, vehicle)
else
onCarjackFail(driver)
end
Wait(2000)
sendPoliceAlertAttempt('carjack')
end
else
makePedFlee(driver)
end

Wait(config.delayBetweenCarjackingsInMs)
isCarjacking = false
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 targetveh = GetVehiclePedIsIn(target, false)

if GetPedInVehicleSeat(targetveh, -1) == target
and not getIsVehicleCarjackingImmune(targetveh)
and getIsCloseToCoords(GetEntityCoords(cache.ped), GetEntityCoords(target), 5.0)
then
carjackVehicle(target, targetveh)
end
end
Wait(100)
end
isWatchCarjackingAttemptRunning = false
end)
end

-----------------------
------ Key Binds ------
-----------------------
Expand Down Expand Up @@ -410,12 +280,6 @@ for _, info in pairs(config.sharedKeys) do
end
end

if config.carjackEnable then
AddEventHandler('ox_lib:cache:weapon', function()
watchCarjackingAttempts()
end)
end

qbx.entityStateHandler('doorslockstate', function(entity, _, value)
if entity == 0 then return end
SetVehicleDoorsLocked(entity, value)
Expand All @@ -425,10 +289,6 @@ AddEventHandler('onResourceStart', function(resourceName)
if (GetCurrentResourceName() ~= resourceName) then return end

showHotwiringLabel(cache.vehicle)

if config.carjackEnable then
watchCarjackingAttempts()
end
end)

RegisterNetEvent('qb-vehiclekeys:client:GiveKeys', function(id, plate)
Expand Down
3 changes: 2 additions & 1 deletion fxmanifest.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ shared_scripts {

client_scripts {
'@qbx_core/modules/playerdata.lua',
'client/main.lua'
'client/main.lua',
'client/carjack.lua',
}

server_scripts {
Expand Down

0 comments on commit c15d4f0

Please sign in to comment.