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
This commit is contained in:
Linden
2021-05-20 22:50:02 +10:00
committed by GitHub
parent 5bf41ac579
commit f81ed024cf
+212 -100
View File
@@ -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')