Files
red-valley/resources/[framework]/[base]/[auth]/17mov_CharacterSystem/client/functions.lua
2026-03-29 21:41:17 +03:00

415 lines
12 KiB
Lua

while Core == nil do
Wait(10)
end
function DisableSpawnManager()
if GetResourceState("spawnmanager") == "started" then
exports.spawnmanager:setAutoSpawn(false)
end
end
RegisterNetEvent("17mov_CharacterSystem:SkinMenuOpened", function()
-- You can add custom code after skin menu open
if GetResourceState("qs-inventory") ~= "missing" then
exports['qs-inventory']:setInClothing(true)
end
end)
RegisterNetEvent("17mov_CharacterSystem:SkinMenuClosed", function()
-- You can add custom code after skin menu open
if GetResourceState("qs-inventory") ~= "missing" then
exports['qs-inventory']:setInClothing(false)
end
end)
function Register.OpenCustom(characterId)
-- Here you can implement your custom register system when using Register.Enable = false
print("Opened character register for slot:", characterId)
end
-- ============================================
-- SPAWN OUTFIT — Red Valley RP
-- Separate outfits for male & female
-- ============================================
local spawnOutfitMale = {
['pants'] = {item = 200, texture = 2},
['arms'] = {item = 96, texture = 0},
['t-shirt'] = {item = 15, texture = 0},
['vest'] = {item = 0, texture = 0},
['torso2'] = {item = 539, texture = 2},
['shoes'] = {item = 77, texture = 8},
['accessory'] = {item = 0, texture = 0},
['bag'] = {item = 0, texture = 0},
['hat'] = {item = -1, texture = -1},
['glass'] = {item = -1, texture = -1},
['mask'] = {item = 0, texture = 0}, -- no mask
}
local spawnOutfitFemale = {
['pants'] = {item = 214, texture = 1},
['arms'] = {item = 18, texture = 0},
['t-shirt'] = {item = 15, texture = 0},
['vest'] = {item = 0, texture = 0},
['torso2'] = {item = 583, texture = 1},
['shoes'] = {item = 81, texture = 10},
['accessory'] = {item = 0, texture = 0},
['bag'] = {item = 0, texture = 0},
['hat'] = {item = -1, texture = -1},
['glass'] = {item = -1, texture = -1},
['mask'] = {item = 0, texture = 0}, -- no mask
}
local spawnComponentMap = {
['mask'] = 1,
['arms'] = 3,
['pants'] = 4,
['bag'] = 5,
['shoes'] = 6,
['accessory'] = 7,
['t-shirt'] = 8,
['vest'] = 9,
['torso2'] = 11,
}
local spawnPropMap = {
['hat'] = 0,
['glass'] = 1,
}
local function ApplySpawnOutfit()
local ped = PlayerPedId()
local model = GetEntityModel(ped)
local isFemale = (model == GetHashKey("mp_f_freemode_01"))
local outfit = isFemale and spawnOutfitFemale or spawnOutfitMale
for name, data in pairs(outfit) do
if spawnComponentMap[name] then
SetPedComponentVariation(ped, spawnComponentMap[name], data.item, data.texture, 0)
elseif spawnPropMap[name] then
if data.item == -1 then
ClearPedProp(ped, spawnPropMap[name])
else
SetPedPropIndex(ped, spawnPropMap[name], data.item, data.texture, true)
end
end
end
end
-- ============================================
function Location.PlayerSpawned(isNew, info)
-- Here you can add some custom code after player spawned
if Config.Framework == "qb-core" then
TriggerServerEvent('QBCore:Server:OnPlayerLoaded')
TriggerEvent('QBCore:Client:OnPlayerLoaded')
elseif Config.Framework == "es_extended" then
-- Added for players who are using "illenium-appearance", because it's not marking player as "spawned" after loading player skin.
-- When ESX see that player is not "spawned" then it's just returning function that saves players with no information.
-- Result: Player is not saved after exiting
if not Skin.Enabled then
TriggerServerEvent("esx:onPlayerSpawn")
end
-- Here you can add your custom code
end
if not isNew then
Housing.EnterLastHouse(info)
Apartments.EnterLastApartment(info)
end
if Skin.DisableHealthRegen then
-- Fix of issue where player health stays at 50%
CreateThread(function()
Wait(5000)
local player = PlayerId()
SetPlayerHealthRechargeMultiplier(player, 0.0)
SetPlayerHealthRechargeLimit(player, 0.0)
end)
end
DisplayRadar(true)
if isNew then
TriggerEvent("inventory:client:GiveStarterItems")
end
-- Apply spawn outfit only for NEW characters (first spawn)
if isNew then
CreateThread(function()
Wait(1000)
ApplySpawnOutfit()
-- Save the spawn outfit to DB so it persists through relogs
Wait(500)
TriggerEvent("17mov_CharacterSystem:SaveCurrentSkin")
end)
end
end
function ShowHelpNotification(msg)
if msg == nil then return end
AddTextEntry('HelpNotification', msg)
DisplayHelpTextThisFrame('HelpNotification', false)
end
function Notify(msg)
if Config.Framework == "qb-core" then
Core?.Functions?.Notify(msg)
elseif Config.Framework == "es_extended" then
Core?.ShowNotification(msg)
else
SetNotificationTextEntry('STRING')
AddTextComponentString(msg)
DrawNotification(false, true)
end
end
function GetJob()
if Config.Framework == "qb-core" then
local playerData = Core?.Functions?.GetPlayerData()
return playerData?.job?.name
elseif Config.Framework == "es_extended" then
local playerData = Core?.GetPlayerData()
return playerData?.job?.name
end
return nil
end
function GetGang()
if Config.Framework == "qb-core" then
local playerData = Core?.Functions?.GetPlayerData()
return playerData?.gang?.name
elseif Config.Framework == "es_extended" then
-- No default gang system, need to implement at your own
end
return nil
end
function GetIdentifier()
if Config.Framework == "qb-core" then
local playerData = Core?.Functions?.GetPlayerData()
return playerData?.license
elseif Config.Framework == "es_extended" then
local playerData = Core?.GetPlayerData()
return playerData?.identifier
end
return nil
end
function OnSelectorEnter()
end
function OnSelectorExit()
end
-- Used to display data about selected character in selector (at right side of screen)
function GetCharacterDetails(character)
local function FormatMoney(amount)
local isMinus = amount < 0
amount = math.abs(amount)
local separator = Config.MoneySeparator or "."
local formatted = tostring(amount)
local k = 0
while true do
formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1' .. separator .. '%2')
if k == 0 then break end
Wait(0)
end
formatted = "$" .. formatted
if isMinus then
formatted = "-" .. formatted
end
return formatted
end
return {
{
label = _L("Selector.Info.Cash"),
value = FormatMoney(character.cash),
},
{
label = _L("Selector.Info.Bank"),
value = FormatMoney(character.bank),
},
{
label = _L("Selector.Info.Nationality"),
value = character.nationality,
},
{
label = _L("Selector.Info.DateOfBirth"),
value = character.dateOfBirth,
},
{
label = _L("Selector.Info.Gender"),
value = character.isMale and _L("Selector.Info.Male") or _L("Selector.Info.Female"),
},
}
end
function ShutDownLoadingScreen()
ShutdownLoadingScreen()
ShutdownLoadingScreenNui()
end
-- Target system
if Config.UseTarget then
if Config.Framework == "qb-core" then
Config.TargetSystem = "qb-target"
else
Config.TargetSystem = "qtarget"
end
if GetResourceState("ox_target") ~= "missing" then
Config.TargetSystem = "qtarget" -- OX_Target have a backward compability to qtarget
end
end
function AddTargetStorePed(ped, shopType, shopIndex)
exports[Config.TargetSystem]:AddTargetEntity(ped, {
options = {
{
event = "17mov_CharacterSystem:OpenStore",
icon = "fa-solid fa-shirt",
label = _L("Store.Use"),
shopType = shopType,
shopIndex = shopIndex,
canInteract = function(entity)
return #(GetEntityCoords(PlayerPedId()) - GetEntityCoords(entity)) <
(Config.Stores[shopIndex]?.radius or 3.0)
end
},
},
distance = Config.Stores[shopIndex]?.radius or 3.0
})
end
if Skin.EnableRefreshSkinCommand then
local isCommandBlocked = false
local lastCommandTime = 0
local commandCooldown = 5000
RegisterCommand("refreshSkin", function()
local currentTime = GetGameTimer()
if isCommandBlocked or currentTime - lastCommandTime < commandCooldown then
return Notify(_L("Skin.RefreshSkinCommand.Unavalible"))
end
lastCommandTime = currentTime
local PlayerPed = PlayerPedId()
local maxhealth = GetEntityMaxHealth(PlayerPed)
local health = GetEntityHealth(PlayerPed)
local maxArmor = GetPlayerMaxArmour(PlayerId())
local armor = GetPedArmour(PlayerPed)
local startTime = GetGameTimer()
local skinToSet = nil
if Config.Framework == "qb-core" then
Core.Functions.TriggerCallback("qb-clothing:server:getPlayerSkin", function(data)
skinToSet = TranslateSkinFromQB(data.skin, data.model)
end)
else
Core.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin)
skinToSet = TranslateSkinFromESX(skin)
end)
end
while not skinToSet do
if GetGameTimer() - startTime > 3000 then
return Functions.Debug("CANNOT FETCH SKINDATA")
end
Wait(10)
end
if IsModelInCdimage(skinToSet.model) then
Functions.LoadModel(skinToSet.model)
SetPlayerModel(PlayerId(), skinToSet.model)
end
Skin.SetOnPed(PlayerPedId(), skinToSet)
Wait(1000)
local PlayerPed = PlayerPedId()
if maxhealth > 0 then
SetPedMaxHealth(PlayerPed, maxhealth)
end
if health > 0 then
SetEntityHealth(PlayerPed, health)
end
if maxArmor > 0 then
SetPlayerMaxArmour(PlayerId(), maxArmor)
end
if armor > 0 then
SetPedArmour(PlayerPed, armor)
end
end, false)
exports("BlockRefreshSkinCommand", function()
isCommandBlocked = true
end)
exports("UnblockRefreshSkinCommand", function()
isCommandBlocked = false
end)
exports("IsRefreshSkinCommandBlocked", function()
return isCommandBlocked
end)
end
if GetResourceState("rcore_clothing") ~= "missing" then
CreateThread(function()
while Skin == nil and Skin.SetOnPed == nil do
Citizen.Wait(100)
end
---@diagnostic disable-next-line: duplicate-set-field
Skin.SetOnPed = function(ped, skinData)
if skinData ~= nil and skinData.components then
for k, v in pairs(skinData.components) do
if not (type(k) == "string" and type(tonumber(k)) == "number" and type(v) == "string") then
return
end
end
exports.rcore_clothing:setPedSkin(ped, skinData)
end
end
end)
end
local _SetPlayerModel = SetPlayerModel
SetPlayerModel = function(player, model)
local returnValue = _SetPlayerModel(player, model)
if Skin.DisableHealthRegen then
SetPlayerHealthRechargeMultiplier(PlayerId(), 0.0)
SetPlayerHealthRechargeLimit(PlayerId(), 0.0)
end
return returnValue
end
local _ChangePlayerPed = ChangePlayerPed
ChangePlayerPed = function(player, ped, b2, resetDamage)
local returnValue = _ChangePlayerPed(player, ped, b2, resetDamage)
if Skin.DisableHealthRegen then
SetPlayerHealthRechargeMultiplier(PlayerId(), 0.0)
SetPlayerHealthRechargeLimit(PlayerId(), 0.0)
end
return returnValue
end