From 781f5064d051b2ae2d3823686cff7db5787b53f2 Mon Sep 17 00:00:00 2001 From: zRxnx Date: Wed, 22 Nov 2023 15:11:17 +0100 Subject: [PATCH] refactor(es_extended/**): cleanup, remove useless code, formatting [+] Added ESX.PlayerData.player [+] Added ESX.Game.IsDriverSeatEmpty [+] Added Config.MapName [+] Added Config.GameType [+] Added Config.AdminGroups.DEFAULT_GROUP [+] Added command_setcoords_h string [+] Added diagnostics [+] Define functions as local [/] Removed useless variables [/] Add more spaces for better visibility [/] Removed [''] [/] Replaced ~= nil with not [/] Unpack vectors properly [/] Replaced " to ' [/] Use RegisterNetEvent [/] Replaced table.insert with [#TABLE + 1] [/] Edited setcoords command [/] Properly written internal functions --- [core]/es_extended/client/common.lua | 5 +- [core]/es_extended/client/functions.lua | 723 +++++++++++------- [core]/es_extended/client/main.lua | 260 ++++--- [core]/es_extended/client/modules/actions.lua | 53 +- .../es_extended/client/modules/callback.lua | 6 +- [core]/es_extended/client/modules/death.lua | 55 +- [core]/es_extended/client/modules/npwd.lua | 11 +- .../es_extended/client/modules/scaleform.lua | 29 +- .../es_extended/client/modules/streaming.lua | 43 +- [core]/es_extended/common/functions.lua | 42 +- [core]/es_extended/common/modules/math.lua | 3 +- [core]/es_extended/common/modules/table.lua | 33 +- [core]/es_extended/common/modules/timeout.lua | 1 + [core]/es_extended/config.lua | 30 +- [core]/es_extended/fxmanifest.lua | 1 + [core]/es_extended/imports.lua | 7 +- [core]/es_extended/locale.lua | 7 +- [core]/es_extended/locales/cs.lua | 1 + [core]/es_extended/locales/de.lua | 1 + [core]/es_extended/locales/el.lua | 1 + [core]/es_extended/locales/en.lua | 1 + [core]/es_extended/locales/es.lua | 1 + [core]/es_extended/locales/fi.lua | 1 + [core]/es_extended/locales/fr.lua | 1 + [core]/es_extended/locales/he.lua | 1 + [core]/es_extended/locales/hu.lua | 1 + [core]/es_extended/locales/it.lua | 1 + [core]/es_extended/locales/nl.lua | 1 + [core]/es_extended/locales/pl.lua | 1 + [core]/es_extended/locales/sl.lua | 1 + [core]/es_extended/locales/sr.lua | 1 + [core]/es_extended/locales/zh-cn.lua | 1 + .../server/classes/overrides/oxinventory.lua | 1 + [core]/es_extended/server/classes/player.lua | 206 ++--- [core]/es_extended/server/commands.lua | 376 +++++---- [core]/es_extended/server/common.lua | 30 +- [core]/es_extended/server/functions.lua | 200 +++-- [core]/es_extended/server/main.lua | 329 ++++---- [core]/es_extended/server/modules/actions.lua | 12 +- .../es_extended/server/modules/callback.lua | 7 +- [core]/es_extended/server/modules/npwd.lua | 15 +- [core]/es_extended/server/onesync.lua | 84 +- [core]/es_extended/server/paycheck.lua | 143 ++-- 43 files changed, 1672 insertions(+), 1055 deletions(-) diff --git a/[core]/es_extended/client/common.lua b/[core]/es_extended/client/common.lua index e18f2884b..674111536 100644 --- a/[core]/es_extended/client/common.lua +++ b/[core]/es_extended/client/common.lua @@ -6,7 +6,6 @@ if GetResourceState('ox_inventory') ~= 'missing' then Config.OxInventory = true end -AddEventHandler("esx:getSharedObject", function() - local Invoke = GetInvokingResource() - print(("[^1ERROR^7] Resource ^5%s^7 Used the ^5getSharedObject^7 Event, this event ^1no longer exists!^7 Visit https://documentation.esx-framework.org/tutorials/tutorials-esx/sharedevent for how to fix!"):format(Invoke)) +RegisterNetEvent('esx:getSharedObject', function() + print(('[^1ERROR^7] Resource ^5%s^7 Used the ^5getSharedObject^7 Event, this event ^1no longer exists!^7 Visit https://documentation.esx-framework.org/tutorials/tutorials-esx/sharedevent for how to fix!'):format(GetInvokingResource)) end) diff --git a/[core]/es_extended/client/functions.lua b/[core]/es_extended/client/functions.lua index 63955e737..8d5abe0f7 100644 --- a/[core]/es_extended/client/functions.lua +++ b/[core]/es_extended/client/functions.lua @@ -1,3 +1,138 @@ +---@diagnostic disable: param-type-mismatch, cast-local-type, duplicate-set-field, missing-fields, redundant-parameter, undefined-field +local AddTextEntry = AddTextEntry +local BeginTextCommandThefeedPost = BeginTextCommandThefeedPost +local ThefeedSetNextPostBackgroundColor = ThefeedSetNextPostBackgroundColor +local EndTextCommandThefeedPostMessagetext = EndTextCommandThefeedPostMessagetext +local EndTextCommandThefeedPostTicker = EndTextCommandThefeedPostTicker +local DisplayHelpTextThisFrame = DisplayHelpTextThisFrame +local BeginTextCommandDisplayHelp = BeginTextCommandDisplayHelp +local EndTextCommandDisplayHelp = EndTextCommandDisplayHelp +local SetFloatingHelpTextWorldPosition = SetFloatingHelpTextWorldPosition +local SetFloatingHelpTextStyle = SetFloatingHelpTextStyle +local format = string.format +local upper = string.upper +local gsub = string.gsub +local GetResourceState = GetResourceState +local GetInvokingResource = GetInvokingResource +local RegisterCommand = RegisterCommand +local RegisterKeyMapping = RegisterKeyMapping +local DoesEntityExist = DoesEntityExist +local RegisterPedheadshotTransparent = RegisterPedheadshotTransparent +local RegisterPedheadshot = RegisterPedheadshot +local IsPedheadshotReady = IsPedheadshotReady +local GetPedheadshotTxdString = GetPedheadshotTxdString +local RequestCollisionAtCoord = RequestCollisionAtCoord +local HasCollisionLoadedAroundEntity = HasCollisionLoadedAroundEntity +local SetEntityCoords = SetEntityCoords +local SetEntityHeading = SetEntityHeading +local NetworkGetEntityFromNetworkId = NetworkGetEntityFromNetworkId +local CreateObject = CreateObject +local SetEntityAsMissionEntity = SetEntityAsMissionEntity +local DeleteVehicle = DeleteVehicle +local DeleteObject = DeleteObject +local GetEntityCoords = GetEntityCoords +local CreateVehicle = CreateVehicle +local SetNetworkIdCanMigrate = SetNetworkIdCanMigrate +local SetVehicleHasBeenOwnedByPlayer = SetVehicleHasBeenOwnedByPlayer +local SetVehicleNeedsToBeHotwired = SetVehicleNeedsToBeHotwired +local SetModelAsNoLongerNeeded = SetModelAsNoLongerNeeded +local SetVehRadioStation = SetVehRadioStation +local GetVehicleNumberOfPassengers = GetVehicleNumberOfPassengers +local IsVehicleSeatFree = IsVehicleSeatFree +local GetGamePool = GetGamePool +local GetPlayerPed = GetPlayerPed +local GetEntityModel = GetEntityModel +local GetOffsetFromEntityInWorldCoords = GetOffsetFromEntityInWorldCoords +local GetVehicleColours = GetVehicleColours +local GetVehicleExtraColours = GetVehicleExtraColours +local GetIsVehiclePrimaryColourCustom = GetIsVehiclePrimaryColourCustom +local GetVehicleDashboardColor = GetVehicleDashboardColor +local GetVehicleInteriorColour = GetVehicleInteriorColour +local GetVehicleCustomPrimaryColour = GetVehicleCustomPrimaryColour +local GetVehicleXenonLightsCustomColor = GetVehicleXenonLightsCustomColor +local GetIsVehicleSecondaryColourCustom = GetIsVehicleSecondaryColourCustom +local GetVehicleCustomSecondaryColour = GetVehicleCustomSecondaryColour +local DoesExtraExist = DoesExtraExist +local IsVehicleExtraTurnedOn = IsVehicleExtraTurnedOn +local GetVehicleNumberOfWheels = GetVehicleNumberOfWheels +local IsVehicleTyreBurst = IsVehicleTyreBurst +local RollUpWindow = RollUpWindow +local IsVehicleWindowIntact = IsVehicleWindowIntact +local GetNumberOfVehicleDoors = GetNumberOfVehicleDoors +local IsVehicleDoorDamaged = IsVehicleDoorDamaged +local GetVehicleTyresCanBurst = GetVehicleTyresCanBurst +local GetVehicleNumberPlateText = GetVehicleNumberPlateText +local GetVehicleBodyHealth = GetVehicleBodyHealth +local GetVehicleEngineHealth = GetVehicleEngineHealth +local GetVehiclePetrolTankHealth = GetVehiclePetrolTankHealth +local GetVehicleFuelLevel = GetVehicleFuelLevel +local GetVehicleDirtLevel = GetVehicleDirtLevel +local GetVehicleWheelType = GetVehicleWheelType +local GetVehicleWindowTint = GetVehicleWindowTint +local GetVehicleXenonLightsColor = GetVehicleXenonLightsColor +local IsVehicleNeonLightEnabled = IsVehicleNeonLightEnabled +local GetVehicleNeonLightsColour = GetVehicleNeonLightsColour +local GetVehicleTyreSmokeColor = GetVehicleTyreSmokeColor +local GetVehicleMod = GetVehicleMod +local GetVehicleRoofLivery = GetVehicleRoofLivery +local IsToggleModOn = IsToggleModOn +local GetVehicleModVariation = GetVehicleModVariation +local GetVehicleLivery = GetVehicleLivery +local SetVehicleModKit = SetVehicleModKit +local SetVehicleTyresCanBurst = SetVehicleTyresCanBurst +local SetVehicleNumberPlateText = SetVehicleNumberPlateText +local SetVehicleNumberPlateTextIndex = SetVehicleNumberPlateTextIndex +local SetVehicleBodyHealth = SetVehicleBodyHealth +local SetVehicleEngineHealth = SetVehicleEngineHealth +local SetVehiclePetrolTankHealth = SetVehiclePetrolTankHealth +local SetVehicleFuelLevel = SetVehicleFuelLevel +local SetVehicleDirtLevel = SetVehicleDirtLevel +local SetVehicleCustomPrimaryColour = SetVehicleCustomPrimaryColour +local SetVehicleCustomSecondaryColour = SetVehicleCustomSecondaryColour +local SetVehicleColours = SetVehicleColours +local SetVehicleExtraColours = SetVehicleExtraColours +local SetVehicleInteriorColor = SetVehicleInteriorColor +local SetVehicleDashboardColor = SetVehicleDashboardColor +local SetVehicleWheelType = SetVehicleWheelType +local SetVehicleWindowTint = SetVehicleWindowTint +local SetVehicleNeonLightEnabled = SetVehicleNeonLightEnabled +local SetVehicleExtra = SetVehicleExtra +local SetVehicleNeonLightsColour = SetVehicleNeonLightsColour +local SetVehicleXenonLightsColor = SetVehicleXenonLightsColor +local SetVehicleXenonLightsCustomColor = SetVehicleXenonLightsCustomColor +local ToggleVehicleMod = ToggleVehicleMod +local SetVehicleTyreSmokeColor = SetVehicleTyreSmokeColor +local SetVehicleMod = SetVehicleMod +local SetVehicleRoofLivery = SetVehicleRoofLivery +local SetVehicleLivery = SetVehicleLivery +local RemoveVehicleWindow = RemoveVehicleWindow +local SetVehicleDoorBroken = SetVehicleDoorBroken +local SetVehicleTyreBurst = SetVehicleTyreBurst +local GetFinalRenderedCamCoord = GetFinalRenderedCamCoord +local GetGameplayCamFov = GetGameplayCamFov +local SetTextScale = SetTextScale +local SetTextFont = SetTextFont +local SetTextProportional = SetTextProportional +local SetTextColour = SetTextColour +local BeginTextCommandDisplayText = BeginTextCommandDisplayText +local SetTextCentre = SetTextCentre +local AddTextComponentSubstringPlayerName = AddTextComponentSubstringPlayerName +local SetDrawOrigin = SetDrawOrigin +local EndTextCommandDisplayText = EndTextCommandDisplayText +local ClearDrawOrigin = ClearDrawOrigin +local HasPedGotWeapon = HasPedGotWeapon +local GetAmmoInPedWeapon = GetAmmoInPedWeapon +local GetPlayerServerId = GetPlayerServerId +local GetPlayerFromServerId = GetPlayerFromServerId +local IsPedOnFoot = IsPedOnFoot +local IsPedFalling = IsPedFalling +local TriggerServerEvent = TriggerServerEvent +local TaskPlayAnim = TaskPlayAnim +local RemoveAnimDict = RemoveAnimDict +local IsModelInCdimage = IsModelInCdimage +local GetVehicleClassFromName = GetVehicleClassFromName +local Wait = Wait + ESX = {} Core = {} ESX.PlayerData = {} @@ -31,9 +166,10 @@ function ESX.SearchInventory(items, count) local returnData = {} local itemCount = #items + local itemName for i = 1, itemCount do - local itemName = items[i] + itemName = items[i] returnData[itemName] = count and 0 for _, item in pairs(ESX.PlayerData.inventory) do @@ -55,6 +191,7 @@ end function ESX.SetPlayerData(key, val) local current = ESX.PlayerData[key] ESX.PlayerData[key] = val + if key ~= 'inventory' and key ~= 'loadout' then if type(val) == 'table' or val ~= current then TriggerEvent('esx:setPlayerData', key, val, current) @@ -63,46 +200,49 @@ function ESX.SetPlayerData(key, val) end function ESX.Progressbar(message, length, Options) - if GetResourceState("esx_progressbar") ~= "missing" then - return exports["esx_progressbar"]:Progressbar(message, length, Options) + if GetResourceState('esx_progressbar') ~= 'missing' then + return exports.esx_progressbar:Progressbar(message, length, Options) end - print("[^1ERROR^7] ^5ESX Progressbar^7 is Missing!") + print('[^1ERROR^7] ^5ESX Progressbar^7 is Missing!') end function ESX.ShowNotification(message, notifyType, length) - if GetResourceState("esx_notify") ~= "missing" then - return exports["esx_notify"]:Notify(notifyType, length, message) + if GetResourceState('esx_notify') ~= 'missing' then + return exports.esx_notify:Notify(notifyType, length, message) end - print("[^1ERROR^7] ^5ESX Notify^7 is Missing!") + print('[^1ERROR^7] ^5ESX Notify^7 is Missing!') end function ESX.TextUI(message, notifyType) - if GetResourceState("esx_textui") ~= "missing" then - return exports["esx_textui"]:TextUI(message, notifyType) + if GetResourceState('esx_textui') ~= 'missing' then + return exports.esx_textui:TextUI(message, notifyType) end - print("[^1ERROR^7] ^5ESX TextUI^7 is Missing!") + print('[^1ERROR^7] ^5ESX TextUI^7 is Missing!') end function ESX.HideUI() - if GetResourceState("esx_textui") ~= "missing" then - return exports["esx_textui"]:HideUI() + if GetResourceState('esx_textui') ~= 'missing' then + return exports.esx_textui:HideUI() end - print("[^1ERROR^7] ^5ESX TextUI^7 is Missing!") + print('[^1ERROR^7] ^5ESX TextUI^7 is Missing!') end function ESX.ShowAdvancedNotification(sender, subject, msg, textureDict, iconType, flash, saveToBrief, hudColorIndex) - if saveToBrief == nil then + if not saveToBrief then saveToBrief = true end + AddTextEntry('esxAdvancedNotification', msg) BeginTextCommandThefeedPost('esxAdvancedNotification') + if hudColorIndex then ThefeedSetNextPostBackgroundColor(hudColorIndex) end + EndTextCommandThefeedPostMessagetext(textureDict, textureDict, false, iconType, sender, subject) EndTextCommandThefeedPostTicker(flash or false, saveToBrief) end @@ -113,9 +253,10 @@ function ESX.ShowHelpNotification(msg, thisFrame, beep, duration) if thisFrame then DisplayHelpTextThisFrame('esxHelpNotification', false) else - if beep == nil then + if not beep then beep = true end + BeginTextCommandDisplayHelp('esxHelpNotification') EndTextCommandDisplayHelp(0, false, beep, duration or -1) end @@ -123,48 +264,47 @@ end function ESX.ShowFloatingHelpNotification(msg, coords) AddTextEntry('esxFloatingHelpNotification', msg) - SetFloatingHelpTextWorldPosition(1, coords) + SetFloatingHelpTextWorldPosition(1, coords.x, coords.y, coords.z) SetFloatingHelpTextStyle(1, 1, 2, -1, 3, 0) BeginTextCommandDisplayHelp('esxFloatingHelpNotification') EndTextCommandDisplayHelp(2, false, false, -1) end ESX.HashString = function(str) - local format = string.format - local upper = string.upper - local gsub = string.gsub local hash = joaat(str) - local input_map = format("~INPUT_%s~", upper(format("%x", hash))) - input_map = gsub(input_map, "FFFFFFFF", "") + local input_map = format('~INPUT_%s~', upper(format('%x', hash))) + input_map = gsub(input_map, 'FFFFFFFF', '') return input_map end -local contextAvailable = GetResourceState("esx_context") ~= "missing" +local contextAvailable = GetResourceState('esx_context') ~= 'missing' function ESX.OpenContext(...) - return contextAvailable and exports["esx_context"]:Open(...) or not contextAvailable and print("[^1ERROR^7] Tried to ^5open^7 context menu, but ^5esx_context^7 is missing!") + return contextAvailable and exports.esx_context:Open(...) or print('[^1ERROR^7] Tried to ^5open^7 context menu, but ^5esx_context^7 is missing!') end function ESX.PreviewContext(...) - return contextAvailable and exports["esx_context"]:Preview(...) or not contextAvailable and print("[^1ERROR^7] Tried to ^5preview^7 context menu, but ^5esx_context^7 is missing!") + return contextAvailable and exports.esx_context:Preview(...) or print('[^1ERROR^7] Tried to ^5preview^7 context menu, but ^5esx_context^7 is missing!') end function ESX.CloseContext(...) - return contextAvailable and exports["esx_context"]:Close(...) or not contextAvailable and print("[^1ERROR^7] Tried to ^5close^7 context menu, but ^5esx_context^7 is missing!") + return contextAvailable and exports.esx_context:Close(...) or print('[^1ERROR^7] Tried to ^5close^7 context menu, but ^5esx_context^7 is missing!') end function ESX.RefreshContext(...) - return contextAvailable and exports["esx_context"]:Refresh(...) or not contextAvailable and print("[^1ERROR^7] Tried to ^5Refresh^7 context menu, but ^5esx_context^7 is missing!") + return contextAvailable and exports.esx_context:Refresh(...) or print('[^1ERROR^7] Tried to ^5Refresh^7 context menu, but ^5esx_context^7 is missing!') end ESX.RegisterInput = function(command_name, label, input_group, key, on_press, on_release) - RegisterCommand(on_release ~= nil and "+" .. command_name or command_name, on_press) - Core.Input[command_name] = on_release ~= nil and ESX.HashString("+" .. command_name) or ESX.HashString(command_name) + Core.Input[command_name] = on_release ~= nil and ESX.HashString('+' .. command_name) or ESX.HashString(command_name) + RegisterCommand(on_release ~= nil and '+' .. command_name or command_name, on_press) + if on_release then - RegisterCommand("-" .. command_name, on_release) + RegisterCommand('-' .. command_name, on_release) end - RegisterKeyMapping(on_release ~= nil and "+" .. command_name or command_name, label, input_group, key) + + RegisterKeyMapping(on_release ~= nil and '+' .. command_name or command_name, label, input_group, key) end function ESX.UI.Menu.RegisterType(menuType, open, close) @@ -179,7 +319,7 @@ function ESX.UI.Menu.Open(menuType, namespace, name, data, submit, cancel, chang menu.type = menuType menu.namespace = namespace - menu.resourceName = (GetInvokingResource() or "Unknown") + menu.resourceName = (GetInvokingResource() or 'Unknown') menu.name = name menu.data = data menu.submit = submit @@ -310,22 +450,22 @@ function ESX.Game.GetPedMugshot(ped, transparent) local mugshot = transparent and RegisterPedheadshotTransparent(ped) or RegisterPedheadshot(ped) while not IsPedheadshotReady(mugshot) do - Wait(0) + Wait(100) end return mugshot, GetPedheadshotTxdString(mugshot) end function ESX.Game.Teleport(entity, coords, cb) - local vector = type(coords) == "vector4" and coords or type(coords) == "vector3" and vector4(coords, 0.0) or vec(coords.x, coords.y, coords.z, coords.heading or 0.0) + local vector = type(coords) == 'vector4' and coords or type(coords) == 'vector3' and vector4(coords, 0.0) or vec(coords.x, coords.y, coords.z, coords.heading or 0.0) if DoesEntityExist(entity) then - RequestCollisionAtCoord(vector.xyz) + RequestCollisionAtCoord(vector.x, vector.y, vector.z) while not HasCollisionLoadedAroundEntity(entity) do - Wait(0) + Wait(100) end - SetEntityCoords(entity, vector.xyz, false, false, false, false) + SetEntityCoords(entity, vector.x, vector.y, vector.z, false, false, false, false) SetEntityHeading(entity, vector.w) end @@ -335,30 +475,36 @@ function ESX.Game.Teleport(entity, coords, cb) end function ESX.Game.SpawnObject(object, coords, cb, networked) - networked = networked == nil and true or networked + networked = not networked and true or networked + if networked then ESX.TriggerServerCallback('esx:Onesync:SpawnObject', function(NetworkID) if cb then local obj = NetworkGetEntityFromNetworkId(NetworkID) - local Tries = 0 + local tries = 0 + while not DoesEntityExist(obj) do obj = NetworkGetEntityFromNetworkId(NetworkID) Wait(0) - Tries = Tries + 1 - if Tries > 250 then + tries = tries + 1 + + if tries > 250 then break end end + cb(obj) end end, object, coords, 0.0) else local model = type(object) == 'number' and object or joaat(object) - local vector = type(coords) == "vector3" and coords or vec(coords.x, coords.y, coords.z) + local vector = type(coords) == 'vector3' and coords or vec(coords.x, coords.y, coords.z) + CreateThread(function() ESX.Streaming.RequestModel(model) - local obj = CreateObject(model, vector.xyz, networked, false, true) + local obj = CreateObject(model, vector.x, vector.y, vector.z, networked, false, true) + if cb then cb(obj) end @@ -381,38 +527,40 @@ function ESX.Game.DeleteObject(object) end function ESX.Game.SpawnVehicle(vehicleModel, coords, heading, cb, networked) - local model = type(vehicleModel) == 'number' and vehicleModel or joaat(vehicleModel) - local vector = type(coords) == "vector3" and coords or vec(coords.x, coords.y, coords.z) - networked = networked == nil and true or networked + networked = not networked and true or networked + local model = type(vehicleModel) == 'number' and vehicleModel or joaat(vehicleModel) + local vector = type(coords) == 'vector3' and coords or vec(coords.x, coords.y, coords.z) local playerCoords = GetEntityCoords(ESX.PlayerData.ped) + if not vector or not playerCoords then return end - local dist = #(playerCoords - vector) - if dist > 424 then -- Onesync infinity Range (https://docs.fivem.net/docs/scripting-reference/onesync/) - local executingResource = GetInvokingResource() or "Unknown" - return print(("[^1ERROR^7] Resource ^5%s^7 Tried to spawn vehicle on the client but the position is too far away (Out of onesync range)."):format(executingResource)) + + if #(playerCoords - vector) > 424 then -- Onesync infinity Range (https://docs.fivem.net/docs/scripting-reference/onesync/) + return print(('[^1ERROR^7] Resource ^5%s^7 Tried to spawn vehicle on the client but the position is too far away (Out of onesync range).'):format(GetInvokingResource() or 'Unknown')) end CreateThread(function() ESX.Streaming.RequestModel(model) - local vehicle = CreateVehicle(model, vector.xyz, heading, networked, true) + local vehicle = CreateVehicle(model, vector.x, vector.y, vector.z, heading, networked, true) if networked then local id = NetworkGetNetworkIdFromEntity(vehicle) + SetNetworkIdCanMigrate(id, true) SetEntityAsMissionEntity(vehicle, true, true) end + SetVehicleHasBeenOwnedByPlayer(vehicle, true) SetVehicleNeedsToBeHotwired(vehicle, false) SetModelAsNoLongerNeeded(model) SetVehRadioStation(vehicle, 'OFF') + RequestCollisionAtCoord(vector.x, vector.y, vector.z) - RequestCollisionAtCoord(vector.xyz) while not HasCollisionLoadedAroundEntity(vehicle) do - Wait(0) + Wait(100) end if cb then @@ -425,12 +573,14 @@ function ESX.Game.SpawnLocalVehicle(vehicle, coords, heading, cb) ESX.Game.SpawnVehicle(vehicle, coords, heading, cb, false) end -function ESX.Game.IsVehicleEmpty(vehicle) - local passengers = GetVehicleNumberOfPassengers(vehicle) - local driverSeatFree = IsVehicleSeatFree(vehicle, -1) +function ESX.Game.IsDriverSeatEmpty(vehicle) + if not DoesEntityExist(vehicle) then + return false + end - return passengers == 0 and driverSeatFree + return GetVehicleNumberOfPassengers(vehicle) == 0 and IsVehicleSeatFree(vehicle, -1) end +ESX.Game.IsVehicleEmpty = ESX.Game.IsDriverSeatEmpty function ESX.Game.GetObjects() -- Leave the function for compatibility return GetGamePool('CObject') @@ -458,12 +608,13 @@ function ESX.Game.GetVehicles() -- Leave the function for compatibility end function ESX.Game.GetPlayers(onlyOtherPlayers, returnKeyValue, returnPeds) - local players, myPlayer = {}, PlayerId() + local players = {} + local ped for _, player in ipairs(GetActivePlayers()) do - local ped = GetPlayerPed(player) + ped = GetPlayerPed(player) - if DoesEntityExist(ped) and ((onlyOtherPlayers and player ~= myPlayer) or not onlyOtherPlayers) then + if DoesEntityExist(ped) and ((onlyOtherPlayers and player ~= ESX.PlayerData.player) or not onlyOtherPlayers) then if returnKeyValue then players[player] = ped else @@ -493,18 +644,18 @@ end local function EnumerateEntitiesWithinDistance(entities, isPlayerEntities, coords, maxDistance) local nearbyEntities = {} + local dist if coords then coords = vector3(coords.x, coords.y, coords.z) else - local playerPed = ESX.PlayerData.ped - coords = GetEntityCoords(playerPed) + coords = GetEntityCoords(ESX.PlayerData.ped) end for k, entity in pairs(entities) do - local distance = #(coords - GetEntityCoords(entity)) + dist = #(coords - GetEntityCoords(entity)) - if distance <= maxDistance then + if dist <= maxDistance then nearbyEntities[#nearbyEntities + 1] = isPlayerEntities and k or entity end end @@ -530,8 +681,7 @@ function ESX.Game.GetClosestEntity(entities, isPlayerEntities, coords, modelFilt if coords then coords = vector3(coords.x, coords.y, coords.z) else - local playerPed = ESX.PlayerData.ped - coords = GetEntityCoords(playerPed) + coords = GetEntityCoords(ESX.PlayerData.ped) end if modelFilter then @@ -556,23 +706,21 @@ function ESX.Game.GetClosestEntity(entities, isPlayerEntities, coords, modelFilt end function ESX.Game.GetVehicleInDirection() - local playerPed = ESX.PlayerData.ped - local playerCoords = GetEntityCoords(playerPed) - local inDirection = GetOffsetFromEntityInWorldCoords(playerPed, 0.0, 5.0, 0.0) - local rayHandle = StartExpensiveSynchronousShapeTestLosProbe(playerCoords, inDirection, 10, playerPed, 0) + local playerCoords = GetEntityCoords(ESX.PlayerData.ped) + local inDirection = GetOffsetFromEntityInWorldCoords(ESX.PlayerData.ped, 0.0, 5.0, 0.0) + local rayHandle = StartExpensiveSynchronousShapeTestLosProbe(playerCoords.x, playerCoords.y, playerCoords.z, inDirection.x, inDirection.y, inDirection.z, 10, ESX.PlayerData.ped, 0) local _, hit, _, _, entityHit = GetShapeTestResult(rayHandle) if hit == 1 and GetEntityType(entityHit) == 2 then - local entityCoords = GetEntityCoords(entityHit) - return entityHit, entityCoords + return entityHit, GetEntityCoords(entityHit) end - return nil + return 0 end function ESX.Game.GetVehicleProperties(vehicle) if not DoesEntityExist(vehicle) then - return + return {} end local colorPrimary, colorSecondary = GetVehicleColours(vehicle) @@ -581,12 +729,14 @@ function ESX.Game.GetVehicleProperties(vehicle) local dashboardColor = GetVehicleDashboardColor(vehicle) local interiorColor = GetVehicleInteriorColour(vehicle) local customPrimaryColor = nil + if hasCustomPrimaryColor then customPrimaryColor = { GetVehicleCustomPrimaryColour(vehicle) } end local hasCustomXenonColor, customXenonColorR, customXenonColorG, customXenonColorB = GetVehicleXenonLightsCustomColor(vehicle) local customXenonColor = nil + if hasCustomXenonColor then customXenonColor = { customXenonColorR, customXenonColorG, customXenonColorB } end @@ -730,241 +880,298 @@ function ESX.Game.SetVehicleProperties(vehicle, props) if not DoesEntityExist(vehicle) then return end + local colorPrimary, colorSecondary = GetVehicleColours(vehicle) local pearlescentColor, wheelColor = GetVehicleExtraColours(vehicle) - SetVehicleModKit(vehicle, 0) - if props.tyresCanBurst ~= nil then + SetVehicleModKit(vehicle, 0) + if props?.tyresCanBurst then SetVehicleTyresCanBurst(vehicle, props.tyresCanBurst) end - if props.plate ~= nil then + if props?.plate then SetVehicleNumberPlateText(vehicle, props.plate) end - if props.plateIndex ~= nil then + + if props?.plateIndex then SetVehicleNumberPlateTextIndex(vehicle, props.plateIndex) end - if props.bodyHealth ~= nil then + + if props?.bodyHealth then SetVehicleBodyHealth(vehicle, props.bodyHealth + 0.0) end - if props.engineHealth ~= nil then + + if props?.engineHealth then SetVehicleEngineHealth(vehicle, props.engineHealth + 0.0) end - if props.tankHealth ~= nil then + + if props?.tankHealth then SetVehiclePetrolTankHealth(vehicle, props.tankHealth + 0.0) end - if props.fuelLevel ~= nil then + + if props?.fuelLevel then SetVehicleFuelLevel(vehicle, props.fuelLevel + 0.0) end - if props.dirtLevel ~= nil then + + if props?.dirtLevel then SetVehicleDirtLevel(vehicle, props.dirtLevel + 0.0) end - if props.customPrimaryColor ~= nil then - SetVehicleCustomPrimaryColour(vehicle, props.customPrimaryColor[1], props.customPrimaryColor[2], - props.customPrimaryColor[3]) + + if props?.customPrimaryColor then + SetVehicleCustomPrimaryColour(vehicle, props.customPrimaryColor[1], props.customPrimaryColor[2], props.customPrimaryColor[3]) end - if props.customSecondaryColor ~= nil then - SetVehicleCustomSecondaryColour(vehicle, props.customSecondaryColor[1], props.customSecondaryColor[2], - props.customSecondaryColor[3]) + + if props?.customSecondaryColor then + SetVehicleCustomSecondaryColour(vehicle, props.customSecondaryColor[1], props.customSecondaryColor[2], props.customSecondaryColor[3]) end - if props.color1 ~= nil then + + if props?.color1 then SetVehicleColours(vehicle, props.color1, colorSecondary) end - if props.color2 ~= nil then + + if props?.color2 then SetVehicleColours(vehicle, props.color1 or colorPrimary, props.color2) end - if props.pearlescentColor ~= nil then + + if props?.pearlescentColor then SetVehicleExtraColours(vehicle, props.pearlescentColor, wheelColor) end - if props.interiorColor ~= nil then + if props?.interiorColor then SetVehicleInteriorColor(vehicle, props.interiorColor) end - if props.dashboardColor ~= nil then + if props?.dashboardColor then SetVehicleDashboardColor(vehicle, props.dashboardColor) end - if props.wheelColor ~= nil then + if props?.wheelColor then SetVehicleExtraColours(vehicle, props.pearlescentColor or pearlescentColor, props.wheelColor) end - if props.wheels ~= nil then + + if props?.wheels then SetVehicleWheelType(vehicle, props.wheels) end - if props.windowTint ~= nil then + if props?.windowTint then SetVehicleWindowTint(vehicle, props.windowTint) end - if props.neonEnabled ~= nil then + if props?.neonEnabled then SetVehicleNeonLightEnabled(vehicle, 0, props.neonEnabled[1]) SetVehicleNeonLightEnabled(vehicle, 1, props.neonEnabled[2]) SetVehicleNeonLightEnabled(vehicle, 2, props.neonEnabled[3]) SetVehicleNeonLightEnabled(vehicle, 3, props.neonEnabled[4]) end - if props.extras ~= nil then + if props?.extras then for extraId, enabled in pairs(props.extras) do SetVehicleExtra(vehicle, tonumber(extraId), enabled and 0 or 1) end end - if props.neonColor ~= nil then + if props?.neonColor then SetVehicleNeonLightsColour(vehicle, props.neonColor[1], props.neonColor[2], props.neonColor[3]) end - if props.xenonColor ~= nil then + + if props?.xenonColor then SetVehicleXenonLightsColor(vehicle, props.xenonColor) end - if props.customXenonColor ~= nil then + + if props?.customXenonColor then SetVehicleXenonLightsCustomColor(vehicle, props.customXenonColor[1], props.customXenonColor[2], props.customXenonColor[3]) end - if props.modSmokeEnabled ~= nil then + + if props?.modSmokeEnabled then ToggleVehicleMod(vehicle, 20, true) end - if props.tyreSmokeColor ~= nil then + + if props?.tyreSmokeColor then SetVehicleTyreSmokeColor(vehicle, props.tyreSmokeColor[1], props.tyreSmokeColor[2], props.tyreSmokeColor[3]) end - if props.modSpoilers ~= nil then + + if props?.modSpoilers then SetVehicleMod(vehicle, 0, props.modSpoilers, false) end - if props.modFrontBumper ~= nil then + + if props?.modFrontBumper then SetVehicleMod(vehicle, 1, props.modFrontBumper, false) end - if props.modRearBumper ~= nil then + + if props?.modRearBumper then SetVehicleMod(vehicle, 2, props.modRearBumper, false) end - if props.modSideSkirt ~= nil then + + if props?.modSideSkirt then SetVehicleMod(vehicle, 3, props.modSideSkirt, false) end - if props.modExhaust ~= nil then + + if props?.modExhaust then SetVehicleMod(vehicle, 4, props.modExhaust, false) end - if props.modFrame ~= nil then + + if props?.modFrame then SetVehicleMod(vehicle, 5, props.modFrame, false) end - if props.modGrille ~= nil then + + if props?.modGrille then SetVehicleMod(vehicle, 6, props.modGrille, false) end - if props.modHood ~= nil then + + if props?.modHood then SetVehicleMod(vehicle, 7, props.modHood, false) end - if props.modFender ~= nil then + + if props?.modFender then SetVehicleMod(vehicle, 8, props.modFender, false) end - if props.modRightFender ~= nil then + + if props?.modRightFender then SetVehicleMod(vehicle, 9, props.modRightFender, false) end - if props.modRoof ~= nil then + + if props?.modRoof then SetVehicleMod(vehicle, 10, props.modRoof, false) end - if props.modRoofLivery ~= nil then + if props?.modRoofLivery then SetVehicleRoofLivery(vehicle, props.modRoofLivery) end - if props.modEngine ~= nil then + if props?.modEngine then SetVehicleMod(vehicle, 11, props.modEngine, false) end - if props.modBrakes ~= nil then + + if props?.modBrakes then SetVehicleMod(vehicle, 12, props.modBrakes, false) end - if props.modTransmission ~= nil then + + if props?.modTransmission then SetVehicleMod(vehicle, 13, props.modTransmission, false) end - if props.modHorns ~= nil then + + if props?.modHorns then SetVehicleMod(vehicle, 14, props.modHorns, false) end - if props.modSuspension ~= nil then + + if props?.modSuspension then SetVehicleMod(vehicle, 15, props.modSuspension, false) end - if props.modArmor ~= nil then + + if props?.modArmor then SetVehicleMod(vehicle, 16, props.modArmor, false) end - if props.modTurbo ~= nil then + + if props?.modTurbo then ToggleVehicleMod(vehicle, 18, props.modTurbo) end - if props.modXenon ~= nil then + + if props?.modXenon then ToggleVehicleMod(vehicle, 22, props.modXenon) end - if props.modFrontWheels ~= nil then + + if props?.modFrontWheels then SetVehicleMod(vehicle, 23, props.modFrontWheels, props.modCustomFrontWheels) end - if props.modBackWheels ~= nil then + + if props?.modBackWheels then SetVehicleMod(vehicle, 24, props.modBackWheels, props.modCustomBackWheels) end - if props.modPlateHolder ~= nil then + + if props?.modPlateHolder then SetVehicleMod(vehicle, 25, props.modPlateHolder, false) end - if props.modVanityPlate ~= nil then + + if props?.modVanityPlate then SetVehicleMod(vehicle, 26, props.modVanityPlate, false) end - if props.modTrimA ~= nil then + + if props?.modTrimA then SetVehicleMod(vehicle, 27, props.modTrimA, false) end - if props.modOrnaments ~= nil then + + if props?.modOrnaments then SetVehicleMod(vehicle, 28, props.modOrnaments, false) end - if props.modDashboard ~= nil then + + if props?.modDashboard then SetVehicleMod(vehicle, 29, props.modDashboard, false) end - if props.modDial ~= nil then + + if props?.modDial then SetVehicleMod(vehicle, 30, props.modDial, false) end - if props.modDoorSpeaker ~= nil then + + if props?.modDoorSpeaker then SetVehicleMod(vehicle, 31, props.modDoorSpeaker, false) end - if props.modSeats ~= nil then + + if props?.modSeats then SetVehicleMod(vehicle, 32, props.modSeats, false) end - if props.modSteeringWheel ~= nil then + + if props?.modSteeringWheel then SetVehicleMod(vehicle, 33, props.modSteeringWheel, false) end - if props.modShifterLeavers ~= nil then + + if props?.modShifterLeavers then SetVehicleMod(vehicle, 34, props.modShifterLeavers, false) end - if props.modAPlate ~= nil then + + if props?.modAPlate then SetVehicleMod(vehicle, 35, props.modAPlate, false) end - if props.modSpeakers ~= nil then + + if props?.modSpeakers then SetVehicleMod(vehicle, 36, props.modSpeakers, false) end - if props.modTrunk ~= nil then + + if props?.modTrunk then SetVehicleMod(vehicle, 37, props.modTrunk, false) end - if props.modHydrolic ~= nil then + + if props?.modHydrolic then SetVehicleMod(vehicle, 38, props.modHydrolic, false) end - if props.modEngineBlock ~= nil then + + if props?.modEngineBlock then SetVehicleMod(vehicle, 39, props.modEngineBlock, false) end - if props.modAirFilter ~= nil then + + if props?.modAirFilter then SetVehicleMod(vehicle, 40, props.modAirFilter, false) end - if props.modStruts ~= nil then + + if props?.modStruts then SetVehicleMod(vehicle, 41, props.modStruts, false) end - if props.modArchCover ~= nil then + + if props?.modArchCover then SetVehicleMod(vehicle, 42, props.modArchCover, false) end - if props.modAerials ~= nil then + + if props?.modAerials then SetVehicleMod(vehicle, 43, props.modAerials, false) end - if props.modTrimB ~= nil then + + if props?.modTrimB then SetVehicleMod(vehicle, 44, props.modTrimB, false) end - if props.modTank ~= nil then + + if props?.modTank then SetVehicleMod(vehicle, 45, props.modTank, false) end - if props.modWindows ~= nil then + + if props?.modWindows then SetVehicleMod(vehicle, 46, props.modWindows, false) end - if props.modLivery ~= nil then + if props?.modLivery then SetVehicleMod(vehicle, 48, props.modLivery, false) SetVehicleLivery(vehicle, props.modLivery) end - if props.windowsBroken ~= nil then + if props?.windowsBroken then for k, v in pairs(props.windowsBroken) do if v then RemoveVehicleWindow(vehicle, tonumber(k)) @@ -972,7 +1179,7 @@ function ESX.Game.SetVehicleProperties(vehicle, props) end end - if props.doorsBroken ~= nil then + if props?.doorsBroken then for k, v in pairs(props.doorsBroken) do if v then SetVehicleDoorBroken(vehicle, tonumber(k), true) @@ -980,7 +1187,7 @@ function ESX.Game.SetVehicleProperties(vehicle, props) end end - if props.tyreBurst ~= nil then + if props?.tyreBurst then for k, v in pairs(props.tyreBurst) do if v then SetVehicleTyreBurst(vehicle, tonumber(k), true, 1000.0) @@ -990,19 +1197,10 @@ function ESX.Game.SetVehicleProperties(vehicle, props) end function ESX.Game.Utils.DrawText3D(coords, text, size, font) - local vector = type(coords) == "vector3" and coords or vec(coords.x, coords.y, coords.z) - - local camCoords = GetFinalRenderedCamCoord() - local distance = #(vector - camCoords) - - if not size then - size = 1 - end - if not font then - font = 0 - end - - local scale = (size / distance) * 2 + size = size or 1 + font = font or 0 + local vector = vec(coords.x, coords.y, coords.z) + local scale = (size / #(vector - GetFinalRenderedCamCoord())) * 2 local fov = (1 / GetGameplayCamFov()) * 100 scale = scale * fov @@ -1013,7 +1211,7 @@ function ESX.Game.Utils.DrawText3D(coords, text, size, font) BeginTextCommandDisplayText('STRING') SetTextCentre(true) AddTextComponentSubstringPlayerName(text) - SetDrawOrigin(vector.xyz, 0) + SetDrawOrigin(vector.x, vector.y, vector.z, 0) EndTextCommandDisplayText(0.0, 0.0) ClearDrawOrigin() end @@ -1026,7 +1224,8 @@ function ESX.GetAccount(account) return ESX.PlayerData.accounts[i] end end - return nil + + return {} end function ESX.ShowInventory() @@ -1034,32 +1233,30 @@ function ESX.ShowInventory() return end - local playerPed = ESX.PlayerData.ped local elements = { { unselectable = true, icon = 'fas fa-box' } } local currentWeight = 0 for i = 1, #(ESX.PlayerData.accounts) do - if ESX.PlayerData.accounts[i].money > 0 then + if ESX.PlayerData.accounts[i]?.money > 0 then local formattedMoney = TranslateCap('locale_currency', ESX.Math.GroupDigits(ESX.PlayerData.accounts[i].money)) - local canDrop = ESX.PlayerData.accounts[i].name ~= 'bank' elements[#elements + 1] = { icon = 'fas fa-money-bill-wave', - title = ('%s: %s'):format(ESX.PlayerData.accounts[i].label, formattedMoney), + title = ('%s: %s'):format(ESX.PlayerData.accounts[i].label, formattedMoney), count = ESX.PlayerData.accounts[i].money, type = 'item_account', value = ESX.PlayerData.accounts[i].name, usable = false, rare = false, - canRemove = canDrop + canRemove = ESX.PlayerData.accounts[i].name ~= 'bank' } end end for _, v in ipairs(ESX.PlayerData.inventory) do - if v.count > 0 then + if v?.count > 0 then currentWeight = currentWeight + (v.weight * v.count) elements[#elements + 1] = { @@ -1081,8 +1278,8 @@ function ESX.ShowInventory() local v = Config.Weapons[i] local weaponHash = joaat(v.name) - if HasPedGotWeapon(playerPed, weaponHash, false) then - local ammo = GetAmmoInPedWeapon(playerPed, weaponHash) + if HasPedGotWeapon(ESX.PlayerData.ped, weaponHash, false) then + local ammo = GetAmmoInPedWeapon(ESX.PlayerData.ped, weaponHash) elements[#elements + 1] = { icon = 'fas fa-gun', @@ -1101,14 +1298,13 @@ function ESX.ShowInventory() ESX.CloseContext() - ESX.OpenContext("right", elements, function(_, element) + ESX.OpenContext('right', elements, function(_, element) local player, distance = ESX.Game.GetClosestPlayer() - local elements2 = {} - if element.usable then + if element?.usable then elements2[#elements2 + 1] = { - icon = "fas fa-utensils", + icon = 'fas fa-utensils', title = TranslateCap('use'), action = 'use', type = element.type, @@ -1116,10 +1312,10 @@ function ESX.ShowInventory() } end - if element.canRemove then + if element?.canRemove then if player ~= -1 and distance <= 3.0 then elements2[#elements2 + 1] = { - icon = "fas fa-hands", + icon = 'fas fa-hands', title = TranslateCap('give'), action = 'give', type = element.type, @@ -1128,7 +1324,7 @@ function ESX.ShowInventory() end elements2[#elements2 + 1] = { - icon = "fas fa-trash", + icon = 'fas fa-trash', title = TranslateCap('remove'), action = 'remove', type = element.type, @@ -1136,9 +1332,9 @@ function ESX.ShowInventory() } end - if element.type == 'item_weapon' and element.canGiveAmmo and element.ammo > 0 and player ~= -1 and distance <= 3.0 then + if element?.type == 'item_weapon' and element.canGiveAmmo and element.ammo > 0 and player ~= -1 and distance <= 3.0 then elements2[#elements2 + 1] = { - icon = "fas fa-gun", + icon = 'fas fa-gun', title = TranslateCap('giveammo'), action = 'give_ammo', type = element.type, @@ -1147,21 +1343,21 @@ function ESX.ShowInventory() end elements2[#elements2 + 1] = { - icon = "fas fa-arrow-left", + icon = 'fas fa-arrow-left', title = TranslateCap('return'), action = 'return' } - ESX.OpenContext("right", elements2, function(_, element2) + ESX.OpenContext('right', elements2, function(_, element2) local item, itemType = element2.value, element2.type - if element2.action == "give" then - local playersNearby = ESX.Game.GetPlayersInArea(GetEntityCoords(playerPed), 3.0) + if element2.action == 'give' then + local playersNearby = ESX.Game.GetPlayersInArea(GetEntityCoords(ESX.PlayerData.ped), 3.0) if #playersNearby > 0 then local players = {} local elements3 = { - { unselectable = true, icon = "fas fa-users", title = "Nearby Players" } + { unselectable = true, icon = 'fas fa-users', title = 'Nearby Players' } } for _, playerNearby in ipairs(playersNearby) do @@ -1171,18 +1367,18 @@ function ESX.ShowInventory() ESX.TriggerServerCallback('esx:getPlayerNames', function(returnedPlayers) for playerId, playerName in pairs(returnedPlayers) do elements3[#elements3 + 1] = { - icon = "fas fa-user", + icon = 'fas fa-user', title = playerName, playerId = playerId } end - ESX.OpenContext("right", elements3, function(_, element3) + ESX.OpenContext('right', elements3, function(_, element3) local selectedPlayer, selectedPlayerId = GetPlayerFromServerId(element3.playerId), element3.playerId - playersNearby = ESX.Game.GetPlayersInArea(GetEntityCoords(playerPed), 3.0) + playersNearby = ESX.Game.GetPlayersInArea(GetEntityCoords(ESX.PlayerData.ped), 3.0) playersNearby = ESX.Table.Set(playersNearby) - if playersNearby[selectedPlayer] then + if playersNearby and playersNearby[selectedPlayer] then local selectedPlayerPed = GetPlayerPed(selectedPlayer) if IsPedOnFoot(selectedPlayerPed) and not IsPedFalling(selectedPlayerPed) then @@ -1191,12 +1387,12 @@ function ESX.ShowInventory() ESX.CloseContext() else local elementsG = { - { unselectable = true, icon = "fas fa-trash", title = element.title }, - { icon = "fas fa-tally", title = "Amount.", input = true, inputType = "number", inputPlaceholder = "Amount to give..", inputMin = 1, inputMax = 1000 }, - { icon = "fas fa-check-double", title = "Confirm", val = "confirm" } + { unselectable = true, icon = 'fas fa-trash', title = element.title }, + { icon = 'fas fa-tally', title = 'Amount.', input = true, inputType = 'number', inputPlaceholder = 'Amount to give..', inputMin = 1, inputMax = 1000 }, + { icon = 'fas fa-check-double', title = 'Confirm', val = 'confirm' } } - ESX.OpenContext("right", elementsG, function(menuG, _) + ESX.OpenContext('right', elementsG, function(menuG, _) local quantity = tonumber(menuG.eles[2].inputValue) if quantity and quantity > 0 and element.count >= quantity then @@ -1217,30 +1413,30 @@ function ESX.ShowInventory() end) end, players) end - elseif element2.action == "remove" then - if IsPedOnFoot(playerPed) and not IsPedFalling(playerPed) then + elseif element2.action == 'remove' then + if IsPedOnFoot(ESX.PlayerData.ped) and not IsPedFalling(ESX.PlayerData.ped) then local dict, anim = 'weapons@first_person@aim_rng@generic@projectile@sticky_bomb@', 'plant_floor' ESX.Streaming.RequestAnimDict(dict) if itemType == 'item_weapon' then ESX.CloseContext() - TaskPlayAnim(playerPed, dict, anim, 8.0, 1.0, 1000, 16, 0.0, false, false, false) + TaskPlayAnim(ESX.PlayerData.ped, dict, anim, 8.0, 1.0, 1000, 16, 0.0, false, false, false) RemoveAnimDict(dict) Wait(1000) TriggerServerEvent('esx:removeInventoryItem', itemType, item) else local elementsR = { - { unselectable = true, icon = "fas fa-trash", title = element.title }, - { icon = "fas fa-tally", title = "Amount.", input = true, inputType = "number", inputPlaceholder = "Amount to remove..", inputMin = 1, inputMax = 1000 }, - { icon = "fas fa-check-double", title = "Confirm", val = "confirm" } + { unselectable = true, icon = 'fas fa-trash', title = element.title }, + { icon = 'fas fa-tally', title = 'Amount.', input = true, inputType = 'number', inputPlaceholder = 'Amount to remove..', inputMin = 1, inputMax = 1000 }, + { icon = 'fas fa-check-double', title = 'Confirm', val = 'confirm' } } - ESX.OpenContext("right", elementsR, function(menuR, _) + ESX.OpenContext('right', elementsR, function(menuR, _) local quantity = tonumber(menuR.eles[2].inputValue) if quantity and quantity > 0 and element.count >= quantity then ESX.CloseContext() - TaskPlayAnim(playerPed, dict, anim, 8.0, 1.0, 1000, 16, 0.0, false, false, false) + TaskPlayAnim(ESX.PlayerData.ped, dict, anim, 8.0, 1.0, 1000, 16, 0.0, false, false, false) RemoveAnimDict(dict) Wait(1000) TriggerServerEvent('esx:removeInventoryItem', itemType, item, quantity) @@ -1250,27 +1446,27 @@ function ESX.ShowInventory() end) end end - elseif element2.action == "use" then + elseif element2.action == 'use' then ESX.CloseContext() TriggerServerEvent('esx:useItem', item) - elseif element2.action == "return" then + elseif element2.action == 'return' then ESX.CloseContext() ESX.ShowInventory() - elseif element2.action == "give_ammo" then + elseif element2.action == 'give_ammo' then local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() local closestPed = GetPlayerPed(closestPlayer) - local pedAmmo = GetAmmoInPedWeapon(playerPed, joaat(item)) + local pedAmmo = GetAmmoInPedWeapon(ESX.PlayerData.ped, joaat(item)) if IsPedOnFoot(closestPed) and not IsPedFalling(closestPed) then if closestPlayer ~= -1 and closestDistance < 3.0 then if pedAmmo > 0 then local elementsGA = { - { unselectable = true, icon = "fas fa-trash", title = element.title }, - { icon = "fas fa-tally", title = "Amount.", input = true, inputType = "number", inputPlaceholder = "Amount to give..", inputMin = 1, inputMax = 1000 }, - { icon = "fas fa-check-double", title = "Confirm", val = "confirm" } + { unselectable = true, icon = 'fas fa-trash', title = element.title }, + { icon = 'fas fa-tally', title = 'Amount.', input = true, inputType = 'number', inputPlaceholder = 'Amount to give..', inputMin = 1, inputMax = 1000 }, + { icon = 'fas fa-check-double', title = 'Confirm', val = 'confirm' } } - ESX.OpenContext("right", elementsGA, function(menuGA, _) + ESX.OpenContext('right', elementsGA, function(menuGA, _) local quantity = tonumber(menuGA.eles[2].inputValue) if quantity and quantity > 0 then @@ -1298,19 +1494,15 @@ function ESX.ShowInventory() end) end -RegisterNetEvent('esx:showNotification') -AddEventHandler('esx:showNotification', function(msg, notifyType, length) +RegisterNetEvent('esx:showNotification', function(msg, notifyType, length) ESX.ShowNotification(msg, notifyType, length) end) -RegisterNetEvent('esx:showAdvancedNotification') -AddEventHandler('esx:showAdvancedNotification', - function(sender, subject, msg, textureDict, iconType, flash, saveToBrief, hudColorIndex) - ESX.ShowAdvancedNotification(sender, subject, msg, textureDict, iconType, flash, saveToBrief, hudColorIndex) - end) +RegisterNetEvent('esx:showAdvancedNotification', function(sender, subject, msg, textureDict, iconType, flash, saveToBrief, hudColorIndex) + ESX.ShowAdvancedNotification(sender, subject, msg, textureDict, iconType, flash, saveToBrief, hudColorIndex) +end) -RegisterNetEvent('esx:showHelpNotification') -AddEventHandler('esx:showHelpNotification', function(msg, thisFrame, beep, duration) +RegisterNetEvent('esx:showHelpNotification', function(msg, thisFrame, beep, duration) ESX.ShowHelpNotification(msg, thisFrame, beep, duration) end) @@ -1324,62 +1516,67 @@ AddEventHandler('onResourceStop', function(resourceName) end end end) + -- Credits to txAdmin for the list. local mismatchedTypes = { - [`airtug`] = "automobile", -- trailer - [`avisa`] = "submarine", -- boat - [`blimp`] = "heli", -- plane - [`blimp2`] = "heli", -- plane - [`blimp3`] = "heli", -- plane - [`caddy`] = "automobile", -- trailer - [`caddy2`] = "automobile", -- trailer - [`caddy3`] = "automobile", -- trailer - [`chimera`] = "automobile", -- bike - [`docktug`] = "automobile", -- trailer - [`forklift`] = "automobile", -- trailer - [`kosatka`] = "submarine", -- boat - [`mower`] = "automobile", -- trailer - [`policeb`] = "bike", -- automobile - [`ripley`] = "automobile", -- trailer - [`rrocket`] = "automobile", -- bike - [`sadler`] = "automobile", -- trailer - [`sadler2`] = "automobile", -- trailer - [`scrap`] = "automobile", -- trailer - [`slamtruck`] = "automobile", -- trailer - [`Stryder`] = "automobile", -- bike - [`submersible`] = "submarine", -- boat - [`submersible2`] = "submarine", -- boat - [`thruster`] = "heli", -- automobile - [`towtruck`] = "automobile", -- trailer - [`towtruck2`] = "automobile", -- trailer - [`tractor`] = "automobile", -- trailer - [`tractor2`] = "automobile", -- trailer - [`tractor3`] = "automobile", -- trailer - [`trailersmall2`] = "trailer", -- automobile - [`utillitruck`] = "automobile", -- trailer - [`utillitruck2`] = "automobile", -- trailer - [`utillitruck3`] = "automobile", -- trailer + [`airtug`] = 'automobile', -- trailer + [`avisa`] = 'submarine', -- boat + [`blimp`] = 'heli', -- plane + [`blimp2`] = 'heli', -- plane + [`blimp3`] = 'heli', -- plane + [`caddy`] = 'automobile', -- trailer + [`caddy2`] = 'automobile', -- trailer + [`caddy3`] = 'automobile', -- trailer + [`chimera`] = 'automobile', -- bike + [`docktug`] = 'automobile', -- trailer + [`forklift`] = 'automobile', -- trailer + [`kosatka`] = 'submarine', -- boat + [`mower`] = 'automobile', -- trailer + [`policeb`] = 'bike', -- automobile + [`ripley`] = 'automobile', -- trailer + [`rrocket`] = 'automobile', -- bike + [`sadler`] = 'automobile', -- trailer + [`sadler2`] = 'automobile', -- trailer + [`scrap`] = 'automobile', -- trailer + [`slamtruck`] = 'automobile', -- trailer + [`Stryder`] = 'automobile', -- bike + [`submersible`] = 'submarine', -- boat + [`submersible2`] = 'submarine', -- boat + [`thruster`] = 'heli', -- automobile + [`towtruck`] = 'automobile', -- trailer + [`towtruck2`] = 'automobile', -- trailer + [`tractor`] = 'automobile', -- trailer + [`tractor2`] = 'automobile', -- trailer + [`tractor3`] = 'automobile', -- trailer + [`trailersmall2`] = 'trailer', -- automobile + [`utillitruck`] = 'automobile', -- trailer + [`utillitruck2`] = 'automobile', -- trailer + [`utillitruck3`] = 'automobile', -- trailer } ---@param model number|string ---@return string function ESX.GetVehicleType(model) model = type(model) == 'string' and joaat(model) or model - if not IsModelInCdimage(model) then return end + + if not IsModelInCdimage(model) then + return '' + end + if mismatchedTypes[model] then return mismatchedTypes[model] end local vehicleType = GetVehicleClassFromName(model) local types = { - [8] = "bike", - [11] = "trailer", - [13] = "bike", - [14] = "boat", - [15] = "heli", - [16] = "plane", - [21] = "train", + [8] = 'bike', + [11] = 'trailer', + [13] = 'bike', + [14] = 'boat', + [15] = 'heli', + [16] = 'plane', + [21] = 'train', } - return types[vehicleType] or "automobile" + return types[vehicleType] or 'automobile' end diff --git a/[core]/es_extended/client/main.lua b/[core]/es_extended/client/main.lua index 3804cfc10..752eab51a 100644 --- a/[core]/es_extended/client/main.lua +++ b/[core]/es_extended/client/main.lua @@ -1,10 +1,71 @@ +---@diagnostic disable: param-type-mismatch, missing-fields local pickups = {} +local DoScreenFadeOut = DoScreenFadeOut +local SetPedIntoVehicle = SetPedIntoVehicle +local SetPedConfigFlag = SetPedConfigFlag +local DisplayAmmoThisFrame = DisplayAmmoThisFrame +local BlockWeaponWheelThisFrame = BlockWeaponWheelThisFrame +local DisableControlAction = DisableControlAction +local IsPedArmed = IsPedArmed +local DisablePlayerVehicleRewards = DisablePlayerVehicleRewards +local SetPlayerLockonRangeOverride = SetPlayerLockonRangeOverride +local EnableDispatchService = EnableDispatchService +local SetScenarioTypeEnabled = SetScenarioTypeEnabled +local PlayerPedId = PlayerPedId +local PlayerId = PlayerId +local RemoveAllPedWeapons = RemoveAllPedWeapons +local GiveWeaponToPed = GiveWeaponToPed +local SetPedWeaponTintIndex = SetPedWeaponTintIndex +local GetPedAmmoTypeFromWeapon = GetPedAmmoTypeFromWeapon +local GiveWeaponComponentToPed = GiveWeaponComponentToPed +local AddAmmoToPed = AddAmmoToPed +local GetGameTimer = GetGameTimer +local NetworkDoesEntityExistWithNetworkId = NetworkDoesEntityExistWithNetworkId +local NetToVeh = NetToVeh +local NetworkGetEntityOwner = NetworkGetEntityOwner +local RemoveWeaponComponentFromPed = RemoveWeaponComponentFromPed +local SetEntityAsMissionEntity = SetEntityAsMissionEntity +local PlaceObjectOnGroundProperly = PlaceObjectOnGroundProperly +local FreezeEntityPosition = FreezeEntityPosition +local SetEntityCollision = SetEntityCollision +local CreateWeaponObject = CreateWeaponObject +local GiveWeaponComponentToWeaponObject = GiveWeaponComponentToWeaponObject +local GetSelectedPedWeapon = GetSelectedPedWeapon +local GetAmmoInPedWeapon = GetAmmoInPedWeapon +local GetEntityCoords = GetEntityCoords +local IsPedOnFoot = IsPedOnFoot +local IsControlJustReleased = IsControlJustReleased +local TaskPlayAnim = TaskPlayAnim +local RemoveAnimDict = RemoveAnimDict +local PlaySoundFrontend = PlaySoundFrontend +local GetGroundZFor_3dCoord = GetGroundZFor_3dCoord +local GetFirstBlipInfoId = GetFirstBlipInfoId +local DoesBlipExist = DoesBlipExist +local GetBlipInfoIdCoord = GetBlipInfoIdCoord +local GetVehiclePedIsIn = GetVehiclePedIsIn +local IsNetworkLoadingScene = IsNetworkLoadingScene +local NewLoadSceneStart = NewLoadSceneStart +local NewLoadSceneStop = NewLoadSceneStop +local SetPedCoordsKeepVehicle = SetPedCoordsKeepVehicle +local HasCollisionLoadedAroundEntity = HasCollisionLoadedAroundEntity +local RequestCollisionAtCoord = RequestCollisionAtCoord +local SetEntityCoordsNoOffset = SetEntityCoordsNoOffset +local IsControlPressed = IsControlPressed +local SetEntityHeading = SetEntityHeading +local GetOffsetFromEntityInWorldCoords = GetOffsetFromEntityInWorldCoords +local SetVehicleEngineHealth = SetVehicleEngineHealth +local SetVehicleEngineOn = SetVehicleEngineOn +local SetVehicleFixed = SetVehicleFixed +local SetVehicleDirtLevel = SetVehicleDirtLevel +local SetPlayerInvincible = SetPlayerInvincible +local GetPlayerServerId = GetPlayerServerId +local Wait = Wait CreateThread(function() while not Config.Multichar do - Wait(100) + Wait(200) - if NetworkIsPlayerActive(PlayerId()) then + if NetworkIsPlayerActive(ESX.PlayerData.player) then exports.spawnmanager:setAutoSpawn(false) DoScreenFadeOut(0) Wait(500) @@ -14,12 +75,11 @@ CreateThread(function() end end) -RegisterNetEvent("esx:requestModel", function(model) +RegisterNetEvent('esx:requestModel', function(model) ESX.Streaming.RequestModel(model) end) -RegisterNetEvent('esx:playerLoaded') -AddEventHandler('esx:playerLoaded', function(xPlayer, isNew, skin) +RegisterNetEvent('esx:playerLoaded', function(xPlayer, isNew, skin) ESX.PlayerData = xPlayer if Config.Multichar then @@ -51,20 +111,21 @@ AddEventHandler('esx:playerLoaded', function(xPlayer, isNew, skin) ESX.PlayerLoaded = true - while ESX.PlayerData.ped == nil do Wait(20) end + while not ESX.PlayerData.ped do + Wait(100) + end if Config.EnablePVP then SetCanAttackFriendly(ESX.PlayerData.ped, true, false) NetworkSetFriendlyFireOption(true) end - local playerId = PlayerId() local metadata = ESX.PlayerData.metadata if metadata.health then SetEntityHealth(ESX.PlayerData.ped, metadata.health) end - if metadata.armor and metadata.armor > 0 then + if metadata?.armor > 0 then SetPedArmour(ESX.PlayerData.ped, metadata.armor) end @@ -79,7 +140,7 @@ AddEventHandler('esx:playerLoaded', function(xPlayer, isNew, skin) if Config.DisableNPCDrops then local weaponPickups = { `PICKUP_WEAPON_CARBINERIFLE`, `PICKUP_WEAPON_PISTOL`, `PICKUP_WEAPON_PUMPSHOTGUN` } for i = 1, #weaponPickups do - ToggleUsePickupsForPlayer(playerId, weaponPickups[i], false) + ToggleUsePickupsForPlayer(ESX.PlayerData.player, weaponPickups[i], false) end end @@ -93,7 +154,7 @@ AddEventHandler('esx:playerLoaded', function(xPlayer, isNew, skin) end if Config.DisableHealthRegeneration then - SetPlayerHealthRechargeMultiplier(playerId, 0.0) + SetPlayerHealthRechargeMultiplier(ESX.PlayerData.player, 0.0) end if Config.DisableWeaponWheel or Config.DisableAimAssist or Config.DisableVehicleRewards then @@ -110,12 +171,12 @@ AddEventHandler('esx:playerLoaded', function(xPlayer, isNew, skin) if Config.DisableAimAssist then if IsPedArmed(ESX.PlayerData.ped, 4) then - SetPlayerLockonRangeOverride(playerId, 2.0) + SetPlayerLockonRangeOverride(ESX.PlayerData.player, 2.0) end end if Config.DisableVehicleRewards then - DisablePlayerVehicleRewards(playerId) + DisablePlayerVehicleRewards(ESX.PlayerData.player) end Wait(0) @@ -195,16 +256,17 @@ AddEventHandler('esx:playerLoaded', function(xPlayer, isNew, skin) StartServerSyncLoops() end) -RegisterNetEvent('esx:onPlayerLogout') -AddEventHandler('esx:onPlayerLogout', function() +RegisterNetEvent('esx:onPlayerLogout', function() ESX.PlayerLoaded = false end) -RegisterNetEvent('esx:setMaxWeight') -AddEventHandler('esx:setMaxWeight', function(newMaxWeight) ESX.SetPlayerData("maxWeight", newMaxWeight) end) +RegisterNetEvent('esx:setMaxWeight', function(newMaxWeight) + ESX.SetPlayerData('maxWeight', newMaxWeight) +end) local function onPlayerSpawn() ESX.SetPlayerData('ped', PlayerPedId()) + ESX.SetPlayerData('player', PlayerId()) ESX.SetPlayerData('dead', false) end @@ -213,6 +275,7 @@ AddEventHandler('esx:onPlayerSpawn', onPlayerSpawn) AddEventHandler('esx:onPlayerDeath', function() ESX.SetPlayerData('ped', PlayerPedId()) + ESX.SetPlayerData('player', PlayerId()) ESX.SetPlayerData('dead', true) end) @@ -220,11 +283,13 @@ AddEventHandler('skinchanger:modelLoaded', function() while not ESX.PlayerLoaded do Wait(100) end + TriggerEvent('esx:restoreLoadout') end) AddEventHandler('esx:restoreLoadout', function() ESX.SetPlayerData('ped', PlayerPedId()) + ESX.SetPlayerData('player', PlayerId()) if not Config.OxInventory then local ammoTypes = {} @@ -260,28 +325,30 @@ AddStateBagChangeHandler('VehicleProperties', nil, function(bagName, _, value) local netId = bagName:gsub('entity:', '') local timer = GetGameTimer() + while not NetworkDoesEntityExistWithNetworkId(tonumber(netId)) do - Wait(0) if GetGameTimer() - timer > 10000 then return end + + Wait(100) end local vehicle = NetToVeh(tonumber(netId)) local timer2 = GetGameTimer() - while NetworkGetEntityOwner(vehicle) ~= PlayerId() do - Wait(0) + while NetworkGetEntityOwner(vehicle) ~= ESX.PlayerData.player do if GetGameTimer() - timer2 > 10000 then return end + + Wait(100) end ESX.Game.SetVehicleProperties(vehicle, value) end) -RegisterNetEvent('esx:setAccountMoney') -AddEventHandler('esx:setAccountMoney', function(account) - for i = 1, #(ESX.PlayerData.accounts) do +RegisterNetEvent('esx:setAccountMoney', function(account) + for i = 1, #ESX.PlayerData.accounts do if ESX.PlayerData.accounts[i].name == account.name then ESX.PlayerData.accounts[i] = account break @@ -292,8 +359,7 @@ AddEventHandler('esx:setAccountMoney', function(account) end) if not Config.OxInventory then - RegisterNetEvent('esx:addInventoryItem') - AddEventHandler('esx:addInventoryItem', function(item, count, showNotification) + RegisterNetEvent('esx:addInventoryItem', function(item, count, showNotification) for k, v in ipairs(ESX.PlayerData.inventory) do if v.name == item then ESX.UI.ShowInventoryItemNotification(true, v.label, count - v.count) @@ -307,8 +373,7 @@ if not Config.OxInventory then end end) - RegisterNetEvent('esx:removeInventoryItem') - AddEventHandler('esx:removeInventoryItem', function(item, count, showNotification) + RegisterNetEvent('esx:removeInventoryItem', function(item, count, showNotification) for k, v in ipairs(ESX.PlayerData.inventory) do if v.name == item then ESX.UI.ShowInventoryItemNotification(false, v.label, v.count - count) @@ -322,46 +387,39 @@ if not Config.OxInventory then end end) - RegisterNetEvent('esx:addWeapon') - AddEventHandler('esx:addWeapon', function() - print("[^1ERROR^7] event ^5'esx:addWeapon'^7 Has Been Removed. Please use ^5xPlayer.addWeapon^7 Instead!") + RegisterNetEvent('esx:addWeapon', function() + print('[^1ERROR^7] event ^5"esx:addWeapon"^7 Has Been Removed. Please use ^5xPlayer.addWeapon^7 Instead!') end) - RegisterNetEvent('esx:addWeaponComponent') - AddEventHandler('esx:addWeaponComponent', function() - print("[^1ERROR^7] event ^5'esx:addWeaponComponent'^7 Has Been Removed. Please use ^5xPlayer.addWeaponComponent^7 Instead!") + RegisterNetEvent('esx:addWeaponComponent', function() + print('[^1ERROR^7] event ^5"esx:addWeaponComponent"^7 Has Been Removed. Please use ^5xPlayer.addWeaponComponent^7 Instead!') end) - RegisterNetEvent('esx:setWeaponAmmo') - AddEventHandler('esx:setWeaponAmmo', function() - print("[^1ERROR^7] event ^5'esx:setWeaponAmmo'^7 Has Been Removed. Please use ^5xPlayer.addWeaponAmmo^7 Instead!") + RegisterNetEvent('esx:setWeaponAmmo', function() + print('[^1ERROR^7] event ^5"esx:setWeaponAmmo"^7 Has Been Removed. Please use ^5xPlayer.addWeaponAmmo^7 Instead!') end) - RegisterNetEvent('esx:setWeaponTint') - AddEventHandler('esx:setWeaponTint', function(weapon, weaponTintIndex) + RegisterNetEvent('esx:setWeaponTint', function(weapon, weaponTintIndex) SetPedWeaponTintIndex(ESX.PlayerData.ped, joaat(weapon), weaponTintIndex) end) - RegisterNetEvent('esx:removeWeapon') - AddEventHandler('esx:removeWeapon', function() - print("[^1ERROR^7] event ^5'esx:removeWeapon'^7 Has Been Removed. Please use ^5xPlayer.removeWeapon^7 Instead!") + RegisterNetEvent('esx:removeWeapon', function() + print('[^1ERROR^7] event ^5"esx:removeWeapon"^7 Has Been Removed. Please use ^5xPlayer.removeWeapon^7 Instead!') end) - RegisterNetEvent('esx:removeWeaponComponent') - AddEventHandler('esx:removeWeaponComponent', function(weapon, weaponComponent) + RegisterNetEvent('esx:removeWeaponComponent', function(weapon, weaponComponent) local componentHash = ESX.GetWeaponComponent(weapon, weaponComponent).hash + RemoveWeaponComponentFromPed(ESX.PlayerData.ped, joaat(weapon), componentHash) end) end -RegisterNetEvent('esx:setJob') -AddEventHandler('esx:setJob', function(Job) +RegisterNetEvent('esx:setJob', function(Job) ESX.SetPlayerData('job', Job) end) if not Config.OxInventory then - RegisterNetEvent('esx:createPickup') - AddEventHandler('esx:createPickup', function(pickupId, label, coords, itemType, name, components, tintIndex) + RegisterNetEvent('esx:createPickup', function(pickupId, label, coords, itemType, name, components, tintIndex) local function setObjectProperties(object) SetEntityAsMissionEntity(object, true, false) PlaceObjectOnGroundProperly(object) @@ -384,6 +442,7 @@ if not Config.OxInventory then for _, v in ipairs(components) do local component = ESX.GetWeaponComponent(name, v) + GiveWeaponComponentToWeaponObject(pickupObject, component.hash) end @@ -393,17 +452,14 @@ if not Config.OxInventory then end end) - RegisterNetEvent('esx:createMissingPickups') - AddEventHandler('esx:createMissingPickups', function(missingPickups) + RegisterNetEvent('esx:createMissingPickups', function(missingPickups) for pickupId, pickup in pairs(missingPickups) do - TriggerEvent('esx:createPickup', pickupId, pickup.label, vector3(pickup.coords.x, pickup.coords.y, pickup.coords.z - 1.0), pickup.type, pickup.name - , pickup.components, pickup.tintIndex) + TriggerEvent('esx:createPickup', pickupId, pickup.label, vector3(pickup.coords.x, pickup.coords.y, pickup.coords.z - 1.0), pickup.type, pickup.name, pickup.components, pickup.tintIndex) end end) end -RegisterNetEvent('esx:registerSuggestions') -AddEventHandler('esx:registerSuggestions', function(registeredCommands) +RegisterNetEvent('esx:registerSuggestions', function(registeredCommands) for name, command in pairs(registeredCommands) do if command.suggestion then TriggerEvent('chat:addSuggestion', ('/%s'):format(name), command.suggestion.help, command.suggestion.arguments) @@ -412,8 +468,7 @@ AddEventHandler('esx:registerSuggestions', function(registeredCommands) end) if not Config.OxInventory then - RegisterNetEvent('esx:removePickup') - AddEventHandler('esx:removePickup', function(pickupId) + RegisterNetEvent('esx:removePickup', function(pickupId) if pickups[pickupId] and pickups[pickupId].obj then ESX.Game.DeleteObject(pickups[pickupId].obj) pickups[pickupId] = nil @@ -427,12 +482,16 @@ function StartServerSyncLoops() CreateThread(function() local currentWeapon = { Ammo = 0 } + local sleep + while ESX.PlayerLoaded do - local sleep = 1500 + sleep = 1500 + if GetSelectedPedWeapon(ESX.PlayerData.ped) ~= -1569615261 then sleep = 1000 local _, weaponHash = GetCurrentPedWeapon(ESX.PlayerData.ped, true) local weapon = ESX.GetWeaponFromHash(weaponHash) + if weapon then local ammoCount = GetAmmoInPedWeapon(ESX.PlayerData.ped, weaponHash) if weapon.name ~= currentWeapon.name then @@ -446,6 +505,7 @@ function StartServerSyncLoops() end end end + Wait(sleep) end end) @@ -453,41 +513,40 @@ function StartServerSyncLoops() end if not Config.OxInventory and Config.EnableDefaultInventory then - RegisterCommand('showinv', function() + ESX.RegisterInput('showinv', TranslateCap('keymap_showinventory'), 'keyboard', 'F2', function() if not ESX.PlayerData.dead then ESX.ShowInventory() end end) - - RegisterKeyMapping('showinv', TranslateCap('keymap_showinventory'), 'keyboard', 'F2') end -- disable wanted level if not Config.EnableWantedLevel then - ClearPlayerWantedLevel(PlayerId()) + ClearPlayerWantedLevel(ESX.PlayerData.player) SetMaxWantedLevel(0) end if not Config.OxInventory then CreateThread(function() + local sleep, playerCoords, _, closestDistance, distance, label, dict, anim while true do - local Sleep = 1500 - local playerCoords = GetEntityCoords(ESX.PlayerData.ped) - local _, closestDistance = ESX.Game.GetClosestPlayer(playerCoords) + sleep = 1500 + playerCoords = GetEntityCoords(ESX.PlayerData.ped) + _, closestDistance = ESX.Game.GetClosestPlayer(playerCoords) for pickupId, pickup in pairs(pickups) do - local distance = #(playerCoords - pickup.coords) + distance = #(playerCoords - pickup.coords) if distance < 5 then - Sleep = 0 - local label = pickup.label + sleep = 0 + label = pickup.label if distance < 1 then if IsControlJustReleased(0, 38) then if IsPedOnFoot(ESX.PlayerData.ped) and (closestDistance == -1 or closestDistance > 3) and not pickup.inRange then pickup.inRange = true - local dict, anim = 'weapons@first_person@aim_rng@generic@projectile@sticky_bomb@', 'plant_floor' + dict, anim = 'weapons@first_person@aim_rng@generic@projectile@sticky_bomb@', 'plant_floor' ESX.Streaming.RequestAnimDict(dict) TaskPlayAnim(ESX.PlayerData.ped, dict, anim, 8.0, 1.0, 1000, 16, 0.0, false, false, false) RemoveAnimDict(dict) @@ -510,38 +569,28 @@ if not Config.OxInventory then pickup.inRange = false end end - Wait(Sleep) + + Wait(sleep) end end) end ----- Admin commands from esx_adminplus -RegisterNetEvent("esx:tpm") -AddEventHandler("esx:tpm", function() - local GetEntityCoords = GetEntityCoords - local GetGroundZFor_3dCoord = GetGroundZFor_3dCoord - local GetFirstBlipInfoId = GetFirstBlipInfoId - local DoesBlipExist = DoesBlipExist - local DoScreenFadeOut = DoScreenFadeOut - local GetBlipInfoIdCoord = GetBlipInfoIdCoord - local GetVehiclePedIsIn = GetVehiclePedIsIn - - ESX.TriggerServerCallback("esx:isUserAdmin", function(admin) +RegisterNetEvent('esx:tpm', function() + ESX.TriggerServerCallback('esx:isUserAdmin', function(admin) if not admin then return end local blipMarker = GetFirstBlipInfoId(8) if not DoesBlipExist(blipMarker) then - ESX.ShowNotification(TranslateCap('tpm_nowaypoint'), true, false, 140) + ESX.ShowNotification(TranslateCap('tpm_nowaypoint'), 'error') return 'marker' end -- Fade screen to hide how clients get teleported. DoScreenFadeOut(650) - while not IsScreenFadedOut() do - Wait(0) - end + Wait(650) local ped, coords = ESX.PlayerData.ped, GetBlipInfoIdCoord(blipMarker) local vehicle = GetVehiclePedIsIn(ped, false) @@ -549,8 +598,9 @@ AddEventHandler("esx:tpm", function() -- Unpack coords instead of having to unpack them while iterating. -- 825.0 seems to be the max a player can reach while 0.0 being the lowest. - local x, y, groundZ, Z_START = coords['x'], coords['y'], 850.0, 950.0 + local x, y, groundZ, Z_START = coords.x, coords.y, 850.0, 950.0 local found = false + FreezeEntityPosition(vehicle > 0 and vehicle or ped, true) for i = Z_START, 0, -25.0 do @@ -561,12 +611,15 @@ AddEventHandler("esx:tpm", function() NewLoadSceneStart(x, y, z, x, y, z, 50.0, 0) local curTime = GetGameTimer() + while IsNetworkLoadingScene() do if GetGameTimer() - curTime > 1000 then break end + Wait(0) end + NewLoadSceneStop() SetPedCoordsKeepVehicle(ped, x, y, z) @@ -575,6 +628,7 @@ AddEventHandler("esx:tpm", function() if GetGameTimer() - curTime > 1000 then break end + Wait(0) end @@ -585,6 +639,7 @@ AddEventHandler("esx:tpm", function() SetPedCoordsKeepVehicle(ped, x, y, groundZ) break end + Wait(0) end @@ -595,13 +650,13 @@ AddEventHandler("esx:tpm", function() if not found then -- If we can't find the coords, set the coords to the old ones. -- We don't unpack them before since they aren't in a loop and only called once. - SetPedCoordsKeepVehicle(ped, oldCoords['x'], oldCoords['y'], oldCoords['z'] - 1.0) - ESX.ShowNotification(TranslateCap('tpm_success'), true, false, 140) + SetPedCoordsKeepVehicle(ped, oldCoords.x, oldCoords.y, oldCoords.z - 1.0) + ESX.ShowNotification(TranslateCap('tpm_success'), 'sucess') end -- If Z coord was found, set coords in found coords. SetPedCoordsKeepVehicle(ped, x, y, groundZ) - ESX.ShowNotification(TranslateCap('tpm_success'), true, false, 140) + ESX.ShowNotification(TranslateCap('tpm_success'), 'sucess') end) end) @@ -646,13 +701,13 @@ local function noclipThread() if IsControlPressed(1, 173) then noclip_pos = GetOffsetFromEntityInWorldCoords(ESX.PlayerData.ped, 0.0, 0.0, -1.0) end + Wait(0) end end -RegisterNetEvent("esx:noclip") -AddEventHandler("esx:noclip", function() - ESX.TriggerServerCallback("esx:isUserAdmin", function(admin) +RegisterNetEvent('esx:noclip', function() + ESX.TriggerServerCallback('esx:isUserAdmin', function(admin) if not admin then return end @@ -667,43 +722,40 @@ AddEventHandler("esx:noclip", function() CreateThread(noclipThread) end - ESX.ShowNotification(TranslateCap('noclip_message', noclip and Translate('enabled') or Translate('disabled')), true, false, 140) + ESX.ShowNotification(TranslateCap('noclip_message', noclip and Translate('enabled') or Translate('disabled'))) end) end) -RegisterNetEvent("esx:killPlayer") -AddEventHandler("esx:killPlayer", function() +RegisterNetEvent('esx:killPlayer', function() SetEntityHealth(ESX.PlayerData.ped, 0) end) -RegisterNetEvent("esx:repairPedVehicle") -AddEventHandler("esx:repairPedVehicle", function() +RegisterNetEvent('esx:repairPedVehicle', function() local ped = ESX.PlayerData.ped local vehicle = GetVehiclePedIsIn(ped, false) + SetVehicleEngineHealth(vehicle, 1000) - SetVehicleEngineOn(vehicle, true, true) + SetVehicleEngineOn(vehicle, true, true, false) SetVehicleFixed(vehicle) SetVehicleDirtLevel(vehicle, 0) end) -RegisterNetEvent("esx:freezePlayer") -AddEventHandler("esx:freezePlayer", function(input) - local player = PlayerId() +RegisterNetEvent('esx:freezePlayer', function(input) if input == 'freeze' then - SetEntityCollision(ESX.PlayerData.ped, false) + SetEntityCollision(ESX.PlayerData.ped, false, true) FreezeEntityPosition(ESX.PlayerData.ped, true) - SetPlayerInvincible(player, true) + SetPlayerInvincible(ESX.PlayerData.player, true) elseif input == 'unfreeze' then - SetEntityCollision(ESX.PlayerData.ped, true) + SetEntityCollision(ESX.PlayerData.ped, true, true) FreezeEntityPosition(ESX.PlayerData.ped, false) - SetPlayerInvincible(player, false) + SetPlayerInvincible(ESX.PlayerData.player, false) end end) -ESX.RegisterClientCallback("esx:GetVehicleType", function(cb, model) +ESX.RegisterClientCallback('esx:GetVehicleType', function(cb, model) cb(ESX.GetVehicleType(model)) end) -AddStateBagChangeHandler('metadata', 'player:' .. tostring(GetPlayerServerId(PlayerId())), function(_, key, val) +AddStateBagChangeHandler('metadata', 'player:' .. GetPlayerServerId(ESX.PlayerData.player), function(_, key, val) ESX.SetPlayerData(key, val) end) diff --git a/[core]/es_extended/client/modules/actions.lua b/[core]/es_extended/client/modules/actions.lua index 2e4e0e675..0d82ce6c5 100644 --- a/[core]/es_extended/client/modules/actions.lua +++ b/[core]/es_extended/client/modules/actions.lua @@ -1,5 +1,24 @@ +local GetPedInVehicleSeat = GetPedInVehicleSeat +local DoesEntityExist = DoesEntityExist +local GetEntityModel = GetEntityModel +local GetDisplayNameFromVehicleModel = GetDisplayNameFromVehicleModel +local NetworkGetEntityIsNetworked = NetworkGetEntityIsNetworked +local PlayerPedId = PlayerPedId +local TriggerEvent = TriggerEvent +local TriggerServerEvent = TriggerServerEvent +local IsPedJumping = IsPedJumping +local IsPauseMenuActive = IsPauseMenuActive +local IsPlayerDead = IsPlayerDead +local PlayerId = PlayerId +local GetVehiclePedIsTryingToEnter = GetVehiclePedIsTryingToEnter +local GetVehicleNumberPlateText = GetVehicleNumberPlateText +local GetSeatPedIsTryingToEnter = GetSeatPedIsTryingToEnter +local GetVehiclePedIsUsing = GetVehiclePedIsUsing +local IsPedInAnyVehicle = IsPedInAnyVehicle +local Wait = Wait + local isInVehicle, isEnteringVehicle, isJumping, inPauseMenu = false, false, false, false -local playerPed = PlayerPedId() +local playerPed, playerId = PlayerPedId(), PlayerId() local current = {} local function GetPedVehicleSeat(ped, vehicle) @@ -13,27 +32,39 @@ local function GetData(vehicle) if not DoesEntityExist(vehicle) then return end + local model = GetEntityModel(vehicle) local displayName = GetDisplayNameFromVehicleModel(model) local netId = vehicle + if NetworkGetEntityIsNetworked(vehicle) then netId = VehToNet(vehicle) end + return displayName, netId end CreateThread(function() while true do - ESX.SetPlayerData('coords',GetEntityCoords(playerPed)) if playerPed ~= PlayerPedId() then playerPed = PlayerPedId() + ESX.SetPlayerData('ped', playerPed) TriggerEvent('esx:playerPedChanged', playerPed) TriggerServerEvent('esx:playerPedChanged', PedToNet(playerPed)) end + if playerId ~= PlayerId() then + playerId = PlayerId() + + ESX.SetPlayerData('player', playerId) + end + + ESX.SetPlayerData('coords', GetEntityCoords(playerPed)) + if IsPedJumping(playerPed) and not isJumping then isJumping = true + TriggerEvent('esx:playerJumping') TriggerServerEvent('esx:playerJumping') elseif not IsPedJumping(playerPed) and isJumping then @@ -42,29 +73,31 @@ CreateThread(function() if IsPauseMenuActive() and not inPauseMenu then inPauseMenu = true + TriggerEvent('esx:pauseMenuActive', inPauseMenu) elseif not IsPauseMenuActive() and inPauseMenu then inPauseMenu = false + TriggerEvent('esx:pauseMenuActive', inPauseMenu) end - - if not isInVehicle and not IsPlayerDead(PlayerId()) then + if not isInVehicle and (not IsPlayerDead(playerId) and not ESX.PlayerData.dead) then if DoesEntityExist(GetVehiclePedIsTryingToEnter(playerPed)) and not isEnteringVehicle then -- trying to enter a vehicle! + isEnteringVehicle = true local vehicle = GetVehiclePedIsTryingToEnter(playerPed) local plate = GetVehicleNumberPlateText(vehicle) local seat = GetSeatPedIsTryingToEnter(playerPed) local _, netId = GetData(vehicle) - isEnteringVehicle = true + TriggerEvent('esx:enteringVehicle', vehicle, plate, seat, netId) TriggerServerEvent('esx:enteringVehicle', plate, seat, netId) - elseif not DoesEntityExist(GetVehiclePedIsTryingToEnter(playerPed)) and - not IsPedInAnyVehicle(playerPed, true) and isEnteringVehicle then + elseif not DoesEntityExist(GetVehiclePedIsTryingToEnter(playerPed)) and not IsPedInAnyVehicle(playerPed, true) and isEnteringVehicle then -- vehicle entering aborted + isEnteringVehicle = false + TriggerEvent('esx:enteringVehicleAborted') TriggerServerEvent('esx:enteringVehicleAborted') - isEnteringVehicle = false elseif IsPedInAnyVehicle(playerPed, false) then -- suddenly appeared in a vehicle, possible teleport isEnteringVehicle = false @@ -73,11 +106,12 @@ CreateThread(function() current.seat = GetPedVehicleSeat(playerPed, current.vehicle) current.plate = GetVehicleNumberPlateText(current.vehicle) current.displayName, current.netId = GetData(current.vehicle) + TriggerEvent('esx:enteredVehicle', current.vehicle, current.plate, current.seat, current.displayName, current.netId) TriggerServerEvent('esx:enteredVehicle', current.plate, current.seat, current.displayName, current.netId) end elseif isInVehicle then - if not IsPedInAnyVehicle(playerPed, false) or IsPlayerDead(PlayerId()) then + if not IsPedInAnyVehicle(playerPed, false) or (not IsPlayerDead(playerId) and not ESX.PlayerData.dead) then -- bye, vehicle TriggerEvent('esx:exitedVehicle', current.vehicle, current.plate, current.seat, current.displayName, current.netId) TriggerServerEvent('esx:exitedVehicle', current.plate, current.seat, current.displayName, current.netId) @@ -85,6 +119,7 @@ CreateThread(function() current = {} end end + Wait(200) end end) diff --git a/[core]/es_extended/client/modules/callback.lua b/[core]/es_extended/client/modules/callback.lua index e6d38cdc4..90a4f88a5 100644 --- a/[core]/es_extended/client/modules/callback.lua +++ b/[core]/es_extended/client/modules/callback.lua @@ -1,6 +1,6 @@ +---@diagnostic disable: duplicate-set-field local RequestId = 0 local serverRequests = {} - local clientCallbacks = {} ---@param eventName string @@ -9,9 +9,9 @@ local clientCallbacks = {} ESX.TriggerServerCallback = function(eventName, callback, ...) serverRequests[RequestId] = callback - TriggerServerEvent('esx:triggerServerCallback', eventName, RequestId, GetInvokingResource() or "unknown", ...) + TriggerServerEvent('esx:triggerServerCallback', eventName, RequestId, GetInvokingResource() or 'UNKOWN', ...) - RequestId = RequestId + 1 + RequestId += 1 end RegisterNetEvent('esx:serverCallback', function(requestId, invoker, ...) diff --git a/[core]/es_extended/client/modules/death.lua b/[core]/es_extended/client/modules/death.lua index 51d8aec70..43ec5ed92 100644 --- a/[core]/es_extended/client/modules/death.lua +++ b/[core]/es_extended/client/modules/death.lua @@ -1,13 +1,30 @@ +local IsPedAPlayer = IsPedAPlayer +local NetworkGetPlayerIndexFromPed = NetworkGetPlayerIndexFromPed +local IsPedDeadOrDying = IsPedDeadOrDying +local IsPedFatallyInjured = IsPedFatallyInjured +local GetPedSourceOfDeath = GetPedSourceOfDeath +local GetPedCauseOfDeath = GetPedCauseOfDeath +local NetworkIsPlayerActive = NetworkIsPlayerActive +local GetPlayerServerId = GetPlayerServerId +local GetEntityCoords = GetEntityCoords +local GetPlayerPed = GetPlayerPed +local TriggerEvent = TriggerEvent +local TriggerServerEvent = TriggerServerEvent + AddEventHandler('gameEventTriggered', function(event, data) if event ~= 'CEventNetworkEntityDamage' then return end + local victim, victimDied = data[1], data[4] - if not IsPedAPlayer(victim) then return end - local player = PlayerId() - local playerPed = PlayerPedId() - if victimDied and NetworkGetPlayerIndexFromPed(victim) == player and (IsPedDeadOrDying(victim, true) or IsPedFatallyInjured(victim)) then - local killerEntity, deathCause = GetPedSourceOfDeath(playerPed), GetPedCauseOfDeath(playerPed) + if not IsPedAPlayer(victim) then + return + end + + if victimDied and NetworkGetPlayerIndexFromPed(victim) == ESX.PlayerData.player and + (IsPedDeadOrDying(victim, true) or IsPedFatallyInjured(victim) or ESX.PlayerData.dead) then + local killerEntity, deathCause = GetPedSourceOfDeath(ESX.PlayerData.ped), GetPedCauseOfDeath(ESX.PlayerData.ped) local killerClientId = NetworkGetPlayerIndexFromPed(killerEntity) - if killerEntity ~= playerPed and killerClientId and NetworkIsPlayerActive(killerClientId) then + + if killerEntity ~= ESX.PlayerData.ped and killerClientId and NetworkIsPlayerActive(killerClientId) then PlayerKilledByPlayer(GetPlayerServerId(killerClientId), killerClientId, deathCause) else PlayerKilled(deathCause) @@ -16,17 +33,26 @@ AddEventHandler('gameEventTriggered', function(event, data) end) function PlayerKilledByPlayer(killerServerId, killerClientId, deathCause) - local victimCoords = GetEntityCoords(PlayerPedId()) + local victimCoords = GetEntityCoords(ESX.PlayerData.ped) local killerCoords = GetEntityCoords(GetPlayerPed(killerClientId)) local distance = #(victimCoords - killerCoords) local data = { - victimCoords = { x = ESX.Math.Round(victimCoords.x, 1), y = ESX.Math.Round(victimCoords.y, 1), z = ESX.Math.Round(victimCoords.z, 1) }, - killerCoords = { x = ESX.Math.Round(killerCoords.x, 1), y = ESX.Math.Round(killerCoords.y, 1), z = ESX.Math.Round(killerCoords.z, 1) }, + victimCoords = { + x = ESX.Math.Round(victimCoords.x, 3), + y = ESX.Math.Round(victimCoords.y, 3), + z = ESX.Math.Round(victimCoords.z, 3) + }, + + killerCoords = { + x = ESX.Math.Round(killerCoords.x, 3), + y = ESX.Math.Round(killerCoords.y, 3), + z = ESX.Math.Round(killerCoords.z, 3) + }, killedByPlayer = true, deathCause = deathCause, - distance = ESX.Math.Round(distance, 1), + distance = ESX.Math.Round(distance, 3), killerServerId = killerServerId, killerClientId = killerClientId @@ -37,11 +63,14 @@ function PlayerKilledByPlayer(killerServerId, killerClientId, deathCause) end function PlayerKilled(deathCause) - local playerPed = PlayerPedId() - local victimCoords = GetEntityCoords(playerPed) + local victimCoords = GetEntityCoords(ESX.PlayerData.ped) local data = { - victimCoords = { x = ESX.Math.Round(victimCoords.x, 1), y = ESX.Math.Round(victimCoords.y, 1), z = ESX.Math.Round(victimCoords.z, 1) }, + victimCoords = { + x = ESX.Math.Round(victimCoords.x, 3), + y = ESX.Math.Round(victimCoords.y, 3), + z = ESX.Math.Round(victimCoords.z, 3) + }, killedByPlayer = false, deathCause = deathCause diff --git a/[core]/es_extended/client/modules/npwd.lua b/[core]/es_extended/client/modules/npwd.lua index cac2e111f..db2082cd5 100644 --- a/[core]/es_extended/client/modules/npwd.lua +++ b/[core]/es_extended/client/modules/npwd.lua @@ -1,4 +1,5 @@ -local npwd = GetResourceState('npwd'):find('start') and exports.npwd or nil +local GetResourceState = GetResourceState +local npwd = GetResourceState('npwd'):find('start') and exports?.npwd local function checkPhone() if not npwd then @@ -16,7 +17,7 @@ AddEventHandler('onClientResourceStart', function(resource) return end - npwd = GetResourceState('npwd'):find('start') and exports.npwd or nil + npwd = GetResourceState('npwd'):find('start') and exports?.npwd if ESX.PlayerLoaded then checkPhone() @@ -29,6 +30,12 @@ AddEventHandler('onClientResourceStop', function(resource) end end) +AddEventHandler('onResourceStop', function(resource) + if resource == 'npwd' then + npwd = nil + end +end) + RegisterNetEvent('esx:onPlayerLogout', function() if not npwd then return diff --git a/[core]/es_extended/client/modules/scaleform.lua b/[core]/es_extended/client/modules/scaleform.lua index 6ef9357a6..dbedc0985 100644 --- a/[core]/es_extended/client/modules/scaleform.lua +++ b/[core]/es_extended/client/modules/scaleform.lua @@ -1,3 +1,13 @@ +---@diagnostic disable: duplicate-set-field +local BeginScaleformMovieMethod = BeginScaleformMovieMethod +local ScaleformMovieMethodAddParamTextureNameString = ScaleformMovieMethodAddParamTextureNameString +local EndScaleformMovieMethod = EndScaleformMovieMethod +local DrawScaleformMovieFullscreen = DrawScaleformMovieFullscreen +local SetScaleformMovieAsNoLongerNeeded = SetScaleformMovieAsNoLongerNeeded +local ScaleformMovieMethodAddParamFloat = ScaleformMovieMethodAddParamFloat +local ScaleformMovieMethodAddParamBool = ScaleformMovieMethodAddParamBool +local HasScaleformMovieLoaded = HasScaleformMovieLoaded + function ESX.Scaleform.ShowFreemodeMessage(title, msg, sec) local scaleform = ESX.Scaleform.Utils.RequestScaleformMovie('MP_BIG_MESSAGE_FREEMODE') @@ -7,10 +17,10 @@ function ESX.Scaleform.ShowFreemodeMessage(title, msg, sec) EndScaleformMovieMethod() while sec > 0 do - Wait(0) sec = sec - 0.01 - DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255) + DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255, -1) + Wait(0) end SetScaleformMovieAsNoLongerNeeded(scaleform) @@ -38,10 +48,10 @@ function ESX.Scaleform.ShowBreakingNews(title, msg, bottom, sec) EndScaleformMovieMethod() while sec > 0 do - Wait(0) sec = sec - 0.01 - DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255) + DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255, -1) + Wait(0) end SetScaleformMovieAsNoLongerNeeded(scaleform) @@ -61,10 +71,10 @@ function ESX.Scaleform.ShowPopupWarning(title, msg, bottom, sec) EndScaleformMovieMethod() while sec > 0 do - Wait(0) sec = sec - 0.01 - DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255) + DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255, -1) + Wait(0) end SetScaleformMovieAsNoLongerNeeded(scaleform) @@ -74,14 +84,13 @@ function ESX.Scaleform.ShowTrafficMovie(sec) local scaleform = ESX.Scaleform.Utils.RequestScaleformMovie('TRAFFIC_CAM') BeginScaleformMovieMethod(scaleform, 'PLAY_CAM_MOVIE') - EndScaleformMovieMethod() while sec > 0 do - Wait(0) sec = sec - 0.01 - DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255) + DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255, -1) + Wait(0) end SetScaleformMovieAsNoLongerNeeded(scaleform) @@ -91,7 +100,7 @@ function ESX.Scaleform.Utils.RequestScaleformMovie(movie) local scaleform = RequestScaleformMovie(movie) while not HasScaleformMovieLoaded(scaleform) do - Wait(0) + Wait(100) end return scaleform diff --git a/[core]/es_extended/client/modules/streaming.lua b/[core]/es_extended/client/modules/streaming.lua index bde539b28..3899a279b 100644 --- a/[core]/es_extended/client/modules/streaming.lua +++ b/[core]/es_extended/client/modules/streaming.lua @@ -1,3 +1,18 @@ +---@diagnostic disable: duplicate-set-field +local HasModelLoaded = HasModelLoaded +local IsModelInCdimage = IsModelInCdimage +local RequestModel = RequestModel +local HasStreamedTextureDictLoaded = HasStreamedTextureDictLoaded +local RequestStreamedTextureDict = RequestStreamedTextureDict +local HasNamedPtfxAssetLoaded = HasNamedPtfxAssetLoaded +local RequestNamedPtfxAsset = RequestNamedPtfxAsset +local HasAnimSetLoaded = HasAnimSetLoaded +local RequestAnimSet = RequestAnimSet +local HasAnimDictLoaded = HasAnimDictLoaded +local RequestAnimDict = RequestAnimDict +local HasWeaponAssetLoaded = HasWeaponAssetLoaded +local RequestWeaponAsset = RequestWeaponAsset + function ESX.Streaming.RequestModel(modelHash, cb) modelHash = (type(modelHash) == 'number' and modelHash or joaat(modelHash)) @@ -5,25 +20,25 @@ function ESX.Streaming.RequestModel(modelHash, cb) RequestModel(modelHash) while not HasModelLoaded(modelHash) do - Wait(0) + Wait(100) end end - if cb ~= nil then + if cb then cb() end end function ESX.Streaming.RequestStreamedTextureDict(textureDict, cb) if not HasStreamedTextureDictLoaded(textureDict) then - RequestStreamedTextureDict(textureDict) + RequestStreamedTextureDict(textureDict, true) while not HasStreamedTextureDictLoaded(textureDict) do - Wait(0) + Wait(100) end end - if cb ~= nil then + if cb then cb() end end @@ -33,11 +48,11 @@ function ESX.Streaming.RequestNamedPtfxAsset(assetName, cb) RequestNamedPtfxAsset(assetName) while not HasNamedPtfxAssetLoaded(assetName) do - Wait(0) + Wait(100) end end - if cb ~= nil then + if cb then cb() end end @@ -47,11 +62,11 @@ function ESX.Streaming.RequestAnimSet(animSet, cb) RequestAnimSet(animSet) while not HasAnimSetLoaded(animSet) do - Wait(0) + Wait(100) end end - if cb ~= nil then + if cb then cb() end end @@ -61,25 +76,25 @@ function ESX.Streaming.RequestAnimDict(animDict, cb) RequestAnimDict(animDict) while not HasAnimDictLoaded(animDict) do - Wait(0) + Wait(100) end end - if cb ~= nil then + if cb then cb() end end function ESX.Streaming.RequestWeaponAsset(weaponHash, cb) if not HasWeaponAssetLoaded(weaponHash) then - RequestWeaponAsset(weaponHash) + RequestWeaponAsset(weaponHash, 31, 0) while not HasWeaponAssetLoaded(weaponHash) do - Wait(0) + Wait(100) end end - if cb ~= nil then + if cb then cb() end end diff --git a/[core]/es_extended/common/functions.lua b/[core]/es_extended/common/functions.lua index 1bf9f8b76..dbee4e473 100644 --- a/[core]/es_extended/common/functions.lua +++ b/[core]/es_extended/common/functions.lua @@ -1,8 +1,19 @@ +---@diagnostic disable: duplicate-set-field +local GetGameTimer = GetGameTimer + local Charset = {} -for i = 48, 57 do table.insert(Charset, string.char(i)) end -for i = 65, 90 do table.insert(Charset, string.char(i)) end -for i = 97, 122 do table.insert(Charset, string.char(i)) end +for i = 48, 57 do + Charset[#Charset + 1] = string.char(i) +end + +for i = 65, 90 do + Charset[#Charset + 1] = string.char(i) +end + +for i = 97, 122 do + Charset[#Charset + 1] = string.char(i) +end local weaponsByName = {} local weaponsByHash = {} @@ -27,14 +38,14 @@ end function ESX.GetWeapon(weaponName) weaponName = string.upper(weaponName) - assert(weaponsByName[weaponName], "Invalid weapon name!") + assert(weaponsByName[weaponName], 'Invalid weapon name!') local index = weaponsByName[weaponName] return index, Config.Weapons[index] end function ESX.GetWeaponFromHash(weaponHash) - weaponHash = type(weaponHash) == "string" and joaat(weaponHash) or weaponHash + weaponHash = type(weaponHash) == 'string' and joaat(weaponHash) or weaponHash return weaponsByHash[weaponHash] end @@ -46,16 +57,16 @@ end function ESX.GetWeaponLabel(weaponName) weaponName = string.upper(weaponName) - assert(weaponsByName[weaponName], "Invalid weapon name!") + assert(weaponsByName[weaponName], 'Invalid weapon name!') local index = weaponsByName[weaponName] - return Config.Weapons[index].label or "" + return Config.Weapons[index].label or '' end function ESX.GetWeaponComponent(weaponName, weaponComponent) weaponName = string.upper(weaponName) - assert(weaponsByName[weaponName], "Invalid weapon name!") + assert(weaponsByName[weaponName], 'Invalid weapon name!') local weapon = Config.Weapons[weaponsByName[weaponName]] for _, component in ipairs(weapon.components) do @@ -66,27 +77,32 @@ function ESX.GetWeaponComponent(weaponName, weaponComponent) end function ESX.DumpTable(table, nb) - if nb == nil then + if not nb then nb = 0 end if type(table) == 'table' then local s = '' + for _ = 1, nb + 1, 1 do - s = s .. " " + s = s .. ' ' end s = '{\n' for k, v in pairs(table) do - if type(k) ~= 'number' then k = '"' .. k .. '"' end + if type(k) ~= 'number' then + k = '\'' .. k .. '\'' + end + for _ = 1, nb, 1 do - s = s .. " " + s = s .. ' ' end + s = s .. '[' .. k .. '] = ' .. ESX.DumpTable(v, nb + 1) .. ',\n' end for _ = 1, nb, 1 do - s = s .. " " + s = s .. ' ' end return s .. '}' diff --git a/[core]/es_extended/common/modules/math.lua b/[core]/es_extended/common/modules/math.lua index c851c08fb..eb9753cbd 100644 --- a/[core]/es_extended/common/modules/math.lua +++ b/[core]/es_extended/common/modules/math.lua @@ -1,3 +1,4 @@ +---@diagnostic disable: duplicate-set-field ESX.Math = {} function ESX.Math.Round(value, numDecimalPlaces) @@ -20,6 +21,6 @@ function ESX.Math.Trim(value) if value then return (string.gsub(value, "^%s*(.-)%s*$", "%1")) else - return nil + return '' end end diff --git a/[core]/es_extended/common/modules/table.lua b/[core]/es_extended/common/modules/table.lua index 3593b245b..f07739047 100644 --- a/[core]/es_extended/common/modules/table.lua +++ b/[core]/es_extended/common/modules/table.lua @@ -1,3 +1,4 @@ +---@diagnostic disable: duplicate-set-field ESX.Table = {} -- nil proof alternative to #table @@ -13,7 +14,11 @@ end function ESX.Table.Set(t) local set = {} - for _, v in ipairs(t) do set[v] = true end + + for _, v in ipairs(t) do + set[v] = true + end + return set end @@ -44,7 +49,7 @@ function ESX.Table.Find(t, cb) end end - return nil + return end function ESX.Table.FindIndex(t, cb) @@ -62,7 +67,7 @@ function ESX.Table.Filter(t, cb) for i = 1, #t, 1 do if cb(t[i]) then - table.insert(newTable, t[i]) + newTable[#newTable + 1] = t[i] end end @@ -83,14 +88,16 @@ function ESX.Table.Reverse(t) local newTable = {} for i = #t, 1, -1 do - table.insert(newTable, t[i]) + newTable[#newTable + 1] = t[i] end return newTable end function ESX.Table.Clone(t) - if type(t) ~= 'table' then return t end + if type(t) ~= 'table' then + return t + end local meta = getmetatable(t) local target = {} @@ -112,7 +119,7 @@ function ESX.Table.Concat(t1, t2) local t3 = ESX.Table.Clone(t1) for i = 1, #t2, 1 do - table.insert(t3, t2[i]) + t3[#t3 + 1] = t2[i] end return t3 @@ -134,21 +141,17 @@ end -- Credits: https://github.com/JonasDev99/qb-garages/blob/b0335d67cb72a6b9ac60f62a87fb3946f5c2f33d/server/main.lua#L5 function ESX.Table.TableContains(tab, val) - if type(val) == "table" then + if type(val) == 'table' then for _, value in pairs(tab) do if ESX.Table.TableContains(val, value) then return true end end + return false - else - for _, value in pairs(tab) do - if value == val then - return true - end - end end - return false + + return not not tab[val] end -- Credit: https://stackoverflow.com/a/15706820 @@ -175,7 +178,7 @@ function ESX.Table.Sort(t, order) local i = 0 return function() - i = i + 1 + i += 1 if keys[i] then return keys[i], t[keys[i]] end diff --git a/[core]/es_extended/common/modules/timeout.lua b/[core]/es_extended/common/modules/timeout.lua index 814b086ce..35e2e7963 100644 --- a/[core]/es_extended/common/modules/timeout.lua +++ b/[core]/es_extended/common/modules/timeout.lua @@ -1,3 +1,4 @@ +---@diagnostic disable: duplicate-set-field local TimeoutCount = 0 local CancelledTimeouts = {} diff --git a/[core]/es_extended/config.lua b/[core]/es_extended/config.lua index 574876b3c..91246562d 100644 --- a/[core]/es_extended/config.lua +++ b/[core]/es_extended/config.lua @@ -1,38 +1,46 @@ -Config = {} -Config.Locale = GetConvar('esx:locale', 'en') +Config = {} +Config.Locale = GetConvar('esx:locale', 'en') -Config.Accounts = { +Config.Accounts = { bank = { label = TranslateCap('account_bank'), round = true }, + black_money = { label = TranslateCap('account_black_money'), round = true }, + money = { label = TranslateCap('account_money'), round = true } } -Config.StartingAccountMoney = { bank = 50000 } +Config.StartingAccountMoney = { + bank = 50000 +} Config.StartingInventoryItems = false -- table/false Config.DefaultSpawns = { -- If you want to have more spawn positions and select them randomly uncomment commented code or add more locations { x = 222.2027, y = -864.0162, z = 30.2922, heading = 1.0 }, - --{x = 224.9865, y = -865.0871, z = 30.2922, heading = 1.0}, - --{x = 227.8436, y = -866.0400, z = 30.2922, heading = 1.0}, - --{x = 230.6051, y = -867.1450, z = 30.2922, heading = 1.0}, - --{x = 233.5459, y = -868.2626, z = 30.2922, heading = 1.0} + -- {x = 224.9865, y = -865.0871, z = 30.2922, heading = 1.0}, + -- {x = 227.8436, y = -866.0400, z = 30.2922, heading = 1.0}, + -- {x = 230.6051, y = -867.1450, z = 30.2922, heading = 1.0}, + -- {x = 233.5459, y = -868.2626, z = 30.2922, heading = 1.0} } Config.AdminGroups = { - ['owner'] = true, - ['admin'] = true + DEFAULT_GROUP = 'admin', + + owner = true, + admin = true } +Config.MapName = 'San Andreas' -- Map name +Config.GameType = 'ESX Legacy' -- Game type Config.EnablePaycheck = true -- enable paycheck Config.LogPaycheck = false -- Logs paychecks to a nominated Discord channel via webhook (default is false) @@ -44,7 +52,7 @@ Config.EnableDefaultInventory = true -- Display the default Inventory ( Config.EnableWantedLevel = false -- Use Normal GTA wanted Level? Config.EnablePVP = true -- Allow Player to player combat -Config.Multichar = GetResourceState("esx_multicharacter") ~= "missing" +Config.Multichar = GetResourceState('esx_multicharacter') ~= 'missing' Config.Identity = true -- Select a characters identity data before they have loaded in (this happens by default with multichar) Config.DistanceGive = 4.0 -- Max distance when giving items, weapons etc. diff --git a/[core]/es_extended/fxmanifest.lua b/[core]/es_extended/fxmanifest.lua index 8c7306869..3a33d3c72 100644 --- a/[core]/es_extended/fxmanifest.lua +++ b/[core]/es_extended/fxmanifest.lua @@ -16,6 +16,7 @@ shared_scripts { server_scripts { '@oxmysql/lib/MySQL.lua', 'config.logs.lua', + 'server/common.lua', 'server/modules/callback.lua', 'server/classes/player.lua', diff --git a/[core]/es_extended/imports.lua b/[core]/es_extended/imports.lua index 7a7933010..1ea3b4a6f 100644 --- a/[core]/es_extended/imports.lua +++ b/[core]/es_extended/imports.lua @@ -1,12 +1,13 @@ +---@diagnostic disable: missing-fields ESX = exports['es_extended']:getSharedObject() if not IsDuplicityVersion() then -- Only register this event for the client AddEventHandler('esx:setPlayerData', function(key, val, last) if GetInvokingResource() == 'es_extended' then ESX.PlayerData[key] = val - if OnPlayerData then - OnPlayerData(key, val, last) - end + -- if OnPlayerData then not used? + -- OnPlayerData(key, val, last) + -- end end end) diff --git a/[core]/es_extended/locale.lua b/[core]/es_extended/locale.lua index a5e2207ea..4671d4ec8 100644 --- a/[core]/es_extended/locale.lua +++ b/[core]/es_extended/locale.lua @@ -1,10 +1,13 @@ +local GetInvokingResource = GetInvokingResource +local GetCurrentResourceName = GetCurrentResourceName Locales = {} function Translate(str, ...) -- Translate string if not str then - print(("[^1ERROR^7] Resource ^5%s^7 You did not specify a parameter for the Translate function or the value is nil!"):format(GetInvokingResource() or GetCurrentResourceName())) + print(('[^1ERROR^7] Resource ^5%s^7 You did not specify a parameter for the Translate function or the value is nil!'):format(GetInvokingResource() or GetCurrentResourceName())) return 'Given translate function parameter is nil!' end + if Locales[Config.Locale] then if Locales[Config.Locale][str] then return string.format(Locales[Config.Locale][str], ...) @@ -21,7 +24,7 @@ function Translate(str, ...) -- Translate string end function TranslateCap(str, ...) -- Translate string first char uppercase - return _(str, ...):gsub("^%l", string.upper) + return _(str, ...):gsub('^%l', string.upper) end _ = Translate diff --git a/[core]/es_extended/locales/cs.lua b/[core]/es_extended/locales/cs.lua index e658fc612..119833005 100644 --- a/[core]/es_extended/locales/cs.lua +++ b/[core]/es_extended/locales/cs.lua @@ -95,6 +95,7 @@ Locales["cs"] = { ['command_setcoords_x'] = 'Hodnota X', ['command_setcoords_y'] = 'Hodnota Y', ['command_setcoords_z'] = 'Hodnota Z', + ['command_setcoords_h'] = 'Heading value', ['command_setjob'] = 'Nastavit práci hráči', ['command_setjob_job'] = 'Název práce', ['command_setjob_grade'] = 'Pozice ve firmě', diff --git a/[core]/es_extended/locales/de.lua b/[core]/es_extended/locales/de.lua index 52f4dd16c..f8a8bda66 100644 --- a/[core]/es_extended/locales/de.lua +++ b/[core]/es_extended/locales/de.lua @@ -95,6 +95,7 @@ Locales["de"] = { ['command_setcoords_x'] = 'X Koordinate', ['command_setcoords_y'] = 'Y Koordinate', ['command_setcoords_z'] = 'Z Koordinate', + ['command_setcoords_h'] = 'Heading Koordinate', ['command_setjob'] = 'Job eines Spielers setzen', ['command_setjob_job'] = 'Name', ['command_setjob_grade'] = 'Job Grad', diff --git a/[core]/es_extended/locales/el.lua b/[core]/es_extended/locales/el.lua index 7bca2071a..6bd2cae95 100644 --- a/[core]/es_extended/locales/el.lua +++ b/[core]/es_extended/locales/el.lua @@ -99,6 +99,7 @@ Locales["el"] = { ['command_setcoords_x'] = 'Τιμή X', ['command_setcoords_y'] = 'Τιμή Y', ['command_setcoords_z'] = 'Τιμή Z', + ['command_setcoords_h'] = 'Heading value', ['command_setjob'] = 'Ορίστε το επάγγελμα ενός παίκτη', ['command_setjob_job'] = 'Όνομα', ['command_setjob_grade'] = 'Βαθμός επαγγέλματος', diff --git a/[core]/es_extended/locales/en.lua b/[core]/es_extended/locales/en.lua index 81eb738b7..88b1ea721 100644 --- a/[core]/es_extended/locales/en.lua +++ b/[core]/es_extended/locales/en.lua @@ -99,6 +99,7 @@ Locales["en"] = { ['command_setcoords_x'] = 'X value', ['command_setcoords_y'] = 'Y value', ['command_setcoords_z'] = 'Z value', + ['command_setcoords_h'] = 'Heading value', ['command_setjob'] = 'Set a player`s job', ['command_setjob_job'] = 'Name', ['command_setjob_grade'] = 'Job grade', diff --git a/[core]/es_extended/locales/es.lua b/[core]/es_extended/locales/es.lua index 9a3791a09..26e108bd1 100644 --- a/[core]/es_extended/locales/es.lua +++ b/[core]/es_extended/locales/es.lua @@ -95,6 +95,7 @@ Locales["es"] = { ['command_setcoords_x'] = 'Eje X', ['command_setcoords_y'] = 'Eje Y', ['command_setcoords_z'] = 'Eje Z', + ['command_setcoords_h'] = 'Heading value', ['command_setjob'] = 'Dar un trabajo a un jugador', ['command_setjob_job'] = 'Nombre del trabajo', ['command_setjob_grade'] = 'Rango del trabajo', diff --git a/[core]/es_extended/locales/fi.lua b/[core]/es_extended/locales/fi.lua index bd32d952d..6de126c91 100644 --- a/[core]/es_extended/locales/fi.lua +++ b/[core]/es_extended/locales/fi.lua @@ -90,6 +90,7 @@ Locales["fi"] = { ['command_setcoords_x'] = 'x akseli', ['command_setcoords_y'] = 'y akseli', ['command_setcoords_z'] = 'z akseli', + ['command_setcoords_h'] = 'Heading value', ['command_setjob'] = 'Aseta pelaajalle työ', ['command_setjob_job'] = 'Työ', ['command_setjob_grade'] = 'Arvo', diff --git a/[core]/es_extended/locales/fr.lua b/[core]/es_extended/locales/fr.lua index 3dedf7928..e4f331943 100644 --- a/[core]/es_extended/locales/fr.lua +++ b/[core]/es_extended/locales/fr.lua @@ -99,6 +99,7 @@ Locales["fr"] = { ["command_setcoords_x"] = "Valeur de l'axe X", ["command_setcoords_y"] = "Valeur de l'axe Y", ["command_setcoords_z"] = "Valeur de l'axe Z", + ['command_setcoords_h'] = 'Heading value', ["command_setjob"] = "Définir le métier d'un joueur", ["command_setjob_job"] = "Nom du métier à définir", ["command_setjob_grade"] = "Grade du métier", diff --git a/[core]/es_extended/locales/he.lua b/[core]/es_extended/locales/he.lua index c2bafc991..e33d34adf 100644 --- a/[core]/es_extended/locales/he.lua +++ b/[core]/es_extended/locales/he.lua @@ -95,6 +95,7 @@ Locales["he"] = { ['command_setcoords_x'] = 'ערך X', ['command_setcoords_y'] = 'ערך Y', ['command_setcoords_z'] = 'ערך Z', + ['command_setcoords_h'] = 'Heading value', ['command_setjob'] = 'הגדר את העבודה של השחקן', ['command_setjob_job'] = 'שם', ['command_setjob_grade'] = 'דרגת עבודה', diff --git a/[core]/es_extended/locales/hu.lua b/[core]/es_extended/locales/hu.lua index 02feb4ed6..246c77338 100644 --- a/[core]/es_extended/locales/hu.lua +++ b/[core]/es_extended/locales/hu.lua @@ -95,6 +95,7 @@ Locales["hu"] = { ["command_setcoords_x"] = "X érték", ["command_setcoords_y"] = "Y érték", ["command_setcoords_z"] = "Z érték", + ['command_setcoords_h'] = 'Heading value', ["command_setjob"] = "Játékos munkájának beállítása", ["command_setjob_job"] = "Munka neve", ["command_setjob_grade"] = "Rang", diff --git a/[core]/es_extended/locales/it.lua b/[core]/es_extended/locales/it.lua index 227978cc2..5a5b39513 100644 --- a/[core]/es_extended/locales/it.lua +++ b/[core]/es_extended/locales/it.lua @@ -99,6 +99,7 @@ Locales["it"] = { ['command_setcoords_x'] = 'Valore X', ['command_setcoords_y'] = 'Valore Y', ['command_setcoords_z'] = 'Valore Z', + ['command_setcoords_h'] = 'Heading value', ['command_setjob'] = 'Setta lavoro ad un giocatore', ['command_setjob_job'] = 'Nome', ['command_setjob_grade'] = 'Grado lavoro', diff --git a/[core]/es_extended/locales/nl.lua b/[core]/es_extended/locales/nl.lua index 938303f52..dafdcf3b9 100644 --- a/[core]/es_extended/locales/nl.lua +++ b/[core]/es_extended/locales/nl.lua @@ -91,6 +91,7 @@ Locales["nl"] = { ['command_setcoords_x'] = 'X waarde', ['command_setcoords_y'] = 'Y waarde', ['command_setcoords_z'] = 'Z waarde', + ['command_setcoords_h'] = 'Heading value', ['command_setjob'] = 'Zet een speler zijn / haar job', ['command_setjob_job'] = 'Naam', ['command_setjob_grade'] = 'Job grade', diff --git a/[core]/es_extended/locales/pl.lua b/[core]/es_extended/locales/pl.lua index d738239a5..c2c7f4fc7 100644 --- a/[core]/es_extended/locales/pl.lua +++ b/[core]/es_extended/locales/pl.lua @@ -89,6 +89,7 @@ Locales["pl"] = { ['command_setcoords_x'] = 'x axis', ['command_setcoords_y'] = 'y axis', ['command_setcoords_z'] = 'z axis', + ['command_setcoords_h'] = 'Heading value', ['command_setjob'] = 'ustaw prace dla gracza', ['command_setjob_job'] = 'nazwa pracy', ['command_setjob_grade'] = 'stanowisko w pracy', diff --git a/[core]/es_extended/locales/sl.lua b/[core]/es_extended/locales/sl.lua index 0fe41be5d..ba6e9f5df 100644 --- a/[core]/es_extended/locales/sl.lua +++ b/[core]/es_extended/locales/sl.lua @@ -95,6 +95,7 @@ Locales["sl"] = { ['command_setcoords_x'] = 'Vrednost X', ['command_setcoords_y'] = 'Vrednost Y', ['command_setcoords_z'] = 'Z vrednost', + ['command_setcoords_h'] = 'Heading value', ['command_setjob'] = 'Nastavi opravilo igralca', ['command_setjob_job'] = 'Ime', ['command_setjob_grade'] = 'Delovna ocena', diff --git a/[core]/es_extended/locales/sr.lua b/[core]/es_extended/locales/sr.lua index 2813b8468..a141d09ea 100644 --- a/[core]/es_extended/locales/sr.lua +++ b/[core]/es_extended/locales/sr.lua @@ -95,6 +95,7 @@ Locales["sr"] = { ['command_setcoords_x'] = 'X', ['command_setcoords_y'] = 'Y', ['command_setcoords_z'] = 'Z', + ['command_setcoords_h'] = 'Heading value', ['command_setjob'] = 'Postavite posao igraču', ['command_setjob_job'] = 'Ime', ['command_setjob_grade'] = 'Stepen posla', diff --git a/[core]/es_extended/locales/zh-cn.lua b/[core]/es_extended/locales/zh-cn.lua index e5093c258..df4bfe34c 100644 --- a/[core]/es_extended/locales/zh-cn.lua +++ b/[core]/es_extended/locales/zh-cn.lua @@ -95,6 +95,7 @@ Locales["zh-cn"] = { ['command_setcoords_x'] = 'X 轴', ['command_setcoords_y'] = 'Y 轴', ['command_setcoords_z'] = 'Z 轴', + ['command_setcoords_h'] = 'Heading value', ['command_setjob'] = '配置该玩家职业', ['command_setjob_job'] = '职业代码', ['command_setjob_grade'] = '职业等级', diff --git a/[core]/es_extended/server/classes/overrides/oxinventory.lua b/[core]/es_extended/server/classes/overrides/oxinventory.lua index 85a1a4392..446cb7aba 100644 --- a/[core]/es_extended/server/classes/overrides/oxinventory.lua +++ b/[core]/es_extended/server/classes/overrides/oxinventory.lua @@ -1,3 +1,4 @@ +local TriggerEvent = TriggerEvent local Inventory if Config.OxInventory then diff --git a/[core]/es_extended/server/classes/player.lua b/[core]/es_extended/server/classes/player.lua index 49b600cf7..146f3f32f 100644 --- a/[core]/es_extended/server/classes/player.lua +++ b/[core]/es_extended/server/classes/player.lua @@ -1,5 +1,16 @@ local GetPlayerPed = GetPlayerPed local GetEntityCoords = GetEntityCoords +local ExecuteCommand = ExecuteCommand +local TriggerClientEvent = TriggerClientEvent +local SetEntityCoords = SetEntityCoords +local SetEntityHeading = SetEntityHeading +local DropPlayer = DropPlayer +local TriggerEvent = TriggerEvent +local GiveWeaponToPed = GiveWeaponToPed +local GiveWeaponComponentToPed = GiveWeaponComponentToPed +local SetPedAmmo = SetPedAmmo +local RemoveWeaponFromPed = RemoveWeaponFromPed +local print = print function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, weight, job, loadout, name, coords, metadata) local targetOverrides = Config.PlayerFunctionOverride and Core.PlayerFunctionOverrides[Config.PlayerFunctionOverride] or {} @@ -21,28 +32,31 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, self.maxWeight = Config.MaxWeight self.metadata = metadata self.admin = Core.IsPlayerAdmin(playerId) - if Config.Multichar then self.license = 'license' .. identifier:sub(identifier:find(':'), identifier:len()) else self.license = 'license:' .. identifier end + + if Config.Multichar then + self.license = 'license' .. identifier:sub(identifier:find(':'), identifier:len()) else self.license = 'license:' .. identifier + end ExecuteCommand(('add_principal identifier.%s group.%s'):format(self.license, self.group)) local stateBag = Player(self.source).state - stateBag:set("identifier", self.identifier, true) - stateBag:set("license", self.license, true) - stateBag:set("job", self.job, true) - stateBag:set("group", self.group, true) - stateBag:set("name", self.name, true) - stateBag:set("metadata", self.metadata, true) + stateBag:set('identifier', self.identifier, true) + stateBag:set('license', self.license, true) + stateBag:set('job', self.job, true) + stateBag:set('group', self.group, true) + stateBag:set('name', self.name, true) + stateBag:set('metadata', self.metadata, true) function self.triggerEvent(eventName, ...) TriggerClientEvent(eventName, self.source, ...) end function self.setCoords(coordinates) - local Ped = GetPlayerPed(self.source) - local vector = type(coordinates) == "vector4" and coordinates or type(coordinates) == "vector3" and vector4(coordinates, 0.0) or - vec(coordinates.x, coordinates.y, coordinates.z, coordinates.heading or 0.0) - SetEntityCoords(Ped, vector.xyz, false, false, false, false) - SetEntityHeading(Ped, vector.w) + local ped = GetPlayerPed(self.source) + local vector = type(coordinates) == 'vector4' and coordinates or type(coordinates) == 'vector3' and vector4(coordinates, 0.0) or vec(coordinates.x, coordinates.y, coordinates.z, coordinates.heading or 0.0) + + SetEntityCoords(ped, vector.x, vector.y, vector.z, false, false, false, false) + SetEntityHeading(ped, vector.w) end function self.getCoords(vector) @@ -65,8 +79,7 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, end function self.setMoney(money) - money = ESX.Math.Round(money) - self.setAccountMoney('money', money) + self.setAccountMoney('money', ESX.Math.Round(money)) end function self.getMoney() @@ -74,13 +87,11 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, end function self.addMoney(money, reason) - money = ESX.Math.Round(money) - self.addAccountMoney('money', money, reason) + self.addAccountMoney('money', ESX.Math.Round(money), reason) end function self.removeMoney(money, reason) - money = ESX.Math.Round(money) - self.removeAccountMoney('money', money, reason) + self.removeAccountMoney('money', ESX.Math.Round(money), reason) end function self.getIdentifier() @@ -90,7 +101,7 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, function self.setGroup(newGroup) ExecuteCommand(('remove_principal identifier.%s group.%s'):format(self.license, self.group)) self.group = newGroup - Player(self.source).state:set("group", self.group, true) + Player(self.source).state:set('group', self.group, true) ExecuteCommand(('add_principal identifier.%s group.%s'):format(self.license, self.group)) end @@ -127,7 +138,8 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, return self.accounts[i] end end - return nil + + return {} end function self.getInventory(minimal) @@ -154,11 +166,17 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, if not minimal then return self.loadout end + local minimalLoadout = {} for _, v in ipairs(self.loadout) do - minimalLoadout[v.name] = { ammo = v.ammo } - if v.tintIndex > 0 then minimalLoadout[v.name].tintIndex = v.tintIndex end + minimalLoadout[v.name] = { + ammo = v.ammo + } + + if v.tintIndex > 0 then + minimalLoadout[v.name].tintIndex = v.tintIndex + end if #v.components > 0 then local components = {} @@ -184,15 +202,16 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, function self.setName(newName) self.name = newName - Player(self.source).state:set("name", self.name, true) + Player(self.source).state:set('name', self.name, true) end function self.setAccountMoney(accountName, money, reason) - reason = reason or 'unknown' + reason = reason or 'UNKOWN' + if not tonumber(money) then - print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) - return + return print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.source, money)) end + if money >= 0 then local account = self.getAccount(accountName) @@ -203,21 +222,23 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, self.triggerEvent('esx:setAccountMoney', account) TriggerEvent('esx:setAccountMoney', self.source, accountName, money, reason) else - print(('[^1ERROR^7] Tried To Set Invalid Account ^5%s^0 For Player ^5%s^0!'):format(accountName, self.playerId)) + print(('[^1ERROR^7] Tried To Set Invalid Account ^5%s^0 For Player ^5%s^0!'):format(accountName, self.source)) end else - print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) + print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.source, money)) end end function self.addAccountMoney(accountName, money, reason) - reason = reason or 'Unknown' + reason = reason or 'UNKOWN' + if not tonumber(money) then - print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) - return + return print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.source, money)) end + if money > 0 then local account = self.getAccount(accountName) + if account then money = account.round and ESX.Math.Round(money) or money self.accounts[account.index].money = self.accounts[account.index].money + money @@ -225,18 +246,18 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, self.triggerEvent('esx:setAccountMoney', account) TriggerEvent('esx:addAccountMoney', self.source, accountName, money, reason) else - print(('[^1ERROR^7] Tried To Set Add To Invalid Account ^5%s^0 For Player ^5%s^0!'):format(accountName, self.playerId)) + print(('[^1ERROR^7] Tried To Set Add To Invalid Account ^5%s^0 For Player ^5%s^0!'):format(accountName, self.source)) end else - print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) + print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.source, money)) end end function self.removeAccountMoney(accountName, money, reason) - reason = reason or 'Unknown' + reason = reason or 'UNKOWN' + if not tonumber(money) then - print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) - return + return print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.source, money)) end if money > 0 then local account = self.getAccount(accountName) @@ -248,10 +269,10 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, self.triggerEvent('esx:setAccountMoney', account) TriggerEvent('esx:removeAccountMoney', self.source, accountName, money, reason) else - print(('[^1ERROR^7] Tried To Set Add To Invalid Account ^5%s^0 For Player ^5%s^0!'):format(accountName, self.playerId)) + print(('[^1ERROR^7] Tried To Set Add To Invalid Account ^5%s^0 For Player ^5%s^0!'):format(accountName, self.source)) end else - print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) + print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.source, money)) end end @@ -281,6 +302,7 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, if item then count = ESX.Math.Round(count) + if count > 0 then local newCount = item.count - count @@ -292,7 +314,7 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, self.triggerEvent('esx:removeInventoryItem', item.name, item.count) end else - print(('[^1ERROR^7] Player ID:^5%s Tried remove a Invalid count -> %s of %s'):format(self.playerId, count, itemName)) + print(('[^1ERROR^7] Player ID:^5%s Tried remove a Invalid count -> %s of %s'):format(self.source, count, itemName)) end end end @@ -326,7 +348,7 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, return newWeight <= self.maxWeight else - print(('[^3WARNING^7] Item ^5"%s"^7 was used but does not exist!'):format(itemName)) + print(('[^3WARNING^7] Item ^5\'%s\'^7 was used but does not exist!'):format(itemName)) end end @@ -379,7 +401,7 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, TriggerEvent('esx:setJob', self.source, self.job, lastJob) self.triggerEvent('esx:setJob', self.job, lastJob) - Player(self.source).state:set("job", self.job, true) + Player(self.source).state:set('job', self.job, true) else print(('[es_extended] [^3WARNING^7] Ignoring invalid ^5.setJob()^7 usage for ID: ^5%s^7, Job: ^5%s^7'):format(self.source, job)) end @@ -389,13 +411,13 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, if not self.hasWeapon(weaponName) then local weaponLabel = ESX.GetWeaponLabel(weaponName) - table.insert(self.loadout, { + self.loadout[#self.loadout + 1] = { name = weaponName, ammo = ammo, label = weaponLabel, components = {}, tintIndex = 0 - }) + } GiveWeaponToPed(GetPlayerPed(self.source), joaat(weaponName), ammo, false, false) self.triggerEvent('esx:addInventoryItem', weaponLabel, false, true) @@ -464,7 +486,7 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, local weaponLabel, playerPed = nil, GetPlayerPed(self.source) if not playerPed then - return print("[^1ERROR^7] xPlayer.removeWeapon ^5invalid^7 player ped!") + return print('[^1ERROR^7] xPlayer.removeWeapon ^5invalid^7 player ped!') end for k, v in ipairs(self.loadout) do @@ -500,7 +522,7 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, if self.hasWeaponComponent(weaponName, weaponComponent) then for k, v in ipairs(self.loadout[loadoutNum].components) do if v == weaponComponent then - table.remove(self.loadout[loadoutNum].components, k) + self.loadout[loadoutNum].components[k] = nil break end end @@ -538,31 +560,15 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, end function self.hasWeapon(weaponName) - for _, v in ipairs(self.loadout) do - if v.name == weaponName then - return true - end - end - - return false + return not not self.loadout[weaponName] end function self.hasItem(item) - for _, v in ipairs(self.inventory) do - if (v.name == item) and (v.count >= 1) then - return v, v.count - end - end - - return false + return self.inventory?[item] > 0 end function self.getWeapon(weaponName) - for k, v in ipairs(self.loadout) do - if v.name == weaponName then - return k, v - end - end + return self.loadout[weaponName] end function self.showNotification(msg, notifyType, length) @@ -580,39 +586,39 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, function self.getMeta(index, subIndex) if not (index) then return self.metadata end - if type(index) ~= "string" then - return print("[^1ERROR^7] xPlayer.getMeta ^5index^7 should be ^5string^7!") + if type(index) ~= 'string' then + return print('[^1ERROR^7] xPlayer.getMeta ^5index^7 should be ^5string^7!') end local metaData = self.metadata[index] - if (metaData == nil) then - return Config.EnableDebug and print(("[^1ERROR^7] xPlayer.getMeta ^5%s^7 not exist!"):format(index)) or nil + if not metaData then + return Config.EnableDebug and print(('[^1ERROR^7] xPlayer.getMeta ^5%s^7 not exist!'):format(index)) or nil end - if (subIndex and type(metaData) == "table") then + if subIndex and type(metaData) == 'table' then local _type = type(subIndex) - if (_type == "string") then + if _type == 'string' then local value = metaData[subIndex] return value end - if (_type == "table") then + if _type == 'table' then local returnValues = {} for i = 1, #subIndex do local key = subIndex[i] - if (type(key) == "string") then + if type(key) == 'string' then returnValues[key] = self.getMeta(index, key) else - print(("[^1ERROR^7] xPlayer.getMeta subIndex should be ^5string^7 or ^5table^7! that contains ^5string^7, received ^5%s^7!, skipping..."):format(type(key))) + print(('[^1ERROR^7] xPlayer.getMeta subIndex should be ^5string^7 or ^5table^7! that contains ^5string^7, received ^5%s^7!, skipping...'):format(type(key))) end end return returnValues end - return print(("[^1ERROR^7] xPlayer.getMeta subIndex should be ^5string^7 or ^5table^7!, received ^5%s^7!"):format(_type)) + return print(('[^1ERROR^7] xPlayer.getMeta subIndex should be ^5string^7 or ^5table^7!, received ^5%s^7!'):format(_type)) end return metaData @@ -620,31 +626,31 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, function self.setMeta(index, value, subValue) if not index then - return print("[^1ERROR^7] xPlayer.setMeta ^5index^7 is Missing!") + return print('[^1ERROR^7] xPlayer.setMeta ^5index^7 is Missing!') end - if type(index) ~= "string" then - return print("[^1ERROR^7] xPlayer.setMeta ^5index^7 should be ^5string^7!") + if type(index) ~= 'string' then + return print('[^1ERROR^7] xPlayer.setMeta ^5index^7 should be ^5string^7!') end if not value then - return print(("[^1ERROR^7] xPlayer.setMeta ^5%s^7 is Missing!"):format(value)) + return print(('[^1ERROR^7] xPlayer.setMeta ^5%s^7 is Missing!'):format(value)) end local _type = type(value) if not subValue then - if _type ~= "number" and _type ~= "string" and _type ~= "table" then - return print(("[^1ERROR^7] xPlayer.setMeta ^5%s^7 should be ^5number^7 or ^5string^7 or ^5table^7!"):format(value)) + if _type ~= 'number' and _type ~= 'string' and _type ~= 'table' then + return print(('[^1ERROR^7] xPlayer.setMeta ^5%s^7 should be ^5number^7 or ^5string^7 or ^5table^7!'):format(value)) end self.metadata[index] = value else - if _type ~= "string" then - return print(("[^1ERROR^7] xPlayer.setMeta ^5value^7 should be ^5string^7 as a subIndex!"):format(value)) + if _type ~= 'string' then + return print(('[^1ERROR^7] xPlayer.setMeta ^5value^7 should be ^5string^7 as a subIndex!'):format(value)) end - if not self.metadata[index] or type(self.metadata[index]) ~= "table" then + if not self.metadata[index] or type(self.metadata[index]) ~= 'table' then self.metadata[index] = { } end @@ -657,46 +663,46 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, function self.clearMeta(index, subValues) if not index then - return print("[^1ERROR^7] xPlayer.clearMeta ^5index^7 is Missing!") + return print('[^1ERROR^7] xPlayer.clearMeta ^5index^7 is Missing!') end - - if type(index) ~= "string" then - return print("[^1ERROR^7] xPlayer.clearMeta ^5index^7 should be ^5string^7!") + + if type(index) ~= 'string' then + return print('[^1ERROR^7] xPlayer.clearMeta ^5index^7 should be ^5string^7!') end - + local metaData = self.metadata[index] if metaData == nil then - return Config.EnableDebug and print(("[^1ERROR^7] xPlayer.clearMeta ^5%s^7 does not exist!"):format(index)) or nil + return Config.EnableDebug and print(('[^1ERROR^7] xPlayer.clearMeta ^5%s^7 does not exist!'):format(index)) or nil end - + if not subValues then -- If no subValues is provided, we will clear the entire value in the metaData table self.metadata[index] = nil - elseif type(subValues) == "string" then + elseif type(subValues) == 'string' then -- If subValues is a string, we will clear the specific subValue within the table - if type(metaData) == "table" then + if type(metaData) == 'table' then metaData[subValues] = nil else - return print(("[^1ERROR^7] xPlayer.clearMeta ^5%s^7 is not a table! Cannot clear subValue ^5%s^7."):format(index, subValues)) + return print(('[^1ERROR^7] xPlayer.clearMeta ^5%s^7 is not a table! Cannot clear subValue ^5%s^7.'):format(index, subValues)) end - elseif type(subValues) == "table" then + elseif type(subValues) == 'table' then -- If subValues is a table, we will clear multiple subValues within the table for i = 1, #subValues do local subValue = subValues[i] - if type(subValue) == "string" then - if type(metaData) == "table" then + if type(subValue) == 'string' then + if type(metaData) == 'table' then metaData[subValue] = nil else - print(("[^1ERROR^7] xPlayer.clearMeta ^5%s^7 is not a table! Cannot clear subValue ^5%s^7."):format(index, subValue)) + print(('[^1ERROR^7] xPlayer.clearMeta ^5%s^7 is not a table! Cannot clear subValue ^5%s^7.'):format(index, subValue)) end else - print(("[^1ERROR^7] xPlayer.clearMeta subValues should contain ^5string^7, received ^5%s^7, skipping..."):format(type(subValue))) + print(('[^1ERROR^7] xPlayer.clearMeta subValues should contain ^5string^7, received ^5%s^7, skipping...'):format(type(subValue))) end end else - return print(("[^1ERROR^7] xPlayer.clearMeta ^5subValues^7 should be ^5string^7 or ^5table^7, received ^5%s^7!"):format(type(subValues))) + return print(('[^1ERROR^7] xPlayer.clearMeta ^5subValues^7 should be ^5string^7 or ^5table^7, received ^5%s^7!'):format(type(subValues))) end - + Player(self.source).state:set('metadata', self.metadata, true) end diff --git a/[core]/es_extended/server/commands.lua b/[core]/es_extended/server/commands.lua index 4bb0de60a..103612a41 100644 --- a/[core]/es_extended/server/commands.lua +++ b/[core]/es_extended/server/commands.lua @@ -1,12 +1,29 @@ +---@diagnostic disable: undefined-field +local GetPlayerPed = GetPlayerPed +local GetEntityCoords = GetEntityCoords +local GetEntityHeading = GetEntityHeading +local GetVehiclePedIsIn = GetVehiclePedIsIn +local DeleteEntity = DeleteEntity +local NetworkGetEntityFromNetworkId = NetworkGetEntityFromNetworkId +local SetPedIntoVehicle = SetPedIntoVehicle +local DoesEntityExist = DoesEntityExist +local GetPedInVehicleSeat = GetPedInVehicleSeat +local GetPlayerName = GetPlayerName +local DoesEntityExist = DoesEntityExist +local DoesEntityExist = DoesEntityExist +local DoesEntityExist = DoesEntityExist +local DoesEntityExist = DoesEntityExist + ESX.RegisterCommand({'setcoords', 'tp'}, 'admin', function(xPlayer, args) - xPlayer.setCoords({ x = args.x, y = args.y, z = args.z }) + xPlayer.setCoords({ x = args.x, y = args.y, z = args.z, heading = args.h }) + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Set Coordinates /setcoords Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "X Coord", value = args.x, inline = true }, - { name = "Y Coord", value = args.y, inline = true }, - { name = "Z Coord", value = args.z, inline = true }, + ESX.DiscordLogFields('UserActions', 'Set Coordinates /setcoords Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'X Coord', value = args.x, inline = true }, + { name = 'Y Coord', value = args.y, inline = true }, + { name = 'Z Coord', value = args.z, inline = true }, }) end end, false, { @@ -15,7 +32,8 @@ end, false, { arguments = { { name = 'x', help = TranslateCap('command_setcoords_x'), type = 'coordinate' }, { name = 'y', help = TranslateCap('command_setcoords_y'), type = 'coordinate' }, - { name = 'z', help = TranslateCap('command_setcoords_z'), type = 'coordinate' } + { name = 'z', help = TranslateCap('command_setcoords_z'), type = 'coordinate' }, + { name = 'h', help = TranslateCap('command_setcoords_h'), type = 'coordinate' }, } }) @@ -26,12 +44,12 @@ ESX.RegisterCommand('setjob', 'admin', function(xPlayer, args, showError) args.playerId.setJob(args.job, args.grade) if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Set Job /setjob Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "Target", value = args.playerId.name, inline = true }, - { name = "Job", value = args.job, inline = true }, - { name = "Grade", value = args.grade, inline = true }, + ESX.DiscordLogFields('UserActions', 'Set Job /setjob Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'Target', value = args.playerId.name, inline = true }, + { name = 'Job', value = args.job, inline = true }, + { name = 'Grade', value = args.grade, inline = true }, }) end end, true, { @@ -46,7 +64,7 @@ end, true, { local upgrades = Config.SpawnVehMaxUpgrades and { - plate = "ADMINCAR", + plate = 'ADMINCAR', modEngine = 3, modBrakes = 2, modTransmission = 2, @@ -63,7 +81,7 @@ ESX.RegisterCommand('car', 'admin', function(xPlayer, args, showError) local playerPed = GetPlayerPed(xPlayer.source) local playerCoords = GetEntityCoords(playerPed) local playerHeading = GetEntityHeading(playerPed) - local playerVehicle = GetVehiclePedIsIn(playerPed) + local playerVehicle = GetVehiclePedIsIn(playerPed, false) if not args.car or type(args.car) ~= 'string' then args.car = 'adder' @@ -74,10 +92,10 @@ ESX.RegisterCommand('car', 'admin', function(xPlayer, args, showError) end if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Spawn Car /car Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "Vehicle", value = args.car, inline = true } + ESX.DiscordLogFields('UserActions', 'Spawn Car /car Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'Vehicle', value = args.car, inline = true } }) end @@ -85,7 +103,7 @@ ESX.RegisterCommand('car', 'admin', function(xPlayer, args, showError) if networkId then local vehicle = NetworkGetEntityFromNetworkId(networkId) for _ = 1, 20 do - Wait(0) + Wait(100) SetPedIntoVehicle(playerPed, vehicle, -1) if GetVehiclePedIsIn(playerPed, false) == vehicle then @@ -105,23 +123,27 @@ end, false, { } }) -ESX.RegisterCommand({ 'cardel', 'dv' }, 'admin', function(xPlayer, args) +ESX.RegisterCommand({'cardel', 'dv'}, 'admin', function(xPlayer, args) local PedVehicle = GetVehiclePedIsIn(GetPlayerPed(xPlayer.source), false) + if DoesEntityExist(PedVehicle) then DeleteEntity(PedVehicle) end - local Vehicles = ESX.OneSync.GetVehiclesInArea(GetEntityCoords(GetPlayerPed(xPlayer.source)), - tonumber(args.radius) or 5.0) + + local Vehicles = ESX.OneSync.GetVehiclesInArea(GetEntityCoords(GetPlayerPed(xPlayer.source)), tonumber(args.radius) or 5.0, {}) + for i = 1, #Vehicles do local Vehicle = NetworkGetEntityFromNetworkId(Vehicles[i]) + if DoesEntityExist(Vehicle) then DeleteEntity(Vehicle) end end + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Delete Vehicle /dv Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, + ESX.DiscordLogFields('UserActions', 'Delete Vehicle /dv Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, }) end end, false, { @@ -132,24 +154,28 @@ end, false, { } }) -ESX.RegisterCommand({ 'fix', 'repair' }, 'admin', function(xPlayer, args, showError) +ESX.RegisterCommand({'fix', 'repair'}, 'admin', function(xPlayer, args, showError) local xTarget = args.playerId local ped = GetPlayerPed(xTarget.source) local pedVehicle = GetVehiclePedIsIn(ped, false) + if not pedVehicle or GetPedInVehicleSeat(pedVehicle, -1) ~= ped then showError(TranslateCap('not_in_vehicle')) return end - xTarget.triggerEvent("esx:repairPedVehicle") - xPlayer.showNotification(TranslateCap('command_repair_success'), true, false, 140) + + xTarget.triggerEvent('esx:repairPedVehicle') + xPlayer.showNotification(TranslateCap('command_repair_success')) + if xPlayer.source ~= xTarget.source then - xTarget.showNotification(TranslateCap('command_repair_success_target'), true, false, 140) + xTarget.showNotification(TranslateCap('command_repair_success_target')) end + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Fix Vehicle /fix Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "Target", value = xTarget.name, inline = true }, + ESX.DiscordLogFields('UserActions', 'Fix Vehicle /fix Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'Target', value = xTarget.name, inline = true }, }) end end, true, { @@ -164,14 +190,16 @@ ESX.RegisterCommand('setaccountmoney', 'admin', function(xPlayer, args, showErro if not args.playerId.getAccount(args.account) then return showError(TranslateCap('command_giveaccountmoney_invalid')) end - args.playerId.setAccountMoney(args.account, args.amount, "Government Grant") + + args.playerId.setAccountMoney(args.account, args.amount, 'Government Grant') + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Set Account Money /setaccountmoney Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "Target", value = args.playerId.name, inline = true }, - { name = "Account", value = args.account, inline = true }, - { name = "Amount", value = args.amount, inline = true }, + ESX.DiscordLogFields('UserActions', 'Set Account Money /setaccountmoney Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'Target', value = args.playerId.name, inline = true }, + { name = 'Account', value = args.account, inline = true }, + { name = 'Amount', value = args.amount, inline = true }, }) end end, true, { @@ -188,14 +216,16 @@ ESX.RegisterCommand('giveaccountmoney', 'admin', function(xPlayer, args, showErr if not args.playerId.getAccount(args.account) then return showError(TranslateCap('command_giveaccountmoney_invalid')) end - args.playerId.addAccountMoney(args.account, args.amount, "Government Grant") + + args.playerId.addAccountMoney(args.account, args.amount, 'Government Grant') + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Give Account Money /giveaccountmoney Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "Target", value = args.playerId.name, inline = true }, - { name = "Account", value = args.account, inline = true }, - { name = "Amount", value = args.amount, inline = true }, + ESX.DiscordLogFields('UserActions', 'Give Account Money /giveaccountmoney Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'Target', value = args.playerId.name, inline = true }, + { name = 'Account', value = args.account, inline = true }, + { name = 'Amount', value = args.amount, inline = true }, }) end end, true, { @@ -212,14 +242,16 @@ ESX.RegisterCommand('removeaccountmoney', 'admin', function(xPlayer, args, showE if not args.playerId.getAccount(args.account) then return showError(TranslateCap('command_removeaccountmoney_invalid')) end - args.playerId.removeAccountMoney(args.account, args.amount, "Government Tax") + + args.playerId.removeAccountMoney(args.account, args.amount, 'Government Tax') + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Remove Account Money /removeaccountmoney Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "Target", value = args.playerId.name, inline = true }, - { name = "Account", value = args.account, inline = true }, - { name = "Amount", value = args.amount, inline = true }, + ESX.DiscordLogFields('UserActions', 'Remove Account Money /removeaccountmoney Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'Target', value = args.playerId.name, inline = true }, + { name = 'Account', value = args.account, inline = true }, + { name = 'Amount', value = args.amount, inline = true }, }) end end, true, { @@ -235,13 +267,14 @@ end, true, { if not Config.OxInventory then ESX.RegisterCommand('giveitem', 'admin', function(xPlayer, args) args.playerId.addInventoryItem(args.item, args.count) + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Give Item /giveitem Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "Target", value = args.playerId.name, inline = true }, - { name = "Item", value = args.item, inline = true }, - { name = "Quantity", value = args.count, inline = true }, + ESX.DiscordLogFields('UserActions', 'Give Item /giveitem Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'Target', value = args.playerId.name, inline = true }, + { name = 'Item', value = args.item, inline = true }, + { name = 'Quantity', value = args.count, inline = true }, }) end end, true, { @@ -258,14 +291,16 @@ if not Config.OxInventory then if args.playerId.hasWeapon(args.weapon) then return showError(TranslateCap('command_giveweapon_hasalready')) end + args.playerId.addWeapon(args.weapon, args.ammo) + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Give Weapon /giveweapon Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "Target", value = args.playerId.name, inline = true }, - { name = "Weapon", value = args.weapon, inline = true }, - { name = "Ammo", value = args.ammo, inline = true }, + ESX.DiscordLogFields('UserActions', 'Give Weapon /giveweapon Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'Target', value = args.playerId.name, inline = true }, + { name = 'Weapon', value = args.weapon, inline = true }, + { name = 'Ammo', value = args.ammo, inline = true }, }) end end, true, { @@ -280,16 +315,18 @@ if not Config.OxInventory then ESX.RegisterCommand('giveammo', 'admin', function(xPlayer, args, showError) if not args.playerId.hasWeapon(args.weapon) then - return showError(TranslateCap("command_giveammo_noweapon_found")) + return showError(TranslateCap('command_giveammo_noweapon_found')) end + args.playerId.addWeaponAmmo(args.weapon, args.ammo) + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Give Ammunition /giveammo Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "Target", value = args.playerId.name, inline = true }, - { name = "Weapon", value = args.weapon, inline = true }, - { name = "Ammo", value = args.ammo, inline = true }, + ESX.DiscordLogFields('UserActions', 'Give Ammunition /giveammo Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'Target', value = args.playerId.name, inline = true }, + { name = 'Weapon', value = args.weapon, inline = true }, + { name = 'Ammo', value = args.ammo, inline = true }, }) end end, true, { @@ -312,14 +349,13 @@ if not Config.OxInventory then else args.playerId.addWeaponComponent(args.weaponName, args.componentName) if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Give Weapon Component /giveweaponcomponent Triggered!", - "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "Target", value = args.playerId.name, inline = true }, - { name = "Weapon", value = args.weaponName, inline = true }, - { name = "Component", value = args.componentName, inline = true }, - }) + ESX.DiscordLogFields('UserActions', 'Give Weapon Component /giveweaponcomponent Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'Target', value = args.playerId.name, inline = true }, + { name = 'Weapon', value = args.weaponName, inline = true }, + { name = 'Component', value = args.componentName, inline = true }, + }) end end else @@ -339,21 +375,22 @@ if not Config.OxInventory then }) end -ESX.RegisterCommand({ 'clear', 'cls' }, 'user', function(xPlayer) +ESX.RegisterCommand({'clear', 'cls'}, 'user', function(xPlayer) xPlayer.triggerEvent('chat:clear') end, false, { help = TranslateCap('command_clear') }) -ESX.RegisterCommand({ 'clearall', 'clsall' }, 'admin', function(xPlayer) +ESX.RegisterCommand({'clearall', 'clsall'}, 'admin', function(xPlayer) TriggerClientEvent('chat:clear', -1) + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Clear Chat /clearall Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, + ESX.DiscordLogFields('UserActions', 'Clear Chat /clearall Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, }) end end, true, { help = TranslateCap('command_clearall') }) -ESX.RegisterCommand("refreshjobs", 'admin', function() +ESX.RegisterCommand('refreshjobs', 'admin', function() ESX.RefreshJobs() end, true, { help = TranslateCap('command_clearall') }) @@ -364,12 +401,14 @@ if not Config.OxInventory then args.playerId.setInventoryItem(v.name, 0) end end + TriggerEvent('esx:playerInventoryCleared', args.playerId) + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Clear Inventory /clearinventory Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "Target", value = args.playerId.name, inline = true }, + ESX.DiscordLogFields('UserActions', 'Clear Inventory /clearinventory Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'Target', value = args.playerId.name, inline = true }, }) end end, true, { @@ -384,12 +423,14 @@ if not Config.OxInventory then for i = #args.playerId.loadout, 1, -1 do args.playerId.removeWeapon(args.playerId.loadout[i].name) end + TriggerEvent('esx:playerLoadoutCleared', args.playerId) + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "/clearloadout Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "Target", value = args.playerId.name, inline = true }, + ESX.DiscordLogFields('UserActions', '/clearloadout Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'Target', value = args.playerId.name, inline = true }, }) end end, true, { @@ -402,18 +443,23 @@ if not Config.OxInventory then end ESX.RegisterCommand('setgroup', 'admin', function(xPlayer, args) - if not args.playerId then args.playerId = xPlayer.source end - if args.group == "superadmin" then - args.group = "admin" - print("[^3WARNING^7] ^5Superadmin^7 detected, setting group to ^5admin^7") + if not args.playerId then + args.playerId = xPlayer.source end + + if args.group == 'superadmin' then + args.group = Config.AdminGroups.DEFAULT_GROUP + print(('[^3WARNING^7] ^5Superadmin^7 detected, setting group to ^5\'%s\'^7'):format(args.group)) + end + args.playerId.setGroup(args.group) + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "/setgroup Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "Target", value = args.playerId.name, inline = true }, - { name = "Group", value = args.group, inline = true }, + ESX.DiscordLogFields('UserActions', '/setgroup Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'Target', value = GetPlayerName(args.playerId.source), inline = true }, + { name = 'Group', value = args.playerId.group, inline = true }, }) end end, true, { @@ -440,48 +486,48 @@ ESX.RegisterCommand('saveall', 'admin', function() Core.SavePlayers() end, true, { help = TranslateCap('command_saveall') }) -ESX.RegisterCommand('group', { "user", "admin" }, function(xPlayer, _, _) - print(('%s, you are currently: ^5%s^0'):format(xPlayer.getName(), xPlayer.getGroup())) +ESX.RegisterCommand('group', { 'user', 'admin' }, function(xPlayer, _, _) + print(('%s, you are currently: ^5%s^0'):format(xPlayer.name, xPlayer.group)) end, true) -ESX.RegisterCommand('job', { "user", "admin" }, function(xPlayer, _, _) - print(('%s, your job is: ^5%s^0 - ^5%s^0'):format(xPlayer.getName(), xPlayer.getJob().name, - xPlayer.getJob().grade_label)) +ESX.RegisterCommand('job', { 'user', 'admin' }, function(xPlayer, _, _) + print(('%s, your job is: ^5%s^0 - ^5%s^0'):format(xPlayer.name, xPlayer.job.name, + xPlayer.job.grade_label)) end, false) -ESX.RegisterCommand('info', { "user", "admin" }, function(xPlayer) - local job = xPlayer.getJob().name - print(('^2ID: ^5%s^0 | ^2Name: ^5%s^0 | ^2Group: ^5%s^0 | ^2Job: ^5%s^0'):format(xPlayer.source, xPlayer.getName(), - xPlayer.getGroup(), job)) +ESX.RegisterCommand('info', { 'user', 'admin' }, function(xPlayer) + print(('^2ID: ^5%s^0 | ^2Name: ^5%s^0 | ^2Group: ^5%s^0 | ^2Job: ^5%s^0'):format(xPlayer.source, xPlayer.name, xPlayer.group, xPlayer.job.name)) end, false) -ESX.RegisterCommand('coords', "admin", function(xPlayer) +ESX.RegisterCommand('coords', 'admin', function(xPlayer) local ped = GetPlayerPed(xPlayer.source) local coords = GetEntityCoords(ped, false) local heading = GetEntityHeading(ped) + print(('Coords - Vector3: ^5%s^0'):format(vector3(coords.x, coords.y, coords.z))) print(('Coords - Vector4: ^5%s^0'):format(vector4(coords.x, coords.y, coords.z, heading))) end, false) -ESX.RegisterCommand('tpm', "admin", function(xPlayer) - xPlayer.triggerEvent("esx:tpm") +ESX.RegisterCommand('tpm', 'admin', function(xPlayer) + xPlayer.triggerEvent('esx:tpm') + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Admin Teleport /tpm Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, + ESX.DiscordLogFields('UserActions', 'Admin Teleport /tpm Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, }) end end, false) -ESX.RegisterCommand('goto', "admin", function(xPlayer, args) - local targetCoords = args.playerId.getCoords() - xPlayer.setCoords(targetCoords) +ESX.RegisterCommand('goto', 'admin', function(xPlayer, args) + xPlayer.setCoords(args.playerId.coords) + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Admin Teleport /goto Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "Target", value = args.playerId.name, inline = true }, - { name = "Target Coords", value = targetCoords, inline = true }, + ESX.DiscordLogFields('UserActions', 'Admin Teleport /goto Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'Target', value = args.playerId.name, inline = true }, + { name = 'Target Coords', value = args.playerId.coords, inline = true }, }) end end, false, { @@ -492,16 +538,18 @@ end, false, { } }) -ESX.RegisterCommand('bring', "admin", function(xPlayer, args) - local targetCoords = args.playerId.getCoords() - local playerCoords = xPlayer.getCoords() +ESX.RegisterCommand('bring', 'admin', function(xPlayer, args) + local targetCoords = args.playerId.coords + local playerCoords = xPlayer.coords + args.playerId.setCoords(playerCoords) + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Admin Teleport /bring Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "Target", value = args.playerId.name, inline = true }, - { name = "Target Coords", value = targetCoords, inline = true }, + ESX.DiscordLogFields('UserActions', 'Admin Teleport /bring Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'Target', value = args.playerId.name, inline = true }, + { name = 'Target Coords', value = targetCoords, inline = true }, }) end end, false, { @@ -512,13 +560,14 @@ end, false, { } }) -ESX.RegisterCommand('kill', "admin", function(xPlayer, args) - args.playerId.triggerEvent("esx:killPlayer") +ESX.RegisterCommand('kill', 'admin', function(xPlayer, args) + args.playerId.triggerEvent('esx:killPlayer') + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Kill Command /kill Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "Target", value = args.playerId.name, inline = true }, + ESX.DiscordLogFields('UserActions', 'Kill Command /kill Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'Target', value = args.playerId.name, inline = true }, }) end end, true, { @@ -529,13 +578,14 @@ end, true, { } }) -ESX.RegisterCommand('freeze', "admin", function(xPlayer, args) - args.playerId.triggerEvent('esx:freezePlayer', "freeze") +ESX.RegisterCommand('freeze', 'admin', function(xPlayer, args) + args.playerId.triggerEvent('esx:freezePlayer', 'freeze') + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Admin Freeze /freeze Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "Target", value = args.playerId.name, inline = true }, + ESX.DiscordLogFields('UserActions', 'Admin Freeze /freeze Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'Target', value = args.playerId.name, inline = true }, }) end end, true, { @@ -546,13 +596,14 @@ end, true, { } }) -ESX.RegisterCommand('unfreeze', "admin", function(xPlayer, args) - args.playerId.triggerEvent('esx:freezePlayer', "unfreeze") +ESX.RegisterCommand('unfreeze', 'admin', function(xPlayer, args) + args.playerId.triggerEvent('esx:freezePlayer', 'unfreeze') + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Admin UnFreeze /unfreeze Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, - { name = "Target", value = args.playerId.name, inline = true }, + ESX.DiscordLogFields('UserActions', 'Admin UnFreeze /unfreeze Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, + { name = 'Target', value = args.playerId.name, inline = true }, }) end end, true, { @@ -563,21 +614,24 @@ end, true, { } }) -ESX.RegisterCommand("noclip", 'admin', function(xPlayer) +ESX.RegisterCommand('noclip', 'admin', function(xPlayer) xPlayer.triggerEvent('esx:noclip') + if Config.AdminLogging then - ESX.DiscordLogFields("UserActions", "Admin NoClip /noclip Triggered!", "pink", { - { name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true }, - { name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true }, + ESX.DiscordLogFields('UserActions', 'Admin NoClip /noclip Triggered!', 'pink', { + { name = 'Player', value = xPlayer and xPlayer.name or 'Server Console', inline = true }, + { name = 'ID', value = xPlayer and xPlayer.source or 'Unknown ID', inline = true }, }) end end, false) -ESX.RegisterCommand('players', "admin", function() +ESX.RegisterCommand('players', 'admin', function() local xPlayers = ESX.GetExtendedPlayers() -- Returns all xPlayers + print(('^5%s^2 online player(s)^0'):format(#xPlayers)) + for i = 1, #(xPlayers) do local xPlayer = xPlayers[i] - print(('^1[^2ID: ^5%s^0 | ^2Name : ^5%s^0 | ^2Group : ^5%s^0 | ^2Identifier : ^5%s^1]^0\n'):format(xPlayer.source, xPlayer.getName(), xPlayer.getGroup(), xPlayer.identifier)) + print(('^1[^2ID: ^5%s^0 | ^2Name : ^5%s^0 | ^2Group : ^5%s^0 | ^2Identifier : ^5%s^1]^0\n'):format(xPlayer.source, xPlayer.name, xPlayer.group, xPlayer.identifier)) end end, true) diff --git a/[core]/es_extended/server/common.lua b/[core]/es_extended/server/common.lua index 1f87bf3b4..25f4bb449 100644 --- a/[core]/es_extended/server/common.lua +++ b/[core]/es_extended/server/common.lua @@ -10,13 +10,12 @@ Core.Pickups = {} Core.PickupId = 0 Core.PlayerFunctionOverrides = {} Core.DatabaseConnected = false -Core.playersByIdentifier = {} +Core.PlayersByIdentifier = {} Core.vehicleTypesByModel = {} -AddEventHandler("esx:getSharedObject", function() - local Invoke = GetInvokingResource() - print(("[^1ERROR^7] Resource ^5%s^7 Used the ^5getSharedObject^7 Event, this event ^1no longer exists!^7 Visit https://documentation.esx-framework.org/tutorials/tutorials-esx/sharedevent for how to fix!"):format(Invoke)) +AddEventHandler('esx:getSharedObject', function() + print(('[^1ERROR^7] Resource ^5%s^7 Used the ^5getSharedObject^7 Event, this event ^1no longer exists!^7 Visit https://documentation.esx-framework.org/tutorials/tutorials-esx/sharedevent for how to fix!'):format(GetInvokingResource())) end) exports('getSharedObject', function() @@ -26,13 +25,14 @@ end) if GetResourceState('ox_inventory') ~= 'missing' then Config.OxInventory = true Config.PlayerFunctionOverride = 'OxInventory' - SetConvarReplicated('inventory:framework', 'esx') - SetConvarReplicated('inventory:weight', Config.MaxWeight * 1000) + + SetConvarReplicated('inventory:weight', tostring(Config.MaxWeight * 1000)) end local function StartDBSync() CreateThread(function() local interval = 10 * 60 * 1000 + while true do Wait(interval) Core.SavePlayers() @@ -42,10 +42,17 @@ end MySQL.ready(function() Core.DatabaseConnected = true + if not Config.OxInventory then local items = MySQL.query.await('SELECT * FROM items') + for _, v in ipairs(items) do - ESX.Items[v.name] = { label = v.label, weight = v.weight, rare = v.rare, canRemove = v.can_remove } + ESX.Items[v.name] = { + label = v.label, + weight = v.weight, + rare = v.rare, + canRemove = v.can_remove + } end else TriggerEvent('__cfx_export_ox_inventory_Items', function(ref) @@ -59,13 +66,13 @@ MySQL.ready(function() end) while not next(ESX.Items) do - Wait(0) + Wait(100) end end ESX.RefreshJobs() - print(('[^2INFO^7] ESX ^5Legacy %s^0 initialized!'):format(GetResourceMetadata(GetCurrentResourceName(), "version", 0))) + print(('[^2INFO^7] ESX ^5Legacy %s^0 initialized!'):format(GetResourceMetadata(GetCurrentResourceName(), 'version', 0))) StartDBSync() if Config.EnablePaycheck then @@ -73,14 +80,13 @@ MySQL.ready(function() end end) -RegisterServerEvent('esx:clientLog') -AddEventHandler('esx:clientLog', function(msg) +RegisterNetEvent('esx:clientLog', function(msg) if Config.EnableDebug then print(('[^2TRACE^7] %s^7'):format(msg)) end end) -RegisterNetEvent("esx:ReturnVehicleType", function(Type, Request) +RegisterNetEvent('esx:ReturnVehicleType', function(Type, Request) if Core.ClientCallbacks[Request] then Core.ClientCallbacks[Request](Type) Core.ClientCallbacks[Request] = nil diff --git a/[core]/es_extended/server/functions.lua b/[core]/es_extended/server/functions.lua index 49ee3a8e9..9ad16e9d0 100644 --- a/[core]/es_extended/server/functions.lua +++ b/[core]/es_extended/server/functions.lua @@ -1,3 +1,14 @@ +---@diagnostic disable: duplicate-set-field +local TriggerClientEvent = TriggerClientEvent +local print = print +local RegisterCommand = RegisterCommand +local ExecuteCommand = ExecuteCommand +local GetEntityHealth = GetEntityHealth +local GetPedArmour = GetPedArmour +local GetPlayerPed = GetPlayerPed +local IsPlayerAceAllowed = IsPlayerAceAllowed +local GetConvar = GetConvar + function ESX.Trace(msg) if Config.EnableDebug then print(('[^2TRACE^7] %s^7'):format(msg)) @@ -14,7 +25,7 @@ function ESX.RegisterCommand(name, group, cb, allowConsole, suggestion) end if Core.RegisteredCommands[name] then - print(('[^3WARNING^7] Command ^5"%s" ^7already registered, overriding command'):format(name)) + print(('[^3WARNING^7] Command ^5\'%s\' ^7already registered, overriding command'):format(name)) if Core.RegisteredCommands[name].suggestion then TriggerClientEvent('chat:removeSuggestion', -1, ('/%s'):format(name)) @@ -32,7 +43,12 @@ function ESX.RegisterCommand(name, group, cb, allowConsole, suggestion) TriggerClientEvent('chat:addSuggestion', -1, ('/%s'):format(name), suggestion.help, suggestion.arguments) end - Core.RegisteredCommands[name] = { group = group, cb = cb, allowConsole = allowConsole, suggestion = suggestion } + Core.RegisteredCommands[name] = { + group = group, + cb = cb, + allowConsole = allowConsole, + suggestion = suggestion + } RegisterCommand(name, function(playerId, args) local command = Core.RegisteredCommands[name] @@ -51,11 +67,12 @@ function ESX.RegisterCommand(name, group, cb, allowConsole, suggestion) if not error and command.suggestion.arguments then local newArgs = {} + local newArg, targetPlayer, xTargetPlayer, length, coord for k, v in ipairs(command.suggestion.arguments) do if v.type then if v.type == 'number' then - local newArg = tonumber(args[k]) + newArg = tonumber(args[k]) if newArg then newArgs[v.name] = newArg @@ -63,14 +80,14 @@ function ESX.RegisterCommand(name, group, cb, allowConsole, suggestion) error = TranslateCap('commanderror_argumentmismatch_number', k) end elseif v.type == 'player' or v.type == 'playerId' then - local targetPlayer = tonumber(args[k]) + targetPlayer = tonumber(args[k]) if args[k] == 'me' then targetPlayer = playerId end if targetPlayer then - local xTargetPlayer = ESX.GetPlayerFromId(targetPlayer) + xTargetPlayer = ESX.GetPlayerFromId(targetPlayer) if xTargetPlayer then if v.type == 'player' then @@ -85,7 +102,8 @@ function ESX.RegisterCommand(name, group, cb, allowConsole, suggestion) error = TranslateCap('commanderror_argumentmismatch_number', k) end elseif v.type == 'string' then - local newArg = tonumber(args[k]) + newArg = tonumber(args[k]) + if not newArg then newArgs[v.name] = args[k] else @@ -106,16 +124,15 @@ function ESX.RegisterCommand(name, group, cb, allowConsole, suggestion) elseif v.type == 'any' then newArgs[v.name] = args[k] elseif v.type == 'merge' then - local lenght = 0 for i = 1, k - 1 do - lenght = lenght + string.len(args[i]) + 1 + length = length + string.len(args[i]) + 1 end - local merge = table.concat(args, " ") - newArgs[v.name] = string.sub(merge, lenght) + newArgs[v.name] = string.sub(table.concat(args, ' '), length) elseif v.type == 'coordinate' then - local coord = tonumber(args[k]:match("(-?%d+%.?%d*)")) - if(not coord) then + coord = tonumber(args[k]:match('(-?%d+%.?%d*)')) + + if (not coord) then error = TranslateCap('commanderror_argumentmismatch_number', k) else newArgs[v.name] = coord @@ -123,8 +140,8 @@ function ESX.RegisterCommand(name, group, cb, allowConsole, suggestion) end end - --backwards compatibility - if v.validate ~= nil and not v.validate then + -- backwards compatibility + if not v.validate then error = nil end @@ -166,32 +183,34 @@ end local function updateHealthAndArmorInMetadata(xPlayer) local ped = GetPlayerPed(xPlayer.source) + xPlayer.setMeta('health', GetEntityHealth(ped)) - xPlayer.setMeta('armor',GetPedArmour(ped)) + xPlayer.setMeta('armor', GetPedArmour(ped)) end function Core.SavePlayer(xPlayer, cb) updateHealthAndArmorInMetadata(xPlayer) + local parameters = { - json.encode(xPlayer.getAccounts(true)), + json.encode(xPlayer.accounts), xPlayer.job.name, xPlayer.job.grade, xPlayer.group, - json.encode(xPlayer.getCoords()), - json.encode(xPlayer.getInventory(true)), - json.encode(xPlayer.getLoadout(true)), - json.encode(xPlayer.getMeta()), + json.encode(xPlayer.coords), + json.encode(xPlayer.inventory), + json.encode(xPlayer.loadout), + json.encode(xPlayer.metadata), xPlayer.identifier } MySQL.prepare( - 'UPDATE `users` SET `accounts` = ?, `job` = ?, `job_grade` = ?, `group` = ?, `position` = ?, `inventory` = ?, `loadout` = ?, `metadata` = ? WHERE `identifier` = ?', - parameters, + 'UPDATE `users` SET `accounts` = ?, `job` = ?, `job_grade` = ?, `group` = ?, `position` = ?, `inventory` = ?, `loadout` = ?, `metadata` = ? WHERE `identifier` = ?', parameters, function(affectedRows) if affectedRows == 1 then - print(('[^2INFO^7] Saved player ^5"%s^7"'):format(xPlayer.name)) - TriggerEvent('esx:playerSaved', xPlayer.playerId, xPlayer) + print(('[^2INFO^7] Saved player ^5\'%s^7\''):format(xPlayer.name)) + TriggerEvent('esx:playerSaved', xPlayer.source, xPlayer) end + if cb then cb() end @@ -201,6 +220,7 @@ end function Core.SavePlayers(cb) local xPlayers = ESX.Players + if not next(xPlayers) then return end @@ -210,22 +230,22 @@ function Core.SavePlayers(cb) for _, xPlayer in pairs(ESX.Players) do updateHealthAndArmorInMetadata(xPlayer) + parameters[#parameters + 1] = { - json.encode(xPlayer.getAccounts(true)), + json.encode(xPlayer.accounts), xPlayer.job.name, xPlayer.job.grade, xPlayer.group, - json.encode(xPlayer.getCoords()), - json.encode(xPlayer.getInventory(true)), - json.encode(xPlayer.getLoadout(true)), - json.encode(xPlayer.getMeta()), + json.encode(xPlayer.coords), + json.encode(xPlayer.inventory), + json.encode(xPlayer.loadout), + json.encode(xPlayer.metadata), xPlayer.identifier } end MySQL.prepare( - "UPDATE `users` SET `accounts` = ?, `job` = ?, `job_grade` = ?, `group` = ?, `position` = ?, `inventory` = ?, `loadout` = ?, `metadata` = ? WHERE `identifier` = ?", - parameters, + 'UPDATE `users` SET `accounts` = ?, `job` = ?, `job_grade` = ?, `group` = ?, `position` = ?, `inventory` = ?, `loadout` = ?, `metadata` = ? WHERE `identifier` = ?', parameters, function(results) if not results then return @@ -243,8 +263,11 @@ end ESX.GetPlayers = GetPlayers local function checkTable(key, val, player, xPlayers) + local value + for valIndex = 1, #val do - local value = val[valIndex] + value = val[valIndex] + if not xPlayers[value] then xPlayers[value] = {} end @@ -257,7 +280,8 @@ end function ESX.GetExtendedPlayers(key, val) local xPlayers = {} - if type(val) == "table" then + + if type(val) == 'table' then for _, v in pairs(ESX.Players) do checkTable(key, val, v, xPlayers) end @@ -281,23 +305,27 @@ function ESX.GetNumPlayers(key, val) return #GetPlayers() end - if type(val) == "table" then + if type(val) == 'table' then local numPlayers = {} - if key == "job" then + + if key == 'job' then for _, v in ipairs(val) do numPlayers[v] = (ESX.JobsPlayerCount[v] or 0) end + return numPlayers end local filteredPlayers = ESX.GetExtendedPlayers(key, val) + for i, v in pairs(filteredPlayers) do numPlayers[i] = (#v or 0) end + return numPlayers end - if key == "job" then + if key == 'job' then return (ESX.JobsPlayerCount[val] or 0) end @@ -309,13 +337,14 @@ function ESX.GetPlayerFromId(source) end function ESX.GetPlayerFromIdentifier(identifier) - return Core.playersByIdentifier[identifier] + return Core.PlayersByIdentifier[identifier] end function ESX.GetIdentifier(playerId) local fxDk = GetConvarInt('sv_fxdkMode', 0) + if fxDk == 1 then - return "ESX-DEBUG-LICENCE" + return 'ESX-DEBUG-LICENCE' end local identifier = GetPlayerIdentifierByType(playerId, 'license') @@ -325,7 +354,6 @@ end ---@param model string|number ---@param player number playerId ---@param cb function - function ESX.GetVehicleType(model, player, cb) model = type(model) == 'string' and joaat(model) or model @@ -333,7 +361,7 @@ function ESX.GetVehicleType(model, player, cb) return cb(Core.vehicleTypesByModel[model]) end - ESX.TriggerClientCallback(player, "esx:GetVehicleType", function(vehicleType) + ESX.TriggerClientCallback(player, 'esx:GetVehicleType', function(vehicleType) Core.vehicleTypesByModel[model] = vehicleType cb(vehicleType) end, model) @@ -341,20 +369,21 @@ end function ESX.DiscordLog(name, title, color, message) local webHook = Config.DiscordLogs.Webhooks[name] or Config.DiscordLogs.Webhooks.default - local embedData = { { + local embedData = {{ ['title'] = title, ['color'] = Config.DiscordLogs.Colors[color] or Config.DiscordLogs.Colors.default, ['footer'] = { - ['text'] = "| ESX Logs | " .. os.date(), - ['icon_url'] = "https://cdn.discordapp.com/attachments/944789399852417096/1020099828266586193/blanc-800x800.png" + ['text'] = '| ESX Logs | ' .. os.date(), + ['icon_url'] = 'https://cdn.discordapp.com/attachments/944789399852417096/1020099828266586193/blanc-800x800.png' }, ['description'] = message, ['author'] = { - ['name'] = "ESX Framework", - ['icon_url'] = "https://cdn.discordapp.com/emojis/939245183621558362.webp?size=128&quality=lossless" + ['name'] = 'ESX Framework', + ['icon_url'] = 'https://cdn.discordapp.com/emojis/939245183621558362.webp?size=128&quality=lossless' } - } } - PerformHttpRequest(webHook, nil, 'POST', json.encode({ + }} + + PerformHttpRequest(webHook, function() end, 'POST', json.encode({ username = 'Logs', embeds = embedData }), { @@ -364,21 +393,22 @@ end function ESX.DiscordLogFields(name, title, color, fields) local webHook = Config.DiscordLogs.Webhooks[name] or Config.DiscordLogs.Webhooks.default - local embedData = { { + local embedData = {{ ['title'] = title, ['color'] = Config.DiscordLogs.Colors[color] or Config.DiscordLogs.Colors.default, ['footer'] = { - ['text'] = "| ESX Logs | " .. os.date(), - ['icon_url'] = "https://cdn.discordapp.com/attachments/944789399852417096/1020099828266586193/blanc-800x800.png" + ['text'] = '| ESX Logs | ' .. os.date(), + ['icon_url'] = 'https://cdn.discordapp.com/attachments/944789399852417096/1020099828266586193/blanc-800x800.png' }, ['fields'] = fields, - ['description'] = "", + ['description'] = '', ['author'] = { - ['name'] = "ESX Framework", - ['icon_url'] = "https://cdn.discordapp.com/emojis/939245183621558362.webp?size=128&quality=lossless" + ['name'] = 'ESX Framework', + ['icon_url'] = 'https://cdn.discordapp.com/emojis/939245183621558362.webp?size=128&quality=lossless' } - } } - PerformHttpRequest(webHook, nil, 'POST', json.encode({ + }} + + PerformHttpRequest(webHook, function() end, 'POST', json.encode({ username = 'Logs', embeds = embedData }), { @@ -404,11 +434,29 @@ function ESX.CreateJob(name, label, grades) end local parameters = {} - local job = { name = name, label = label, grades = {} } + local job = { + name = name, + label = label, + grades = {} + } for _, v in pairs(grades) do - job.grades[tostring(v.grade)] = { job_name = name, grade = v.grade, name = v.name, label = v.label, salary = v.salary, skin_male = {}, skin_female = {} } - parameters[#parameters + 1] = { name, v.grade, v.name, v.label, v.salary } + job.grades[tostring(v.grade)] = { + job_name = name, + grade = v.grade, + name = v.name, + label = v.label, + salary = v.salary, + skin_male = {}, + skin_female = {} + } + parameters[#parameters + 1] = { + name, + v.grade, + v.name, + v.label, + v.salary + } end MySQL.insert('INSERT IGNORE INTO jobs (name, label) VALUES (?, ?)', { name, label }) @@ -432,20 +480,31 @@ function ESX.RefreshJobs() if Jobs[v.job_name] then Jobs[v.job_name].grades[tostring(v.grade)] = v else - print(('[^3WARNING^7] Ignoring job grades for ^5"%s"^0 due to missing job'):format(v.job_name)) + print(('[^3WARNING^7] Ignoring job grades for ^5\'%s\'^0 due to missing job'):format(v.job_name)) end end for _, v in pairs(Jobs) do if ESX.Table.SizeOf(v.grades) == 0 then Jobs[v.name] = nil - print(('[^3WARNING^7] Ignoring job ^5"%s"^0 due to no job grades found'):format(v.name)) + print(('[^3WARNING^7] Ignoring job ^5\'%s\'^0 due to no job grades found'):format(v.name)) end end if not Jobs then -- Fallback data, if no jobs exist - ESX.Jobs['unemployed'] = { label = 'Unemployed', grades = { ['0'] = { grade = 0, label = 'Unemployed', salary = 200, skin_male = {}, skin_female = {} } } } + ESX.Jobs.unemployed = { + label = 'Unemployed', + grades = { + ['0'] = { + grade = 0, + label = 'Unemployed', + salary = 200, + skin_male = {}, + skin_female = {} + } + } + } else ESX.Jobs = Jobs end @@ -463,11 +522,11 @@ function ESX.UseItem(source, item, ...) local success, result = pcall(itemCallback, source, item, ...) if not success then - return result and print(result) or print(('[^3WARNING^7] An error occured when using item ^5"%s"^7! This was not caused by ESX.'):format(item)) + return result and print(result) or print(('[^3WARNING^7] An error occured when using item ^5\'%s\'^7! This was not caused by ESX.'):format(item)) end end else - print(('[^3WARNING^7] Item ^5"%s"^7 was used but does not exist!'):format(item)) + print(('[^3WARNING^7] Item ^5\'%s\'^7 was used but does not exist!'):format(item)) end end @@ -486,6 +545,7 @@ end function ESX.GetItemLabel(item) if Config.OxInventory then item = exports.ox_inventory:Items(item) + if item then return item.label end @@ -504,9 +564,11 @@ end function ESX.GetUsableItems() local Usables = {} + for k in pairs(Core.UsableItemsCallbacks) do Usables[k] = true end + return Usables end @@ -514,9 +576,15 @@ if not Config.OxInventory then function ESX.CreatePickup(itemType, name, count, label, playerId, components, tintIndex, coords) local pickupId = (Core.PickupId == 65635 and 0 or Core.PickupId + 1) local xPlayer = ESX.Players[playerId] - coords = ( (type(coords) == "vector3" or type(coords) == "vector4") and coords.xyz or xPlayer.getCoords(true)) - - Core.Pickups[pickupId] = { type = itemType, name = name, count = count, label = label, coords = coords } + coords = ((type(coords) == 'vector3' or type(coords) == 'vector4') and coords.xyz or xPlayer.coords) + + Core.Pickups[pickupId] = { + type = itemType, + name = name, + count = count, + label = label, + coords = coords + } if itemType == 'item_weapon' then Core.Pickups[pickupId].components = components diff --git a/[core]/es_extended/server/main.lua b/[core]/es_extended/server/main.lua index 91b25bc71..46b0ed2d9 100644 --- a/[core]/es_extended/server/main.lua +++ b/[core]/es_extended/server/main.lua @@ -1,5 +1,22 @@ -SetMapName('San Andreas') -SetGameType('ESX Legacy') +---@diagnostic disable: undefined-field, need-check-nil +local GetPlayerName = GetPlayerName +local GetPlayerPed = GetPlayerPed +local GetEntityHealth = GetEntityHealth +local GetPedArmour = GetPedArmour +local TriggerEvent = TriggerEvent +local CancelEvent = CancelEvent +local GetConvarInt = GetConvarInt +local TriggerClientEvent = TriggerClientEvent +local GetEntityCoords = GetEntityCoords +local NetworkGetEntityFromNetworkId = NetworkGetEntityFromNetworkId +local GetVehiclePedIsIn = GetVehiclePedIsIn +local SetPedIntoVehicle = SetPedIntoVehicle +local GetResourceState = GetResourceState +local StopResource = StopResource + +SetMapName(Config.MapName) +SetGameType(Config.GameType) +SetConvarReplicated('inventory:framework', 'esx') local oneSyncState = GetConvar('onesync', 'off') local newPlayer = 'INSERT INTO `users` SET `accounts` = ?, `identifier` = ?, `group` = ?' @@ -22,74 +39,78 @@ loadPlayer = loadPlayer .. ' FROM `users` WHERE identifier = ?' if Config.Multichar then AddEventHandler('esx:onPlayerJoined', function(src, char, data) while not next(ESX.Jobs) do - Wait(50) + Wait(100) end if not ESX.Players[src] then local identifier = char .. ':' .. ESX.GetIdentifier(src) + if data then - createESXPlayer(identifier, src, data) + CreateESXPlayer(identifier, src, data) else - loadESXPlayer(identifier, src, false) + LoadESXPlayer(identifier, src, false) end end end) else - RegisterNetEvent('esx:onPlayerJoined') - AddEventHandler('esx:onPlayerJoined', function() - local _source = source + RegisterNetEvent('esx:onPlayerJoined', function() + local playerId = source + while not next(ESX.Jobs) do - Wait(50) + Wait(100) end - if not ESX.Players[_source] then - onPlayerJoined(_source) + if not ESX.Players[playerId] then + OnPlayerJoined(playerId) end end) end -function onPlayerJoined(playerId) +function OnPlayerJoined(playerId) local identifier = ESX.GetIdentifier(playerId) + if identifier then if ESX.GetPlayerFromIdentifier(identifier) then - DropPlayer(playerId, - ('there was an error loading your character!\nError code: identifier-active-ingame\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same Rockstar account.\n\nYour Rockstar identifier: %s'):format( - identifier)) + DropPlayer(playerId, ('there was an error loading your character!\nError code: identifier-active-ingame\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same Rockstar account.\n\nYour Rockstar identifier: %s'):format(identifier)) else local result = MySQL.scalar.await('SELECT 1 FROM users WHERE identifier = ?', { identifier }) + if result then - loadESXPlayer(identifier, playerId, false) + LoadESXPlayer(identifier, playerId, false) else - createESXPlayer(identifier, playerId) + CreateESXPlayer(identifier, playerId) end end else - DropPlayer(playerId, - 'there was an error loading your character!\nError code: identifier-missing-ingame\n\nThe cause of this error is not known, your identifier could not be found. Please come back later or report this problem to the server administration team.') + DropPlayer(playerId, 'there was an error loading your character!\nError code: identifier-missing-ingame\n\nThe cause of this error is not known, your identifier could not be found. Please come back later or report this problem to the server administration team.') end end -function createESXPlayer(identifier, playerId, data) +function CreateESXPlayer(identifier, playerId, data) local accounts = {} for account, money in pairs(Config.StartingAccountMoney) do accounts[account] = money end - local defaultGroup = "user" + local defaultGroup = 'user' if Core.IsPlayerAdmin(playerId) then print(('[^2INFO^0] Player ^5%s^0 Has been granted admin permissions via ^5Ace Perms^7.'):format(playerId)) - defaultGroup = "admin" + defaultGroup = Config.AdminGroups.DEFAULT_GROUP end - local parameters = Config.Multichar and { json.encode(accounts), identifier, defaultGroup, data.firstname, data.lastname, data.dateofbirth, data.sex, data.height } or { json.encode(accounts), identifier, defaultGroup } + local parameters = Config.Multichar and { + json.encode(accounts), identifier, defaultGroup, data.firstname, data.lastname, data.dateofbirth, data.sex, data.height + } or { + json.encode(accounts), identifier, defaultGroup + } if Config.StartingInventoryItems then - table.insert(parameters, json.encode(Config.StartingInventoryItems)) + parameters[#parameters + 1] = json.encode(Config.StartingInventoryItems) end MySQL.prepare(newPlayer, parameters, function() - loadESXPlayer(identifier, playerId, true) + LoadESXPlayer(identifier, playerId, true) end) end @@ -99,7 +120,7 @@ if not Config.Multichar then local playerId = source local identifier = ESX.GetIdentifier(playerId) - if oneSyncState == "off" or oneSyncState == "legacy" then + if oneSyncState ~= 'infinity' then return deferrals.done(('[ESX] ESX Requires Onesync Infinity to work. This server currently has Onesync set to: %s'):format(oneSyncState)) end @@ -109,20 +130,17 @@ if not Config.Multichar then if identifier then if ESX.GetPlayerFromIdentifier(identifier) then - return deferrals.done( - ('[ESX] There was an error loading your character!\nError code: identifier-active\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same account.\n\nYour identifier: %s'):format( - identifier)) + return deferrals.done(('[ESX] There was an error loading your character!\nError code: identifier-active\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same account.\n\nYour identifier: %s'):format(identifier)) else return deferrals.done() end else - return deferrals.done( - '[ESX] There was an error loading your character!\nError code: identifier-missing\n\nThe cause of this error is not known, your identifier could not be found. Please come back later or report this problem to the server administration team.') + return deferrals.done('[ESX] There was an error loading your character!\nError code: identifier-missing\n\nThe cause of this error is not known, your identifier could not be found. Please come back later or report this problem to the server administration team.') end end) end -function loadESXPlayer(identifier, playerId, isNew) +function LoadESXPlayer(identifier, playerId, isNew) local userData = { accounts = {}, inventory = {}, @@ -133,11 +151,11 @@ function loadESXPlayer(identifier, playerId, isNew) metadata = {} } local result = MySQL.prepare.await(loadPlayer, { identifier }) - local job, grade, jobObject, gradeObject = result.job, tostring(result.job_grade) + local job, grade, jobObject, gradeObject = result?.job, tostring(result?.job_grade) local foundAccounts, foundItems = {}, {} -- Accounts - if result.accounts and result.accounts ~= '' then + if result?.accounts and result?.accounts ~= '' then local accounts = json.decode(result.accounts) for account, money in pairs(accounts) do @@ -146,9 +164,10 @@ function loadESXPlayer(identifier, playerId, isNew) end for account, data in pairs(Config.Accounts) do - if data.round == nil then + if not data.round then data.round = true end + local index = #userData.accounts + 1 userData.accounts[index] = { name = account, @@ -189,7 +208,7 @@ function loadESXPlayer(identifier, playerId, isNew) -- Inventory if not Config.OxInventory then - if result.inventory and result.inventory ~= '' then + if result?.inventory and result?.inventory ~= '' then local inventory = json.decode(result.inventory) for name, count in pairs(inventory) do @@ -198,34 +217,34 @@ function loadESXPlayer(identifier, playerId, isNew) if item then foundItems[name] = count else - print(('[^3WARNING^7] Ignoring invalid item ^5"%s"^7 for ^5"%s^7"'):format(name, identifier)) + print(('[^3WARNING^7] Ignoring invalid item ^5\'%s\'^7 for ^5\'%s^7\''):format(name, identifier)) end end end for name, item in pairs(ESX.Items) do local count = foundItems[name] or 0 + if count > 0 then userData.weight = userData.weight + (item.weight * count) end - table.insert(userData.inventory, - { - name = name, - count = count, - label = item.label, - weight = item.weight, - usable = Core.UsableItemsCallbacks[name] ~= nil, - rare = item.rare, - canRemove = item.canRemove - }) + userData.inventory[#userData.inventory + 1] = { + name = name, + count = count, + label = item.label, + weight = item.weight, + usable = Core.UsableItemsCallbacks[name] ~= nil, + rare = item.rare, + canRemove = item.canRemove + } end table.sort(userData.inventory, function(a, b) return a.label < b.label end) else - if result.inventory and result.inventory ~= '' then + if result?.inventory and result?.inventory ~= '' then userData.inventory = json.decode(result.inventory) else userData.inventory = {} @@ -233,12 +252,12 @@ function loadESXPlayer(identifier, playerId, isNew) end -- Group - if result.group then - if result.group == "superadmin" then - userData.group = "admin" - print("[^3WARNING^7] ^5Superadmin^7 detected, setting group to ^5admin^7") + if result?.group then + if result?.group == 'superadmin' then + userData.group = Config.AdminGroups.DEFAULT_GROUP + print(('[^3WARNING^7] ^5Superadmin^7 detected, setting group to ^5\'%s\'^7'):format(userData.group)) else - userData.group = result.group + userData.group = result?.group end else userData.group = 'user' @@ -246,11 +265,12 @@ function loadESXPlayer(identifier, playerId, isNew) -- Loadout if not Config.OxInventory then - if result.loadout and result.loadout ~= '' then + if result?.loadout and result?.loadout ~= '' then local loadout = json.decode(result.loadout) + local label for name, weapon in pairs(loadout) do - local label = ESX.GetWeaponLabel(name) + label = ESX.GetWeaponLabel(name) if label then if not weapon.components then @@ -260,24 +280,25 @@ function loadESXPlayer(identifier, playerId, isNew) weapon.tintIndex = 0 end - table.insert(userData.loadout, - { - name = name, - ammo = weapon.ammo, - label = label, - components = weapon.components, - tintIndex = weapon.tintIndex - }) + userData.loadout[#userData.loadout + 1] = { + name = name, + ammo = weapon.ammo, + label = label, + components = weapon.components, + tintIndex = weapon.tintIndex + } end end end end -- Position - userData.coords = json.decode(result.position) or Config.DefaultSpawns[math.random(#Config.DefaultSpawns)] + if result?.position then + userData.coords = json.decode(result.position) or Config.DefaultSpawns[math.random(#Config.DefaultSpawns)] + end -- Skin - if result.skin and result.skin ~= '' then + if result?.skin and result?.skin ~= '' then userData.skin = json.decode(result.skin) else if userData.sex == 'f' then @@ -288,45 +309,54 @@ function loadESXPlayer(identifier, playerId, isNew) end -- Identity - if result.firstname and result.firstname ~= '' then + if result?.firstname and result?.firstname ~= '' then userData.firstname = result.firstname userData.lastname = result.lastname userData.playerName = userData.firstname .. ' ' .. userData.lastname - if result.dateofbirth then + + if result?.dateofbirth then userData.dateofbirth = result.dateofbirth end - if result.sex then + + if result?.sex then userData.sex = result.sex end - if result.height then + + if result?.height then userData.height = result.height end end - if result.metadata and result.metadata ~= '' then + if result?.metadata and result?.metadata ~= '' then local metadata = json.decode(result.metadata) + userData.metadata = metadata end local xPlayer = CreateExtendedPlayer(playerId, identifier, userData.group, userData.accounts, userData.inventory, userData.weight, userData.job, userData.loadout, userData.playerName, userData.coords, userData.metadata) ESX.Players[playerId] = xPlayer - Core.playersByIdentifier[identifier] = xPlayer + Core.PlayersByIdentifier[identifier] = xPlayer if userData.firstname then xPlayer.set('firstName', userData.firstname) xPlayer.set('lastName', userData.lastname) + if userData.dateofbirth then xPlayer.set('dateofbirth', userData.dateofbirth) end + if userData.sex then xPlayer.set('sex', userData.sex) end + if userData.height then xPlayer.set('height', userData.height) end end - --saved player health and armor in metadata + + -- saved player health and armor in metadata local ped = GetPlayerPed(xPlayer.source) + if ped then xPlayer.setMeta('health', xPlayer.getMeta('health') or GetEntityHealth(ped)) xPlayer.setMeta('armor', xPlayer.getMeta('armor') or GetPedArmour(ped)) @@ -344,11 +374,11 @@ function loadESXPlayer(identifier, playerId, isNew) loadout = xPlayer.getLoadout(), maxWeight = xPlayer.getMaxWeight(), money = xPlayer.getMoney(), - sex = xPlayer.get("sex") or "m", - firstName = xPlayer.get("firstName") or "John", - lastName = xPlayer.get("lastName") or "Doe", - dateofbirth = xPlayer.get("dateofbirth") or "01/01/2000", - height = xPlayer.get("height") or 120, + sex = xPlayer.get('sex') or 'm', + firstName = xPlayer.get('firstName') or 'John', + lastName = xPlayer.get('lastName') or 'Doe', + dateofbirth = xPlayer.get('dateofbirth') or '01/01/2000', + height = xPlayer.get('height') or 120, dead = false, metadata = xPlayer.getMeta() }, isNew, @@ -361,51 +391,55 @@ function loadESXPlayer(identifier, playerId, isNew) if isNew then for account, money in pairs(Config.StartingAccountMoney) do - if account == 'money' or account == 'black_money' then + if account ~= 'bank' then exports.ox_inventory:AddItem(playerId, account, money) end end end end + xPlayer.triggerEvent('esx:registerSuggestions', Core.RegisteredCommands) - print(('[^2INFO^0] Player ^5"%s"^0 has connected to the server. ID: ^5%s^7'):format(xPlayer.getName(), playerId)) + print(('[^2INFO^0] Player ^5\'%s\'^0 has connected to the server. ID: ^5%s^7'):format(xPlayer.getName(), playerId)) end AddEventHandler('chatMessage', function(playerId, _, message) - local xPlayer = ESX.GetPlayerFromId(playerId) if message:sub(1, 1) == '/' and playerId > 0 then - CancelEvent() - local commandName = message:sub(1):gmatch("%w+")() + local xPlayer = ESX.GetPlayerFromId(playerId) + local commandName = message:sub(1):gmatch('%w+')() + xPlayer.showNotification(TranslateCap('commanderror_invalidcommand', commandName)) + CancelEvent() end end) AddEventHandler('playerDropped', function(reason) - local playerId = source - local xPlayer = ESX.GetPlayerFromId(playerId) + local xPlayer = ESX.GetPlayerFromId(source) if xPlayer then - TriggerEvent('esx:playerDropped', playerId, reason) local job = xPlayer.getJob().name local currentJob = ESX.JobsPlayerCount[job] + ESX.JobsPlayerCount[job] = ((currentJob and currentJob > 0) and currentJob or 1) - 1 - GlobalState[("%s:count"):format(job)] = ESX.JobsPlayerCount[job] - Core.playersByIdentifier[xPlayer.identifier] = nil + GlobalState[('%s:count'):format(job)] = ESX.JobsPlayerCount[job] + Core.PlayersByIdentifier[xPlayer.identifier] = nil + Core.SavePlayer(xPlayer, function() - ESX.Players[playerId] = nil + ESX.Players[xPlayer.source] = nil end) + + TriggerEvent('esx:playerDropped', xPlayer.source, reason) end end) -AddEventHandler("esx:playerLoaded", function(_, xPlayer) - local job = xPlayer.getJob().name - local jobKey = ("%s:count"):format(job) +AddEventHandler('esx:playerLoaded', function(_, xPlayer) + local job = xPlayer.job.name + local jobKey = ('%s:count'):format(job) ESX.JobsPlayerCount[job] = (ESX.JobsPlayerCount[job] or 0) + 1 GlobalState[jobKey] = ESX.JobsPlayerCount[job] end) -AddEventHandler("esx:setJob", function(_, job, lastJob) +AddEventHandler('esx:setJob', function(_, job, lastJob) local lastJobKey = ('%s:count'):format(lastJob.name) local jobKey = ('%s:count'):format(job.name) local currentLastJob = ESX.JobsPlayerCount[lastJob.name] @@ -419,23 +453,24 @@ end) AddEventHandler('esx:playerLogout', function(playerId, cb) local xPlayer = ESX.GetPlayerFromId(playerId) - if xPlayer then - TriggerEvent('esx:playerDropped', playerId) - Core.playersByIdentifier[xPlayer.identifier] = nil + if xPlayer then + Core.PlayersByIdentifier[xPlayer.identifier] = nil Core.SavePlayer(xPlayer, function() ESX.Players[playerId] = nil if cb then cb() end end) + + TriggerEvent('esx:playerDropped', playerId) end - TriggerClientEvent("esx:onPlayerLogout", playerId) + + TriggerClientEvent('esx:onPlayerLogout', playerId) end) if not Config.OxInventory then - RegisterNetEvent('esx:updateWeaponAmmo') - AddEventHandler('esx:updateWeaponAmmo', function(weaponName, ammoCount) + RegisterNetEvent('esx:updateWeaponAmmo', function(weaponName, ammoCount) local xPlayer = ESX.GetPlayerFromId(source) if xPlayer then @@ -443,14 +478,13 @@ if not Config.OxInventory then end end) - RegisterNetEvent('esx:giveInventoryItem') - AddEventHandler('esx:giveInventoryItem', function(target, itemType, itemName, itemCount) - local playerId = source - local sourceXPlayer = ESX.GetPlayerFromId(playerId) + RegisterNetEvent('esx:giveInventoryItem', function(target, itemType, itemName, itemCount) + local sourceXPlayer = ESX.GetPlayerFromId(source) local targetXPlayer = ESX.GetPlayerFromId(target) - local distance = #(GetEntityCoords(GetPlayerPed(playerId)) - GetEntityCoords(GetPlayerPed(target))) + local distance = #(GetEntityCoords(GetPlayerPed(sourceXPlayer.source)) - GetEntityCoords(GetPlayerPed(target))) + if not sourceXPlayer or not targetXPlayer or distance > Config.DistanceGive then - print(('[^3WARNING^7] Player Detected Cheating: ^5%s^7'):format(GetPlayerName(playerId))) + print(('[^3WARNING^7] Player Detected Cheating: ^5%s^7'):format(GetPlayerName(sourceXPlayer.source))) return end @@ -472,8 +506,8 @@ if not Config.OxInventory then end elseif itemType == 'item_account' then if itemCount > 0 and sourceXPlayer.getAccount(itemName).money >= itemCount then - sourceXPlayer.removeAccountMoney(itemName, itemCount, "Gave to " .. targetXPlayer.name) - targetXPlayer.addAccountMoney(itemName, itemCount, "Received from " .. sourceXPlayer.name) + sourceXPlayer.removeAccountMoney(itemName, itemCount, 'Gave to ' .. targetXPlayer.name) + targetXPlayer.addAccountMoney(itemName, itemCount, 'Received from ' .. sourceXPlayer.name) sourceXPlayer.showNotification(TranslateCap('gave_account_money', ESX.Math.GroupDigits(itemCount), Config.Accounts[itemName].label, targetXPlayer.name)) targetXPlayer.showNotification(TranslateCap('received_account_money', ESX.Math.GroupDigits(itemCount), Config.Accounts[itemName].label, @@ -484,25 +518,30 @@ if not Config.OxInventory then elseif itemType == 'item_weapon' then if sourceXPlayer.hasWeapon(itemName) then local weaponLabel = ESX.GetWeaponLabel(itemName) + if not targetXPlayer.hasWeapon(itemName) then local _, weapon = sourceXPlayer.getWeapon(itemName) local _, weaponObject = ESX.GetWeapon(itemName) itemCount = weapon.ammo local weaponComponents = ESX.Table.Clone(weapon.components) local weaponTint = weapon.tintIndex + if weaponTint then targetXPlayer.setWeaponTint(itemName, weaponTint) end + if weaponComponents then for _, v in pairs(weaponComponents) do targetXPlayer.addWeaponComponent(itemName, v) end end + sourceXPlayer.removeWeapon(itemName) targetXPlayer.addWeapon(itemName, itemCount) if weaponObject.ammo and itemCount > 0 then local ammoLabel = weaponObject.ammo.label + sourceXPlayer.showNotification(TranslateCap('gave_weapon_withammo', weaponLabel, itemCount, ammoLabel, targetXPlayer.name)) targetXPlayer.showNotification(TranslateCap('received_weapon_withammo', weaponLabel, itemCount, ammoLabel, sourceXPlayer.name)) else @@ -540,10 +579,8 @@ if not Config.OxInventory then end end) - RegisterNetEvent('esx:removeInventoryItem') - AddEventHandler('esx:removeInventoryItem', function(itemType, itemName, itemCount) - local playerId = source - local xPlayer = ESX.GetPlayerFromId(playerId) + RegisterNetEvent('esx:removeInventoryItem', function(itemType, itemName, itemCount) + local xPlayer = ESX.GetPlayerFromId(source) if itemType == 'item_standard' then if itemCount == nil or itemCount < 1 then @@ -556,7 +593,7 @@ if not Config.OxInventory then else xPlayer.removeInventoryItem(itemName, itemCount) local pickupLabel = ('%s [%s]'):format(xItem.label, itemCount) - ESX.CreatePickup('item_standard', itemName, itemCount, pickupLabel, playerId) + ESX.CreatePickup('item_standard', itemName, itemCount, pickupLabel, xPlayer.source) xPlayer.showNotification(TranslateCap('threw_standard', itemCount, xItem.label)) end end @@ -569,9 +606,9 @@ if not Config.OxInventory then if (itemCount > account.money or account.money < 1) then xPlayer.showNotification(TranslateCap('imp_invalid_amount')) else - xPlayer.removeAccountMoney(itemName, itemCount, "Threw away") + xPlayer.removeAccountMoney(itemName, itemCount, 'Threw away') local pickupLabel = ('%s [%s]'):format(account.label, TranslateCap('locale_currency', ESX.Math.GroupDigits(itemCount))) - ESX.CreatePickup('item_account', itemName, itemCount, pickupLabel, playerId) + ESX.CreatePickup('item_account', itemName, itemCount, pickupLabel, xPlayer.source) xPlayer.showNotification(TranslateCap('threw_account', ESX.Math.GroupDigits(itemCount), string.lower(account.label))) end end @@ -593,33 +630,28 @@ if not Config.OxInventory then xPlayer.showNotification(TranslateCap('threw_weapon', weapon.label)) end - ESX.CreatePickup('item_weapon', itemName, weapon.ammo, pickupLabel, playerId, components, weapon.tintIndex) + ESX.CreatePickup('item_weapon', itemName, weapon.ammo, pickupLabel, xPlayer.source, components, weapon.tintIndex) end end end) - RegisterNetEvent('esx:useItem') - AddEventHandler('esx:useItem', function(itemName) - local source = source + RegisterNetEvent('esx:useItem', function(itemName) local xPlayer = ESX.GetPlayerFromId(source) local count = xPlayer.getInventoryItem(itemName).count if count > 0 then - ESX.UseItem(source, itemName) + ESX.UseItem(xPlayer.source, itemName) else xPlayer.showNotification(TranslateCap('act_imp')) end end) - RegisterNetEvent('esx:onPickup') - AddEventHandler('esx:onPickup', function(pickupId) + RegisterNetEvent('esx:onPickup', function(pickupId) local pickup, xPlayer, success = Core.Pickups[pickupId], ESX.GetPlayerFromId(source) if pickup then - local playerPickupDistance = #(pickup.coords - xPlayer.getCoords(true)) - if (playerPickupDistance > 5.0) then - print(('[^3WARNING^7] Player Detected Cheating (Out of range pickup): ^5%s^7'):format(xPlayer.getIdentifier())) - return + if (#(pickup.coords - xPlayer.getCoords(true)) > 5.0) then + return print(('[^3WARNING^7] Player Detected Cheating (Out of range pickup): ^5%s^7'):format(xPlayer.identifier)) end if pickup.type == 'item_standard' then @@ -631,7 +663,7 @@ if not Config.OxInventory then end elseif pickup.type == 'item_account' then success = true - xPlayer.addAccountMoney(pickup.name, pickup.count, "Picked up") + xPlayer.addAccountMoney(pickup.name, pickup.count, 'Picked up') elseif pickup.type == 'item_weapon' then if xPlayer.hasWeapon(pickup.name) then xPlayer.showNotification(TranslateCap('threw_weapon_already')) @@ -659,13 +691,13 @@ ESX.RegisterServerCallback('esx:getPlayerData', function(source, cb) cb({ identifier = xPlayer.identifier, - accounts = xPlayer.getAccounts(), - inventory = xPlayer.getInventory(), - job = xPlayer.getJob(), - loadout = xPlayer.getLoadout(), - money = xPlayer.getMoney(), - position = xPlayer.getCoords(true), - metadata = xPlayer.getMeta() + accounts = xPlayer.accounts, + inventory = xPlayer.inventory, + job = xPlayer.job, + loadout = xPlayer.loadout, + money = xPlayer.getAccount('money').money, + position = xPlayer.coords, + metadata = xPlayer.metadata }) end) @@ -674,7 +706,7 @@ ESX.RegisterServerCallback('esx:isUserAdmin', function(source, cb) end) ESX.RegisterServerCallback('esx:getGameBuild', function(_, cb) - cb(tonumber(GetConvar("sv_enforceGameBuild", 1604))) + cb(GetConvarInt('sv_enforceGameBuild', 1604)) end) ESX.RegisterServerCallback('esx:getOtherPlayerData', function(_, cb, target) @@ -682,13 +714,13 @@ ESX.RegisterServerCallback('esx:getOtherPlayerData', function(_, cb, target) cb({ identifier = xPlayer.identifier, - accounts = xPlayer.getAccounts(), - inventory = xPlayer.getInventory(), - job = xPlayer.getJob(), - loadout = xPlayer.getLoadout(), - money = xPlayer.getMoney(), - position = xPlayer.getCoords(true), - metadata = xPlayer.getMeta() + accounts = xPlayer.accounts, + inventory = xPlayer.inventory, + job = xPlayer.job, + loadout = xPlayer.loadout, + money = xPlayer.getAccount('money').money, + position = xPlayer.coords, + metadata = xPlayer.metadata }) end) @@ -708,18 +740,21 @@ ESX.RegisterServerCallback('esx:getPlayerNames', function(source, cb, players) cb(players) end) -ESX.RegisterServerCallback("esx:spawnVehicle", function(source, cb, vehData) +ESX.RegisterServerCallback('esx:spawnVehicle', function(source, cb, vehData) local ped = GetPlayerPed(source) + ESX.OneSync.SpawnVehicle(vehData.model or `ADDER`, vehData.coords or GetEntityCoords(ped), vehData.coords.w or 0.0, vehData.props or {}, function(id) if vehData.warp then local vehicle = NetworkGetEntityFromNetworkId(id) local timeout = 0 - while GetVehiclePedIsIn(ped) ~= vehicle and timeout <= 15 do - Wait(0) - TaskWarpPedIntoVehicle(ped, vehicle, -1) + + while GetVehiclePedIsIn(ped, false) ~= vehicle and timeout <= 15 do + Wait(100) + SetPedIntoVehicle(ped, vehicle, -1) timeout += 1 end end + cb(id) end) end) @@ -751,17 +786,17 @@ local DoNotUse = { AddEventHandler('onResourceStart', function(key) if DoNotUse[string.lower(key)] then while GetResourceState(key) ~= 'started' do - Wait(0) + Wait(100) end StopResource(key) - print(("[^1ERROR^7] WE STOPPED A RESOURCE THAT WILL BREAK ^1ESX^7, PLEASE REMOVE ^5%s^7"):format(key)) + print(('[^1ERROR^7] WE STOPPED A RESOURCE THAT WILL BREAK ^1ESX^7, PLEASE REMOVE ^5\'%s\'^7'):format(key)) end end) for key in pairs(DoNotUse) do if GetResourceState(key) == 'started' or GetResourceState(key) == 'starting' then StopResource(key) - print(("[^1ERROR^7] WE STOPPED A RESOURCE THAT WILL BREAK ^1ESX^7, PLEASE REMOVE ^5%s^7"):format(key)) + print(('[^1ERROR^7] WE STOPPED A RESOURCE THAT WILL BREAK ^1ESX^7, PLEASE REMOVE ^5\'%s\'^7'):format(key)) end end diff --git a/[core]/es_extended/server/modules/actions.lua b/[core]/es_extended/server/modules/actions.lua index c05131268..42614fa01 100644 --- a/[core]/es_extended/server/modules/actions.lua +++ b/[core]/es_extended/server/modules/actions.lua @@ -1,9 +1,9 @@ -RegisterServerEvent('esx:playerPedChanged') -RegisterServerEvent('esx:playerJumping') -RegisterServerEvent('esx:enteringVehicle') -RegisterServerEvent('esx:enteringVehicleAborted') -RegisterServerEvent('esx:enteredVehicle') -RegisterServerEvent('esx:exitedVehicle') +RegisterNetEvent('esx:playerPedChanged') +RegisterNetEvent('esx:playerJumping') +RegisterNetEvent('esx:enteringVehicle') +RegisterNetEvent('esx:enteringVehicleAborted') +RegisterNetEvent('esx:enteredVehicle') +RegisterNetEvent('esx:exitedVehicle') if Config.EnableDebug then AddEventHandler('esx:playerPedChanged', function(netId) diff --git a/[core]/es_extended/server/modules/callback.lua b/[core]/es_extended/server/modules/callback.lua index d78e9d4a7..eb05e2b15 100644 --- a/[core]/es_extended/server/modules/callback.lua +++ b/[core]/es_extended/server/modules/callback.lua @@ -1,5 +1,6 @@ +---@diagnostic disable: duplicate-set-field +local TriggerClientEvent = TriggerClientEvent local serverCallbacks = {} - local clientRequests = {} local RequestId = 0 @@ -14,8 +15,6 @@ RegisterNetEvent('esx:triggerServerCallback', function(eventName, requestId, inv return print(('[^1ERROR^7] Server Callback not registered, name: ^5%s^7, invoker resource: ^5%s^7'):format(eventName, invoker)) end - local source = source - serverCallbacks[eventName](source, function(...) TriggerClientEvent('esx:serverCallback', source, requestId, invoker, ...) end, ...) @@ -30,7 +29,7 @@ ESX.TriggerClientCallback = function(player, eventName, callback, ...) TriggerClientEvent('esx:triggerClientCallback', player, eventName, RequestId, GetInvokingResource() or "unknown", ...) - RequestId = RequestId + 1 + RequestId += 1 end RegisterNetEvent('esx:clientCallback', function(requestId, invoker, ...) diff --git a/[core]/es_extended/server/modules/npwd.lua b/[core]/es_extended/server/modules/npwd.lua index c4712b018..c4699a965 100644 --- a/[core]/es_extended/server/modules/npwd.lua +++ b/[core]/es_extended/server/modules/npwd.lua @@ -1,11 +1,12 @@ -local npwd = GetResourceState('npwd'):find('start') and exports.npwd or nil +---@diagnostic disable: need-check-nil, undefined-field +local npwd = GetResourceState('npwd'):find('start') and exports?.npwd AddEventHandler('onServerResourceStart', function(resource) if resource ~= 'npwd' then return end - npwd = GetResourceState('npwd'):find('start') and exports.npwd or nil + npwd = GetResourceState('npwd'):find('start') and exports?.npwd or nil for _, xPlayer in pairs(ESX.Players) do npwd:newPlayer({ @@ -23,6 +24,12 @@ AddEventHandler('onServerResourceStop', function(resource) end end) +AddEventHandler('onResourceStop', function(resource) + if resource == 'npwd' then + npwd = nil + end +end) + AddEventHandler('esx:playerLoaded', function(playerId, xPlayer) if not npwd then return @@ -35,8 +42,8 @@ AddEventHandler('esx:playerLoaded', function(playerId, xPlayer) npwd:newPlayer({ source = playerId, identifier = xPlayer.identifier, - firstname = xPlayer.get('firstName'), - lastname = xPlayer.get('lastName') + firstname = xPlayer.variables.firstName, + lastname = xPlayer.variables.lastName }) end) diff --git a/[core]/es_extended/server/onesync.lua b/[core]/es_extended/server/onesync.lua index 9fefaa744..5195e26d8 100644 --- a/[core]/es_extended/server/onesync.lua +++ b/[core]/es_extended/server/onesync.lua @@ -1,3 +1,20 @@ +---@diagnostic disable: duplicate-set-field, return-type-mismatch +local GetPlayerPed = GetPlayerPed +local GetEntityCoords = GetEntityCoords +local error = error +local NetworkGetNetworkIdFromEntity = NetworkGetNetworkIdFromEntity +local CreateVehicleServerSetter = CreateVehicleServerSetter +local DoesEntityExist = DoesEntityExist +local CreateObject = CreateObject +local SetEntityHeading = SetEntityHeading +local CreatePed = CreatePed +local CreatePedInsideVehicle = CreatePedInsideVehicle +local IsPedAPlayer = IsPedAPlayer +local GetEntityModel = GetEntityModel +local GetAllPeds = GetAllPeds +local GetAllObjects = GetAllObjects +local GetAllVehicles = GetAllVehicles + ESX.OneSync = {} ---@param source number|vector3 @@ -14,16 +31,16 @@ local function getNearbyPlayers(source, closest, distance, ignore) if type(source) == 'number' then playerPed = GetPlayerPed(source) - + if not source then - error("Received invalid first argument (source); should be playerId") + error('Received invalid first argument (source); should be playerId') return result end playerCoords = GetEntityCoords(playerPed) if not playerCoords then - error("Received nil value (playerCoords); perhaps source is nil at first place?") + error('Received nil value (playerCoords); perhaps source is nil at first place?') return result end end @@ -32,7 +49,7 @@ local function getNearbyPlayers(source, closest, distance, ignore) playerCoords = source if not playerCoords then - error("Received nil value (playerCoords); perhaps source is nil at first place?") + error('Received nil value (playerCoords); perhaps source is nil at first place?') return result end end @@ -87,9 +104,11 @@ function ESX.OneSync.SpawnVehicle(model, coords, heading, properties, cb) CreateThread(function() local xPlayer = ESX.OneSync.GetClosestPlayer(coords, 300) + ESX.GetVehicleType(vehicleModel, xPlayer.id, function(vehicleType) if vehicleType then - local createdVehicle = CreateVehicleServerSetter(vehicleModel, vehicleType, coords, heading) + local createdVehicle = CreateVehicleServerSetter(vehicleModel, vehicleType, coords.x, coords.y, coords.z, heading) + if not DoesEntityExist(createdVehicle) then return print('[^1ERROR^7] Unfortunately, this vehicle has not spawned') end @@ -109,11 +128,18 @@ end ---@param heading number ---@param cb function function ESX.OneSync.SpawnObject(model, coords, heading, cb) - if type(model) == 'string' then model = joaat(model) end - local objectCoords = type(coords) == "vector3" and coords or vector3(coords.x, coords.y, coords.z) + if type(model) == 'string' then + model = joaat(model) + end + + local objectCoords = type(coords) == 'vector3' and coords or vector3(coords.x, coords.y, coords.z) CreateThread(function() - local entity = CreateObject(model, objectCoords, true, true) - while not DoesEntityExist(entity) do Wait(50) end + local entity = CreateObject(model, objectCoords.x, objectCoords.y, objectCoords.z, true, true, true) + + while not DoesEntityExist(entity) do + Wait(100) + end + SetEntityHeading(entity, heading) cb(NetworkGetNetworkIdFromEntity(entity)) end) @@ -124,10 +150,17 @@ end ---@param heading number ---@param cb function function ESX.OneSync.SpawnPed(model, coords, heading, cb) - if type(model) == 'string' then model = joaat(model) end + if type(model) == 'string' then + model = joaat(model) + end + CreateThread(function() local entity = CreatePed(0, model, coords.x, coords.y, coords.z, heading, true, true) - while not DoesEntityExist(entity) do Wait(50) end + + while not DoesEntityExist(entity) do + Wait(100) + end + cb(NetworkGetNetworkIdFromEntity(entity)) end) end @@ -137,21 +170,30 @@ end ---@param seat number ---@param cb function function ESX.OneSync.SpawnPedInVehicle(model, vehicle, seat, cb) - if type(model) == 'string' then model = joaat(model) end + if type(model) == 'string' then + model = joaat(model) + end + CreateThread(function() local entity = CreatePedInsideVehicle(vehicle, 1, model, seat, true, true) - while not DoesEntityExist(entity) do Wait(50) end + + while not DoesEntityExist(entity) do + Wait(100) + end + cb(NetworkGetNetworkIdFromEntity(entity)) end) end local function getNearbyEntities(entities, coords, modelFilter, maxDistance, isPed) - local nearbyEntities = {} + local nearbyEntities, entityCoords = {}, nil coords = type(coords) == 'number' and GetEntityCoords(GetPlayerPed(coords)) or vector3(coords.x, coords.y, coords.z) + for _, entity in pairs(entities) do if not isPed or (isPed and not IsPedAPlayer(entity)) then if not modelFilter or modelFilter[GetEntityModel(entity)] then - local entityCoords = GetEntityCoords(entity) + entityCoords = GetEntityCoords(entity) + if not maxDistance or #(coords - entityCoords) <= maxDistance then nearbyEntities[#nearbyEntities + 1] = NetworkGetNetworkIdFromEntity(entity) end @@ -187,20 +229,22 @@ function ESX.OneSync.GetVehiclesInArea(coords, maxDistance, modelFilter) end local function getClosestEntity(entities, coords, modelFilter, isPed) - local distance, closestEntity, closestCoords = 100, nil, nil + local distance, closestEntity, closestCoords, entityCoords, dist = 100, 0, nil, nil, nil coords = type(coords) == 'number' and GetEntityCoords(GetPlayerPed(coords)) or vector3(coords.x, coords.y, coords.z) for _, entity in pairs(entities) do if not isPed or (isPed and not IsPedAPlayer(entity)) then if not modelFilter or modelFilter[GetEntityModel(entity)] then - local entityCoords = GetEntityCoords(entity) - local dist = #(coords - entityCoords) + entityCoords = GetEntityCoords(entity) + dist = #(coords - entityCoords) + if dist < distance then closestEntity, distance, closestCoords = entity, dist, entityCoords end end end end + return NetworkGetNetworkIdFromEntity(closestEntity), distance, closestCoords end @@ -225,6 +269,6 @@ function ESX.OneSync.GetClosestVehicle(coords, modelFilter) return getClosestEntity(GetAllVehicles(), coords, modelFilter) end -ESX.RegisterServerCallback("esx:Onesync:SpawnObject", function(_, cb, model, coords, heading) +ESX.RegisterServerCallback('esx:Onesync:SpawnObject', function(_, cb, model, coords, heading) ESX.OneSync.SpawnObject(model, coords, heading, cb) -end) +end) \ No newline at end of file diff --git a/[core]/es_extended/server/paycheck.lua b/[core]/es_extended/server/paycheck.lua index 981382934..4c96ab8ea 100644 --- a/[core]/es_extended/server/paycheck.lua +++ b/[core]/es_extended/server/paycheck.lua @@ -1,72 +1,77 @@ function StartPayCheck() - CreateThread(function() - while true do - Wait(Config.PaycheckInterval) - for player, xPlayer in pairs(ESX.Players) do - local jobLabel = xPlayer.job.label - local job = xPlayer.job.grade_name - local salary = xPlayer.job.grade_salary + CreateThread(function() + local jobLabel, job, salary - if salary > 0 then - if job == 'unemployed' then -- unemployed - xPlayer.addAccountMoney('bank', salary, "Welfare Check") - TriggerClientEvent('esx:showAdvancedNotification', player, TranslateCap('bank'), TranslateCap('received_paycheck'), TranslateCap('received_help', salary), - 'CHAR_BANK_MAZE', 9) - if Config.LogPaycheck then - ESX.DiscordLogFields("Paycheck", "Paycheck - Unemployment Benefits", "green", { - { name = "Player", value = xPlayer.name, inline = true }, - { name = "ID", value = xPlayer.source, inline = true }, - { name = "Amount", value = salary, inline = true } - }) - end - elseif Config.EnableSocietyPayouts then -- possibly a society - TriggerEvent('esx_society:getSociety', xPlayer.job.name, function(society) - if society ~= nil then -- verified society - TriggerEvent('esx_addonaccount:getSharedAccount', society.account, function(account) - if account.money >= salary then -- does the society money to pay its employees? - xPlayer.addAccountMoney('bank', salary, "Paycheck") - account.removeMoney(salary) - if Config.LogPaycheck then - ESX.DiscordLogFields("Paycheck", "Paycheck - " .. jobLabel, "green", { - { name = "Player", value = xPlayer.name, inline = true }, - { name = "ID", value = xPlayer.source, inline = true }, - { name = "Amount", value = salary, inline = true } - }) - end + while true do + Wait(Config.PaycheckInterval) + for player, xPlayer in pairs(ESX.Players) do + jobLabel = xPlayer.job.label + job = xPlayer.job.grade_name + salary = xPlayer.job.grade_salary - TriggerClientEvent('esx:showAdvancedNotification', player, TranslateCap('bank'), TranslateCap('received_paycheck'), - TranslateCap('received_salary', salary), 'CHAR_BANK_MAZE', 9) - else - TriggerClientEvent('esx:showAdvancedNotification', player, TranslateCap('bank'), '', TranslateCap('company_nomoney'), 'CHAR_BANK_MAZE', 1) - end - end) - else -- not a society - xPlayer.addAccountMoney('bank', salary, "Paycheck") - if Config.LogPaycheck then - ESX.DiscordLogFields("Paycheck", "Paycheck - " .. jobLabel, "green", { - { name = "Player", value = xPlayer.name, inline = true }, - { name = "ID", value = xPlayer.source, inline = true }, - { name = "Amount", value = salary, inline = true } - }) - end - TriggerClientEvent('esx:showAdvancedNotification', player, TranslateCap('bank'), TranslateCap('received_paycheck'), TranslateCap('received_salary', salary), - 'CHAR_BANK_MAZE', 9) - end - end) - else -- generic job - xPlayer.addAccountMoney('bank', salary, "Paycheck") - if Config.LogPaycheck then - ESX.DiscordLogFields("Paycheck", "Paycheck - Generic", "green", { - { name = "Player", value = xPlayer.name, inline = true }, - { name = "ID", value = xPlayer.source, inline = true }, - { name = "Amount", value = salary, inline = true } - }) - end - TriggerClientEvent('esx:showAdvancedNotification', player, TranslateCap('bank'), TranslateCap('received_paycheck'), TranslateCap('received_salary', salary), - 'CHAR_BANK_MAZE', 9) - end - end - end - end - end) -end + if salary > 0 then + if job == 'unemployed' then -- unemployed + xPlayer.addAccountMoney('bank', salary, 'Welfare Check') + TriggerClientEvent('esx:showAdvancedNotification', player, TranslateCap('bank'), TranslateCap('received_paycheck'), TranslateCap('received_help', salary), 'CHAR_BANK_MAZE', 9) + + if Config.LogPaycheck then + ESX.DiscordLogFields('Paycheck', 'Paycheck - Unemployment Benefits', 'green', { + { name = 'Player', value = xPlayer.name, inline = true }, + { name = 'ID', value = xPlayer.source, inline = true }, + { name = 'Amount', value = salary, inline = true } + }) + end + elseif Config.EnableSocietyPayouts then -- possibly a society + TriggerEvent('esx_society:getSociety', xPlayer.job.name, function(society) + if society then -- verified society + TriggerEvent('esx_addonaccount:getSharedAccount', society.account, function(account) + if account.money >= salary then -- does the society money to pay its employees? + xPlayer.addAccountMoney('bank', salary, 'Paycheck') + account.removeMoney(salary) + + if Config.LogPaycheck then + ESX.DiscordLogFields('Paycheck', 'Paycheck - ' .. jobLabel, 'green', { + { name = 'Player', value = xPlayer.name, inline = true }, + { name = 'ID', value = xPlayer.source, inline = true }, + { name = 'Amount', value = salary, inline = true } + }) + end + + TriggerClientEvent('esx:showAdvancedNotification', player, TranslateCap('bank'), TranslateCap('received_paycheck'), + TranslateCap('received_salary', salary), 'CHAR_BANK_MAZE', 9) + else + TriggerClientEvent('esx:showAdvancedNotification', player, TranslateCap('bank'), '', TranslateCap('company_nomoney'), 'CHAR_BANK_MAZE', 1) + end + end) + else -- not a society + xPlayer.addAccountMoney('bank', salary, 'Paycheck') + + if Config.LogPaycheck then + ESX.DiscordLogFields('Paycheck', 'Paycheck - ' .. jobLabel, 'green', { + { name = 'Player', value = xPlayer.name, inline = true }, + { name = 'ID', value = xPlayer.source, inline = true }, + { name = 'Amount', value = salary, inline = true } + }) + end + + TriggerClientEvent('esx:showAdvancedNotification', player, TranslateCap('bank'), TranslateCap('received_paycheck'), TranslateCap('received_salary', salary), 'CHAR_BANK_MAZE', 9) + end + end) + else -- generic job + xPlayer.addAccountMoney('bank', salary, 'Paycheck') + + if Config.LogPaycheck then + ESX.DiscordLogFields('Paycheck', 'Paycheck - Generic', 'green', { + { name = 'Player', value = xPlayer.name, inline = true }, + { name = 'ID', value = xPlayer.source, inline = true }, + { name = 'Amount', value = salary, inline = true } + }) + end + + TriggerClientEvent('esx:showAdvancedNotification', player, TranslateCap('bank'), TranslateCap('received_paycheck'), TranslateCap('received_salary', salary), 'CHAR_BANK_MAZE', 9) + end + end + end + end + end) +end \ No newline at end of file