From 93c427b5e64f37aaaa23883ff8c3f6616ebe2d35 Mon Sep 17 00:00:00 2001 From: josshmot Date: Fri, 4 Apr 2025 15:16:18 +1000 Subject: [PATCH 01/24] Added function for custom credits music and duration --- .../Builder/Volumes/CreditsVolumeBuilder.cs | 4 +- .../Builder/Volumes/VolumesBuildManager.cs | 2 +- NewHorizons/Components/NHGameOverManager.cs | 40 ++++++++++++++++--- .../Components/Volumes/LoadCreditsVolume.cs | 4 +- .../External/Modules/GameOverModule.cs | 35 ++++++++++++++++ .../SerializableEnums/NHCreditsType.cs | 4 +- NewHorizons/NewHorizons.csproj.user | 2 +- 7 files changed, 81 insertions(+), 10 deletions(-) diff --git a/NewHorizons/Builder/Volumes/CreditsVolumeBuilder.cs b/NewHorizons/Builder/Volumes/CreditsVolumeBuilder.cs index 81c3c6ce..4f1c0ecb 100644 --- a/NewHorizons/Builder/Volumes/CreditsVolumeBuilder.cs +++ b/NewHorizons/Builder/Volumes/CreditsVolumeBuilder.cs @@ -1,5 +1,6 @@ using NewHorizons.Components.Volumes; using NewHorizons.External.Modules.Volumes.VolumeInfos; +using OWML.Common; using OWML.Utils; using UnityEngine; @@ -7,12 +8,13 @@ namespace NewHorizons.Builder.Volumes { internal static class CreditsVolumeBuilder { - public static LoadCreditsVolume Make(GameObject planetGO, Sector sector, LoadCreditsVolumeInfo info) + public static LoadCreditsVolume Make(GameObject planetGO, Sector sector, LoadCreditsVolumeInfo info, IModBehaviour mod) { var volume = VolumeBuilder.Make(planetGO, sector, info); volume.gameOver = info.gameOver; volume.deathType = info.deathType == null ? null : EnumUtils.Parse(info.deathType.ToString(), DeathType.Default); + volume.mod = mod; return volume; } diff --git a/NewHorizons/Builder/Volumes/VolumesBuildManager.cs b/NewHorizons/Builder/Volumes/VolumesBuildManager.cs index bdaa4a5a..128717f6 100644 --- a/NewHorizons/Builder/Volumes/VolumesBuildManager.cs +++ b/NewHorizons/Builder/Volumes/VolumesBuildManager.cs @@ -209,7 +209,7 @@ namespace NewHorizons.Builder.Volumes { foreach (var creditsVolume in config.Volumes.creditsVolume) { - CreditsVolumeBuilder.Make(go, sector, creditsVolume); + CreditsVolumeBuilder.Make(go, sector, creditsVolume, mod); } } } diff --git a/NewHorizons/Components/NHGameOverManager.cs b/NewHorizons/Components/NHGameOverManager.cs index 93a7339a..354b8319 100644 --- a/NewHorizons/Components/NHGameOverManager.cs +++ b/NewHorizons/Components/NHGameOverManager.cs @@ -1,7 +1,9 @@ using NewHorizons.External.Modules; using NewHorizons.External.SerializableEnums; using NewHorizons.Handlers; +using NewHorizons.Utility.Files; using NewHorizons.Utility.OWML; +using OWML.Common; using System.Collections; using System.Collections.Generic; using System.Linq; @@ -48,13 +50,13 @@ namespace NewHorizons.Components } } - public void StartGameOverSequence(GameOverModule gameOver, DeathType? deathType) + public void StartGameOverSequence(GameOverModule gameOver, DeathType? deathType, IModBehaviour mod = null) { _gameOverSequenceStarted = true; - Delay.StartCoroutine(GameOver(gameOver, deathType)); + Delay.StartCoroutine(GameOver(gameOver, deathType, mod)); } - private IEnumerator GameOver(GameOverModule gameOver, DeathType? deathType) + private IEnumerator GameOver(GameOverModule gameOver, DeathType? deathType, IModBehaviour mod) { OWInput.ChangeInputMode(InputMode.None); ReticleController.Hide(); @@ -104,15 +106,17 @@ namespace NewHorizons.Components yield return new WaitUntil(ReadytoLoadCreditsScene); } - LoadCreditsScene(gameOver); + LoadCreditsScene(gameOver, mod); } private bool ReadytoLoadCreditsScene() => _gameOverController._fadedOutText && _gameOverController._textAnimator.IsComplete(); - private void LoadCreditsScene(GameOverModule gameOver) + private void LoadCreditsScene(GameOverModule gameOver, IModBehaviour mod) { NHLogger.LogVerbose($"Load credits {gameOver.creditsType}"); + + switch (gameOver.creditsType) { case NHCreditsType.Fast: @@ -124,6 +128,32 @@ namespace NewHorizons.Components case NHCreditsType.Kazoo: TimelineObliterationController.s_hasRealityEnded = true; LoadManager.LoadScene(OWScene.Credits_Fast, LoadManager.FadeType.ToBlack); + break; + case NHCreditsType.Custom: + // We can't load in custom music if an IModBehaviour cannot be provided. This should only happen if called via TryHijackDeathSequence(). + if (mod is null) + NHLogger.LogWarning("Credits called using TryHijackDeathSequence(), custom credits audio cannot not be loaded."); + + LoadManager.LoadScene(OWScene.Credits_Fast, LoadManager.FadeType.ToBlack); + + // Patch new music + var musicSource = Locator.FindObjectsOfType().Where(x => x.name == "AudioSource").Single(); + musicSource.Stop(); + if (mod is not null) + { + AudioUtilities.SetAudioClip(musicSource, gameOver.audio, mod); + } + musicSource.SetMaxVolume(gameOver.audioVolume); + musicSource.loop = gameOver.audioLooping; + + // Patch scroll duration + var creditsScroll = Locator.FindObjectOfType(); + creditsScroll._scrollDuration = gameOver.scrollDuration; + + // Restart credits scroll + creditsScroll.Start(); + musicSource.FadeIn(gameOver.audioFadeInLength); + break; default: // GameOverController disables post processing diff --git a/NewHorizons/Components/Volumes/LoadCreditsVolume.cs b/NewHorizons/Components/Volumes/LoadCreditsVolume.cs index 26f75831..4f2dbfeb 100644 --- a/NewHorizons/Components/Volumes/LoadCreditsVolume.cs +++ b/NewHorizons/Components/Volumes/LoadCreditsVolume.cs @@ -1,4 +1,5 @@ using NewHorizons.External.Modules; +using OWML.Common; using UnityEngine; @@ -8,12 +9,13 @@ namespace NewHorizons.Components.Volumes { public GameOverModule gameOver; public DeathType? deathType; + public IModBehaviour mod; public override void OnTriggerVolumeEntry(GameObject hitObj) { if (hitObj.CompareTag("PlayerDetector") && enabled && (string.IsNullOrEmpty(gameOver.condition) || DialogueConditionManager.SharedInstance.GetConditionState(gameOver.condition))) { - NHGameOverManager.Instance.StartGameOverSequence(gameOver, deathType); + NHGameOverManager.Instance.StartGameOverSequence(gameOver, deathType, mod); } } diff --git a/NewHorizons/External/Modules/GameOverModule.cs b/NewHorizons/External/Modules/GameOverModule.cs index 00d029bd..dee5f302 100644 --- a/NewHorizons/External/Modules/GameOverModule.cs +++ b/NewHorizons/External/Modules/GameOverModule.cs @@ -2,6 +2,7 @@ using NewHorizons.External.SerializableData; using NewHorizons.External.SerializableEnums; using Newtonsoft.Json; using System.ComponentModel; +using System.ComponentModel.DataAnnotations; namespace NewHorizons.External.Modules { @@ -24,6 +25,40 @@ namespace NewHorizons.External.Modules /// public string condition; + /// + /// Path to the audio file to use as custom music for the credits. + /// Note: only applies when creditsType is set to "custom". + /// + public string audio; + + /// + /// The length of the fade in and out for the credits music. + /// Note: only applies when creditsType is set to "custom". + /// + [DefaultValue(1f)] + public float audioVolume; + + /// + /// Determines if the credits music should loop. + /// Note: only applies when creditsType is set to "custom". + /// + [DefaultValue(false)] + public bool audioLooping; + + /// + /// The length of the fade in for the credits music. + /// Note: only applies when creditsType is set to "custom". + /// + [DefaultValue(0f)] + public float audioFadeInLength; + + /// + /// Duration of the credits scroll in seconds. + /// Note: only applies when creditsType is set to "custom". + /// + [DefaultValue(120f)] + public float scrollDuration; + /// /// The type of credits that will run after the game over message is shown /// diff --git a/NewHorizons/External/SerializableEnums/NHCreditsType.cs b/NewHorizons/External/SerializableEnums/NHCreditsType.cs index 83c1dc51..f4d0f6c4 100644 --- a/NewHorizons/External/SerializableEnums/NHCreditsType.cs +++ b/NewHorizons/External/SerializableEnums/NHCreditsType.cs @@ -13,6 +13,8 @@ namespace NewHorizons.External.SerializableEnums [EnumMember(Value = @"kazoo")] Kazoo = 2, - [EnumMember(Value = @"none")] None = 3 + [EnumMember(Value = @"custom")] Custom = 3, + + [EnumMember(Value = @"none")] None = 4 } } diff --git a/NewHorizons/NewHorizons.csproj.user b/NewHorizons/NewHorizons.csproj.user index 5e39a9dd..44729020 100644 --- a/NewHorizons/NewHorizons.csproj.user +++ b/NewHorizons/NewHorizons.csproj.user @@ -1,4 +1,4 @@ - + $(AppData)\OuterWildsModManager\OWML\Mods\xen.NewHorizons From 803d2d6e2dccb89a063875043ef8a6a9888a3c7e Mon Sep 17 00:00:00 2001 From: josshmot Date: Fri, 4 Apr 2025 16:49:39 +1000 Subject: [PATCH 02/24] Fixed it so it actually works --- NewHorizons/Components/NHGameOverManager.cs | 71 +++++++++++++------ .../External/Modules/GameOverModule.cs | 4 +- 2 files changed, 51 insertions(+), 24 deletions(-) diff --git a/NewHorizons/Components/NHGameOverManager.cs b/NewHorizons/Components/NHGameOverManager.cs index 354b8319..2a8496ee 100644 --- a/NewHorizons/Components/NHGameOverManager.cs +++ b/NewHorizons/Components/NHGameOverManager.cs @@ -7,6 +7,7 @@ using OWML.Common; using System.Collections; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using UnityEngine; namespace NewHorizons.Components @@ -115,8 +116,6 @@ namespace NewHorizons.Components { NHLogger.LogVerbose($"Load credits {gameOver.creditsType}"); - - switch (gameOver.creditsType) { case NHCreditsType.Fast: @@ -132,28 +131,10 @@ namespace NewHorizons.Components case NHCreditsType.Custom: // We can't load in custom music if an IModBehaviour cannot be provided. This should only happen if called via TryHijackDeathSequence(). if (mod is null) - NHLogger.LogWarning("Credits called using TryHijackDeathSequence(), custom credits audio cannot not be loaded."); - - LoadManager.LoadScene(OWScene.Credits_Fast, LoadManager.FadeType.ToBlack); - - // Patch new music - var musicSource = Locator.FindObjectsOfType().Where(x => x.name == "AudioSource").Single(); - musicSource.Stop(); - if (mod is not null) { - AudioUtilities.SetAudioClip(musicSource, gameOver.audio, mod); + NHLogger.LogWarning("Credits called using TryHijackDeathSequence(), custom credits audio cannot not be loaded."); } - musicSource.SetMaxVolume(gameOver.audioVolume); - musicSource.loop = gameOver.audioLooping; - - // Patch scroll duration - var creditsScroll = Locator.FindObjectOfType(); - creditsScroll._scrollDuration = gameOver.scrollDuration; - - // Restart credits scroll - creditsScroll.Start(); - musicSource.FadeIn(gameOver.audioFadeInLength); - + LoadCustomCreditsScene(gameOver, mod); break; default: // GameOverController disables post processing @@ -164,5 +145,51 @@ namespace NewHorizons.Components break; } } + + private void LoadCustomCreditsScene(GameOverModule gameOver, IModBehaviour mod) + { + var fromScene = LoadManager.GetCurrentScene(); + var toScene = OWScene.Credits_Fast; + + LoadManager.LoadScene(toScene, LoadManager.FadeType.ToBlack); + + // We need to do this so we can unsubscribe from within the lambda. + LoadManager.SceneLoadEvent completeCreditsLoad = null; + + completeCreditsLoad = (fromScene, toScene) => + { + // Patch new music + var musicSource = Locator.FindObjectsOfType().Where(x => x.name == "AudioSource").Single(); + musicSource.Stop(); + if (mod is not null) + { + AudioUtilities.SetAudioClip(musicSource, gameOver.audio, mod); + } + musicSource.SetMaxVolume(gameOver.audioVolume); + musicSource.loop = gameOver.audioLooping; + musicSource.FadeIn(gameOver.audioFadeInLength); + + // Janky wait until credits are built + Task.Run( () => + { + var startTime = Time.time; + while (Locator.FindObjectsOfType().Length == 0) { + if (Time.time > startTime + 0.1f) + { + NHLogger.LogError("Timeout while waiting for credits to be built. Scroll duration couldn't be changed."); + return; + } + } + + // Patch scroll duration + var creditsScroll = Locator.FindObjectOfType(); + creditsScroll._scrollDuration = gameOver.scrollDuration; + }); + + LoadManager.OnCompleteSceneLoad -= completeCreditsLoad; + }; + + LoadManager.OnCompleteSceneLoad += completeCreditsLoad; + } } } diff --git a/NewHorizons/External/Modules/GameOverModule.cs b/NewHorizons/External/Modules/GameOverModule.cs index dee5f302..eb0fd911 100644 --- a/NewHorizons/External/Modules/GameOverModule.cs +++ b/NewHorizons/External/Modules/GameOverModule.cs @@ -23,7 +23,7 @@ namespace NewHorizons.External.Modules /// Condition that must be true for this game over to trigger. If this is on a LoadCreditsVolume, leave empty to always trigger this game over. /// Note this is a regular dialogue condition, not a persistent condition. /// - public string condition; + public string condition; /// /// Path to the audio file to use as custom music for the credits. @@ -46,7 +46,7 @@ namespace NewHorizons.External.Modules public bool audioLooping; /// - /// The length of the fade in for the credits music. + /// Whether the credits music should fade in. /// Note: only applies when creditsType is set to "custom". /// [DefaultValue(0f)] From e94aced8346f427745bb24b867d00dbe662ef647 Mon Sep 17 00:00:00 2001 From: josshmot Date: Fri, 4 Apr 2025 20:19:17 +1000 Subject: [PATCH 03/24] Made it explicitly required to provide IModeBehaviour for StartGameOverSequence() --- NewHorizons/Components/NHGameOverManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NewHorizons/Components/NHGameOverManager.cs b/NewHorizons/Components/NHGameOverManager.cs index 2a8496ee..3fb7f560 100644 --- a/NewHorizons/Components/NHGameOverManager.cs +++ b/NewHorizons/Components/NHGameOverManager.cs @@ -47,11 +47,11 @@ namespace NewHorizons.Components var gameOver = _gameOvers.FirstOrDefault(x => !string.IsNullOrEmpty(x.condition) && DialogueConditionManager.SharedInstance.GetConditionState(x.condition)); if (!_gameOverSequenceStarted && gameOver != null && !Locator.GetDeathManager()._finishedDLC) { - StartGameOverSequence(gameOver, null); + StartGameOverSequence(gameOver, null, null); } } - public void StartGameOverSequence(GameOverModule gameOver, DeathType? deathType, IModBehaviour mod = null) + public void StartGameOverSequence(GameOverModule gameOver, DeathType? deathType, IModBehaviour mod) { _gameOverSequenceStarted = true; Delay.StartCoroutine(GameOver(gameOver, deathType, mod)); From 29f1c4ab8cee0a55b825152a6d0bdf3d25dd1915 Mon Sep 17 00:00:00 2001 From: josshmot Date: Fri, 4 Apr 2025 20:23:15 +1000 Subject: [PATCH 04/24] Moved an if statement to a more appropriate place --- NewHorizons/Components/NHGameOverManager.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/NewHorizons/Components/NHGameOverManager.cs b/NewHorizons/Components/NHGameOverManager.cs index 3fb7f560..467d3a66 100644 --- a/NewHorizons/Components/NHGameOverManager.cs +++ b/NewHorizons/Components/NHGameOverManager.cs @@ -129,11 +129,6 @@ namespace NewHorizons.Components LoadManager.LoadScene(OWScene.Credits_Fast, LoadManager.FadeType.ToBlack); break; case NHCreditsType.Custom: - // We can't load in custom music if an IModBehaviour cannot be provided. This should only happen if called via TryHijackDeathSequence(). - if (mod is null) - { - NHLogger.LogWarning("Credits called using TryHijackDeathSequence(), custom credits audio cannot not be loaded."); - } LoadCustomCreditsScene(gameOver, mod); break; default: @@ -165,6 +160,11 @@ namespace NewHorizons.Components { AudioUtilities.SetAudioClip(musicSource, gameOver.audio, mod); } + else + { + // We can't load in custom music if an IModBehaviour cannot be provided. This should only happen if called via TryHijackDeathSequence(). + NHLogger.LogWarning("Credits called using TryHijackDeathSequence(), custom credits audio cannot not be loaded."); + } musicSource.SetMaxVolume(gameOver.audioVolume); musicSource.loop = gameOver.audioLooping; musicSource.FadeIn(gameOver.audioFadeInLength); From 5cf7c18a511a05bbbf815c8fad0493f9737edb9f Mon Sep 17 00:00:00 2001 From: josshmot Date: Sat, 5 Apr 2025 10:47:54 +1000 Subject: [PATCH 05/24] Renamed a few things --- NewHorizons/Components/NHGameOverManager.cs | 2 +- NewHorizons/External/Modules/GameOverModule.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NewHorizons/Components/NHGameOverManager.cs b/NewHorizons/Components/NHGameOverManager.cs index 467d3a66..f1055799 100644 --- a/NewHorizons/Components/NHGameOverManager.cs +++ b/NewHorizons/Components/NHGameOverManager.cs @@ -183,7 +183,7 @@ namespace NewHorizons.Components // Patch scroll duration var creditsScroll = Locator.FindObjectOfType(); - creditsScroll._scrollDuration = gameOver.scrollDuration; + creditsScroll._scrollDuration = gameOver.length; }); LoadManager.OnCompleteSceneLoad -= completeCreditsLoad; diff --git a/NewHorizons/External/Modules/GameOverModule.cs b/NewHorizons/External/Modules/GameOverModule.cs index eb0fd911..2fae76ee 100644 --- a/NewHorizons/External/Modules/GameOverModule.cs +++ b/NewHorizons/External/Modules/GameOverModule.cs @@ -46,7 +46,7 @@ namespace NewHorizons.External.Modules public bool audioLooping; /// - /// Whether the credits music should fade in. + /// Length of the credits music fade in. /// Note: only applies when creditsType is set to "custom". /// [DefaultValue(0f)] @@ -57,7 +57,7 @@ namespace NewHorizons.External.Modules /// Note: only applies when creditsType is set to "custom". /// [DefaultValue(120f)] - public float scrollDuration; + public float length; /// /// The type of credits that will run after the game over message is shown From 8fcf7d303163b995433b76882fb3c574974c9d12 Mon Sep 17 00:00:00 2001 From: josshmot Date: Sat, 5 Apr 2025 12:18:08 +1000 Subject: [PATCH 06/24] Removed audio fade in feature that wasn't working --- NewHorizons/Components/NHGameOverManager.cs | 11 +++++------ NewHorizons/External/Modules/GameOverModule.cs | 7 ------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/NewHorizons/Components/NHGameOverManager.cs b/NewHorizons/Components/NHGameOverManager.cs index f1055799..6dd351ad 100644 --- a/NewHorizons/Components/NHGameOverManager.cs +++ b/NewHorizons/Components/NHGameOverManager.cs @@ -153,9 +153,8 @@ namespace NewHorizons.Components completeCreditsLoad = (fromScene, toScene) => { - // Patch new music + // Patch new music clip var musicSource = Locator.FindObjectsOfType().Where(x => x.name == "AudioSource").Single(); - musicSource.Stop(); if (mod is not null) { AudioUtilities.SetAudioClip(musicSource, gameOver.audio, mod); @@ -164,10 +163,10 @@ namespace NewHorizons.Components { // We can't load in custom music if an IModBehaviour cannot be provided. This should only happen if called via TryHijackDeathSequence(). NHLogger.LogWarning("Credits called using TryHijackDeathSequence(), custom credits audio cannot not be loaded."); + return; } - musicSource.SetMaxVolume(gameOver.audioVolume); musicSource.loop = gameOver.audioLooping; - musicSource.FadeIn(gameOver.audioFadeInLength); + musicSource._maxSourceVolume = gameOver.audioVolume; // Janky wait until credits are built Task.Run( () => @@ -176,11 +175,11 @@ namespace NewHorizons.Components while (Locator.FindObjectsOfType().Length == 0) { if (Time.time > startTime + 0.1f) { - NHLogger.LogError("Timeout while waiting for credits to be built. Scroll duration couldn't be changed."); + NHLogger.LogError("Timeout while waiting for credits to be built. Scroll duration won't be changed."); return; } } - + // Patch scroll duration var creditsScroll = Locator.FindObjectOfType(); creditsScroll._scrollDuration = gameOver.length; diff --git a/NewHorizons/External/Modules/GameOverModule.cs b/NewHorizons/External/Modules/GameOverModule.cs index 2fae76ee..4c10830e 100644 --- a/NewHorizons/External/Modules/GameOverModule.cs +++ b/NewHorizons/External/Modules/GameOverModule.cs @@ -45,13 +45,6 @@ namespace NewHorizons.External.Modules [DefaultValue(false)] public bool audioLooping; - /// - /// Length of the credits music fade in. - /// Note: only applies when creditsType is set to "custom". - /// - [DefaultValue(0f)] - public float audioFadeInLength; - /// /// Duration of the credits scroll in seconds. /// Note: only applies when creditsType is set to "custom". From 5e0d44d911c3e639737f08eca17f687744876e45 Mon Sep 17 00:00:00 2001 From: josshmot Date: Sat, 5 Apr 2025 13:07:30 +1000 Subject: [PATCH 07/24] Fixed credits music fade in still sometimes occuring --- NewHorizons/Components/NHGameOverManager.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NewHorizons/Components/NHGameOverManager.cs b/NewHorizons/Components/NHGameOverManager.cs index 6dd351ad..2dc57d36 100644 --- a/NewHorizons/Components/NHGameOverManager.cs +++ b/NewHorizons/Components/NHGameOverManager.cs @@ -180,6 +180,10 @@ namespace NewHorizons.Components } } + // Override fade in + musicSource.Stop(); + musicSource.Play(); + // Patch scroll duration var creditsScroll = Locator.FindObjectOfType(); creditsScroll._scrollDuration = gameOver.length; From 6d77b0b1d1e38fe70c9d0c50018075055bdc55d5 Mon Sep 17 00:00:00 2001 From: josshmot Date: Tue, 8 Apr 2025 16:50:31 +1000 Subject: [PATCH 08/24] Fixed incorrect log level in NHGameOverManager.LoadCustomCreditsScene() --- NewHorizons/Components/NHGameOverManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/Components/NHGameOverManager.cs b/NewHorizons/Components/NHGameOverManager.cs index 2dc57d36..3da1b8cf 100644 --- a/NewHorizons/Components/NHGameOverManager.cs +++ b/NewHorizons/Components/NHGameOverManager.cs @@ -162,7 +162,7 @@ namespace NewHorizons.Components else { // We can't load in custom music if an IModBehaviour cannot be provided. This should only happen if called via TryHijackDeathSequence(). - NHLogger.LogWarning("Credits called using TryHijackDeathSequence(), custom credits audio cannot not be loaded."); + NHLogger.Log("Credits called using TryHijackDeathSequence(), custom credits audio cannot not be loaded."); return; } musicSource.loop = gameOver.audioLooping; From 0e6555d9336b2bbebc32f64bcf188ea49fe3e4c3 Mon Sep 17 00:00:00 2001 From: josshmot Date: Tue, 8 Apr 2025 17:01:06 +1000 Subject: [PATCH 09/24] Neatened up NHGameOverManager.LoadCustomCreditsScene() and added some comments to explain things --- NewHorizons/Components/NHGameOverManager.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/NewHorizons/Components/NHGameOverManager.cs b/NewHorizons/Components/NHGameOverManager.cs index 3da1b8cf..25f3549e 100644 --- a/NewHorizons/Components/NHGameOverManager.cs +++ b/NewHorizons/Components/NHGameOverManager.cs @@ -148,13 +148,12 @@ namespace NewHorizons.Components LoadManager.LoadScene(toScene, LoadManager.FadeType.ToBlack); - // We need to do this so we can unsubscribe from within the lambda. - LoadManager.SceneLoadEvent completeCreditsLoad = null; - + // Unfortunately we can't make this a private method, as LoadManager.SceneLoadEvent enforces the (fromScene, toScene) parameters, which prevents us from passing in gameOver and mod, which we need. + LoadManager.SceneLoadEvent completeCreditsLoad = null; // needs to be done so we can unsubscribe from within the lambda. completeCreditsLoad = (fromScene, toScene) => { // Patch new music clip - var musicSource = Locator.FindObjectsOfType().Where(x => x.name == "AudioSource").Single(); + var musicSource = Locator.FindObjectsOfType().Where(x => x.name == "AudioSource").Single(); // AudioSource that plays the credits music is literally called "AudioSource", luckily it's the only one called that. Lazy OW devs do be lazy. if (mod is not null) { AudioUtilities.SetAudioClip(musicSource, gameOver.audio, mod); From 5d680277ecb7a989bf649611d5a473f6a072e2f2 Mon Sep 17 00:00:00 2001 From: josshmot Date: Tue, 8 Apr 2025 17:30:43 +1000 Subject: [PATCH 10/24] Patched in event for CreditsBuilt and refactored NHGameOverManager.LoadCustomCreditsScene() to implement it and remove the janky task --- NewHorizons/Components/NHGameOverManager.cs | 43 +++++++------------ .../CreditsScenePatches/CreditsPatches.cs | 13 ++++++ 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/NewHorizons/Components/NHGameOverManager.cs b/NewHorizons/Components/NHGameOverManager.cs index 25f3549e..087205f6 100644 --- a/NewHorizons/Components/NHGameOverManager.cs +++ b/NewHorizons/Components/NHGameOverManager.cs @@ -1,9 +1,11 @@ using NewHorizons.External.Modules; using NewHorizons.External.SerializableEnums; using NewHorizons.Handlers; +using NewHorizons.Patches.CreditsScenePatches; using NewHorizons.Utility.Files; using NewHorizons.Utility.OWML; using OWML.Common; +using System; using System.Collections; using System.Collections.Generic; using System.Linq; @@ -143,15 +145,13 @@ namespace NewHorizons.Components private void LoadCustomCreditsScene(GameOverModule gameOver, IModBehaviour mod) { - var fromScene = LoadManager.GetCurrentScene(); - var toScene = OWScene.Credits_Fast; + LoadManager.LoadScene(OWScene.Credits_Fast, LoadManager.FadeType.ToBlack); - LoadManager.LoadScene(toScene, LoadManager.FadeType.ToBlack); - - // Unfortunately we can't make this a private method, as LoadManager.SceneLoadEvent enforces the (fromScene, toScene) parameters, which prevents us from passing in gameOver and mod, which we need. - LoadManager.SceneLoadEvent completeCreditsLoad = null; // needs to be done so we can unsubscribe from within the lambda. - completeCreditsLoad = (fromScene, toScene) => + // Unfortunately we can't make this a private method, as EventArgs/EventHandler enforces the (sender, e) parameters, which prevents us from passing in gameOver and mod, which we need. + EventHandler onCreditsBuilt = null; // needs to be done so we can unsubscribe from within the lambda. + onCreditsBuilt = (sender, e) => { + // Patch new music clip var musicSource = Locator.FindObjectsOfType().Where(x => x.name == "AudioSource").Single(); // AudioSource that plays the credits music is literally called "AudioSource", luckily it's the only one called that. Lazy OW devs do be lazy. if (mod is not null) @@ -167,31 +167,18 @@ namespace NewHorizons.Components musicSource.loop = gameOver.audioLooping; musicSource._maxSourceVolume = gameOver.audioVolume; - // Janky wait until credits are built - Task.Run( () => - { - var startTime = Time.time; - while (Locator.FindObjectsOfType().Length == 0) { - if (Time.time > startTime + 0.1f) - { - NHLogger.LogError("Timeout while waiting for credits to be built. Scroll duration won't be changed."); - return; - } - } + // Override fade in + musicSource.Stop(); + musicSource.Play(); - // Override fade in - musicSource.Stop(); - musicSource.Play(); + // Patch scroll duration + var creditsScroll = Locator.FindObjectOfType(); + creditsScroll._scrollDuration = gameOver.length; - // Patch scroll duration - var creditsScroll = Locator.FindObjectOfType(); - creditsScroll._scrollDuration = gameOver.length; - }); - - LoadManager.OnCompleteSceneLoad -= completeCreditsLoad; + CreditsPatches.CreditsBuilt -= onCreditsBuilt; }; - LoadManager.OnCompleteSceneLoad += completeCreditsLoad; + CreditsPatches.CreditsBuilt += onCreditsBuilt; } } } diff --git a/NewHorizons/Patches/CreditsScenePatches/CreditsPatches.cs b/NewHorizons/Patches/CreditsScenePatches/CreditsPatches.cs index 8892f334..037b30bf 100644 --- a/NewHorizons/Patches/CreditsScenePatches/CreditsPatches.cs +++ b/NewHorizons/Patches/CreditsScenePatches/CreditsPatches.cs @@ -1,17 +1,30 @@ using HarmonyLib; using NewHorizons.Handlers; +using System; namespace NewHorizons.Patches.CreditsScenePatches { [HarmonyPatch(typeof(Credits))] public static class CreditsPatches { + public static event EventHandler CreditsBuilt; // Used in NHGameOverManager to patch credits music and scroll speed + [HarmonyPrefix] [HarmonyPatch(nameof(Credits.Start))] public static void Credits_Start(Credits __instance) { CreditsHandler.AddCredits(__instance); } + + [HarmonyPostfix] + [HarmonyPatch(nameof(Credits.BuildCredits))] + public static void Credits_BuildCredits_Post(Credits __instance) + { + // Do things BuildCredits() normally does + + // Fire event once finished + CreditsBuilt?.Invoke(__instance, new EventArgs()); + } } } From ee776e384b4d5dcb263be13aa95d07c3b574b5d1 Mon Sep 17 00:00:00 2001 From: xen-42 Date: Tue, 8 Apr 2025 11:17:45 -0400 Subject: [PATCH 11/24] Rewrite to support hijackdeathsequence, but haven't tested --- NewHorizons/Components/NHGameOverManager.cs | 41 +++++++++++---------- NewHorizons/Main.cs | 2 +- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/NewHorizons/Components/NHGameOverManager.cs b/NewHorizons/Components/NHGameOverManager.cs index 087205f6..0fe3dc08 100644 --- a/NewHorizons/Components/NHGameOverManager.cs +++ b/NewHorizons/Components/NHGameOverManager.cs @@ -9,7 +9,6 @@ using System; using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using UnityEngine; namespace NewHorizons.Components @@ -20,14 +19,14 @@ namespace NewHorizons.Components /// Mod unique id to game over module list /// Done as a dictionary so that Reload Configs can overwrite entries per mod /// - public static Dictionary gameOvers = new(); + public static Dictionary gameOvers = new(); public static NHGameOverManager Instance { get; private set; } private GameOverController _gameOverController; private PlayerCameraEffectController _playerCameraEffectController; - private GameOverModule[] _gameOvers; + private (IModBehaviour mod, GameOverModule gameOver)[] _gameOvers; private bool _gameOverSequenceStarted; @@ -41,15 +40,25 @@ namespace NewHorizons.Components _gameOverController = FindObjectOfType(); _playerCameraEffectController = FindObjectOfType(); - _gameOvers = gameOvers.SelectMany(x => x.Value).ToArray(); + var gameOverList = new List<(IModBehaviour, GameOverModule)>(); + foreach (var gameOverPair in gameOvers) + { + var mod = gameOverPair.Key; + foreach (var gameOver in gameOverPair.Value) + { + gameOverList.Add((mod, gameOver)); + } + } + _gameOvers = gameOverList.ToArray(); } public void TryHijackDeathSequence() { - var gameOver = _gameOvers.FirstOrDefault(x => !string.IsNullOrEmpty(x.condition) && DialogueConditionManager.SharedInstance.GetConditionState(x.condition)); - if (!_gameOverSequenceStarted && gameOver != null && !Locator.GetDeathManager()._finishedDLC) + var gameOver = _gameOvers.FirstOrDefault(x => !string.IsNullOrEmpty(x.gameOver.condition) + && DialogueConditionManager.SharedInstance.GetConditionState(x.gameOver.condition)); + if (!_gameOverSequenceStarted && gameOver != default && !Locator.GetDeathManager()._finishedDLC) { - StartGameOverSequence(gameOver, null, null); + StartGameOverSequence(gameOver.gameOver, null, gameOver.mod); } } @@ -151,19 +160,13 @@ namespace NewHorizons.Components EventHandler onCreditsBuilt = null; // needs to be done so we can unsubscribe from within the lambda. onCreditsBuilt = (sender, e) => { - + // Unsubscribe first, playing it safe in case it NREs + CreditsPatches.CreditsBuilt -= onCreditsBuilt; + // Patch new music clip var musicSource = Locator.FindObjectsOfType().Where(x => x.name == "AudioSource").Single(); // AudioSource that plays the credits music is literally called "AudioSource", luckily it's the only one called that. Lazy OW devs do be lazy. - if (mod is not null) - { - AudioUtilities.SetAudioClip(musicSource, gameOver.audio, mod); - } - else - { - // We can't load in custom music if an IModBehaviour cannot be provided. This should only happen if called via TryHijackDeathSequence(). - NHLogger.Log("Credits called using TryHijackDeathSequence(), custom credits audio cannot not be loaded."); - return; - } + AudioUtilities.SetAudioClip(musicSource, gameOver.audio, mod); + musicSource.loop = gameOver.audioLooping; musicSource._maxSourceVolume = gameOver.audioVolume; @@ -174,8 +177,6 @@ namespace NewHorizons.Components // Patch scroll duration var creditsScroll = Locator.FindObjectOfType(); creditsScroll._scrollDuration = gameOver.length; - - CreditsPatches.CreditsBuilt -= onCreditsBuilt; }; CreditsPatches.CreditsBuilt += onCreditsBuilt; diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index f81400a9..113be63b 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -849,7 +849,7 @@ namespace NewHorizons } if (addonConfig.gameOver != null) { - NHGameOverManager.gameOvers[mod.ModHelper.Manifest.UniqueName] = addonConfig.gameOver; + NHGameOverManager.gameOvers[mod] = addonConfig.gameOver; } AddonConfigs[mod] = addonConfig; From e02dd94cad0366c917ea634ee522231e66b2f684 Mon Sep 17 00:00:00 2001 From: xen-42 Date: Tue, 8 Apr 2025 11:54:07 -0400 Subject: [PATCH 12/24] Fixed a bug where changing an existing AudioSource to use a specific AudioClip resource didn't work --- NewHorizons/External/Modules/GameOverModule.cs | 1 - NewHorizons/Utility/Files/AudioUtilities.cs | 17 ++++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/NewHorizons/External/Modules/GameOverModule.cs b/NewHorizons/External/Modules/GameOverModule.cs index 4c10830e..7bb884e1 100644 --- a/NewHorizons/External/Modules/GameOverModule.cs +++ b/NewHorizons/External/Modules/GameOverModule.cs @@ -2,7 +2,6 @@ using NewHorizons.External.SerializableData; using NewHorizons.External.SerializableEnums; using Newtonsoft.Json; using System.ComponentModel; -using System.ComponentModel.DataAnnotations; namespace NewHorizons.External.Modules { diff --git a/NewHorizons/Utility/Files/AudioUtilities.cs b/NewHorizons/Utility/Files/AudioUtilities.cs index fe09d46e..f3c2924d 100644 --- a/NewHorizons/Utility/Files/AudioUtilities.cs +++ b/NewHorizons/Utility/Files/AudioUtilities.cs @@ -27,23 +27,34 @@ namespace NewHorizons.Utility.Files source._clipArrayLength = 0; source._clipSelectionOnPlay = OWAudioSource.ClipSelectionOnPlay.MANUAL; source.clip = clip; + NHLogger.LogVerbose($"[{nameof(AudioUtilities)}] : Audio {audio} was loaded from a file"); return; } catch { - NHLogger.LogError($"Could not load file {audio}"); + NHLogger.LogError($"[{nameof(AudioUtilities)}] : Could not load file {audio}"); } } if (EnumUtils.TryParse(audio, out AudioType type)) { source._audioLibraryClip = type; + NHLogger.LogVerbose($"[{nameof(AudioUtilities)}] : Audio {audio} was an AudioType enum"); } else { var audioClip = SearchUtilities.FindResourceOfTypeAndName(audio); - if (audioClip == null) NHLogger.Log($"Couldn't find audio clip {audio}"); - else source.clip = audioClip; + if (audioClip == null) + { + NHLogger.LogError($"[{nameof(AudioUtilities)}] : Couldn't find audio clip {audio}"); + } + else + { + NHLogger.LogVerbose($"[{nameof(AudioUtilities)}] : Audio {audio} was an AudioClip resource"); + // Else if this is set it will try to change the clip back when it starts playing + source._audioLibraryClip = AudioType.None; + source.clip = audioClip; + } } } From 6767ab3548a820b64939adc9887fb00887040eef Mon Sep 17 00:00:00 2001 From: xen-42 Date: Tue, 8 Apr 2025 12:46:36 -0400 Subject: [PATCH 13/24] Destroy flood sensors on docks --- NewHorizons/Builder/Props/DetailBuilder.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/NewHorizons/Builder/Props/DetailBuilder.cs b/NewHorizons/Builder/Props/DetailBuilder.cs index 825af0c1..d7400937 100644 --- a/NewHorizons/Builder/Props/DetailBuilder.cs +++ b/NewHorizons/Builder/Props/DetailBuilder.cs @@ -473,10 +473,14 @@ namespace NewHorizons.Builder.Props { // These flood toggles are to disable flooded docks on the Stranger // Presumably the user isn't making one of those - foreach (var toggle in dock.GetComponents()) + foreach (var toggle in dock.GetComponents().Concat(dock.GetComponentsInChildren())) { Component.DestroyImmediate(toggle); } + foreach (var floodSensor in dock.GetComponents().Concat(dock.GetComponentsInChildren())) + { + Component.DestroyImmediate(floodSensor); + } } } From ca1bc3701446e99cd9fc1add7a80d61a97c0d017 Mon Sep 17 00:00:00 2001 From: xen-42 Date: Tue, 8 Apr 2025 13:00:50 -0400 Subject: [PATCH 14/24] Update manifest.json --- NewHorizons/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/manifest.json b/NewHorizons/manifest.json index eff475cf..3311a8fb 100644 --- a/NewHorizons/manifest.json +++ b/NewHorizons/manifest.json @@ -4,7 +4,7 @@ "author": "xen, Bwc9876, JohnCorby, MegaPiggy, and friends", "name": "New Horizons", "uniqueName": "xen.NewHorizons", - "version": "1.27.3", + "version": "1.27.4", "owmlVersion": "2.12.1", "dependencies": [ "JohnCorby.VanillaFix", "xen.CommonCameraUtility", "dgarro.CustomShipLogModes" ], "conflicts": [ "PacificEngine.OW_CommonResources" ], From 8f06cab729961bb6dd109fe647e10c76a1668873 Mon Sep 17 00:00:00 2001 From: xen-42 Date: Tue, 8 Apr 2025 13:02:43 -0400 Subject: [PATCH 15/24] Mention that audio clip and audio type also work --- NewHorizons/External/Modules/GameOverModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/External/Modules/GameOverModule.cs b/NewHorizons/External/Modules/GameOverModule.cs index 7bb884e1..33cf2269 100644 --- a/NewHorizons/External/Modules/GameOverModule.cs +++ b/NewHorizons/External/Modules/GameOverModule.cs @@ -25,7 +25,7 @@ namespace NewHorizons.External.Modules public string condition; /// - /// Path to the audio file to use as custom music for the credits. + /// Path to the audio file to use as custom music for the credits. Also supports AudioClips and AudioType like other audio settings. /// Note: only applies when creditsType is set to "custom". /// public string audio; From a6efef5ee392aee84f81ece1a9e71813acd6a20a Mon Sep 17 00:00:00 2001 From: xen-42 Date: Tue, 8 Apr 2025 13:03:55 -0400 Subject: [PATCH 16/24] Reword --- NewHorizons/External/Modules/GameOverModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NewHorizons/External/Modules/GameOverModule.cs b/NewHorizons/External/Modules/GameOverModule.cs index 33cf2269..a844a190 100644 --- a/NewHorizons/External/Modules/GameOverModule.cs +++ b/NewHorizons/External/Modules/GameOverModule.cs @@ -22,10 +22,10 @@ namespace NewHorizons.External.Modules /// Condition that must be true for this game over to trigger. If this is on a LoadCreditsVolume, leave empty to always trigger this game over. /// Note this is a regular dialogue condition, not a persistent condition. /// - public string condition; + public string condition; /// - /// Path to the audio file to use as custom music for the credits. Also supports AudioClips and AudioType like other audio settings. + /// The audio to use for the credits music. Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list. /// Note: only applies when creditsType is set to "custom". /// public string audio; From 2f53572d7582eac150c7617098ccd1cdf83bdeea Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Tue, 8 Apr 2025 16:37:43 -0400 Subject: [PATCH 17/24] change to dreamworld standing torch --- NewHorizons/Builder/Props/ProjectionBuilder.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index 2ebf64fc..38bedc5d 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -92,11 +92,14 @@ namespace NewHorizons.Builder.Props if (_standingVisionTorchPrefab == null) { - _standingVisionTorchPrefab = SearchUtilities.Find("RingWorld_Body/Sector_RingWorld/Sector_SecretEntrance/Interactibles_SecretEntrance/Experiment_1/VisionTorchApparatus/VisionTorchRoot/Prefab_IP_VisionTorchProjector")?.gameObject?.InstantiateInactive()?.Rename("Prefab_IP_VisionTorchProjector")?.DontDestroyOnLoad(); + _standingVisionTorchPrefab = SearchUtilities.Find("DreamWorld_Body/Sector_DreamWorld/Sector_DreamZone_4/Interactibles_DreamZone_4_Upper/Prefab_IP_VisionTorchProjector")?.gameObject?.InstantiateInactive()?.Rename("Prefab_IP_VisionTorchProjector")?.DontDestroyOnLoad(); if (_standingVisionTorchPrefab == null) NHLogger.LogWarning($"Tried to make standing vision torch prefab but couldn't. Do you have the DLC installed?"); else + { _standingVisionTorchPrefab.AddComponent()._destroyOnDLCNotOwned = true; + GameObject.DestroyImmediate(_standingVisionTorchPrefab.FindChild("Prefab_IP_Reel_PrisonPeephole_Vision")); + } } } From 0b65c852d2626c321e5394dcb804ca8ae477de09 Mon Sep 17 00:00:00 2001 From: josshmot Date: Thu, 10 Apr 2025 17:34:19 +1000 Subject: [PATCH 18/24] Fixed undefined behaviour when custom credits attributes aren't specified --- NewHorizons/Components/NHGameOverManager.cs | 9 ++++++++- NewHorizons/External/Modules/GameOverModule.cs | 13 +++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/NewHorizons/Components/NHGameOverManager.cs b/NewHorizons/Components/NHGameOverManager.cs index 0fe3dc08..acc3080d 100644 --- a/NewHorizons/Components/NHGameOverManager.cs +++ b/NewHorizons/Components/NHGameOverManager.cs @@ -165,7 +165,14 @@ namespace NewHorizons.Components // Patch new music clip var musicSource = Locator.FindObjectsOfType().Where(x => x.name == "AudioSource").Single(); // AudioSource that plays the credits music is literally called "AudioSource", luckily it's the only one called that. Lazy OW devs do be lazy. - AudioUtilities.SetAudioClip(musicSource, gameOver.audio, mod); + if (gameOver.audio != string.Empty) // string.Empty is default value for "audio" in GameOverModule, means no audio is specified. + { + AudioUtilities.SetAudioClip(musicSource, gameOver.audio, mod); // Load audio if specified + } + else + { + musicSource.AssignAudioLibraryClip(AudioType.PLACEHOLDER); // Otherwise default custom credits are silent + } musicSource.loop = gameOver.audioLooping; musicSource._maxSourceVolume = gameOver.audioVolume; diff --git a/NewHorizons/External/Modules/GameOverModule.cs b/NewHorizons/External/Modules/GameOverModule.cs index 7bb884e1..d9dba70b 100644 --- a/NewHorizons/External/Modules/GameOverModule.cs +++ b/NewHorizons/External/Modules/GameOverModule.cs @@ -22,34 +22,31 @@ namespace NewHorizons.External.Modules /// Condition that must be true for this game over to trigger. If this is on a LoadCreditsVolume, leave empty to always trigger this game over. /// Note this is a regular dialogue condition, not a persistent condition. /// - public string condition; + public string condition; /// /// Path to the audio file to use as custom music for the credits. /// Note: only applies when creditsType is set to "custom". /// - public string audio; + public string audio = string.Empty; // Explicitly declaring this for condition in NHGameOverManager /// /// The length of the fade in and out for the credits music. /// Note: only applies when creditsType is set to "custom". /// - [DefaultValue(1f)] - public float audioVolume; + [DefaultValue(1f)] public float audioVolume = 1f; /// /// Determines if the credits music should loop. /// Note: only applies when creditsType is set to "custom". /// - [DefaultValue(false)] - public bool audioLooping; + [DefaultValue(false)] public bool audioLooping = false; /// /// Duration of the credits scroll in seconds. /// Note: only applies when creditsType is set to "custom". /// - [DefaultValue(120f)] - public float length; + [DefaultValue(120f)] public float length = 120f; /// /// The type of credits that will run after the game over message is shown From 105e03a3efc55a616f9b2d7ae65ef104680c3cb3 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Thu, 10 Apr 2025 10:49:51 -0400 Subject: [PATCH 19/24] Change so that you can still use ringworld model --- .../Builder/Props/ProjectionBuilder.cs | 22 +++++++++++++++---- .../Props/EchoesOfTheEye/ProjectionInfo.cs | 2 +- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index 38bedc5d..8639d3c7 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -43,6 +43,7 @@ namespace NewHorizons.Builder.Props private static GameObject _autoPrefab; private static GameObject _visionTorchDetectorPrefab; private static GameObject _standingVisionTorchPrefab; + private static GameObject _standingVisionTorchCleanPrefab; private static readonly int EmissionMap = Shader.PropertyToID("_EmissionMap"); private static bool _isInit; @@ -90,15 +91,27 @@ namespace NewHorizons.Builder.Props _visionTorchDetectorPrefab.AddComponent()._destroyOnDLCNotOwned = true; } + if (_standingVisionTorchCleanPrefab == null) + { + _standingVisionTorchCleanPrefab = SearchUtilities.Find("DreamWorld_Body/Sector_DreamWorld/Sector_DreamZone_4/Interactibles_DreamZone_4_Upper/Prefab_IP_VisionTorchProjector")?.gameObject?.InstantiateInactive()?.Rename("Prefab_DW_VisionTorchProjector")?.DontDestroyOnLoad(); + if (_standingVisionTorchCleanPrefab == null) + NHLogger.LogWarning($"Tried to make standing vision torch prefab but couldn't. Do you have the DLC installed?"); + else + { + _standingVisionTorchCleanPrefab.AddComponent()._destroyOnDLCNotOwned = true; + GameObject.DestroyImmediate(_standingVisionTorchCleanPrefab.FindChild("Prefab_IP_Reel_PrisonPeephole_Vision")); + } + } + if (_standingVisionTorchPrefab == null) { - _standingVisionTorchPrefab = SearchUtilities.Find("DreamWorld_Body/Sector_DreamWorld/Sector_DreamZone_4/Interactibles_DreamZone_4_Upper/Prefab_IP_VisionTorchProjector")?.gameObject?.InstantiateInactive()?.Rename("Prefab_IP_VisionTorchProjector")?.DontDestroyOnLoad(); + _standingVisionTorchPrefab = SearchUtilities.Find("RingWorld_Body/Sector_RingWorld/Sector_SecretEntrance/Interactibles_SecretEntrance/Experiment_1/VisionTorchApparatus/VisionTorchRoot/Prefab_IP_VisionTorchProjector")?.gameObject?.InstantiateInactive()?.Rename("Prefab_IP_VisionTorchProjector")?.DontDestroyOnLoad(); if (_standingVisionTorchPrefab == null) NHLogger.LogWarning($"Tried to make standing vision torch prefab but couldn't. Do you have the DLC installed?"); else { _standingVisionTorchPrefab.AddComponent()._destroyOnDLCNotOwned = true; - GameObject.DestroyImmediate(_standingVisionTorchPrefab.FindChild("Prefab_IP_Reel_PrisonPeephole_Vision")); + GameObject.Instantiate(_standingVisionTorchCleanPrefab.FindChild("Effects_IP_SIM_VisionTorch"), _standingVisionTorchPrefab.transform, false).Rename("Effects_IP_SIM_VisionTorch"); } } } @@ -449,10 +462,11 @@ namespace NewHorizons.Builder.Props { InitPrefabs(); - if (_standingVisionTorchPrefab == null) return null; + if (_standingVisionTorchPrefab == null || _standingVisionTorchCleanPrefab == null) return null; // Spawn the torch itself - var standingTorch = DetailBuilder.Make(planetGO, sector, mod, _standingVisionTorchPrefab, new DetailInfo(info)); + var prefab = info.reelCondition == ProjectionInfo.SlideReelCondition.Pristine ? _standingVisionTorchCleanPrefab : _standingVisionTorchPrefab; + var standingTorch = DetailBuilder.Make(planetGO, sector, mod, prefab, new DetailInfo(info)); if (standingTorch == null) { diff --git a/NewHorizons/External/Modules/Props/EchoesOfTheEye/ProjectionInfo.cs b/NewHorizons/External/Modules/Props/EchoesOfTheEye/ProjectionInfo.cs index e059c310..43424ec0 100644 --- a/NewHorizons/External/Modules/Props/EchoesOfTheEye/ProjectionInfo.cs +++ b/NewHorizons/External/Modules/Props/EchoesOfTheEye/ProjectionInfo.cs @@ -82,7 +82,7 @@ namespace NewHorizons.External.Modules.Props.EchoesOfTheEye [DefaultValue("sevenSlides")] public SlideReelType reelModel = SlideReelType.SevenSlides; /// - /// Exclusive to the slide reel type. Condition/material of the reel. Antique is the Stranger, Pristine is the Dreamworld, Rusted is a burned reel. + /// Exclusive to the slide reel and standing vision torch type. Condition/material of the reel. Antique is the Stranger, Pristine is the Dreamworld, Rusted (exclusive to slide reels) is a burned reel. /// [DefaultValue("antique")] public SlideReelCondition reelCondition = SlideReelCondition.Antique; From 3cae688e2c14ece815b63ca77d00d3877317d74d Mon Sep 17 00:00:00 2001 From: josshmot Date: Fri, 11 Apr 2025 04:58:30 +1000 Subject: [PATCH 20/24] Replaced != string.Empty with string.IsNullOrEmpty() in NHGameOverManager --- NewHorizons/Components/NHGameOverManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NewHorizons/Components/NHGameOverManager.cs b/NewHorizons/Components/NHGameOverManager.cs index acc3080d..1586755d 100644 --- a/NewHorizons/Components/NHGameOverManager.cs +++ b/NewHorizons/Components/NHGameOverManager.cs @@ -165,13 +165,13 @@ namespace NewHorizons.Components // Patch new music clip var musicSource = Locator.FindObjectsOfType().Where(x => x.name == "AudioSource").Single(); // AudioSource that plays the credits music is literally called "AudioSource", luckily it's the only one called that. Lazy OW devs do be lazy. - if (gameOver.audio != string.Empty) // string.Empty is default value for "audio" in GameOverModule, means no audio is specified. + if (string.IsNullOrEmpty(gameOver.audio)) // string.Empty is default value for "audio" in GameOverModule, means no audio is specified. { AudioUtilities.SetAudioClip(musicSource, gameOver.audio, mod); // Load audio if specified } else { - musicSource.AssignAudioLibraryClip(AudioType.PLACEHOLDER); // Otherwise default custom credits are silent + musicSource.AssignAudioLibraryClip(AudioType.PLACEHOLDER); // Otherwise default custom credits are silent - AudioType.PLACEHOLDER is silence (apparently) } musicSource.loop = gameOver.audioLooping; From ad3802d383febc14efa43abfcc57a8920c602011 Mon Sep 17 00:00:00 2001 From: josshmot Date: Fri, 11 Apr 2025 05:07:49 +1000 Subject: [PATCH 21/24] Added intended behaviour when unspecified to json description for GameOverModule.audio --- NewHorizons/External/Modules/GameOverModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NewHorizons/External/Modules/GameOverModule.cs b/NewHorizons/External/Modules/GameOverModule.cs index d9dba70b..2f62a5b6 100644 --- a/NewHorizons/External/Modules/GameOverModule.cs +++ b/NewHorizons/External/Modules/GameOverModule.cs @@ -25,7 +25,7 @@ namespace NewHorizons.External.Modules public string condition; /// - /// Path to the audio file to use as custom music for the credits. + /// Path to the audio file to use as custom music for the credits. When creditsType is set to "custom", credits will be silent unless this is specified. /// Note: only applies when creditsType is set to "custom". /// public string audio = string.Empty; // Explicitly declaring this for condition in NHGameOverManager @@ -37,7 +37,7 @@ namespace NewHorizons.External.Modules [DefaultValue(1f)] public float audioVolume = 1f; /// - /// Determines if the credits music should loop. + /// Determines if the credits music should loop () /// Note: only applies when creditsType is set to "custom". /// [DefaultValue(false)] public bool audioLooping = false; From a8d944a4c9e4bf867b344b7b1d55c76db69234f8 Mon Sep 17 00:00:00 2001 From: josshmot Date: Fri, 11 Apr 2025 05:09:46 +1000 Subject: [PATCH 22/24] Fixed typo in GameOverModule --- NewHorizons/External/Modules/GameOverModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NewHorizons/External/Modules/GameOverModule.cs b/NewHorizons/External/Modules/GameOverModule.cs index 2f62a5b6..859e9d3b 100644 --- a/NewHorizons/External/Modules/GameOverModule.cs +++ b/NewHorizons/External/Modules/GameOverModule.cs @@ -25,7 +25,7 @@ namespace NewHorizons.External.Modules public string condition; /// - /// Path to the audio file to use as custom music for the credits. When creditsType is set to "custom", credits will be silent unless this is specified. + /// Path to the audio file to use as custom music for the credits. When creditsType is set to "custom", credits will be silent unless this attribute is specified. /// Note: only applies when creditsType is set to "custom". /// public string audio = string.Empty; // Explicitly declaring this for condition in NHGameOverManager @@ -37,7 +37,7 @@ namespace NewHorizons.External.Modules [DefaultValue(1f)] public float audioVolume = 1f; /// - /// Determines if the credits music should loop () + /// Determines if the credits music should loop. /// Note: only applies when creditsType is set to "custom". /// [DefaultValue(false)] public bool audioLooping = false; From 539ef61c534be2feccc2d48b4992143f5b2c7642 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Thu, 10 Apr 2025 15:11:34 -0400 Subject: [PATCH 23/24] correction --- NewHorizons/Components/NHGameOverManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/Components/NHGameOverManager.cs b/NewHorizons/Components/NHGameOverManager.cs index 1586755d..37661562 100644 --- a/NewHorizons/Components/NHGameOverManager.cs +++ b/NewHorizons/Components/NHGameOverManager.cs @@ -165,7 +165,7 @@ namespace NewHorizons.Components // Patch new music clip var musicSource = Locator.FindObjectsOfType().Where(x => x.name == "AudioSource").Single(); // AudioSource that plays the credits music is literally called "AudioSource", luckily it's the only one called that. Lazy OW devs do be lazy. - if (string.IsNullOrEmpty(gameOver.audio)) // string.Empty is default value for "audio" in GameOverModule, means no audio is specified. + if (!string.IsNullOrEmpty(gameOver.audio)) // string.Empty is default value for "audio" in GameOverModule, means no audio is specified. { AudioUtilities.SetAudioClip(musicSource, gameOver.audio, mod); // Load audio if specified } From 5cde777159b45a244cb1118dbb485bd6f3c987ec Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Fri, 18 Apr 2025 05:53:41 -0400 Subject: [PATCH 24/24] log xml file --- .../Builder/Props/TranslatorText/TranslatorTextBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/Builder/Props/TranslatorText/TranslatorTextBuilder.cs b/NewHorizons/Builder/Props/TranslatorText/TranslatorTextBuilder.cs index cd967809..f5cf3b2b 100644 --- a/NewHorizons/Builder/Props/TranslatorText/TranslatorTextBuilder.cs +++ b/NewHorizons/Builder/Props/TranslatorText/TranslatorTextBuilder.cs @@ -471,7 +471,7 @@ namespace NewHorizons.Builder.Props.TranslatorText if (info.arcInfo != null && info.arcInfo.Count() != dict.Values.Count()) { - NHLogger.LogError($"Can't make NomaiWallText, arcInfo length [{info.arcInfo.Count()}] doesn't equal number of TextBlocks [{dict.Values.Count()}] in the xml"); + NHLogger.LogError($"Can't make NomaiWallText [{info.xmlFile}], arcInfo length [{info.arcInfo.Count()}] doesn't equal number of TextBlocks [{dict.Values.Count()}] in the xml"); return; }