Decompiled source of PeakSoundtrackRemastered v0.1.7

PEAKsoundtrackRemastered.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using ExitGames.Client.Photon;
using HarmonyLib;
using Peak;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace PeakSoundtrackRemastered;

public sealed class ModBadge : MonoBehaviour
{
	private const string Key = "purp.mod.peaksoundtrackremastered";

	private const int Slot = 1;

	private BaseUnityPlugin owner;

	private float nextScan;

	private Material material;

	private Texture2D texture;

	private Mesh mesh;

	private readonly Dictionary<Character, GameObject> badges = new Dictionary<Character, GameObject>();

	public static void Attach(BaseUnityPlugin plugin)
	{
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Expected O, but got Unknown
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Expected O, but got Unknown
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Expected O, but got Unknown
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_0206: Unknown result type (might be due to invalid IL or missing references)
		//IL_021d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0222: Unknown result type (might be due to invalid IL or missing references)
		//IL_0239: Unknown result type (might be due to invalid IL or missing references)
		//IL_023e: Unknown result type (might be due to invalid IL or missing references)
		ModBadge modBadge = ((Component)plugin).gameObject.AddComponent<ModBadge>();
		modBadge.owner = plugin;
		try
		{
			string directoryName = Path.GetDirectoryName(plugin.Info.Location);
			string path = Path.Combine(directoryName, "icon.png");
			if (!File.Exists(path))
			{
				path = Path.Combine(directoryName, "assets", "icon.png");
			}
			modBadge.texture = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(modBadge.texture, File.ReadAllBytes(path)))
			{
				throw new InvalidOperationException("Invalid logo image.");
			}
			Shader val = Shader.Find("Sprites/Default");
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = Shader.Find("Unlit/Transparent");
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				throw new InvalidOperationException("Logo shader unavailable.");
			}
			modBadge.material = new Material(val);
			modBadge.material.mainTexture = (Texture)(object)modBadge.texture;
			modBadge.mesh = new Mesh();
			modBadge.mesh.vertices = (Vector3[])(object)new Vector3[4]
			{
				new Vector3(-0.5f, -0.5f, 0f),
				new Vector3(0.5f, -0.5f, 0f),
				new Vector3(0.5f, 0.5f, 0f),
				new Vector3(-0.5f, 0.5f, 0f)
			};
			modBadge.mesh.colors = (Color[])(object)new Color[4]
			{
				Color.white,
				Color.white,
				Color.white,
				Color.white
			};
			modBadge.mesh.uv = (Vector2[])(object)new Vector2[4]
			{
				new Vector2(0f, 0f),
				new Vector2(1f, 0f),
				new Vector2(1f, 1f),
				new Vector2(0f, 1f)
			};
			modBadge.mesh.triangles = new int[6] { 0, 2, 1, 0, 3, 2 };
			modBadge.mesh.RecalculateBounds();
		}
		catch (Exception ex)
		{
			Debug.LogWarning((object)("PeakSoundtrackRemastered badges: " + ex.Message));
			((Behaviour)modBadge).enabled = false;
		}
	}

	private static bool Present(Player player)
	{
		if (player == null)
		{
			return false;
		}
		if (((Dictionary<object, object>)(object)player.CustomProperties).TryGetValue((object)"purp.mod.peaksoundtrackremastered", out object value) && value is bool)
		{
			return (bool)value;
		}
		return false;
	}

	private void Advertise(bool value)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Expected O, but got Unknown
		Player localPlayer = PhotonNetwork.LocalPlayer;
		if (localPlayer != null && value != Present(localPlayer))
		{
			Hashtable val = new Hashtable();
			((Dictionary<object, object>)(object)val).Add((object)"purp.mod.peaksoundtrackremastered", value ? ((object)true) : null);
			localPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
		}
	}

	private void Update()
	{
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Expected O, but got Unknown
		//IL_0169: Unknown result type (might be due to invalid IL or missing references)
		if (Time.unscaledTime < nextScan)
		{
			return;
		}
		nextScan = Time.unscaledTime + 0.5f;
		bool flag = Object.op_Implicit((Object)(object)owner) && ((Behaviour)owner).isActiveAndEnabled && PhotonNetwork.InRoom;
		Advertise(flag);
		List<Character> list = new List<Character>();
		foreach (KeyValuePair<Character, GameObject> badge in badges)
		{
			if (!flag || !Eligible(badge.Key))
			{
				if (Object.op_Implicit((Object)(object)badge.Value))
				{
					Object.Destroy((Object)(object)badge.Value);
				}
				list.Add(badge.Key);
			}
		}
		foreach (Character item in list)
		{
			badges.Remove(item);
		}
		if (!flag || !Object.op_Implicit((Object)(object)material) || !Object.op_Implicit((Object)(object)mesh))
		{
			return;
		}
		foreach (Character allCharacter in Character.AllCharacters)
		{
			if (Eligible(allCharacter) && !badges.ContainsKey(allCharacter))
			{
				GameObject val = new GameObject("PeakSoundtrackRemastered ownership logo");
				val.transform.SetParent(((Component)allCharacter).transform, false);
				val.transform.localScale = Vector3.one;
				val.AddComponent<MeshFilter>().sharedMesh = mesh;
				MeshRenderer val2 = val.AddComponent<MeshRenderer>();
				((Renderer)val2).sharedMaterial = material;
				((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)val2).receiveShadows = false;
				badges.Add(allCharacter, val);
			}
		}
	}

	private static bool Eligible(Character c)
	{
		if (Object.op_Implicit((Object)(object)c) && !c.IsLocal && !c.isBot && Object.op_Implicit((Object)(object)((MonoBehaviourPun)c).photonView) && !((MonoBehaviourPun)c).photonView.IsMine)
		{
			return Present(((MonoBehaviourPun)c).photonView.Owner);
		}
		return false;
	}

	private void LateUpdate()
	{
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		Camera main = Camera.main;
		foreach (KeyValuePair<Character, GameObject> badge in badges)
		{
			Character key = badge.Key;
			GameObject value = badge.Value;
			if (Object.op_Implicit((Object)(object)key) && Object.op_Implicit((Object)(object)value))
			{
				bool flag = Object.op_Implicit((Object)(object)main) && Eligible(key) && key.refs != null && Object.op_Implicit((Object)(object)key.refs.head);
				value.SetActive(flag);
				if (flag)
				{
					value.transform.position = key.refs.head.transform.position + Vector3.up * 0.55f + ((Component)main).transform.right * 0f;
					value.transform.rotation = ((Component)main).transform.rotation;
					value.transform.localScale = Vector3.one;
					Vector3 lossyScale = value.transform.lossyScale;
					value.transform.localScale = new Vector3(0.22f / Mathf.Max(0.001f, Mathf.Abs(lossyScale.x)), 0.22f / Mathf.Max(0.001f, Mathf.Abs(lossyScale.y)), 1f);
				}
			}
		}
	}

	private void OnDisable()
	{
		Advertise(value: false);
		foreach (GameObject value in badges.Values)
		{
			if (Object.op_Implicit((Object)(object)value))
			{
				Object.Destroy((Object)(object)value);
			}
		}
		badges.Clear();
	}

	private void OnDestroy()
	{
		OnDisable();
		if (Object.op_Implicit((Object)(object)material))
		{
			Object.Destroy((Object)(object)material);
		}
		if (Object.op_Implicit((Object)(object)texture))
		{
			Object.Destroy((Object)(object)texture);
		}
		if (Object.op_Implicit((Object)(object)mesh))
		{
			Object.Destroy((Object)(object)mesh);
		}
	}
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("local.peaksoundtrackremastered", "PEAKsoundtrack remastered", "0.1.7")]
public sealed class Plugin : BaseUnityPlugin
{
	internal static Plugin Instance;

