Decompiled source of ReverbOnDeath v1.0.1

ReverbOnDeath.dll

Decompiled 10 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using Dissonance.Audio.Playback;
using GameNetcodeStuff;
using HarmonyLib;
using ReverbOnDeath.Configuration;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("ReverbOnDeath")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Adds a heavy reverb effect to the final sounds made before death.")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("ReverbOnDeath")]
[assembly: AssemblyTitle("ReverbOnDeath")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
namespace ReverbOnDeath
{
	[BepInPlugin("ReverbOnDeath", "ReverbOnDeath", "1.0.1")]
	public class Plugin : BaseUnityPlugin
	{
		private static Plugin Instance;

		private readonly Harmony harmony = new Harmony("ReverbOnDeath");

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin ReverbOnDeath is loaded!");
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "ReverbOnDeath";

		public const string PLUGIN_NAME = "ReverbOnDeath";

		public const string PLUGIN_VERSION = "1.0.1";
	}
}
namespace ReverbOnDeath.Patches
{
	[HarmonyPatch]
	internal class DissonancePatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.FirstMethod(typeof(VoicePlayback), (Func<MethodInfo, bool>)((MethodInfo method) => method.Name.Contains("SetTransform")));
		}

		private static bool Prefix(object __instance)
		{
			foreach (AudioConfig value in UpdatePlayerVoiceEffectsPatch.Configs.Values)
			{
				if (!value.EchoOn || !((object)((Component)((__instance is VoicePlayback) ? __instance : null)).transform).Equals((object?)value.AudioSourceT))
				{
					continue;
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "UpdatePlayerVoiceEffects")]
	internal class UpdatePlayerVoiceEffectsPatch
	{
		private static bool updateStarted = false;

		private static Dictionary<PlayerControllerB, AudioConfig> configs = new Dictionary<PlayerControllerB, AudioConfig>();

		public static Dictionary<PlayerControllerB, AudioConfig> Configs => configs;

		private static void Prefix()
		{
			if (configs == null)
			{
				configs = new Dictionary<PlayerControllerB, AudioConfig>();
			}
			if (!updateStarted)
			{
				((MonoBehaviour)HUDManager.Instance).StartCoroutine(UpdateNumerator());
				updateStarted = true;
			}
			if ((Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.allPlayerScripts == null)
			{
				return;
			}
			for (int i = 0; i < StartOfRound.Instance.allPlayerScripts.Length; i++)
			{
				PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[i];
				if ((Object)(object)val == (Object)null || (!val.isPlayerControlled && !val.isPlayerDead) || !((Object)(object)val != (Object)(object)GameNetworkManager.Instance.localPlayerController))
				{
					continue;
				}
				AudioSource currentVoiceChatAudioSource = val.currentVoiceChatAudioSource;
				if (!((Object)(object)currentVoiceChatAudioSource == (Object)null))
				{
					if ((Object)(object)((Component)currentVoiceChatAudioSource).gameObject.GetComponent<AudioEchoFilter>() == (Object)null)
					{
						((Component)currentVoiceChatAudioSource).gameObject.AddComponent<AudioEchoFilter>();
						AudioEchoFilter component = ((Component)currentVoiceChatAudioSource).gameObject.GetComponent<AudioEchoFilter>();
						component.delay = 25f;
						component.decayRatio = 0.94f;
						component.wetMix = 1f;
						component.dryMix = 0f;
						((Behaviour)component).enabled = false;
					}
					if (val.isPlayerDead && !configs.ContainsKey(val))
					{
						configs.Add(val, new AudioConfig(val, Time.time + 2f, Time.time + 0.1f, ((Behaviour)((Component)currentVoiceChatAudioSource).GetComponent<AudioLowPassFilter>()).enabled, ((Behaviour)((Component)currentVoiceChatAudioSource).GetComponent<AudioHighPassFilter>()).enabled, currentVoiceChatAudioSource.panStereo, SoundManager.Instance.playerVoicePitchTargets[(int)(IntPtr)(long)val.playerClientId], GetPitch(val)));
					}
				}
			}
		}

		private static void Postfix()
		{
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			if (configs == null)
			{
				configs = new Dictionary<PlayerControllerB, AudioConfig>();
			}
			if ((Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null)
			{
				return;
			}
			PlayerControllerB[] array = configs.Keys.ToArray();
			foreach (PlayerControllerB val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				AudioConfig audioConfig = configs[val];
				if (audioConfig == null)
				{
					continue;
				}
				if ((val.isPlayerControlled || val.isPlayerDead) && !((Object)(object)val == (Object)(object)GameNetworkManager.Instance.localPlayerController))
				{
					if ((Object)(object)val.currentVoiceChatAudioSource == (Object)null)
					{
						continue;
					}
					AudioSource currentVoiceChatAudioSource = val.currentVoiceChatAudioSource;
					if (audioConfig.EchoOn)
					{
						if ((Object)(object)val.deadBody != (Object)null)
						{
							((Component)currentVoiceChatAudioSource).transform.position = ((Component)val.deadBody).transform.position;
						}
						((Behaviour)((Component)currentVoiceChatAudioSource).gameObject.GetComponent<AudioEchoFilter>()).enabled = true;
						if ((Object)(object)((Component)currentVoiceChatAudioSource).GetComponent<AudioLowPassFilter>() != (Object)null)
						{
							((Behaviour)((Component)currentVoiceChatAudioSource).GetComponent<AudioLowPassFilter>()).enabled = audioConfig.LpOn;
						}
						if ((Object)(object)((Component)currentVoiceChatAudioSource).GetComponent<AudioHighPassFilter>() != (Object)null)
						{
							((Behaviour)((Component)currentVoiceChatAudioSource).GetComponent<AudioHighPassFilter>()).enabled = audioConfig.HpOn;
						}
						currentVoiceChatAudioSource.panStereo = audioConfig.PanStereo;
						if ((Object)(object)SoundManager.Instance != (Object)null)
						{
							SoundManager.Instance.playerVoicePitchTargets[(int)(IntPtr)(long)val.playerClientId] = audioConfig.PlayerVoicePitchTarget;
							SoundManager.Instance.SetPlayerPitch(audioConfig.PlayerPitch, (int)val.playerClientId);
						}
						currentVoiceChatAudioSource.spatialBlend = 1f;
						val.currentVoiceChatIngameSettings.set2D = false;
						val.voicePlayerState.Volume = (audioConfig.VoiceOn ? 1f : 0f);
						currentVoiceChatAudioSource.volume = 1f;
					}
					else if (((Behaviour)((Component)currentVoiceChatAudioSource).gameObject.GetComponent<AudioEchoFilter>()).enabled)
					{
						((Behaviour)((Component)currentVoiceChatAudioSource).gameObject.GetComponent<AudioEchoFilter>()).enabled = false;
					}
				}
				else if (!val.isPlayerDead)
				{
					configs.Remove(val);
				}
			}
		}

		private static IEnumerator UpdateNumerator()
		{
			yield return 0;
			while (true)
			{
				UpdatePlayersStatus();
				yield return (object)new WaitForFixedUpdate();
			}
		}

		private static void UpdatePlayersStatus()
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			if (configs == null)
			{
				return;
			}
			bool flag = false;
			KeyValuePair<PlayerControllerB, AudioConfig>[] array = configs.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<PlayerControllerB, AudioConfig> keyValuePair = array[i];
				if (!((Object)(object)keyValuePair.Key == (Object)null))
				{
					if (!keyValuePair.Key.isPlayerDead)
					{
						configs.Remove(keyValuePair.Key);
						flag = true;
					}
					else if ((Object)(object)keyValuePair.Value.DeadBodyT != (Object)null && (Object)(object)keyValuePair.Value.AudioSourceT != (Object)null)
					{
						keyValuePair.Value.AudioSourceT.position = keyValuePair.Value.DeadBodyT.position;
					}
				}
			}
			if (flag)
			{
				StartOfRound.Instance.UpdatePlayerVoiceEffects();
			}
		}

		private static float GetPitch(PlayerControllerB playerControllerB)
		{
			int num = (int)playerControllerB.playerClientId;
			float result = default(float);
			SoundManager.Instance.diageticMixer.GetFloat($"PlayerPitch{num}", ref result);
			return result;
		}
	}
}
namespace ReverbOnDeath.Configuration
{
	public class AudioConfig
	{
		private PlayerControllerB playerControllerB;

		private float stopEchoAt = 0f;

		private float stopVoiceAt = 0f;

		private bool lpOn;

		private bool hpOn;

		private float panStereo;

		private float playerVoicePitchTarget;

		private float playerPitch;

		public bool EchoOn => Time.time < stopEchoAt;

		public bool VoiceOn => Time.time < stopVoiceAt;

		public float StopEchoAt => stopEchoAt;

		public float StopVoiceAt => stopVoiceAt;

		public bool LpOn => lpOn;

		public bool HpOn => hpOn;

		public float PanStereo => panStereo;

		public float PlayerVoicePitchTarget => playerVoicePitchTarget;

		public float PlayerPitch => playerPitch;

		public Transform DeadBodyT => ((Component)playerControllerB.deadBody).transform;

		public Transform AudioSourceT => ((Component)playerControllerB.currentVoiceChatAudioSource).transform;

		public AudioConfig(PlayerControllerB playerControllerB, float stopEchoAt, float stopVoiceAt, bool lpOn, bool hpOn, float panStereo, float playerVoicePitchTarget, float playerPitch)
		{
			this.playerControllerB = playerControllerB;
			this.stopEchoAt = stopEchoAt;
			this.stopVoiceAt = stopVoiceAt;
			this.lpOn = lpOn;
			this.hpOn = hpOn;
			this.panStereo = panStereo;
			this.playerVoicePitchTarget = playerVoicePitchTarget;
			this.playerPitch = playerPitch;
		}
	}
}