Merge branch 'dev' into extra-callback-functions

This commit is contained in:
Kasey FItton
2024-12-03 22:45:54 +00:00
18 changed files with 237 additions and 129 deletions
+7
View File
@@ -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`
--
+1 -1
View File
@@ -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
+65 -31
View File
@@ -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
+23 -8
View File
@@ -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)
+13 -26
View File
@@ -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)
+11 -2
View File
@@ -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
+16 -14
View File
@@ -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)
+21 -6
View File
@@ -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
+14 -14
View File
@@ -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",
+7
View File
@@ -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)
+31 -19
View File
@@ -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()
+1
View File
@@ -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