Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of LouderMonsters v1.2.0
LouderMonsters.dll
Decompiled 2 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyVersion("0.0.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 LouderMonsters { [BepInPlugin("rev.loudermonsters", "LouderMonsters", "1.2.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "rev.loudermonsters"; public const string Name = "LouderMonsters"; public const string Version = "1.2.0"; private const int PresetRevision = 2; private static readonly Dictionary<string, (float gain, float range)> Presets = new Dictionary<string, (float, float)> { { "Animal", (1.5f, 1.35f) }, { "Clown", (1.5f, 1.35f) }, { "Upscream", (1.5f, 1.35f) }, { "Trudge", (1.5f, 1.35f) }, { "Banger", (0.5f, 0.6f) }, { "Clown Laser", (1.5f, 1.3f) } }; internal static ManualLogSource Log; internal static ConfigFile Cfg; internal static MonsterAudio General; private static readonly Dictionary<string, MonsterAudio> Groups = new Dictionary<string, MonsterAudio>(); private static int configRevision; private void Awake() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown //IL_0144: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Cfg = ((BaseUnityPlugin)this).Config; configRevision = ReadConfigRevision(((BaseUnityPlugin)this).Config.ConfigFilePath); General = new MonsterAudio(null, ((BaseUnityPlugin)this).Config.Bind<float>("General", "Gain", 2f, new ConfigDescription("Signal amplification for all monster sounds. 1 = vanilla, 2 = twice as loud.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 4f), Array.Empty<object>())), ((BaseUnityPlugin)this).Config.Bind<float>("General", "Range", 1.3f, new ConfigDescription("Audible distance multiplier for all monster sounds. 1 = vanilla. Applies to newly spawned monsters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f), Array.Empty<object>()))); if (configRevision < 2 && Mathf.Approximately(General.RangeEntry.Value, 1.5f)) { General.RangeEntry.Value = 1.3f; } foreach (KeyValuePair<string, (float, float)> preset in Presets) { GetGroup(preset.Key); } ((BaseUnityPlugin)this).Config.Bind<int>("Internal", "PresetRevision", 2, "Used by the mod to update default values after upgrades. Do not edit.").Value = 2; new Harmony("rev.loudermonsters").PatchAll(typeof(Patches)); Log.LogInfo((object)string.Format("{0} {1} loaded (gain x{2}, range x{3})", "LouderMonsters", "1.2.0", General.GainEntry.Value, General.RangeEntry.Value)); } private static int ReadConfigRevision(string path) { if (!File.Exists(path)) { return 2; } string[] array = File.ReadAllLines(path); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.StartsWith("PresetRevision") && int.TryParse(text.Substring(text.IndexOf('=') + 1).Trim(), out var result)) { return result; } } return 1; } internal static MonsterAudio GetMonster(string enemyName) { return GetGroup(enemyName); } internal static MonsterAudio GetLaser(string enemyName) { return GetGroup(enemyName + " Laser", GetMonster(enemyName)); } private static MonsterAudio GetGroup(string groupName, MonsterAudio parent = null) { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Expected O, but got Unknown //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Expected O, but got Unknown if (Groups.TryGetValue(groupName, out var value)) { return value; } if (parent == null && groupName.EndsWith(" Laser")) { parent = GetGroup(groupName.Substring(0, groupName.Length - " Laser".Length)); } string text = SanitizeKey(groupName); (float, float) value2; bool flag = Presets.TryGetValue(groupName, out value2); float num; if (flag) { (num, _) = value2; } else { num = 1f; } float num2 = num; float num3 = (flag ? value2.Item2 : 1f); string text2 = ((parent != null) ? parent.DisplayName : "General"); ConfigEntry<float> val = Cfg.Bind<float>("Monsters", text + " Gain", num2, new ConfigDescription("Extra amplification for " + groupName + ", multiplied with " + text2 + " Gain. Below 1 makes it quieter.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 4f), Array.Empty<object>())); ConfigEntry<float> val2 = Cfg.Bind<float>("Monsters", text + " Range", num3, new ConfigDescription("Extra audible distance for " + groupName + ", multiplied with " + text2 + " Range. Below 1 makes it heard from closer.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f), Array.Empty<object>())); if (flag && configRevision < 2) { if (Mathf.Approximately(val.Value, 1f)) { val.Value = num2; } if (Mathf.Approximately(val2.Value, 1f) || Mathf.Approximately(val2.Value, 1.5f)) { val2.Value = num3; } } value = new MonsterAudio(parent ?? General, val, val2, groupName); Groups[groupName] = value; return value; } private static string SanitizeKey(string name) { char[] array = name.ToCharArray(); for (int i = 0; i < array.Length; i++) { if ("=\n\t\\\"'[]".IndexOf(array[i]) >= 0) { array[i] = '_'; } } return new string(array).Trim(); } } internal class MonsterAudio { public readonly ConfigEntry<float> GainEntry; public readonly ConfigEntry<float> RangeEntry; public readonly string DisplayName; private readonly MonsterAudio parent; public volatile float Gain = 1f; public float Range => RangeEntry.Value * ((parent != null) ? parent.Range : 1f); public event Action Changed; public MonsterAudio(MonsterAudio parent, ConfigEntry<float> gain, ConfigEntry<float> range, string displayName = "General") { this.parent = parent; GainEntry = gain; RangeEntry = range; DisplayName = displayName; Refresh(); gain.SettingChanged += delegate { Refresh(); }; if (parent != null) { parent.Changed += Refresh; } } private void Refresh() { Gain = GainEntry.Value * ((parent != null) ? parent.Gain : 1f); this.Changed?.Invoke(); } } internal static class EnemySounds { private static readonly ConditionalWeakTable<Sound, MonsterAudio> Registered = new ConditionalWeakTable<Sound, MonsterAudio>(); private static readonly Dictionary<Type, FieldInfo[]> FieldCache = new Dictionary<Type, FieldInfo[]>(); public static MonsterAudio Find(Sound sound) { if (sound == null || !Registered.TryGetValue(sound, out var value)) { return null; } return value; } public static void RegisterEnemy(EnemyParent enemy) { string text = (string.IsNullOrEmpty(enemy.enemyName) ? ((Object)enemy).name : enemy.enemyName); MonsterAudio monster = Plugin.GetMonster(text); MonoBehaviour[] componentsInChildren = ((Component)enemy).GetComponentsInChildren<MonoBehaviour>(true); HashSet<SemiLaser> hashSet = new HashSet<SemiLaser>(((Component)enemy).GetComponentsInChildren<SemiLaser>(true)); MonoBehaviour[] array = componentsInChildren; foreach (MonoBehaviour obj in array) { EnemyBeamer val = (EnemyBeamer)(object)((obj is EnemyBeamer) ? obj : null); if (val != null && (Object)(object)val.laser != (Object)null) { hashSet.Add(val.laser); } } int num = 0; if (hashSet.Count > 0) { MonsterAudio laser = Plugin.GetLaser(text); foreach (SemiLaser item in hashSet) { num += RegisterBehaviour((MonoBehaviour)(object)item, laser); } } int num2 = 0; array = componentsInChildren; foreach (MonoBehaviour val2 in array) { if ((Object)(object)val2 != (Object)null && !(val2 is SemiLaser)) { num2 += RegisterBehaviour(val2, monster); } } string text2 = ((num > 0) ? $", laser {num} sounds" : ""); Plugin.Log.LogInfo((object)$"Monster spawned: {text} ({num2} sounds{text2}, gain x{monster.Gain:0.##}, range x{monster.Range:0.##})"); } private static int RegisterBehaviour(MonoBehaviour behaviour, MonsterAudio audio) { int num = 0; FieldInfo[] soundFields = GetSoundFields(((object)behaviour).GetType()); for (int i = 0; i < soundFields.Length; i++) { object value = soundFields[i].GetValue(behaviour); Sound val = (Sound)((value is Sound) ? value : null); if (val != null) { num += Register(val, audio); } else { if (!(value is IEnumerable<Sound> enumerable)) { continue; } foreach (Sound item in enumerable) { num += Register(item, audio); } } } return num; } private static int Register(Sound sound, MonsterAudio audio) { if (sound == null || Registered.TryGetValue(sound, out var _)) { return 0; } Registered.Add(sound, audio); if ((Object)(object)sound.Source != (Object)null) { float range = audio.Range; AudioSource source = sound.Source; source.minDistance *= range; AudioSource source2 = sound.Source; source2.maxDistance *= range; AttachGain(((Component)sound.Source).gameObject, audio); } return 1; } public static void AttachGain(GameObject go, MonsterAudio audio) { GainFilter gainFilter = go.GetComponent<GainFilter>(); if ((Object)(object)gainFilter == (Object)null) { gainFilter = go.AddComponent<GainFilter>(); } gainFilter.Audio = audio; } private static FieldInfo[] GetSoundFields(Type type) { if (FieldCache.TryGetValue(type, out var value)) { return value; } List<FieldInfo> list = new List<FieldInfo>(); Type type2 = type; while (type2 != null && type2 != typeof(MonoBehaviour)) { FieldInfo[] fields = type2.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { Type fieldType = fieldInfo.FieldType; if (fieldType == typeof(Sound) || typeof(IEnumerable<Sound>).IsAssignableFrom(fieldType)) { list.Add(fieldInfo); } } type2 = type2.BaseType; } value = list.ToArray(); FieldCache[type] = value; return value; } } internal class GainFilter : MonoBehaviour { private const float Knee = 0.7f; internal volatile MonsterAudio Audio; private void OnAudioFilterRead(float[] data, int channels) { MonsterAudio audio = Audio; if (audio == null) { return; } float gain = audio.Gain; if (Mathf.Abs(gain - 1f) < 0.001f) { return; } for (int i = 0; i < data.Length; i++) { float num = data[i] * gain; float num2 = ((num < 0f) ? (0f - num) : num); if (num2 > 0.7f) { float num3 = 0.7f + 0.3f * (float)Math.Tanh((num2 - 0.7f) / 0.3f); num = ((num < 0f) ? (0f - num3) : num3); } data[i] = num; } } } internal static class Patches { [HarmonyPatch(typeof(EnemyParent), "Awake")] [HarmonyPostfix] private static void EnemyParentAwake(EnemyParent __instance) { try { EnemySounds.RegisterEnemy(__instance); } catch (Exception arg) { Plugin.Log.LogError((object)$"Failed to register sounds on {((Object)__instance).name}: {arg}"); } } [HarmonyPatch(typeof(Sound), "Play", new Type[] { typeof(Vector3), typeof(float), typeof(float), typeof(float), typeof(float) })] [HarmonyPrefix] private static void PlayPrefix(Sound __instance, ref float falloffMultiplier) { if (!((Object)(object)__instance.Source != (Object)null)) { MonsterAudio monsterAudio = EnemySounds.Find(__instance); if (monsterAudio != null) { falloffMultiplier *= monsterAudio.Range; } } } [HarmonyPatch(typeof(Sound), "Play", new Type[] { typeof(Vector3), typeof(float), typeof(float), typeof(float), typeof(float) })] [HarmonyPostfix] private static void PlayPostfix(Sound __instance, AudioSource __result) { if (!((Object)(object)__result == (Object)null)) { MonsterAudio monsterAudio = EnemySounds.Find(__instance); if (monsterAudio != null) { EnemySounds.AttachGain(((Component)__result).gameObject, monsterAudio); } } } } }