Merge pull request #1789 from ASTROWwwW/refactor/move-modules-to-lib

refactor(esx_lib): move streaming/scaleform/points/interactions/game/onesync helpers into the lib
This commit is contained in:
_Not_
2026-07-15 22:46:14 -05:00
committed by GitHub
20 changed files with 1389 additions and 1123 deletions
+53
View File
@@ -37,3 +37,56 @@ end
ESX.Game.GetClosestEntity = xLib.entity.closest
EnumerateEntitiesWithinDistance = xLib.entity.EnumerateWithinDistance
ESX.Game.Teleport = xLib.entity.Teleport
ESX.Streaming = {
RequestModel = xLib.streaming.requestModel,
RequestStreamedTextureDict = xLib.streaming.requestStreamedTextureDict,
RequestNamedPtfxAsset = xLib.streaming.requestNamedPtfxAsset,
RequestAnimSet = xLib.streaming.requestAnimSet,
RequestAnimDict = xLib.streaming.requestAnimDict,
RequestWeaponAsset = xLib.streaming.requestWeaponAsset,
}
ESX.Scaleform = {
ShowFreemodeMessage = xLib.scaleform.showFreemodeMessage,
ShowBreakingNews = xLib.scaleform.showBreakingNews,
ShowPopupWarning = xLib.scaleform.showPopupWarning,
ShowTrafficMovie = xLib.scaleform.showTrafficMovie,
Utils = {
RequestScaleformMovie = xLib.scaleform.utils.requestScaleformMovie,
RunMethod = xLib.scaleform.utils.runMethod,
},
}
ESX.CreatePointInternal = xLib.points.create
ESX.RemovePointInternal = xLib.points.remove
ESX.HidePointInternal = xLib.points.hide
StartPointsLoop = xLib.points.startLoop
ESX.Point = xLib.point
ESX.RegisterInteraction = xLib.interactions.register
ESX.RemoveInteraction = xLib.interactions.remove
ESX.GetInteractKey = xLib.interactions.getInteractKey
ESX.Game.GetPedMugshot = xLib.game.getPedMugshot
ESX.Game.SpawnObject = xLib.game.spawnObject
ESX.Game.SpawnLocalObject = xLib.game.spawnLocalObject
ESX.Game.DeleteVehicle = xLib.game.deleteVehicle
ESX.Game.DeleteObject = xLib.game.deleteObject
ESX.Game.SpawnVehicle = xLib.game.spawnVehicle
ESX.Game.SpawnLocalVehicle = xLib.game.spawnLocalVehicle
ESX.Game.IsVehicleEmpty = xLib.game.isVehicleEmpty
ESX.Game.GetObjects = xLib.game.getObjects
ESX.Game.GetPeds = xLib.game.getPeds
ESX.Game.GetVehicles = xLib.game.getVehicles
ESX.Game.GetPlayers = xLib.game.getPlayers
ESX.Game.GetClosestObject = xLib.game.getClosestObject
ESX.Game.GetClosestPed = xLib.game.getClosestPed
ESX.Game.GetClosestPlayer = xLib.game.getClosestPlayer
ESX.Game.GetClosestVehicle = xLib.game.getClosestVehicle
ESX.Game.GetPlayersInArea = xLib.game.getPlayersInArea
ESX.Game.GetVehiclesInArea = xLib.game.getVehiclesInArea
ESX.Game.IsSpawnPointClear = xLib.game.isSpawnPointClear
ESX.Game.GetVehicleInDirection = xLib.game.getVehicleInDirection
ESX.Game.GetVehicleProperties = xLib.game.getVehicleProperties
ESX.Game.SetVehicleProperties = xLib.game.setVehicleProperties
-670
View File
@@ -442,676 +442,6 @@ function ESX.UI.ShowInventoryItemNotification(add, item, count)
})
end
---@param ped integer The ped to get the mugshot of
---@param transparent? boolean Whether the mugshot should be transparent
function ESX.Game.GetPedMugshot(ped, transparent)
if not DoesEntityExist(ped) then
return
end
local mugshot = transparent and RegisterPedheadshotTransparent(ped) or RegisterPedheadshot(ped)
while not IsPedheadshotReady(mugshot) do
Wait(0)
end
return mugshot, GetPedheadshotTxdString(mugshot)
end
---@param object integer | string The object to spawn
---@param coords table | vector3 The coords to spawn the object at
---@param cb? function The callback function
---@param networked? boolean Whether the object should be networked
---@return integer | nil
function ESX.Game.SpawnObject(object, coords, cb, networked)
local model = type(object) == "number" and object or joaat(object)
ESX.Streaming.RequestModel(model)
local obj = CreateObject(model, coords.x, coords.y, coords.z, networked == nil or networked, false, true)
return cb and cb(obj) or obj
end
---@param object integer | string The object to spawn
---@param coords table | vector3 The coords to spawn the object at
---@param cb? function The callback function
---@return nil
function ESX.Game.SpawnLocalObject(object, coords, cb)
ESX.Game.SpawnObject(object, coords, cb, false)
end
---@param vehicle integer The vehicle to delete
---@return nil
function ESX.Game.DeleteVehicle(vehicle)
SetEntityAsMissionEntity(vehicle, true, true)
DeleteVehicle(vehicle)
end
---@param object integer The object to delete
---@return nil
function ESX.Game.DeleteObject(object)
SetEntityAsMissionEntity(object, false, true)
DeleteObject(object)
end
---@param vehicleModel integer | string The vehicle to spawn
---@param coords table | vector3 The coords to spawn the vehicle at
---@param heading number The heading of the vehicle
---@param cb? fun(vehicle: number) The callback function
---@param networked? boolean Whether the vehicle should be networked
---@return number? vehicle
function ESX.Game.SpawnVehicle(vehicleModel, coords, heading, cb, networked)
if cb and not ESX.IsFunctionReference(cb) then
error("Invalid callback function")
end
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 isNetworked = networked == nil or networked
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 error(("Resource ^5%s^1 Tried to spawn vehicle on the client but the position is too far away (Out of onesync range)."):format(executingResource))
end
local promise = not cb and promise.new()
CreateThread(function()
local modelHash = ESX.Streaming.RequestModel(model)
if not modelHash then
if promise then
promise:reject(("Tried to spawn invalid vehicle - ^5%s^7!"):format(model))
return
end
error(("Tried to spawn invalid vehicle - ^5%s^7!"):format(model))
end
local vehicle = CreateVehicle(model, vector.x, vector.y, vector.z, heading, isNetworked, 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)
while not HasCollisionLoadedAroundEntity(vehicle) do
Wait(0)
end
if promise then
promise:resolve(vehicle)
elseif cb then
cb(vehicle)
end
end)
if promise then
return Citizen.Await(promise)
end
end
---@param vehicle integer The vehicle to spawn
---@param coords table | vector3 The coords to spawn the vehicle at
---@param heading number The heading of the vehicle
---@param cb? function The callback function
---@return nil
function ESX.Game.SpawnLocalVehicle(vehicle, coords, heading, cb)
ESX.Game.SpawnVehicle(vehicle, coords, heading, cb, false)
end
---@param vehicle integer The vehicle to check
---@return boolean
function ESX.Game.IsVehicleEmpty(vehicle)
return GetVehicleNumberOfPassengers(vehicle) == 0 and IsVehicleSeatFree(vehicle, -1)
end
---@return table
function ESX.Game.GetObjects() -- Leave the function for compatibility
return GetGamePool("CObject")
end
---@param onlyOtherPeds? boolean Whether to exlude the player ped
---@return table
function ESX.Game.GetPeds(onlyOtherPeds)
local pool = GetGamePool("CPed")
if onlyOtherPeds then
local myPed = ESX.PlayerData.ped
for i = 1, #pool do
if pool[i] == myPed then
table.remove(pool, i)
break
end
end
end
return pool
end
---@return table
function ESX.Game.GetVehicles() -- Leave the function for compatibility
return GetGamePool("CVehicle")
end
---@param onlyOtherPlayers? boolean Whether to exclude the player
---@param returnKeyValue? boolean Whether to return the key value pair
---@param returnPeds? boolean Whether to return the peds
---@return table
function ESX.Game.GetPlayers(onlyOtherPlayers, returnKeyValue, returnPeds)
local players = {}
local active = GetActivePlayers()
for i = 1, #active do
local currentPlayer = active[i]
local ped = GetPlayerPed(currentPlayer)
if DoesEntityExist(ped) and ((onlyOtherPlayers and currentPlayer ~= ESX.playerId) or not onlyOtherPlayers) then
if returnKeyValue then
players[currentPlayer] = ped
else
players[#players + 1] = returnPeds and ped or currentPlayer
end
end
end
return players
end
---@param coords? table | vector3 The coords to get the closest object to
---@param modelFilter? table The model filter
---@return integer, integer
function ESX.Game.GetClosestObject(coords, modelFilter)
return ESX.Game.GetClosestEntity(ESX.Game.GetObjects(), false, coords, modelFilter)
end
---@param coords? table | vector3 The coords to get the closest ped to
---@param modelFilter? table The model filter
---@return integer, integer
function ESX.Game.GetClosestPed(coords, modelFilter)
return ESX.Game.GetClosestEntity(ESX.Game.GetPeds(true), false, coords, modelFilter)
end
---@param coords? table | vector3 The coords to get the closest player to
---@return integer, integer
function ESX.Game.GetClosestPlayer(coords)
return ESX.Game.GetClosestEntity(ESX.Game.GetPlayers(true, true), true, coords, nil)
end
---@param coords? table | vector3 The coords to get the closest vehicle to
---@param modelFilter? table The model filter
---@return integer, integer
function ESX.Game.GetClosestVehicle(coords, modelFilter)
return ESX.Game.GetClosestEntity(ESX.Game.GetVehicles(), false, coords, modelFilter)
end
---@param coords table | vector3 The coords to search from
---@param maxDistance number The max distance to search within
---@return table
function ESX.Game.GetPlayersInArea(coords, maxDistance)
return EnumerateEntitiesWithinDistance(ESX.Game.GetPlayers(true, true), true, coords, maxDistance)
end
---@param coords table | vector3 The coords to search from
---@param maxDistance number The max distance to search within
---@return table
function ESX.Game.GetVehiclesInArea(coords, maxDistance)
return EnumerateEntitiesWithinDistance(ESX.Game.GetVehicles(), false, coords, maxDistance)
end
---@param coords table | vector3 The coords to search from
---@param maxDistance number The max distance to search within
---@return boolean
function ESX.Game.IsSpawnPointClear(coords, maxDistance)
return #ESX.Game.GetVehiclesInArea(coords, maxDistance) == 0
end
---@return integer | nil, vector3 | nil
function ESX.Game.GetVehicleInDirection()
local _, hit, coords, _, _, entity = ESX.Game.RaycastScreen(5, 10, ESX.PlayerData.ped)
if hit and IsEntityAVehicle(entity) then
return entity, coords
end
end
---@param vehicle integer The vehicle to get the properties of
---@return table | nil
function ESX.Game.GetVehicleProperties(vehicle)
if not DoesEntityExist(vehicle) then
return
end
---@type number | number[], number | number[]
local colorPrimary, colorSecondary = GetVehicleColours(vehicle)
local pearlescentColor, wheelColor = GetVehicleExtraColours(vehicle)
local dashboardColor = GetVehicleDashboardColor(vehicle)
local interiorColor = GetVehicleInteriorColour(vehicle)
if GetIsVehiclePrimaryColourCustom(vehicle) then
colorPrimary = { GetVehicleCustomPrimaryColour(vehicle) }
end
if GetIsVehicleSecondaryColourCustom(vehicle) then
colorSecondary = { GetVehicleCustomSecondaryColour(vehicle) }
end
local hasCustomXenonColor, customXenonColorR, customXenonColorG, customXenonColorB = GetVehicleXenonLightsCustomColor(vehicle)
local customXenonColor = nil
if hasCustomXenonColor then
customXenonColor = { customXenonColorR, customXenonColorG, customXenonColorB }
end
local extras = {}
for extraId = 0, 20 do
if DoesExtraExist(vehicle, extraId) then
extras[tostring(extraId)] = IsVehicleExtraTurnedOn(vehicle, extraId)
end
end
local doorsBroken, windowsBroken, tyreBurst = {}, {}, {}
local numWheels = tostring(GetVehicleNumberOfWheels(vehicle))
local TyresIndex = { -- Wheel index list according to the number of vehicle wheels.
["2"] = { 0, 4 }, -- Bike and cycle.
["3"] = { 0, 1, 4, 5 }, -- Vehicle with 3 wheels (get for wheels because some 3 wheels vehicles have 2 wheels on front and one rear or the reverse).
["4"] = { 0, 1, 4, 5 }, -- Vehicle with 4 wheels.
["6"] = { 0, 1, 2, 3, 4, 5 }, -- Vehicle with 6 wheels.
}
if TyresIndex[numWheels] then
for _, idx in pairs(TyresIndex[numWheels]) do
tyreBurst[tostring(idx)] = IsVehicleTyreBurst(vehicle, idx, false)
end
end
for windowId = 0, 7 do -- 13
RollUpWindow(vehicle, windowId) --fix when you put the car away with the window down
windowsBroken[tostring(windowId)] = not IsVehicleWindowIntact(vehicle, windowId)
end
local numDoors = GetNumberOfVehicleDoors(vehicle)
if numDoors and numDoors > 0 then
for doorsId = 0, numDoors do
doorsBroken[tostring(doorsId)] = IsVehicleDoorDamaged(vehicle, doorsId)
end
end
return {
model = GetEntityModel(vehicle),
doorsBroken = doorsBroken,
windowsBroken = windowsBroken,
tyreBurst = tyreBurst,
tyresCanBurst = GetVehicleTyresCanBurst(vehicle),
plate = ESX.Math.Trim(GetVehicleNumberPlateText(vehicle)),
plateIndex = GetVehicleNumberPlateTextIndex(vehicle),
bodyHealth = ESX.Math.Round(GetVehicleBodyHealth(vehicle), 1),
engineHealth = ESX.Math.Round(GetVehicleEngineHealth(vehicle), 1),
tankHealth = ESX.Math.Round(GetVehiclePetrolTankHealth(vehicle), 1),
fuelLevel = ESX.Math.Round(GetVehicleFuelLevel(vehicle), 1),
dirtLevel = ESX.Math.Round(GetVehicleDirtLevel(vehicle), 1),
color1 = colorPrimary,
color2 = colorSecondary,
pearlescentColor = pearlescentColor,
wheelColor = wheelColor,
dashboardColor = dashboardColor,
interiorColor = interiorColor,
wheels = GetVehicleWheelType(vehicle),
windowTint = GetVehicleWindowTint(vehicle),
xenonColor = GetVehicleXenonLightsColor(vehicle),
customXenonColor = customXenonColor,
neonEnabled = { IsVehicleNeonLightEnabled(vehicle, 0), IsVehicleNeonLightEnabled(vehicle, 1), IsVehicleNeonLightEnabled(vehicle, 2), IsVehicleNeonLightEnabled(vehicle, 3) },
neonColor = table.pack(GetVehicleNeonLightsColour(vehicle)),
extras = extras,
tyreSmokeColor = table.pack(GetVehicleTyreSmokeColor(vehicle)),
modSpoilers = GetVehicleMod(vehicle, 0),
modFrontBumper = GetVehicleMod(vehicle, 1),
modRearBumper = GetVehicleMod(vehicle, 2),
modSideSkirt = GetVehicleMod(vehicle, 3),
modExhaust = GetVehicleMod(vehicle, 4),
modFrame = GetVehicleMod(vehicle, 5),
modGrille = GetVehicleMod(vehicle, 6),
modHood = GetVehicleMod(vehicle, 7),
modFender = GetVehicleMod(vehicle, 8),
modRightFender = GetVehicleMod(vehicle, 9),
modRoof = GetVehicleMod(vehicle, 10),
modRoofLivery = GetVehicleRoofLivery(vehicle),
modEngine = GetVehicleMod(vehicle, 11),
modBrakes = GetVehicleMod(vehicle, 12),
modTransmission = GetVehicleMod(vehicle, 13),
modHorns = GetVehicleMod(vehicle, 14),
modSuspension = GetVehicleMod(vehicle, 15),
modArmor = GetVehicleMod(vehicle, 16),
modTurbo = IsToggleModOn(vehicle, 18),
modSmokeEnabled = IsToggleModOn(vehicle, 20),
modXenon = IsToggleModOn(vehicle, 22),
modFrontWheels = GetVehicleMod(vehicle, 23),
modCustomFrontWheels = GetVehicleModVariation(vehicle, 23),
modBackWheels = GetVehicleMod(vehicle, 24),
modCustomBackWheels = GetVehicleModVariation(vehicle, 24),
modPlateHolder = GetVehicleMod(vehicle, 25),
modVanityPlate = GetVehicleMod(vehicle, 26),
modTrimA = GetVehicleMod(vehicle, 27),
modOrnaments = GetVehicleMod(vehicle, 28),
modDashboard = GetVehicleMod(vehicle, 29),
modDial = GetVehicleMod(vehicle, 30),
modDoorSpeaker = GetVehicleMod(vehicle, 31),
modSeats = GetVehicleMod(vehicle, 32),
modSteeringWheel = GetVehicleMod(vehicle, 33),
modShifterLeavers = GetVehicleMod(vehicle, 34),
modAPlate = GetVehicleMod(vehicle, 35),
modSpeakers = GetVehicleMod(vehicle, 36),
modTrunk = GetVehicleMod(vehicle, 37),
modHydrolic = GetVehicleMod(vehicle, 38),
modEngineBlock = GetVehicleMod(vehicle, 39),
modAirFilter = GetVehicleMod(vehicle, 40),
modStruts = GetVehicleMod(vehicle, 41),
modArchCover = GetVehicleMod(vehicle, 42),
modAerials = GetVehicleMod(vehicle, 43),
modTrimB = GetVehicleMod(vehicle, 44),
modTank = GetVehicleMod(vehicle, 45),
modWindows = GetVehicleMod(vehicle, 46),
modLivery = GetVehicleMod(vehicle, 48) == -1 and GetVehicleLivery(vehicle) or GetVehicleMod(vehicle, 48),
modLightbar = GetVehicleMod(vehicle, 49),
}
end
---@param vehicle integer The vehicle to set the properties of
---@param props table The properties to set
---@return nil
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
SetVehicleTyresCanBurst(vehicle, props.tyresCanBurst)
end
if props.plate ~= nil then
SetVehicleNumberPlateText(vehicle, props.plate)
end
if props.plateIndex ~= nil then
SetVehicleNumberPlateTextIndex(vehicle, props.plateIndex)
end
if props.bodyHealth ~= nil then
SetVehicleBodyHealth(vehicle, props.bodyHealth + 0.0)
end
if props.engineHealth ~= nil then
SetVehicleEngineHealth(vehicle, props.engineHealth + 0.0)
end
if props.tankHealth ~= nil then
SetVehiclePetrolTankHealth(vehicle, props.tankHealth + 0.0)
end
if props.fuelLevel ~= nil then
SetVehicleFuelLevel(vehicle, props.fuelLevel + 0.0)
end
if props.dirtLevel ~= nil then
SetVehicleDirtLevel(vehicle, props.dirtLevel + 0.0)
end
if props.color1 ~= nil then
if type(props.color1) == "table" then
SetVehicleCustomPrimaryColour(vehicle, props.color1[1], props.color1[2], props.color1[3])
else
SetVehicleColours(vehicle, props.color1, colorSecondary)
end
end
if props.color2 ~= nil then
if type(props.color2) == "table" then
SetVehicleCustomSecondaryColour(vehicle, props.color2[1], props.color2[2], props.color2[3])
else
SetVehicleColours(vehicle, props.color1 or colorPrimary, props.color2)
end
end
if props.pearlescentColor ~= nil then
SetVehicleExtraColours(vehicle, props.pearlescentColor, wheelColor)
end
if props.interiorColor ~= nil then
SetVehicleInteriorColor(vehicle, props.interiorColor)
end
if props.dashboardColor ~= nil then
SetVehicleDashboardColor(vehicle, props.dashboardColor)
end
if props.wheelColor ~= nil then
SetVehicleExtraColours(vehicle, props.pearlescentColor or pearlescentColor, props.wheelColor)
end
if props.wheels ~= nil then
SetVehicleWheelType(vehicle, props.wheels)
end
if props.windowTint ~= nil then
SetVehicleWindowTint(vehicle, props.windowTint)
end
if props.neonEnabled ~= nil 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
for extraId, enabled in pairs(props.extras) do
extraId = tonumber(extraId)
if extraId then
SetVehicleExtra(vehicle, extraId, not enabled)
end
end
end
if props.neonColor ~= nil then
SetVehicleNeonLightsColour(vehicle, props.neonColor[1], props.neonColor[2], props.neonColor[3])
end
if props.xenonColor ~= nil then
SetVehicleXenonLightsColor(vehicle, props.xenonColor)
end
if props.customXenonColor ~= nil then
SetVehicleXenonLightsCustomColor(vehicle, props.customXenonColor[1], props.customXenonColor[2], props.customXenonColor[3])
end
if props.modSmokeEnabled ~= nil then
ToggleVehicleMod(vehicle, 20, true)
end
if props.tyreSmokeColor ~= nil then
SetVehicleTyreSmokeColor(vehicle, props.tyreSmokeColor[1], props.tyreSmokeColor[2], props.tyreSmokeColor[3])
end
if props.modSpoilers ~= nil then
SetVehicleMod(vehicle, 0, props.modSpoilers, false)
end
if props.modFrontBumper ~= nil then
SetVehicleMod(vehicle, 1, props.modFrontBumper, false)
end
if props.modRearBumper ~= nil then
SetVehicleMod(vehicle, 2, props.modRearBumper, false)
end
if props.modSideSkirt ~= nil then
SetVehicleMod(vehicle, 3, props.modSideSkirt, false)
end
if props.modExhaust ~= nil then
SetVehicleMod(vehicle, 4, props.modExhaust, false)
end
if props.modFrame ~= nil then
SetVehicleMod(vehicle, 5, props.modFrame, false)
end
if props.modGrille ~= nil then
SetVehicleMod(vehicle, 6, props.modGrille, false)
end
if props.modHood ~= nil then
SetVehicleMod(vehicle, 7, props.modHood, false)
end
if props.modFender ~= nil then
SetVehicleMod(vehicle, 8, props.modFender, false)
end
if props.modRightFender ~= nil then
SetVehicleMod(vehicle, 9, props.modRightFender, false)
end
if props.modRoof ~= nil then
SetVehicleMod(vehicle, 10, props.modRoof, false)
end
if props.modRoofLivery ~= nil then
SetVehicleRoofLivery(vehicle, props.modRoofLivery)
end
if props.modEngine ~= nil then
SetVehicleMod(vehicle, 11, props.modEngine, false)
end
if props.modBrakes ~= nil then
SetVehicleMod(vehicle, 12, props.modBrakes, false)
end
if props.modTransmission ~= nil then
SetVehicleMod(vehicle, 13, props.modTransmission, false)
end
if props.modHorns ~= nil then
SetVehicleMod(vehicle, 14, props.modHorns, false)
end
if props.modSuspension ~= nil then
SetVehicleMod(vehicle, 15, props.modSuspension, false)
end
if props.modArmor ~= nil then
SetVehicleMod(vehicle, 16, props.modArmor, false)
end
if props.modTurbo ~= nil then
ToggleVehicleMod(vehicle, 18, props.modTurbo)
end
if props.modXenon ~= nil then
ToggleVehicleMod(vehicle, 22, props.modXenon)
end
if props.modFrontWheels ~= nil then
SetVehicleMod(vehicle, 23, props.modFrontWheels, props.modCustomFrontWheels)
end
if props.modBackWheels ~= nil then
SetVehicleMod(vehicle, 24, props.modBackWheels, props.modCustomBackWheels)
end
if props.modPlateHolder ~= nil then
SetVehicleMod(vehicle, 25, props.modPlateHolder, false)
end
if props.modVanityPlate ~= nil then
SetVehicleMod(vehicle, 26, props.modVanityPlate, false)
end
if props.modTrimA ~= nil then
SetVehicleMod(vehicle, 27, props.modTrimA, false)
end
if props.modOrnaments ~= nil then
SetVehicleMod(vehicle, 28, props.modOrnaments, false)
end
if props.modDashboard ~= nil then
SetVehicleMod(vehicle, 29, props.modDashboard, false)
end
if props.modDial ~= nil then
SetVehicleMod(vehicle, 30, props.modDial, false)
end
if props.modDoorSpeaker ~= nil then
SetVehicleMod(vehicle, 31, props.modDoorSpeaker, false)
end
if props.modSeats ~= nil then
SetVehicleMod(vehicle, 32, props.modSeats, false)
end
if props.modSteeringWheel ~= nil then
SetVehicleMod(vehicle, 33, props.modSteeringWheel, false)
end
if props.modShifterLeavers ~= nil then
SetVehicleMod(vehicle, 34, props.modShifterLeavers, false)
end
if props.modAPlate ~= nil then
SetVehicleMod(vehicle, 35, props.modAPlate, false)
end
if props.modSpeakers ~= nil then
SetVehicleMod(vehicle, 36, props.modSpeakers, false)
end
if props.modTrunk ~= nil then
SetVehicleMod(vehicle, 37, props.modTrunk, false)
end
if props.modHydrolic ~= nil then
SetVehicleMod(vehicle, 38, props.modHydrolic, false)
end
if props.modEngineBlock ~= nil then
SetVehicleMod(vehicle, 39, props.modEngineBlock, false)
end
if props.modAirFilter ~= nil then
SetVehicleMod(vehicle, 40, props.modAirFilter, false)
end
if props.modStruts ~= nil then
SetVehicleMod(vehicle, 41, props.modStruts, false)
end
if props.modArchCover ~= nil then
SetVehicleMod(vehicle, 42, props.modArchCover, false)
end
if props.modAerials ~= nil then
SetVehicleMod(vehicle, 43, props.modAerials, false)
end
if props.modTrimB ~= nil then
SetVehicleMod(vehicle, 44, props.modTrimB, false)
end
if props.modTank ~= nil then
SetVehicleMod(vehicle, 45, props.modTank, false)
end
if props.modWindows ~= nil then
SetVehicleMod(vehicle, 46, props.modWindows, false)
end
if props.modLivery ~= nil then
SetVehicleMod(vehicle, 48, props.modLivery, false)
SetVehicleLivery(vehicle, props.modLivery)
end
if props.windowsBroken ~= nil then
for k, v in pairs(props.windowsBroken) do
if v then
k = tonumber(k)
if k then
RemoveVehicleWindow(vehicle, k)
end
end
end
end
if props.doorsBroken ~= nil then
for k, v in pairs(props.doorsBroken) do
if v then
k = tonumber(k)
if k then
SetVehicleDoorBroken(vehicle, k, true)
end
end
end
end
if props.tyreBurst ~= nil then
for k, v in pairs(props.tyreBurst) do
if v then
k = tonumber(k)
if k then
SetVehicleTyreBurst(vehicle, k, true, 1000.0)
end
end
end
end
end
---@param coords vector3 | table coords to get the closest pickup to
---@param text string The text to display
---@param size? number The size of the text
@@ -1,53 +0,0 @@
local Point = ESX.Class()
local nearby, loop = {}, nil
function Point:constructor(properties)
self.coords = properties.coords
self.hidden = properties.hidden
self.enter = properties.enter
self.leave = properties.leave
self.inside = properties.inside
self.handle = ESX.CreatePointInternal(properties.coords, properties.distance, properties.hidden, function()
nearby[self.handle] = self
if self.enter then
self:enter()
end
if not loop then
loop = true
CreateThread(function()
while loop do
local coords = GetEntityCoords(ESX.PlayerData.ped)
for _, point in pairs(nearby) do
if point.inside then
point:inside(#(coords - point.coords))
end
end
Wait(0)
end
end)
end
end, function()
nearby[self.handle] = nil
if self.leave then
self:leave()
end
if #nearby == 0 then
loop = false
end
end)
end
function Point:delete()
ESX.RemovePointInternal(self.handle)
end
function Point:toggle(hidden)
if hidden == nil then
hidden = not self.hidden
end
self.hidden = hidden
ESX.HidePointInternal(self.handle, hidden)
end
return Point
+29 -43
View File
@@ -1,10 +1,14 @@
-- ESX glue over the generic xLib.cache.
-- ped and weapon are tracked by the lib cache; this module mirrors them into
-- ESX.PlayerData, re-emits the legacy esx: events resources depend on, and keeps
-- the vehicle enter/exit state machine that produces the richer vehicle events.
Actions = {}
Actions._index = Actions
Actions.inVehicle = false
Actions.enteringVehicle = false
Actions.inPauseMenu = false
Actions.currentWeapon = false
function Actions:GetSeatPedIsIn()
for i = -1, 16 do
@@ -55,21 +59,6 @@ function Actions:TrackPedCoordsOnce()
end)
end
function Actions:TrackPed()
local playerPed = ESX.PlayerData.ped
local newPed = PlayerPedId()
if playerPed ~= newPed then
ESX.SetPlayerData("ped", newPed)
TriggerEvent("esx:playerPedChanged", newPed)
if Config.EnableDebug then
print("[DEBUG] Player ped changed:", newPed)
end
end
end
function Actions:TrackPauseMenu()
local isActive = IsPauseMenuActive()
@@ -189,46 +178,43 @@ function Actions:TrackSeat()
end
end
function Actions:TrackWeapon()
---@type number|false
local newWeapon = GetSelectedPedWeapon(ESX.PlayerData.ped)
newWeapon = newWeapon ~= `WEAPON_UNARMED` and newWeapon or false
if newWeapon ~= self.currentWeapon then
self.currentWeapon = newWeapon
ESX.SetPlayerData("weapon", self.currentWeapon)
TriggerEvent("esx:weaponChanged", self.currentWeapon)
if Config.EnableDebug then
print("[DEBUG] Weapon changed:", self.currentWeapon)
end
end
end
function Actions:SlowLoop()
CreateThread(function()
while ESX.PlayerLoaded do
self:TrackPauseMenu()
self:TrackVehicle()
self:TrackWeapon()
Wait(500)
end
end)
end
function Actions:PedLoop()
CreateThread(function()
while ESX.PlayerLoaded do
self:TrackPed()
Wait(0)
end
end)
end
function Actions:Init()
-- Re-seed the cached values on every (re)login. The change handlers below are
-- registered once at file load so a relogin never stacks duplicate handlers.
ESX.SetPlayerData("ped", xLib.cache.ped)
ESX.SetPlayerData("weapon", xLib.cache.weapon)
self:SlowLoop()
self:PedLoop()
self:TrackPedCoordsOnce()
end
-- Mirror the lib cache into ESX.PlayerData and re-emit the legacy esx: events.
AddEventHandler("xLib:cache:ped", function(ped)
ESX.SetPlayerData("ped", ped)
TriggerEvent("esx:playerPedChanged", ped)
if Config.EnableDebug then
print("[DEBUG] Player ped changed:", ped)
end
end)
AddEventHandler("xLib:cache:weapon", function(weapon)
ESX.SetPlayerData("weapon", weapon)
TriggerEvent("esx:weaponChanged", weapon)
if Config.EnableDebug then
print("[DEBUG] Weapon changed:", weapon)
end
end)
Actions:Init()
@@ -1,38 +0,0 @@
local interactions = {}
local pressedInteractions = {}
function ESX.RemoveInteraction(name)
if not interactions[name] then return end
interactions[name] = nil
end
ESX.RegisterInteraction = function(name, onPress, condition)
interactions[name] = {
condition = condition or function() return true end,
onPress = onPress,
creator = GetInvokingResource() or "es_extended"
}
end
function ESX.GetInteractKey()
local hash = joaat('esx_interact') | 0x80000000
return GetControlInstructionalButton(0, hash, true):sub(3)
end
ESX.RegisterInput("esx_interact", "Interact", "keyboard", "e", function()
for _, interaction in pairs(interactions) do
local success, result = pcall(interaction.condition)
if success and result then
pressedInteractions[#pressedInteractions+1] = interaction
interaction.onPress()
end
end
end)
AddEventHandler("onResourceStop", function(resource)
for name, interaction in pairs(interactions) do
if interaction.creator == resource then
interactions[name] = nil
end
end
end)
@@ -1,54 +0,0 @@
local points = {}
function ESX.CreatePointInternal(coords, distance, hidden, enter, leave)
local point = {
coords = coords,
distance = distance,
hidden = hidden,
enter = enter,
leave = leave,
resource = GetInvokingResource()
}
local handle = ESX.Table.SizeOf(points) + 1
points[handle] = point
return handle
end
function ESX.RemovePointInternal(handle)
points[handle] = nil
end
function ESX.HidePointInternal(handle, hidden)
if points[handle] then
points[handle].hidden = hidden
end
end
function StartPointsLoop()
CreateThread(function()
while true do
local coords = GetEntityCoords(ESX.PlayerData.ped)
for handle, point in pairs(points) do
if not point.hidden and #(coords - point.coords) <= point.distance then
if not point.nearby then
points[handle].nearby = true
points[handle].enter()
end
elseif point.nearby then
points[handle].nearby = false
points[handle].leave()
end
end
Wait(500)
end
end)
end
AddEventHandler('onResourceStop', function(resource)
for handle, point in pairs(points) do
if point.resource == resource then
points[handle] = nil
end
end
end)
@@ -1,70 +0,0 @@
ESX.Streaming = {}
---@param modelHash number | string
---@param cb? function
---@return number | nil
function ESX.Streaming.RequestModel(modelHash, cb)
modelHash = type(modelHash) == "number" and modelHash or joaat(modelHash)
if not IsModelInCdimage(modelHash) then return end
RequestModel(modelHash)
while not HasModelLoaded(modelHash) do Wait(500) end
return cb and cb(modelHash) or modelHash
end
---@param textureDict string
---@param cb? function
---@return string | nil
function ESX.Streaming.RequestStreamedTextureDict(textureDict, cb)
RequestStreamedTextureDict(textureDict, false)
while not HasStreamedTextureDictLoaded(textureDict) do Wait(500) end
return cb and cb(textureDict) or textureDict
end
---@param assetName string
---@param cb? function
---@return string | nil
function ESX.Streaming.RequestNamedPtfxAsset(assetName, cb)
RequestNamedPtfxAsset(assetName)
while not HasNamedPtfxAssetLoaded(assetName) do Wait(500) end
return cb and cb(assetName) or assetName
end
---@param animSet string
---@param cb? function
---@return string | nil
function ESX.Streaming.RequestAnimSet(animSet, cb)
RequestAnimSet(animSet)
while not HasAnimSetLoaded(animSet) do Wait(500) end
return cb and cb(animSet) or animSet
end
---@param animDict string
---@param cb? function
---@return string | nil
function ESX.Streaming.RequestAnimDict(animDict, cb)
RequestAnimDict(animDict)
while not HasAnimDictLoaded(animDict) do Wait(500) end
return cb and cb(animDict) or animDict
end
---@param weaponHash number | string
---@param cb? function
---@return string | number | nil
function ESX.Streaming.RequestWeaponAsset(weaponHash, cb)
RequestWeaponAsset(weaponHash, 31, 0)
while not HasWeaponAssetLoaded(weaponHash) do Wait(500) end
return cb and cb(weaponHash) or weaponHash
end
-4
View File
@@ -49,16 +49,12 @@ client_scripts {
'client/modules/wrapper.lua',
'client/modules/callback.lua',
'client/modules/adjustments.lua',
'client/modules/points.lua',
'client/modules/events.lua',
'client/modules/actions.lua',
'client/modules/death.lua',
'client/modules/npwd.lua',
'client/modules/interactions.lua',
'client/modules/scaleform.lua',
'client/modules/streaming.lua',
}
ui_page {
+1 -1
View File
@@ -87,7 +87,7 @@ if not IsDuplicityVersion() then -- Only register this event for the client
end)
end
local external = { { "Class", "class.lua" }, { "Point", "point.lua" } }
local external = { { "Class", "class.lua" } }
for i = 1, #external do
local module = external[i]
local path = string.format("client/imports/%s", module[2])
+10 -1
View File
@@ -1 +1,10 @@
--All server-side functions outsourced from the Core to the lib will be stored here for compatability, e.g:
--All server-side functions outsourced from the Core to the lib will be stored here for compatability, e.g:
ESX.OneSync.GetPlayersInArea = xLib.onesync.getPlayersInArea
ESX.OneSync.GetClosestPlayer = xLib.onesync.getClosestPlayer
ESX.OneSync.GetPedsInArea = xLib.onesync.getPedsInArea
ESX.OneSync.GetObjectsInArea = xLib.onesync.getObjectsInArea
ESX.OneSync.GetVehiclesInArea = xLib.onesync.getVehiclesInArea
ESX.OneSync.GetClosestPed = xLib.onesync.getClosestPed
ESX.OneSync.GetClosestObject = xLib.onesync.getClosestObject
ESX.OneSync.GetClosestVehicle = xLib.onesync.getClosestVehicle
@@ -1,84 +1,5 @@
ESX.OneSync = {}
---@param source number|vector3
---@param closest boolean
---@param distance? number
---@param ignore? table
---@param routingBucket? number
local function getNearbyPlayers(source, closest, distance, ignore, routingBucket)
local result = {}
local count = 0
local playerPed
local playerCoords
ignore = ignore or {}
if not distance then
distance = 100
end
if type(source) == "number" then
playerPed = GetPlayerPed(source)
if not source then
error("Received invalid first argument (source); should be playerId")
end
playerCoords = GetEntityCoords(playerPed)
if not playerCoords then
error("Received nil value (playerCoords); perhaps source is nil at first place?")
end
end
if type(source) == "vector3" then
playerCoords = source
if not playerCoords then
error("Received nil value (playerCoords); perhaps source is nil at first place?")
end
end
for _, xPlayer in pairs(ESX.Players) do
if not ignore[xPlayer.source] and (not routingBucket or GetPlayerRoutingBucket(xPlayer.source) == routingBucket) then
local entity = GetPlayerPed(xPlayer.source)
local coords = GetEntityCoords(entity)
if not closest then
local dist = #(playerCoords - coords)
if dist <= distance then
count = count + 1
result[count] = { id = xPlayer.source, ped = NetworkGetNetworkIdFromEntity(entity), coords = coords, dist = dist }
end
else
if xPlayer.source ~= source then
local dist = #(playerCoords - coords)
if dist <= (result.dist or distance) then
result = { id = xPlayer.source, ped = NetworkGetNetworkIdFromEntity(entity), coords = coords, dist = dist }
end
end
end
end
end
return result
end
---@param source vector3|number playerId or vector3 coordinates
---@param maxDistance number
---@param ignore? table playerIds to ignore, where the key is playerId and value is true
---@param routingBucket? number
function ESX.OneSync.GetPlayersInArea(source, maxDistance, ignore, routingBucket)
return getNearbyPlayers(source, false, maxDistance, ignore, routingBucket)
end
---@param source vector3|number playerId or vector3 coordinates
---@param maxDistance number
---@param ignore? table playerIds to ignore, where the key is playerId and value is true
---@param routingBucket? number
function ESX.OneSync.GetClosestPlayer(source, maxDistance, ignore, routingBucket)
return getNearbyPlayers(source, true, maxDistance, ignore, routingBucket)
end
---@param vehicleModel number|string
---@param coords vector3|table
---@param heading number
@@ -304,84 +225,3 @@ function ESX.OneSync.SpawnPedInVehicle(model, vehicle, seat, cb)
return Citizen.Await(promise)
end
end
local function getNearbyEntities(entities, coords, modelFilter, maxDistance, isPed)
local nearbyEntities = {}
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)
if not maxDistance or #(coords - entityCoords) <= maxDistance then
nearbyEntities[#nearbyEntities + 1] = NetworkGetNetworkIdFromEntity(entity)
end
end
end
end
return nearbyEntities
end
---@param coords vector3
---@param maxDistance number
---@param modelFilter table models to ignore, where the key is the model hash and the value is true
---@return table
function ESX.OneSync.GetPedsInArea(coords, maxDistance, modelFilter)
return getNearbyEntities(GetAllPeds(), coords, modelFilter, maxDistance, true)
end
---@param coords vector3
---@param maxDistance number
---@param modelFilter table models to ignore, where the key is the model hash and the value is true
---@return table
function ESX.OneSync.GetObjectsInArea(coords, maxDistance, modelFilter)
return getNearbyEntities(GetAllObjects(), coords, modelFilter, maxDistance)
end
---@param coords vector3
---@param maxDistance number
---@param modelFilter table | nil models to ignore, where the key is the model hash and the value is true
---@return table
function ESX.OneSync.GetVehiclesInArea(coords, maxDistance, modelFilter)
return getNearbyEntities(GetAllVehicles(), coords, modelFilter, maxDistance)
end
local function getClosestEntity(entities, coords, modelFilter, isPed)
local distance, closestEntity, closestCoords = 100, 0, vector3(0, 0, 0)
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)
if dist < distance then
closestEntity, distance, closestCoords = entity, dist, entityCoords
end
end
end
end
return NetworkGetNetworkIdFromEntity(closestEntity), distance, closestCoords
end
---@param coords vector3
---@param modelFilter table models to ignore, where the key is the model hash and the value is true
---@return number entityId, number distance, vector3 coords
function ESX.OneSync.GetClosestPed(coords, modelFilter)
return getClosestEntity(GetAllPeds(), coords, modelFilter, true)
end
---@param coords vector3
---@param modelFilter table models to ignore, where the key is the model hash and the value is true
---@return number entityId, number distance, vector3 coords
function ESX.OneSync.GetClosestObject(coords, modelFilter)
return getClosestEntity(GetAllObjects(), coords, modelFilter)
end
---@param coords vector3
---@param modelFilter table models to ignore, where the key is the model hash and the value is true
---@return number entityId, number distance, vector3 coords
function ESX.OneSync.GetClosestVehicle(coords, modelFilter)
return getClosestEntity(GetAllVehicles(), coords, modelFilter)
end
+89
View File
@@ -0,0 +1,89 @@
--[[
Generic client-side player state cache, modelled on ox_lib cache.
Framework agnostic: natives only, no ESX coupling.
Loaded per-resource VM through the lazy loader. PlayerPedId() and friends
return the same value in every client VM, so the cached values are correct
in each resource that requires it.
Exposes the live values as xLib.cache and emits `xLib:cache:<key>` (value, previous)
whenever a tracked value changes. `coords` is read on demand from the live ped
and never stored.
]]
local playerId = PlayerId()
local cache = setmetatable({
playerId = playerId,
ped = PlayerPedId(),
vehicle = false,
seat = false,
weapon = false,
}, {
__index = function(self, key)
if key == "coords" then
return GetEntityCoords(self.ped)
elseif key == "serverId" then
-- resolved lazily: GetPlayerServerId can return -1 before the network
-- session is ready, so only cache it once it is valid.
local id = GetPlayerServerId(playerId)
if id and id ~= -1 then
rawset(self, "serverId", id)
end
return id
end
end,
})
local function set(key, value)
if cache[key] == value then
return
end
local previous = cache[key]
rawset(cache, key, value)
TriggerEvent(("xLib:cache:%s"):format(key), value, previous)
end
local function getSeat(ped, vehicle)
for seat = -1, 16 do
if GetPedInVehicleSeat(vehicle, seat) == ped then
return seat
end
end
return false
end
CreateThread(function()
while true do
local ped = PlayerPedId()
if ped ~= cache.ped then
set("ped", ped)
end
---@type integer|false
local vehicle = GetVehiclePedIsIn(ped, false)
vehicle = vehicle ~= 0 and vehicle or false
if vehicle ~= cache.vehicle then
set("vehicle", vehicle)
set("seat", vehicle and getSeat(ped, vehicle) or false)
elseif vehicle then
local seat = getSeat(ped, vehicle)
if seat ~= cache.seat then
set("seat", seat)
end
end
---@type integer|false
local weapon = GetSelectedPedWeapon(ped)
weapon = weapon ~= `WEAPON_UNARMED` and weapon or false
if weapon ~= cache.weapon then
set("weapon", weapon)
end
Wait(100)
end
end)
return cache
+695
View File
@@ -0,0 +1,695 @@
---@class gamelib
xLib.game = {}
local function isCallable(val)
local valType = type(val)
local mt = getmetatable(val)
return valType == "function" or (valType == "table" and mt ~= nil and type(mt.__call) == "function")
end
---@param ped integer The ped to get the mugshot of
---@param transparent? boolean Whether the mugshot should be transparent
function xLib.game.getPedMugshot(ped, transparent)
if not DoesEntityExist(ped) then
return
end
local mugshot = transparent and RegisterPedheadshotTransparent(ped) or RegisterPedheadshot(ped)
while not IsPedheadshotReady(mugshot) do
Wait(0)
end
return mugshot, GetPedheadshotTxdString(mugshot)
end
---@param object integer | string The object to spawn
---@param coords table | vector3 The coords to spawn the object at
---@param cb? function The callback function
---@param networked? boolean Whether the object should be networked
---@return integer | nil
function xLib.game.spawnObject(object, coords, cb, networked)
local model = type(object) == "number" and object or joaat(object)
xLib.streaming.requestModel(model)
local obj = CreateObject(model, coords.x, coords.y, coords.z, networked == nil or networked, false, true)
return cb and cb(obj) or obj
end
---@param object integer | string The object to spawn
---@param coords table | vector3 The coords to spawn the object at
---@param cb? function The callback function
---@return nil
function xLib.game.spawnLocalObject(object, coords, cb)
xLib.game.spawnObject(object, coords, cb, false)
end
---@param vehicle integer The vehicle to delete
---@return nil
function xLib.game.deleteVehicle(vehicle)
SetEntityAsMissionEntity(vehicle, true, true)
DeleteVehicle(vehicle)
end
---@param object integer The object to delete
---@return nil
function xLib.game.deleteObject(object)
SetEntityAsMissionEntity(object, false, true)
DeleteObject(object)
end
---@param vehicleModel integer | string The vehicle to spawn
---@param coords table | vector3 The coords to spawn the vehicle at
---@param heading number The heading of the vehicle
---@param cb? fun(vehicle: number) The callback function
---@param networked? boolean Whether the vehicle should be networked
---@return number? vehicle
function xLib.game.spawnVehicle(vehicleModel, coords, heading, cb, networked)
if cb and not isCallable(cb) then
error("Invalid callback function")
end
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 isNetworked = networked == nil or networked
local playerCoords = GetEntityCoords(PlayerPedId())
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 error(("Resource ^5%s^1 Tried to spawn vehicle on the client but the position is too far away (Out of onesync range)."):format(executingResource))
end
local promise = not cb and promise.new()
CreateThread(function()
local modelHash = xLib.streaming.requestModel(model)
if not modelHash then
if promise then
promise:reject(("Tried to spawn invalid vehicle - ^5%s^7!"):format(model))
return
end
error(("Tried to spawn invalid vehicle - ^5%s^7!"):format(model))
end
local vehicle = CreateVehicle(model, vector.x, vector.y, vector.z, heading, isNetworked, 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)
while not HasCollisionLoadedAroundEntity(vehicle) do
Wait(0)
end
if promise then
promise:resolve(vehicle)
elseif cb then
cb(vehicle)
end
end)
if promise then
return Citizen.Await(promise)
end
end
---@param vehicle integer The vehicle to spawn
---@param coords table | vector3 The coords to spawn the vehicle at
---@param heading number The heading of the vehicle
---@param cb? function The callback function
---@return nil
function xLib.game.spawnLocalVehicle(vehicle, coords, heading, cb)
xLib.game.spawnVehicle(vehicle, coords, heading, cb, false)
end
---@param vehicle integer The vehicle to check
---@return boolean
function xLib.game.isVehicleEmpty(vehicle)
return GetVehicleNumberOfPassengers(vehicle) == 0 and IsVehicleSeatFree(vehicle, -1)
end
---@return table
function xLib.game.getObjects() -- Leave the function for compatibility
return GetGamePool("CObject")
end
---@param onlyOtherPeds? boolean Whether to exlude the player ped
---@return table
function xLib.game.getPeds(onlyOtherPeds)
local pool = GetGamePool("CPed")
if onlyOtherPeds then
local myPed = PlayerPedId()
for i = 1, #pool do
if pool[i] == myPed then
table.remove(pool, i)
break
end
end
end
return pool
end
---@return table
function xLib.game.getVehicles() -- Leave the function for compatibility
return GetGamePool("CVehicle")
end
---@param onlyOtherPlayers? boolean Whether to exclude the player
---@param returnKeyValue? boolean Whether to return the key value pair
---@param returnPeds? boolean Whether to return the peds
---@return table
function xLib.game.getPlayers(onlyOtherPlayers, returnKeyValue, returnPeds)
local players = {}
local active = GetActivePlayers()
for i = 1, #active do
local currentPlayer = active[i]
local ped = GetPlayerPed(currentPlayer)
if DoesEntityExist(ped) and ((onlyOtherPlayers and currentPlayer ~= PlayerId()) or not onlyOtherPlayers) then
if returnKeyValue then
players[currentPlayer] = ped
else
players[#players + 1] = returnPeds and ped or currentPlayer
end
end
end
return players
end
---@param coords? table | vector3 The coords to get the closest object to
---@param modelFilter? table The model filter
---@return integer, integer
function xLib.game.getClosestObject(coords, modelFilter)
return xLib.entity.closest(xLib.game.getObjects(), false, coords, modelFilter)
end
---@param coords? table | vector3 The coords to get the closest ped to
---@param modelFilter? table The model filter
---@return integer, integer
function xLib.game.getClosestPed(coords, modelFilter)
return xLib.entity.closest(xLib.game.getPeds(true), false, coords, modelFilter)
end
---@param coords? table | vector3 The coords to get the closest player to
---@return integer, integer
function xLib.game.getClosestPlayer(coords)
return xLib.entity.closest(xLib.game.getPlayers(true, true), true, coords, nil)
end
---@param coords? table | vector3 The coords to get the closest vehicle to
---@param modelFilter? table The model filter
---@return integer, integer
function xLib.game.getClosestVehicle(coords, modelFilter)
return xLib.entity.closest(xLib.game.getVehicles(), false, coords, modelFilter)
end
---@param coords table | vector3 The coords to search from
---@param maxDistance number The max distance to search within
---@return table
function xLib.game.getPlayersInArea(coords, maxDistance)
return xLib.entity.EnumerateWithinDistance(xLib.game.getPlayers(true, true), true, coords, maxDistance)
end
---@param coords table | vector3 The coords to search from
---@param maxDistance number The max distance to search within
---@return table
function xLib.game.getVehiclesInArea(coords, maxDistance)
return xLib.entity.EnumerateWithinDistance(xLib.game.getVehicles(), false, coords, maxDistance)
end
---@param coords table | vector3 The coords to search from
---@param maxDistance number The max distance to search within
---@return boolean
function xLib.game.isSpawnPointClear(coords, maxDistance)
return #xLib.game.getVehiclesInArea(coords, maxDistance) == 0
end
---@return integer | nil, vector3 | nil
function xLib.game.getVehicleInDirection()
local _, hit, coords, _, _, entity = xLib.Raycast.FromScreen(5, 10, PlayerPedId())
if hit and IsEntityAVehicle(entity) then
return entity, coords
end
end
local function round(value, numDecimalPlaces)
if numDecimalPlaces then
local power = 10 ^ numDecimalPlaces
return math.floor((value * power) + 0.5) / power
else
return math.floor(value + 0.5)
end
end
local function trim(value)
value = tostring(value)
return (string.gsub(value, "^%s*(.-)%s*$", "%1"))
end
---@param vehicle integer The vehicle to get the properties of
---@return table | nil
function xLib.game.getVehicleProperties(vehicle)
if not DoesEntityExist(vehicle) then
return
end
---@type number | number[], number | number[]
local colorPrimary, colorSecondary = GetVehicleColours(vehicle)
local pearlescentColor, wheelColor = GetVehicleExtraColours(vehicle)
local dashboardColor = GetVehicleDashboardColor(vehicle)
local interiorColor = GetVehicleInteriorColour(vehicle)
if GetIsVehiclePrimaryColourCustom(vehicle) then
colorPrimary = { GetVehicleCustomPrimaryColour(vehicle) }
end
if GetIsVehicleSecondaryColourCustom(vehicle) then
colorSecondary = { GetVehicleCustomSecondaryColour(vehicle) }
end
local hasCustomXenonColor, customXenonColorR, customXenonColorG, customXenonColorB = GetVehicleXenonLightsCustomColor(vehicle)
local customXenonColor = nil
if hasCustomXenonColor then
customXenonColor = { customXenonColorR, customXenonColorG, customXenonColorB }
end
local extras = {}
for extraId = 0, 20 do
if DoesExtraExist(vehicle, extraId) then
extras[tostring(extraId)] = IsVehicleExtraTurnedOn(vehicle, extraId)
end
end
local doorsBroken, windowsBroken, tyreBurst = {}, {}, {}
local numWheels = tostring(GetVehicleNumberOfWheels(vehicle))
local TyresIndex = { -- Wheel index list according to the number of vehicle wheels.
["2"] = { 0, 4 }, -- Bike and cycle.
["3"] = { 0, 1, 4, 5 }, -- Vehicle with 3 wheels (get for wheels because some 3 wheels vehicles have 2 wheels on front and one rear or the reverse).
["4"] = { 0, 1, 4, 5 }, -- Vehicle with 4 wheels.
["6"] = { 0, 1, 2, 3, 4, 5 }, -- Vehicle with 6 wheels.
}
if TyresIndex[numWheels] then
for _, idx in pairs(TyresIndex[numWheels]) do
tyreBurst[tostring(idx)] = IsVehicleTyreBurst(vehicle, idx, false)
end
end
for windowId = 0, 7 do -- 13
RollUpWindow(vehicle, windowId) --fix when you put the car away with the window down
windowsBroken[tostring(windowId)] = not IsVehicleWindowIntact(vehicle, windowId)
end
local numDoors = GetNumberOfVehicleDoors(vehicle)
if numDoors and numDoors > 0 then
for doorsId = 0, numDoors do
doorsBroken[tostring(doorsId)] = IsVehicleDoorDamaged(vehicle, doorsId)
end
end
return {
model = GetEntityModel(vehicle),
doorsBroken = doorsBroken,
windowsBroken = windowsBroken,
tyreBurst = tyreBurst,
tyresCanBurst = GetVehicleTyresCanBurst(vehicle),
plate = trim(GetVehicleNumberPlateText(vehicle)),
plateIndex = GetVehicleNumberPlateTextIndex(vehicle),
bodyHealth = round(GetVehicleBodyHealth(vehicle), 1),
engineHealth = round(GetVehicleEngineHealth(vehicle), 1),
tankHealth = round(GetVehiclePetrolTankHealth(vehicle), 1),
fuelLevel = round(GetVehicleFuelLevel(vehicle), 1),
dirtLevel = round(GetVehicleDirtLevel(vehicle), 1),
color1 = colorPrimary,
color2 = colorSecondary,
pearlescentColor = pearlescentColor,
wheelColor = wheelColor,
dashboardColor = dashboardColor,
interiorColor = interiorColor,
wheels = GetVehicleWheelType(vehicle),
windowTint = GetVehicleWindowTint(vehicle),
xenonColor = GetVehicleXenonLightsColor(vehicle),
customXenonColor = customXenonColor,
neonEnabled = { IsVehicleNeonLightEnabled(vehicle, 0), IsVehicleNeonLightEnabled(vehicle, 1), IsVehicleNeonLightEnabled(vehicle, 2), IsVehicleNeonLightEnabled(vehicle, 3) },
neonColor = table.pack(GetVehicleNeonLightsColour(vehicle)),
extras = extras,
tyreSmokeColor = table.pack(GetVehicleTyreSmokeColor(vehicle)),
modSpoilers = GetVehicleMod(vehicle, 0),
modFrontBumper = GetVehicleMod(vehicle, 1),
modRearBumper = GetVehicleMod(vehicle, 2),
modSideSkirt = GetVehicleMod(vehicle, 3),
modExhaust = GetVehicleMod(vehicle, 4),
modFrame = GetVehicleMod(vehicle, 5),
modGrille = GetVehicleMod(vehicle, 6),
modHood = GetVehicleMod(vehicle, 7),
modFender = GetVehicleMod(vehicle, 8),
modRightFender = GetVehicleMod(vehicle, 9),
modRoof = GetVehicleMod(vehicle, 10),
modRoofLivery = GetVehicleRoofLivery(vehicle),
modEngine = GetVehicleMod(vehicle, 11),
modBrakes = GetVehicleMod(vehicle, 12),
modTransmission = GetVehicleMod(vehicle, 13),
modHorns = GetVehicleMod(vehicle, 14),
modSuspension = GetVehicleMod(vehicle, 15),
modArmor = GetVehicleMod(vehicle, 16),
modTurbo = IsToggleModOn(vehicle, 18),
modSmokeEnabled = IsToggleModOn(vehicle, 20),
modXenon = IsToggleModOn(vehicle, 22),
modFrontWheels = GetVehicleMod(vehicle, 23),
modCustomFrontWheels = GetVehicleModVariation(vehicle, 23),
modBackWheels = GetVehicleMod(vehicle, 24),
modCustomBackWheels = GetVehicleModVariation(vehicle, 24),
modPlateHolder = GetVehicleMod(vehicle, 25),
modVanityPlate = GetVehicleMod(vehicle, 26),
modTrimA = GetVehicleMod(vehicle, 27),
modOrnaments = GetVehicleMod(vehicle, 28),
modDashboard = GetVehicleMod(vehicle, 29),
modDial = GetVehicleMod(vehicle, 30),
modDoorSpeaker = GetVehicleMod(vehicle, 31),
modSeats = GetVehicleMod(vehicle, 32),
modSteeringWheel = GetVehicleMod(vehicle, 33),
modShifterLeavers = GetVehicleMod(vehicle, 34),
modAPlate = GetVehicleMod(vehicle, 35),
modSpeakers = GetVehicleMod(vehicle, 36),
modTrunk = GetVehicleMod(vehicle, 37),
modHydrolic = GetVehicleMod(vehicle, 38),
modEngineBlock = GetVehicleMod(vehicle, 39),
modAirFilter = GetVehicleMod(vehicle, 40),
modStruts = GetVehicleMod(vehicle, 41),
modArchCover = GetVehicleMod(vehicle, 42),
modAerials = GetVehicleMod(vehicle, 43),
modTrimB = GetVehicleMod(vehicle, 44),
modTank = GetVehicleMod(vehicle, 45),
modWindows = GetVehicleMod(vehicle, 46),
modLivery = GetVehicleMod(vehicle, 48) == -1 and GetVehicleLivery(vehicle) or GetVehicleMod(vehicle, 48),
modLightbar = GetVehicleMod(vehicle, 49),
}
end
---@param vehicle integer The vehicle to set the properties of
---@param props table The properties to set
---@return nil
function xLib.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
SetVehicleTyresCanBurst(vehicle, props.tyresCanBurst)
end
if props.plate ~= nil then
SetVehicleNumberPlateText(vehicle, props.plate)
end
if props.plateIndex ~= nil then
SetVehicleNumberPlateTextIndex(vehicle, props.plateIndex)
end
if props.bodyHealth ~= nil then
SetVehicleBodyHealth(vehicle, props.bodyHealth + 0.0)
end
if props.engineHealth ~= nil then
SetVehicleEngineHealth(vehicle, props.engineHealth + 0.0)
end
if props.tankHealth ~= nil then
SetVehiclePetrolTankHealth(vehicle, props.tankHealth + 0.0)
end
if props.fuelLevel ~= nil then
SetVehicleFuelLevel(vehicle, props.fuelLevel + 0.0)
end
if props.dirtLevel ~= nil then
SetVehicleDirtLevel(vehicle, props.dirtLevel + 0.0)
end
if props.color1 ~= nil then
if type(props.color1) == "table" then
SetVehicleCustomPrimaryColour(vehicle, props.color1[1], props.color1[2], props.color1[3])
else
SetVehicleColours(vehicle, props.color1, colorSecondary)
end
end
if props.color2 ~= nil then
if type(props.color2) == "table" then
SetVehicleCustomSecondaryColour(vehicle, props.color2[1], props.color2[2], props.color2[3])
else
SetVehicleColours(vehicle, props.color1 or colorPrimary, props.color2)
end
end
if props.pearlescentColor ~= nil then
SetVehicleExtraColours(vehicle, props.pearlescentColor, wheelColor)
end
if props.interiorColor ~= nil then
SetVehicleInteriorColor(vehicle, props.interiorColor)
end
if props.dashboardColor ~= nil then
SetVehicleDashboardColor(vehicle, props.dashboardColor)
end
if props.wheelColor ~= nil then
SetVehicleExtraColours(vehicle, props.pearlescentColor or pearlescentColor, props.wheelColor)
end
if props.wheels ~= nil then
SetVehicleWheelType(vehicle, props.wheels)
end
if props.windowTint ~= nil then
SetVehicleWindowTint(vehicle, props.windowTint)
end
if props.neonEnabled ~= nil 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
for extraId, enabled in pairs(props.extras) do
extraId = tonumber(extraId)
if extraId then
SetVehicleExtra(vehicle, extraId, not enabled)
end
end
end
if props.neonColor ~= nil then
SetVehicleNeonLightsColour(vehicle, props.neonColor[1], props.neonColor[2], props.neonColor[3])
end
if props.xenonColor ~= nil then
SetVehicleXenonLightsColor(vehicle, props.xenonColor)
end
if props.customXenonColor ~= nil then
SetVehicleXenonLightsCustomColor(vehicle, props.customXenonColor[1], props.customXenonColor[2], props.customXenonColor[3])
end
if props.modSmokeEnabled ~= nil then
ToggleVehicleMod(vehicle, 20, true)
end
if props.tyreSmokeColor ~= nil then
SetVehicleTyreSmokeColor(vehicle, props.tyreSmokeColor[1], props.tyreSmokeColor[2], props.tyreSmokeColor[3])
end
if props.modSpoilers ~= nil then
SetVehicleMod(vehicle, 0, props.modSpoilers, false)
end
if props.modFrontBumper ~= nil then
SetVehicleMod(vehicle, 1, props.modFrontBumper, false)
end
if props.modRearBumper ~= nil then
SetVehicleMod(vehicle, 2, props.modRearBumper, false)
end
if props.modSideSkirt ~= nil then
SetVehicleMod(vehicle, 3, props.modSideSkirt, false)
end
if props.modExhaust ~= nil then
SetVehicleMod(vehicle, 4, props.modExhaust, false)
end
if props.modFrame ~= nil then
SetVehicleMod(vehicle, 5, props.modFrame, false)
end
if props.modGrille ~= nil then
SetVehicleMod(vehicle, 6, props.modGrille, false)
end
if props.modHood ~= nil then
SetVehicleMod(vehicle, 7, props.modHood, false)
end
if props.modFender ~= nil then
SetVehicleMod(vehicle, 8, props.modFender, false)
end
if props.modRightFender ~= nil then
SetVehicleMod(vehicle, 9, props.modRightFender, false)
end
if props.modRoof ~= nil then
SetVehicleMod(vehicle, 10, props.modRoof, false)
end
if props.modRoofLivery ~= nil then
SetVehicleRoofLivery(vehicle, props.modRoofLivery)
end
if props.modEngine ~= nil then
SetVehicleMod(vehicle, 11, props.modEngine, false)
end
if props.modBrakes ~= nil then
SetVehicleMod(vehicle, 12, props.modBrakes, false)
end
if props.modTransmission ~= nil then
SetVehicleMod(vehicle, 13, props.modTransmission, false)
end
if props.modHorns ~= nil then
SetVehicleMod(vehicle, 14, props.modHorns, false)
end
if props.modSuspension ~= nil then
SetVehicleMod(vehicle, 15, props.modSuspension, false)
end
if props.modArmor ~= nil then
SetVehicleMod(vehicle, 16, props.modArmor, false)
end
if props.modTurbo ~= nil then
ToggleVehicleMod(vehicle, 18, props.modTurbo)
end
if props.modXenon ~= nil then
ToggleVehicleMod(vehicle, 22, props.modXenon)
end
if props.modFrontWheels ~= nil then
SetVehicleMod(vehicle, 23, props.modFrontWheels, props.modCustomFrontWheels)
end
if props.modBackWheels ~= nil then
SetVehicleMod(vehicle, 24, props.modBackWheels, props.modCustomBackWheels)
end
if props.modPlateHolder ~= nil then
SetVehicleMod(vehicle, 25, props.modPlateHolder, false)
end
if props.modVanityPlate ~= nil then
SetVehicleMod(vehicle, 26, props.modVanityPlate, false)
end
if props.modTrimA ~= nil then
SetVehicleMod(vehicle, 27, props.modTrimA, false)
end
if props.modOrnaments ~= nil then
SetVehicleMod(vehicle, 28, props.modOrnaments, false)
end
if props.modDashboard ~= nil then
SetVehicleMod(vehicle, 29, props.modDashboard, false)
end
if props.modDial ~= nil then
SetVehicleMod(vehicle, 30, props.modDial, false)
end
if props.modDoorSpeaker ~= nil then
SetVehicleMod(vehicle, 31, props.modDoorSpeaker, false)
end
if props.modSeats ~= nil then
SetVehicleMod(vehicle, 32, props.modSeats, false)
end
if props.modSteeringWheel ~= nil then
SetVehicleMod(vehicle, 33, props.modSteeringWheel, false)
end
if props.modShifterLeavers ~= nil then
SetVehicleMod(vehicle, 34, props.modShifterLeavers, false)
end
if props.modAPlate ~= nil then
SetVehicleMod(vehicle, 35, props.modAPlate, false)
end
if props.modSpeakers ~= nil then
SetVehicleMod(vehicle, 36, props.modSpeakers, false)
end
if props.modTrunk ~= nil then
SetVehicleMod(vehicle, 37, props.modTrunk, false)
end
if props.modHydrolic ~= nil then
SetVehicleMod(vehicle, 38, props.modHydrolic, false)
end
if props.modEngineBlock ~= nil then
SetVehicleMod(vehicle, 39, props.modEngineBlock, false)
end
if props.modAirFilter ~= nil then
SetVehicleMod(vehicle, 40, props.modAirFilter, false)
end
if props.modStruts ~= nil then
SetVehicleMod(vehicle, 41, props.modStruts, false)
end
if props.modArchCover ~= nil then
SetVehicleMod(vehicle, 42, props.modArchCover, false)
end
if props.modAerials ~= nil then
SetVehicleMod(vehicle, 43, props.modAerials, false)
end
if props.modTrimB ~= nil then
SetVehicleMod(vehicle, 44, props.modTrimB, false)
end
if props.modTank ~= nil then
SetVehicleMod(vehicle, 45, props.modTank, false)
end
if props.modWindows ~= nil then
SetVehicleMod(vehicle, 46, props.modWindows, false)
end
if props.modLivery ~= nil then
SetVehicleMod(vehicle, 48, props.modLivery, false)
SetVehicleLivery(vehicle, props.modLivery)
end
if props.windowsBroken ~= nil then
for k, v in pairs(props.windowsBroken) do
if v then
k = tonumber(k)
if k then
RemoveVehicleWindow(vehicle, k)
end
end
end
end
if props.doorsBroken ~= nil then
for k, v in pairs(props.doorsBroken) do
if v then
k = tonumber(k)
if k then
SetVehicleDoorBroken(vehicle, k, true)
end
end
end
end
if props.tyreBurst ~= nil then
for k, v in pairs(props.tyreBurst) do
if v then
k = tonumber(k)
if k then
SetVehicleTyreBurst(vehicle, k, true, 1000.0)
end
end
end
end
end
return xLib.game
@@ -0,0 +1,54 @@
---@class interactionslib
xLib.interactions = {}
local interactions = {}
local pressedInteractions = {}
---@param name string
function xLib.interactions.remove(name)
if not interactions[name] then return end
interactions[name] = nil
end
---@param name string
---@param onPress function
---@param condition? function
function xLib.interactions.register(name, onPress, condition)
interactions[name] = {
condition = condition or function() return true end,
onPress = onPress,
creator = GetInvokingResource() or "es_extended"
}
end
---@return string
function xLib.interactions.getInteractKey()
local hash = joaat("esx_interact") | 0x80000000
return GetControlInstructionalButton(0, hash, true):sub(3)
end
xLib.addKeybind({
name = "esx_interact",
description = "Interact",
defaultMapper = "keyboard",
defaultKey = "e",
onPressed = function()
for _, interaction in pairs(interactions) do
local success, result = pcall(interaction.condition)
if success and result then
pressedInteractions[#pressedInteractions + 1] = interaction
interaction.onPress()
end
end
end
})
AddEventHandler("onResourceStop", function(resource)
for name, interaction in pairs(interactions) do
if interaction.creator == resource then
interactions[name] = nil
end
end
end)
return xLib.interactions
+164
View File
@@ -0,0 +1,164 @@
---@class onesynclib
xLib.onesync = {}
---@param source number|vector3
---@param closest boolean
---@param distance? number
---@param ignore? table
---@param routingBucket? number
local function getNearbyPlayers(source, closest, distance, ignore, routingBucket)
local result = {}
local count = 0
local playerPed
local playerCoords
ignore = ignore or {}
if not distance then
distance = 100
end
if type(source) == "number" then
playerPed = GetPlayerPed(source)
if not source then
error("Received invalid first argument (source); should be playerId")
end
playerCoords = GetEntityCoords(playerPed)
if not playerCoords then
error("Received nil value (playerCoords); perhaps source is nil at first place?")
end
end
if type(source) == "vector3" then
playerCoords = source
if not playerCoords then
error("Received nil value (playerCoords); perhaps source is nil at first place?")
end
end
for _, xPlayer in pairs(ESX.Players) do
if not ignore[xPlayer.source] and (not routingBucket or GetPlayerRoutingBucket(xPlayer.source) == routingBucket) then
local entity = GetPlayerPed(xPlayer.source)
local coords = GetEntityCoords(entity)
if not closest then
local dist = #(playerCoords - coords)
if dist <= distance then
count = count + 1
result[count] = { id = xPlayer.source, ped = NetworkGetNetworkIdFromEntity(entity), coords = coords, dist = dist }
end
else
if xPlayer.source ~= source then
local dist = #(playerCoords - coords)
if dist <= (result.dist or distance) then
result = { id = xPlayer.source, ped = NetworkGetNetworkIdFromEntity(entity), coords = coords, dist = dist }
end
end
end
end
end
return result
end
---@param source vector3|number playerId or vector3 coordinates
---@param maxDistance number
---@param ignore? table playerIds to ignore, where the key is playerId and value is true
---@param routingBucket? number
function xLib.onesync.getPlayersInArea(source, maxDistance, ignore, routingBucket)
return getNearbyPlayers(source, false, maxDistance, ignore, routingBucket)
end
---@param source vector3|number playerId or vector3 coordinates
---@param maxDistance number
---@param ignore? table playerIds to ignore, where the key is playerId and value is true
---@param routingBucket? number
function xLib.onesync.getClosestPlayer(source, maxDistance, ignore, routingBucket)
return getNearbyPlayers(source, true, maxDistance, ignore, routingBucket)
end
local function getNearbyEntities(entities, coords, modelFilter, maxDistance, isPed)
local nearbyEntities = {}
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)
if not maxDistance or #(coords - entityCoords) <= maxDistance then
nearbyEntities[#nearbyEntities + 1] = NetworkGetNetworkIdFromEntity(entity)
end
end
end
end
return nearbyEntities
end
---@param coords vector3
---@param maxDistance number
---@param modelFilter table models to ignore, where the key is the model hash and the value is true
---@return table
function xLib.onesync.getPedsInArea(coords, maxDistance, modelFilter)
return getNearbyEntities(GetAllPeds(), coords, modelFilter, maxDistance, true)
end
---@param coords vector3
---@param maxDistance number
---@param modelFilter table models to ignore, where the key is the model hash and the value is true
---@return table
function xLib.onesync.getObjectsInArea(coords, maxDistance, modelFilter)
return getNearbyEntities(GetAllObjects(), coords, modelFilter, maxDistance)
end
---@param coords vector3
---@param maxDistance number
---@param modelFilter table | nil models to ignore, where the key is the model hash and the value is true
---@return table
function xLib.onesync.getVehiclesInArea(coords, maxDistance, modelFilter)
return getNearbyEntities(GetAllVehicles(), coords, modelFilter, maxDistance)
end
local function getClosestEntity(entities, coords, modelFilter, isPed)
local distance, closestEntity, closestCoords = 100, 0, vector3(0, 0, 0)
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)
if dist < distance then
closestEntity, distance, closestCoords = entity, dist, entityCoords
end
end
end
end
return NetworkGetNetworkIdFromEntity(closestEntity), distance, closestCoords
end
---@param coords vector3
---@param modelFilter table models to ignore, where the key is the model hash and the value is true
---@return number entityId, number distance, vector3 coords
function xLib.onesync.getClosestPed(coords, modelFilter)
return getClosestEntity(GetAllPeds(), coords, modelFilter, true)
end
---@param coords vector3
---@param modelFilter table models to ignore, where the key is the model hash and the value is true
---@return number entityId, number distance, vector3 coords
function xLib.onesync.getClosestObject(coords, modelFilter)
return getClosestEntity(GetAllObjects(), coords, modelFilter)
end
---@param coords vector3
---@param modelFilter table models to ignore, where the key is the model hash and the value is true
---@return number entityId, number distance, vector3 coords
function xLib.onesync.getClosestVehicle(coords, modelFilter)
return getClosestEntity(GetAllVehicles(), coords, modelFilter)
end
return xLib.onesync
+52
View File
@@ -0,0 +1,52 @@
---@class xPoint
---@field coords vector3
---@field hidden? boolean
---@field enter? function
---@field leave? function
---@field inside? function
---@field handle integer
xLib.point = xLib.class()
---@param properties table coords, distance, hidden, enter, leave, inside
function xLib.point:constructor(properties)
self.coords = properties.coords
self.hidden = properties.hidden
self.enter = properties.enter
self.leave = properties.leave
self.inside = properties.inside
self.handle = xLib.points.create(
properties.coords,
properties.distance,
properties.hidden,
function()
if self.enter then
self:enter()
end
end,
function()
if self.leave then
self:leave()
end
end,
properties.inside and function(dist)
self:inside(dist)
end or nil
)
end
function xLib.point:delete()
xLib.points.remove(self.handle)
end
---@param hidden? boolean
function xLib.point:toggle(hidden)
if hidden == nil then
hidden = not self.hidden
end
self.hidden = hidden
xLib.points.hide(self.handle, hidden)
end
return xLib.point
+100
View File
@@ -0,0 +1,100 @@
---@class pointslib
xLib.points = {}
local points = {}
local insidePoints = {}
local handleCount = 0
---@param coords vector3
---@param distance number
---@param hidden? boolean
---@param enter function
---@param leave function
---@param inside? function
---@return integer handle
function xLib.points.create(coords, distance, hidden, enter, leave, inside)
handleCount = handleCount + 1
local handle = handleCount
points[handle] = {
coords = coords,
distance = distance,
hidden = hidden,
enter = enter,
leave = leave,
inside = inside,
resource = GetInvokingResource()
}
return handle
end
---@param handle integer
function xLib.points.remove(handle)
points[handle] = nil
insidePoints[handle] = nil
end
---@param handle integer
---@param hidden boolean
function xLib.points.hide(handle, hidden)
if points[handle] then
points[handle].hidden = hidden
end
end
function xLib.points.startLoop()
CreateThread(function()
local lastScan = 0
while true do
local coords = GetEntityCoords(PlayerPedId())
for _, point in pairs(insidePoints) do
point.inside(#(coords - point.coords))
end
local now = GetGameTimer()
if now - lastScan >= 500 then
lastScan = now
for handle, point in pairs(points) do
if not point.hidden and #(coords - point.coords) <= point.distance then
if not point.nearby then
point.nearby = true
if point.enter then
point.enter()
end
if point.inside then
insidePoints[handle] = point
end
end
elseif point.nearby then
point.nearby = false
if point.leave then
point.leave()
end
insidePoints[handle] = nil
end
end
end
Wait(next(insidePoints) and 0 or 500)
end
end)
end
AddEventHandler("onResourceStop", function(resource)
for handle, point in pairs(points) do
if point.resource == resource then
points[handle] = nil
insidePoints[handle] = nil
end
end
end)
return xLib.points
@@ -1,22 +1,12 @@
ESX.Scaleform = {}
ESX.Scaleform.Utils = {}
---@class scaleformlib
xLib.scaleform = {}
xLib.scaleform.utils = {}
function ESX.Scaleform.ShowFreemodeMessage(title, msg, sec)
local scaleform = ESX.Scaleform.Utils.RunMethod("MP_BIG_MESSAGE_FREEMODE", "SHOW_SHARD_WASTED_MP_MESSAGE", false, title, msg)
local endTime = GetGameTimer() + (sec * 1000)
while GetGameTimer() < endTime do
Wait(0)
DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255, 0)
end
SetScaleformMovieAsNoLongerNeeded(scaleform)
end
function ESX.Scaleform.ShowBreakingNews(title, msg, bottom, sec)
local scaleform = ESX.Scaleform.Utils.RunMethod("BREAKING_NEWS", "SET_TEXT", false, msg, bottom)
ESX.Scaleform.Utils.RunMethod(scaleform, "SET_SCROLL_TEXT", false, 0, 0, title)
ESX.Scaleform.Utils.RunMethod(scaleform, "DISPLAY_SCROLL_TEXT", false, 0, 0)
---@param title string
---@param msg string
---@param sec number
function xLib.scaleform.showFreemodeMessage(title, msg, sec)
local scaleform = xLib.scaleform.utils.runMethod("MP_BIG_MESSAGE_FREEMODE", "SHOW_SHARD_WASTED_MP_MESSAGE", false, title, msg)
local endTime = GetGameTimer() + (sec * 1000)
while GetGameTimer() < endTime do
@@ -27,8 +17,14 @@ function ESX.Scaleform.ShowBreakingNews(title, msg, bottom, sec)
SetScaleformMovieAsNoLongerNeeded(scaleform)
end
function ESX.Scaleform.ShowPopupWarning(title, msg, bottom, sec)
local scaleform = ESX.Scaleform.Utils.RunMethod("POPUP_WARNING", "SHOW_POPUP_WARNING", false, 500.0, title, msg, bottom, true)
---@param title string
---@param msg string
---@param bottom string
---@param sec number
function xLib.scaleform.showBreakingNews(title, msg, bottom, sec)
local scaleform = xLib.scaleform.utils.runMethod("BREAKING_NEWS", "SET_TEXT", false, msg, bottom)
xLib.scaleform.utils.runMethod(scaleform, "SET_SCROLL_TEXT", false, 0, 0, title)
xLib.scaleform.utils.runMethod(scaleform, "DISPLAY_SCROLL_TEXT", false, 0, 0)
local endTime = GetGameTimer() + (sec * 1000)
while GetGameTimer() < endTime do
@@ -39,8 +35,12 @@ function ESX.Scaleform.ShowPopupWarning(title, msg, bottom, sec)
SetScaleformMovieAsNoLongerNeeded(scaleform)
end
function ESX.Scaleform.ShowTrafficMovie(sec)
local scaleform = ESX.Scaleform.Utils.RunMethod("TRAFFIC_CAM", "PLAY_CAM_MOVIE", false)
---@param title string
---@param msg string
---@param bottom string
---@param sec number
function xLib.scaleform.showPopupWarning(title, msg, bottom, sec)
local scaleform = xLib.scaleform.utils.runMethod("POPUP_WARNING", "SHOW_POPUP_WARNING", false, 500.0, title, msg, bottom, true)
local endTime = GetGameTimer() + (sec * 1000)
while GetGameTimer() < endTime do
@@ -51,7 +51,22 @@ function ESX.Scaleform.ShowTrafficMovie(sec)
SetScaleformMovieAsNoLongerNeeded(scaleform)
end
function ESX.Scaleform.Utils.RequestScaleformMovie(movie)
---@param sec number
function xLib.scaleform.showTrafficMovie(sec)
local scaleform = xLib.scaleform.utils.runMethod("TRAFFIC_CAM", "PLAY_CAM_MOVIE", false)
local endTime = GetGameTimer() + (sec * 1000)
while GetGameTimer() < endTime do
Wait(0)
DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255, 0)
end
SetScaleformMovieAsNoLongerNeeded(scaleform)
end
---@param movie string
---@return number
function xLib.scaleform.utils.requestScaleformMovie(movie)
local scaleform = RequestScaleformMovie(movie)
while not HasScaleformMovieLoaded(scaleform) do
@@ -68,8 +83,11 @@ end
---@param returnValue? boolean # Whether to return the value from the method
---@param ... number|string|boolean # Arguments to pass to the method
---@return number, number? # The scaleform handle, and the return value if `returnValue` is true
function ESX.Scaleform.Utils.RunMethod(scaleform, methodName, returnValue, ...)
scaleform = type(scaleform) == "number" and scaleform or ESX.Scaleform.Utils.RequestScaleformMovie(scaleform)
function xLib.scaleform.utils.runMethod(scaleform, methodName, returnValue, ...)
if type(scaleform) ~= "number" then
scaleform = xLib.scaleform.utils.requestScaleformMovie(scaleform)
end
BeginScaleformMovieMethod(scaleform, methodName)
local args = { ... }
@@ -97,3 +115,5 @@ function ESX.Scaleform.Utils.RunMethod(scaleform, methodName, returnValue, ...)
return scaleform
end
return xLib.scaleform
@@ -0,0 +1,86 @@
---@class streaminglib
xLib.streaming = {}
---@param modelHash number | string
---@param cb? function
---@return number | nil
function xLib.streaming.requestModel(modelHash, cb)
modelHash = type(modelHash) == "number" and modelHash or joaat(modelHash)
if not IsModelInCdimage(modelHash) then return end
RequestModel(modelHash)
while not HasModelLoaded(modelHash) do
Wait(500)
end
return cb and cb(modelHash) or modelHash
end
---@param textureDict string
---@param cb? function
---@return string | nil
function xLib.streaming.requestStreamedTextureDict(textureDict, cb)
RequestStreamedTextureDict(textureDict, false)
while not HasStreamedTextureDictLoaded(textureDict) do
Wait(500)
end
return cb and cb(textureDict) or textureDict
end
---@param assetName string
---@param cb? function
---@return string | nil
function xLib.streaming.requestNamedPtfxAsset(assetName, cb)
RequestNamedPtfxAsset(assetName)
while not HasNamedPtfxAssetLoaded(assetName) do
Wait(500)
end
return cb and cb(assetName) or assetName
end
---@param animSet string
---@param cb? function
---@return string | nil
function xLib.streaming.requestAnimSet(animSet, cb)
RequestAnimSet(animSet)
while not HasAnimSetLoaded(animSet) do
Wait(500)
end
return cb and cb(animSet) or animSet
end
---@param animDict string
---@param cb? function
---@return string | nil
function xLib.streaming.requestAnimDict(animDict, cb)
RequestAnimDict(animDict)
while not HasAnimDictLoaded(animDict) do
Wait(500)
end
return cb and cb(animDict) or animDict
end
---@param weaponHash number | string
---@param cb? function
---@return string | number | nil
function xLib.streaming.requestWeaponAsset(weaponHash, cb)
RequestWeaponAsset(weaponHash, 31, 0)
while not HasWeaponAssetLoaded(weaponHash) do
Wait(500)
end
return cb and cb(weaponHash) or weaponHash
end
return xLib.streaming
+11 -4
View File
@@ -8,6 +8,7 @@
local registeredCallbacks = {}
local resource_name = GetCurrentResourceName() --TODO: Add cache
local IS_DEBUG <const> = GetConvar("xLib:debug", "false") == "true"
AddEventHandler('onResourceStop', function(resourceName)
@@ -37,13 +38,19 @@ function xLib.setValidCallback(callbackName, isValid)
if callbackResource == resourceName then return end
local errMessage = ("^1resource '%s' attempted to overwrite callback '%s' owned by resource '%s'^0"):format(resourceName, callbackName, callbackResource)
if IS_DEBUG then
local errMessage = ("^1resource '%s' attempted to overwrite callback '%s' owned by resource '%s'^0"):format(resourceName, callbackName, callbackResource)
return print(('^1SCRIPT ERROR: %s^0\n%s'):format(errMessage,
Citizen.InvokeNative(`FORMAT_STACK_TRACE` & 0xFFFFFFFF, nil, 0, Citizen.ResultAsString()) or ''))
print(('^1SCRIPT ERROR: %s^0\n%s'):format(errMessage,
Citizen.InvokeNative(`FORMAT_STACK_TRACE` & 0xFFFFFFFF, nil, 0, Citizen.ResultAsString()) or ''))
end
return
end
print(("set valid callback '%s' for resource '%s'"):format(callbackName, resourceName))
if IS_DEBUG then
print(("set valid callback '%s' for resource '%s'"):format(callbackName, resourceName))
end
registeredCallbacks[callbackName] = resourceName
end