using 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
{
}
}