using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Dissonance.Audio.Playback;
using GameNetcodeStuff;
using HarmonyLib;
using MoreScreams.Configuration;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("MoreScreams")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MoreScreams")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("ba7e5619-9c03-4b8d-9888-381fda81ea0f")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace MoreScreams
{
[BepInPlugin("egeadam.MoreScreams", "MoreScreams", "1.0.3")]
public class MoreScreams : BaseUnityPlugin
{
private const string modGUID = "egeadam.MoreScreams";
private const string modName = "MoreScreams";
private const string modVersion = "1.0.3";
private readonly Harmony harmony = new Harmony("egeadam.MoreScreams");
private static MoreScreams Instance;
internal static ManualLogSource mls;
private void Awake()
{
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
mls = Logger.CreateLogSource("egeadam.MoreScreams");
Config.Init();
harmony.PatchAll();
}
}
}
namespace MoreScreams.Patches
{
public class AudioConfig
{
private PlayerControllerB playerControllerB;
private float shutUpAt;
private bool lowPassFilter;
private bool highPassFilter;
private float panStereo;
private float playerVoicePitchTargets;
private float playerPitch;
private float spatialBlend;
private bool set2D;
private float volume;
public bool IsAliveOrShuttedUp
{
get
{
if (!(shutUpAt < Time.time))
{
return !playerControllerB.isPlayerDead;
}
return true;
}
}
public float ShutUpAt => shutUpAt;
public bool LowPassFilter => lowPassFilter;
public bool HighPassFilter => highPassFilter;
public float PanStereo => panStereo;
public float PlayerVoicePitchTargets => playerVoicePitchTargets;
public float PlayerPitch => playerPitch;
public float SpatialBlend => spatialBlend;
public bool Set2D => set2D;
public float Volume => volume;
public Transform DeadBodyT => ((Component)playerControllerB.deadBody).transform;
public Transform AudioSourceT => ((Component)playerControllerB.currentVoiceChatAudioSource).transform;
public AudioConfig(PlayerControllerB playerControllerB, float shutUpAt, bool lowPassFilter, bool highPassFilter, float panStereo, float playerVoicePitchTargets, float playerPitch, float spatialBlend, bool set2D, float volume)
{
this.playerControllerB = playerControllerB;
this.shutUpAt = shutUpAt;
this.lowPassFilter = lowPassFilter;
this.highPassFilter = highPassFilter;
this.panStereo = panStereo;
this.playerVoicePitchTargets = playerVoicePitchTargets;
this.playerPitch = playerPitch;
this.spatialBlend = spatialBlend;
this.set2D = set2D;
this.volume = volume;
}
}
[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;
[HarmonyBefore(new string[] { "BiggerLobby" })]
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)
{
AudioSource currentVoiceChatAudioSource = val.currentVoiceChatAudioSource;
if (!((Object)(object)currentVoiceChatAudioSource == (Object)null) && val.isPlayerDead && !configs.ContainsKey(val))
{
Dictionary<PlayerControllerB, AudioConfig> dictionary = configs;
float shutUpAt = Time.time + Config.ShutUpAfter;
bool enabled = ((Behaviour)((Component)currentVoiceChatAudioSource).GetComponent<AudioLowPassFilter>()).enabled;
bool enabled2 = ((Behaviour)((Component)currentVoiceChatAudioSource).GetComponent<AudioHighPassFilter>()).enabled;
float panStereo = (currentVoiceChatAudioSource.panStereo = 0f);
dictionary.Add(val, new AudioConfig(val, shutUpAt, enabled, enabled2, panStereo, SoundManager.Instance.playerVoicePitchTargets[(int)(IntPtr)(long)val.playerClientId], GetPitch(val), currentVoiceChatAudioSource.spatialBlend, val.currentVoiceChatIngameSettings.set2D, val.voicePlayerState.Volume));
}
}
}
}
private static void Postfix()
{
//IL_00d6: 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.IsAliveOrShuttedUp)
{
if ((Object)(object)val.deadBody != (Object)null)
{
((Component)currentVoiceChatAudioSource).transform.position = ((Component)val.deadBody).transform.position;
}
currentVoiceChatAudioSource.panStereo = audioConfig.PanStereo;
currentVoiceChatAudioSource.spatialBlend = audioConfig.SpatialBlend;
AudioLowPassFilter component = ((Component)currentVoiceChatAudioSource).GetComponent<AudioLowPassFilter>();
AudioHighPassFilter component2 = ((Component)currentVoiceChatAudioSource).GetComponent<AudioHighPassFilter>();
if ((Object)(object)component != (Object)null)
{
((Behaviour)component).enabled = audioConfig.LowPassFilter;
}
if ((Object)(object)component2 != (Object)null)
{
((Behaviour)component2).enabled = audioConfig.HighPassFilter;
}
if ((Object)(object)SoundManager.Instance != (Object)null)
{
SoundManager.Instance.playerVoicePitchTargets[(int)(IntPtr)(long)val.playerClientId] = audioConfig.PlayerVoicePitchTargets;
SoundManager.Instance.SetPlayerPitch(audioConfig.PlayerPitch, (int)val.playerClientId);
}
val.currentVoiceChatIngameSettings.set2D = audioConfig.Set2D;
val.voicePlayerState.Volume = audioConfig.Volume;
val.currentVoiceChatAudioSource.volume = audioConfig.Volume;
}
}
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_0097: 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;
}
}
[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.IsAliveOrShuttedUp && ((object)((Component)((__instance is VoicePlayback) ? __instance : null)).transform).Equals((object?)value.AudioSourceT))
{
return false;
}
}
return true;
}
}
}
namespace MoreScreams.Configuration
{
internal static class Config
{
private const string CONFIG_FILE_NAME = "MoreScreams.cfg";
private static ConfigFile config;
private static ConfigEntry<float> shutUpAfter;
public static float ShutUpAfter => shutUpAfter.Value;
public static void Init()
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Expected O, but got Unknown
config = new ConfigFile(Path.Combine(Paths.ConfigPath, "MoreScreams.cfg"), true);
shutUpAfter = config.Bind<float>("Config", "Shut up after", 2f, "Mutes death player after given seconds.");
}
}
}