mirror of
https://github.com/esx-framework/esx_core.git
synced 2026-08-29 09:18:53 +00:00
Merge branch 'dev' into extra-callback-functions
This commit is contained in:
@@ -821,6 +821,13 @@ ALTER TABLE `licenses`
|
||||
ALTER TABLE `owned_vehicles`
|
||||
ADD PRIMARY KEY (`plate`);
|
||||
|
||||
--
|
||||
--
|
||||
-- Indexes for table `vehicles`
|
||||
--
|
||||
ALTER TABLE `vehicles`
|
||||
ADD PRIMARY KEY (`model`);
|
||||
|
||||
--
|
||||
-- Indexes for table `rented_vehicles`
|
||||
--
|
||||
|
||||
@@ -1019,7 +1019,7 @@ function ESX.Game.SetVehicleProperties(vehicle, props)
|
||||
for extraId, enabled in pairs(props.extras) do
|
||||
extraId = tonumber(extraId)
|
||||
if extraId then
|
||||
SetVehicleExtra(vehicle, extraId, enabled)
|
||||
SetVehicleExtra(vehicle, extraId, not enabled)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,16 +4,6 @@ ESX.SecureNetEvent("esx:requestModel", function(model)
|
||||
ESX.Streaming.RequestModel(model)
|
||||
end)
|
||||
|
||||
local function ApplyMetadata(metadata)
|
||||
if metadata.health then
|
||||
SetEntityHealth(ESX.PlayerData.ped, metadata.health)
|
||||
end
|
||||
|
||||
if metadata.armor and metadata.armor > 0 then
|
||||
SetPedArmour(ESX.PlayerData.ped, metadata.armor)
|
||||
end
|
||||
end
|
||||
|
||||
RegisterNetEvent("esx:playerLoaded", function(xPlayer, _, skin)
|
||||
ESX.PlayerData = xPlayer
|
||||
|
||||
@@ -34,8 +24,6 @@ RegisterNetEvent("esx:playerLoaded", function(xPlayer, _, skin)
|
||||
|
||||
ESX.PlayerLoaded = true
|
||||
|
||||
ApplyMetadata(ESX.PlayerData.metadata)
|
||||
|
||||
local timer = GetGameTimer()
|
||||
while not HaveAllStreamingRequestsCompleted(ESX.PlayerData.ped) and (GetGameTimer() - timer) < 2000 do
|
||||
Wait(0)
|
||||
@@ -56,10 +44,13 @@ RegisterNetEvent("esx:playerLoaded", function(xPlayer, _, skin)
|
||||
Actions:Init()
|
||||
StartPointsLoop()
|
||||
StartServerSyncLoops()
|
||||
NetworkSetLocalPlayerSyncLookAt(true)
|
||||
end)
|
||||
|
||||
local isFirstSpawn = true
|
||||
ESX.SecureNetEvent("esx:onPlayerLogout", function()
|
||||
ESX.PlayerLoaded = false
|
||||
isFirstSpawn = true
|
||||
end)
|
||||
|
||||
ESX.SecureNetEvent("esx:setMaxWeight", function(newMaxWeight)
|
||||
@@ -72,7 +63,21 @@ local function onPlayerSpawn()
|
||||
end
|
||||
|
||||
AddEventHandler("playerSpawned", onPlayerSpawn)
|
||||
AddEventHandler("esx:onPlayerSpawn", onPlayerSpawn)
|
||||
AddEventHandler("esx:onPlayerSpawn", function()
|
||||
onPlayerSpawn()
|
||||
|
||||
if isFirstSpawn then
|
||||
isFirstSpawn = false
|
||||
|
||||
if ESX.PlayerData.metadata.health and (ESX.PlayerData.metadata.health > 0 or Config.SaveDeathStatus) then
|
||||
SetEntityHealth(ESX.PlayerData.ped, ESX.PlayerData.metadata.health)
|
||||
end
|
||||
|
||||
if ESX.PlayerData.metadata.armor and ESX.PlayerData.metadata.armor > 0 then
|
||||
SetPedArmour(ESX.PlayerData.ped, ESX.PlayerData.metadata.armor)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler("esx:onPlayerDeath", function()
|
||||
ESX.SetPlayerData("ped", PlayerPedId())
|
||||
@@ -282,29 +287,58 @@ end
|
||||
|
||||
function StartServerSyncLoops()
|
||||
if Config.CustomInventory then return end
|
||||
-- keep track of ammo
|
||||
|
||||
local currentWeapon = {
|
||||
---@type number
|
||||
---@diagnostic disable-next-line: assign-type-mismatch
|
||||
hash = `WEAPON_UNARMED`,
|
||||
ammo = 0,
|
||||
}
|
||||
|
||||
local function updateCurrentWeaponAmmo(weaponName)
|
||||
local newAmmo = GetAmmoInPedWeapon(ESX.PlayerData.ped, currentWeapon.hash)
|
||||
|
||||
if newAmmo ~= currentWeapon.ammo then
|
||||
currentWeapon.ammo = newAmmo
|
||||
TriggerServerEvent("esx:updateWeaponAmmo", weaponName, newAmmo)
|
||||
end
|
||||
end
|
||||
|
||||
CreateThread(function()
|
||||
local currentWeapon = { Ammo = 0 }
|
||||
while ESX.PlayerLoaded do
|
||||
local sleep = 1500
|
||||
if GetSelectedPedWeapon(ESX.PlayerData.ped) ~= -1569615261 then
|
||||
sleep = 1000
|
||||
local _, weaponHash = GetCurrentPedWeapon(ESX.PlayerData.ped, true)
|
||||
local weapon = ESX.GetWeaponFromHash(weaponHash)
|
||||
if weapon then
|
||||
local ammoCount = GetAmmoInPedWeapon(ESX.PlayerData.ped, weaponHash)
|
||||
if weapon.name ~= currentWeapon.name then
|
||||
currentWeapon.Ammo = ammoCount
|
||||
currentWeapon.name = weapon.name
|
||||
else
|
||||
if ammoCount ~= currentWeapon.Ammo then
|
||||
currentWeapon.Ammo = ammoCount
|
||||
TriggerServerEvent("esx:updateWeaponAmmo", weapon.name, ammoCount)
|
||||
end
|
||||
currentWeapon.hash = GetSelectedPedWeapon(ESX.PlayerData.ped)
|
||||
|
||||
if currentWeapon.hash ~= `WEAPON_UNARMED` then
|
||||
local weaponConfig = ESX.GetWeaponFromHash(currentWeapon.hash)
|
||||
|
||||
if weaponConfig then
|
||||
currentWeapon.ammo = GetAmmoInPedWeapon(ESX.PlayerData.ped, currentWeapon.hash)
|
||||
|
||||
while GetSelectedPedWeapon(ESX.PlayerData.ped) == currentWeapon.hash do
|
||||
updateCurrentWeaponAmmo(weaponConfig.name)
|
||||
Wait(1000)
|
||||
end
|
||||
|
||||
updateCurrentWeaponAmmo(weaponConfig.name)
|
||||
end
|
||||
end
|
||||
Wait(sleep)
|
||||
Wait(250)
|
||||
end
|
||||
end)
|
||||
|
||||
CreateThread(function()
|
||||
local PARACHUTE_OPENING <const> = 1
|
||||
local PARACHUTE_OPEN <const> = 2
|
||||
|
||||
while ESX.PlayerLoaded do
|
||||
local parachuteState = GetPedParachuteState(ESX.PlayerData.ped)
|
||||
|
||||
if parachuteState == PARACHUTE_OPENING or parachuteState == PARACHUTE_OPEN then
|
||||
TriggerServerEvent("esx:updateWeaponAmmo", "GADGET_PARACHUTE", 0)
|
||||
|
||||
while GetPedParachuteState(ESX.PlayerData.ped) ~= -1 do Wait(1000) end
|
||||
end
|
||||
Wait(500)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -4,6 +4,7 @@ function Adjustments:RemoveHudComponents()
|
||||
for i = 1, #Config.RemoveHudComponents do
|
||||
if Config.RemoveHudComponents[i] then
|
||||
SetHudComponentSize(i, 0.0, 0.0)
|
||||
SetHudComponentPosition(i, 900, 900)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -215,6 +216,15 @@ function Adjustments:WantedLevel()
|
||||
end
|
||||
end
|
||||
|
||||
function Adjustments:DisableRadio()
|
||||
if Config.RemoveHudComponents[16] then
|
||||
AddEventHandler("esx:enteredVehicle", function(vehicle, plate, seat, displayName, netId)
|
||||
SetVehRadioStation(vehicle,"OFF")
|
||||
SetUserRadioControlEnabled(false)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function Adjustments:Load()
|
||||
self:RemoveHudComponents()
|
||||
self:DisableAimAssist()
|
||||
@@ -228,4 +238,5 @@ function Adjustments:Load()
|
||||
self:LicensePlates()
|
||||
self:DiscordPresence()
|
||||
self:WantedLevel()
|
||||
self:DisableRadio()
|
||||
end
|
||||
|
||||
@@ -51,8 +51,11 @@ function Callbacks:ServerRecieve(requestId, invoker, ...)
|
||||
end
|
||||
end
|
||||
|
||||
function Callbacks:Register(name, cb)
|
||||
self.storage[name] = cb
|
||||
function Callbacks:Register(name, resource, cb)
|
||||
self.storage[name] = {
|
||||
resource = resource,
|
||||
cb = cb
|
||||
}
|
||||
end
|
||||
|
||||
function Callbacks:ClientRecieve(eventName, requestId, invoker, ...)
|
||||
@@ -64,7 +67,7 @@ function Callbacks:ClientRecieve(eventName, requestId, invoker, ...)
|
||||
local returnCb = function(...)
|
||||
TriggerServerEvent("esx:clientCallback", requestId, invoker, ...)
|
||||
end
|
||||
local callback = self.storage[eventName]
|
||||
local callback = self.storage[eventName].cb
|
||||
|
||||
self:Execute(callback, requestId, returnCb, ...)
|
||||
end
|
||||
@@ -115,13 +118,17 @@ function ESX.AwaitServerCallback(eventName, ...)
|
||||
return table.unpack(p.value)
|
||||
end
|
||||
|
||||
---@param eventName string
|
||||
---@param callback function
|
||||
---@return nil
|
||||
function ESX.RegisterClientCallback(eventName, callback)
|
||||
Callbacks:Register(eventName, callback)
|
||||
ESX.RegisterClientCallback = function(eventName, callback)
|
||||
local invokingResource = GetInvokingResource()
|
||||
local invoker = (invokingResource and invokingResource ~= "Unknown") and invokingResource or "es_extended"
|
||||
|
||||
Callbacks:Register(eventName, invoker, callback)
|
||||
end
|
||||
|
||||
ESX.SecureNetEvent("esx:triggerClientCallback", function(...)
|
||||
Callbacks:ClientRecieve(...)
|
||||
end)
|
||||
|
||||
---@param eventName string
|
||||
---@return boolean
|
||||
function ESX.DoesClientCallbackExist(eventName)
|
||||
@@ -133,3 +140,11 @@ end
|
||||
function ESX.GetClientCallbackInfo(eventName)
|
||||
return Callbacks.storage[eventName]
|
||||
end
|
||||
|
||||
AddEventHandler("onResourceStop", function(resource)
|
||||
for k, v in pairs(Callbacks.storage) do
|
||||
if v.resource == resource then
|
||||
Callbacks.storage[k] = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -29,7 +29,7 @@ function Death:ByPlayer()
|
||||
TriggerServerEvent("esx:onPlayerDeath", data)
|
||||
end
|
||||
|
||||
function Death:Natual()
|
||||
function Death:Natural()
|
||||
local coords = GetEntityCoords(ESX.PlayerData.ped)
|
||||
|
||||
local data = {
|
||||
@@ -43,25 +43,7 @@ function Death:Natual()
|
||||
TriggerServerEvent("esx:onPlayerDeath", data)
|
||||
end
|
||||
|
||||
function Death:Damaged(victim, victimDied)
|
||||
if not victimDied then
|
||||
return
|
||||
end
|
||||
|
||||
if not IsEntityAPed(victim) then
|
||||
return
|
||||
end
|
||||
|
||||
if not IsPedAPlayer(victim) then
|
||||
return
|
||||
end
|
||||
|
||||
local victimId = NetworkGetPlayerIndexFromPed(victim)
|
||||
local isDead = IsPedDeadOrDying(victim, true) or IsPedFatallyInjured(victim)
|
||||
if victimId ~= ESX.playerId or not isDead then
|
||||
return
|
||||
end
|
||||
|
||||
function Death:Died()
|
||||
self.killerEntity = GetPedSourceOfDeath(ESX.PlayerData.ped)
|
||||
self.deathCause = GetPedCauseOfDeath(ESX.PlayerData.ped)
|
||||
self.killerId = NetworkGetPlayerIndexFromPed(self.killerEntity)
|
||||
@@ -72,15 +54,20 @@ function Death:Damaged(victim, victimDied)
|
||||
if self.killerEntity ~= ESX.PlayerData.ped and self.killerId and isActive then
|
||||
self:ByPlayer()
|
||||
else
|
||||
self:Natual()
|
||||
self:Natural()
|
||||
end
|
||||
|
||||
self:ResetValues()
|
||||
end
|
||||
|
||||
AddEventHandler("gameEventTriggered", function(event, data)
|
||||
if event ~= "CEventNetworkEntityDamage" then
|
||||
return
|
||||
end
|
||||
Death:Damaged(data[1], data[4])
|
||||
AddEventHandler("esx:onPlayerSpawn", function()
|
||||
Citizen.CreateThreadNow(function()
|
||||
while not ESX.PlayerData.dead do
|
||||
if IsPedDeadOrDying(ESX.PlayerData.ped, true) or IsPedFatallyInjured(ESX.PlayerData.ped) then
|
||||
Death:Died()
|
||||
break
|
||||
end
|
||||
Citizen.Wait(250)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -608,8 +608,17 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory,
|
||||
function self.updateWeaponAmmo(weaponName, ammoCount)
|
||||
local _, weapon = self.getWeapon(weaponName)
|
||||
|
||||
if weapon then
|
||||
weapon.ammo = ammoCount
|
||||
if not weapon then
|
||||
return
|
||||
end
|
||||
|
||||
weapon.ammo = ammoCount
|
||||
|
||||
if weapon.ammo <= 0 then
|
||||
local _, weaponConfig = ESX.GetWeapon(weaponName)
|
||||
if weaponConfig.throwable then
|
||||
self.removeWeapon(weaponName)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -276,15 +276,15 @@ end
|
||||
|
||||
ESX.GetPlayers = GetPlayers
|
||||
|
||||
local function checkTable(key, val, player, xPlayers)
|
||||
local function checkTable(key, val, xPlayer, xPlayers)
|
||||
for valIndex = 1, #val do
|
||||
local value = val[valIndex]
|
||||
if not xPlayers[value] then
|
||||
xPlayers[value] = {}
|
||||
end
|
||||
|
||||
if (key == "job" and player.job.name == value) or player[key] == value then
|
||||
xPlayers[value][#xPlayers[value] + 1] = player
|
||||
if (key == "job" and xPlayer.job.name == value) or xPlayer[key] == value then
|
||||
xPlayers[value][#xPlayers[value] + 1] = xPlayer
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -293,20 +293,22 @@ end
|
||||
---@param val? string|table
|
||||
---@return table
|
||||
function ESX.GetExtendedPlayers(key, val)
|
||||
if not key then
|
||||
return ESX.Table.ToArray(ESX.Players)
|
||||
end
|
||||
|
||||
local xPlayers = {}
|
||||
if type(val) == "table" then
|
||||
for _, v in pairs(ESX.Players) do
|
||||
checkTable(key, val, v, xPlayers)
|
||||
for i, xPlayer in pairs(ESX.Players) do
|
||||
checkTable(key, val, xPlayer, xPlayers)
|
||||
end
|
||||
else
|
||||
for _, v in pairs(ESX.Players) do
|
||||
if key then
|
||||
if (key == "job" and v.job.name == val) or v[key] == val then
|
||||
xPlayers[#xPlayers + 1] = v
|
||||
end
|
||||
else
|
||||
xPlayers[#xPlayers + 1] = v
|
||||
end
|
||||
|
||||
return xPlayers
|
||||
end
|
||||
|
||||
for i, xPlayer in pairs(ESX.Players) do
|
||||
if (key == "job" and xPlayer.job.name == val) or xPlayer[key] == val then
|
||||
xPlayers[#xPlayers + 1] = xPlayer
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
RegisterServerEvent("esx:playerPedChanged")
|
||||
RegisterServerEvent("esx:playerJumping")
|
||||
RegisterServerEvent("esx:enteringVehicle")
|
||||
RegisterServerEvent("esx:enteringVehicleAborted")
|
||||
RegisterServerEvent("esx:enteredVehicle")
|
||||
RegisterServerEvent("esx:exitedVehicle")
|
||||
RegisterNetEvent("esx:playerPedChanged")
|
||||
RegisterNetEvent("esx:playerJumping")
|
||||
RegisterNetEvent("esx:enteringVehicle")
|
||||
RegisterNetEvent("esx:enteringVehicleAborted")
|
||||
RegisterNetEvent("esx:enteredVehicle")
|
||||
RegisterNetEvent("esx:exitedVehicle")
|
||||
|
||||
if Config.EnableDebug then
|
||||
AddEventHandler("esx:playerPedChanged", function(netId)
|
||||
|
||||
@@ -6,8 +6,11 @@ Callbacks.requests = {}
|
||||
Callbacks.storage = {}
|
||||
Callbacks.id = 0
|
||||
|
||||
function Callbacks:Register(name, cb)
|
||||
self.storage[name] = cb
|
||||
function Callbacks:Register(name, resource, cb)
|
||||
self.storage[name] = {
|
||||
resource = resource,
|
||||
cb = cb
|
||||
}
|
||||
end
|
||||
|
||||
function Callbacks:Execute(cb, ...)
|
||||
@@ -39,7 +42,7 @@ function Callbacks:ServerRecieve(player, event, requestId, invoker, ...)
|
||||
local returnCb = function(...)
|
||||
TriggerClientEvent("esx:serverCallback", player, requestId, invoker, ...)
|
||||
end
|
||||
local callback = self.storage[event]
|
||||
local callback = self.storage[event].cb
|
||||
|
||||
self:Execute(callback, player, returnCb, ...)
|
||||
end
|
||||
@@ -73,15 +76,19 @@ end)
|
||||
---@param ... any
|
||||
function ESX.TriggerClientCallback(player, eventName, callback, ...)
|
||||
local invokingResource = GetInvokingResource()
|
||||
local invoker = (invokingResource and invokingResource ~= "unknown") and invokingResource or "es_extended"
|
||||
local invoker = (invokingResource and invokingResource ~= "Unknown") and invokingResource or "es_extended"
|
||||
|
||||
Callbacks:Trigger(player, eventName, callback, invoker, ...)
|
||||
end
|
||||
|
||||
---@param eventName string
|
||||
---@param callback function
|
||||
function ESX.RegisterServerCallback(eventName, callback)
|
||||
Callbacks:Register(eventName, callback)
|
||||
---@return nil
|
||||
ESX.RegisterServerCallback = function(eventName, callback)
|
||||
local invokingResource = GetInvokingResource()
|
||||
local invoker = (invokingResource and invokingResource ~= "Unknown") and invokingResource or "es_extended"
|
||||
|
||||
Callbacks:Register(eventName, invoker, callback)
|
||||
end
|
||||
|
||||
---@param eventName string
|
||||
@@ -95,3 +102,11 @@ end
|
||||
function ESX.GetServerCallbackInfo(eventName)
|
||||
return Callbacks.storage[eventName]
|
||||
end
|
||||
|
||||
AddEventHandler("onResourceStop", function(resource)
|
||||
for k, v in pairs(Callbacks.storage) do
|
||||
if v.resource == resource then
|
||||
Callbacks.storage[k] = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -40,6 +40,7 @@ Config.LogPaycheck = false -- Logs paychecks to a nominated Discord channel via
|
||||
Config.EnableSocietyPayouts = false -- pay from the society account that the player is employed at? Requirement: esx_society
|
||||
Config.MaxWeight = 24 -- the max inventory weight without a backpack
|
||||
Config.PaycheckInterval = 7 * 60000 -- how often to receive paychecks in milliseconds
|
||||
Config.SaveDeathStatus = true -- Save the death status of a player
|
||||
Config.EnableDebug = false -- Use Debug options?
|
||||
|
||||
Config.DefaultJobDuty = true -- A players default duty status when changing jobs
|
||||
|
||||
@@ -1008,22 +1008,22 @@ Config.Weapons = {
|
||||
{ name = "WEAPON_RPG", label = TranslateCap("weapon_rpg"), tints = Config.DefaultWeaponTints, components = {}, ammo = { label = TranslateCap("ammo_rockets"), hash = `AMMO_RPG` } },
|
||||
{ name = "WEAPON_RAYMINIGUN", label = TranslateCap("weapon_rayminigun"), tints = Config.DefaultWeaponTints, components = {}, ammo = { label = TranslateCap("ammo_rounds"), hash = `AMMO_MINIGUN` } },
|
||||
-- Thrown
|
||||
{ name = "WEAPON_BALL", label = TranslateCap("weapon_ball"), components = {}, ammo = { label = TranslateCap("ammo_ball"), hash = `AMMO_BALL` } },
|
||||
{ name = "WEAPON_BZGAS", label = TranslateCap("weapon_bzgas"), components = {}, ammo = { label = TranslateCap("ammo_bzgas"), hash = `AMMO_BZGAS` } },
|
||||
{ name = "WEAPON_FLARE", label = TranslateCap("weapon_flare"), components = {}, ammo = { label = TranslateCap("ammo_flare"), hash = `AMMO_FLARE` } },
|
||||
{ name = "WEAPON_GRENADE", label = TranslateCap("weapon_grenade"), components = {}, ammo = { label = TranslateCap("ammo_grenade"), hash = `AMMO_GRENADE` } },
|
||||
{ name = "WEAPON_PETROLCAN", label = TranslateCap("weapon_petrolcan"), components = {}, ammo = { label = TranslateCap("ammo_petrol"), hash = `AMMO_PETROLCAN` } },
|
||||
{ name = "WEAPON_HAZARDCAN", label = TranslateCap("weapon_hazardcan"), components = {}, ammo = { label = TranslateCap("ammo_petrol"), hash = `AMMO_PETROLCAN` } },
|
||||
{ name = "WEAPON_MOLOTOV", label = TranslateCap("weapon_molotov"), components = {}, ammo = { label = TranslateCap("ammo_molotov"), hash = `AMMO_MOLOTOV` } },
|
||||
{ name = "WEAPON_PROXMINE", label = TranslateCap("weapon_proxmine"), components = {}, ammo = { label = TranslateCap("ammo_proxmine"), hash = `AMMO_PROXMINE` } },
|
||||
{ name = "WEAPON_PIPEBOMB", label = TranslateCap("weapon_pipebomb"), components = {}, ammo = { label = TranslateCap("ammo_pipebomb"), hash = `AMMO_PIPEBOMB` } },
|
||||
{ name = "WEAPON_SNOWBALL", label = TranslateCap("weapon_snowball"), components = {}, ammo = { label = TranslateCap("ammo_snowball"), hash = `AMMO_SNOWBALL` } },
|
||||
{ name = "WEAPON_STICKYBOMB", label = TranslateCap("weapon_stickybomb"), components = {}, ammo = { label = TranslateCap("ammo_stickybomb"), hash = `AMMO_STICKYBOMB` } },
|
||||
{ name = "WEAPON_SMOKEGRENADE", label = TranslateCap("weapon_smokegrenade"), components = {}, ammo = { label = TranslateCap("ammo_smokebomb"), hash = `AMMO_SMOKEGRENADE` } },
|
||||
{ name = "WEAPON_BALL", label = TranslateCap("weapon_ball"), components = {}, ammo = { label = TranslateCap("ammo_ball"), hash = `AMMO_BALL` }, throwable = true },
|
||||
{ name = "WEAPON_BZGAS", label = TranslateCap("weapon_bzgas"), components = {}, ammo = { label = TranslateCap("ammo_bzgas"), hash = `AMMO_BZGAS` }, throwable = true },
|
||||
{ name = "WEAPON_FLARE", label = TranslateCap("weapon_flare"), components = {}, ammo = { label = TranslateCap("ammo_flare"), hash = `AMMO_FLARE` }, throwable = true },
|
||||
{ name = "WEAPON_GRENADE", label = TranslateCap("weapon_grenade"), components = {}, ammo = { label = TranslateCap("ammo_grenade"), hash = `AMMO_GRENADE` }, throwable = true },
|
||||
{ name = "WEAPON_PETROLCAN", label = TranslateCap("weapon_petrolcan"), components = {}, ammo = { label = TranslateCap("ammo_petrol"), hash = `AMMO_PETROLCAN` }, throwable = true },
|
||||
{ name = "WEAPON_HAZARDCAN", label = TranslateCap("weapon_hazardcan"), components = {}, ammo = { label = TranslateCap("ammo_petrol"), hash = `AMMO_PETROLCAN` }, throwable = true },
|
||||
{ name = "WEAPON_MOLOTOV", label = TranslateCap("weapon_molotov"), components = {}, ammo = { label = TranslateCap("ammo_molotov"), hash = `AMMO_MOLOTOV` }, throwable = true },
|
||||
{ name = "WEAPON_PROXMINE", label = TranslateCap("weapon_proxmine"), components = {}, ammo = { label = TranslateCap("ammo_proxmine"), hash = `AMMO_PROXMINE` }, throwable = true },
|
||||
{ name = "WEAPON_PIPEBOMB", label = TranslateCap("weapon_pipebomb"), components = {}, ammo = { label = TranslateCap("ammo_pipebomb"), hash = `AMMO_PIPEBOMB` }, throwable = true },
|
||||
{ name = "WEAPON_SNOWBALL", label = TranslateCap("weapon_snowball"), components = {}, ammo = { label = TranslateCap("ammo_snowball"), hash = `AMMO_SNOWBALL` }, throwable = true },
|
||||
{ name = "WEAPON_STICKYBOMB", label = TranslateCap("weapon_stickybomb"), components = {}, ammo = { label = TranslateCap("ammo_stickybomb"), hash = `AMMO_STICKYBOMB` }, throwable = true },
|
||||
{ name = "WEAPON_SMOKEGRENADE", label = TranslateCap("weapon_smokegrenade"), components = {}, ammo = { label = TranslateCap("ammo_smokebomb"), hash = `AMMO_SMOKEGRENADE` }, throwable = true },
|
||||
-- Tools
|
||||
{ name = "WEAPON_FIREEXTINGUISHER", label = TranslateCap("weapon_fireextinguisher"), components = {}, ammo = { label = TranslateCap("ammo_charge"), hash = `AMMO_FIREEXTINGUISHER` } },
|
||||
{ name = "WEAPON_DIGISCANNER", label = TranslateCap("weapon_digiscanner"), components = {} },
|
||||
{ name = "GADGET_PARACHUTE", label = TranslateCap("gadget_parachute"), components = {} },
|
||||
{ name = "GADGET_PARACHUTE", label = TranslateCap("gadget_parachute"), components = {}, throwable = true },
|
||||
{
|
||||
name = "WEAPON_TACTICALRIFLE",
|
||||
label = TranslateCap("weapon_tactilerifle"),
|
||||
@@ -1057,7 +1057,7 @@ Config.Weapons = {
|
||||
{ name = "suppressor", label = TranslateCap("component_suppressor"), hash = `COMPONENT_PISTOLXM3_SUPP` },
|
||||
},
|
||||
},
|
||||
{ name = "WEAPON_ACIDPACKAGE", label = TranslateCap("weapon_acidpackage"), components = {} },
|
||||
{ name = "WEAPON_ACIDPACKAGE", label = TranslateCap("weapon_acidpackage"), components = {}, throwable = true },
|
||||
{ name = "WEAPON_CANDYCANE", label = TranslateCap("weapon_candycane"), components = {} },
|
||||
{
|
||||
name = "WEAPON_RAILGUNXM3",
|
||||
|
||||
@@ -164,3 +164,10 @@ function ESX.AssertType(...)
|
||||
|
||||
return matches
|
||||
end
|
||||
|
||||
---@param val unknown
|
||||
function ESX.IsFunctionReference(val)
|
||||
local typeVal = type(val)
|
||||
|
||||
return typeVal == "function" or (typeVal == "table" and type(getmetatable(val)?.__call) == "function")
|
||||
end
|
||||
@@ -223,3 +223,11 @@ function ESX.Table.Sort(t, order)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ESX.Table.ToArray(table)
|
||||
local array = {}
|
||||
for _, v in pairs(table) do
|
||||
array[#array + 1] = v
|
||||
end
|
||||
return array
|
||||
end
|
||||
|
||||
@@ -272,7 +272,6 @@ function Multicharacter:PlayerLoaded(playerData, isNew, skin)
|
||||
|
||||
TriggerServerEvent("esx:onPlayerSpawn")
|
||||
TriggerEvent("esx:onPlayerSpawn")
|
||||
TriggerEvent("playerSpawned")
|
||||
TriggerEvent("esx:restoreLoadout")
|
||||
|
||||
self:Reset()
|
||||
|
||||
@@ -13,7 +13,7 @@ function Multicharacter:SetupCharacters(source)
|
||||
local identifier = Server:GetIdentifier(source)
|
||||
ESX.Players[identifier] = true
|
||||
|
||||
local slots = Database:GetPlayerSlots()
|
||||
local slots = Database:GetPlayerSlots(identifier)
|
||||
identifier = Server.prefix .. "%:" .. identifier
|
||||
|
||||
local rawCharacters = Database:GetPlayerInfo(identifier, slots)
|
||||
|
||||
@@ -47,7 +47,7 @@ function Menu:InsertElements()
|
||||
value = GetPedPropIndex(playerPed, self.components[i].componentId)
|
||||
end
|
||||
|
||||
local data = self.components[i]
|
||||
local data = table.clone(self.components[i])
|
||||
data.value = value
|
||||
data.type = "slider"
|
||||
data.max = self.maxValues[self.components[i].name]
|
||||
@@ -57,7 +57,7 @@ function Menu:InsertElements()
|
||||
end
|
||||
|
||||
function Menu:Submit(data, menu)
|
||||
Skin.last = exports["skinchanger"]:GetSkin()
|
||||
Skin.Last = exports["skinchanger"]:GetSkin()
|
||||
self.submitCb(data, menu)
|
||||
Camera:Destroy()
|
||||
end
|
||||
@@ -65,7 +65,7 @@ end
|
||||
function Menu:Cancel(data, menu)
|
||||
menu.close()
|
||||
Camera:Destroy()
|
||||
TriggerEvent("skinchanger:loadSkin", Skin.last)
|
||||
TriggerEvent("skinchanger:loadSkin", Skin.Last)
|
||||
|
||||
if self.cancelCb then
|
||||
self.cancelCb(data, menu)
|
||||
@@ -78,27 +78,39 @@ function Menu:Change(data, menu)
|
||||
Skin.zoomOffset = data.current.zoomOffset
|
||||
Skin.camOffset = data.current.camOffset
|
||||
|
||||
if skin[data.current.name] ~= data.current.value then
|
||||
-- Change skin element
|
||||
exports["skinchanger"]:Change(data.current.name, data.current.value)
|
||||
skin[data.current.name] = data.current.value
|
||||
if skin[data.current.name] == data.current.value then
|
||||
return
|
||||
end
|
||||
|
||||
local newData = {}
|
||||
-- Change skin element
|
||||
exports["skinchanger"]:Change(data.current.name, data.current.value)
|
||||
skin[data.current.name] = data.current.value
|
||||
|
||||
for i = 1, #self.elements, 1 do
|
||||
-- Texture variation changed. We don't have to update anything.
|
||||
if data.current.textureof then
|
||||
return
|
||||
end
|
||||
|
||||
-- Texture changed. Update variation max value.
|
||||
for i = 1, #self.elements, 1 do
|
||||
local element = self.elements[i]
|
||||
|
||||
if element.textureof == data.current.name then
|
||||
local component = self.components[i]
|
||||
|
||||
newData.max = type(component.max) == "function" and component.max(PlayerPedId(), skin) or component.max
|
||||
|
||||
if self.elements[i].textureof ~= nil and data.current.name == self.elements[i].textureof then
|
||||
newData.value = 0
|
||||
if ESX.IsFunctionReference(component.max) then
|
||||
self.elements[i].max = component.max(PlayerPedId(), skin)
|
||||
end
|
||||
self.elements[i].value = 0
|
||||
|
||||
menu.update({ name = self.elements[i].name }, newData)
|
||||
-- Change skin element
|
||||
exports["skinchanger"]:Change(element.name, 0)
|
||||
skin[element.name] = data.current.value
|
||||
|
||||
menu.update({ name = self.elements[i].name }, self.elements[i])
|
||||
menu.refresh()
|
||||
break
|
||||
end
|
||||
|
||||
self.elements = newData
|
||||
menu.refresh()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -111,7 +123,7 @@ function Menu:Open(submit, cancel, restrict)
|
||||
self.submitCb = submit
|
||||
self.cancelCb = cancel
|
||||
self.restricted = restrict
|
||||
Skin.last = exports["skinchanger"]:GetSkin()
|
||||
Skin.Last = exports["skinchanger"]:GetSkin()
|
||||
|
||||
self.components, self.maxValues = exports["skinchanger"]:GetData()
|
||||
if restrict then
|
||||
@@ -128,7 +140,7 @@ function Menu:Open(submit, cancel, restrict)
|
||||
end
|
||||
|
||||
function Menu:Saveable(submitCb, cancelCb, restrict)
|
||||
Skin.last = exports["skinchanger"]:GetSkin()
|
||||
Skin.Last = exports["skinchanger"]:GetSkin()
|
||||
|
||||
self:Open(function(data, menu)
|
||||
menu.close()
|
||||
|
||||
@@ -237,6 +237,7 @@ Config.Components = {
|
||||
min = 0,
|
||||
zoomOffset = 0.6,
|
||||
camOffset = 0.65,
|
||||
textureof = "hair_1",
|
||||
max = function(playerPed, Character)
|
||||
return GetNumberOfPedTextureVariations(playerPed, 2, Character["hair_1"]) - 1
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user