From f81ed024cfbc9ef950d466c25a1e814e61338b09 Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Thu, 20 May 2021 22:50:02 +1000 Subject: [PATCH] feat(rewrite/client): Overhauled spawning logic and character selection - Utilise spawnmanager for character selection and spawning - Removed old character selection interface, opting for the easily scaleable ESX Menu - Player concealment while selecting a character - Improved character registration and loading player skin --- client/main.lua | 312 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 212 insertions(+), 100 deletions(-) diff --git a/client/main.lua b/client/main.lua index 1f079e7c..2e590169 100644 --- a/client/main.lua +++ b/client/main.lua @@ -12,133 +12,245 @@ if ESX.GetConfig().Multichar then end) AddEventHandler("onClientMapStart", function() - exports.spawnmanager:spawnPlayer() - Citizen.Wait(5000) exports.spawnmanager:setAutoSpawn(false) end) local cam, cam2 = nil, nil + local Characters = {} + local Spawned RegisterNetEvent('esx_multicharacter:SetupCharacters') AddEventHandler('esx_multicharacter:SetupCharacters', function() ESX.PlayerLoaded = false ESX.PlayerData = {} + Spawned = false ESX.UI.HUD.SetDisplay(0.0) DisplayHud(false) DisplayRadar(false) - ShutdownLoadingScreen() - Citizen.Wait(100) - while not IsScreenFadedOut() do - Citizen.Wait(10) - end - SetTimecycleModifier('hud_def_blur') - FreezeEntityPosition(PlayerPedId(), true) - cam = CreateCamWithParams("DEFAULT_SCRIPTED_CAMERA", -1355.93,-1487.78,520.75, 300.00,0.00,0.00, 100.00, false, 0) - SetCamActive(cam, true) - RenderScriptCams(true, false, 1, true, true) - DoScreenFadeIn(500) - end) - - RegisterNetEvent('esx_multicharacter:SetupUI') - AddEventHandler('esx_multicharacter:SetupUI', function(Characters) - NetworkConcealPlayer(PlayerId(), 1, 0) - Citizen.Wait(500) - SetNuiFocus(true, true) - SendNUIMessage({ - action = "openui", - characters = Characters, - }) + StartLoop() ShutdownLoadingScreen() ShutdownLoadingScreenNui() TriggerEvent('esx:loadingScreenOff') + cam = CreateCamWithParams("DEFAULT_SCRIPTED_CAMERA", Config.Spawn.x, Config.Spawn.y+1.6, Config.Spawn.z+0.5, 0.0, 0.0, 180.0, 100.00, false, 0) + SetCamActive(cam, true) + RenderScriptCams(true, false, 1, true, true) + SetPlayerControl(PlayerId(), false, false) + end) + + StartLoop = function() + Citizen.CreateThread(function() + while true do + if hidePlayers == false then break end + local players = GetActivePlayers() + for i=1, #players do + if players[i] ~= PlayerId() then NetworkConcealPlayer(players[i], true, true) end + end + Citizen.Wait(500) + end + local players = GetActivePlayers() + for i=1, #players do + if players[i] ~= PlayerId() then NetworkConcealPlayer(players[i], false, false) end + end + end) + end + + SetupCharacter = function(index) + if Spawned == false then + exports.spawnmanager:forceRespawn() + exports.spawnmanager:spawnPlayer({ + x = Config.Spawn.x, + y = Config.Spawn.y, + z = Config.Spawn.z, + heading = Config.Spawn.w, + model = Characters[index].model or `mp_m_freemode_01`, + skipFade = true + }, function() + if Characters[index] then TriggerEvent('skinchanger:loadSkin', Characters[index].skin) end + end) + elseif Characters[index] and Characters[index].skin then + if Characters[Spawned] and Characters[Spawned].model ~= Characters[index].model then + RequestModel(Characters[index].model) + while not HasModelLoaded(Characters[index].model) do + RequestModel(Characters[index].model) + Citizen.Wait(0) + end + SetPlayerModel(PlayerId(), Characters[index].model) + SetModelAsNoLongerNeeded(Characters[index].model) + end + TriggerEvent('skinchanger:loadSkin', Characters[index].skin) + end + FreezeEntityPosition(PlayerPedId(), true) + Spawned = index + --[[SendNUIMessage({ + action = "openui", + character = Characters[index] + })]] + end + + LoadPed = function(isNew, skin) + if isNew then + if skin.sex == 0 then isMale = true else isMale = false end + TriggerEvent('skinchanger:loadDefaultModel', isMale, function() + TriggerEvent('skinchanger:loadSkin', {sex = skin.sex}) + Citizen.Wait(500) + TriggerEvent('esx_skin:openSaveableMenu') + end) + else TriggerEvent('skinchanger:loadSkin', skin) Citizen.Wait(500) end + end + + RegisterNetEvent('esx_multicharacter:SetupUI') + AddEventHandler('esx_multicharacter:SetupUI', function(data) + if data then Characters = data end + local elements = {} + + if #Characters == 0 then + exports.spawnmanager:spawnPlayer({ + x = Config.Spawn.x, + y = Config.Spawn.y, + z = Config.Spawn.z, + heading = Config.Spawn.w, + model = `mp_m_freemode_01`, + skipFade = true + }, function() + local playerPed = PlayerPedId() + SetPedAoBlobRendering(playerPed, false) + SetEntityAlpha(playerPed, 0) + TriggerServerEvent('esx_multicharacter:CharacterChosen', 1, true) + TriggerEvent('esx_identity:showRegisterIdentity') + end) + else + for i=1, #Characters+1 do + local label = 'Create new character' + if Characters[i] then + if Spawned == false then SetupCharacter(i) end + label = Characters[i].firstname..' '..Characters[i].lastname + if Characters[i].sex == 'Female' then Characters[i].model = `mp_f_freemode_01` else Characters[i].model = `mp_m_freemode_01` end + elements[#elements+1] = {label = label, value = Characters[i].id, new = false} + else elements[#elements+1] = {label = label, new = true} end + end + + ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'selectchar', { + title = 'Select character', + align = 'top-left', + elements = elements + }, function(data, menu) + local elements = { } + if not data.current.new then + elements[1] = {label = 'Play this character', action = 'play', value = data.current.value} + elements[2] = {label = 'Delete this character', action = 'delete', value = data.current.value} + ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'choosechar', { + title = 'Select character', + align = 'top-left', + elements = elements + }, function(data, menu) + if data.current.action == 'play' then + ESX.UI.Menu.CloseAll() + DoScreenFadeOut(300) + --[[SendNUIMessage({ + action = "closeui" + })]] + TriggerServerEvent('esx_multicharacter:CharacterChosen', data.current.value, false) + Citizen.Wait(300) + else + local elements2 = {} + elements2[1] = {label = 'Return'} + elements2[2] = {label = 'Confirm', value = data.current.value} + ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'deletechar', { + title = 'Delete '..Characters[data.current.value].firstname..' '..Characters[data.current.value].lastname..'?', + align = 'center', + elements = elements2 + }, function(data, menu) + if data.current.value then + TriggerServerEvent('esx_multicharacter:DeleteCharacter', data.current.value) + table.remove(Characters, data.current.value) + ESX.UI.Menu.CloseAll() + TriggerServerEvent('esx_multicharacter:SetupCharacters') + Citizen.Wait(100) + else + menu.close() + end + end, function(data, menu) + menu.close() + end) + end + end, function(data, menu) + menu.close() + end) + else + ESX.UI.Menu.CloseAll() + local GetSlot = function() + for i=1, #Characters+1 do + if not Characters[i] then + return i + end + end + end + local slot = GetSlot() + TriggerServerEvent('esx_multicharacter:CharacterChosen', slot, true) + TriggerEvent('esx_identity:showRegisterIdentity') + end + end, function(data, menu) + menu.refresh() + end, function(data, menu) + if data.current.new then + local playerPed = PlayerPedId() + SetPedAoBlobRendering(playerPed, false) + SetEntityAlpha(playerPed, 0) + --[[SendNUIMessage({ + action = "closeui" + })]] + else + SetupCharacter(data.current.value) + local playerPed = PlayerPedId() + SetPedAoBlobRendering(playerPed, true) + SetEntityAlpha(playerPed, 255) + end + end) + end end) RegisterNetEvent('esx_multicharacter:SpawnCharacter') AddEventHandler('esx_multicharacter:SpawnCharacter', function(spawn, isNew, skin) - local pos = spawn + DoScreenFadeOut(0) + Citizen.Wait(300) + local playerPed = PlayerPedId() + cam2 = CreateCamWithParams("DEFAULT_SCRIPTED_CAMERA", spawn.x,spawn.y,spawn.z+200, 0.0, 0.0, 0.0, 100.00, false, 0) + PointCamAtCoord(cam2, spawn.x,spawn.y,spawn.z+10) + SetCamActiveWithInterp(cam2, cam, 400, true, true) - SetTimecycleModifier('default') + Citizen.Wait(700) + DoScreenFadeIn(500) + FreezeEntityPosition(playerPed, true) + SetEntityVisible(playerPed, true, 0) + SetEntityCoords(playerPed, spawn.x, spawn.y, spawn.z, true, false, false, false) - exports.spawnmanager:spawnPlayer({ - x = spawn.x, - y = spawn.y, - z = spawn.z + 0.25, - heading = spawn.heading, - model = `mp_m_freemode_01`, - skipFade = true - }, function() - DoScreenFadeIn(500) - Citizen.Wait(500) - NetworkConcealPlayer(PlayerId(), 0, 0) + cam = CreateCamWithParams("DEFAULT_SCRIPTED_CAMERA", spawn.x,spawn.y,spawn.z+10, GetEntityRotation(playerPed), 100.00, false, 0) + PointCamAtCoord(cam, spawn.x,spawn.y,spawn.z+2) + SetCamActiveWithInterp(cam, cam2, 2700, true, true) - cam2 = CreateCamWithParams("DEFAULT_SCRIPTED_CAMERA", -1355.93,-1487.78,520.75, 300.00,0.00,0.00, 100.00, false, 0) - PointCamAtCoord(cam2, pos.x,pos.y,pos.z+200) - SetCamActiveWithInterp(cam2, cam, 900, true, true) - - Citizen.Wait(900) - - cam = CreateCamWithParams("DEFAULT_SCRIPTED_CAMERA", pos.x,pos.y,pos.z+200, 300.00,0.00,0.00, 100.00, false, 0) - PointCamAtCoord(cam, pos.x,pos.y,pos.z+2) - SetCamActiveWithInterp(cam, cam2, 3700, true, true) - - Citizen.Wait(3700) - - PlaySoundFrontend(-1, "Zoom_Out", "DLC_HEIST_PLANNING_BOARD_SOUNDS", 1) - RenderScriptCams(false, true, 500, true, true) - PlaySoundFrontend(-1, "CAR_BIKE_WHOOSH", "MP_LOBBY_SOUNDS", 1) - if isNew then - if skin.sex == 0 then - TriggerEvent('skinchanger:loadDefaultModel', true) - else - TriggerEvent('skinchanger:loadDefaultModel', false) - end - elseif skin then TriggerEvent('skinchanger:loadSkin', skin) end - - Citizen.Wait(500) - - FreezeEntityPosition(PlayerPedId(), false) - TriggerServerEvent('esx:onPlayerSpawn') - TriggerEvent('esx:onPlayerSpawn') - TriggerEvent('playerSpawned') -- compatibility with old scripts, will be removed soon. - - SetCamActive(cam, false) - DestroyCam(cam, true) - - DisplayHud(true) - DisplayRadar(true) - end) - end) - - RegisterNetEvent('esx_multicharacter:ReloadCharacters') - AddEventHandler('esx_multicharacter:ReloadCharacters', function() - TriggerServerEvent("esx_multicharacter:SetupCharacters") - TriggerEvent("esx_multicharacter:SetupCharacters") - end) - - RegisterNUICallback("CharacterChosen", function(data, cb) - SetNuiFocus(false,false) - DoScreenFadeOut(500) - TriggerServerEvent('esx_multicharacter:CharacterChosen', data.charid, data.ischar) - if not data.ischar then TriggerEvent('esx_identity:showRegisterIdentity') end - while not IsScreenFadedOut() do - Citizen.Wait(10) - end - cb("ok") - end) - - RegisterNUICallback("DeleteCharacter", function(data, cb) - SetNuiFocus(false,false) - DoScreenFadeOut(500) - TriggerServerEvent('esx_multicharacter:DeleteCharacter', data.charid) - while not IsScreenFadedOut() do - Citizen.Wait(10) - end - cb("ok") + PlaySoundFrontend(-1, "Zoom_Out", "DLC_HEIST_PLANNING_BOARD_SOUNDS", 1) + Citizen.Wait(1000) + LoadPed(isNew, skin) + playerPed = PlayerPedId() + TriggerServerEvent('esx:onPlayerSpawn') + TriggerEvent('esx:onPlayerSpawn') + TriggerEvent('playerSpawned') + RenderScriptCams(false, true, 500, true, true) + PlaySoundFrontend(-1, "CAR_BIKE_WHOOSH", "MP_LOBBY_SOUNDS", 1) + SetCamActive(cam, false) + DestroyCam(cam, true) + DisplayHud(true) + DisplayRadar(true) + FreezeEntityPosition(playerPed, false) + SetPlayerControl(PlayerId(), true, false) + SetEntityHeading(playerPed, spawn.heading) + hidePlayers = false end) RegisterNetEvent('esx:onPlayerLogout') AddEventHandler('esx:onPlayerLogout', function() DoScreenFadeOut(0) + Spawned = false TriggerServerEvent("esx_multicharacter:SetupCharacters") TriggerEvent("esx_multicharacter:SetupCharacters") TriggerEvent('esx_skin:resetFirstSpawn')