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 Megaphone v1.2.3
plugins/ESN.Megaphone/ESN.Megaphone.dll
Decompiled 10 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ESN.Megaphone.NetcodePatcher; using GameNetcodeStuff; using HarmonyLib; using LethalLib.Modules; using Megaphone.Items; using Megaphone.Patches; using Megaphone.Scripts; using Microsoft.CodeAnalysis; using Unity.Netcode; 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: AssemblyCompany("ESN.Megaphone")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.2.3.0")] [assembly: AssemblyInformationalVersion("1.2.3+6553b1e478f8abd9e4961d5397060f3596e90eb7")] [assembly: AssemblyProduct("Megaphone")] [assembly: AssemblyTitle("ESN.Megaphone")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] internal class <Module> { static <Module>() { } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 Megaphone { internal class Commands { public static string DefaultCMD() { return "Not Yet Implemented"; } } public class MyConfig { public const int SIREN_NOISE_ID = 1880; private static ConfigEntry<bool> configCanBuy; private static ConfigEntry<bool> configIsScrap; private static ConfigEntry<int> configRarity; private static ConfigEntry<int> configPrice; private static ConfigEntry<float> configHearDistance; private static ConfigEntry<float> configSirenHearDistance; private static ConfigEntry<float> configSFXHearDistance; private static ConfigEntry<float> configSFXEnemyHearDistance; private static ConfigEntry<float> configLoudVoiceVolume; private static ConfigEntry<float> configSFXVolume; private static ConfigEntry<float> configRobotVoicePitch; private static ConfigEntry<int> configScrapMinPrice; private static ConfigEntry<int> configScrapMaxPrice; public static bool CanBuy => configCanBuy.Value; public static bool IsScrap => configIsScrap.Value; public static int Rarity => (int)MathF.Max(0f, MathF.Min(100f, configRarity.Value)); public static int Price => (int)MathF.Max(0f, configPrice.Value); public static float HearDistance { get { float num = configHearDistance.Value; if (num <= 0f) { num = 1f; } return num; } } public static float SirenHearDistance { get { float num = configSirenHearDistance.Value; if (num <= 0f) { num = 1f; } return num; } } public static float SFXHearDistance { get { float num = configSFXHearDistance.Value; if (num <= 0f) { num = 1f; } return num; } } public static float SFXEnemyHearDistance { get { float num = configSFXEnemyHearDistance.Value; if (num <= 0f) { num = 1f; } return num; } } public static float LoudVoiceVolume { get { float value = configLoudVoiceVolume.Value; value = MathF.Min(1.2f, value); return MathF.Max(0f, value); } } public static float SFXVolume { get { float value = configSFXVolume.Value; value = MathF.Min(1.2f, value); return MathF.Max(0f, value); } } public static float RobotVoicePitch { get { float value = configRobotVoicePitch.Value; value = MathF.Min(2f, value); return MathF.Max(0.5f, value); } } public static int ScrapMinValue => (int)MathF.Max(0f, configScrapMinPrice.Value); public static int ScrapMaxValue => (int)MathF.Max(ScrapMinValue, configScrapMaxPrice.Value); public static void Setup(BaseUnityPlugin p) { configCanBuy = p.Config.Bind<bool>("Item", "CanBeBought", false, "Can the item be bought from the terminal.\r\n[Client side]"); configIsScrap = p.Config.Bind<bool>("Item", "IsScrap", true, "Can the item spawn in interiors.\r\nNot recommended to have both this and 'CanBuy' set to true.\r\n[Host side]"); configRarity = p.Config.Bind<int>("Item", "ScrapRarity", 10, "Rarity of the object. 0 is never, 100 is often.\r\nMin: 0 Max: 100\r\n[Host side]"); configPrice = p.Config.Bind<int>("Item", "Price", 60, "Buy cost of the item.\r\nMin: 0\r\n[Client side]"); configHearDistance = p.Config.Bind<float>("Audio.Distances", "HearingDistanceModifier", 2f, "Change the distance multiplier the voices can be heard from when talking in\r\n'loud mode' (switch with Q).\r\nMin: 0.0\r\n[Client side]"); configSirenHearDistance = p.Config.Bind<float>("Audio.Distances", "SirenHearingDistanceModifier", 2f, "Change the distance multiplier the siren can be heard from (switch with Q).\r\nMin: 0.0\r\n[Client side]"); configSFXHearDistance = p.Config.Bind<float>("Audio.Distances", "SFXHearingDistanceModifier", 2f, "Change the distance multiplier the SFX can be heard from.\r\nMin: 0.0\r\n[Client side]"); configSFXEnemyHearDistance = p.Config.Bind<float>("Audio.Distances", "EnemySFXHearingDistanceModifier", 1f, "Change the distance multiplier the SFX can be heard from by enemies.\r\nThis multiplier is applied after the base hear distance modifier.\r\nMin: 0.0\r\n[Client side]"); configLoudVoiceVolume = p.Config.Bind<float>("Audio.Volume", "LoudVoiceVolume", 0.9f, "Volume multiplier of the 'Loud voice' filter. Recommended below 1.0 because\r\nthe distortion increases the volume, 1.0 is already higher than normal voice.\r\nMin: 0.0 Max: 1.2\r\n[Client side]"); configSFXVolume = p.Config.Bind<float>("Audio.Volume", "SFXVolume", 1f, "Volume multiplier of the SFX sounds.\r\nMin: 0.0 Max: 1.2\r\n[Client side]"); configRobotVoicePitch = p.Config.Bind<float>("Audio.Pitch", "RobotVoicePitch", 0.9f, "Set the pitch for the robot voice.\r\nMin: 0.5 Max: 2.0\r\n[Client side]"); configScrapMinPrice = p.Config.Bind<int>("Scrap", "ScrapMinPrince", 30, "Set the minimum scrap sell value.\r\nMin: 0\r\n[Host side]"); configScrapMaxPrice = p.Config.Bind<int>("Scrap", "ScrapMaxPrince", 60, "Set the maximum scrap sell value.\r\nMin: <ScrapMinPrince>\r\n[Host side]"); } } public class MyLog { public static void LogInfo(string message) { Plugin.Logger.LogInfo((object)message); } public static void LogWarning(string message) { Plugin.Logger.LogWarning((object)message); } public static void LogError(string message) { Plugin.Logger.LogError((object)message); } public static void LogDebug(string message) { } } [HarmonyPatch] public class NetworkObjectManager { private static GameObject networkPrefab; [HarmonyPostfix] [HarmonyPatch(typeof(GameNetworkManager), "Start")] public static void Init() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown if (!((Object)(object)networkPrefab != (Object)null)) { networkPrefab = (GameObject)Plugin.Assets_network.LoadAsset("Assets/Network/ExampleNetworkHandler.prefab"); NetworkManager.Singleton.AddNetworkPrefab(networkPrefab); MyLog.LogDebug("ExampleNetworkHandler successfully added"); } } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "Awake")] private static void SpawnNetworkHandler() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) { GameObject val = Object.Instantiate<GameObject>(networkPrefab, Vector3.zero, Quaternion.identity); val.GetComponent<NetworkObject>().Spawn(false); MyLog.LogDebug("NetworkObject successfully spawned"); } } } [BepInPlugin("ESN.Megaphone", "Megaphone", "1.2.3")] [BepInDependency("atomic.terminalapi", "1.5.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string ASSET_PATH_MEGAPHONE_ITEM = "Assets/Megaphone/MegaphoneItem.asset"; public const string ASSET_PATH_MEGAPHONE_SFX = "Assets/Megaphone/sfx.mp3"; public const string ASSET_PATH_MEGAPHONE_SIREN = "Assets/Megaphone/siren.mp3"; public const string ASSET_PATH_MEGAPHONE_TNODE = "Assets/Megaphone/iTerminalNodeMegaphone.asset"; public const string ASSET_PATH_NET_HANDLER = "Assets/Network/ExampleNetworkHandler.prefab"; public static AssetBundle Assets; public static AssetBundle Assets_network; public static Plugin Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } internal static Harmony Harmony { get; set; } private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; Instance = this; MyConfig.Setup((BaseUnityPlugin)(object)this); LoadAssets(); Patch(); CreateTerminalCommands(); CreateItems(); Logger.LogInfo((object)"ESN.Megaphone v1.2.3 has loaded!"); } private static void CreateItems() { Item val = Assets.LoadAsset<Item>("Assets/Megaphone/MegaphoneItem.asset"); val.minValue = (int)Mathf.Round((float)MyConfig.ScrapMinValue / 0.4f); val.maxValue = (int)Mathf.Round((float)MyConfig.ScrapMaxValue / 0.4f); Logger.LogDebug((object)("Found item " + val.itemName)); GrabbableObject val2 = (GrabbableObject)(object)val.spawnPrefab.AddComponent<MegaphoneItem>(); Logger.LogDebug((object)$"Found script {val2}"); val2.grabbable = true; val2.isInFactory = true; val2.itemProperties = val; val2.grabbableToEnemies = true; MyLog.LogDebug("Found item '" + val.itemName + "'"); NetworkPrefabs.RegisterNetworkPrefab(val.spawnPrefab); if (MyConfig.IsScrap) { Items.RegisterScrap(val, MyConfig.Rarity, (LevelTypes)(-1)); } if (MyConfig.CanBuy) { TerminalNode val3 = Assets.LoadAsset<TerminalNode>("Assets/Megaphone/iTerminalNodeMegaphone.asset"); Items.RegisterShopItem(val, (TerminalNode)null, (TerminalNode)null, val3, MyConfig.Price); } else { Items.RegisterItem(val); } } private static void LoadAssets() { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); Assets = AssetBundle.LoadFromFile(Path.Combine(directoryName, "assets/esn_megaphone")); if ((Object)(object)Assets == (Object)null) { Logger.LogError((object)"Failed to load custom assets."); return; } Assets_network = AssetBundle.LoadFromFile(Path.Combine(directoryName, "assets/esn_network")); if ((Object)(object)Assets == (Object)null) { Logger.LogError((object)"Failed to load network assets."); return; } Logger.LogDebug((object)"Assets loaded"); string[] allAssetNames = Assets.GetAllAssetNames(); string[] array = allAssetNames; foreach (string text in array) { Logger.LogDebug((object)(text ?? "")); } allAssetNames = Assets_network.GetAllAssetNames(); string[] array2 = allAssetNames; foreach (string text2 in array2) { Logger.LogDebug((object)(text2 ?? "")); } AudioMod.LoadAssets(); } private static void CreateTerminalCommands() { } private static void NetcodePatcher() { Logger.LogDebug((object)"Patching netcode..."); Type[] types = Assembly.GetExecutingAssembly().GetTypes(); Type[] array = types; foreach (Type type in array) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); MethodInfo[] array2 = methods; foreach (MethodInfo methodInfo in array2) { object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false); if (customAttributes.Length != 0) { methodInfo.Invoke(null, null); } } } Logger.LogDebug((object)"Patching netcode... complete"); } internal void Patch() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown if (Harmony == null) { Harmony = new Harmony("ESN.Megaphone"); } Logger.LogDebug((object)"Patching..."); Harmony.PatchAll(typeof(AudioPatch)); Harmony.PatchAll(typeof(BlobPatch)); Harmony.PatchAll(typeof(PufferPatch)); Harmony.PatchAll(typeof(NetworkObjectManager)); NetcodePatcher(); Logger.LogDebug((object)"Finished patching!"); } internal static void Unpatch() { Logger.LogDebug((object)"Unpatching..."); Harmony harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } Logger.LogDebug((object)"Finished unpatching!"); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "ESN.Megaphone"; public const string PLUGIN_NAME = "Megaphone"; public const string PLUGIN_VERSION = "1.2.3"; } } namespace Megaphone.Scripts { public class AudioFiltering { public MegaphoneItem parent; public PlayerControllerB player; private const AudioFilteringMode endNode = AudioFilteringMode.Siren; private AudioFilteringMode _mode; public bool active; public AudioFilteringMode Mode => _mode; private AudioFiltering() { } public AudioFiltering(MegaphoneItem parent) { this.parent = parent; } public bool NextFilterMode(bool enable) { AudioFilteringMode newMode = ((_mode != AudioFilteringMode.Siren) ? (_mode + 1) : AudioFilteringMode.Robot); bool flag = SetFilterMode(newMode, enable); if (flag) { MyLog.LogInfo("Switched to mode " + Enum.GetName(typeof(AudioFilteringMode), _mode)); } else { MyLog.LogError("Unable to switch to mode " + Enum.GetName(typeof(AudioFilteringMode), _mode)); } return flag; } public bool SetFilterMode(AudioFilteringMode newMode, bool enable) { if (active && !Disable()) { return false; } _mode = newMode; if (enable) { return Enable(); } return true; } public bool Enable() { MyLog.LogDebug("Enabling..."); if (active) { MyLog.LogDebug("Already enabled..."); return true; } active = true; switch (_mode) { case AudioFilteringMode.Robot: AudioMod.EnableRobotVoice(player, on: true); break; case AudioFilteringMode.Loud: AudioMod.EnableLoudVoice(player, on: true); break; case AudioFilteringMode.HighPitch: AudioMod.EnableHighPitch(player, on: true); break; case AudioFilteringMode.LowPitch: AudioMod.EnableLowPitch(player, on: true); break; case AudioFilteringMode.Siren: AudioMod.PlaySFX(parent, AudioMod.Siren, 0, 1880); break; default: return false; } return true; } public bool Disable() { MyLog.LogDebug("Disabling..."); if (!active) { MyLog.LogDebug("Already disabled..."); return true; } switch (_mode) { case AudioFilteringMode.Robot: AudioMod.EnableRobotVoice(player, on: false); break; case AudioFilteringMode.Loud: AudioMod.EnableLoudVoice(player, on: false); break; case AudioFilteringMode.HighPitch: AudioMod.EnableHighPitch(player, on: false); break; case AudioFilteringMode.LowPitch: AudioMod.EnableLowPitch(player, on: false); break; case AudioFilteringMode.Siren: AudioMod.StopSFX(parent); break; default: return false; } active = false; return true; } public void PlaySirenAudibleNoiseIfApplicable(MegaphoneItem item, int counter) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (active && _mode == AudioFilteringMode.Siren) { RoundManager.Instance.PlayAudibleNoise(((Component)item).transform.position, MyConfig.SFXHearDistance * MyConfig.SFXEnemyHearDistance * 50f, 1f, counter, ((GrabbableObject)item).isInElevator && StartOfRound.Instance.hangarDoorsClosed, 1880); } } } public enum AudioFilteringMode { Robot, Loud, HighPitch, LowPitch, Siren } public class AudioMod { protected static List<ulong> setupPlayersID = new List<ulong>(); protected static AudioClip sfx; protected static AudioClip siren; public static AudioClip SFX => sfx; public static AudioClip Siren => siren; public static void LoadAssets() { sfx = Plugin.Assets.LoadAsset<AudioClip>("Assets/Megaphone/sfx.mp3"); siren = Plugin.Assets.LoadAsset<AudioClip>("Assets/Megaphone/siren.mp3"); } public static void RegisterNewPlayer(PlayerControllerB player) { if (setupPlayersID.Contains(player.playerClientId)) { setupPlayersID.Remove(player.playerClientId); } } public static bool SetupGameobjects(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { MyLog.LogError("Unable to continue, player is null... Owner must re-equip the item"); return false; } if (setupPlayersID.Contains(player.playerClientId)) { return true; } setupPlayersID.Add(player.actualClientId); MyLog.LogDebug($"Setting gameobjects for player {((Object)player).name} - {player.playerClientId}"); MyLog.LogInfo($"Settings up audio components for player {player.playerUsername} ; ID({player.playerClientId})"); AudioSource currentVoiceChatAudioSource = player.currentVoiceChatAudioSource; if ((Object)(object)currentVoiceChatAudioSource == (Object)null) { MyLog.LogInfo("No AudioSource found..."); return false; } AudioEchoFilter component = ((Component)currentVoiceChatAudioSource).GetComponent<AudioEchoFilter>(); if ((Object)(object)component == (Object)null) { MyLog.LogDebug("AudioEchoFilter missing"); ((Component)currentVoiceChatAudioSource).gameObject.AddComponent<AudioEchoFilter>(); component = ((Component)currentVoiceChatAudioSource).GetComponent<AudioEchoFilter>(); } ((Behaviour)component).enabled = false; MyLog.LogDebug("Echo ready"); AudioHighPassFilter component2 = ((Component)currentVoiceChatAudioSource).GetComponent<AudioHighPassFilter>(); if ((Object)(object)component2 == (Object)null) { MyLog.LogDebug("AudioHighPassFilter missing"); ((Component)currentVoiceChatAudioSource).gameObject.AddComponent<AudioHighPassFilter>(); component2 = ((Component)currentVoiceChatAudioSource).GetComponent<AudioHighPassFilter>(); } ((Behaviour)component2).enabled = false; MyLog.LogDebug("HighPass ready"); AudioDistortionFilter component3 = ((Component)currentVoiceChatAudioSource).GetComponent<AudioDistortionFilter>(); if ((Object)(object)component3 == (Object)null) { MyLog.LogDebug("AudioDistortionFilter missing"); ((Component)currentVoiceChatAudioSource).gameObject.AddComponent<AudioDistortionFilter>(); component3 = ((Component)currentVoiceChatAudioSource).GetComponent<AudioDistortionFilter>(); } ((Behaviour)component3).enabled = false; MyLog.LogDebug("Distortion ready"); AudioChorusFilter component4 = ((Component)currentVoiceChatAudioSource).GetComponent<AudioChorusFilter>(); if ((Object)(object)component4 == (Object)null) { MyLog.LogDebug("AudioHighPassFilter missing"); ((Component)currentVoiceChatAudioSource).gameObject.AddComponent<AudioChorusFilter>(); component4 = ((Component)currentVoiceChatAudioSource).GetComponent<AudioChorusFilter>(); } ((Behaviour)component4).enabled = false; MyLog.LogDebug("Chorus ready"); MyLog.LogInfo($"Player {player.playerUsername} ; ID({player.playerClientId}) ready !"); return true; } protected static bool AreAllComponentsAdded(AudioSource src) { AudioEchoFilter component = ((Component)src).GetComponent<AudioEchoFilter>(); OccludeAudio component2 = ((Component)src).GetComponent<OccludeAudio>(); AudioHighPassFilter component3 = ((Component)src).GetComponent<AudioHighPassFilter>(); AudioChorusFilter component4 = ((Component)src).GetComponent<AudioChorusFilter>(); AudioDistortionFilter component5 = ((Component)src).GetComponent<AudioDistortionFilter>(); if ((Object)(object)component == (Object)null) { MyLog.LogError("AudioEchoFilter missing"); return false; } if ((Object)(object)component2 == (Object)null) { MyLog.LogError("OccludeAudio missing"); return false; } if ((Object)(object)component3 == (Object)null) { MyLog.LogError("AudioHighPassFilter missing"); return false; } if ((Object)(object)component4 == (Object)null) { MyLog.LogError("AudioChorusFilter missing"); return false; } if ((Object)(object)component5 == (Object)null) { MyLog.LogError("AudioDistortionFilter missing"); return false; } return true; } protected static bool CheckComponents(PlayerControllerB player) { AudioSource currentVoiceChatAudioSource = player.currentVoiceChatAudioSource; if ((Object)(object)currentVoiceChatAudioSource == (Object)null) { return false; } if (!AreAllComponentsAdded(currentVoiceChatAudioSource)) { RegisterNewPlayer(player); return SetupGameobjects(player); } return true; } internal static bool EnableRobotVoice(PlayerControllerB player, bool on) { MyLog.LogInfo((on ? "Enabling" : "Disabling") + " robot voice for player " + player.playerUsername); if (!CheckComponents(player)) { return false; } AudioSource currentVoiceChatAudioSource = player.currentVoiceChatAudioSource; AudioEchoFilter component = ((Component)currentVoiceChatAudioSource).GetComponent<AudioEchoFilter>(); AudioHighPassFilter component2 = ((Component)currentVoiceChatAudioSource).GetComponent<AudioHighPassFilter>(); AudioChorusFilter component3 = ((Component)currentVoiceChatAudioSource).GetComponent<AudioChorusFilter>(); if (on) { component.delay = 10f; component.decayRatio = 0.75f; component2.cutoffFrequency = 500f; component3.dryMix = 0.75f; float wetMix = (component3.wetMix2 = 0.75f); component3.wetMix1 = wetMix; component3.delay = 40f; component3.depth = 0.7f; component3.rate = 1.2f; } bool flag2 = (((Behaviour)component3).enabled = on); bool enabled = (((Behaviour)component2).enabled = flag2); ((Behaviour)component).enabled = enabled; AudioPatch.playersPitchTargets[player.playerClientId] = (on ? MyConfig.RobotVoicePitch : (-1f)); return true; } internal static bool EnableLoudVoice(PlayerControllerB player, bool on) { MyLog.LogInfo((on ? "Enabling" : "Disabling") + " loud voice for player " + player.playerUsername); if (!CheckComponents(player)) { return false; } AudioSource currentVoiceChatAudioSource = player.currentVoiceChatAudioSource; AudioEchoFilter component = ((Component)currentVoiceChatAudioSource).GetComponent<AudioEchoFilter>(); OccludeAudio component2 = ((Component)currentVoiceChatAudioSource).GetComponent<OccludeAudio>(); AudioHighPassFilter component3 = ((Component)currentVoiceChatAudioSource).GetComponent<AudioHighPassFilter>(); AudioChorusFilter component4 = ((Component)currentVoiceChatAudioSource).GetComponent<AudioChorusFilter>(); AudioDistortionFilter component5 = ((Component)currentVoiceChatAudioSource).GetComponent<AudioDistortionFilter>(); ((Behaviour)component).enabled = false; ((Behaviour)component4).enabled = false; if (on) { component3.cutoffFrequency = 800f; component5.distortionLevel = 0.9f; } currentVoiceChatAudioSource.volume = (on ? MyConfig.LoudVoiceVolume : 1f); player.voiceMuffledByEnemy = true; component2.overridingLowPass = on; component2.lowPassOverride = (on ? 3500f : 20000f); bool enabled = (((Behaviour)component5).enabled = on); ((Behaviour)component3).enabled = enabled; AudioPatch.EnableHighpass(player.actualClientId, on); currentVoiceChatAudioSource.maxDistance = (on ? (MyConfig.HearDistance * 50f) : 50f); return true; } internal static void EnableHighPitch(PlayerControllerB player, bool on) { MyLog.LogInfo((on ? "Enabling" : "Disabling") + " high pitch voice for player " + player.playerUsername); AudioPatch.playersPitchTargets[player.playerClientId] = (on ? 2 : (-1)); } internal static void EnableLowPitch(PlayerControllerB player, bool on) { MyLog.LogInfo((on ? "Enabling" : "Disabling") + " low pitch voice for player " + player.playerUsername); AudioPatch.playersPitchTargets[player.playerClientId] = (on ? 0.5f : (-1f)); } internal static bool PlaySFX(MegaphoneItem item, AudioClip sound, int counter = 0, int noiseID = 0) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)sound == (Object)null) { MyLog.LogError("SFX is null"); return false; } MyLog.LogInfo("Playing SFX..."); AudioSource component = ((Component)item).GetComponent<AudioSource>(); if ((Object)(object)component == (Object)null) { MyLog.LogError("No AudioSource to play SFX..."); return false; } component.maxDistance = MyConfig.SFXHearDistance * 50f; component.volume = MyConfig.SFXVolume; component.PlayOneShot(sound); RoundManager.Instance.PlayAudibleNoise(((Component)item).transform.position, component.maxDistance * MyConfig.SFXEnemyHearDistance, 1f, counter, ((GrabbableObject)item).isInElevator && StartOfRound.Instance.hangarDoorsClosed, noiseID); return true; } internal static bool StopSFX(MegaphoneItem item) { if ((Object)(object)sfx == (Object)null) { MyLog.LogError("SFX is null"); return false; } MyLog.LogInfo("Stopping SFX..."); AudioSource component = ((Component)item).GetComponent<AudioSource>(); if ((Object)(object)component == (Object)null) { MyLog.LogError("No AudioSource to play SFX..."); return false; } component.maxDistance = 50f; component.volume = 1f; component.Stop(true); return true; } } } namespace Megaphone.Patches { [HarmonyPatch] public class AudioPatch { public static List<ulong> EnableHighPassIndexes = new List<ulong>(); public static Dictionary<ulong, float> playersPitchTargets = new Dictionary<ulong, float>(); public static void EnableHighpass(ulong index, bool on) { if (on) { EnableHighPassIndexes.Add(index); } else if (EnableHighPassIndexes.Contains(index)) { EnableHighPassIndexes.Remove(index); } } [HarmonyPatch(typeof(StartOfRound), "OnPlayerConnectedClientRpc")] [HarmonyPostfix] private static void ConnectClientToPlayerObjectPatch(StartOfRound __instance, ulong clientId, int connectedPlayers, ulong[] connectedPlayerIdsOrdered, int assignedPlayerObjectId, int serverMoneyAmount, int levelID, int profitQuota, int timeUntilDeadline, int quotaFulfilled, int randomSeed, bool isChallenge) { PlayerControllerB val = __instance.allPlayerScripts[assignedPlayerObjectId]; MyLog.LogDebug("Player " + ((Object)val).name + " connected"); AudioMod.RegisterNewPlayer(val); } [HarmonyPatch(typeof(StartOfRound), "UpdatePlayerVoiceEffects")] [HarmonyPostfix] private static void UpdatePlayerVoiceEffectsPostfix(StartOfRound __instance) { foreach (ulong enableHighPassIndex in EnableHighPassIndexes) { AudioSource currentVoiceChatAudioSource = __instance.allPlayerScripts[enableHighPassIndex].currentVoiceChatAudioSource; if ((Object)(object)currentVoiceChatAudioSource == (Object)null) { MyLog.LogError("voiceChatAudioSource is null..."); } ((Behaviour)((Component)currentVoiceChatAudioSource).GetComponent<AudioHighPassFilter>()).enabled = true; } } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PlayerControllerBUpdatePostFix(PlayerControllerB __instance) { if ((Object)(object)__instance == (Object)null) { return; } ulong playerClientId = __instance.playerClientId; if (playersPitchTargets.ContainsKey(playerClientId)) { float num = playersPitchTargets[playerClientId]; if (!(num < 0.5f) && !(num > 2f) && num != 1f) { MyLog.LogDebug($"Overwriting pitch for {playerClientId} to {num}"); SoundManager.Instance.playerVoicePitchTargets[playerClientId] = num; } } } } [HarmonyPatch(typeof(BlobAI))] public class BlobPatch { [HarmonyPatch("DetectNoise")] [HarmonyPostfix] private static void DetectNoisePatch(BlobAI __instance, Vector3 noisePosition, float noiseLoudness, int timesPlayedInOneSpot = 0, int noiseID = 0) { //IL_000f: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (noiseID == 1880 && !Physics.Linecast(((Component)__instance).transform.position, noisePosition, StartOfRound.Instance.collidersAndRoomMask) && !((double)Vector3.Distance(((Component)__instance).transform.position, noisePosition) >= 12.0)) { __instance.tamedTimer = 2f; } } } [HarmonyPatch(typeof(PufferAI))] public class PufferPatch { [HarmonyPatch("DetectNoise")] [HarmonyPostfix] private static void DetectNoisePatch(PufferAI __instance, Vector3 noisePosition, float noiseLoudness, int timesPlayedInOneSpot = 0, int noiseID = 0) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) if (noiseID != 1880) { return; } float num = Vector3.Distance(noisePosition, ((Component)__instance).transform.position); if (!(num > 25f)) { if (Physics.Linecast(((EnemyAI)__instance).eye.position, noisePosition, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1)) { noiseLoudness /= 2f; } if (!(noiseLoudness / num <= 0.045f) && !(__instance.timeSinceLookingAtNoise <= 4f)) { __instance.timeSinceLookingAtNoise = 0f; __instance.lookAtNoise = noisePosition; } } } } } namespace Megaphone.Items { public class MegaphoneItem : GrabbableObject { public AudioFiltering audioFiltering; protected bool isSynced; protected int TimesPlayedWithoutTurnedOff; public override void OnNetworkSpawn() { MyLog.LogDebug("OnNetworkSpawn() called"); ((NetworkBehaviour)this).OnNetworkSpawn(); } public override void Start() { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) MyLog.LogDebug("MegaphoneItem item created !"); ((GrabbableObject)this).Start(); base.itemProperties.itemIsTrigger = false; base.itemProperties.batteryUsage = 120f; base.itemProperties.syncUseFunction = true; base.itemProperties.syncInteractLRFunction = true; base.itemProperties.syncDiscardFunction = true; base.itemProperties.holdButtonUse = true; base.insertedBattery.charge = 1f; base.itemProperties.positionOffset = new Vector3(0.08f, 0.2f, -0.1f); base.itemProperties.rotationOffset = new Vector3(-90f, 180f, 38f); TimesPlayedWithoutTurnedOff = 0; audioFiltering = new AudioFiltering(this); isSynced = NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer; } public override void ItemInteractLeftRight(bool right) { ((GrabbableObject)this).ItemInteractLeftRight(right); if (!right) { audioFiltering.NextFilterMode(base.isBeingUsed); UpdateTooltips(); } } public override void PocketItem() { MyLog.LogDebug("PocketItem()"); if ((Object)(object)base.playerHeldBy != (Object)null) { base.playerHeldBy.equippedUsableItemQE = false; base.isBeingUsed = false; audioFiltering.Disable(); } ((GrabbableObject)this).PocketItem(); } public override void EquipItem() { MyLog.LogDebug("Equipped"); ((GrabbableObject)this).EquipItem(); audioFiltering.player = base.playerHeldBy; if ((Object)(object)base.playerHeldBy == (Object)null) { MyLog.LogWarning("Unable to continue, player is null... Owner must re-equip the item"); return; } base.playerHeldBy.equippedUsableItemQE = true; AudioMod.SetupGameobjects(base.playerHeldBy); UpdateTooltips(); if (!isSynced) { MyLog.LogDebug("Syncing mode..."); SyncAudioModeToClientsServerRpc(); } } [ServerRpc(RequireOwnership = false)] public void SyncAudioModeToClientsServerRpc() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager != null && networkManager.IsListening) { if ((int)((NetworkBehaviour)this).__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { ServerRpcParams val = default(ServerRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(358012765u, val, (RpcDelivery)0); ((NetworkBehaviour)this).__endSendServerRpc(ref val2, 358012765u, val, (RpcDelivery)0); } if ((int)((NetworkBehaviour)this).__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost) && (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer)) { MyLog.LogInfo($"Sending RPC... mode='{audioFiltering.Mode}'"); SyncAudioModeClientRpc(audioFiltering.Mode); } } } [ClientRpc] public void SyncAudioModeClientRpc(AudioFilteringMode mode) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)((NetworkBehaviour)this).__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3614960129u, val, (RpcDelivery)0); ((FastBufferWriter)(ref val2)).WriteValueSafe<AudioFilteringMode>(ref mode, default(ForEnums)); ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3614960129u, val, (RpcDelivery)0); } if ((int)((NetworkBehaviour)this).__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost)) { MyLog.LogDebug("EventClientRpc() called"); MyLog.LogDebug($"isSynced={isSynced}"); if (!isSynced) { isSynced = true; audioFiltering.SetFilterMode(mode, enable: false); UpdateTooltips(); MyLog.LogInfo($"Synced to mode '{mode}'"); } } } protected void UpdateTooltips() { if (((NetworkBehaviour)this).IsOwner) { string text = audioFiltering.Mode switch { AudioFilteringMode.Robot => "Robot", AudioFilteringMode.Siren => "Siren", AudioFilteringMode.Loud => "Loud", AudioFilteringMode.HighPitch => "High Pitch", AudioFilteringMode.LowPitch => "Low Pitch", _ => "Unknown", }; string[] toolTips = new string[2] { "Change mode : [Q]", "Mode : " + text }; base.itemProperties.toolTips = toolTips; HUDManager.Instance.ChangeControlTipMultiple(base.itemProperties.toolTips, true, base.itemProperties); } } public override void DiscardItem() { MyLog.LogDebug("DiscardItem()"); base.playerHeldBy.equippedUsableItemQE = false; audioFiltering.Disable(); if (base.playerHeldBy.isPlayerDead && base.isBeingUsed) { AudioMod.PlaySFX(this, AudioMod.SFX, TimesPlayedWithoutTurnedOff); } ((GrabbableObject)this).DiscardItem(); } public override void Update() { ((GrabbableObject)this).Update(); if (base.isBeingUsed) { TimesPlayedWithoutTurnedOff++; audioFiltering.PlaySirenAudibleNoiseIfApplicable(this, TimesPlayedWithoutTurnedOff); } else { TimesPlayedWithoutTurnedOff = 0; } } public override void ItemActivate(bool used, bool buttonDown = true) { SwitchOnOff(buttonDown); } public override void UseUpBatteries() { MyLog.LogDebug("UseUpBatteries()"); SwitchOnOff(on: false); ((GrabbableObject)this).UseUpBatteries(); } public void SwitchOnOff(bool on) { MyLog.LogDebug($"SwitchOnOff({on})"); AudioMod.SetupGameobjects(base.playerHeldBy); base.isBeingUsed = on; if (!((NetworkBehaviour)this).IsOwner) { if ((Object)(object)base.playerHeldBy != (Object)null) { if (!(on ? audioFiltering.Enable() : audioFiltering.Disable())) { MyLog.LogError("Unable to " + (on ? "enable" : "disable")); } } else { MyLog.LogWarning("playerHeldBy: null"); } } else { MyLog.LogInfo("Megaphone click by owner"); if (audioFiltering.Mode == AudioFilteringMode.Siren && !(on ? audioFiltering.Enable() : audioFiltering.Disable())) { MyLog.LogError("Unable to " + (on ? "enable" : "disable")); } } } protected override void __initializeVariables() { ((GrabbableObject)this).__initializeVariables(); } [RuntimeInitializeOnLoadMethod] internal static void InitializeRPCS_MegaphoneItem() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown NetworkManager.__rpc_func_table.Add(358012765u, new RpcReceiveHandler(__rpc_handler_358012765)); NetworkManager.__rpc_func_table.Add(3614960129u, new RpcReceiveHandler(__rpc_handler_3614960129)); } private static void __rpc_handler_358012765(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { target.__rpc_exec_stage = (__RpcExecStage)1; ((MegaphoneItem)(object)target).SyncAudioModeToClientsServerRpc(); target.__rpc_exec_stage = (__RpcExecStage)0; } } private static void __rpc_handler_3614960129(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { AudioFilteringMode mode = default(AudioFilteringMode); ((FastBufferReader)(ref reader)).ReadValueSafe<AudioFilteringMode>(ref mode, default(ForEnums)); target.__rpc_exec_stage = (__RpcExecStage)2; ((MegaphoneItem)(object)target).SyncAudioModeClientRpc(mode); target.__rpc_exec_stage = (__RpcExecStage)0; } } [MethodImpl(MethodImplOptions.NoInlining)] protected internal override string __getTypeName() { return "MegaphoneItem"; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } } namespace ESN.Megaphone.NetcodePatcher { [AttributeUsage(AttributeTargets.Module)] internal class NetcodePatchedAssemblyAttribute : Attribute { } }