Decompiled source of ScrapRanking FIXED V2 v1.0.1

ScrapRanking.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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: AssemblyCompany("ScrapRanking")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ScrapRanking")]
[assembly: AssemblyTitle("ScrapRanking")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace ScrapRanking
{
	[BepInPlugin("mai.scrapranking", "Scrap Ranking", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("mai.scrapranking");

		private void Awake()
		{
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"ScrapRanking cargado!");
		}
	}
	public static class RankingData
	{
		public static Dictionary<int, int> totalScrap = new Dictionary<int, int>();

		public static void AccumulateAndReset(EndOfGameStats gameStats)
		{
			if (gameStats?.allPlayerStats == null)
			{
				return;
			}
			for (int i = 0; i < gameStats.allPlayerStats.Length; i++)
			{
				if (!totalScrap.ContainsKey(i))
				{
					totalScrap[i] = 0;
				}
				totalScrap[i] += gameStats.allPlayerStats[i].profitable;
				gameStats.allPlayerStats[i].profitable = 0;
			}
		}

		public static void ResetTotal(EndOfGameStats gameStats)
		{
			totalScrap.Clear();
			if (gameStats?.allPlayerStats != null)
			{
				for (int i = 0; i < gameStats.allPlayerStats.Length; i++)
				{
					gameStats.allPlayerStats[i].profitable = 0;
				}
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "StartGame")]
	public class ResetDailyOnStartGame
	{
		private static void Postfix(StartOfRound __instance)
		{
			if (__instance.gameStats?.allPlayerStats == null)
			{
				return;
			}
			for (int i = 0; i < __instance.gameStats.allPlayerStats.Length; i++)
			{
				int profitable = __instance.gameStats.allPlayerStats[i].profitable;
				if (!RankingData.totalScrap.ContainsKey(i))
				{
					RankingData.totalScrap[i] = 0;
				}
				RankingData.totalScrap[i] += profitable;
				__instance.gameStats.allPlayerStats[i].profitable = 0;
				Debug.Log((object)$"[ScrapRanking] StartGame - jugador {i}: profitable={profitable}, totalAcumulado={RankingData.totalScrap[i]}");
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "FirePlayersAfterDeadlineClientRpc")]
	public class ResetTotalOnFired
	{
		private static void Postfix(StartOfRound __instance)
		{
			RankingData.ResetTotal(__instance.gameStats);
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager), "ResetSavedGameValues")]
	public class ResetTotalOnNewGame
	{
		private static void Postfix()
		{
			RankingData.ResetTotal(StartOfRound.Instance?.gameStats);
		}
	}
	[HarmonyPatch(typeof(Terminal), "OnSubmit")]
	public class TerminalRankingCommand
	{
		private static bool Prefix(Terminal __instance)
		{
			if (__instance.textAdded == 0)
			{
				return true;
			}
			string text = __instance.screenText.text.Substring(__instance.screenText.text.Length - __instance.textAdded).Trim().ToLower();
			if (text != "ranking")
			{
				return true;
			}
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			EndOfGameStats gameStats = StartOfRound.Instance.gameStats;
			List<(string, int)> list = new List<(string, int)>();
			for (int i = 0; i < allPlayerScripts.Length; i++)
			{
				PlayerControllerB val = allPlayerScripts[i];
				if (val.isPlayerControlled || val.isPlayerDead || val.disconnectedMidGame)
				{
					int profitable = gameStats.allPlayerStats[i].profitable;
					int num = (RankingData.totalScrap.ContainsKey(i) ? RankingData.totalScrap[i] : 0);
					list.Add((val.playerUsername, profitable + num));
				}
			}
			list = list.OrderByDescending<(string, int), int>(((string name, int scrap) p) => p.scrap).ToList();
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("\n----- SCRAP RANKING -----\n");
			for (int j = 0; j < list.Count; j++)
			{
				string text2 = j switch
				{
					2 => "#3", 
					1 => "#2", 
					0 => "#1", 
					_ => "#" + (j + 1), 
				};
				stringBuilder.AppendLine(text2 + "  " + list[j].Item1 + "  -  $" + list[j].Item2);
			}
			stringBuilder.AppendLine("\n-------------------------");
			TerminalNode val2 = ScriptableObject.CreateInstance<TerminalNode>();
			val2.displayText = stringBuilder.ToString();
			val2.clearPreviousText = true;
			val2.terminalEvent = "";
			__instance.LoadNewNode(val2);
			__instance.textAdded = 0;
			__instance.screenText.ActivateInputField();
			((Selectable)__instance.screenText).Select();
			return false;
		}
	}
	[HarmonyPatch(typeof(HUDManager), "FillEndGameStats")]
	[HarmonyPriority(0)]
	public class FillEndGameStatsPatch
	{
		private static bool Prefix(HUDManager __instance, EndOfGameStats stats, int scrapCollected = 0)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Invalid comparison between Unknown and I4
			PlayerControllerB[] allPlayerScripts = __instance.playersManager.allPlayerScripts;
			List<(string, int, bool, bool)> list = new List<(string, int, bool, bool)>();
			int num = 0;
			int num2 = 0;
			for (int i = 0; i < allPlayerScripts.Length; i++)
			{
				PlayerControllerB val = allPlayerScripts[i];
				if (val.isPlayerControlled || val.isPlayerDead || val.disconnectedMidGame)
				{
					if (val.isPlayerDead)
					{
						num++;
					}
					else if (val.isPlayerControlled)
					{
						num2++;
					}
					bool item = val.isPlayerDead && (int)val.causeOfDeath == 10;
					int profitable = stats.allPlayerStats[i].profitable;
					list.Add((val.playerUsername, profitable, val.isPlayerDead, item));
				}
			}
			list = list.OrderByDescending<(string, int, bool, bool), int>(((string name, int scrap, bool isDead, bool isMissing) p) => p.scrap).ToList();
			EndOfGameStatUIElements statsUIElements = __instance.statsUIElements;
			for (int j = 0; j < statsUIElements.playerNamesText.Length; j++)
			{
				((TMP_Text)statsUIElements.playerNamesText[j]).text = "";
				((TMP_Text)statsUIElements.playerNotesText[j]).text = "";
				((Behaviour)statsUIElements.playerStates[j]).enabled = false;
			}
			for (int k = 0; k < list.Count && k < statsUIElements.playerNamesText.Length; k++)
			{
				(string, int, bool, bool) tuple = list[k];
				string text = k switch
				{
					2 => "#3", 
					1 => "#2", 
					0 => "#1", 
					_ => "#" + (k + 1), 
				};
				((TMP_Text)statsUIElements.playerNamesText[k]).text = text + " " + tuple.Item1;
				((TMP_Text)statsUIElements.playerNotesText[k]).text = "Scrap: $" + tuple.Item2;
				((TMP_Text)statsUIElements.playerNotesText[k]).fontSize = 16f;
				((Behaviour)statsUIElements.playerStates[k]).enabled = true;
				statsUIElements.playerStates[k].sprite = (tuple.Item3 ? (tuple.Item4 ? statsUIElements.missingIcon : statsUIElements.deceasedIcon) : statsUIElements.aliveIcon);
			}
			((TMP_Text)statsUIElements.quotaNumerator).text = scrapCollected.ToString();
			((TMP_Text)statsUIElements.quotaDenominator).text = RoundManager.Instance.totalScrapValueInLevel.ToString();
			if (StartOfRound.Instance.allPlayersDead)
			{
				((Behaviour)statsUIElements.allPlayersDeadOverlay).enabled = true;
				((TMP_Text)statsUIElements.gradeLetter).text = "F";
				return false;
			}
			((Behaviour)statsUIElements.allPlayersDeadOverlay).enabled = false;
			int num3 = 0;
			float num4 = (float)RoundManager.Instance.scrapCollectedInLevel / RoundManager.Instance.totalScrapValueInLevel;
			if (num2 == StartOfRound.Instance.connectedPlayersAmount + 1)
			{
				num3++;
			}
			else if (num > 1)
			{
				num3--;
			}
			if (num4 >= 0.99f)
			{
				num3 += 2;
			}
			else if (num4 >= 0.6f)
			{
				num3++;
			}
			else if (num4 <= 0.25f)
			{
				num3--;
			}
			switch (num3)
			{
			case -1:
				((TMP_Text)statsUIElements.gradeLetter).text = "D";
				break;
			case 0:
				((TMP_Text)statsUIElements.gradeLetter).text = "C";
				break;
			case 1:
				((TMP_Text)statsUIElements.gradeLetter).text = "B";
				break;
			case 2:
				((TMP_Text)statsUIElements.gradeLetter).text = "A";
				break;
			case 3:
				((TMP_Text)statsUIElements.gradeLetter).text = "S";
				break;
			}
			return false;
		}
	}
}