From 742d7a8d5075ebdc453beb7a85d7b23a597914e6 Mon Sep 17 00:00:00 2001 From: Jannify <23176718+Jannify@users.noreply.github.com> Date: Sun, 7 Jan 2024 21:21:10 +0100 Subject: [PATCH] Fix getting stuck in cinematic bugs Also skip intro by default for creative --- .../GameLogic/PlayerLogic/PlayerCinematics.cs | 18 +++++++++++++++--- .../EscapePodWorldEntitySpawner.cs | 19 +++++++++---------- .../MultiplayerCinematicReference.cs | 14 +++++++++++++- .../GameLogic/IntroCinematicMode.cs | 1 + .../uGUI_SceneIntro_IntroSequence_Patch.cs | 2 ++ .../SetIntroCinematicModeProcessor.cs | 5 +++-- 6 files changed, 43 insertions(+), 16 deletions(-) diff --git a/NitroxClient/GameLogic/PlayerLogic/PlayerCinematics.cs b/NitroxClient/GameLogic/PlayerLogic/PlayerCinematics.cs index e5f3467b38..22e4c426db 100644 --- a/NitroxClient/GameLogic/PlayerLogic/PlayerCinematics.cs +++ b/NitroxClient/GameLogic/PlayerLogic/PlayerCinematics.cs @@ -1,4 +1,5 @@ -using NitroxClient.Communication.Abstract; +using System.Collections.Generic; +using NitroxClient.Communication.Abstract; using NitroxModel.DataStructures; using NitroxModel.DataStructures.GameLogic; using NitroxModel.Packets; @@ -10,6 +11,11 @@ public class PlayerCinematics private readonly IPacketSender packetSender; private readonly LocalPlayer localPlayer; + /// + /// Some cinematics should not be played. Example the intro as it's completely handled by a dedicated system. + /// + private readonly HashSet blacklistedKeys = ["escapepod_intro"]; + public PlayerCinematics(IPacketSender packetSender, LocalPlayer localPlayer) { this.packetSender = packetSender; @@ -18,12 +24,18 @@ public PlayerCinematics(IPacketSender packetSender, LocalPlayer localPlayer) public void StartCinematicMode(ushort playerId, NitroxId controllerID, int controllerNameHash, string key) { - packetSender.Send(new PlayerCinematicControllerCall(playerId, controllerID, controllerNameHash, key, true)); + if (!blacklistedKeys.Contains(key)) + { + packetSender.Send(new PlayerCinematicControllerCall(playerId, controllerID, controllerNameHash, key, true)); + } } public void EndCinematicMode(ushort playerId, NitroxId controllerID, int controllerNameHash, string key) { - packetSender.Send(new PlayerCinematicControllerCall(playerId, controllerID, controllerNameHash, key, false)); + if (!blacklistedKeys.Contains(key)) + { + packetSender.Send(new PlayerCinematicControllerCall(playerId, controllerID, controllerNameHash, key, false)); + } } public void SetLocalIntroCinematicMode(IntroCinematicMode introCinematicMode) diff --git a/NitroxClient/GameLogic/Spawning/WorldEntities/EscapePodWorldEntitySpawner.cs b/NitroxClient/GameLogic/Spawning/WorldEntities/EscapePodWorldEntitySpawner.cs index 1d2086f1b0..dd4f711a95 100644 --- a/NitroxClient/GameLogic/Spawning/WorldEntities/EscapePodWorldEntitySpawner.cs +++ b/NitroxClient/GameLogic/Spawning/WorldEntities/EscapePodWorldEntitySpawner.cs @@ -48,7 +48,7 @@ private GameObject CreateNewEscapePod(EscapePodWorldEntity escapePodEntity) // TODO: When we want to implement multiple escape pods, instantiate the prefab. Backlog task: #1945 // This will require some work as instantiating the prefab as-is will not make it visible. //GameObject escapePod = Object.Instantiate(EscapePod.main.gameObject); - + GameObject escapePod = EscapePod.main.gameObject; UnityEngine.Component.DestroyImmediate(escapePod.GetComponent()); // if template has a pre-existing NitroxEntity, remove. NitroxEntity.SetNewId(escapePod, escapePodEntity.Id); @@ -69,13 +69,6 @@ private GameObject CreateNewEscapePod(EscapePodWorldEntity escapePodEntity) FixStartMethods(escapePod); - // Start() isn't executed for the EscapePod, why? Idk, maybe because it's a scene... - MultiplayerCinematicReference reference = escapePod.AddComponent(); - foreach (PlayerCinematicController controller in escapePod.GetComponentsInChildren()) - { - reference.AddController(controller); - } - return escapePod; } @@ -84,15 +77,21 @@ private GameObject CreateNewEscapePod(EscapePodWorldEntity escapePodEntity) /// private static void FixStartMethods(GameObject escapePod) { - foreach (FMOD_CustomEmitter customEmitter in escapePod.GetComponentsInChildren()) + foreach (FMOD_CustomEmitter customEmitter in escapePod.GetComponentsInChildren(true)) { customEmitter.Start(); } - foreach (FMOD_StudioEventEmitter studioEventEmitter in escapePod.GetComponentsInChildren()) + foreach (FMOD_StudioEventEmitter studioEventEmitter in escapePod.GetComponentsInChildren(true)) { studioEventEmitter.Start(); } + + MultiplayerCinematicReference reference = escapePod.AddComponent(); + foreach (PlayerCinematicController controller in escapePod.GetComponentsInChildren(true)) + { + reference.AddController(controller); + } } public bool SpawnsOwnChildren() diff --git a/NitroxClient/MonoBehaviours/CinematicController/MultiplayerCinematicReference.cs b/NitroxClient/MonoBehaviours/CinematicController/MultiplayerCinematicReference.cs index 4ab0a1bcbb..19358f8471 100644 --- a/NitroxClient/MonoBehaviours/CinematicController/MultiplayerCinematicReference.cs +++ b/NitroxClient/MonoBehaviours/CinematicController/MultiplayerCinematicReference.cs @@ -2,6 +2,7 @@ using System.Linq; using NitroxClient.GameLogic; using NitroxClient.Unity.Helper; +using NitroxModel.DataStructures.GameLogic; using UnityEngine; namespace NitroxClient.MonoBehaviours.CinematicController; @@ -10,8 +11,18 @@ public class MultiplayerCinematicReference : MonoBehaviour { private readonly Dictionary> controllerByKey = new(); + private bool isEscapePod; + + private void Start() + { + // TODO: Currently only single EscapePod is supported, therefor EscapePod.main. Can probably be removed after we use one pod per intro sequence + isEscapePod = gameObject == EscapePod.main.gameObject; + } + public void CallStartCinematicMode(string key, int identifier, RemotePlayer player) { + if(isEscapePod && this.Resolve().IntroCinematicMode is IntroCinematicMode.PLAYING or IntroCinematicMode.SINGLEPLAYER) return; + if (!controllerByKey.TryGetValue(key, out Dictionary controllers)) { throw new KeyNotFoundException($"There was no entry for the key {key} at {gameObject.GetFullHierarchyPath()}"); @@ -27,6 +38,8 @@ public void CallStartCinematicMode(string key, int identifier, RemotePlayer play public void CallCinematicModeEnd(string key, int identifier, RemotePlayer player) { + if(isEscapePod && this.Resolve().IntroCinematicMode is IntroCinematicMode.PLAYING or IntroCinematicMode.SINGLEPLAYER) return; + if (!controllerByKey.TryGetValue(key, out Dictionary controllers)) { throw new KeyNotFoundException($"There was no entry for the key {key} at {gameObject.GetFullHierarchyPath()}"); @@ -44,7 +57,6 @@ public void CallCinematicModeEnd(string key, int identifier, RemotePlayer player public void AddController(PlayerCinematicController playerController) { - MultiplayerCinematicController[] allControllers = controllerByKey.SelectMany(n => n.Value.Select(x => x.Value)).ToArray(); if (!controllerByKey.TryGetValue(playerController.playerViewAnimationName, out Dictionary controllers)) diff --git a/NitroxModel/DataStructures/GameLogic/IntroCinematicMode.cs b/NitroxModel/DataStructures/GameLogic/IntroCinematicMode.cs index fc53e07bc8..c4b1dcdfc9 100644 --- a/NitroxModel/DataStructures/GameLogic/IntroCinematicMode.cs +++ b/NitroxModel/DataStructures/GameLogic/IntroCinematicMode.cs @@ -6,6 +6,7 @@ public enum IntroCinematicMode : byte LOADING, WAITING, START, + PLAYING, SINGLEPLAYER, COMPLETED } diff --git a/NitroxPatcher/Patches/Dynamic/uGUI_SceneIntro_IntroSequence_Patch.cs b/NitroxPatcher/Patches/Dynamic/uGUI_SceneIntro_IntroSequence_Patch.cs index c70947a474..5053c8a9ec 100644 --- a/NitroxPatcher/Patches/Dynamic/uGUI_SceneIntro_IntroSequence_Patch.cs +++ b/NitroxPatcher/Patches/Dynamic/uGUI_SceneIntro_IntroSequence_Patch.cs @@ -93,6 +93,7 @@ private static float GetSkipTime() private static bool IsRemoteCinematicReady(uGUI_SceneIntro uGuiSceneIntro) { if (callbackRun) return true; + if (GameModeUtils.currentGameMode.HasFlag(GameModeOption.Creative)) uGuiSceneIntro.Stop(true); // Stopping intro if Creative like in normal SN if (Resolve().IntroCinematicMode == IntroCinematicMode.COMPLETED) { @@ -120,6 +121,7 @@ private static bool IsRemoteCinematicReady(uGUI_SceneIntro uGuiSceneIntro) { partner = firstWaitingRemotePlayer; EnqueueStartCinematic(uGuiSceneIntro); + Resolve().SetLocalIntroCinematicMode(IntroCinematicMode.PLAYING); } return false; diff --git a/NitroxServer/Communication/Packets/Processors/SetIntroCinematicModeProcessor.cs b/NitroxServer/Communication/Packets/Processors/SetIntroCinematicModeProcessor.cs index e0576dc814..0c8631822f 100644 --- a/NitroxServer/Communication/Packets/Processors/SetIntroCinematicModeProcessor.cs +++ b/NitroxServer/Communication/Packets/Processors/SetIntroCinematicModeProcessor.cs @@ -14,6 +14,7 @@ public SetIntroCinematicModeProcessor(PlayerManager playerManager) { this.playerManager = playerManager; } + public override void Process(SetIntroCinematicMode packet, Player player) { if (packet.PlayerId != player.Id) @@ -31,8 +32,8 @@ public override void Process(SetIntroCinematicMode packet, Player player) Log.Info($"Starting IntroCinematic for {allWaitingPlayers[0].PlayerContext.PlayerName} and {allWaitingPlayers[1].PlayerContext.PlayerName}"); allWaitingPlayers[0].PlayerContext.IntroCinematicMode = allWaitingPlayers[1].PlayerContext.IntroCinematicMode = IntroCinematicMode.START; - allWaitingPlayers[0].SendPacket(new SetIntroCinematicMode(allWaitingPlayers[1].Id, IntroCinematicMode.START)); - allWaitingPlayers[1].SendPacket(new SetIntroCinematicMode(allWaitingPlayers[0].Id, IntroCinematicMode.START)); + playerManager.SendPacketToAllPlayers(new SetIntroCinematicMode(allWaitingPlayers[0].Id, IntroCinematicMode.START)); + playerManager.SendPacketToAllPlayers(new SetIntroCinematicMode(allWaitingPlayers[1].Id, IntroCinematicMode.START)); } } }