From db3663381363a6944df83b25de45b2988e0214e0 Mon Sep 17 00:00:00 2001 From: devek1 Date: Tue, 5 May 2026 20:59:35 +0300 Subject: [PATCH 1/3] Added various options which make music behavior more accurate to the original release in different ways --- OFFHarmonyPatches.cs | 114 ++++++++++++++++++++++++++++++++++++++++++- OFFMainPlugin.cs | 63 ++++++++++++++++++++++++ 2 files changed, 176 insertions(+), 1 deletion(-) diff --git a/OFFHarmonyPatches.cs b/OFFHarmonyPatches.cs index 911dfc9..333c937 100644 --- a/OFFHarmonyPatches.cs +++ b/OFFHarmonyPatches.cs @@ -112,8 +112,10 @@ static bool Prefix() [HarmonyPatch(typeof(FPGAudioManager), "ChangeBGM")] class MusicPatch { - static bool Prefix(ScriptedAudioClip sound) + static bool Prefix(ScriptedAudioClip sound, ref bool savePositionOfCurrentlyPlayingTrack) { + if (OFFMainPlugin.DontSaveBGMProgress.Value) + savePositionOfCurrentlyPlayingTrack = false; ReplaceSound.Replace(sound, "Music"); // Continue with the rest of the function @@ -156,4 +158,114 @@ static bool Prefix(ScriptedAudioClip sound) return true; } } + + // Changes speed-change-based tracks back to behaving that way as in the original French version of OFF, and also undo some remake changes + [HarmonyPatch(typeof(FPGCmdPlayMusic), "Activate")] + class PitchShiftPatch_Events + { + static bool Prefix(FPGCmdPlayMusic __instance) + { + if (OFFMainPlugin.QueenPostFightOriginal.Value && __instance.bgmTrack == OFFMusicTracks.Stille) + return false; + if (OFFMainPlugin.RestoreEnochPrefightSlowdown.Value && + __instance.bgmTrack == OFFMusicTracks.ORostoDeUmAssassinoCansado) + { + __instance.scriptedAudio.pitch = 0.7f; + return true; + } + if (!OFFMainPlugin.RestoreOriginalSpeedChanges.Value) + return true; + float pitch; + (__instance.bgmTrack, pitch) = OFFMainPlugin.ConvertSpeed(__instance.bgmTrack); + if (pitch != 0f) + __instance.scriptedAudio.pitch = pitch; + return true; + } + } + + [HarmonyPatch(typeof(FPGGameState), "PlaySystemBGM")] + class PitchShiftPatch_System + { + static bool Prefix(FPGGameState __instance, FPGSystemBGM.SystemBGMType type, bool savePositionOfCurrentlyPlayingTrack) + { + FPGSystemBGM fPGSystemBGM = null; + foreach (FPGAudioOverride audioOverride in __instance.audioOverrides) + { + if (audioOverride.type == type) + { + fPGSystemBGM = new FPGSystemBGM(); + fPGSystemBGM.bgmTrack = audioOverride.track; + } + } + if (fPGSystemBGM == null) + { + foreach (FPGSystemBGM systemBGM in FPGOverworldMode.instance.globalDatabase.systemBGMs) + { + if (systemBGM.systemBGMType == type) + { + fPGSystemBGM = systemBGM; + } + } + } + float pitch = 0f; + if (OFFMainPlugin.RestoreOriginalSpeedChanges.Value) + (fPGSystemBGM.bgmTrack, pitch) = OFFMainPlugin.ConvertSpeed(fPGSystemBGM.bgmTrack); + if (pitch != 0f) + fPGSystemBGM.scriptedAudioClip.pitch = pitch; + fPGSystemBGM.scriptedAudioClip.clip = FPGOverworldMode.instance.audioManager.musicMap.GetBGM(fPGSystemBGM.bgmTrack); + FPGOverworldMode.instance.audioManager.ChangeBGM(fPGSystemBGM.scriptedAudioClip, loop: true, savePositionOfCurrentlyPlayingTrack); + return false; + } + } + + [HarmonyPatch(typeof(FPGOverworldMode), "StartMusic")] + class PitchShiftPatch_OverworldMode + { + static bool Prefix(FPGOverworldMode __instance, bool isBackFromBattle, OFFMapComponent ___m_mapComp) + { + float pitch = 0f; + OFFMusicTracks track; + if (!__instance.gameState.playerState.isInBoat && isBackFromBattle && + ___m_mapComp.bgmTrackBackFromBattle != (OFFMusicTracks)(-1)) + { + if (OFFMainPlugin.RestoreOriginalSpeedChanges.Value) + (track, pitch) = OFFMainPlugin.ConvertSpeed(___m_mapComp.bgmTrackBackFromBattle); + else + track = ___m_mapComp.bgmTrackBackFromBattle; + ___m_mapComp.backgroundMusic.clip = __instance.audioManager.musicMap.GetBGM(track); + if (pitch != 0f) + ___m_mapComp.backgroundMusic.pitch = pitch; + __instance.audioManager.ChangeBGM(___m_mapComp.backgroundMusic, loop: true); + } + else if (!__instance.gameState.playerState.isInBoat) + { + if (OFFMainPlugin.RestoreOriginalSpeedChanges.Value) + (track, pitch) = OFFMainPlugin.ConvertSpeed(___m_mapComp.bgmTrack); + else + track = ___m_mapComp.bgmTrack; + ___m_mapComp.backgroundMusic.clip = __instance.audioManager.musicMap.GetBGM(track); + if (pitch != 0f) + ___m_mapComp.backgroundMusic.pitch = pitch; + __instance.audioManager.ChangeBGM(___m_mapComp.backgroundMusic, loop: true); + } + else + { + __instance.gameState.PlaySystemBGM(FPGSystemBGM.SystemBGMType.Boat); + } + + return false; + } + } + + // boss death animations don't cut out the music + [HarmonyPatch(typeof(BATBattleAnimator), "FadeOutMusic")] + class BossDeathNoPause + { + static bool Prefix(BATBattleAnimator __instance) + { + if (OFFMainPlugin.BossDeathDontStopBGM.Value) + return false; + return true; + } + } } \ No newline at end of file diff --git a/OFFMainPlugin.cs b/OFFMainPlugin.cs index 3ac94b5..2055361 100644 --- a/OFFMainPlugin.cs +++ b/OFFMainPlugin.cs @@ -1,6 +1,8 @@ using BepInEx; using BepInEx.Configuration; +using System.Collections.Generic; using BepInEx.Logging; +using FangamerRPG; using HarmonyLib; namespace OFFRestored; @@ -21,6 +23,11 @@ public class OFFMainPlugin : BaseUnityPlugin public static ConfigEntry ReplaceMusic; public static ConfigEntry DedanLoopFix; public static ConfigEntry DisableCreditsLoop; + public static ConfigEntry RestoreEnochPrefightSlowdown; + public static ConfigEntry RestoreOriginalSpeedChanges; + public static ConfigEntry QueenPostFightOriginal; + public static ConfigEntry BossDeathDontStopBGM; + public static ConfigEntry DontSaveBGMProgress; // SFX config public static ConfigEntry ReplaceSFX; @@ -97,6 +104,41 @@ private void SetConfig() true, "If true, The credits music will not loop." ); + // Queen post-fight restoration + QueenPostFightOriginal = Config.Bind( + "Music", + "QueenPostFightOriginal", + true, + "If true, The Woman of Your Dreams (or its counterpart) will be restored in the cutscene after Queen is defeated, instead of playing 50% speed Silence (or its counterpart)." + ); + // all Burned Bodies variants restored + RestoreEnochPrefightSlowdown = Config.Bind( + "Music", + "RestoreEnochPrefightSlowdown", + true, + "If true, Enoch's battle theme will be slowed down in the prefight cutscene, like in the original game." + ); + // bosses don't stop music during their death animations + BossDeathDontStopBGM = Config.Bind( + "Music", + "BossDeathDontStopBGM", + false, + "If true, battle music will not pause during boss defeat animations. This also means Tender Sugar won't restart after winning." + ); + // pitch-shifted music behaves like in French version + RestoreOriginalSpeedChanges = Config.Bind( + "Music", + "RestoreOriginalSpeedChanges", + true, + "If true, tracks that were originally just sped-up or slowed-down of other tracks in the original French version will be restored to that form, making them transition as they did originally before the English fan translation." + ); + // bgm progress doesn't save + DontSaveBGMProgress = Config.Bind( + "Music", + "DontSaveBGMProgress", + false, + "If true, disables the remake's new feature where overworld music continues from where it left off after battles instead of starting over from the beginning of the track (this doesn't change the behavior when battle music and overworld music are the same)" + ); // Replace SFX ReplaceSFX = Config.Bind( @@ -113,4 +155,25 @@ private void SetConfig() "If true, removes the sound that plays at the start of an ally's turn in battle." ); } + + public static (OFFMusicTracks, float) ConvertSpeed(OFFMusicTracks track) => track switch + { + OFFMusicTracks.BrainPlagueSlowRewind => (OFFMusicTracks.BrainPlagueRewind, 0.6f), + OFFMusicTracks.TheRaceOfAThousandAntsOhno => (OFFMusicTracks.TheRaceOfAThousandAnts, 0.8f), + OFFMusicTracks.TheRaceofAThousandAntsSafe => (OFFMusicTracks.TheRaceOfAThousandAnts, 0.5f), + OFFMusicTracks.Stille => (OFFMusicTracks.Silence, 0.5f), + OFFMusicTracks.Shhhhhh => (OFFMusicTracks.Silencio, 1.5f), + OFFMusicTracks.TheWallsAreListeningCliff => (OFFMusicTracks.TheWallsAreListeningCliff, 0.6f), + OFFMusicTracks.ClockworkLostGripOfTime => (OFFMusicTracks.Clockwork, 0.6f), + OFFMusicTracks.EndlessHallwayStuck => (OFFMusicTracks.EndlessHallway, 0.5f), + OFFMusicTracks.FourteenFakeResidents => (OFFMusicTracks.FourteenResidents, 0.8f), + OFFMusicTracks.FourteenResidentsOFFTitle => (OFFMusicTracks.FourteenResidents, 0.5f), + OFFMusicTracks.BurnedBodiesOut => (OFFMusicTracks.BurnedBodies, 0.8f), + OFFMusicTracks.BurnedBodiesThe => (OFFMusicTracks.BurnedBodies, 0.7f), + OFFMusicTracks.BurnedBodiesChimney => (OFFMusicTracks.BurnedBodies, 0.6f), + OFFMusicTracks.BurnedBodiesSweetTooth => (OFFMusicTracks.BurnedBodies, 0.5f), + OFFMusicTracks.YesterdayWasEvenBetter => (OFFMusicTracks.YesterdayWasBetter, 0.8f), + OFFMusicTracks.TodayIsWorstSweet => (OFFMusicTracks.TodayIsWorst, 0.8f), + _ => (track, 0f) + }; } \ No newline at end of file From 65f8f6be5849db65bd2f6f499e0a096e00905706 Mon Sep 17 00:00:00 2001 From: devek1 Date: Tue, 5 May 2026 21:28:56 +0300 Subject: [PATCH 2/3] Fixed inaccurate comment --- OFFMainPlugin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OFFMainPlugin.cs b/OFFMainPlugin.cs index 2055361..6bec8e4 100644 --- a/OFFMainPlugin.cs +++ b/OFFMainPlugin.cs @@ -111,7 +111,7 @@ private void SetConfig() true, "If true, The Woman of Your Dreams (or its counterpart) will be restored in the cutscene after Queen is defeated, instead of playing 50% speed Silence (or its counterpart)." ); - // all Burned Bodies variants restored + // Enoch pre-fight music slowed down RestoreEnochPrefightSlowdown = Config.Bind( "Music", "RestoreEnochPrefightSlowdown", From 2f1cdad8b027a2d1e9e642ba22447320ea0fbe33 Mon Sep 17 00:00:00 2001 From: devek1 Date: Tue, 5 May 2026 21:36:42 +0300 Subject: [PATCH 3/3] Fixed one incorrect track in the pitch-shift restoration --- OFFMainPlugin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OFFMainPlugin.cs b/OFFMainPlugin.cs index 6bec8e4..0aaa77c 100644 --- a/OFFMainPlugin.cs +++ b/OFFMainPlugin.cs @@ -163,7 +163,7 @@ private void SetConfig() OFFMusicTracks.TheRaceofAThousandAntsSafe => (OFFMusicTracks.TheRaceOfAThousandAnts, 0.5f), OFFMusicTracks.Stille => (OFFMusicTracks.Silence, 0.5f), OFFMusicTracks.Shhhhhh => (OFFMusicTracks.Silencio, 1.5f), - OFFMusicTracks.TheWallsAreListeningCliff => (OFFMusicTracks.TheWallsAreListeningCliff, 0.6f), + OFFMusicTracks.TheWallsAreListeningCliff => (OFFMusicTracks.TheWallsAreListening, 0.6f), OFFMusicTracks.ClockworkLostGripOfTime => (OFFMusicTracks.Clockwork, 0.6f), OFFMusicTracks.EndlessHallwayStuck => (OFFMusicTracks.EndlessHallway, 0.5f), OFFMusicTracks.FourteenFakeResidents => (OFFMusicTracks.FourteenResidents, 0.8f),