51
51
-- If in vehicle returns that, otherwise tries 3 different raycasts to get the vehicle they are facing.
52
52
-- Raycasts picture: https://i.imgur.com/FRED0kV.png
53
53
local function getVehicle ()
54
- local vehicle = cache .vehicle
55
54
local raycastOffsetTable = {
56
55
{ fromOffset = vec3 (0.0 , 0.0 , 0.0 ), toOffset = vec3 (0.0 , 20.0 , - 10.0 ) }, -- Waist to ground 45 degree angle
57
56
{ fromOffset = vec3 (0.0 , 0.0 , 0.7 ), toOffset = vec3 (0.0 , 10.0 , - 10.0 ) }, -- Head to ground 30 degree angle
58
57
{ fromOffset = vec3 (0.0 , 0.0 , 0.7 ), toOffset = vec3 (0.0 , 10.0 , - 20.0 ) }, -- Head to ground 15 degree angle
59
58
}
60
59
61
- local count = 0
62
- while not vehicle and count < # raycastOffsetTable do
63
- count += 1
64
- vehicle = getVehicleInDirection (raycastOffsetTable [count ][' fromOffset' ], raycastOffsetTable [count ][' toOffset' ])
65
- end
60
+ if not cache .vehicle then
61
+ for i = 1 , # raycastOffsetTable do
62
+ local vehicle = getVehicleInDirection (raycastOffsetTable [i ][' fromOffset' ], raycastOffsetTable [i ][' toOffset' ])
66
63
67
- if not IsEntityAVehicle (vehicle ) then
68
- vehicle = nil
64
+ if IsEntityAVehicle (vehicle ) then
65
+ return vehicle
66
+ end
67
+ end
69
68
end
70
-
71
- return vehicle
72
69
end
73
70
74
71
--- manages the opening of locks
@@ -79,13 +76,11 @@ local function setVehicleDoorLock(vehicle, state, anim)
79
76
if not vehicle then return end
80
77
if not isBlacklistedVehicle (vehicle ) then
81
78
if hasKeys (qbx .getVehiclePlate (vehicle )) or areKeysJobShared (vehicle ) then
82
-
83
79
if anim then
84
- lib .requestAnimDict (' anim@mp_player_intmenu@key_fob@' )
85
- TaskPlayAnim (cache .ped , ' anim@mp_player_intmenu@key_fob@' , ' fob_click' , 3.0 , 3.0 , - 1 , 49 , 0 , false , false , false )
80
+ lib .playAnim (cache .ped , ' anim@mp_player_intmenu@key_fob@' , ' fob_click' , 3.0 , 3.0 , - 1 , 49 )
86
81
end
87
82
88
- StartVehicleHorn (vehicle , 1 , ' HELDDOWN' , false )
83
+ StartVehicleHorn (vehicle , 50 , ` HELDDOWN` , false )
89
84
NetworkRequestControlOfEntity (vehicle )
90
85
91
86
local lockstate
144
139
145
140
local function findKeys (vehicle , plate )
146
141
local hotwireTime = math.random (config .minHotwireTime , config .maxHotwireTime )
147
- isHotwiring = true
148
142
149
143
if lib .progressCircle ({
150
144
duration = hotwireTime ,
@@ -175,7 +169,33 @@ local function findKeys(vehicle, plate)
175
169
SetTimeout (10000 , function ()
176
170
attemptPoliceAlert (' steal' )
177
171
end )
172
+ end
178
173
174
+ local function showHotwiringLabel ()
175
+ if isHotwiring then return end
176
+ isHotwiring = true
177
+ CreateThread (function ()
178
+ -- Hotwiring while in vehicle, also keeps engine off for vehicles you don't own keys to
179
+ while LocalPlayer .state .isLoggedIn and cache .vehicle do
180
+ local plate = qbx .getVehiclePlate (cache .vehicle )
181
+ if cache .seat == - 1
182
+ and not hasKeys (plate )
183
+ and not isBlacklistedVehicle (cache .vehicle )
184
+ and not areKeysJobShared (cache .vehicle )
185
+ then
186
+ local vehiclePos = GetOffsetFromEntityInWorldCoords (cache .vehicle , 0.0 , 1.0 , 0.5 )
187
+ qbx .drawText3d ({ text = locale (' info.search_keys' ), coords = vehiclePos })
188
+ SetVehicleEngineOn (cache .vehicle , false , false , true )
189
+
190
+ if IsControlJustPressed (0 , 74 ) then
191
+ findKeys (cache .vehicle , plate )
192
+ end
193
+ Wait (0 )
194
+ else
195
+ Wait (1000 )
196
+ end
197
+ end
198
+ end )
179
199
isHotwiring = false
180
200
end
181
201
@@ -186,7 +206,7 @@ local function carjackVehicle(target)
186
206
local vehicle = GetVehiclePedIsUsing (target )
187
207
local occupants = getPedsInVehicle (vehicle )
188
208
189
- CreateThread (function ()
209
+ CreateThread (function ()
190
210
while isCarjacking do
191
211
TaskVehicleTempAction (occupants [1 ], vehicle , 6 , 1 )
192
212
Wait (0 )
@@ -267,101 +287,45 @@ local function carjackVehicle(target)
267
287
canCarjack = true
268
288
end
269
289
290
+
291
+ local function toggleEngine ()
292
+ local vehicle = cache .vehicle
293
+ if vehicle and hasKeys (qbx .getVehiclePlate (vehicle )) then
294
+ local engineOn = GetIsVehicleEngineRunning (vehicle )
295
+ SetVehicleEngineOn (vehicle , not engineOn , false , true )
296
+ end
297
+ end
298
+
270
299
---- -------------------
271
300
---- Threads ----
272
301
---- -------------------
273
302
274
- CreateThread (function ()
275
- while true do
276
- local sleep = 1000
277
- if LocalPlayer .state .isLoggedIn then
278
- sleep = 100
279
- local entering = GetVehiclePedIsTryingToEnter (cache .ped )
280
- local carIsImmune = false
281
- if entering ~= 0 and not isBlacklistedVehicle (entering ) then
282
- sleep = 500
283
- local plate = qbx .getVehiclePlate (entering )
284
- local driver = GetPedInVehicleSeat (entering , - 1 )
285
- for i = 1 , # config .immuneVehicles do
286
- if GetEntityModel (entering ) == joaat (config .immuneVehicles [i ]) then
287
- carIsImmune = true
288
- end
289
- end
290
-
291
- -- Driven vehicle logic
292
- if driver ~= 0 and not IsPedAPlayer (driver ) and not hasKeys (plate ) and not carIsImmune then
293
- if IsEntityDead (driver ) then
294
- if not isTakingKeys then
295
- isTakingKeys = true
296
-
297
- TriggerServerEvent (' qb-vehiclekeys:server:setVehLockState' , NetworkGetNetworkIdFromEntity (entering ), 1 )
298
- if lib .progressCircle ({
299
- duration = 2500 ,
300
- label = locale (' progress.takekeys' ),
301
- position = ' bottom' ,
302
- useWhileDead = false ,
303
- canCancel = true ,
304
- disable = {
305
- car = true ,
306
- },
307
- }) then
308
- TriggerServerEvent (' qb-vehiclekeys:server:AcquireVehicleKeys' , plate )
309
- end
310
- isTakingKeys = false
311
- end
312
- elseif config .lockNPCDrivenCars then
313
- TriggerServerEvent (' qb-vehiclekeys:server:setVehLockState' , NetworkGetNetworkIdFromEntity (entering ), 2 )
314
- else
315
- TriggerServerEvent (' qb-vehiclekeys:server:setVehLockState' , NetworkGetNetworkIdFromEntity (entering ), 1 )
316
- TriggerServerEvent (' qb-vehiclekeys:server:AcquireVehicleKeys' , plate )
317
-
318
- -- Make passengers flee
319
- local pedsInVehicle = getPedsInVehicle (entering )
320
- for i = 1 , # pedsInVehicle do
321
- local pedInVehicle = pedsInVehicle [i ]
322
- if pedInVehicle ~= GetPedInVehicleSeat (entering , - 1 ) then
323
- makePedFlee (pedInVehicle )
324
- end
325
- end
326
- end
327
- -- Parked car logic
328
- elseif driver == 0 and not Entity (entering ).state .isOpen and not hasKeys (plate ) and not isTakingKeys and not Entity (entering ).state .vehicleid then
329
- TriggerServerEvent (' qb-vehiclekeys:server:setVehLockState' , NetworkGetNetworkIdFromEntity (entering ), config .lockNPCParkedCars and 2 or 1 )
330
- end
331
- end
332
-
333
- -- Hotwiring while in vehicle, also keeps engine off for vehicles you don't own keys to
334
- if cache .vehicle and not isHotwiring then
335
- sleep = 1000
336
- local plate = qbx .getVehiclePlate (cache .vehicle )
337
- if cache .seat == - 1
338
- and not hasKeys (plate )
339
- and not isBlacklistedVehicle (cache .vehicle )
340
- and not areKeysJobShared (cache .vehicle )
341
- then
342
- sleep = 0
343
- local vehiclePos = GetOffsetFromEntityInWorldCoords (cache .vehicle , 0.0 , 1.0 , 0.5 )
344
- qbx .drawText3d ({ text = locale (' info.search_keys' ), coords = vehiclePos })
345
- SetVehicleEngineOn (cache .vehicle , false , false , true )
346
-
347
- if IsControlJustPressed (0 , 74 ) then
348
- findKeys (cache .vehicle , plate )
349
- end
350
- end
351
- end
352
-
353
- if config .carjackEnable and canCarjack then
354
- local aiming , target = GetEntityPlayerIsFreeAimingAt (cache .playerId )
355
- if aiming and target and target ~= 0 then
356
- if DoesEntityExist (target ) and IsPedInAnyVehicle (target , false ) and not IsEntityDead (target ) and not IsPedAPlayer (target ) then
303
+ if config .carjackEnable then
304
+ CreateThread (function ()
305
+ while true do
306
+ if LocalPlayer .state .isLoggedIn then
307
+ if canCarjack then
308
+ local aiming , target = GetEntityPlayerIsFreeAimingAt (cache .playerId )
309
+ if aiming
310
+ and target
311
+ and target ~= 0
312
+ and DoesEntityExist (target )
313
+ and IsPedInAnyVehicle (target , false )
314
+ and not IsEntityDead (target )
315
+ and not IsPedAPlayer (target )
316
+ then
357
317
local targetveh = GetVehiclePedIsIn (target , false )
318
+ local carIsImmune = false
358
319
for i = 1 , # config .immuneVehicles do
359
320
if GetEntityModel (targetveh ) == joaat (config .immuneVehicles [i ]) then
360
321
carIsImmune = true
361
322
end
362
323
end
363
324
364
- if GetPedInVehicleSeat (targetveh , - 1 ) == target and not isBlacklistedWeapon () then
325
+ if not carIsImmune
326
+ and GetPedInVehicleSeat (targetveh , - 1 ) == target
327
+ and not isBlacklistedWeapon ()
328
+ then
365
329
local pos = GetEntityCoords (cache .ped )
366
330
local targetpos = GetEntityCoords (target )
367
331
if # (pos - targetpos ) < 5.0 and not carIsImmune then
@@ -370,32 +334,99 @@ CreateThread(function()
370
334
end
371
335
end
372
336
end
337
+ Wait (100 )
338
+ else
339
+ Wait (1000 )
373
340
end
374
341
end
375
-
376
- Wait (sleep )
377
- end
378
- end )
342
+ end )
343
+ end
379
344
380
345
---- -------------------
381
346
---- Client Events ----
382
347
---- -------------------
348
+ local togglelocksBind
349
+ togglelocksBind = lib .addKeybind ({
350
+ name = ' togglelocks' ,
351
+ description = locale (' info.toggle_locks' ),
352
+ defaultKey = ' L' ,
353
+ onPressed = function ()
354
+ togglelocksBind :disable (true )
355
+ setVehicleDoorLock (getVehicle (), nil , true )
356
+ Wait (1000 )
357
+ togglelocksBind :disable (false )
358
+ end
359
+ })
360
+
361
+ local engineBind
362
+ engineBind = lib .addKeybind ({
363
+ name = ' engine' ,
364
+ description = locale (' info.engine' ),
365
+ defaultKey = ' G' ,
366
+ onPressed = function ()
367
+ engineBind :disable (true )
368
+ toggleEngine ()
369
+ Wait (1000 )
370
+ engineBind :disable (false )
371
+ end
372
+ })
383
373
384
- RegisterKeyMapping (' togglelocks' , locale (' info.toggle_locks' ), ' keyboard' , ' L' )
385
- RegisterCommand (' togglelocks' , function ()
386
- setVehicleDoorLock (getVehicle (), nil , true )
387
- end , false )
374
+ AddEventHandler (' ox_lib:cache:vehicle' , function ()
375
+ showHotwiringLabel ()
376
+ end )
377
+ showHotwiringLabel ()
378
+
379
+ RegisterNetEvent (' QBCore:Client:VehicleInfo' , function (data )
380
+ if not LocalPlayer .state .isLoggedIn and data .event ~= ' Entering' then return end
381
+ if isBlacklistedVehicle (data .vehicle ) then return end
382
+ local isVehicleImmune
383
+ for i = 1 , # config .immuneVehicles do
384
+ if GetEntityModel (data .vehicle ) == joaat (config .immuneVehicles [i ]) then
385
+ isVehicleImmune = true
386
+ end
387
+ end
388
388
389
- RegisterKeyMapping (' engine' , locale (' info.engine' ), ' keyboard' , ' G' )
390
- RegisterCommand (' engine' , function ()
391
- TriggerEvent (' qb-vehiclekeys:client:ToggleEngine' )
392
- end , false )
389
+ local driver = GetPedInVehicleSeat (data .vehicle , - 1 )
390
+ local plate = qbx .getVehiclePlate (data .vehicle )
391
+
392
+ if driver ~= 0 and not (isVehicleImmune or IsPedAPlayer (driver ) or hasKeys (plate )) then
393
+ if IsEntityDead (driver ) then
394
+ if not isTakingKeys then
395
+ isTakingKeys = true
396
+
397
+ TriggerServerEvent (' qb-vehiclekeys:server:setVehLockState' , data .netId , 1 )
398
+ if lib .progressCircle ({
399
+ duration = 2500 ,
400
+ label = locale (' progress.takekeys' ),
401
+ position = ' bottom' ,
402
+ useWhileDead = false ,
403
+ canCancel = true ,
404
+ disable = {
405
+ car = true ,
406
+ },
407
+ }) then
408
+ TriggerServerEvent (' qb-vehiclekeys:server:AcquireVehicleKeys' , plate )
409
+ end
410
+ isTakingKeys = false
411
+ end
412
+ elseif config .lockNPCDrivenCars then
413
+ TriggerServerEvent (' qb-vehiclekeys:server:setVehLockState' , data .netId , 2 )
414
+ else
415
+ TriggerServerEvent (' qb-vehiclekeys:server:setVehLockState' , data .netId , 1 )
416
+ TriggerServerEvent (' qb-vehiclekeys:server:AcquireVehicleKeys' , plate )
393
417
394
- RegisterNetEvent (' qb-vehiclekeys:client:ToggleEngine' , function ()
395
- local vehicle = cache .vehicle
396
- if vehicle and hasKeys (qbx .getVehiclePlate (vehicle )) then
397
- local engineOn = GetIsVehicleEngineRunning (vehicle )
398
- SetVehicleEngineOn (vehicle , not engineOn , false , true )
418
+ -- Make passengers flee
419
+ local pedsInVehicle = getPedsInVehicle (data .vehicle )
420
+ for i = 1 , # pedsInVehicle do
421
+ local pedInVehicle = pedsInVehicle [i ]
422
+ if pedInVehicle ~= GetPedInVehicleSeat (data .vehicle , - 1 ) then
423
+ makePedFlee (pedInVehicle )
424
+ end
425
+ end
426
+ end
427
+ -- Parked car logic
428
+ elseif driver == 0 and not Entity (data .vehicle ).state .isOpen and not hasKeys (plate ) and not isTakingKeys and not Entity (data .vehicle ).state .vehicleid then
429
+ TriggerServerEvent (' qb-vehiclekeys:server:setVehLockState' , data .netId , config .lockNPCParkedCars and 2 or 1 )
399
430
end
400
431
end )
401
432
@@ -408,7 +439,7 @@ RegisterNetEvent('qb-vehiclekeys:client:GiveKeys', function(id, plate)
408
439
return exports .qbx_core :Notify (locale (' notify.no_keys' ), ' error' )
409
440
end
410
441
411
- if id and type (id ) == ' number' then -- Give keys to specific ID
442
+ if id and type (id ) == ' number' then -- Give keys to specific ID
412
443
giveKeys (id , targetPlate )
413
444
elseif IsPedSittingInVehicle (cache .ped , targetVehicle ) then -- Give keys to everyone in vehicle
414
445
local otherOccupants = getOtherPlayersInVehicle (targetVehicle )
@@ -420,7 +451,7 @@ RegisterNetEvent('qb-vehiclekeys:client:GiveKeys', function(id, plate)
420
451
TriggerServerEvent (' qb-vehiclekeys:server:GiveVehicleKeys' , otherOccupants [p ], targetPlate )
421
452
end
422
453
exports .qbx_core :Notify (locale (' notify.gave_keys' ))
423
- else -- Give keys to closest player
454
+ else -- Give keys to closest player
424
455
local playerId = lib .getClosestPlayer (GetEntityCoords (cache .ped ), 3 , false )
425
456
giveKeys (playerId , targetPlate )
426
457
end
0 commit comments