using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using FMOD.Studio;
using FMODUnity;
using FistVR;
using HarmonyLib;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")]
[assembly: AssemblyCompany("AmbientMuter")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("AmbientMuter")]
[assembly: AssemblyTitle("AmbientMuter")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace AmbientMuter;
[BepInPlugin("h3vr.invent60.ambientmuter", "AmbientMuter", "1.0.7")]
public class AmbientMuterPlugin : BaseUnityPlugin
{
private ConfigEntry<bool> _cfgMuteMusic;
private ConfigEntry<bool> _cfgMuteAmbient;
private ConfigEntry<float> _cfgSweepDelay;
private ConfigEntry<bool> _cfgKeepFootsteps;
private ConfigEntry<bool> _cfgKeepInteractive;
private ConfigEntry<bool> _cfgMutePlayerHurt;
private Bus _musicBus;
private bool _busObtained;
private Harmony _harmony;
private bool _calibrated;
private int _calibrationAttempts;
private void Awake()
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Expected O, but got Unknown
BindConfig();
SceneManager.sceneLoaded += OnSceneLoaded;
_harmony = new Harmony("h3vr.invent60.ambientmuter");
_harmony.PatchAll(typeof(CursedLLPitchFix));
try
{
_harmony.PatchAll(typeof(MagBoopTimerFix));
((BaseUnityPlugin)this).Logger.LogInfo((object)"[AmbientMuter] MagBoop slow-mo timer fix applied.");
}
catch
{
}
((MonoBehaviour)this).StartCoroutine(DetectCursedLL());
((BaseUnityPlugin)this).Logger.LogInfo((object)"[AmbientMuter] Loaded.");
}
private void BindConfig()
{
_cfgMuteMusic = ((BaseUnityPlugin)this).Config.Bind<bool>("Music", "Mute map music", true, "Zeros the FMOD music bus every frame, silencing background music in all maps (TNH, outdoor assault maps, etc.). Overrides any other mod that sets music volume.");
_cfgMuteAmbient = ((BaseUnityPlugin)this).Config.Bind<bool>("Ambient", "Mute ambient sounds", true, "Mutes map ambient AudioSources (wind loops, propaganda speakers, environment drones). Applied once per scene load after the sweep delay.");
_cfgSweepDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Ambient", "Sweep delay seconds", 4f, "Seconds to wait after scene load before sweeping ambient sources. Increase if some ambient sounds are not being caught. (0 to 30)");
_cfgKeepInteractive = ((BaseUnityPlugin)this).Config.Bind<bool>("Ambient", "Keep interactive object sounds", true, "Buttons, levers, switches, and other interactive map objects keep their sounds. Disable to also silence these.");
_cfgKeepFootsteps = ((BaseUnityPlugin)this).Config.Bind<bool>("Player", "Keep footstep mod sounds", true, "Footstep mods (PlayerFootsteps, AlyxFootsteps, EFT Frame, BF4 Footsteps) are not silenced. Disable to mute footstep sounds too.");
_cfgMutePlayerHurt = ((BaseUnityPlugin)this).Config.Bind<bool>("Player", "Mute player hurt sounds", false, "Mutes pain and impact sounds when the player takes damage.");
}
private IEnumerator DetectCursedLL()
{
yield return null;
try
{
PropertyInfo property = typeof(AudioSource).GetProperty("pitch");
if ((object)property == null)
{
yield break;
}
MethodInfo setMethod = property.GetSetMethod();
if ((object)setMethod == null)
{
yield break;
}
Patches patchInfo = Harmony.GetPatchInfo((MethodBase)setMethod);
if (patchInfo == null)
{
yield break;
}
int num = 0;
foreach (Patch prefix in patchInfo.Prefixes)
{
if (!string.Equals(prefix.owner, "h3vr.invent60.ambientmuter", StringComparison.OrdinalIgnoreCase))
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("[AmbientMuter] pitch-setter prefix: " + prefix.owner));
num++;
}
}
foreach (Patch postfix in patchInfo.Postfixes)
{
if (!string.Equals(postfix.owner, "h3vr.invent60.ambientmuter", StringComparison.OrdinalIgnoreCase))
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("[AmbientMuter] pitch-setter postfix: " + postfix.owner));
num++;
}
}
foreach (Patch transpiler in patchInfo.Transpilers)
{
if (!string.Equals(transpiler.owner, "h3vr.invent60.ambientmuter", StringComparison.OrdinalIgnoreCase))
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("[AmbientMuter] pitch-setter transpiler: " + transpiler.owner));
num++;
}
}
if (num > 0)
{
CursedLLPitchFix.PatcherDetected = true;
((BaseUnityPlugin)this).Logger.LogInfo((object)("[AmbientMuter] pitch-setter patcher(s) found (" + num + "). Calibration deferred to first slow-mo."));
}
else
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"[AmbientMuter] CursedLL pitch fix: not needed");
}
}
catch
{
}
}
private void TryGetBus()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
try
{
_musicBus = RuntimeManager.GetBus("bus:/Music");
_busObtained = true;
}
catch
{
}
}
private void Update()
{
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
CursedLLPitchFix.CachedTimeScale = Time.timeScale;
if (CursedLLPitchFix.PatcherDetected && !_calibrated && _calibrationAttempts < 5 && Time.timeScale < 0.99f && Time.timeScale > 0.001f)
{
_calibrationAttempts++;
MeasurePitchCompound();
_calibrated = CursedLLPitchFix.Initialized;
}
if (!_cfgMuteMusic.Value)
{
return;
}
if (!_busObtained)
{
TryGetBus();
return;
}
try
{
((Bus)(ref _musicBus)).setVolume(0f);
}
catch
{
_busObtained = false;
}
}
private void MeasurePitchCompound()
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Expected O, but got Unknown
try
{
float cachedTimeScale = CursedLLPitchFix.CachedTimeScale;
if (cachedTimeScale <= 0.001f || cachedTimeScale >= 0.999f)
{
return;
}
GameObject val = new GameObject("__AMCalib");
AudioSource obj = val.AddComponent<AudioSource>();
obj.volume = 0f;
obj.mute = true;
obj.pitch = 1f;
float pitch = obj.pitch;
Object.Destroy((Object)(object)val);
if (pitch <= 0f)
{
return;
}
float num = Mathf.Log(cachedTimeScale);
float num2 = Mathf.Log(pitch);
if (!(Mathf.Abs(num) < 0.0001f))
{
int num3 = Mathf.RoundToInt(num2 / num);
if (num3 > 0)
{
CursedLLPitchFix.CompoundLevels = num3;
CursedLLPitchFix.ExtraCompounders = Mathf.Max(0, num3 - 1);
CursedLLPitchFix.CursedActive = true;
CursedLLPitchFix.Initialized = true;
((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AmbientMuter] CursedLL calibrated: {num3} compound level(s), {CursedLLPitchFix.ExtraCompounders} extra (ts={cachedTimeScale:F3})");
}
}
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("[AmbientMuter] CursedLL calibration error: " + ex.Message));
}
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
_busObtained = false;
if (_cfgMuteAmbient.Value)
{
((MonoBehaviour)this).StartCoroutine(MuteAmbientDelayed());
}
}
private IEnumerator MuteAmbientDelayed()
{
yield return (object)new WaitForSeconds(_cfgSweepDelay.Value);
MuteAmbientSources();
}
private void MuteAmbientSources()
{
//IL_0063: 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)
bool value = _cfgKeepFootsteps.Value;
bool value2 = _cfgKeepInteractive.Value;
bool value3 = _cfgMutePlayerHurt.Value;
int num = 0;
int num2 = 0;
AudioSource[] array = Object.FindObjectsOfType<AudioSource>();
foreach (AudioSource val in array)
{
if ((Object)(object)((Component)val).GetComponent<FVRPooledAudioSource>() != (Object)null)
{
num2++;
continue;
}
if (value)
{
Scene scene = ((Component)val).gameObject.scene;
if (((Scene)(ref scene)).name == "DontDestroyOnLoad")
{
num2++;
continue;
}
}
if (value2 && (Object)(object)((Component)val).GetComponentInParent<FVRInteractiveObject>() != (Object)null)
{
num2++;
continue;
}
if (!value2 && (Object)(object)((Component)val).GetComponentInParent<FVRPhysicalObject>() != (Object)null)
{
num2++;
continue;
}
if ((Object)(object)((Component)val).GetComponentInParent<Sosig>() != (Object)null)
{
num2++;
continue;
}
if ((Object)(object)((Component)val).GetComponentInParent<FVRMovementManager>() != (Object)null && !value3)
{
num2++;
continue;
}
if (value && (Object)(object)((Component)val).GetComponentInParent<BaseUnityPlugin>() != (Object)null)
{
num2++;
continue;
}
val.mute = true;
num++;
}
((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AmbientMuter] Scene sweep done. Muted: {num}, Kept: {num2}");
}
}
[HarmonyPatch]
public static class MagBoopTimerFix
{
private static MethodBase TargetMethod()
{
return AccessTools.Method("MagBoop.MagTriggerScript:Update", (Type[])null, (Type[])null);
}
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
MethodInfo getMethod = typeof(Time).GetProperty("fixedUnscaledDeltaTime").GetGetMethod();
List<CodeInstruction> list = instructions.ToList();
for (int i = 0; i < list.Count; i++)
{
if (list[i].opcode == OpCodes.Call && list[i].operand is MethodInfo methodInfo && methodInfo.DeclaringType == typeof(Time) && methodInfo.Name == "get_fixedDeltaTime")
{
list[i].operand = getMethod;
}
}
return list;
}
}
public static class CursedLLPitchFix
{
public static bool PatcherDetected = false;
public static bool Initialized = false;
public static bool CursedActive = false;
public static int CompoundLevels = 0;
public static int ExtraCompounders = 0;
public static float CachedTimeScale = 1f;
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
[HarmonyPostfix]
public static void CompensatePitchRead(ref float __result)
{
if (Initialized && CursedActive && !(CachedTimeScale >= 0.9999f) && !(CachedTimeScale <= 0.001f))
{
__result /= CachedTimeScale;
}
}
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
[HarmonyPrefix]
public static void PreCompensatePitchSet(ref float value)
{
if (Initialized && CursedActive && !(CachedTimeScale >= 0.9999f) && !(CachedTimeScale <= 0.001f) && ExtraCompounders > 0)
{
for (int i = 0; i < ExtraCompounders; i++)
{
value /= CachedTimeScale;
}
}
}
}