Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: break up client thread #65

Merged
merged 7 commits into from
Jun 21, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions client/functions.lua
Original file line number Diff line number Diff line change
@@ -18,9 +18,8 @@ exports('HasKeys', public.hasKeys)
---Checking weapon on the blacklist.
---@return boolean? `true` if the vehicle is blacklisted, `nil` otherwise.
function public.isBlacklistedWeapon()
local weapon = GetSelectedPedWeapon(cache.ped)
for i = 1, #config.noCarjackWeapons do
if weapon == joaat(config.noCarjackWeapons[i]) then
if cache.weapon == joaat(config.noCarjackWeapons[i]) then
return true
end
end
330 changes: 188 additions & 142 deletions client/main.lua
Original file line number Diff line number Diff line change
@@ -19,9 +19,7 @@ local areKeysJobShared = functions.areKeysJobShared
-----------------------

local isTakingKeys = false
local isCarjacking = false
local isHotwiring = false
local canCarjack = true
local isCarjackingAvailable = true

-----------------------
---- Functions ----
@@ -51,24 +49,21 @@ end
-- If in vehicle returns that, otherwise tries 3 different raycasts to get the vehicle they are facing.
-- Raycasts picture: https://i.imgur.com/FRED0kV.png
local function getVehicle()
local vehicle = cache.vehicle
local raycastOffsetTable = {
{ fromOffset = vec3(0.0, 0.0, 0.0), toOffset = vec3(0.0, 20.0, -10.0) }, -- Waist to ground 45 degree angle
{ fromOffset = vec3(0.0, 0.0, 0.7), toOffset = vec3(0.0, 10.0, -10.0) }, -- Head to ground 30 degree angle
{ fromOffset = vec3(0.0, 0.0, 0.7), toOffset = vec3(0.0, 10.0, -20.0) }, -- Head to ground 15 degree angle
}

local count = 0
while not vehicle and count < #raycastOffsetTable do
count += 1
vehicle = getVehicleInDirection(raycastOffsetTable[count]['fromOffset'], raycastOffsetTable[count]['toOffset'])
end
if not cache.vehicle then
for i = 1, #raycastOffsetTable do
local vehicle = getVehicleInDirection(raycastOffsetTable[i]['fromOffset'], raycastOffsetTable[i]['toOffset'])

if not IsEntityAVehicle(vehicle) then
vehicle = nil
if IsEntityAVehicle(vehicle) then
return vehicle
end
end
end

return vehicle
end

---manages the opening of locks
@@ -81,11 +76,10 @@ local function setVehicleDoorLock(vehicle, state, anim)
if hasKeys(qbx.getVehiclePlate(vehicle)) or areKeysJobShared(vehicle) then

if anim then
lib.requestAnimDict('anim@mp_player_intmenu@key_fob@')
TaskPlayAnim(cache.ped, 'anim@mp_player_intmenu@key_fob@', 'fob_click', 3.0, 3.0, -1, 49, 0, false, false, false)
lib.playAnim(cache.ped, 'anim@mp_player_intmenu@key_fob@', 'fob_click', 3.0, 3.0, -1, 49)
end

StartVehicleHorn(vehicle, 1, 'HELDDOWN', false)
StartVehicleHorn(vehicle, 50, `HELDDOWN`, false)
NetworkRequestControlOfEntity(vehicle)

local lockstate
@@ -144,7 +138,6 @@ end

local function findKeys(vehicle, plate)
local hotwireTime = math.random(config.minHotwireTime, config.maxHotwireTime)
isHotwiring = true

