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.1.0
Mods/HealthVoiceover.dll
Decompiled a month agousing System; using System.Collections; 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 MelonLoader.Preferences; using Microsoft.CodeAnalysis; using RumbleModdingAPI.RMAPI; using UIFramework; using UIFramework.UiExtensions; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(VoiceOverMod), "Health Voiceover", "1.1.0", "Pepuldo", null)] [assembly: MelonGame("Buckethead Entertainment", "RUMBLE")] [assembly: AssemblyTitle("HealthVoiceover")] [assembly: MelonOptionalDependencies(new string[] { "RUMBLE.Runtime", "PhotonUnityNetworking" })] [assembly: MelonAdditionalDependencies(new string[] { "UIFramework" })] [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.1.0.0")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyVersion("1.1.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace HealthVoiceover { public static class BuildInfo { public const string ModName = "Health Voiceover"; public const string ModVersion = "1.1.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 MelonPreferences_Entry<bool> announceSelf; public static MelonPreferences_Entry<bool> announceOpponent; public static MelonPreferences_Entry<bool> announceZero; public static MelonPreferences_Entry<bool> announceDamage; public static MelonPreferences_Entry<float> selfVolume; public static MelonPreferences_Entry<float> opponentVolume; private static short pendingSelfHealth; private static bool selfScheduled; private static short pendingOpponentHealth; private static bool opponentScheduled; public override void OnInitializeMelon() { ((MelonBase)this).HarmonyInstance.PatchAll(); LoadSounds(); BuildSettings(); MelonLogger.Msg("Health Voiceover loaded!"); } private void BuildSettings() { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown MelonPreferences_Category val = MelonPreferences.CreateCategory("HealthVoiceover", "Health Voiceover"); announceSelf = val.CreateEntry<bool>("AnnounceSelf", true, "Announce my health", "Speak your own health when it changes.", false, false, (ValueValidator)null, (string)null); announceOpponent = val.CreateEntry<bool>("AnnounceOpponent", false, "Announce opponent health", "Speak your opponent's health when it changes.", false, false, (ValueValidator)null, (string)null); announceZero = val.CreateEntry<bool>("AnnounceZero", false, "Announce no-damage hits", "Speak even when a hit deals no damage.", false, false, (ValueValidator)null, (string)null); announceDamage = val.CreateEntry<bool>("AnnounceDamage", false, "Announce damage dealt", "Speak the damage dealt instead of remaining health.", false, false, (ValueValidator)null, (string)null); selfVolume = val.CreateEntry<float>("SelfVolume", 0.75f, "My volume", "Volume of your own health readout.", false, false, (ValueValidator)new SliderDescriptor { Min = 0.1f, Max = 1.5f, DecimalPlaces = 2 }); opponentVolume = val.CreateEntry<float>("OpponentVolume", 0.75f, "Opponent volume", "Volume of opponent health readout.", false, false, (ValueValidator)new SliderDescriptor { Min = 0.1f, Max = 1.5f, DecimalPlaces = 2 }); UI.RegisterMelon((MelonBase)(object)this, (MelonPreferences_Category[])(object)new MelonPreferences_Category[1] { val }); MelonLogger.Msg("Health Voiceover settings registered with UIFramework."); } private void LoadSounds() { for (int i = 0; i <= 20; i++) { string text = "UserData/HealthReadout/" + i + ".wav"; healthCalls[i] = AudioManager.CreateAudioCall(text, 0.75f); } } public static void ScheduleReadout(short health, bool isLocal) { if (isLocal) { pendingSelfHealth = health; if (selfScheduled) { return; } selfScheduled = true; } else { pendingOpponentHealth = health; if (opponentScheduled) { return; } opponentScheduled = true; } MelonCoroutines.Start(PlayNextFrame(isLocal)); } private static IEnumerator PlayNextFrame(bool isLocal) { yield return null; short num; if (isLocal) { selfScheduled = false; num = pendingSelfHealth; } else { opponentScheduled = false; num = pendingOpponentHealth; } AudioCall val = healthCalls[num]; if (!((Object)(object)val == (Object)null)) { PooledAudioSource val2 = (isLocal ? currentSelfReadout : currentOpponentReadout); if ((Object)(object)val2 != (Object)null) { val2.audioSource.Stop(); } float volume = Mathf.Clamp((isLocal ? selfVolume : opponentVolume).Value, 0.1f, 1.5f); PooledAudioSource val3 = AudioManager.PlaySound(val, Vector3.zero, false); val3.audioSource.volume = volume; val3.audioSource.spatialBlend = 0f; if (isLocal) { currentSelfReadout = val3; } else { currentOpponentReadout = val3; } } } } [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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Invalid comparison between Unknown and I4 if (VoiceOverMod.announceSelf == null) { return; } ControllerType controllerType = ((PlayerControllerSubsystem)__instance).ParentController.controllerType; bool isLocal = (int)controllerType == 1; if (previousHealth == newHealth && !VoiceOverMod.announceZero.Value) { return; } bool value; if ((int)controllerType == 1) { value = VoiceOverMod.announceSelf.Value; } else { if ((int)controllerType != 2) { return; } value = VoiceOverMod.announceOpponent.Value; } if (value) { short num = ((!VoiceOverMod.announceDamage.Value) ? newHealth : ((short)Mathf.Abs(newHealth - previousHealth))); if (num >= 0 && num <= 20) { VoiceOverMod.ScheduleReadout(num, isLocal); } } } } }