	private readonly ScoreRules rules = new ScoreRules();

	private readonly FallCue fallCue = new FallCue();

	private AudioSource meme;

	private float lastMeme = -100f;

	private float lastWarning = -100f;

	private readonly Dictionary<Track, float> resumeTimes = new Dictionary<Track, float>();

	private readonly Dictionary<Track, AudioClip> clips = new Dictionary<Track, AudioClip>();

	private readonly Dictionary<AudioSource, bool> muted = new Dictionary<AudioSource, bool>();

	private readonly HashSet<GhostBall> resolvedGhosts = new HashSet<GhostBall>();

	private readonly FieldInfo tornadoCaught = AccessTools.Field(typeof(Tornado), "caughtCharacters");

	private readonly FieldInfo ghostHealth = AccessTools.Field(typeof(GhostBall), "burnHealth");

	private readonly MethodInfo checkReached = AccessTools.Method(typeof(MountainProgressHandler), "CheckReached", (Type[])null, (Type[])null);

	private readonly MethodInfo spawnTornado = AccessTools.Method(typeof(TornadoSpawner), "SpawnTornado", (Type[])null, (Type[])null);

	private float nextTestSpawn;

	private float noticeUntil;

	private string notice = "";

	private ConfigEntry<float> volume;

	private ConfigEntry<float> fadeSeconds;

	private ConfigEntry<bool> enabledMusic;

	private ConfigEntry<bool> duckMusic;

	private AudioSource source;

	private AudioSource tail;

	private float tailStart;

	private float tailVolume;

	private Track tailTrack;

	private PropertyInfo afterglowProperty;

	private bool lastDead;

	private Harmony harmony;

	private Character tracked;

	private MapHandler trackedMap;

	private Track playing;

	private bool loaded;

	private bool fading;

	private bool failed;

	private float fadeStart;

	private float fadeVolume;

	private float nextPoll;

	private float nextDuck;

	private string root;

	private string region = "";

	private int dustCount;

	private int ghostCount;

	private string AssetPath(string name)
	{
		string text = Path.Combine(root, "assets", name);
		if (File.Exists(text))
		{
			return text;
		}
		string text2 = Path.Combine(root, name);
		if (File.Exists(text2))
		{
			return text2;
		}
		throw new FileNotFoundException("Missing mod asset '" + name + "'. Expected " + text + " or " + text2);
	}

	private void Awake()
	{
		//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Expected O, but got Unknown
		Instance = this;
		ModBadge.Attach((BaseUnityPlugin)(object)this);
		root = Path.GetDirectoryName(typeof(Plugin).Assembly.Location);
		enabledMusic = ((BaseUnityPlugin)this).Config.Bind<bool>("Music", "Enabled", true, "Enable this local soundtrack.");
		volume = ((BaseUnityPlugin)this).Config.Bind<float>("Music", "Volume", 0.65f, "Local soundtrack volume, 0 to 1.");
		fadeSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Music", "FadeSeconds", 2f, "Fade after a flare, defeated ghost, departing biome, or leaving a dust devil.");
		duckMusic = ((BaseUnityPlugin)this).Config.Bind<bool>("Music", "QuietVanillaMusic", true, "Temporarily mute known vanilla music sources while a replacement track plays. Voice and game effects are untouched.");
		try
		{
			if (tornadoCaught == null || ghostHealth == null || checkReached == null)
			{
				throw new MissingMemberException("Required game event fields are missing.");
			}
			source = ((Component)this).gameObject.AddComponent<AudioSource>();
			source.playOnAwake = false;
			source.spatialBlend = 0f;
			source.priority = 64;
			tail = ((Component)this).gameObject.AddComponent<AudioSource>();
			tail.playOnAwake = false;
			tail.spatialBlend = 0f;
			tail.priority = 64;
			meme = ((Component)this).gameObject.AddComponent<AudioSource>();
			meme.playOnAwake = false;
			meme.spatialBlend = 0f;
			meme.priority = 60;
			SceneManager.sceneLoaded += SceneLoaded;
			harmony = new Harmony("local.peaksoundtrackremastered");
			harmony.PatchAll(typeof(Plugin).Assembly);
			((MonoBehaviour)this).StartCoroutine(LoadTracks());
			Log("0.1.7 loaded. Local soundtrack; Lost Girl plays for a lone summit arrival.");
		}
		catch (Exception error)
		{
			Fail(error);
		}
	}

