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