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
{
}
}