Decompiled source of Advance Features v1.1.0

BepInEx/plugins/advancedfeatures/AdvancedFeatures.dll

Decompiled 2 months ago
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.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading.Tasks;
using AdvancedFeatures.NetcodePatcher;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Dissonance;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Steamworks;
using Steamworks.Data;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[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 = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
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 AdvancedFeatures
{
	[HarmonyPatch]
	public class DeathScreen
	{
		public class SpectatorBox
		{
			public PlayerControllerB Player;

			public GameObject Container;

			public RawImage Avatar;

			public Animator Animator;

			public Text NameText;

			public Texture2D AvatarTexture;

			public float SmoothedVolume;
		}

		private static GameObject PlayerBoxPrefab;

		private static GridLayoutGroup GridLayout;

		private static readonly Dictionary<ulong, SpectatorBox> Spectators = new Dictionary<ulong, SpectatorBox>();

		private static int _prevChildCount = -1;

		public static void LoadAssets(AssetBundle assets)
		{
			Plugin.Log.LogInfo((object)"Loading DeathScreen assets");
			PlayerBoxPrefab = assets.LoadAsset<GameObject>("Assets/Prefabs/UI/PlayerBox.prefab");
			if ((Object)(object)PlayerBoxPrefab == (Object)null)
			{
				Plugin.Log.LogError((object)"Failed to load PlayerBox prefab for DeathScreen");
			}
			else if (Plugin.EnableAdvancedLogging.Value)
			{
				Plugin.Log.LogInfo((object)"DeathScreen assets loaded");
			}
		}

		[HarmonyPatch(typeof(HUDManager), "Start")]
		[HarmonyPrefix]
		public static void Init(HUDManager __instance)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.EnableDeathUI.Value)
			{
				Plugin.Log.LogInfo((object)"Initializing DeathScreen UI");
				if (Plugin.EnableAdvancedLogging.Value)
				{
					Plugin.Log.LogInfo((object)"Initializing DeathScreen");
				}
				RectTransform component = ((Component)__instance.SpectateBoxesContainer).GetComponent<RectTransform>();
				RectTransform component2 = ((Component)((Component)component).transform.parent).GetComponent<RectTransform>();
				RectTransform component3 = ((Component)((Component)component2).transform.parent).GetComponent<RectTransform>();
				component2.anchorMin = Vector2.zero;
				component2.anchorMax = Vector2.one;
				component2.offsetMin = Vector2.zero;
				component2.offsetMax = Vector2.zero;
				component3.anchorMin = Vector2.zero;
				component3.anchorMax = Vector2.one;
				component3.offsetMin = Vector2.zero;
				component3.offsetMax = Vector2.zero;
				component.anchorMin = Vector2.zero;
				component.anchorMax = new Vector2(1f, 0f);
				component.pivot = Vector2.zero;
				component.offsetMin = new Vector2(15f, 15f);
				component.offsetMax = new Vector2(-15f, 115f);
				GridLayout = ((Component)component).gameObject.AddComponent<GridLayoutGroup>();
				GridLayout.spacing = new Vector2(5f, 0f);
				GridLayout.constraint = (Constraint)2;
				GridLayout.constraintCount = 1;
				GridLayout.startCorner = (Corner)2;
				((LayoutGroup)GridLayout).childAlignment = (TextAnchor)6;
			}
		}

		[HarmonyPatch(typeof(HUDManager), "RemoveSpectateUI")]
		[HarmonyPrefix]
		public static void RemoveSpectateUI()
		{
			if (Plugin.EnableDeathUI.Value)
			{
				Plugin.Log.LogInfo((object)"Cleaning up DeathScreen UI");
				if (Plugin.EnableAdvancedLogging.Value)
				{
					Plugin.Log.LogInfo((object)"Removing DeathScreen spectate UI");
				}
				ulong[] array = Spectators.Keys.ToArray();
				foreach (ulong id in array)
				{
					DestroySpectatorBox(id);
				}
				_prevChildCount = -1;
			}
		}

		[HarmonyPatch(typeof(HUDManager), "Update")]
		[HarmonyPrefix]
		private static void Update()
		{
			if (!Plugin.EnableDeathUI.Value || (Object)(object)StartOfRound.Instance.voiceChatModule == (Object)null)
			{
				return;
			}
			bool flag = false;
			List<ulong> list = new List<ulong>();
			foreach (KeyValuePair<ulong, SpectatorBox> spectator in Spectators)
			{
				if ((Object)(object)spectator.Value.Container == (Object)null)
				{
					list.Add(spectator.Key);
					continue;
				}
				PlayerControllerB player = spectator.Value.Player;
				if (!player.isPlayerControlled && !player.isPlayerDead)
				{
					continue;
				}
				if ((Object)(object)player == (Object)(object)GameNetworkManager.Instance.localPlayerController)
				{
					if (!string.IsNullOrEmpty(StartOfRound.Instance.voiceChatModule.LocalPlayerName))
					{
						VoicePlayerState val = StartOfRound.Instance.voiceChatModule.FindPlayer(StartOfRound.Instance.voiceChatModule.LocalPlayerName);
						if (val != null)
						{
							float num = ((StartOfRound.Instance.voiceChatModule.IsMuted || !val.IsSpeaking || val.Amplitude < 0.005f) ? 0f : (val.Amplitude * Plugin.DeathVoiceSensitivity.Value));
							spectator.Value.SmoothedVolume = Mathf.Lerp(spectator.Value.SmoothedVolume, num, Time.unscaledDeltaTime * Plugin.BounceSmoothness.Value);
							spectator.Value.Animator.SetFloat("Volume", spectator.Value.SmoothedVolume);
						}
					}
				}
				else if (player.voicePlayerState == null)
				{
					if (!flag)
					{
						flag = true;
						StartOfRound.Instance.RefreshPlayerVoicePlaybackObjects();
					}
				}
				else
				{
					VoicePlayerState voicePlayerState = player.voicePlayerState;
					float num2 = ((!voicePlayerState.IsSpeaking || voicePlayerState.IsLocallyMuted || voicePlayerState.Amplitude < 0.005f) ? 0f : (voicePlayerState.Amplitude / Mathf.Max(voicePlayerState.Volume, 0.01f) * Plugin.DeathVoiceSensitivity.Value));
					spectator.Value.SmoothedVolume = Mathf.Lerp(spectator.Value.SmoothedVolume, num2, Time.unscaledDeltaTime * Plugin.BounceSmoothness.Value);
					spectator.Value.Animator.SetFloat("Volume", spectator.Value.SmoothedVolume);
				}
			}
			if (list.Count <= 0)
			{
				return;
			}
			foreach (ulong item in list)
			{
				DestroySpectatorBox(item);
			}
			UpdateLayoutSize();
		}

		private static void UpdateLayoutSize()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			int num = ((Component)GridLayout).transform.childCount - 4;
			if (num != _prevChildCount && num > 0)
			{
				_prevChildCount = num;
				Rect rect = ((Component)GridLayout).GetComponent<RectTransform>().rect;
				float num2 = ((Rect)(ref rect)).width / (float)num;
				num2 -= 5f;
				if (num2 > 70f)
				{
					num2 = 70f;
				}
				GridLayout.cellSize = new Vector2(num2, num2);
				if (Plugin.EnableAdvancedLogging.Value)
				{
					Plugin.Log.LogInfo((object)$"Updated layout size: {num} boxes, width {num2}");
				}
			}
		}

		[HarmonyPatch(typeof(HUDManager), "UpdateBoxesSpectateUI")]
		[HarmonyPrefix]
		public static bool UpdateBoxes(HUDManager __instance)
		{
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Expected O, but got Unknown
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_0391: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.EnableDeathUI.Value)
			{
				return true;
			}
			if (Plugin.EnableAdvancedLogging.Value)
			{
				Plugin.Log.LogInfo((object)"Updating death spectate boxes");
			}
			if (Plugin.EnableAdvancedLogging.Value)
			{
				Plugin.Log.LogInfo((object)"Updating death spectate boxes - Advanced");
			}
			if ((Object)(object)PlayerBoxPrefab == (Object)null)
			{
				Plugin.Log.LogError((object)"PlayerBox prefab missing, cannot update spectators");
				return true;
			}
			for (int i = 0; i < StartOfRound.Instance.allPlayerScripts.Length; i++)
			{
				PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[i];
				if (!val.isPlayerDead)
				{
					if (!val.isPlayerControlled && Spectators.ContainsKey(val.playerClientId))
					{
						DestroySpectatorBox(val.playerClientId);
					}
					continue;
				}
				if (Spectators.ContainsKey(val.playerClientId))
				{
					if ((Object)(object)Spectators[val.playerClientId].Container == (Object)null)
					{
						DestroySpectatorBox(val.playerClientId);
					}
					else if (!Spectators[val.playerClientId].Container.activeSelf)
					{
						Spectators[val.playerClientId].Container.SetActive(true);
					}
					continue;
				}
				GameObject val2 = Object.Instantiate<GameObject>(PlayerBoxPrefab, __instance.SpectateBoxesContainer, false);
				if (Plugin.EnableAdvancedLogging.Value)
				{
					Plugin.Log.LogInfo((object)("Created spectator box for " + val.playerUsername));
				}
				val2.transform.localScale = Vector3.one;
				val2.SetActive(true);
				SpectatorBox spectatorBox = new SpectatorBox
				{
					Container = val2,
					Animator = val2.GetComponent<Animator>(),
					Player = val,
					Avatar = ((Component)val2.transform.GetChild(0).GetChild(2)).GetComponent<RawImage>()
				};
				Spectators[val.playerClientId] = spectatorBox;
				if (Plugin.ShowDeathUsername.Value)
				{
					GameObject val3 = new GameObject("NameText", new Type[1] { typeof(RectTransform) });
					val3.transform.SetParent(val2.transform, false);
					Text val4 = val3.AddComponent<Text>();
					val4.text = val.playerUsername;
					val4.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
					val4.fontSize = 14;
					val4.alignment = (TextAnchor)4;
					((Graphic)val4).color = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)75, (byte)54, byte.MaxValue));
					Outline val5 = val3.AddComponent<Outline>();
					((Shadow)val5).effectColor = Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, (byte)170));
					((Shadow)val5).effectDistance = new Vector2(1f, -1f);
					RectTransform component = val3.GetComponent<RectTransform>();
					component.anchorMin = new Vector2(0f, 1f);
					component.anchorMax = new Vector2(1f, 1f);
					component.pivot = new Vector2(0.5f, 1f);
					component.sizeDelta = new Vector2(0f, 20f);
					Rect rect = ((Graphic)spectatorBox.Avatar).rectTransform.rect;
					float height = ((Rect)(ref rect)).height;
					component.anchoredPosition = new Vector2(0f, 0f - (height + 78f));
					spectatorBox.NameText = val4;
				}
				if (!GameNetworkManager.Instance.disableSteam)
				{
					FillImageWithSteamProfile(spectatorBox, SteamId.op_Implicit(val.playerSteamId));
				}
			}
			UpdateLayoutSize();
			return false;
		}

		private static void DestroySpectatorBox(ulong id)
		{
			if (!Spectators.TryGetValue(id, out var value))
			{
				Plugin.Log.LogError((object)$"Tried to destroy missing spectator box {id}");
				return;
			}
			if (Plugin.EnableAdvancedLogging.Value)
			{
				Plugin.Log.LogInfo((object)$"Destroying spectator box for {id}");
			}
			if ((Object)(object)value.AvatarTexture != (Object)null)
			{
				Object.Destroy((Object)(object)value.AvatarTexture);
				value.AvatarTexture = null;
			}
			if ((Object)(object)value.Container != (Object)null)
			{
				Object.Destroy((Object)(object)value.Container);
			}
			Spectators.Remove(id);
			if (Plugin.EnableAdvancedLogging.Value)
			{
				Plugin.Log.LogInfo((object)$"Spectator box removed. Remaining: {Spectators.Count}");
			}
		}

		private static async Task FillImageWithSteamProfile(SpectatorBox box, SteamId steamId)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (!SteamClient.IsValid)
			{
				return;
			}
			if (Plugin.EnableAdvancedLogging.Value)
			{
				Plugin.Log.LogInfo((object)$"Loading avatar for {steamId}");
			}
			Image? steamImg = await SteamFriends.GetLargeAvatarAsync(steamId);
			if (!steamImg.HasValue)
			{
				Plugin.Log.LogError((object)$"Steam avatar not found for {steamId}");
				return;
			}
			int w = (int)steamImg.Value.Width;
			int h = (int)steamImg.Value.Height;
			Texture2D tex = new Texture2D(w, h, (TextureFormat)4, false);
			bool loaded = false;
			byte[] data = steamImg.Value.Data;
			if (data != null && data.Length == w * h * 4)
			{
				try
				{
					tex.LoadRawTextureData(data);
					loaded = true;
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("Failed to load avatar texture data: " + ex));
				}
			}
			if (!loaded)
			{
				Color32[] pixels = (Color32[])(object)new Color32[w * h];
				for (int y = 0; y < h; y++)
				{
					for (int x = 0; x < w; x++)
					{
						Image value = steamImg.Value;
						Color p = ((Image)(ref value)).GetPixel(x, y);
						pixels[(h - y - 1) * w + x] = new Color32(p.r, p.g, p.b, p.a);
					}
				}
				tex.SetPixels32(pixels);
			}
			tex.Apply();
			if ((Object)(object)box.AvatarTexture != (Object)null)
			{
				Object.Destroy((Object)(object)box.AvatarTexture);
			}
			box.AvatarTexture = tex;
			box.Avatar.texture = (Texture)(object)tex;
			box.Avatar.uvRect = new Rect(0f, 1f, 1f, -1f);
			if (Plugin.EnableAdvancedLogging.Value)
			{
				Plugin.Log.LogInfo((object)$"Avatar loaded for {steamId}");
			}
		}
	}
	[HarmonyPatch]
	public class Endscreen
	{
		[HarmonyPatch(typeof(Animator), "SetTrigger", new Type[] { typeof(string) })]
		private static class Animator_SetTrigger_Patch
		{
			[HarmonyPostfix]
			private static void Postfix(Animator __instance, string name)
			{
				if (Plugin.EnablePerformanceUI.Value && name == "displayStats" && (Object)(object)__instance == (Object)(object)HUDManager.Instance.endgameStatsAnimator)
				{
					if (Plugin.EnableAdvancedLogging.Value)
					{
						Plugin.Log.LogInfo((object)"Animator trigger received; opening end screen");
					}
					Open();
				}
			}
		}

		[CompilerGenerated]
		private sealed class <AnimateMenu>d__30 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			private float <p>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <AnimateMenu>d__30(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0087: Unknown result type (might be due to invalid IL or missing references)
				//IL_0091: Expected O, but got Unknown
				//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
				//IL_01bb: Expected O, but got Unknown
				//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ff: Expected O, but got Unknown
				//IL_012b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0135: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (Plugin.EnableAdvancedLogging.Value)
					{
						Plugin.Log.LogInfo((object)"Animating performance report UI");
					}
					Cursor.lockState = (CursorLockMode)2;
					Cursor.visible = !Plugin.EnablePerformanceReportCameraScroll.Value;
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<p>5__1 = 0f;
					((TMP_Text)TotalText).text = TotalScrap.ToString();
					goto IL_0107;
				case 2:
					<>1__state = -1;
					goto IL_0107;
				case 3:
					<>1__state = -1;
					((Component)CollectedText).gameObject.SetActive(false);
					((Component)TotalText).gameObject.SetActive(false);
					((Component)CollectedLine).gameObject.SetActive(false);
					((Component)CollectedLabel).gameObject.SetActive(false);
					((TMP_Text)ScrapLostText).text = "Lost 0% scrap";
					((Component)ScrapLost).gameObject.SetActive(true);
					goto IL_01ab;
				case 4:
					<>1__state = -1;
					((TMP_Text)GradeText).text = Grade;
					<>2__current = (object)new WaitForSeconds(5.5f - (AreAllDead ? 1f : 0f));
					<>1__state = 5;
					return true;
				case 5:
					{
						<>1__state = -1;
						Container.SetActive(false);
						if (Plugin.EnableAdvancedLogging.Value)
						{
							Plugin.Log.LogInfo((object)"Performance report UI closed");
						}
						Cursor.lockState = (CursorLockMode)1;
						Cursor.visible = false;
						return false;
					}
					IL_0107:
					if (<p>5__1 < 1f)
					{
						((TMP_Text)CollectedText).text = CollectedScrap.ToString();
						<p>5__1 += 0.05f;
						<>2__current = WaitFrame;
						<>1__state = 2;
						return true;
					}
					if (AreAllDead)
					{
						<>2__current = (object)new WaitForSeconds(1f);
						<>1__state = 3;
						return true;
					}
					goto IL_01ab;
					IL_01ab:
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 4;
					return true;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static readonly MethodInfo _setTrigger = AccessTools.Method(typeof(Animator), "SetTrigger", new Type[1] { typeof(string) }, (Type[])null);

		private static GameObject Container;

		private static GameObject PerformanceReportPrefab;

		private static GameObject DeadContainerPrefab;

		private static GameObject MissingContainerPrefab;

		private static GameObject NoteContainerPrefab;

		private static Transform AllDead;

		private static Transform PlayerNoteContainer;

		private static Transform DeadNoteContainer;

		private static Transform MissingTitle;

		private static Transform MissingScrollBox;

		private static Transform MissingNoteContainer;

		private static Transform CollectedLabel;

		private static Transform CollectedLine;

		private static TextMeshProUGUI CollectedText;

		private static TextMeshProUGUI TotalText;

		private static Transform ScrapLost;

		private static TextMeshProUGUI ScrapLostText;

		private static TextMeshProUGUI GradeText;

		private static int CollectedScrap;

		private static int TotalScrap;

		private static string Grade;

		private static bool AreAllDead;

		private static int _playerNoteIndex;

		private static int _deadNoteIndex;

		private static int _missingNoteIndex;

		private static readonly WaitForEndOfFrame WaitFrame = new WaitForEndOfFrame();

		private static GameObject GetOrCreate(Transform container, GameObject prefab, ref int index)
		{
			GameObject val = ((index >= container.childCount) ? Object.Instantiate<GameObject>(prefab, container) : ((Component)container.GetChild(index)).gameObject);
			val.SetActive(true);
			index++;
			return val;
		}

		public static void LoadAssets(AssetBundle assets)
		{
			Plugin.Log.LogInfo((object)"Loading Endscreen assets");
			PerformanceReportPrefab = assets.LoadAsset<GameObject>("Assets/Prefabs/UI/PerformanceReport.prefab");
			DeadContainerPrefab = assets.LoadAsset<GameObject>("Assets/Prefabs/UI/DeadContainer.prefab");
			MissingContainerPrefab = assets.LoadAsset<GameObject>("Assets/Prefabs/UI/MissingContainer.prefab");
			NoteContainerPrefab = assets.LoadAsset<GameObject>("Assets/Prefabs/UI/NoteContainer.prefab");
			if ((Object)(object)PerformanceReportPrefab == (Object)null || (Object)(object)DeadContainerPrefab == (Object)null || (Object)(object)MissingContainerPrefab == (Object)null || (Object)(object)NoteContainerPrefab == (Object)null)
			{
				Plugin.Log.LogError((object)"Failed to load one or more Endscreen prefabs");
			}
			else if (Plugin.EnableAdvancedLogging.Value)
			{
				Plugin.Log.LogInfo((object)"Endscreen assets loaded");
				Plugin.Log.LogInfo((object)$"Prefabs: report={(Object)(object)PerformanceReportPrefab != (Object)null}, dead={(Object)(object)DeadContainerPrefab != (Object)null}, missing={(Object)(object)MissingContainerPrefab != (Object)null}, note={(Object)(object)NoteContainerPrefab != (Object)null}");
			}
		}

		public static void Open()
		{
			if (!Plugin.EnablePerformanceUI.Value)
			{
				return;
			}
			Plugin.Log.LogInfo((object)"Opening custom performance report screen");
			if (Plugin.EnableAdvancedLogging.Value)
			{
				Plugin.Log.LogInfo((object)"Open() was called.");
			}
			try
			{
				Transform transform = ((Component)HUDManager.Instance.endgameStatsAnimator).gameObject.transform;
				for (int i = 0; i < transform.childCount; i++)
				{
					Transform child = transform.GetChild(i);
					if (((Object)child).name == "Text")
					{
						((Component)child).gameObject.SetActive(false);
					}
					if (((Object)child).name == "BGBoxes" || ((Object)child).name == "Lines")
					{
						Object.Destroy((Object)(object)((Component)child).gameObject);
					}
				}
				bool active = false;
				_playerNoteIndex = 0;
				_deadNoteIndex = 0;
				_missingNoteIndex = 0;
				int childCount = PlayerNoteContainer.childCount;
				for (int j = 0; j < childCount; j++)
				{
					((Component)PlayerNoteContainer.GetChild(j)).gameObject.SetActive(false);
				}
				childCount = DeadNoteContainer.childCount;
				for (int k = 0; k < childCount; k++)
				{
					((Component)DeadNoteContainer.GetChild(k)).gameObject.SetActive(false);
				}
				childCount = MissingNoteContainer.childCount;
				for (int l = 0; l < childCount; l++)
				{
					((Component)MissingNoteContainer.GetChild(l)).gameObject.SetActive(false);
				}
				for (int m = 0; m < StartOfRound.Instance.allPlayerScripts.Length; m++)
				{
					PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[m];
					if (val.disconnectedMidGame)
					{
						continue;
					}
					string text = ((TMP_Text)HUDManager.Instance.statsUIElements.playerNamesText[m]).text;
					Texture2D val2 = null;
					string text2 = ((TMP_Text)HUDManager.Instance.statsUIElements.playerNotesText[m]).text;
					if (text2.StartsWith("Notes:"))
					{
						text2 = text2.Substring(6);
					}
					int num = text2.IndexOf("Cause of Death:", StringComparison.OrdinalIgnoreCase);
					if (num > -1)
					{
						text2 = text2.Substring(0, num);
					}
					text2 = text2.Trim();
					string text3;
					try
					{
						if (Chainloader.PluginInfos.TryGetValue("com.elitemastereric.coroner", out var value))
						{
							try
							{
								Type type = ((object)value.Instance).GetType().Assembly.GetType("Coroner.AdvancedDeathTracker");
								if (type == null)
								{
									throw new Exception("Coroner.AdvancedDeathTracker not found");
								}
								MethodInfo methodInfo = AccessTools.Method(type, "GetCauseOfDeath", new Type[2]
								{
									typeof(PlayerControllerB),
									typeof(bool)
								}, (Type[])null);
								if (methodInfo == null)
								{
									throw new Exception("GetCauseOfDeath(PlayerControllerB, bool) not found");
								}
								object obj = methodInfo.Invoke(null, new object[2] { val, true });
								MethodInfo methodInfo2 = AccessTools.Method(type, "StringifyCauseOfDeath", new Type[1] { methodInfo.ReturnType }, (Type[])null);
								if (methodInfo2 == null)
								{
									throw new Exception("StringifyCauseOfDeath(" + methodInfo.ReturnType.Name + ") not found");
								}
								text3 = (string)methodInfo2.Invoke(null, new object[1] { obj });
								if (Plugin.EnableAdvancedLogging.Value)
								{
									Plugin.Log.LogInfo((object)("[Coroner] " + text + " died of: " + text3));
								}
							}
							catch (Exception ex)
							{
								Plugin.Log.LogError((object)("Coroner reflection failed: " + ex));
								text3 = ((object)(CauseOfDeath)(ref val.causeOfDeath)).ToString();
							}
						}
						else
						{
							text3 = ((object)(CauseOfDeath)(ref val.causeOfDeath)).ToString();
							if (Plugin.EnableAdvancedLogging.Value)
							{
								Plugin.Log.LogInfo((object)("[Vanilla] " + text + " died of: " + text3));
							}
						}
					}
					catch (Exception ex2)
					{
						Plugin.Log.LogError((object)("Coroner test failed: " + ex2));
						text3 = ((object)(CauseOfDeath)(ref val.causeOfDeath)).ToString();
					}
					bool flag = (Object)(object)HUDManager.Instance.statsUIElements.playerStates[m].sprite == (Object)(object)HUDManager.Instance.statsUIElements.deceasedIcon;
					bool flag2 = (Object)(object)HUDManager.Instance.statsUIElements.playerStates[m].sprite == (Object)(object)HUDManager.Instance.statsUIElements.missingIcon;
					if (!string.IsNullOrEmpty(text2) && !flag && !flag2)
					{
						AddPlayerNote(val.playerSteamId, text, text2);
					}
					if ((Object)(object)HUDManager.Instance.statsUIElements.playerStates[m].sprite == (Object)(object)HUDManager.Instance.statsUIElements.deceasedIcon)
					{
						AddDeceasedNote(val.playerSteamId, text, text3);
					}
					if ((Object)(object)HUDManager.Instance.statsUIElements.playerStates[m].sprite == (Object)(object)HUDManager.Instance.statsUIElements.missingIcon)
					{
						active = true;
						AddMissingNote(val.playerSteamId, text);
					}
				}
				((Component)MissingTitle).gameObject.SetActive(active);
				((Component)MissingScrollBox).gameObject.SetActive(active);
				CollectedScrap = RoundManager.Instance.scrapCollectedInLevel;
				TotalScrap = (int)RoundManager.Instance.totalScrapValueInLevel;
				AreAllDead = ((Behaviour)HUDManager.Instance.statsUIElements.allPlayersDeadOverlay).enabled;
				((Component)AllDead).gameObject.SetActive(AreAllDead);
				((TMP_Text)CollectedText).text = string.Empty;
				((TMP_Text)TotalText).text = string.Empty;
				((Component)CollectedText).gameObject.SetActive(true);
				((Component)TotalText).gameObject.SetActive(true);
				((Component)CollectedLine).gameObject.SetActive(true);
				((Component)CollectedLabel).gameObject.SetActive(true);
				((Component)ScrapLost).gameObject.SetActive(false);
				Grade = ((TMP_Text)HUDManager.Instance.statsUIElements.gradeLetter).text;
				((TMP_Text)GradeText).text = string.Empty;
				Plugin.Log.LogInfo((object)$"Scrap collected: {CollectedScrap}/{TotalScrap} - Grade {Grade}");
				Container.SetActive(true);
				LayoutRebuilder.ForceRebuildLayoutImmediate(Container.GetComponent<RectTransform>());
				((MonoBehaviour)HUDManager.Instance).StartCoroutine(AnimateMenu());
				if (Plugin.EnableAdvancedLogging.Value)
				{
					Plugin.Log.LogInfo((object)"End screen animation coroutine started");
				}
				Plugin.Log.LogInfo((object)"Performance report screen displayed");
			}
			catch (Exception ex3)
			{
				Plugin.Log.LogError((object)"Error occurred while opening end screen!");
				Plugin.Log.LogError((object)ex3);
			}
		}

		[IteratorStateMachine(typeof(<AnimateMenu>d__30))]
		private static IEnumerator AnimateMenu()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <AnimateMenu>d__30(0);
		}

		private static void AddPlayerNote(ulong steamId, string username, string notes)
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			GameObject orCreate = GetOrCreate(PlayerNoteContainer, NoteContainerPrefab, ref _playerNoteIndex);
			if (Plugin.EnableAdvancedLogging.Value)
			{
				Plugin.Log.LogInfo((object)("Adding player note for " + username));
			}
			Transform child = orCreate.transform.GetChild(0);
			RawImage component = ((Component)child.GetChild(0)).GetComponent<RawImage>();
			if (Plugin.ShowAvatars.Value)
			{
				HUDManager.FillImageWithSteamProfile(component, SteamId.op_Implicit(steamId), true);
				((Component)component).gameObject.SetActive(true);
			}
			else
			{
				component.texture = null;
				component.uvRect = new Rect(0f, 0f, 1f, 1f);
				((Component)component).gameObject.SetActive(false);
			}
			TextMeshProUGUI component2 = ((Component)child.GetChild(1)).GetComponent<TextMeshProUGUI>();
			((TMP_Text)component2).text = username;
			((TMP_Text)component2).fontSize = 36f;
			((TMP_Text)((Component)orCreate.transform.GetChild(1)).GetComponent<TextMeshProUGUI>()).text = notes;
			orCreate.transform.localScale = Vector3.one;
		}

		private static void AddDeceasedNote(ulong steamId, string username, string deathReason)
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			GameObject orCreate = GetOrCreate(DeadNoteContainer, DeadContainerPrefab, ref _deadNoteIndex);
			if (Plugin.EnableAdvancedLogging.Value)
			{
				Plugin.Log.LogInfo((object)("Adding deceased note for " + username));
			}
			Transform child = orCreate.transform.GetChild(0);
			RawImage component = ((Component)child.GetChild(0)).GetComponent<RawImage>();
			if (Plugin.ShowAvatars.Value)
			{
				HUDManager.FillImageWithSteamProfile(component, SteamId.op_Implicit(steamId), true);
				((Component)component).gameObject.SetActive(true);
			}
			else
			{
				component.texture = null;
				component.uvRect = new Rect(0f, 0f, 1f, 1f);
				((Component)component).gameObject.SetActive(false);
			}
			((TMP_Text)((Component)child.GetChild(1)).GetComponent<TextMeshProUGUI>()).text = username;
			TextMeshProUGUI component2 = ((Component)orCreate.transform.GetChild(1)).GetComponent<TextMeshProUGUI>();
			((TMP_Text)component2).text = "* " + deathReason;
			((Graphic)component2).color = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)51, (byte)1, byte.MaxValue));
			((TMP_Text)component2).fontSize = 21.31f;
			orCreate.transform.localScale = Vector3.one;
		}

		private static void AddMissingNote(ulong steamId, string username)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			GameObject orCreate = GetOrCreate(MissingNoteContainer, MissingContainerPrefab, ref _missingNoteIndex);
			if (Plugin.EnableAdvancedLogging.Value)
			{
				Plugin.Log.LogInfo((object)("Adding missing note for " + username));
			}
			Transform child = orCreate.transform.GetChild(0);
			RawImage component = ((Component)child.GetChild(0)).GetComponent<RawImage>();
			if (Plugin.ShowAvatars.Value)
			{
				HUDManager.FillImageWithSteamProfile(component, SteamId.op_Implicit(steamId), true);
				((Component)component).gameObject.SetActive(true);
			}
			else
			{
				component.texture = null;
				component.uvRect = new Rect(0f, 0f, 1f, 1f);
				((Component)component).gameObject.SetActive(false);
			}
			((TMP_Text)((Component)child.GetChild(1)).GetComponent<TextMeshProUGUI>()).text = username;
			orCreate.transform.localScale = Vector3.one;
		}

		[HarmonyPatch(typeof(HUDManager), "Start")]
		[HarmonyPostfix]
		public static void Attach(HUDManager __instance)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.EnablePerformanceUI.Value)
			{
				if (Plugin.EnableAdvancedLogging.Value)
				{
					Plugin.Log.LogInfo((object)"Endscreen.Attach postfix invoked");
				}
				Container = Object.Instantiate<GameObject>(PerformanceReportPrefab, ((Component)__instance.endgameStatsAnimator).transform.parent);
				Container.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
				Container.GetComponent<RectTransform>().sizeDelta = new Vector2(823f, 717f);
				Transform child = Container.transform.GetChild(1);
				Transform child2 = child.GetChild(0);
				Transform child3 = child.GetChild(1);
				Transform child4 = Container.transform.GetChild(2);
				AllDead = child2.GetChild(1);
				PlayerNoteContainer = child2.GetChild(2).GetChild(0).GetChild(0);
				DeadNoteContainer = child3.GetChild(1).GetChild(0).GetChild(0);
				MissingTitle = child3.GetChild(2);
				MissingScrollBox = child3.GetChild(3);
				MissingNoteContainer = MissingScrollBox.GetChild(0).GetChild(0);
				ScrollRect componentInChildren = ((Component)MissingScrollBox).GetComponentInChildren<ScrollRect>();
				Transform child5 = child4.GetChild(0);
				CollectedLabel = child5.GetChild(0);
				CollectedText = ((Component)child5.GetChild(1)).GetComponent<TextMeshProUGUI>();
				CollectedLine = child5.GetChild(2);
				TotalText = ((Component)child5.GetChild(3)).GetComponent<TextMeshProUGUI>();
				ScrapLost = child5.GetChild(4);
				ScrapLostText = ((Component)ScrapLost.GetChild(0)).GetComponent<TextMeshProUGUI>();
				GradeText = ((Component)child4.GetChild(1).GetChild(1)).GetComponent<TextMeshProUGUI>();
				Container.SetActive(false);
			}
		}
	}
	[BepInPlugin("com.example.Advancedfeatures", "Advanced Features", "1.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public static ConfigEntry<bool> EnablePerformanceUI;

		public static ConfigEntry<bool> EnableDeathUI;

		public static ConfigEntry<bool> ShowDeathUsername;

		public static ConfigEntry<float> DeathVoiceSensitivity;

		public static ConfigEntry<float> BounceSmoothness;

		public static ConfigEntry<bool> ShowAvatars;

		public static ConfigEntry<bool> EnableAdvancedLogging;

		public static ConfigEntry<bool> EnablePerformanceReportCameraScroll;

		internal static ManualLogSource Log;

		private Harmony _harmony;

		private AssetBundle _assetBundle;

		private void Awake()
		{
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"Initializing Advanced Features plugin");
			EnablePerformanceUI = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnablePerformanceReportUI", true, "Toggle the custom performance-report UI");
			EnableDeathUI = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableDeathSpectateUI", true, "Toggle the custom death-spectate UI");
			ShowDeathUsername = ((BaseUnityPlugin)this).Config.Bind<bool>("DeathScreen", "ShowUsernameUnderAvatar", true, "Enable or disable the player?s name under their avatar on the death spectate screen");
			DeathVoiceSensitivity = ((BaseUnityPlugin)this).Config.Bind<float>("DeathScreen", "VoiceSensitivity", 10f, "How strongly avatars bounce in response to voice");
			BounceSmoothness = ((BaseUnityPlugin)this).Config.Bind<float>("DeathScreen", "BounceSmoothness", 12f, "How quickly the avatar bounce reacts to voice volume. Higher = snappier bounce.");
			ShowAvatars = ((BaseUnityPlugin)this).Config.Bind<bool>("Performance Report UI", "ShowAvatars", false, "If true, fetch and display each player's Steam avatar on the performance report.");
			EnableAdvancedLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "EnableAdvancedLogging", false, "If true, logs when the mod does anything");
			EnablePerformanceReportCameraScroll = ((BaseUnityPlugin)this).Config.Bind<bool>("Performance Report UI", "EnableCameraScroll", false, "If true, hides cursor and enables scroll wheel for all lists during performance report");
			if (EnableAdvancedLogging.Value)
			{
				Log.LogInfo((object)"Advanced logging enabled");
			}
			_harmony = new Harmony("com.example.Advancedfeatures");
			_harmony.PatchAll();
			Log.LogInfo((object)"Harmony patches applied");
			string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "advancedfeaturesassets");
			try
			{
				if (File.Exists(text))
				{
					Log.LogInfo((object)"Loading asset bundle for Advanced Features");
					_assetBundle = AssetBundle.LoadFromFile(text);
					Endscreen.LoadAssets(_assetBundle);
					DeathScreen.LoadAssets(_assetBundle);
					Log.LogInfo((object)("Asset bundle has been found at " + text));
				}
				else
				{
					Log.LogWarning((object)("Asset bundle not found at " + text));
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)"Failed to load asset bundle");
				Log.LogError((object)ex);
			}
		}
	}
}
namespace __GEN
{
	internal class NetworkVariableSerializationHelper
	{
		[RuntimeInitializeOnLoadMethod]
		internal static void InitializeSerialization()
		{
		}
	}
}
namespace AdvancedFeatures.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}