Utils
Quality of life scripts for your FiveM server. Performance optimized resources that install in minutes, with free updates and support that actually answers.
bridge/client.lua
lua
function ControlsDisabled()
DisablePlayerFiring(PlayerPedId(), true)
HudWeaponWheelIgnoreSelection()
DisableControlAction(0, 1, true)
DisableControlAction(0, 2, true)
DisableControlAction(0, 24, true)
DisableControlAction(0, 25, true)
DisableControlAction(0, 37, true)
DisableControlAction(0, 38, true)
DisableControlAction(0, 45, true)
DisableControlAction(0, 46, true)
DisableControlAction(0, 245, true)
DisableControlAction(0, 263, true)
DisableControlAction(0, 264, true)
DisableControlAction(0, 257, true)
DisableControlAction(0, 140, true)
DisableControlAction(0, 141, true)
DisableControlAction(0, 142, true)
DisableControlAction(0, 143, true)
DisableControlAction(0, 322, true)
end
---@param message string
---@param data table
function SendMessage(message, data)
if not Config.DisableMessages then
print('Player: '..json.encode(data, { indent = true }))
TriggerEvent('chat:addMessage', {
templateId = 'default',
multiline = true,
args = {"Player List", message}
})
end
end
---@param data table { coords: vec3, font_size: number, font_style: number, color: {r: number, g: number, b: number}, text: string }
function OverHeadText(data)
local onScreen, screenX, screenY = World3dToScreen2d(data.coords.x, data.coords.y, data.coords.z)
if onScreen then
local camCoords = GetGameplayCamCoords()
local distance = #(data.coords - camCoords)
local fov = (1 / GetGameplayCamFov()) * 75
local scale = (1 / distance) * (4) * fov * (data.font_size)
SetTextScale(0.0, scale)
SetTextFont(data.font_style)
SetTextProportional(true)
SetTextColour(data.color.r, data.color.g, data.color.b, 255)
SetTextOutline()
SetTextEntry("STRING")
SetTextCentre(true)
AddTextComponentString(data.text)
DrawText(screenX, screenY)
end
endbridge/server.lua
lua
---@param playerSrc number
---@param format string ('identifier' | 'name_identifier' | 'name_ping' | 'name' | 'id' | 'citizenid')
---@return string
local function formatPlayerText(playerSrc, format)
local playerId = tostring(playerSrc)
local identifier = GetPlayerIdentifierByType(playerId, Config.UseIdentifier)
if format == 'identifier' then
return identifier or 'Unknown'
elseif format == 'name_identifier' then
return string.format('%s (%s)', GetPlayerName(playerId), identifier or 'Could not load')
elseif format == 'name_ping' then
return string.format('%s (%d)', GetPlayerName(playerId), GetPlayerPing(playerId))
elseif format == 'name' then
return GetPlayerName(playerId)
elseif format == 'id' then
return playerId
elseif format == 'citizenid' then
return GetCharacterId(playerSrc) or 'Unknown'
end
return identifier or 'Unknown'
end
---@param playerSrc number
---@param player table (Framework Player Data)
function GetText(playerSrc, player)
return formatPlayerText(playerSrc, Config.TextFormat or 'identifier')
end
---@param playerSrc number
---@param player table (Framework Player Data)
function GetTextOverHead(playerSrc, player)
return formatPlayerText(playerSrc, Config.TextOverHeadFormat or 'id')
end
---@param playerSrc number
---@param player table (Framework Player Data)
function GetPlayerColor(playerSrc, player)
if IsPlayerAceAllowed(playerSrc --[[@as string]], 'command')
or IsPlayerAceAllowed(playerSrc --[[@as string]], 'admin') then
return '#DB0F0F'
end
local identifier = GetPlayerIdentifierByType(playerSrc --[[@as string]], Config.UseIdentifier)
-- Keep in mind Config.UseIdentifier should be same as the one in `cad-queue`
if GetResourceState('cad-queue') == 'started' then
local prio = exports['cad-queue']:GetPrio(identifier)
-- returns: { label: string, name: string, points: number }
return prio.name == 'police' and '#06214C' or prio.name == 'ambulance' and '#DE264F' or nil
end
return nil
end
local cachedImages = {}
---@param playerSrc number
---@param player table (Framework Player Data)
function GetImage(playerSrc, player)
local playerId = tostring(playerSrc)
local identifier = GetPlayerIdentifierByType(playerId, Config.UseIdentifier)
if cachedImages[identifier] then return cachedImages[identifier] end
local timeout = 5
local imageUrl = nil
if Config.UseIdentifier == 'steam' then
local hex = {string.strsplit(':', identifier)}
if not hex or not hex[2] then goto skip end
local steamId = tonumber(hex[2], 16)
local apiKey = Config.SteamAPIKey
local apiUrl = "http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=" .. apiKey .. "&steamids=" .. steamId
PerformHttpRequest(apiUrl, function(status, response)
if status == 200 then
local responseData = json.decode(response)
if responseData.response.players[1] then
local avatarURL = responseData.response.players[1].avatarmedium
imageUrl = avatarURL
cachedImages[identifier] = avatarURL
end
end
end, "GET", "", {["Content-Type"] = "application/json"})
elseif Config.UseIdentifier == 'discord' then
local discordId = {string.strsplit(':', identifier)}
if not discordId or not discordId[2] then goto skip end
PerformHttpRequest(('https://discord.com/api/v8/users/%s'):format(discordId[2]), function(_, response)
if response then
local _response = json.decode(response)
local avatarURL = ('https://cdn.discordapp.com/avatars/%s/%s'):format(_response.id, _response.avatar)
imageUrl = avatarURL
cachedImages[identifier] = avatarURL
end
end, 'GET', '', {
['Content-Type'] = 'application/json',
['Authorization'] = ('Bot %s'):format(Config.DiscordBotToken)
})
end
while timeout > 0 and (imageUrl == nil) do
timeout = timeout - 1
Wait(100)
end
::skip::
return imageUrl or false
end
function GetAllPlayers()
if GetResourceState('qbx_core') == 'started' then
return exports.qbx_core:GetQBPlayers()
elseif GetResourceState('qb-core') == 'started' then
local QBCore = exports['qb-core']:GetCoreObject()
return QBCore.Functions.GetQBPlayers()
elseif GetResourceState('ox_core') == 'started' then
local Ox = require '@ox_core.lib.init'
return Ox.GetPlayers()
elseif GetResourceState('es_extended') == 'started' then
local ESX = exports.es_extended:getSharedObject()
return ESX.GetExtendedPlayers()
else
assert(false, 'No framework initialised, jobs count set to null')
return {}
end
end
function GetJobCounts()
if GetResourceState('qbx_core') == 'started' then
local players = exports.qbx_core:GetQBPlayers()
local jobCounts = {}
for _, player in pairs(players) do
local jobName = player.PlayerData.job.name
local jobOnduty = player.PlayerData.job.onduty
local jobData = Config.Jobs[jobName]
if jobData and jobOnduty then
if not jobCounts[jobName] then jobCounts[jobName] = 0 end
jobCounts[jobName] = jobCounts[jobName] + 1
end
end
return jobCounts
elseif GetResourceState('qb-core') == 'started' then
local QBCore = exports['qb-core']:GetCoreObject()
local players = QBCore.Functions.GetQBPlayers()
local jobCounts = {}
for _, player in pairs(players) do
local jobName = player.PlayerData.job.name
local jobOnduty = player.PlayerData.job.onduty
local jobData = Config.Jobs[jobName]
if jobData and jobOnduty then
if not jobCounts[jobName] then jobCounts[jobName] = 0 end
jobCounts[jobName] = jobCounts[jobName] + 1
end
end
return jobCounts
elseif GetResourceState('ox_core') == 'started' then
local Ox = require '@ox_core.lib.init'
local jobCounts = {}
for name in pairs(Config.Jobs) do
jobCounts[name] = Ox.GetGroupActivePlayers(name) or 0
end
return jobCounts
elseif GetResourceState('es_extended') == 'started' then
local ESX = exports.es_extended:getSharedObject()
local jobCounts = {}
for name in pairs(Config.Jobs) do
jobCounts[name] = ESX.GetNumPlayers('job', 'police')
end
return jobCounts
else
assert(nil, 'No framework initialised, jobs count set to null')
return nil
end
end
---@param playerSrc number
---@return string|nil
function GetCharacterId(playerSrc)
if GetResourceState('qbx_core') == 'started' then
local player = exports.qbx_core:GetPlayer(playerSrc)
return player and player.PlayerData.citizenid or nil
elseif GetResourceState('qb-core') == 'started' then
local QBCore = exports['qb-core']:GetCoreObject()
local player = QBCore.Functions.GetPlayer(playerSrc)
return player and player.PlayerData.citizenid or nil
elseif GetResourceState('es_extended') == 'started' then
local ESX = exports.es_extended:getSharedObject()
local player = ESX.GetPlayerFromId(playerSrc)
return player and player.identifier or nil
elseif GetResourceState('ox_core') == 'started' then
local Ox = require '@ox_core.lib.init'
local player = Ox.GetPlayer(playerSrc)
return player and tostring(player.charId) or nil
end
return nil
end
if GetResourceState('qbx_core') == 'started' or GetResourceState('qb-core') == 'started' then
RegisterNetEvent('QBCore:Server:PlayerLoaded', function(player)
TriggerEvent('cad-playerlist:playerLoaded', player.PlayerData.source, player)
end)
elseif GetResourceState('es_extended') == 'started' then
AddEventHandler('esx:playerLoaded', function (playerId, xPlayer, isNew)
TriggerEvent('playerlist:playerLoaded', playerId, xPlayer)
end)
elseif GetResourceState('ox_core') == 'started' then
local Ox = require '@ox_core.lib.init'
AddEventHandler('ox:playerLoaded', function(playerId, userId, charId)
TriggerEvent('playerlist:playerLoaded', playerId, Ox.GetPlayer(playerId))
end)
else
AddEventHandler('playerJoining', function(source)
TriggerEvent('playerlist:playerLoaded', source, nil)
end)
end