RUMBLE does not support other mod managers. If you want to use a manager, you must use the RUMBLE Mod Manager, a manager specifically designed for this game.
Decompiled source of HealthVoiceover v1.0.0
Mods/HealthVoiceover.dll
Decompiled a week agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using HarmonyLib; using HealthVoiceover; using Il2CppRUMBLE.Audio; using Il2CppRUMBLE.Players; using Il2CppRUMBLE.Players.Subsystems; using Il2CppRUMBLE.Pools; using MelonLoader; using RumbleModUI; using RumbleModdingAPI.RMAPI; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(VoiceOverMod), "Health Voiceover", "1.0.0", "Pepuldo", null)] [assembly: MelonGame("Buckethead Entertainment", "RUMBLE")] [assembly: AssemblyTitle("HealthVoiceover")] [assembly: MelonOptionalDependencies(new string[] { "RUMBLE.Runtime", "PhotonUnityNetworking" })] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("HealthVoiceover")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("87097c2d-ff58-433f-993b-b08508a65b04")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace HealthVoiceover; public static class BuildInfo { public const string ModName = "Health Voiceover"; public const string ModVersion = "1.0.0"; public const string Description = "Speaks your health aloud when it changes"; public const string Author = "Pepuldo"; public const string Company = ""; } public class VoiceOverMod : MelonMod { public static AudioCall[] healthCalls = (AudioCall[])(object)new AudioCall[21]; public static PooledAudioSource currentSelfReadout; public static PooledAudioSource currentOpponentReadout; public static Mod Mod = new Mod(); public static ModSetting<bool> announceSelf; public static ModSetting<bool> announceOpponent; public static ModSetting<bool> announceZero; public static ModSetting<bool> announceDamage; public static ModSetting<float> selfVolume; public static ModSetting<float> opponentVolume; public static short pendingSelfHealth; public static bool selfPending = false; public static short pendingOpponentHealth; public static bool opponentPending = false; public override void OnInitializeMelon() { ((MelonBase)this).HarmonyInstance.PatchAll(); LoadSounds(); MelonLogger.Msg("Health Voiceover loaded!"); } public override void OnLateInitializeMelon() { MelonLogger.Msg("OnLateInitializeMelon ran - subscribing to UI_Initialized"); UI.instance.UI_Initialized += OnUIInit; } public void OnUIInit() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Expected O, but got Unknown //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Expected O, but got Unknown Mod.ModName = "Health Voiceover"; Mod.ModVersion = "1.0.0"; Mod.SetFolder("HealthVoiceover"); Mod.AddDescription("Description", "", "Speaks your health aloud when it changes", new Tags { IsSummary = true }); announceSelf = Mod.AddToList("Announce my health", true, 0, "Speak your own health when it changes.", new Tags()); announceOpponent = Mod.AddToList("Announce opponent health", false, 0, "Speak your opponent's health when it changes.", new Tags()); announceZero = Mod.AddToList("Announce no-damage hits", false, 0, "Speak even when a hit deals no damage.", new Tags()); announceDamage = Mod.AddToList("Announce damage dealt", false, 0, "Speak the damage dealt instead of remaining health.", new Tags()); selfVolume = Mod.AddToList("My volume", 0.75f, "Volume of your own health readout (0.1 to 1.5).", new Tags()); opponentVolume = Mod.AddToList("Opponent volume", 0.75f, "Volume of opponent health readout (0.1 to 1.5).", new Tags()); Mod.GetFromFile(); Mod.ModSaved += OnModSaved; UI.instance.AddMod(Mod); MelonLogger.Msg("Health Voiceover settings registered!"); } private void LoadSounds() { for (int i = 0; i <= 20; i++) { string text = "UserData/HealthReadout/" + i + ".wav"; healthCalls[i] = AudioManager.CreateAudioCall(text, 0.75f); } } private void OnModSaved() { if ((float)((ModSetting)selfVolume).Value > 1.5f) { ((ModSetting)selfVolume).Value = 1.5f; ((ModSetting)selfVolume).SavedValue = 1.5f; } else if ((float)((ModSetting)selfVolume).Value < 0.1f) { ((ModSetting)selfVolume).Value = 0.1f; ((ModSetting)selfVolume).SavedValue = 0.1f; } if ((float)((ModSetting)opponentVolume).Value > 1.5f) { ((ModSetting)opponentVolume).Value = 1.5f; ((ModSetting)opponentVolume).SavedValue = 1.5f; } else if ((float)((ModSetting)opponentVolume).Value < 0.1f) { ((ModSetting)opponentVolume).Value = 0.1f; ((ModSetting)opponentVolume).SavedValue = 0.1f; } UI.instance.ForceRefresh(); } public override void OnUpdate() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) if (selfPending) { if ((Object)(object)currentSelfReadout != (Object)null) { currentSelfReadout.audioSource.Stop(); } float volume = Mathf.Clamp((float)((ModSetting)selfVolume).Value, 0.1f, 1.5f); currentSelfReadout = AudioManager.PlaySound(healthCalls[pendingSelfHealth], Vector3.zero, false); currentSelfReadout.audioSource.volume = volume; currentSelfReadout.audioSource.spatialBlend = 0f; selfPending = false; } if (opponentPending) { if ((Object)(object)currentOpponentReadout != (Object)null) { currentOpponentReadout.audioSource.Stop(); } float volume2 = Mathf.Clamp((float)((ModSetting)opponentVolume).Value, 0.1f, 1.5f); currentOpponentReadout = AudioManager.PlaySound(healthCalls[pendingOpponentHealth], Vector3.zero, false); currentOpponentReadout.audioSource.volume = volume2; currentOpponentReadout.audioSource.spatialBlend = 0f; opponentPending = false; } } } [HarmonyPatch(typeof(PlayerHealth), "SetHealth", new Type[] { typeof(short), typeof(short), typeof(bool) })] public static class HealthReadoutPatch { private static void Postfix(PlayerHealth __instance, short newHealth, short previousHealth, bool useEffects) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Invalid comparison between Unknown and I4 ControllerType controllerType = ((PlayerControllerSubsystem)__instance).ParentController.controllerType; bool flag = (int)controllerType == 1; if (previousHealth == newHealth && !(bool)((ModSetting)VoiceOverMod.announceZero).Value) { return; } bool flag2; if ((int)controllerType == 1) { flag2 = (bool)((ModSetting)VoiceOverMod.announceSelf).Value; } else { if ((int)controllerType != 2) { return; } flag2 = (bool)((ModSetting)VoiceOverMod.announceOpponent).Value; } if (!flag2) { return; } short num = ((!(bool)((ModSetting)VoiceOverMod.announceDamage).Value) ? newHealth : ((short)Mathf.Abs(newHealth - previousHealth))); if (num >= 0 && num <= 20) { if (flag) { VoiceOverMod.pendingSelfHealth = num; VoiceOverMod.selfPending = true; } else { VoiceOverMod.pendingOpponentHealth = num; VoiceOverMod.opponentPending = true; } } } }