ESX Legacy

  • Remove esx_skin, skinchanger and other related scripts with skin.

  • Delete dependencies in fxmanifest.lua from scripts above.

  • Replace code in esx_multicharacter/client/main.lua to this.

esx_multicharacter/client/main.lua
local mp_m_freemode_01 = "mp_m_freemode_01"
local mp_f_freemode_01 = "mp_f_freemode_01"

local SpawnCoords = Config.Spawn[ESX.Math.Random(1, #Config.Spawn)]

if ESX.GetConfig().Multichar then
    CreateThread(function()
        while not ESX.PlayerLoaded do
            Wait(100)

            if NetworkIsPlayerActive(PlayerId()) then
                exports.spawnmanager:setAutoSpawn(false)
                DoScreenFadeOut(0)
                while GetResourceState("esx_context") ~= "started" do
                    Wait(100)
                end
                TriggerEvent("esx_multicharacter:SetupCharacters")
                break
            end
        end
    end)

    local canRelog, cam, spawned = true, nil, nil
    local Characters, hidePlayers = {}, false

    RegisterNetEvent("esx_multicharacter:SetupCharacters")
    AddEventHandler("esx_multicharacter:SetupCharacters", function()
        ESX.PlayerLoaded = false
        ESX.PlayerData = {}
        spawned = false
        cam = CreateCam("DEFAULT_SCRIPTED_CAMERA", true)
        local playerPed = PlayerPedId()
        SetEntityCoords(playerPed, SpawnCoords.x, SpawnCoords.y, SpawnCoords.z, true, false, false, false)
        SetEntityHeading(playerPed, SpawnCoords.w)
        local offset = GetOffsetFromEntityInWorldCoords(playerPed, 0, 1.7, 0.4)
        DoScreenFadeOut(0)
        SetCamActive(cam, true)
        RenderScriptCams(true, false, 1, true, true)
        SetCamCoord(cam, offset.x, offset.y, offset.z)
        PointCamAtCoord(cam, SpawnCoords.x, SpawnCoords.y, SpawnCoords.z + 1.3)
        StartLoop()
        ShutdownLoadingScreen()
        ShutdownLoadingScreenNui()
        TriggerEvent("esx:loadingScreenOff")
        Wait(200)
        TriggerServerEvent("esx_multicharacter:SetupCharacters")
    end)

    StartLoop = function()
        hidePlayers = true
        MumbleSetVolumeOverride(PlayerId(), 0.0)
        CreateThread(function()
            local keys = { 18, 27, 172, 173, 174, 175, 176, 177, 187, 188, 191, 201, 108, 109, 209, 19 }
            while hidePlayers do
                DisableAllControlActions(0)
                for i = 1, #keys do
                    EnableControlAction(0, keys[i], true)
                end
                SetEntityVisible(PlayerPedId(), 0, 0)
                SetLocalPlayerVisibleLocally(1)
                SetPlayerInvincible(PlayerId(), 1)
                ThefeedHideThisFrame()
                HideHudComponentThisFrame(11)
                HideHudComponentThisFrame(12)
                HideHudComponentThisFrame(21)
                HideHudAndRadarThisFrame()
                Wait(0)
                local vehicles = GetGamePool("CVehicle")
                for i = 1, #vehicles do
                    SetEntityLocallyInvisible(vehicles[i])
                end
            end
            local playerId, playerPed = PlayerId(), PlayerPedId()
            MumbleSetVolumeOverride(playerId, -1.0)
            SetEntityVisible(playerPed, 1, 0)
            SetPlayerInvincible(playerId, 0)
            FreezeEntityPosition(playerPed, false)
            Wait(10000)
            canRelog = true
        end)
        CreateThread(function()
            local playerPool = {}
            while hidePlayers do
                local players = GetActivePlayers()
                for i = 1, #players do
                    local player = players[i]
                    if player ~= PlayerId() and not playerPool[player] then
                        playerPool[player] = true
                        NetworkConcealPlayer(player, true, true)
                    end
                end
                Wait(500)
            end
            for k in pairs(playerPool) do
                NetworkConcealPlayer(k, false, false)
            end
        end)
    end

    SetupCharacter = function(index)
        if not spawned then
            exports.spawnmanager:spawnPlayer({
                x = SpawnCoords.x,
                y = SpawnCoords.y,
                z = SpawnCoords.z,
                heading = SpawnCoords.w,
                model = Characters[index].model or mp_m_freemode_01,
                skipFade = true,
            }, function()
                canRelog = false
                if Characters[index] then
                    local skin = Characters[index].skin
                    exports['nf-skin']:SetPedAppearance(PlayerPedId(), skin)
                end
                DoScreenFadeIn(600)
            end)
            repeat
                Wait(200)
            until not IsScreenFadedOut()
        elseif Characters[index] and Characters[index].skin then
            if Characters[spawned] and Characters[spawned].model then
                exports['nf-skin']:SetPedModel(Characters[index].model, function(entityPed)
                    exports['nf-skin']:SetPedAppearance(entityPed, Characters[index].skin)
                end)
            else
                exports['nf-skin']:SetPedAppearance(PlayerPedId(), Characters[index].skin)
            end
        end
        spawned = index
        local playerPed = PlayerPedId()
        FreezeEntityPosition(PlayerPedId(), true)
        SetPedAoBlobRendering(playerPed, true)
        SetEntityAlpha(playerPed, 255)
        SendNUIMessage({
            action = "openui",
            character = Characters[spawned],
        })
    end

    function CharacterDeleteConfirmation(characters, slots, SelectedCharacter, value)
        local elements = {
            { title = TranslateCap("char_delete_confirmation"), icon = "fa-solid fa-users", description = TranslateCap("char_delete_confirmation_description"), unselectable = true },
            { title = TranslateCap("char_delete"),              icon = "fa-solid fa-xmark", description = TranslateCap("char_delete_yes_description"),          action = "delete",                                        value = value },
            { title = TranslateCap("return"),                   unselectable = false,       icon = "fa-solid fa-arrow-left",                                    description = TranslateCap("char_delete_no_description"), action = "return" },
        }

        ESX.OpenContext("left", elements, function(_, Action)
            if Action.action == "delete" then
                ESX.CloseContext()
                TriggerServerEvent("esx_multicharacter:DeleteCharacter", Action.value)
                spawned = false
            elseif Action.action == "return" then
                CharacterOptions(characters, slots, SelectedCharacter)
            end
        end, nil, false)
    end

    function CharacterOptions(characters, slots, SelectedCharacter)
        local elements = {
            { title = TranslateCap("character", characters[SelectedCharacter.value].firstname .. " " .. characters[SelectedCharacter.value].lastname), icon = "fa-regular fa-user", unselectable = true },
            { title = TranslateCap("return"),                                                                                                          unselectable = false,        icon = "fa-solid fa-arrow-left", description = TranslateCap("return_description"), action = "return" },
        }
        if not characters[SelectedCharacter.value].disabled then
            elements[3] = {
                title = TranslateCap("char_play"),
                description = TranslateCap("char_play_description"),
                icon =
                "fa-solid fa-play",
                action = "play",
                value = SelectedCharacter.value
            }
        else
            elements[3] = {
                title = TranslateCap("char_disabled"),
                value = SelectedCharacter.value,
                icon =
                "fa-solid fa-xmark",
                description = TranslateCap("char_disabled_description")
            }
        end
        if Config.CanDelete then
            elements[4] = {
                title = TranslateCap("char_delete"),
                icon = "fa-solid fa-xmark",
                description = TranslateCap(
                    "char_delete_description"),
                action = "delete",
                value = SelectedCharacter.value
            }
        end
        ESX.OpenContext("left", elements, function(_, Action)
            if Action.action == "play" then
                SendNUIMessage({
                    action = "closeui",
                })
                ESX.CloseContext()
                TriggerServerEvent("esx_multicharacter:CharacterChosen", Action.value, false)
            elseif Action.action == "delete" then
                CharacterDeleteConfirmation(characters, slots, SelectedCharacter, Action.value)
            elseif Action.action == "return" then
                SelectCharacterMenu(characters, slots)
            end
        end, nil, false)
    end

    function SelectCharacterMenu(characters, slots)
        local Character = next(characters)
        local elements = { { title = TranslateCap("select_char"), icon = "fa-solid fa-users", description = TranslateCap("select_char_description"), unselectable = true } }
        for k, v in pairs(characters) do
            if not v.model and v.skin then
                if v.skin.model then
                    v.model = v.skin.model
                elseif v.skin.sex == 1 then
                    v.model = mp_f_freemode_01
                else
                    v.model = mp_m_freemode_01
                end
            end
            if not spawned then
                SetupCharacter(Character)
            end
            local label = v.firstname .. " " .. v.lastname
            if characters[k].disabled then
                elements[#elements + 1] = { title = label, icon = "fa-regular fa-user", value = v.id }
            else
                elements[#elements + 1] = { title = label, icon = "fa-regular fa-user", value = v.id }
            end
        end
        if #elements - 1 < slots then
            elements[#elements + 1] = { title = TranslateCap("create_char"), icon = "fa-solid fa-plus", value = (#elements + 1), new = true }
        end

        ESX.OpenContext("left", elements, function(_, SelectedCharacter)
            if SelectedCharacter.new then
                ESX.CloseContext()
                local GetSlot = function()
                    for i = 1, slots do
                        if not characters[i] then
                            return i
                        end
                    end
                end
                local slot = GetSlot()
                TriggerServerEvent("esx_multicharacter:CharacterChosen", slot, true)
                TriggerEvent("esx_identity:showRegisterIdentity")
                local playerPed = PlayerPedId()
                SetPedAoBlobRendering(playerPed, false)
                SetEntityAlpha(playerPed, 0)
                SendNUIMessage({
                    action = "closeui",
                })
            else
                CharacterOptions(characters, slots, SelectedCharacter)
                SetupCharacter(SelectedCharacter.value)
                local playerPed = PlayerPedId()
                SetPedAoBlobRendering(playerPed, true)
                ResetEntityAlpha(playerPed)
            end
        end, nil, false)
    end

    RegisterNetEvent("esx_multicharacter:SetupUI")
    AddEventHandler("esx_multicharacter:SetupUI", function(data, slots)
        DoScreenFadeOut(0)
        Characters = data
        slots = slots
        local Character = next(Characters)
        exports.spawnmanager:forceRespawn()

        if not Character then
            SendNUIMessage({
                action = "closeui",
            })
            exports.spawnmanager:spawnPlayer({
                x = SpawnCoords.x,
                y = SpawnCoords.y,
                z = SpawnCoords.z,
                heading = SpawnCoords.w,
                model = mp_m_freemode_01,
                skipFade = true,
            }, function()
                canRelog = false
                DoScreenFadeIn(400)
                Wait(400)
                local playerPed = PlayerPedId()
                SetPedAoBlobRendering(playerPed, false)
                SetEntityAlpha(playerPed, 0)
                TriggerServerEvent("esx_multicharacter:CharacterChosen", 1, true)
                TriggerEvent("esx_identity:showRegisterIdentity")
            end)
        else
            SelectCharacterMenu(Characters, slots)
        end
    end)

    RegisterNetEvent("esx:playerLoaded")
    AddEventHandler("esx:playerLoaded", function(playerData, isNew, skin)
        local spawn = playerData.coords or Config.Spawn
        if isNew or not skin or #skin == 1 then
            local finished = false
            skin.sex = playerData.sex == "m" and 0 or 1
            local model = skin.sex == 0 and mp_m_freemode_01 or mp_f_freemode_01

            exports['nf-skin']:SetPedModel(model, function(entityPed)
                SetPedAoBlobRendering(entityPed, true)
                ResetEntityAlpha(entityPed)
                exports['nf-skin']:OpenCreationMenu(entityPed, function()
                    finished = true
                end)
            end)

            repeat
                Wait(200)
            until finished
        end

        DoScreenFadeOut(750)
        Wait(750)

        SetCamActive(cam, false)
        RenderScriptCams(false, false, 0, true, true)
        cam = nil
        local playerPed = PlayerPedId()
        FreezeEntityPosition(playerPed, true)
        SetEntityCoordsNoOffset(playerPed, spawn.x, spawn.y, spawn.z, false, false, false, true)
        SetEntityHeading(playerPed, spawn.heading)
        if not isNew then
            -- TriggerEvent("skinchanger:loadSkin", skin or Characters[spawned].skin)
            exports['nf-skin']:SetPedAppearance(playerPed, Characters[spawned].skin)
        end
        Wait(500)

        DoScreenFadeIn(750)
        Wait(750)

        repeat
            Wait(200)
        until not IsScreenFadedOut()
        TriggerServerEvent("esx:onPlayerSpawn")
        TriggerEvent("esx:onPlayerSpawn")
        TriggerEvent("playerSpawned")
        TriggerEvent("esx:restoreLoadout")
        Characters, hidePlayers = {}, false
    end)

    RegisterNetEvent("esx:onPlayerLogout")
    AddEventHandler("esx:onPlayerLogout", function()
        DoScreenFadeOut(500)
        Wait(1000)
        spawned = false
        TriggerEvent("esx_multicharacter:SetupCharacters")
        TriggerEvent("esx_skin:resetFirstSpawn")
    end)

    if Config.Relog then
        RegisterCommand("relog", function()
            if canRelog then
                canRelog = false
                TriggerServerEvent("esx_multicharacter:relog")
                ESX.SetTimeout(10000, function()
                    canRelog = true
                end)
            end
        end, false)
    end
end

Last updated