	private void Log(string message)
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)message);
		try
		{
			File.AppendAllText(Path.Combine(root, "soundtrack-diagnostics.log"), DateTime.UtcNow.ToString("o") + " " + message + Environment.NewLine);
		}
		catch
		{
		}
	}

	private IEnumerator LoadTracks()
	{
		try
		{
			Track[] array = new Track[14]
			{
				Track.DustDevils,
				Track.Summit,
				Track.Nadir,
				Track.Ghost,
				Track.Citadel,
				Track.NadirAmbient,
				Track.Finale,
				Track.Credits,
				Track.Spectating,
				Track.Airport,
				Track.LoneSummit,
				Track.Falling,
				Track.Rising,
				Track.ScoutChase
			};
			foreach (Track track in array)
			{
				string path = AssetPath(track.ToString() + ".wav");
				UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(new Uri(path).AbsoluteUri, (AudioType)20);
				try
				{
					((DownloadHandlerAudioClip)request.downloadHandler).streamAudio = true;
					yield return request.SendWebRequest();
					if ((int)request.result != 1)
					{
						Log(string.Concat("Cannot load ", track, ": ", request.error));
						continue;
					}
					AudioClip clip = DownloadHandlerAudioClip.GetContent(request);
					if ((Object)(object)clip == (Object)null || clip.length <= ScoreRules.StartSeconds(track) + 0.1f)
					{
						Log("Track missing or too short for offset: " + track);
						if ((Object)(object)clip != (Object)null)
						{
							Object.Destroy((Object)(object)clip);
						}
						continue;
					}
					clips[track] = clip;
					Log(string.Concat("Loaded ", track, ", ", clip.length.ToString("F1"), "s, starts at ", ScoreRules.StartSeconds(track), "s."));
				}
				finally
				{
					((IDisposable)request)?.Dispose();
				}
			}
		}
		finally
		{
		}
		loaded = true;
	}

	private bool LocalAlive(Character c)
	{
		if ((Object)(object)c != (Object)null && (Object)(object)c.data != (Object)null && c.IsLocal && (Object)(object)((MonoBehaviourPun)c).photonView != (Object)null && ((MonoBehaviourPun)c).photonView.IsMine && !c.data.dead)
		{
			return !c.isBot;
		}
		return false;
	}

	private void Update()
	{
		if (failed)
		{
			return;
		}
		try
		{
			CheckTestKey();
			if (!enabledMusic.Value)
			{
				StopAll();
				fallCue.Reset();
				rules.RisingWarning = false;
				return;
			}
			UpdateFallCue();
			if (Time.unscaledTime >= nextPoll)
			{
				nextPoll = Time.unscaledTime + 0.25f;
				Poll();
			}
			UpdateTail();
			if ((Object)(object)source == (Object)null || playing == Track.None)
			{
				if ((Object)(object)tail != (Object)null && tail.isPlaying && duckMusic.Value)
				{
					QuietVanilla();
				}
				return;
			}
			if (fading)
			{
				source.volume = fadeVolume * ScoreRules.FadeGain(Time.unscaledTime - fadeStart, Mathf.Max(0.05f, fadeSeconds.Value));
				if (source.volume <= 0.0001f)
				{
					StopNow();
					return;
				}
			}
			else
			{
				source.volume = Mathf.Clamp01(volume.Value);
			}
			if (!source.isPlaying && !AudioListener.pause)
			{
				rules.Finished(playing);
				resumeTimes.Remove(playing);
				StopNow();
				nextPoll = 0f;
			}
			else if (!duckMusic.Value)
			{
				RestoreVanilla();
			}
			else if (Time.unscaledTime >= nextDuck)
			{
				nextDuck = Time.unscaledTime + 0.5f;
				QuietVanilla();
			}
		}
		catch (Exception error)
		{
			Fail(error);
		}
	}

	private void Notice(string text)
	{
		notice = text;
		noticeUntil = Time.unscaledTime + 4f;
		Log(text);
	}

	private void CheckTestKey()
	{
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		Keyboard current = Keyboard.current;
		if (current == null || !Application.isFocused || (!((ButtonControl)current.digit6Key).wasPressedThisFrame && !((ButtonControl)current.numpad6Key).wasPressedThisFrame) || (Object)(object)GUIManager.instance == (Object)null || GUIManager.instance.windowBlockingInput || GUIManager.instance.wheelActive)
		{
			return;
		}
		Character localCharacter = Character.localCharacter;
		MapHandler instance = Singleton<MapHandler>.Instance;
		if (!PhotonNetwork.InRoom || !LocalAlive(localCharacter) || !localCharacter.data.fullyConscious || (Object)(object)instance == (Object)null)
		{
			Notice("Dust-devil test: enter a round as a conscious scout.");
		}
		else if (!PhotonNetwork.IsMasterClient)
		{
			Notice("Dust-devil test: only the host can spawn one.");
		}
		else if (CurrentRegion(localCharacter, instance) != "MESA")
		{
			Notice("Dust-devil test: you must be in Mesa.");
		}
		else
		{
			if (Time.unscaledTime < nextTestSpawn)
			{
				return;
			}
			TornadoSpawner val = null;
			float num = float.PositiveInfinity;
			TornadoSpawner[] array = Object.FindObjectsByType<TornadoSpawner>((FindObjectsSortMode)0);
			foreach (TornadoSpawner val2 in array)
			{
				if ((Object)(object)val2 == (Object)null || !((Behaviour)val2).isActiveAndEnabled)
				{
					continue;
				}
				PhotonView component = ((Component)val2).GetComponent<PhotonView>();
				Transform val3 = ((Component)val2).transform.Find("TornadoPoints");
				if (!((Object)(object)component == (Object)null) && component.ViewID != 0 && !((Object)(object)val3 == (Object)null) && val3.childCount != 0)
				{
					Vector3 val4 = ((Component)val2).transform.position - localCharacter.Center;
					float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						num = sqrMagnitude;
						val = val2;
					}
				}
			}
			if (!((Object)(object)val == (Object)null) && !(spawnTornado == null))
			{
				nextTestSpawn = Time.unscaledTime + 1f;
				try
				{
					spawnTornado.Invoke(val, null);
					nextPoll = 0f;
					Notice("Dust devil spawned at a vanilla Mesa spawn point. Everyone can see it.");
					return;
				}
				catch (Exception ex)
				{
					Notice("Dust-devil test failed: " + ex.GetBaseException().Message);
					return;
				}
			}
			Notice("Dust-devil test: no active Mesa spawner with valid spawn points.");
		}
	}

	private void OnGUI()
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		if (!(Time.unscaledTime >= noticeUntil))
		{
			GUI.Box(new Rect((float)Screen.width / 2f - 300f, 35f, 600f, 60f), notice);
		}
	}

	private string CurrentRegion(Character c, MapHandler map)
	{
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: 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)
		//IL_00a8: Invalid comparison between Unknown and I4
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Invalid comparison between Unknown and I4
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		if (VoidBiome.VoidBiomeActive)
		{
			return "NADIR";
		}
		MountainProgressHandler instance = Singleton<MountainProgressHandler>.Instance;
		if ((Object)(object)instance != (Object)null && instance.progressPoints != null)
		{
			for (int num = instance.progressPoints.Length - 1; num >= 0; num--)
			{
				ProgressPoint val = instance.progressPoints[num];
				if (val != null && (Object)(object)val.transform != (Object)null && (bool)checkReached.Invoke(instance, new object[1] { val }))
				{
					return (val.title ?? "").Trim().ToUpperInvariant();
				}
			}
		}
		if ((Object)(object)map == (Object)null)
		{
			return "";
		}
		BiomeType currentBiome = map.GetCurrentBiome();
		if ((int)currentBiome == 17)
		{
			return "NADIR";
		}
		if ((int)currentBiome == 8)
		{
			return "GLOOM";
		}
		return ((object)currentBiome).ToString().ToUpperInvariant();
	}

	private void Poll()
	{
		//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_0314: Unknown result type (might be due to invalid IL or missing references)
		//IL_031a: Unknown result type (might be due to invalid IL or missing references)
		Character localCharacter = Character.localCharacter;
		MapHandler instance = Singleton<MapHandler>.Instance;
		Scene activeScene = SceneManager.GetActiveScene();
		if (((Scene)(ref activeScene)).name == "Airport")
		{
			if (region != "AIRPORT")
			{
				ResetSession();
				region = "AIRPORT";
			}
			if (loaded)
			{
				Apply(rules.Select("AIRPORT", alive: true, CountCaptured(localCharacter), 0));
			}
			return;
		}
		if (region == "AIRPORT")
		{
			ResetSession();
		}
		if (!PhotonNetwork.InRoom)
		{
			ResetSession();
			return;
		}
		if (rules.InCredits || rules.FinalCutscene)
		{
			if (loaded)
			{
				Apply(rules.Select(region, alive: true, 0, 0));
			}
			return;
		}
		if ((Object)(object)localCharacter == (Object)null || (Object)(object)instance == (Object)null)
		{
			ResetSession();
			return;
		}
		if ((Object)(object)tracked != (Object)(object)localCharacter || (Object)(object)trackedMap != (Object)(object)instance)
		{
			ResetSession();
			tracked = localCharacter;
			trackedMap = instance;
		}
		if (!loaded || (Object)(object)localCharacter.data == (Object)null)
		{
			return;
		}
		bool dead = localCharacter.data.dead;
		if (dead != lastDead)
		{
			lastDead = dead;
			resumeTimes.Clear();
			if (dead)
			{
				Log("Waiting for AFTERGLOW and spectating.");
			}
		}
		if (dead)
		{
			meme.Stop();
			Apply(rules.Select(region, alive: false, 0, 0, AfterglowShowing(), localCharacter.data.deathTimer >= 5f));
			return;
		}
		if (!LocalAlive(localCharacter))
		{
			BeginFade();
			return;
		}
		string text = CurrentRegion(localCharacter, instance);
		if (region != text)
		{
			resumeTimes.Clear();
			region = text;
			Log("Local region: " + region);
		}
		dustCount = 0;
		ghostCount = 0;
		resolvedGhosts.RemoveWhere((GhostBall g) => (Object)(object)g == (Object)null);
		dustCount = CountCaptured(localCharacter);
		if (region == "GLOOM")
		{
			GhostBall[] array = Object.FindObjectsByType<GhostBall>((FindObjectsSortMode)0);
			foreach (GhostBall val in array)
			{
				if ((Object)(object)val != (Object)null && ((Behaviour)val).isActiveAndEnabled && !resolvedGhosts.Contains(val) && (float)ghostHealth.GetValue(val) > 0f)
				{
					ghostCount++;
				}
			}
		}
		bool scoutPresent = rules.ScoutPresent;
		rules.ScoutPresent = false;
		Scoutmaster[] array2 = Object.FindObjectsByType<Scoutmaster>((FindObjectsSortMode)0);
		foreach (Scoutmaster val2 in array2)
		{
			if ((Object)(object)val2 != (Object)null && ((Behaviour)val2).isActiveAndEnabled && (Object)(object)val2.currentTarget == (Object)(object)localCharacter && Vector3.Distance(((Component)val2).transform.position, localCharacter.Center) < 50f)
			{
				rules.ScoutPresent = true;
				break;
			}
		}
		if (scoutPresent && !rules.ScoutPresent)
		{
			resumeTimes.Remove(Track.ScoutChase);
		}
		Apply(rules.Select(region, alive: true, dustCount, ghostCount, afterglow: false, spectating: false, region == "PEAK" && AloneAmongSurvivors(localCharacter)));
	}

	private void UpdateFallCue()
	{
		Character localCharacter = Character.localCharacter;
		bool flag = PhotonNetwork.InRoom && LocalAlive(localCharacter) && !localCharacter.warping && !localCharacter.data.isClimbingAnything && !localCharacter.data.isInWater && !localCharacter.data.isCarried;
		if (fallCue.Step(flag, !flag || localCharacter.data.isGrounded, flag ? localCharacter.data.avarageVelocity.y : 0f, Time.deltaTime))
		{
			PlayMeme();
		}
		if ((Object)(object)meme != (Object)null)
		{
			meme.volume = Mathf.Clamp01(volume.Value);
			if (!flag && !LocalAlive(localCharacter))
			{
				meme.Stop();
			}
		}
	}

	internal void PlayMeme()
	{
		if (!failed && enabledMusic.Value && loaded && PhotonNetwork.InRoom && LocalAlive(Character.localCharacter) && !rules.FinalCutscene && !rules.InCredits && clips.TryGetValue(Track.Falling, out var value) && !meme.isPlaying && !(Time.unscaledTime - lastMeme < 1f))
		{
			lastMeme = Time.unscaledTime;
			meme.clip = value;
			meme.loop = false;
			meme.volume = Mathf.Clamp01(volume.Value);
			meme.Play();
			Log("Let Me Know triggered.");
		}
	}

	internal void BugleUsed(Action_CallScoutmaster action)
	{
		Item val = (((Object)(object)action == (Object)null) ? null : ((Component)action).GetComponent<Item>());
		if ((Object)(object)val != (Object)null && (Object)(object)val.holderCharacter == (Object)(object)Character.localCharacter)
		{
			PlayMeme();
		}
	}

	internal void HazardWarning()
	{
		if (!failed && enabledMusic.Value && PhotonNetwork.InRoom && LocalAlive(Character.localCharacter) && !rules.FinalCutscene && !rules.InCredits && !(Time.unscaledTime - lastWarning < 5f))
		{
			lastWarning = Time.unscaledTime;
			rules.RisingWarning = true;
			nextPoll = 0f;
			Log("Rising-hazard warning received.");
		}
	}

	private bool AloneAmongSurvivors(Character local)
	{
		if (!LocalAlive(local) || !PhotonNetwork.InRoom)
		{
			return false;
		}
		Player[] playerList = PhotonNetwork.PlayerList;
		foreach (Player val in playerList)
		{
			if (val == null || val.IsLocal || val.IsInactive)
			{
				continue;
			}
			bool flag = false;
			foreach (Character allCharacter in Character.AllCharacters)
			{
				if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.isBot && !((Object)(object)((MonoBehaviourPun)allCharacter).photonView == (Object)null) && ((MonoBehaviourPun)allCharacter).photonView.OwnerActorNr == val.ActorNumber)
				{
					flag = true;
					if (!allCharacter.IsInitialized || (Object)(object)allCharacter.data == (Object)null || !allCharacter.data.dead)
					{
						return false;
					}
				}
			}
			if (!flag)
			{
				return false;
			}
		}
		return true;
	}

	private int CountCaptured(Character c)
	{
		if (!LocalAlive(c))
		{
			return 0;
		}
		int num = 0;
		Tornado[] array = Object.FindObjectsByType<Tornado>((FindObjectsSortMode)0);
		foreach (Tornado val in array)
		{
			if (!((Object)(object)val == (Object)null) && ((Behaviour)val).isActiveAndEnabled && tornadoCaught.GetValue(val) is List<Character> list && list.Contains(c))
			{
				num++;
			}
		}
		return num;
	}

	private void Apply(Track wanted)
	{
		if (wanted == Track.None)
		{
			BeginFade();
		}
		else if (wanted == playing)
		{
			if (fading)
			{
				fading = false;
				source.volume = Mathf.Clamp01(volume.Value);
			}
		}
		else
		{
			Play(wanted);
		}
	}

	private void Play(Track track)
	{
		if (clips.TryGetValue(track, out var value))
		{
			tail.Stop();
			if (source.isPlaying)
			{
				tail.clip = source.clip;
				tail.loop = source.loop;
				tail.time = source.time;
				tail.volume = source.volume;
				tailVolume = source.volume;
				tailStart = Time.unscaledTime;
				tailTrack = playing;
				tail.Play();
			}
			if ((track == Track.Rising || track == Track.ScoutChase) && playing != Track.None && playing != Track.ScoutChase && source.isPlaying && !fading)
			{
				resumeTimes[playing] = source.time;
			}
			source.Stop();
			fading = false;
			playing = track;
			source.clip = value;
			source.loop = ScoreRules.Loops(track);
			source.volume = Mathf.Clamp01(volume.Value);
			source.time = ((resumeTimes.TryGetValue(track, out var value2) && value2 < value.length - 0.1f) ? value2 : ScoreRules.StartSeconds(track));
			source.Play();
			nextDuck = 0f;
			Log(string.Concat("Playing ", track, " from ", ScoreRules.StartSeconds(track), "s."));
		}
	}

	private void BeginFade()
	{
		if (playing != Track.None && !fading)
		{
			fading = true;
			fadeStart = Time.unscaledTime;
			fadeVolume = source.volume;
			Log(string.Concat("Fading ", playing, "."));
		}
	}

	private void StopNow()
	{
		if ((Object)(object)source != (Object)null)
		{
			source.Stop();
		}
		playing = Track.None;
		fading = false;
		if ((Object)(object)tail == (Object)null || !tail.isPlaying)
		{
			RestoreVanilla();
		}
	}

	private void StopAll()
	{
		if ((Object)(object)meme != (Object)null)
		{
			meme.Stop();
		}
		if ((Object)(object)tail != (Object)null)
		{
			tail.Stop();
		}
		StopNow();
	}

	private void UpdateTail()
	{
		if ((Object)(object)tail == (Object)null || !tail.isPlaying)
		{
			return;
		}
		tail.volume = tailVolume * ScoreRules.FadeGain(Time.unscaledTime - tailStart, Mathf.Max(0.05f, fadeSeconds.Value));
		if (tail.volume <= 0.0001f)
		{
			tail.Stop();
			if (playing == Track.None)
			{
				RestoreVanilla();
			}
		}
	}

	private void SceneLoaded(Scene scene, LoadSceneMode mode)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		if ((int)mode == 0)
		{
			ResetSession();
		}
	}

	private bool AfterglowShowing()
	{
		if (!Chainloader.PluginInfos.TryGetValue("local.entitiesplus", out var value) || (Object)(object)value.Instance == (Object)null)
		{
			return false;
		}
		if (afterglowProperty == null)
		{
			afterglowProperty = AccessTools.Property(((object)value.Instance).GetType(), "DeathShowing");
		}
		if (afterglowProperty != null)
		{
			return (bool)afterglowProperty.GetValue(null, null);
		}
		return false;
	}

	internal void EndingEvent(int stage)
	{
		if (failed || !PhotonNetwork.InRoom)
		{
			return;
		}
		if (stage == 1)
		{
			rules.NadirWon = true;
			Log("Nadir completed; fading its music.");
			if (playing == Track.Nadir || playing == Track.NadirAmbient)
			{
				BeginFade();
			}
		}
		if (stage == 2)
		{
			rules.NadirWon = true;
			rules.FinalCutscene = true;
			Log("Post-Nadir final cutscene.");
		}
		if (stage == 3)
		{
			rules.InCredits = true;
			Log("Credits started.");
		}
		nextPoll = 0f;
	}

	private void ResetSession()
	{
		StopAll();
		fallCue.Reset();
		resumeTimes.Clear();
		lastMeme = (lastWarning = -100f);
		lastDead = false;
		rules.Reset();
		tracked = null;
		trackedMap = null;
		region = "";
		resolvedGhosts.Clear();
		dustCount = (ghostCount = 0);
	}

	internal void GhostEnded(GhostBall ghost)
	{
		if (!failed && !((Object)(object)ghost == (Object)null))
		{
			resolvedGhosts.Add(ghost);
			nextPoll = 0f;
		}
	}

	internal void FlareLit()
	{
		if (!failed && LocalAlive(Character.localCharacter) && (playing == Track.Summit || playing == Track.LoneSummit || region == "PEAK"))
		{
			rules.FlareLit();
			if (playing == Track.Summit || playing == Track.LoneSummit)
			{
				BeginFade();
			}
		}
	}

	private void Quiet(AudioSource audio)
	{
		if (!((Object)(object)audio == (Object)null) && !((Object)(object)audio == (Object)(object)source) && !((Object)(object)audio == (Object)(object)tail) && !((Object)(object)audio == (Object)(object)meme))
		{
			if (!muted.ContainsKey(audio))
			{
				muted[audio] = audio.mute;
			}
			audio.mute = true;
		}
	}

	private void QuietRoot(GameObject obj)
	{
		if ((Object)(object)obj != (Object)null)
		{
			AudioSource[] componentsInChildren = obj.GetComponentsInChildren<AudioSource>(true);
			foreach (AudioSource audio in componentsInChildren)
			{
				Quiet(audio);
			}
		}
	}

	private void QuietVanilla()
	{
		//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)
		if (region == "AIRPORT")
		{
			AudioSource[] array = Object.FindObjectsByType<AudioSource>((FindObjectsSortMode)0);
			foreach (AudioSource val in array)
			{
				Scene scene = ((Component)val).gameObject.scene;
				if (((Scene)(ref scene)).name == "Airport" && (Object)(object)val.outputAudioMixerGroup != (Object)null && ((Object)val.outputAudioMixerGroup).name.IndexOf("music", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					Quiet(val);
				}
			}
		}
		AmbienceAudio[] array2 = Object.FindObjectsByType<AmbienceAudio>((FindObjectsSortMode)0);
		foreach (AmbienceAudio val2 in array2)
		{
			Quiet(val2.mainMusic);
		}
		BiomeMusicCheck[] array3 = Object.FindObjectsByType<BiomeMusicCheck>((FindObjectsSortMode)0);
		foreach (BiomeMusicCheck val3 in array3)
		{
			QuietRoot(val3.regularMusic);
			QuietRoot(val3.mesaMusic);
		}
		MyresAmbience[] array4 = Object.FindObjectsByType<MyresAmbience>((FindObjectsSortMode)0);
		foreach (MyresAmbience val4 in array4)
		{
			Quiet(val4.fearMusic);
		}
		if (region == "NADIR" && !rules.NadirWon)
		{
			ScoutmasterSoulPillar[] array5 = Object.FindObjectsByType<ScoutmasterSoulPillar>((FindObjectsSortMode)0);
			foreach (ScoutmasterSoulPillar val5 in array5)
			{
				Quiet(val5.music);
			}
		}
		PeakHandler instance = Singleton<PeakHandler>.Instance;
		if ((Object)(object)instance != (Object)null && (rules.FinalCutscene || rules.InCredits))
		{
			QuietCutsceneMusic(instance.endCutscene);
			QuietCutsceneMusic(instance.endCutsceneFinal);
			QuietCutsceneMusic(instance.endCutsceneFinalSpecialDay);
		}
		Type type = AccessTools.TypeByName("DeathTunes.DeathTunesPlugin");
		PropertyInfo propertyInfo = ((type == null) ? null : AccessTools.Property(type, "AudioSource"));
		if (propertyInfo != null && propertyInfo.GetGetMethod(nonPublic: true) != null && propertyInfo.GetGetMethod(nonPublic: true).IsStatic)
		{
			object? value = propertyInfo.GetValue(null, null);
			AudioSource val6 = (AudioSource)((value is AudioSource) ? value : null);
			if (playing == Track.Spectating || ((Object)(object)tail != (Object)null && tail.isPlaying && tailTrack == Track.Spectating))
			{
				Quiet(val6);
			}
			else if ((Object)(object)val6 != (Object)null && muted.ContainsKey(val6))
			{
				val6.mute = muted[val6];
				muted.Remove(val6);
			}
		}
	}

	private void QuietCutsceneMusic(GameObject obj)
	{
		if ((Object)(object)obj == (Object)null)
		{
			return;
		}
		AudioSource[] componentsInChildren = obj.GetComponentsInChildren<AudioSource>(true);
		foreach (AudioSource val in componentsInChildren)
		{
			if ((Object)(object)val.outputAudioMixerGroup != (Object)null && ((Object)val.outputAudioMixerGroup).name.IndexOf("music", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				Quiet(val);
			}
		}
	}

	private void RestoreVanilla()
	{
		foreach (KeyValuePair<AudioSource, bool> item in muted)
		{
			if ((Object)(object)item.Key != (Object)null)
			{
				item.Key.mute = item.Value;
			}
		}
		muted.Clear();
	}

	private void Fail(Exception error)
	{
		Log("Soundtrack disabled after error: " + error);
		failed = true;
		StopAll();
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}

	private void OnDisable()
	{
		StopAll();
	}

	private void OnDestroy()
	{
		SceneManager.sceneLoaded -= SceneLoaded;
		StopAll();
		((MonoBehaviour)this).StopAllCoroutines();
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		foreach (AudioClip value in clips.Values)
		{
			if ((Object)(object)value != (Object)null)
			{
				Object.Destroy((Object)(object)value);
			}
		}
		if ((Object)(object)source != (Object)null)
		{
			Object.Destroy((Object)(object)source);
		}
		if ((Object)(object)tail != (Object)null)
		{
			Object.Destroy((Object)(object)tail);
		}
		if ((Object)(object)meme != (Object)null)
		{
			Object.Destroy((Object)(object)meme);
		}
		if ((Object)(object)Instance == (Object)(object)this)
		{
			Instance = null;
		}
	}
}
[HarmonyPatch(typeof(Action_CallScoutmaster), "RunAction")]
internal static class BugleCue
{
	private static void Postfix(Action_CallScoutmaster __instance)
	{
		if ((Object)(object)Plugin.Instance != (Object)null)
		{
			Plugin.Instance.BugleUsed(__instance);
		}
	}
}
[HarmonyPatch(typeof(GUIManager), "TheFogRises")]
internal static class FogWarningCue
{
	private static void Postfix()
	{
		if ((Object)(object)Plugin.Instance != (Object)null)
		{
			Plugin.Instance.HazardWarning();
		}
	}
}
[HarmonyPatch(typeof(GUIManager), "TheGloomRises")]
internal static class GloomWarningCue
{
	private static void Postfix()
	{
		if ((Object)(object)Plugin.Instance != (Object)null)
		{
			Plugin.Instance.HazardWarning();
		}
	}
}
[HarmonyPatch(typeof(GUIManager), "TheLavaRises")]
internal static class LavaWarningCue
{
	private static void Postfix()
	{
		if ((Object)(object)Plugin.Instance != (Object)null)
		{
			Plugin.Instance.HazardWarning();
		}
	}
}
[HarmonyPatch(typeof(GhostBall), "Explode")]
internal static class GhostExplosion
{
	private static void Postfix(GhostBall __instance)
	{
		if ((Object)(object)Plugin.Instance != (Object)null)
		{
			Plugin.Instance.GhostEnded(__instance);
		}
	}
}
[HarmonyPatch(typeof(GhostBall), "OnDestroy")]
internal static class GhostDestroyed
{
	private static void Prefix(GhostBall __instance)
	{
		if ((Object)(object)Plugin.Instance != (Object)null)
		{
			Plugin.Instance.GhostEnded(__instance);
		}
	}
}
[HarmonyPatch(typeof(Flare), "LightFlare")]
internal static class FlareIgnition
{
	private static void Postfix()
	{
		if ((Object)(object)Plugin.Instance != (Object)null)
		{
			Plugin.Instance.FlareLit();
		}
	}
}
[HarmonyPatch(typeof(Flare), "EnableFlareVisuals")]
internal static class SyncedFlareIgnition
{
	private static void Postfix()
	{
		if ((Object)(object)Plugin.Instance != (Object)null)
		{
			Plugin.Instance.FlareLit();
		}
	}
}
[HarmonyPatch(typeof(GlobalEvents), "TriggerSoulFreed")]
internal static class NadirVictory
{
	private static void Postfix(int __0)
	{
		if (__0 >= 1 && (Object)(object)Plugin.Instance != (Object)null)
		{
			Plugin.Instance.EndingEvent(1);
		}
	}
}
[HarmonyPatch(typeof(PeakHandler), "EndCutsceneFinal")]
internal static class NadirFinale
{
	private static void Postfix()
	{
		if ((Object)(object)Plugin.Instance != (Object)null)
		{
			Plugin.Instance.EndingEvent(2);
		}
	}
}
[HarmonyPatch(typeof(PeakHandler), "EndScreenComplete")]
internal static class CreditsStart
{
	private static void Postfix()
	{
		if ((Object)(object)Plugin.Instance != (Object)null)
		{
			Plugin.Instance.EndingEvent(3);
		}
	}
}
public enum Track
{
	None,
	DustDevils,
	Summit,
	Nadir,
	Ghost,
	Citadel,
	NadirAmbient,
	Finale,
	Credits,
	Spectating,
	Airport,
	LoneSummit,
	Falling,
	Rising,
	ScoutChase
}
public sealed class FallCue
{
	private float descending;

	private bool fired;

	public void Reset()
	{
		descending = 0f;
		fired = false;
	}

	public bool Step(bool eligible, bool grounded, float velocityY, float delta)
	{
		if (!eligible || grounded)
		{
			Reset();
			return false;
		}
		if (velocityY > -5f)
		{
			descending = 0f;
			return false;
		}
		descending += Math.Max(0f, Math.Min(delta, 0.1f));
		if (fired || descending < 1f)
		{
			return false;
		}
		fired = true;
		return true;
	}
}
public sealed class ScoreRules
{
	private string previous = "";

	private bool summitFinished;

	private bool nadirFinished;

	private bool summitChosen;

	private bool loneSummit;

	public bool NadirWon;

	public bool FinalCutscene;

	public bool InCredits;

	public bool RisingWarning;

	public bool ScoutPresent;

	public void Reset()
	{
		previous = "";
		RisingWarning = (ScoutPresent = false);
		summitChosen = (loneSummit = (summitFinished = (nadirFinished = (NadirWon = (FinalCutscene = (InCredits = false))))));
	}

	public Track Select(string region, bool alive, int dustDevils, int ghosts)
	{
		return Select(region, alive, dustDevils, ghosts, afterglow: false, spectating: false);
	}

	public Track Select(string region, bool alive, int dustDevils, int ghosts, bool afterglow, bool spectating)
	{
		return Select(region, alive, dustDevils, ghosts, afterglow, spectating, alone: false);
	}

	public Track Select(string region, bool alive, int dustDevils, int ghosts, bool afterglow, bool spectating, bool alone)
	{
		region = (region ?? "").Trim().ToUpperInvariant();
		if (region != previous)
		{
			if (region == "PEAK")
			{
				summitFinished = false;
				summitChosen = false;
			}
			if (region == "NADIR")
			{
				nadirFinished = false;
			}
			previous = region;
		}
		if (InCredits)
		{
			return Track.Credits;
		}
		if (FinalCutscene)
		{
			return Track.Finale;
		}
		if (!alive)
		{
			RisingWarning = (ScoutPresent = false);
			if (afterglow || !spectating)
			{
				return Track.None;
			}
			return Track.Spectating;
		}
		if (region == "PEAK" && !summitChosen)
		{
			summitChosen = true;
			loneSummit = alone;
		}
		if (ScoutPresent)
		{
			return Track.ScoutChase;
		}
		if (RisingWarning)
		{
			return Track.Rising;
		}
		if (dustDevils > 0)
		{
			return Track.DustDevils;
		}
		if (region == "AIRPORT")
		{
			return Track.Airport;
		}
		if (region == "GLOOM" && ghosts > 0)
		{
			return Track.Ghost;
		}
		if (region == "NADIR" && !NadirWon)
		{
			if (!nadirFinished)
			{
				return Track.Nadir;
			}
			return Track.NadirAmbient;
		}
		switch (region)
		{
		case "THE CITADEL":
		case "CITADEL":
			return Track.Citadel;
		case "PEAK":
			if (!summitFinished)
			{
				if (!loneSummit)
				{
					return Track.Summit;
				}
				return Track.LoneSummit;
			}
			break;
		}
		return Track.None;
	}

	public void Finished(Track track)
	{
		if (track == Track.Rising)
		{
			RisingWarning = false;
		}
		if (track == Track.Summit || track == Track.LoneSummit)
		{
			summitFinished = true;
		}
		if (track == Track.Nadir)
		{
			nadirFinished = true;
		}
	}

	public void FlareLit()
	{
		summitFinished = true;
	}

	public static float StartSeconds(Track track)
	{
		return track switch
		{
			Track.Nadir => 26f, 
			Track.Summit => 181f, 
			_ => 0f, 
		};
	}

	public static bool Loops(Track track)
	{
		if (track != Track.ScoutChase && track != Track.Airport && track != Track.DustDevils && track != Track.Ghost && track != Track.Citadel && track != Track.NadirAmbient && track != Track.Finale && track != Track.Credits)
		{
			return track == Track.Spectating;
		}
		return true;
	}

	public static float FadeGain(float age, float duration)
	{
		if (!(duration <= 0f))
		{
			return Math.Max(0f, Math.Min(1f, 1f - age / duration));
		}
		return 0f;
	}
}