if lib.progressCircle({
duration = hotwireTime,
@@ -175,18 +168,45 @@ local function findKeys(vehicle, plate)
SetTimeout(10000, function()
attemptPoliceAlert('steal')
end)
end

isHotwiring = false
local isShowHotwiringLabelRunning = false
local function showHotwiringLabel()
if isShowHotwiringLabelRunning then return end
isShowHotwiringLabelRunning = true
CreateThread(function()
-- Hotwiring while in vehicle, also keeps engine off for vehicles you don't own keys to
while cache.vehicle do
local plate = qbx.getVehiclePlate(cache.vehicle)
if cache.seat == -1
and not hasKeys(plate)
and not isBlacklistedVehicle(cache.vehicle)
and not areKeysJobShared(cache.vehicle)
then
local vehiclePos = GetOffsetFromEntityInWorldCoords(cache.vehicle, 0.0, 1.0, 0.5)
qbx.drawText3d({ text = locale('info.search_keys'), coords = vehiclePos })
SetVehicleEngineOn(cache.vehicle, false, false, true)

if IsControlJustPressed(0, 74) then
findKeys(cache.vehicle, plate)
end
Wait(0)
else
Wait(1000)
end
end
end)
isShowHotwiringLabelRunning = false
end

local function carjackVehicle(target)
if not config.carjackEnable then return end
isCarjacking = true
canCarjack = false
if not isCarjackingAvailable then return end
isCarjackingAvailable = false
local isCarjacking = true
local vehicle = GetVehiclePedIsUsing(target)
local occupants = getPedsInVehicle(vehicle)

CreateThread(function ()
CreateThread(function()
while isCarjacking do
TaskVehicleTempAction(occupants[1], vehicle, 6, 1)
Wait(0)
@@ -223,10 +243,9 @@ local function carjackVehicle(target)
car = true,
},
}) then
local hasWeapon, weaponHash = GetCurrentPedWeapon(cache.ped, true)
if hasWeapon and isCarjacking then
if cache.weapon and isCarjacking then
local carjackChance = 0.5
local chance = config.carjackChance[GetWeapontypeGroup(weaponHash) --[[@as string]]]
local chance = config.carjackChance[GetWeapontypeGroup(cache.weapon) --[[@as string]]]
if chance then
carjackChance = chance
end
@@ -264,138 +283,144 @@ local function carjackVehicle(target)
end

Wait(config.delayBetweenCarjackingsInMs)
canCarjack = true
isCarjackingAvailable = true
end

-----------------------
---- Threads ----
-----------------------

CreateThread(function()
while true do
local sleep = 1000
if LocalPlayer.state.isLoggedIn then
sleep = 100
local entering = GetVehiclePedIsTryingToEnter(cache.ped)
local carIsImmune = false
if entering ~= 0 and not isBlacklistedVehicle(entering) then
sleep = 500
local plate = qbx.getVehiclePlate(entering)
local driver = GetPedInVehicleSeat(entering, -1)
for i = 1, #config.immuneVehicles do
if GetEntityModel(entering) == joaat(config.immuneVehicles[i]) then
carIsImmune = true
end
end

-- Driven vehicle logic
if driver ~= 0 and not IsPedAPlayer(driver) and not hasKeys(plate) and not carIsImmune then
if IsEntityDead(driver) then
if not isTakingKeys then
isTakingKeys = true

TriggerServerEvent('qb-vehiclekeys:server:setVehLockState', NetworkGetNetworkIdFromEntity(entering), 1)
if lib.progressCircle({
duration = 2500,
label = locale('progress.takekeys'),
position = 'bottom',
useWhileDead = false,
canCancel = true,
disable = {
car = true,
},
}) then
TriggerServerEvent('qb-vehiclekeys:server:AcquireVehicleKeys', plate)
end
isTakingKeys = false
end
elseif config.lockNPCDrivenCars then
TriggerServerEvent('qb-vehiclekeys:server:setVehLockState', NetworkGetNetworkIdFromEntity(entering), 2)
else
TriggerServerEvent('qb-vehiclekeys:server:setVehLockState', NetworkGetNetworkIdFromEntity(entering), 1)
TriggerServerEvent('qb-vehiclekeys:server:AcquireVehicleKeys', plate)

--Make passengers flee
local pedsInVehicle = getPedsInVehicle(entering)
for i = 1, #pedsInVehicle do
local pedInVehicle = pedsInVehicle[i]
if pedInVehicle ~= GetPedInVehicleSeat(entering, -1) then
makePedFlee(pedInVehicle)
end
end
end
-- Parked car logic
elseif driver == 0 and not Entity(entering).state.isOpen and not hasKeys(plate) and not isTakingKeys and not Entity(entering).state.vehicleid then
TriggerServerEvent('qb-vehiclekeys:server:setVehLockState', NetworkGetNetworkIdFromEntity(entering), config.lockNPCParkedCars and 2 or 1)
end
end

-- Hotwiring while in vehicle, also keeps engine off for vehicles you don't own keys to
if cache.vehicle and not isHotwiring then
sleep = 1000
local plate = qbx.getVehiclePlate(cache.vehicle)
if cache.seat == -1
and not hasKeys(plate)
and not isBlacklistedVehicle(cache.vehicle)
and not areKeysJobShared(cache.vehicle)
then
sleep = 0
local vehiclePos = GetOffsetFromEntityInWorldCoords(cache.vehicle, 0.0, 1.0, 0.5)
qbx.drawText3d({ text = locale('info.search_keys'), coords = vehiclePos })
SetVehicleEngineOn(cache.vehicle, false, false, true)

if IsControlJustPressed(0, 74) then
findKeys(cache.vehicle, plate)
end
end
end
local function toggleEngine()
local vehicle = cache.vehicle
if vehicle and hasKeys(qbx.getVehiclePlate(vehicle)) then
local engineOn = GetIsVehicleEngineRunning(vehicle)
SetVehicleEngineOn(vehicle, not engineOn, false, true)
end
end

if config.carjackEnable and canCarjack then
local isWatchCarjackingAttemptsRunning = false
local function watchCarjackingAttempts()
if isWatchCarjackingAttemptsRunning then return end
isWatchCarjackingAttemptsRunning = true
CreateThread(function()
while cache.weapon do
if isCarjackingAvailable then
local aiming, target = GetEntityPlayerIsFreeAimingAt(cache.playerId)
if aiming and target and target ~= 0 then
if DoesEntityExist(target) and IsPedInAnyVehicle(target, false) and not IsEntityDead(target) and not IsPedAPlayer(target) then
local targetveh = GetVehiclePedIsIn(target, false)
for i = 1, #config.immuneVehicles do
if GetEntityModel(targetveh) == joaat(config.immuneVehicles[i]) then
carIsImmune = true
end
if aiming
and target
and target ~= 0
and DoesEntityExist(target)
and IsPedInAnyVehicle(target, false)
and not IsEntityDead(target)
and not IsPedAPlayer(target)
then
local targetveh = GetVehiclePedIsIn(target, false)
local isVehicleImmune = false
for i = 1, #config.immuneVehicles do
if GetEntityModel(targetveh) == joaat(config.immuneVehicles[i]) then
isVehicleImmune = true
end
end

if GetPedInVehicleSeat(targetveh, -1) == target and not isBlacklistedWeapon() then
local pos = GetEntityCoords(cache.ped)
local targetpos = GetEntityCoords(target)
if #(pos - targetpos) < 5.0 and not carIsImmune then
carjackVehicle(target)
end
if not isVehicleImmune
and GetPedInVehicleSeat(targetveh, -1) == target
and not isBlacklistedWeapon()
then
local pos = GetEntityCoords(cache.ped)
local targetpos = GetEntityCoords(target)
if #(pos - targetpos) < 5.0 and not isVehicleImmune then
carjackVehicle(target)
end
end
end
end
Wait(100)
end

Wait(sleep)
end
end)
end)
isWatchCarjackingAttemptsRunning = false
end

-----------------------
---- Client Events ----
-----------------------
local togglelocksBind
togglelocksBind = lib.addKeybind({
name = 'togglelocks',
description = locale('info.toggle_locks'),
defaultKey = 'L',
onPressed = function()
togglelocksBind:disable(true)
setVehicleDoorLock(getVehicle(), nil, true)
Wait(1000)
togglelocksBind:disable(false)
end
})

local engineBind
engineBind = lib.addKeybind({
name = 'engine',
description = locale('info.engine'),
defaultKey = 'G',
onPressed = function()
engineBind:disable(true)
toggleEngine()
Wait(1000)
engineBind:disable(false)
end
})

RegisterNetEvent('QBCore:Client:VehicleInfo', function(data)
if not LocalPlayer.state.isLoggedIn and data.event ~= 'Entering' then return end
if isBlacklistedVehicle(data.vehicle) then return end
local isVehicleImmune
for i = 1, #config.immuneVehicles do
if GetEntityModel(data.vehicle) == joaat(config.immuneVehicles[i]) then
isVehicleImmune = true
end
end

RegisterKeyMapping('togglelocks', locale('info.toggle_locks'), 'keyboard', 'L')
RegisterCommand('togglelocks', function()
setVehicleDoorLock(getVehicle(), nil, true)
end, false)

RegisterKeyMapping('engine', locale('info.engine'), 'keyboard', 'G')
RegisterCommand('engine', function()
TriggerEvent('qb-vehiclekeys:client:ToggleEngine')
end, false)
local driver = GetPedInVehicleSeat(data.vehicle, -1)
local plate = qbx.getVehiclePlate(data.vehicle)

if driver ~= 0 and not (isVehicleImmune or IsPedAPlayer(driver) or hasKeys(plate)) then
if IsEntityDead(driver) then
if not isTakingKeys then
isTakingKeys = true

TriggerServerEvent('qb-vehiclekeys:server:setVehLockState', data.netId, 1)
if lib.progressCircle({
duration = 2500,
label = locale('progress.takekeys'),
position = 'bottom',
useWhileDead = false,
canCancel = true,
disable = {
car = true,
},
}) then
TriggerServerEvent('qb-vehiclekeys:server:AcquireVehicleKeys', plate)
end
isTakingKeys = false
end
elseif config.lockNPCDrivenCars then
TriggerServerEvent('qb-vehiclekeys:server:setVehLockState', data.netId, 2)
else
TriggerServerEvent('qb-vehiclekeys:server:setVehLockState', data.netId, 1)
TriggerServerEvent('qb-vehiclekeys:server:AcquireVehicleKeys', plate)

RegisterNetEvent('qb-vehiclekeys:client:ToggleEngine', function()
local vehicle = cache.vehicle
if vehicle and hasKeys(qbx.getVehiclePlate(vehicle)) then
local engineOn = GetIsVehicleEngineRunning(vehicle)
SetVehicleEngineOn(vehicle, not engineOn, false, true)
--Make passengers flee
local pedsInVehicle = getPedsInVehicle(data.vehicle)
for i = 1, #pedsInVehicle do
local pedInVehicle = pedsInVehicle[i]
if pedInVehicle ~= GetPedInVehicleSeat(data.vehicle, -1) then
makePedFlee(pedInVehicle)
end
end
end
-- Parked car logic
elseif driver == 0 and
not (isTakingKeys
or Entity(data.vehicle).state.isOpen
or Entity(data.vehicle).state.vehicleid
or hasKeys(plate))
then
TriggerServerEvent('qb-vehiclekeys:server:setVehLockState', data.netId, config.lockNPCParkedCars and 2 or 1)
end
end)

@@ -408,7 +433,7 @@ RegisterNetEvent('qb-vehiclekeys:client:GiveKeys', function(id, plate)
return exports.qbx_core:Notify(locale('notify.no_keys'), 'error')
end

if id and type(id) == 'number' then -- Give keys to specific ID
if id and type(id) == 'number' then -- Give keys to specific ID
giveKeys(id, targetPlate)
elseif IsPedSittingInVehicle(cache.ped, targetVehicle) then -- Give keys to everyone in vehicle
local otherOccupants = getOtherPlayersInVehicle(targetVehicle)
@@ -420,7 +445,7 @@ RegisterNetEvent('qb-vehiclekeys:client:GiveKeys', function(id, plate)
TriggerServerEvent('qb-vehiclekeys:server:GiveVehicleKeys', otherOccupants[p], targetPlate)
end
exports.qbx_core:Notify(locale('notify.gave_keys'))
else -- Give keys to closest player
else -- Give keys to closest player
local playerId = lib.getClosestPlayer(GetEntityCoords(cache.ped), 3, false)
giveKeys(playerId, targetPlate)
end
@@ -435,6 +460,27 @@ RegisterNetEvent('lockpicks:UseLockpick', function(isAdvanced)
end
end)

AddEventHandler('ox_lib:cache:vehicle', function()
showHotwiringLabel()
end)


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

AddEventHandler('onResourceStart', function (resourceName)
if (GetCurrentResourceName() ~= resourceName) then return end

showHotwiringLabel()

if config.carjackEnable then
watchCarjackingAttempts()
end
end)

--#region Backwards Compatibility ONLY -- Remove at some point --
RegisterNetEvent('qb-vehiclekeys:client:AddKeys', function(plate)
TriggerServerEvent('qb-vehiclekeys:server:AcquireVehicleKeys', plate)