From c21506b4796fb66094f4926551f81bfcd9469777 Mon Sep 17 00:00:00 2001 From: Manason Date: Sat, 26 Oct 2024 12:20:21 -0700 Subject: [PATCH] refactor!: cleanup --- client/carjack.lua | 16 +- client/functions.lua | 9 +- client/main.lua | 68 ++++----- client/searchkeys.lua | 4 +- config/client.lua | 313 +++++++++++--------------------------- config/shared.lua | 33 ---- fxmanifest.lua | 2 +- server/keys.lua | 2 +- server/main.lua | 9 +- shared/functions.lua | 127 ---------------- shared/vehicle-config.lua | 56 +++++++ types.lua | 2 + 12 files changed, 198 insertions(+), 443 deletions(-) delete mode 100644 shared/functions.lua create mode 100644 shared/vehicle-config.lua diff --git a/client/carjack.lua b/client/carjack.lua index 5ceaf35..9d6c576 100644 --- a/client/carjack.lua +++ b/client/carjack.lua @@ -1,9 +1,4 @@ local config = require 'config.client' -local sharedFunctions = require 'shared.functions' - -local getIsCloseToCoords = sharedFunctions.getIsCloseToCoords -local getIsBlacklistedWeapon = sharedFunctions.getIsBlacklistedWeapon -local getIsVehicleCarjackingImmune = sharedFunctions.getIsVehicleCarjackingImmune local function getNPCPedsInVehicle(vehicle) local otherPeds = {} @@ -110,6 +105,13 @@ local function carjackVehicle(driver, vehicle) 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 @@ -126,8 +128,8 @@ local function watchCarjackingAttempts() local targetveh = GetVehiclePedIsIn(target, false) if GetPedInVehicleSeat(targetveh, -1) == target - and not getIsVehicleCarjackingImmune(targetveh) - and getIsCloseToCoords(GetEntityCoords(cache.ped), GetEntityCoords(target), 5.0) + and not GetVehicleConfig(targetveh).carjackingImmune + and #(GetEntityCoords(cache.ped) - GetEntityCoords(target)) < 5.0 then carjackVehicle(target, targetveh) end diff --git a/client/functions.lua b/client/functions.lua index afab81d..2b80256 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -1,5 +1,4 @@ local config = require 'config.client' -local functions = require 'shared.functions' ---Grants keys for job shared vehicles ---@param vehicle number The entity number of the vehicle. @@ -8,7 +7,7 @@ function AreKeysJobShared(vehicle) local job = QBX.PlayerData.job.name local jobInfo = config.sharedKeys[job] - if not jobInfo or (jobInfo.requireOnduty and not QBX.PlayerData.job.onduty) then return end + if not jobInfo or (jobInfo.requireOnDuty and not QBX.PlayerData.job.onduty) then return end assert(jobInfo.vehicles, string.format('Vehicles not configured for the %s job.', job)) return jobInfo.vehicles and jobInfo.vehicles[GetEntityModel(vehicle)] or jobInfo.classes and jobInfo.classes[GetVehicleClass(vehicle)] @@ -86,7 +85,7 @@ end local function getIsCloseToAnyBone(coords, entity, bones, maxDistance) for i = 1, #bones do local boneCoords = getBoneCoords(entity, bones[i]) - if functions.getIsCloseToCoords(coords, boneCoords, maxDistance) then + if #(coords - boneCoords) < maxDistance then return true end end @@ -116,7 +115,7 @@ end ---@param vehicle number local function breakLockpick(isAdvancedLockedpick, vehicle) local chance = math.random() - local vehicleConfig = functions.getVehicleConfig(vehicle) + local vehicleConfig = GetVehicleConfig(vehicle) if isAdvancedLockedpick then -- there is no benefit to using an advanced tool in the default configuration. if chance <= vehicleConfig.removeAdvancedLockpickChance then TriggerServerEvent("qb-vehiclekeys:server:breakLockpick", "advancedlockpick") @@ -173,7 +172,7 @@ function LockpickDoor(isAdvancedLockedpick, maxDistance, customChallenge) --- player may attempt to open the lock if: if not isDriverSeatFree -- no one in the driver's seat or not getIsCloseToAnyBone(pedCoords, vehicle, doorBones, maxDistance) -- the player's ped is close enough to the driver's door - or functions.getIsVehicleLockpickImmune(vehicle) + or GetVehicleConfig(vehicle).lockpickImmune then return end local skillCheckConfig = config.skillCheck[isAdvancedLockedpick and 'advancedLockpick' or 'lockpick'] diff --git a/client/main.lua b/client/main.lua index d057ab8..4f3a39a 100644 --- a/client/main.lua +++ b/client/main.lua @@ -1,30 +1,14 @@ ------------------------ ----- Imports ---- ------------------------ - local config = require 'config.client' -local sharedFunctions = require 'shared.functions' - -local getIsVehicleInitiallyLocked = sharedFunctions.getIsVehicleInitiallyLocked -local getIsVehicleShared = sharedFunctions.getIsVehicleShared -local getIsVehicleAlwaysUnlocked = sharedFunctions.getIsVehicleAlwaysUnlocked -local getIsVehicleCarjackingImmune = sharedFunctions.getIsVehicleCarjackingImmune - ------------------------ ----- Functions ---- ------------------------ ----manages the opening of locks ----@param vehicle number? The entity number of the vehicle. ----@param state boolean? State of the vehicle lock. ----@param anim any Animation -local function setVehicleDoorLock(vehicle, state, anim) - if not vehicle or getIsVehicleAlwaysUnlocked(vehicle) or getIsVehicleShared(vehicle) then return end +---client uses key fob to toggle the door locks +---@param vehicle number The entity number of the vehicle. +local function toggleLock(vehicle) + if not vehicle then return end + local vehicleConfig = GetVehicleConfig(vehicle) + if vehicleConfig.noLock or vehicleConfig.shared then return end if GetIsVehicleAccessible(vehicle) then - if anim then - lib.playAnim(cache.ped, 'anim@mp_player_intmenu@key_fob@', 'fob_click', 3.0, 3.0, -1, 49) - end + lib.playAnim(cache.ped, 'anim@mp_player_intmenu@key_fob@', 'fob_click', 3.0, 3.0, -1, 49) --- if the statebag is out of sync, rely on it as the source of truth and sync the client to the statebag's value local stateBagValue = Entity(vehicle).state.doorslockstate @@ -32,9 +16,7 @@ local function setVehicleDoorLock(vehicle, state, anim) SetVehicleDoorsLocked(vehicle, stateBagValue) end - local lockstate = state ~= nil - and (state and 2 or 1) - or (GetVehicleDoorLockStatus(vehicle) % 2) + 1 -- use ternary + local lockstate = (GetVehicleDoorLockStatus(vehicle) % 2) + 1 TriggerServerEvent('qb-vehiclekeys:server:setVehLockState', NetworkGetNetworkIdFromEntity(vehicle), lockstate) exports.qbx_core:Notify(locale(lockstate == 2 and 'notify.vehicle_locked' or 'notify.vehicle_unlocked')) @@ -52,8 +34,6 @@ local function setVehicleDoorLock(vehicle, state, anim) end end -exports('SetVehicleDoorLock', setVehicleDoorLock) - ---if the player does not have ignition access to the vehicle: ---check whether to give keys if engine is on ---disable the engine and listen for search keys if applicable to the vehicle @@ -68,7 +48,8 @@ local function onEnteringDriverSeat() Wait(0) end end) - if getIsVehicleShared(vehicle) then return end + local vehicleConfig = GetVehicleConfig(vehicle) + if vehicleConfig.shared then return end local isVehicleAccessible = GetIsVehicleAccessible(vehicle) if isVehicleAccessible then return end @@ -95,7 +76,7 @@ local function onEnteringDriverSeat() DisableKeySearch() end) - if sharedFunctions.getVehicleConfig(vehicle).findKeysChance ~= 0.0 then + if vehicleConfig.findKeysChance ~= 0.0 then EnableKeySearch() end end @@ -118,7 +99,7 @@ togglelocksBind = lib.addKeybind({ onPressed = function() togglelocksBind:disable(true) local vehicle = lib.getClosestVehicle(GetEntityCoords(cache.ped), config.vehicleMaximumLockingDistance, true) - setVehicleDoorLock(vehicle, nil, true) + toggleLock(vehicle) Wait(1000) togglelocksBind:disable(false) end @@ -176,12 +157,12 @@ EngineBind = lib.addKeybind({ local isTakingKeys = false RegisterNetEvent('QBCore:Client:VehicleInfo', function(data) if not LocalPlayer.state.isLoggedIn or data.event ~= 'Entering' then return end - if getIsVehicleAlwaysUnlocked(data.vehicle) or isTakingKeys then return end + local vehicleConfig = GetVehicleConfig(data.vehicle) + if vehicleConfig.noLock or isTakingKeys then return end isTakingKeys = true - local isVehicleImmune = getIsVehicleCarjackingImmune(data.vehicle) local driver = GetPedInVehicleSeat(data.vehicle, -1) - if driver ~= 0 and IsEntityDead(driver) and not (isVehicleImmune or IsPedAPlayer(driver)) then + if driver ~= 0 and IsEntityDead(driver) and not (vehicleConfig.carjackingImmune or IsPedAPlayer(driver)) then TriggerServerEvent('qb-vehiclekeys:server:setVehLockState', data.netId, 1) if lib.progressCircle({ duration = 2500, @@ -249,13 +230,30 @@ AddEventHandler('onResourceStart', function(resourceName) end end) +---Checks the vehicle is always locked at spawn. +---@param vehicle number The entity number of the vehicle. +---@param isDriven boolean +---@return boolean `true` if the vehicle is locked, `false` otherwise. +local function getIsVehicleInitiallyLocked(vehicle, isDriven) + local vehicleConfig = GetVehicleConfig(vehicle) + local vehicleLockedChance = isDriven + and vehicleConfig.spawnLockedIfDriven + or vehicleConfig.spawnLockedIfParked + + if type(vehicleLockedChance) == 'number' then + return math.random() < vehicleLockedChance + else + return vehicleLockedChance == true + end +end + local function onVehicleAttemptToEnter(vehicle) if Entity(vehicle).state.doorslockstate then return end local ped = GetPedInVehicleSeat(vehicle, -1) if IsPedAPlayer(ped) then return end - local isLocked = not getIsVehicleAlwaysUnlocked(vehicle) and getIsVehicleInitiallyLocked(vehicle, ped and ped ~= 0) + local isLocked = not GetVehicleConfig(vehicle).noLock and getIsVehicleInitiallyLocked(vehicle, ped and ped ~= 0) local lockState = isLocked and 2 or 1 SetVehicleDoorsLocked(vehicle, lockState) TriggerServerEvent('qb-vehiclekeys:server:setVehLockState', NetworkGetNetworkIdFromEntity(vehicle), lockState) diff --git a/client/searchkeys.lua b/client/searchkeys.lua index 9d94f08..76bc25d 100644 --- a/client/searchkeys.lua +++ b/client/searchkeys.lua @@ -1,12 +1,10 @@ local config = require 'config.client' -local sharedFunctions = require 'shared.functions' - local isSearchLocked = false local isSearchAllowed = false local function setSearchLabelState(isAllowed) if isSearchLocked and isAllowed then return end - if isAllowed and cache.vehicle and sharedFunctions.getVehicleConfig(cache.vehicle).findKeysChance == 0.0 then + if isAllowed and cache.vehicle and GetVehicleConfig(cache.vehicle).findKeysChance == 0.0 then isSearchAllowed = false return end diff --git a/config/client.lua b/config/client.lua index 5907af7..e1515e0 100644 --- a/config/client.lua +++ b/config/client.lua @@ -23,25 +23,9 @@ local hardLockpickSkillCheck = { inputs = { '1', '2', '3', '4' } } ----@alias Anim {dict: string, clip: string, delay?: integer} - ----@type Anim -local defaultHotwireAnim = { dict = 'anim@veh@plane@howard@front@ds@base', clip = 'hotwire' } - ----@type Anim -local defaultSearchKeysAnim = { dict = 'anim@amb@clubhouse@tutorial@bkr_tut_ig3@', clip = 'machinic_loop_mechandplayer' } - ----@type Anim -local defaultLockpickAnim = { dict = 'veh@break_in@0h@p_m_one@', clip = 'low_force_entry_ds' } - ----@type Anim -local defaultHoldupAnim = { dict = 'mp_am_hold_up', clip = 'holdup_victim_20s' } - return { vehicleMaximumLockingDistance = 5.0, -- Minimum distance for vehicle locking - getKeysWhenEngineIsRunning = true, -- when enabled, gives keys to a player who doesn't have them if they enter the driver seat when the engine is running - keepEngineOnWhenAbandoned = true, -- when enabled, keeps a vehicle's engine running after exiting -- Carjack Settings @@ -60,6 +44,7 @@ return { policeNightAlertChance = 0.50, -- Chance of alerting the police at night (times: 01-06) policeAlertNightStartHour = 1, policeAlertNightDuration = 5, + ---Sends an alert to police ---@param crime string ---@param vehicle number entity @@ -72,6 +57,14 @@ return { hotwireCooldown = 1000, -- Job Settings + ---@class SharedKeysConfig + ---@field enableAutolock? boolean auto-lock door on driver exit + ---@field requireOnDuty? boolean requires player to be on duty to access the vehicle + ---@field classes? table vehicle classes to enable shared keys on + ---@field vehicles? table vehicle hashes to enable shared keys on + + ---@alias JobName string + ---@type table sharedKeys = { -- Share keys amongst employees. Employees can lock/unlock any job-listed vehicle police = { -- Job name enableAutolock = true, @@ -114,122 +107,48 @@ return { lockpick = { default = normalLockpickSkillCheck, class = { - [VehicleClass.COMPACTS] = normalLockpickSkillCheck, - [VehicleClass.SEDANS] = normalLockpickSkillCheck, - [VehicleClass.SUVS] = normalLockpickSkillCheck, - [VehicleClass.COUPES] = normalLockpickSkillCheck, - [VehicleClass.MUSCLE] = normalLockpickSkillCheck, - [VehicleClass.SPORTS_CLASSICS] = normalLockpickSkillCheck, - [VehicleClass.SPORTS] = normalLockpickSkillCheck, - [VehicleClass.SUPER] = normalLockpickSkillCheck, - [VehicleClass.MOTORCYCLES] = normalLockpickSkillCheck, - [VehicleClass.OFF_ROAD] = normalLockpickSkillCheck, - [VehicleClass.INDUSTRIAL] = normalLockpickSkillCheck, - [VehicleClass.UTILITY] = normalLockpickSkillCheck, - [VehicleClass.VANS] = normalLockpickSkillCheck, - [VehicleClass.BOATS] = normalLockpickSkillCheck, - [VehicleClass.HELICOPTERS] = {}, - [VehicleClass.PLANES] = normalLockpickSkillCheck, - [VehicleClass.SERVICE] = normalLockpickSkillCheck, - [VehicleClass.EMERGENCY] = hardLockpickSkillCheck, - [VehicleClass.MILITARY] = {}, -- The vehicle class can only be opened with an advanced lockpick - [VehicleClass.COMMERCIAL] = normalLockpickSkillCheck, - [VehicleClass.TRAINS] = {}, - [VehicleClass.OPEN_WHEEL] = easyLockpickSkillCheck, + [VehicleClass.PLANES] = hardLockpickSkillCheck, + [VehicleClass.HELICOPTERS] = hardLockpickSkillCheck, + [VehicleClass.EMERGENCY] = hardLockpickSkillCheck, + [VehicleClass.MILITARY] = {}, -- cannot be lockpicked + [VehicleClass.TRAINS] = {}, -- cannot be lockpicked + [VehicleClass.OPEN_WHEEL] = easyLockpickSkillCheck, }, - model = { - [`zombiea`] = normalLockpickSkillCheck - } + model = {} }, advancedLockpick = { default = easyLockpickSkillCheck, class = { - [VehicleClass.COMPACTS] = easyLockpickSkillCheck, - [VehicleClass.SEDANS] = easyLockpickSkillCheck, - [VehicleClass.SUVS] = easyLockpickSkillCheck, - [VehicleClass.COUPES] = easyLockpickSkillCheck, - [VehicleClass.MUSCLE] = easyLockpickSkillCheck, - [VehicleClass.SPORTS_CLASSICS] = easyLockpickSkillCheck, - [VehicleClass.SPORTS] = easyLockpickSkillCheck, - [VehicleClass.SUPER] = easyLockpickSkillCheck, - [VehicleClass.MOTORCYCLES] = easyLockpickSkillCheck, - [VehicleClass.OFF_ROAD] = easyLockpickSkillCheck, - [VehicleClass.INDUSTRIAL] = easyLockpickSkillCheck, - [VehicleClass.UTILITY] = easyLockpickSkillCheck, - [VehicleClass.VANS] = easyLockpickSkillCheck, - [VehicleClass.BOATS] = easyLockpickSkillCheck, - [VehicleClass.HELICOPTERS] = hardLockpickSkillCheck, - [VehicleClass.PLANES] = hardLockpickSkillCheck, - [VehicleClass.SERVICE] = easyLockpickSkillCheck, - [VehicleClass.EMERGENCY] = easyLockpickSkillCheck, - [VehicleClass.MILITARY] = hardLockpickSkillCheck, - [VehicleClass.COMMERCIAL] = easyLockpickSkillCheck, - [VehicleClass.TRAINS] = {}, -- The vehicle class can't be opened with an lockpick - [VehicleClass.OPEN_WHEEL] = easyLockpickSkillCheck, + [VehicleClass.PLANES] = hardLockpickSkillCheck, + [VehicleClass.HELICOPTERS] = hardLockpickSkillCheck, + [VehicleClass.EMERGENCY] = hardLockpickSkillCheck, + [VehicleClass.MILITARY] = {}, -- cannot be lockpicked + [VehicleClass.TRAINS] = {}, -- cannot be lockpicked }, - model = { - [`zombiea`] = easyLockpickSkillCheck - } + model = {} }, hotwire = { default = normalLockpickSkillCheck, class = { - [VehicleClass.COMPACTS] = normalLockpickSkillCheck, - [VehicleClass.SEDANS] = normalLockpickSkillCheck, - [VehicleClass.SUVS] = normalLockpickSkillCheck, - [VehicleClass.COUPES] = normalLockpickSkillCheck, - [VehicleClass.MUSCLE] = normalLockpickSkillCheck, - [VehicleClass.SPORTS_CLASSICS] = normalLockpickSkillCheck, - [VehicleClass.SPORTS] = normalLockpickSkillCheck, - [VehicleClass.SUPER] = normalLockpickSkillCheck, - [VehicleClass.MOTORCYCLES] = normalLockpickSkillCheck, - [VehicleClass.OFF_ROAD] = normalLockpickSkillCheck, - [VehicleClass.INDUSTRIAL] = normalLockpickSkillCheck, - [VehicleClass.UTILITY] = normalLockpickSkillCheck, - [VehicleClass.VANS] = normalLockpickSkillCheck, - [VehicleClass.BOATS] = normalLockpickSkillCheck, - [VehicleClass.HELICOPTERS] = {}, - [VehicleClass.PLANES] = normalLockpickSkillCheck, - [VehicleClass.SERVICE] = normalLockpickSkillCheck, - [VehicleClass.EMERGENCY] = hardLockpickSkillCheck, - [VehicleClass.MILITARY] = {}, - [VehicleClass.COMMERCIAL] = normalLockpickSkillCheck, - [VehicleClass.TRAINS] = {}, - [VehicleClass.OPEN_WHEEL] = easyLockpickSkillCheck, + [VehicleClass.PLANES] = hardLockpickSkillCheck, + [VehicleClass.HELICOPTERS] = hardLockpickSkillCheck, + [VehicleClass.EMERGENCY] = hardLockpickSkillCheck, + [VehicleClass.MILITARY] = {}, -- cannot be hotwired + [VehicleClass.TRAINS] = {}, -- cannot be hotwired + [VehicleClass.OPEN_WHEEL] = easyLockpickSkillCheck, }, - model = { - [`zombiea`] = normalLockpickSkillCheck - } + model = {} }, advancedHotwire = { default = easyLockpickSkillCheck, class = { - [VehicleClass.COMPACTS] = easyLockpickSkillCheck, - [VehicleClass.SEDANS] = easyLockpickSkillCheck, - [VehicleClass.SUVS] = easyLockpickSkillCheck, - [VehicleClass.COUPES] = easyLockpickSkillCheck, - [VehicleClass.MUSCLE] = easyLockpickSkillCheck, - [VehicleClass.SPORTS_CLASSICS] = easyLockpickSkillCheck, - [VehicleClass.SPORTS] = easyLockpickSkillCheck, - [VehicleClass.SUPER] = easyLockpickSkillCheck, - [VehicleClass.MOTORCYCLES] = easyLockpickSkillCheck, - [VehicleClass.OFF_ROAD] = easyLockpickSkillCheck, - [VehicleClass.INDUSTRIAL] = easyLockpickSkillCheck, - [VehicleClass.UTILITY] = easyLockpickSkillCheck, - [VehicleClass.VANS] = easyLockpickSkillCheck, - [VehicleClass.BOATS] = easyLockpickSkillCheck, - [VehicleClass.HELICOPTERS] = hardLockpickSkillCheck, - [VehicleClass.PLANES] = hardLockpickSkillCheck, - [VehicleClass.SERVICE] = easyLockpickSkillCheck, - [VehicleClass.EMERGENCY] = easyLockpickSkillCheck, - [VehicleClass.MILITARY] = hardLockpickSkillCheck, - [VehicleClass.COMMERCIAL] = easyLockpickSkillCheck, - [VehicleClass.TRAINS] = {}, -- The vehicle class can't be hotwired - [VehicleClass.OPEN_WHEEL] = easyLockpickSkillCheck, + [VehicleClass.PLANES] = hardLockpickSkillCheck, + [VehicleClass.HELICOPTERS] = hardLockpickSkillCheck, + [VehicleClass.EMERGENCY] = hardLockpickSkillCheck, + [VehicleClass.MILITARY] = {}, -- cannot be hotwired + [VehicleClass.TRAINS] = {}, -- cannot be hotwired }, - model = { - [`zombiea`] = easyLockpickSkillCheck - } + model = {} } }, @@ -248,124 +167,36 @@ return { ---@type AnimConfigEntities anims = { hotwire = { - default = defaultHotwireAnim, - class = { - [VehicleClass.COMPACTS] = defaultHotwireAnim, - [VehicleClass.SEDANS] = defaultHotwireAnim, - [VehicleClass.SUVS] = defaultHotwireAnim, - [VehicleClass.COUPES] = defaultHotwireAnim, - [VehicleClass.MUSCLE] = defaultHotwireAnim, - [VehicleClass.SPORTS_CLASSICS] = defaultHotwireAnim, - [VehicleClass.SPORTS] = defaultHotwireAnim, - [VehicleClass.SUPER] = defaultHotwireAnim, - [VehicleClass.MOTORCYCLES] = defaultHotwireAnim, - [VehicleClass.OFF_ROAD] = defaultHotwireAnim, - [VehicleClass.INDUSTRIAL] = defaultHotwireAnim, - [VehicleClass.UTILITY] = defaultHotwireAnim, - [VehicleClass.VANS] = defaultHotwireAnim, - [VehicleClass.BOATS] = defaultHotwireAnim, - [VehicleClass.HELICOPTERS] = defaultHotwireAnim, - [VehicleClass.PLANES] = defaultHotwireAnim, - [VehicleClass.SERVICE] = defaultHotwireAnim, - [VehicleClass.EMERGENCY] = defaultHotwireAnim, - [VehicleClass.MILITARY] = defaultHotwireAnim, - [VehicleClass.COMMERCIAL] = defaultHotwireAnim, - [VehicleClass.TRAINS] = defaultHotwireAnim, - [VehicleClass.OPEN_WHEEL] = defaultHotwireAnim, + default = { + dict = 'anim@veh@plane@howard@front@ds@base', + clip = 'hotwire' }, - model = { - [`zombiea`] = defaultHotwireAnim - } + class = {}, + model = {} }, searchKeys = { - default = defaultSearchKeysAnim, - class = { - [VehicleClass.COMPACTS] = defaultSearchKeysAnim, - [VehicleClass.SEDANS] = defaultSearchKeysAnim, - [VehicleClass.SUVS] = defaultSearchKeysAnim, - [VehicleClass.COUPES] = defaultSearchKeysAnim, - [VehicleClass.MUSCLE] = defaultSearchKeysAnim, - [VehicleClass.SPORTS_CLASSICS] = defaultSearchKeysAnim, - [VehicleClass.SPORTS] = defaultSearchKeysAnim, - [VehicleClass.SUPER] = defaultSearchKeysAnim, - [VehicleClass.MOTORCYCLES] = defaultSearchKeysAnim, - [VehicleClass.OFF_ROAD] = defaultSearchKeysAnim, - [VehicleClass.INDUSTRIAL] = defaultSearchKeysAnim, - [VehicleClass.UTILITY] = defaultSearchKeysAnim, - [VehicleClass.VANS] = defaultSearchKeysAnim, - [VehicleClass.BOATS] = defaultSearchKeysAnim, - [VehicleClass.HELICOPTERS] = defaultSearchKeysAnim, - [VehicleClass.PLANES] = defaultSearchKeysAnim, - [VehicleClass.SERVICE] = defaultSearchKeysAnim, - [VehicleClass.EMERGENCY] = defaultSearchKeysAnim, - [VehicleClass.MILITARY] = defaultSearchKeysAnim, - [VehicleClass.COMMERCIAL] = defaultSearchKeysAnim, - [VehicleClass.TRAINS] = defaultSearchKeysAnim, - [VehicleClass.OPEN_WHEEL] = defaultSearchKeysAnim, + default = { + dict = 'anim@amb@clubhouse@tutorial@bkr_tut_ig3@', + clip = 'machinic_loop_mechandplayer', }, - model = { - [`zombiea`] = defaultSearchKeysAnim - } + class = {}, + model = {} }, lockpick = { - default = defaultLockpickAnim, - class = { - [VehicleClass.COMPACTS] = defaultLockpickAnim, - [VehicleClass.SEDANS] = defaultLockpickAnim, - [VehicleClass.SUVS] = defaultLockpickAnim, - [VehicleClass.COUPES] = defaultLockpickAnim, - [VehicleClass.MUSCLE] = defaultLockpickAnim, - [VehicleClass.SPORTS_CLASSICS] = defaultLockpickAnim, - [VehicleClass.SPORTS] = defaultLockpickAnim, - [VehicleClass.SUPER] = defaultLockpickAnim, - [VehicleClass.MOTORCYCLES] = defaultLockpickAnim, - [VehicleClass.OFF_ROAD] = defaultLockpickAnim, - [VehicleClass.INDUSTRIAL] = defaultLockpickAnim, - [VehicleClass.UTILITY] = defaultLockpickAnim, - [VehicleClass.VANS] = defaultLockpickAnim, - [VehicleClass.BOATS] = defaultLockpickAnim, - [VehicleClass.HELICOPTERS] = defaultLockpickAnim, - [VehicleClass.PLANES] = defaultLockpickAnim, - [VehicleClass.SERVICE] = defaultLockpickAnim, - [VehicleClass.EMERGENCY] = defaultLockpickAnim, - [VehicleClass.MILITARY] = defaultLockpickAnim, - [VehicleClass.COMMERCIAL] = defaultLockpickAnim, - [VehicleClass.TRAINS] = defaultLockpickAnim, - [VehicleClass.OPEN_WHEEL] = defaultLockpickAnim, + default = { + dict = 'veh@break_in@0h@p_m_one@', + clip = 'low_force_entry_ds' }, - model = { - [`zombiea`] = defaultLockpickAnim - } + class = {}, + model = {} }, holdup = { - default = defaultHoldupAnim, - class = { - [VehicleClass.COMPACTS] = defaultHoldupAnim, - [VehicleClass.SEDANS] = defaultHoldupAnim, - [VehicleClass.SUVS] = defaultHoldupAnim, - [VehicleClass.COUPES] = defaultHoldupAnim, - [VehicleClass.MUSCLE] = defaultHoldupAnim, - [VehicleClass.SPORTS_CLASSICS] = defaultHoldupAnim, - [VehicleClass.SPORTS] = defaultHoldupAnim, - [VehicleClass.SUPER] = defaultHoldupAnim, - [VehicleClass.MOTORCYCLES] = defaultHoldupAnim, - [VehicleClass.OFF_ROAD] = defaultHoldupAnim, - [VehicleClass.INDUSTRIAL] = defaultHoldupAnim, - [VehicleClass.UTILITY] = defaultHoldupAnim, - [VehicleClass.VANS] = defaultHoldupAnim, - [VehicleClass.BOATS] = defaultHoldupAnim, - [VehicleClass.HELICOPTERS] = defaultHoldupAnim, - [VehicleClass.PLANES] = defaultHoldupAnim, - [VehicleClass.SERVICE] = defaultHoldupAnim, - [VehicleClass.EMERGENCY] = defaultHoldupAnim, - [VehicleClass.MILITARY] = defaultHoldupAnim, - [VehicleClass.COMMERCIAL] = defaultHoldupAnim, - [VehicleClass.TRAINS] = defaultHoldupAnim, - [VehicleClass.OPEN_WHEEL] = defaultHoldupAnim, + default = { + dict = 'mp_am_hold_up', + clip = 'holdup_victim_20s' }, - model = { - [`zombiea`] = defaultHoldupAnim - } + class = {}, + model = {} }, toggleEngine = { default = { @@ -383,5 +214,37 @@ return { }, model = {}, }, - } + }, + -- Weapons that cannot be used for carjacking + noCarjackWeapons = { + `WEAPON_UNARMED`, + `WEAPON_KNIFE`, + `WEAPON_NIGHTSTICK`, + `WEAPON_HAMMER`, + `WEAPON_BAT`, + `WEAPON_CROWBAR`, + `WEAPON_GOLFCLUB`, + `WEAPON_BOTTLE`, + `WEAPON_DAGGER`, + `WEAPON_HATCHET`, + `WEAPON_KNUCKLE`, + `WEAPON_MACHETE`, + `WEAPON_FLASHLIGHT`, + `WEAPON_SWITCHBLADE`, + `WEAPON_POOLCUE`, + `WEAPON_WRENCH`, + `WEAPON_BATTLEAXE`, + `WEAPON_GRENADE`, + `WEAPON_STOCKYBOMB`, + `WEAPON_PROXIMITYMINE`, + `WEAPON_BZGAS`, + `WEAPON_MOLOTOV`, + `WEAPON_FIREEXTINGUISHER`, + `WEAPON_PETROLCAN`, + `WEAPON_FLARE`, + `WEAPON_BALL`, + `WEAPON_SNOWBALL`, + `WEAPON_SMOKEGRENADE`, + -- Add more weapon names as needed + }, } diff --git a/config/shared.lua b/config/shared.lua index 267f658..7e17311 100644 --- a/config/shared.lua +++ b/config/shared.lua @@ -62,37 +62,4 @@ return { -- } } }, - - -- Weapons that cannot be used for carjacking - noCarjackWeapons = { - `WEAPON_UNARMED`, - `WEAPON_KNIFE`, - `WEAPON_NIGHTSTICK`, - `WEAPON_HAMMER`, - `WEAPON_BAT`, - `WEAPON_CROWBAR`, - `WEAPON_GOLFCLUB`, - `WEAPON_BOTTLE`, - `WEAPON_DAGGER`, - `WEAPON_HATCHET`, - `WEAPON_KNUCKLE`, - `WEAPON_MACHETE`, - `WEAPON_FLASHLIGHT`, - `WEAPON_SWITCHBLADE`, - `WEAPON_POOLCUE`, - `WEAPON_WRENCH`, - `WEAPON_BATTLEAXE`, - `WEAPON_GRENADE`, - `WEAPON_STOCKYBOMB`, - `WEAPON_PROXIMITYMINE`, - `WEAPON_BZGAS`, - `WEAPON_MOLOTOV`, - `WEAPON_FIREEXTINGUISHER`, - `WEAPON_PETROLCAN`, - `WEAPON_FLARE`, - `WEAPON_BALL`, - `WEAPON_SNOWBALL`, - `WEAPON_SMOKEGRENADE`, - -- Add more weapon names as needed - }, } diff --git a/fxmanifest.lua b/fxmanifest.lua index d403809..8bfcefc 100644 --- a/fxmanifest.lua +++ b/fxmanifest.lua @@ -11,6 +11,7 @@ shared_scripts { '@ox_lib/init.lua', '@qbx_core/modules/lib.lua', 'shared/types.lua', + 'shared/vehicle-config.lua', 'bridge/qb/shared.lua', } @@ -33,7 +34,6 @@ server_scripts { } files { - 'shared/functions.lua', 'locales/*.json', 'config/client.lua', 'config/shared.lua' diff --git a/server/keys.lua b/server/keys.lua index 0d91db4..db06273 100644 --- a/server/keys.lua +++ b/server/keys.lua @@ -132,7 +132,7 @@ lib.callback.register('qbx_vehiclekeys:server:giveKeys', function(source, netId) GiveKeys(source, NetworkGetEntityFromNetworkId(netId)) end) -AddStateBagChangeHandler('vehicleid', nil, function(bagName, _, vehicleId) +AddStateBagChangeHandler('vehicleid', '', function(bagName, _, vehicleId) local vehicle = GetEntityFromStateBagName(bagName) if not vehicle or vehicle == 0 then return end local owner = exports.qbx_vehicles:GetPlayerVehicle(vehicleId)?.citizenid diff --git a/server/main.lua b/server/main.lua index 1fb1267..c039f8b 100644 --- a/server/main.lua +++ b/server/main.lua @@ -1,12 +1,8 @@ local config = require 'config.server' -local sharedFunctions = require 'shared.functions' - -local getIsVehicleAlwaysUnlocked = sharedFunctions.getIsVehicleAlwaysUnlocked -local getIsVehicleShared = sharedFunctions.getIsVehicleShared lib.callback.register('qbx_vehiclekeys:server:findKeys', function(source, netId) local vehicle = NetworkGetEntityFromNetworkId(netId) - if math.random() <= sharedFunctions.getVehicleConfig(vehicle).findKeysChance then + if math.random() <= GetVehicleConfig(vehicle).findKeysChance then GiveKeys(source, vehicle) return true end @@ -47,6 +43,7 @@ end) RegisterNetEvent('qb-vehiclekeys:server:setVehLockState', function(vehNetId, state) local vehicleEntity = NetworkGetEntityFromNetworkId(vehNetId) if type(state) ~= 'number' or not DoesEntityExist(vehicleEntity) then return end - if getIsVehicleAlwaysUnlocked(vehicleEntity) or getIsVehicleShared(vehicleEntity) then return end + local vehicleConfig = GetVehicleConfig(vehicleEntity) + if vehicleConfig.noLock or vehicleConfig.shared then return end Entity(vehicleEntity).state:set('doorslockstate', state, true) end) diff --git a/shared/functions.lua b/shared/functions.lua deleted file mode 100644 index e575afc..0000000 --- a/shared/functions.lua +++ /dev/null @@ -1,127 +0,0 @@ -local public = {} -local config = require 'config.shared' -local VEHICLES = exports.qbx_core:GetVehiclesByHash() - ---- Checks if the given two coordinates are close to each other based on distance. ----@param coord1 vector3[] The first set of coordinates. ----@param coord2 vector3[] The second set of coordinates. ----@param distance number The maximum allowed distance for them to be considered close. ----@return boolean true if the distance between two entities is less than the distance parameter. -function public.getIsCloseToCoords(coord1, coord2, distance) - return #(coord1 - coord2) < distance -end - -local function getIsOnList(item, list) - for i = 1, #list do - if item == list[i] then - return true - end - end -end - ----Checks if the vehicle has no locks and is accessible to everyone. ----@param vehicle number The entity number of the vehicle. ----@return boolean `true` if the vehicle is blacklisted, `false` otherwise. -function public.getIsVehicleShared(vehicle) - return public.getVehicleConfig(vehicle).shared -end - ----Checks if the vehicle cannot be locked. ----@param vehicle number The entity number of the vehicle. ----@return boolean? `true` if the vehicle is blacklisted, `nil` otherwise. -function public.getIsVehicleAlwaysUnlocked(vehicle) - return public.getVehicleConfig(vehicle).noLock or Entity(vehicle).state.ignoreLocks -end - ----Checks the vehicle is always locked at spawn. ----@param vehicle number The entity number of the vehicle. ----@param isDriven boolean ----@return boolean `true` if the vehicle is locked, `false` otherwise. -function public.getIsVehicleInitiallyLocked(vehicle, isDriven) - local vehicleConfig = public.getVehicleConfig(vehicle) - local vehicleLockedChance = isDriven - and vehicleConfig.spawnLockedIfDriven - or vehicleConfig.spawnLockedIfParked - - if type(vehicleLockedChance) == 'number' then - return math.random() < vehicleLockedChance - else - return vehicleLockedChance == true - end -end - ----Checks the vehicle is carjacking immune. ----@param vehicle number The entity number of the vehicle. ----@return boolean `true` if the vehicle is immune, `false` otherwise. -function public.getIsVehicleCarjackingImmune(vehicle) - return public.getVehicleConfig(vehicle).carjackingImmune -end - ----Checks the vehicle is lockpicking immune. ----@param vehicle number The entity number of the vehicle. ----@return boolean `true` if the vehicle is immune, `false` otherwise. -function public.getIsVehicleLockpickImmune(vehicle) - return public.getVehicleConfig(vehicle).lockpickImmune -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, `nil` otherwise. -function public.getIsBlacklistedWeapon(weaponHash) - return getIsOnList(weaponHash, config.noCarjackWeapons) -end - -local function findConfigValue(filteredConfig, key, default) - if filteredConfig.modelConfig?[key] ~= nil then - return filteredConfig.modelConfig[key] - elseif filteredConfig.categoryConfig?[key] ~= nil then - return filteredConfig.categoryConfig[key] - elseif filteredConfig.classConfig?[key] ~= nil then - return filteredConfig.classConfig[key] - elseif filteredConfig.typeConfig?[key] ~= nil then - return filteredConfig.typeConfig[key] - elseif filteredConfig.defaultConfig?[key] ~= nil then - return filteredConfig.defaultConfig[key] - else - return default - end -end - ----Gets the vehicle's config ----@param vehicle number ----@return VehicleConfig -function public.getVehicleConfig(vehicle) - local model = GetEntityModel(vehicle) - local class = IsDuplicityVersion() and exports.qbx_core:GetVehicleClass(model) or GetVehicleClass(vehicle) - local filteredConfig = { - modelConfig = config.vehicles.models[model], - categoryConfig = config.vehicles.categories[VEHICLES[model]?.category], - classConfig = config.vehicles.classes[class], - typeConfig = config.vehicles.types[GetVehicleType(vehicle)], - defaultConfig = config.vehicles.default - } - - local noLock = findConfigValue(filteredConfig, 'noLock', false) - local spawnLockedIfParked = noLock and 0.0 or findConfigValue(filteredConfig, 'spawnLockedIfParked', 1.0) - local spawnLockedIfDriven = noLock and 0.0 or findConfigValue(filteredConfig, 'spawnLockedIfDriven', 1.0) - local carjackingImmune = findConfigValue(filteredConfig, 'carjackingImmune', false) - local lockpickImmune = findConfigValue(filteredConfig, 'lockpickImmune', false) - local shared = findConfigValue(filteredConfig, 'shared', false) - local removeNormalLockpickChance = findConfigValue(filteredConfig, 'removeNormalLockpickChance', 1.0) - local removeAdvancedLockpickChance = findConfigValue(filteredConfig, 'removeAdvancedLockpickChance', 1.0) - local findKeysChance = findConfigValue(filteredConfig, 'findKeysChance', 1.0) - - return { - spawnLockedIfParked = spawnLockedIfParked, - spawnLockedIfDriven = spawnLockedIfDriven, - noLock = noLock, - carjackingImmune = carjackingImmune, - lockpickImmune = lockpickImmune, - shared = shared, - removeNormalLockpickChance = removeNormalLockpickChance, - removeAdvancedLockpickChance = removeAdvancedLockpickChance, - findKeysChance = findKeysChance, - } -end - -return public diff --git a/shared/vehicle-config.lua b/shared/vehicle-config.lua new file mode 100644 index 0000000..3e6ad1a --- /dev/null +++ b/shared/vehicle-config.lua @@ -0,0 +1,56 @@ +local config = require 'config.shared' +local VEHICLES = exports.qbx_core:GetVehiclesByHash() + +local function findConfigValue(filteredConfig, key, default) + if filteredConfig.modelConfig?[key] ~= nil then + return filteredConfig.modelConfig[key] + elseif filteredConfig.categoryConfig?[key] ~= nil then + return filteredConfig.categoryConfig[key] + elseif filteredConfig.classConfig?[key] ~= nil then + return filteredConfig.classConfig[key] + elseif filteredConfig.typeConfig?[key] ~= nil then + return filteredConfig.typeConfig[key] + elseif filteredConfig.defaultConfig?[key] ~= nil then + return filteredConfig.defaultConfig[key] + else + return default + end +end + +---Gets the vehicle's config +---@param vehicle number +---@return VehicleConfig +function GetVehicleConfig(vehicle) + assert(vehicle and vehicle ~= 0, 'cannot get the vehicle config for a vehicle that doesn\'t exist') + local model = GetEntityModel(vehicle) + local class = IsDuplicityVersion() and exports.qbx_core:GetVehicleClass(model) or GetVehicleClass(vehicle) + local filteredConfig = { + modelConfig = config.vehicles.models[model], + categoryConfig = config.vehicles.categories[VEHICLES[model]?.category], + classConfig = config.vehicles.classes[class], + typeConfig = config.vehicles.types[GetVehicleType(vehicle)], + defaultConfig = config.vehicles.default + } + + local noLock = findConfigValue(filteredConfig, 'noLock', false) + local spawnLockedIfParked = noLock and 0.0 or findConfigValue(filteredConfig, 'spawnLockedIfParked', 1.0) + local spawnLockedIfDriven = noLock and 0.0 or findConfigValue(filteredConfig, 'spawnLockedIfDriven', 1.0) + local carjackingImmune = findConfigValue(filteredConfig, 'carjackingImmune', false) + local lockpickImmune = findConfigValue(filteredConfig, 'lockpickImmune', false) + local shared = findConfigValue(filteredConfig, 'shared', false) + local removeNormalLockpickChance = findConfigValue(filteredConfig, 'removeNormalLockpickChance', 1.0) + local removeAdvancedLockpickChance = findConfigValue(filteredConfig, 'removeAdvancedLockpickChance', 1.0) + local findKeysChance = findConfigValue(filteredConfig, 'findKeysChance', 1.0) + + return { + spawnLockedIfParked = spawnLockedIfParked, + spawnLockedIfDriven = spawnLockedIfDriven, + noLock = noLock, + carjackingImmune = carjackingImmune, + lockpickImmune = lockpickImmune, + shared = shared, + removeNormalLockpickChance = removeNormalLockpickChance, + removeAdvancedLockpickChance = removeAdvancedLockpickChance, + findKeysChance = findKeysChance, + } +end \ No newline at end of file diff --git a/types.lua b/types.lua index a6da9fa..0ef6088 100644 --- a/types.lua +++ b/types.lua @@ -1,5 +1,7 @@ ---@meta +---@alias Anim {dict: string, clip: string, delay?: integer} + ---@alias VehicleType 'automobile' | 'bike' | 'boat' | 'heli' | 'plane' | 'submarine' | 'trailer' | 'train' ---@alias Hash number|string actually a number but `model` is treated as a string by language server