forked from Simnation/Main
ed
This commit is contained in:
parent
5a5b4b855d
commit
f57a27b8df
152 changed files with 1554 additions and 0 deletions
382
resources/[tools]/jg-hud/framework/cl-functions.lua
Normal file
382
resources/[tools]/jg-hud/framework/cl-functions.lua
Normal file
|
@ -0,0 +1,382 @@
|
|||
Framework.CachedPlayerData = {
|
||||
job = nil,
|
||||
gang = nil,
|
||||
cash = nil,
|
||||
bank = nil,
|
||||
dirtyMoney = nil,
|
||||
hunger = nil,
|
||||
thirst = nil,
|
||||
stress = nil,
|
||||
micRange = 2,
|
||||
radioActive = false,
|
||||
voiceModes = 3,
|
||||
}
|
||||
|
||||
---@param vehicle integer
|
||||
---@return number fuelLevel
|
||||
function Framework.Client.VehicleGetFuel(vehicle)
|
||||
if not DoesEntityExist(vehicle) then return 0 end
|
||||
|
||||
if (Config.FuelSystem == "LegacyFuel" or Config.FuelSystem == "lc_fuel" or Config.FuelSystem == "ps-fuel" or Config.FuelSystem == "lj-fuel" or Config.FuelSystem == "cdn-fuel" or Config.FuelSystem == "hyon_gas_station" or Config.FuelSystem == "okokGasStation" or Config.FuelSystem == "nd_fuel" or Config.FuelSystem == "myFuel") then
|
||||
return exports[Config.FuelSystem]:GetFuel(vehicle)
|
||||
elseif Config.FuelSystem == "ti_fuel" then
|
||||
local level = exports["ti_fuel"]:getFuel(vehicle)
|
||||
return level
|
||||
elseif Config.FuelSystem == "ox_fuel" or Config.FuelSystem == "Renewed-Fuel" then
|
||||
return GetVehicleFuelLevel(vehicle)
|
||||
elseif Config.FuelSystem == "rcore_fuel" then
|
||||
return exports.rcore_fuel:GetVehicleFuelPercentage(vehicle)
|
||||
else
|
||||
return 100 -- or set up custom fuel system here...
|
||||
end
|
||||
end
|
||||
|
||||
---Toggles the engine, this is used in the keybind & in the vehicle control panel
|
||||
---@param vehicle integer
|
||||
---@param on boolean on or off
|
||||
function Framework.Client.ToggleEngine(vehicle, on)
|
||||
-- !! Consider adding a key script check here - to disallow enabling the engine if no keys are present
|
||||
SetVehicleEngineOn(vehicle, on, false, true)
|
||||
end
|
||||
|
||||
---Code to run when seatbelt is toggled
|
||||
---Please note; you need Config.UseCustomSeatbeltIntegration = true for this to take effect!
|
||||
---@param vehicle integer
|
||||
---@param seatbeltOn boolean true = seatbelt on, false = seatbelt off
|
||||
function Framework.Client.ToggleSeatbelt(vehicle, seatbeltOn)
|
||||
if GetResourceState("jim-mechanic") == "started" then
|
||||
if (seatbeltOn and not exports["jim-mechanic"]:seatBeltOn()) or (seatbeltOn and exports["jim-mechanic"]:seatBeltOn()) then
|
||||
TriggerEvent("jim-mechanic:client:ToggleSeatbelt")
|
||||
end
|
||||
end
|
||||
|
||||
-- ...or add another custom seatbelt integration here!
|
||||
end
|
||||
|
||||
---@return table | false playerData
|
||||
function Framework.Client.GetPlayerData()
|
||||
if Config.Framework == "QBCore" then
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
return QBCore.Functions.GetPlayerData()
|
||||
elseif Config.Framework == "Qbox" then
|
||||
return exports.qbx_core:GetPlayerData()
|
||||
elseif Config.Framework == "ESX" then
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
return ESX.GetPlayerData()
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
---@return string?
|
||||
function Framework.Client.GetPlayerJob()
|
||||
local player = Framework.Client.GetPlayerData()
|
||||
if not player or not player.job then return nil end
|
||||
|
||||
if Config.Framework == "QBCore" or Config.Framework == "Qbox" then
|
||||
return string.format("%s (%s)", player.job.label, player.job.grade.name)
|
||||
elseif Config.Framework == "ESX" then
|
||||
return string.format("%s (%s)", player.job.label, player.job.grade_label)
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
---@return string?
|
||||
function Framework.Client.GetPlayerGang()
|
||||
if GetResourceState("rcore_gangs") == "started" then
|
||||
local gang = exports.rcore_gangs:GetPlayerGang()
|
||||
if not gang then return nil end
|
||||
|
||||
return gang.tag
|
||||
end
|
||||
|
||||
local player = Framework.Client.GetPlayerData()
|
||||
if not player or not player.gang then return nil end
|
||||
|
||||
if Config.Framework == "QBCore" or Config.Framework == "Qbox" then
|
||||
return string.format("%s (%s)", player.gang.label, player.gang.grade.name)
|
||||
elseif Config.Framework == "ESX" then
|
||||
return nil
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
---@return boolean dead
|
||||
function Framework.Client.IsPlayerDead()
|
||||
if Config.Framework == "QBCore" then
|
||||
local player = Framework.Client.GetPlayerData()
|
||||
if not player then return false end
|
||||
|
||||
if player.metadata?.isdead or player.metadata?.inlaststand then
|
||||
return true
|
||||
end
|
||||
elseif Config.Framework == "Qbox" then
|
||||
return LocalPlayer.state.isDead
|
||||
elseif Config.Framework == "ESX" then
|
||||
return IsEntityDead(cache.ped)
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
---@param type "cash" | "bank" | "money" | "dirtyMoney" | "black_money"
|
||||
---@return number? balance
|
||||
function Framework.Client.GetBalance(type)
|
||||
if Config.Framework == "QBCore" then
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
local playerData = QBCore.Functions.GetPlayerData()
|
||||
|
||||
if type == "dirtyMoney" then
|
||||
-- Fetch "markedbills" from inventory
|
||||
local dirty = 0
|
||||
for _, item in pairs(playerData.items or {}) do
|
||||
if item.name == "markedbills" then
|
||||
if item.info and item.info.worth then
|
||||
dirty = dirty + item.info.worth
|
||||
end
|
||||
end
|
||||
end
|
||||
return dirty
|
||||
end
|
||||
|
||||
return playerData?.money?[type] or 0
|
||||
elseif Config.Framework == "Qbox" then
|
||||
if type == "dirtyMoney" and GetResourceState("ox_inventory") == "started" then
|
||||
-- Fetch dirty_money from ox_inv
|
||||
return exports.ox_inventory:GetItemCount("black_money") or 0
|
||||
end
|
||||
|
||||
return exports.qbx_core:GetPlayerData()?.money?[type] or 0
|
||||
elseif Config.Framework == "ESX" then
|
||||
if type == "cash" then type = "money" end
|
||||
if type == "dirtyMoney" then type = "black_money" end
|
||||
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
local playerData = ESX.GetPlayerData()
|
||||
if not playerData then return 0 end
|
||||
|
||||
for i, acc in pairs(playerData?.accounts or {}) do
|
||||
if acc.name == type then
|
||||
return acc.money or 0
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
---@param vehicle integer
|
||||
function Framework.Client.GetVehicleMileageInKm(vehicle)
|
||||
if not vehicle or vehicle == 0 then return false end
|
||||
|
||||
-- t1ger_mechanic integration
|
||||
if GetResourceState("t1ger_mechanic") == "started" then
|
||||
return exports["t1ger_mechanic"]:GetVehicleMileage(vehicle)
|
||||
end
|
||||
|
||||
-- jim-mechanic integration
|
||||
if GetResourceState("jim-mechanic") == "started" then
|
||||
local plate = GetVehicleNumberPlateText(vehicle)
|
||||
return exports["jim-mechanic"]:GetMilage(plate)
|
||||
end
|
||||
|
||||
-- This is for jg-vehiclemileage (jg-mechanic), as it's stored in a statebag
|
||||
-- If you're using a different vehicle mileage script, you can add the export for it here! :)
|
||||
return Entity(vehicle).state.vehicleMileage or 0
|
||||
end
|
||||
|
||||
---@param km number
|
||||
---@return number
|
||||
function Framework.Client.ConvertKmToMiles(km)
|
||||
return km * 0.621371
|
||||
end
|
||||
|
||||
function Framework.Client.ConvertSpeed(speed, unit)
|
||||
if unit == "mph" then return speed * 2.236936 end
|
||||
if unit == "kph" then return speed * 3.6 end
|
||||
return speed
|
||||
end
|
||||
|
||||
function Framework.Client.ConvertDistance(dist, unit)
|
||||
if unit == "meters" then return dist * 1 end
|
||||
if unit == "feet" then return dist * 3.28084 end
|
||||
return dist
|
||||
end
|
||||
|
||||
--
|
||||
-- From this point on, it's setting up framework event listeners
|
||||
--
|
||||
|
||||
local function updateCachedData(player)
|
||||
if Config.ShowComponents.job then
|
||||
Framework.CachedPlayerData.job = Framework.Client.GetPlayerJob()
|
||||
end
|
||||
if Config.ShowComponents.gang then
|
||||
Framework.CachedPlayerData.gang = Framework.Client.GetPlayerGang()
|
||||
end
|
||||
if Config.ShowComponents.cashBalance then
|
||||
Framework.CachedPlayerData.cash = Framework.Client.GetBalance("cash")
|
||||
end
|
||||
if Config.ShowComponents.bankBalance then
|
||||
Framework.CachedPlayerData.bank = Framework.Client.GetBalance("bank")
|
||||
end
|
||||
if Config.ShowComponents.dirtyMoneyBalance then
|
||||
Framework.CachedPlayerData.dirtyMoney = Framework.Client.GetBalance("dirtyMoney")
|
||||
end
|
||||
|
||||
if Config.Framework == "QBCore" and player then
|
||||
Framework.CachedPlayerData.hunger = lib.math.clamp(player.metadata?.hunger or 0, 0, 100)
|
||||
Framework.CachedPlayerData.thirst = lib.math.clamp(player.metadata?.thirst or 0, 0, 100)
|
||||
end
|
||||
end
|
||||
|
||||
function Framework.Client.SetupPlayerLoginListeners()
|
||||
if Config.Framework == "QBCore" then
|
||||
RegisterNetEvent("QBCore:Client:OnPlayerLoaded", function()
|
||||
LocalPlayer.state:set("jgHudPlayerLoggedIn", true)
|
||||
updateCachedData(Framework.Client.GetPlayerData())
|
||||
end)
|
||||
|
||||
RegisterNetEvent("QBCore:Client:OnPlayerUnload", function()
|
||||
LocalPlayer.state:set("jgHudPlayerLoggedIn", false)
|
||||
end)
|
||||
|
||||
elseif Config.Framework == "Qbox" then
|
||||
AddStateBagChangeHandler("isLoggedIn", ("player:%s"):format(cache.serverId), function(_, _, loggedIn)
|
||||
LocalPlayer.state:set("jgHudPlayerLoggedIn", loggedIn)
|
||||
end)
|
||||
|
||||
elseif Config.Framework == "ESX" then
|
||||
local function onPlayerLoad()
|
||||
lib.waitFor(function()
|
||||
return Framework.Client.GetPlayerData() and cache.ped
|
||||
end, "Ped has not loaded or GetPlayerData returned false (waited 30 seconds)", 30000)
|
||||
|
||||
LocalPlayer.state:set("jgHudPlayerLoggedIn", true)
|
||||
Framework.CachedPlayerData.job = Framework.Client.GetPlayerJob()
|
||||
end
|
||||
|
||||
RegisterNetEvent("esx:playerLoaded", onPlayerLoad)
|
||||
RegisterNetEvent("esx:onPlayerSpawn", onPlayerLoad)
|
||||
RegisterNetEvent("esx:onPlayerLogout", function()
|
||||
LocalPlayer.state:set("jgHudPlayerLoggedIn", false)
|
||||
end)
|
||||
|
||||
else
|
||||
-- No framework, just say they are already logged in.
|
||||
-- Or you can add your own system or exports here! Just update the
|
||||
-- LocalPlayer jgHudPlayerLoggedIn true/false and everything will work!
|
||||
lib.waitFor(function()
|
||||
if cache.ped then
|
||||
LocalPlayer.state:set("jgHudPlayerLoggedIn", true)
|
||||
return true
|
||||
end
|
||||
end, "[Standalone] Ped never loaded in; could not login (waited 500 seconds)", 500000)
|
||||
end
|
||||
end
|
||||
|
||||
function Framework.Client.CreateEventListeners()
|
||||
local state = LocalPlayer.state
|
||||
Framework.CachedPlayerData.hunger = lib.math.clamp(state.hunger or 0, 0, 100)
|
||||
Framework.CachedPlayerData.thirst = lib.math.clamp(state.thirst or 0, 0, 100)
|
||||
Framework.CachedPlayerData.stress = lib.math.clamp(state.stress or 0, 0, 100)
|
||||
|
||||
if (Config.Framework == "ESX" or Config.Framework == "QBCore" or Config.Framework == "Qbox") and Framework.Client.GetPlayerData() then
|
||||
updateCachedData(Framework.Client.GetPlayerData())
|
||||
end
|
||||
|
||||
if Config.Framework == "ESX" then
|
||||
RegisterNetEvent("esx_status:onTick", function(data)
|
||||
local newHunger, newThirst
|
||||
for i = 1, #data do
|
||||
if data[i].name == "thirst" then newThirst = math.floor(data[i].percent)
|
||||
elseif data[i].name == "hunger" then newHunger = math.floor(data[i].percent) end
|
||||
end
|
||||
Framework.CachedPlayerData.hunger = lib.math.clamp(newHunger or 0, 0, 100)
|
||||
Framework.CachedPlayerData.thirst = lib.math.clamp(newThirst or 0, 0, 100)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("esx:setJob", function(job)
|
||||
Framework.CachedPlayerData.job = string.format("%s (%s)", job.label, job.grade_label)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("esx:setAccountMoney", function(account)
|
||||
if account.name == "money" then Framework.CachedPlayerData.cash = account.money end
|
||||
if account.name == "bank" then Framework.CachedPlayerData.bank = account.money end
|
||||
if account.name == "black_money" then Framework.CachedPlayerData.dirtyMoney = account.money end
|
||||
end)
|
||||
end
|
||||
|
||||
if Config.Framework == "QBCore" or Config.Framework == "Qbox" then
|
||||
RegisterNetEvent("hud:client:UpdateNeeds", function(newHunger, newThirst)
|
||||
Framework.CachedPlayerData.hunger = newHunger
|
||||
Framework.CachedPlayerData.thirst = newThirst
|
||||
end)
|
||||
|
||||
RegisterNetEvent("hud:client:OnMoneyChange", function(type)
|
||||
-- The reason I fetch them directly from `GetBalance` and don't use the amount/isMinus args is because
|
||||
-- they didn't consistently work for me - especially when using /setmoney in QB or Qbox
|
||||
if type == "cash" then Framework.CachedPlayerData.cash = Framework.Client.GetBalance("cash") end
|
||||
if type == "bank" then Framework.CachedPlayerData.bank = Framework.Client.GetBalance("bank") end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("QBCore:Client:OnJobUpdate", function()
|
||||
Framework.CachedPlayerData.job = Framework.Client.GetPlayerJob()
|
||||
end)
|
||||
|
||||
RegisterNetEvent("QBCore:Client:OnGangUpdate", function()
|
||||
Framework.CachedPlayerData.gang = Framework.Client.GetPlayerGang()
|
||||
end)
|
||||
end
|
||||
|
||||
if Config.Framework == "Qbox" then
|
||||
local playerState = LocalPlayer.state
|
||||
Framework.CachedPlayerData.hunger = lib.math.clamp(playerState.hunger or 0, 0, 100)
|
||||
Framework.CachedPlayerData.thirst = lib.math.clamp(playerState.thirst or 0, 0, 100)
|
||||
|
||||
AddEventHandler("ox_inventory:itemCount", function(itemName, totalCount)
|
||||
if itemName == "black_money" then
|
||||
Framework.CachedPlayerData.dirtyMoney = totalCount
|
||||
end
|
||||
end)
|
||||
|
||||
AddStateBagChangeHandler("hunger", ("player:%s"):format(cache.serverId), function(_, _, value)
|
||||
Framework.CachedPlayerData.hunger = lib.math.clamp(value or 0, 0, 100)
|
||||
end)
|
||||
|
||||
AddStateBagChangeHandler("thirst", ("player:%s"):format(cache.serverId), function(_, _, value)
|
||||
Framework.CachedPlayerData.thirst = lib.math.clamp(value or 0, 0, 100)
|
||||
end)
|
||||
end
|
||||
|
||||
-- rcore_gangs
|
||||
if GetResourceState("rcore_gangs") == "started" then
|
||||
RegisterNetEvent("rcore_gangs:client:set_gang", function(gang)
|
||||
Framework.CachedPlayerData.gang = gang?.tag
|
||||
end)
|
||||
end
|
||||
|
||||
-- jg-stress integration
|
||||
AddStateBagChangeHandler("stress", ("player:%s"):format(cache.serverId), function(_, _, value)
|
||||
Framework.CachedPlayerData.stress = lib.math.clamp(value or 0, 0, 100)
|
||||
end)
|
||||
|
||||
-- PMA Voice
|
||||
if GetResourceState("pma-voice") == "started" then
|
||||
AddEventHandler("pma-voice:setTalkingMode", function(mode)
|
||||
Framework.CachedPlayerData.micRange = mode
|
||||
end)
|
||||
|
||||
AddEventHandler("pma-voice:radioActive", function(isActive)
|
||||
Framework.CachedPlayerData.radioActive = isActive
|
||||
end)
|
||||
|
||||
AddEventHandler("pma-voice:settingsCallback", function(voiceSettings)
|
||||
Framework.CachedPlayerData.voiceModes = #voiceSettings.voiceModes
|
||||
end)
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue