Decompiled source of HealthVoiceover v1.1.0

Mods/HealthVoiceover.dll

Decompiled a month ago
using 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);
				}
			}
		}
	}
}