Decompiled source of BetterEXP v3.0.1

LCBetterEXP.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LCBetterEXP.patches;
using Newtonsoft.Json;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("LCBetterEXP")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LCBetterEXP")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("3d1909e4-ce70-48f2-a2d1-28b67cea8eee")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace LCBetterEXP
{
	public class BEXPPlayerClasses
	{
		public class DeathInformation
		{
			public string formattedCauseOfDeath;

			public CauseOfDeath causeOfDeath;

			public string formattedDayTimeOfDeath;

			public float normalizedTimeOfDeath;

			public float realLifeTimeOfDeathInSeconds;
		}

		public class RoundStats
		{
			public int damageTaken;

			public int stepsTaken;

			public int scrapDelivered;

			public int objectsDelivered;

			public int turns;

			public float indoorTime;

			public float outdoorTime;

			public float shipTime;

			public int jumps;

			public int scrapFound;

			public int scrapFoundDeliveredToShip;

			public int enemyKills;

			public int indoorAINodesCleared;

			public int totalXpEnemies;

			public int highestXpEnemies;
		}
	}
	internal class EnemyManager
	{
		public class EnemyTargets
		{
			public EnemyAI enemy;

			public List<BEXPPlayer> players;
		}

		public static Dictionary<EnemyAI, EnemyTargets> enemyTargets = new Dictionary<EnemyAI, EnemyTargets>();

		public static int GetXpFromEnemy(EnemyAI originalEnemy)
		{
			if (originalEnemy is RadMechAI)
			{
				return 18;
			}
			if (originalEnemy is SandWormAI)
			{
				return 16;
			}
			if (originalEnemy is ForestGiantAI)
			{
				return 15;
			}
			if (originalEnemy is GiantKiwiAI)
			{
				return 13;
			}
			if (originalEnemy is CaveDwellerAI)
			{
				return 12;
			}
			if (originalEnemy is MouthDogAI)
			{
				return 12;
			}
			if (originalEnemy is BushWolfEnemy)
			{
				return 10;
			}
			if (originalEnemy is PumaAI)
			{
				return 9;
			}
			if (originalEnemy is FlowermanAI)
			{
				return 8;
			}
			if (originalEnemy is ClaySurgeonAI)
			{
				return 7;
			}
			if (originalEnemy is NutcrackerEnemyAI)
			{
				return 7;
			}
			if (originalEnemy is SandSpiderAI)
			{
				return 6;
			}
			if (originalEnemy is CadaverBloomAI)
			{
				return 6;
			}
			if (originalEnemy is MaskedPlayerEnemy)
			{
				return 6;
			}
			if (originalEnemy is CrawlerAI)
			{
				return 6;
			}
			if (originalEnemy is ButlerEnemyAI)
			{
				return 5;
			}
			if (originalEnemy is HoarderBugAI)
			{
				return 5;
			}
			if (originalEnemy is ButlerBeesEnemyAI)
			{
				return 5;
			}
			if (originalEnemy is RedLocustBees)
			{
				return 5;
			}
			if (originalEnemy is BaboonBirdAI)
			{
				return 5;
			}
			if (originalEnemy is StingrayAI)
			{
				return 4;
			}
			if (originalEnemy is DressGirlAI)
			{
				return 4;
			}
			if (originalEnemy is CentipedeAI)
			{
				return 4;
			}
			if (originalEnemy is PufferAI)
			{
				return 3;
			}
			if (originalEnemy is SpringManAI)
			{
				return 2;
			}
			if (originalEnemy is BlobAI)
			{
				return 2;
			}
			if (originalEnemy is JesterAI)
			{
				return 2;
			}
			if (originalEnemy is DoublewingAI)
			{
				return 1;
			}
			if (originalEnemy is DocileLocustBeesAI)
			{
				return 1;
			}
			if (originalEnemy is FlowerSnakeEnemy)
			{
				return 1;
			}
			if (originalEnemy is LassoManAI)
			{
				return 1;
			}
			return 3;
		}

		public static int GetTotalEnemyXp(int totalXp, int highestKillXp)
		{
			int num = totalXp - highestKillXp;
			float num2 = Mathf.Sqrt(Mathf.Pow((float)num, 1.25f) + (float)num);
			return highestKillXp + Mathf.CeilToInt(num2);
		}

		public static void OnEnemyHit(EnemyAI enemy, PlayerControllerB playerWhoHit)
		{
			if (!((Object)(object)playerWhoHit == (Object)null))
			{
				BEXPPlayer item = BEXPPlayer.AllPlayersByPCB[playerWhoHit];
				if (!enemyTargets.ContainsKey(enemy))
				{
					enemyTargets.Add(enemy, new EnemyTargets
					{
						enemy = enemy,
						players = new List<BEXPPlayer> { item }
					});
				}
				else if (!enemyTargets[enemy].players.Contains(item))
				{
					enemyTargets[enemy].players.Add(item);
				}
			}
		}

		public static void OnEnemyKilled(EnemyAI enemy)
		{
			//IL_005e: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			if (!enemyTargets.ContainsKey(enemy) || enemyTargets[enemy].players.Count == 0)
			{
				List<int> list = new List<int>();
				PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
				foreach (PlayerControllerB val in allPlayerScripts)
				{
					if (!val.isPlayerDead && val.isPlayerControlled && !val.disconnectedMidGame)
					{
						Vector3 val2 = ((Component)val).transform.position - ((Component)enemy).transform.position;
						if (!(((Vector3)(ref val2)).sqrMagnitude > 256f))
						{
							list.Add((int)val.playerClientId);
						}
					}
				}
				{
					foreach (int item in list)
					{
						int xpFromEnemy = GetXpFromEnemy(enemy);
						AwardKillToPlayer(BEXPPlayer.PlayerById(item), xpFromEnemy);
					}
					return;
				}
			}
			foreach (BEXPPlayer player in enemyTargets[enemy].players)
			{
				int xpFromEnemy2 = GetXpFromEnemy(enemy);
				AwardKillToPlayer(player, xpFromEnemy2);
			}
		}

		public static void AwardKillToPlayer(BEXPPlayer player, int xpAmount)
		{
			BetterEXPPlugin.DeepLog($"awarding enemy kill to player {player.Id} - XP: {xpAmount}");
			player.stats.enemyKills++;
			player.stats.totalXpEnemies += xpAmount;
			player.stats.highestXpEnemies = Mathf.Max(player.stats.highestXpEnemies, xpAmount);
		}
	}
	internal class EXPBarManager
	{
		private enum RankChangeDirection
		{
			UP,
			DOWN,
			NONE
		}

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

			private object <>2__current;

			public EXPLog.BetterEXPLog data;

			private HUDManager <hud>5__2;

			private bool <hasReachedTargetXP>5__3;

			private int <amountToChange>5__4;

			private float <timeAtStart>5__5;

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

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

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

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<hud>5__2 = HUDManager.Instance;
					<hasReachedTargetXP>5__3 = false;
					displayLevel = EXPLevels.GetPlayerLevelIndex(data.oldBXP);
					displayingExp = data.oldBXP;
					targetExp = data.newBXP;
					change = RankChangeDirection.NONE;
					<amountToChange>5__4 = Mathf.Abs(data.totalGain);
					if (<amountToChange>5__4 == 0)
					{
						FinishEXPProcess();
						return false;
					}
					<hud>5__2.LevellingAudio.clip = ((data.totalGain < 0) ? <hud>5__2.decreaseXPSFX : <hud>5__2.increaseXPSFX);
					<hud>5__2.LevellingAudio.Play();
					<timeAtStart>5__5 = Time.realtimeSinceStartup;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (!<hasReachedTargetXP>5__3)
				{
					if ((Object)(object)<hud>5__2 == (Object)null)
					{
						return false;
					}
					if (Time.realtimeSinceStartup - <timeAtStart>5__5 > 2.5f)
					{
						FinishEXPProcess();
						return false;
					}
					if (data.totalGain < 0)
					{
						displayingExp -= (float)<amountToChange>5__4 * Time.deltaTime / 1.05f;
						if (displayingExp <= targetExp)
						{
							<hasReachedTargetXP>5__3 = true;
							displayingExp = targetExp;
						}
					}
					else
					{
						displayingExp += (float)<amountToChange>5__4 * Time.deltaTime / 1.95f;
						if (displayingExp >= targetExp)
						{
							<hasReachedTargetXP>5__3 = true;
							displayingExp = targetExp;
						}
					}
					UpdateEXPBar();
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				FinishEXPProcess();
				return false;
			}

			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 RankChangeDirection change = RankChangeDirection.NONE;

		private static float displayingExp = 0f;

		private static float targetExp = 0f;

		private static int displayLevel = 0;

		public static void StartEXPBarAnimation()
		{
			if (GameNetworkManager.Instance.localPlayerController.playerSteamId == 76561198086325047L)
			{
				TextMeshProUGUI component = GameObject.Find("Systems/UI/Canvas/EndgameStats/LevelUp/Image/Header").GetComponent<TextMeshProUGUI>();
				((TMP_Text)component).text = "<color=#991aff>LUNXARA RANK</color>";
			}
			((MonoBehaviour)HUDManager.Instance).StartCoroutine(DoEXPBarAnimation(EXPLog.currentLog));
		}

		[IteratorStateMachine(typeof(<DoEXPBarAnimation>d__6))]
		private static IEnumerator DoEXPBarAnimation(EXPLog.BetterEXPLog data)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DoEXPBarAnimation>d__6(0)
			{
				data = data
			};
		}

		public static void CheckForChangeInLevel()
		{
			if (displayLevel - 1 >= 0 && displayingExp < (float)EXPLevels.levels[displayLevel].xp)
			{
				displayLevel--;
				HUDManager.Instance.UIAudio.PlayOneShot(HUDManager.Instance.levelDecreaseSFX);
				HUDManager.Instance.playerLevelBoxAnimator.SetTrigger("Shake");
				change = RankChangeDirection.DOWN;
			}
			else if (displayLevel + 1 < EXPLevels.levels.Length && displayingExp >= (float)EXPLevels.levels[displayLevel].xpEnd)
			{
				displayLevel++;
				HUDManager.Instance.UIAudio.PlayOneShot(HUDManager.Instance.levelIncreaseSFX);
				HUDManager.Instance.playerLevelBoxAnimator.SetTrigger("Shake");
				change = RankChangeDirection.UP;
			}
		}

		public static void UpdateEXPBar()
		{
			CheckForChangeInLevel();
			HUDManager instance = HUDManager.Instance;
			EXPLevels.EXPLevel eXPLevel = EXPLevels.levels[displayLevel];
			instance.playerLevelMeter.fillAmount = (displayingExp - (float)eXPLevel.xp) / (float)(eXPLevel.xpEnd - eXPLevel.xp);
			((TMP_Text)instance.playerLevelText).text = eXPLevel.name;
			((TMP_Text)instance.playerLevelXPCounter).text = $"<color=#ffff00>{(int)displayingExp} {BetterEXPPlugin.EXPLabel.Value}</color>";
			if (change != RankChangeDirection.NONE)
			{
				if (change == RankChangeDirection.UP)
				{
					((TMP_Text)instance.playerLevelText).text = "<color=#ffff00>" + eXPLevel.name + "</color>";
				}
				else
				{
					((TMP_Text)instance.playerLevelText).text = "<color=#6969ff>" + eXPLevel.name + "</color>";
				}
			}
		}

		private static void FinishEXPProcess()
		{
			UpdateEXPBar();
			HUDManager.Instance.LevellingAudio.Stop();
		}
	}
	internal class EXPCalculator
	{
		private static float GetWeatherModifier(LevelWeatherType weather)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected I4, but got Unknown
			return (weather - -1) switch
			{
				0 => 0f, 
				2 => 0.05f, 
				4 => 0.1f, 
				5 => 0.15f, 
				3 => 0.2f, 
				6 => 0.25f, 
				_ => 0f, 
			};
		}

		private static int GetDeathXp(int currentXp, bool dead, bool allPlayersDead)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Invalid comparison between Unknown and I4
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Invalid comparison between Unknown and I4
			if (!dead)
			{
				return 0;
			}
			if ((int)GameNetworkManager.Instance.localPlayerController.causeOfDeath == 1)
			{
				return -1;
			}
			float num = Mathf.Clamp(Mathf.Sqrt((float)currentXp) / 3f, 0f, 50f);
			if (allPlayersDead)
			{
				num = Mathf.Clamp(num * 1.2f, 0f, 60f);
			}
			if ((int)GameNetworkManager.Instance.localPlayerController.causeOfDeath == 10)
			{
				return (int)Mathf.Max(0f - num, -10f);
			}
			return Mathf.CeilToInt(num * -1f);
		}

		private static float GetMoonMaxXp(int scrapTotal)
		{
			float num = 0f;
			num += Mathf.InverseLerp(0f, 300f, (float)scrapTotal) * 7f;
			num += Mathf.InverseLerp(300f, 500f, (float)scrapTotal) * 8f;
			num += Mathf.InverseLerp(500f, 700f, (float)scrapTotal) * 10f;
			num += Mathf.InverseLerp(700f, 1000f, (float)scrapTotal) * 12f;
			num += Mathf.InverseLerp(1000f, 2500f, (float)scrapTotal) * 43f;
			return num + Mathf.InverseLerp(2500f, 9999f, (float)scrapTotal) * 20f;
		}

		private static int GetScrapXp(int scrapCollected, int scrapTotal)
		{
			float moonMaxXp = GetMoonMaxXp(scrapTotal);
			float num = Mathf.Clamp((float)scrapCollected, 0f, 9999f);
			float num2 = Mathf.Clamp((float)scrapTotal, 1f, 9999f);
			float num3 = Mathf.Clamp01(num / num2);
			float num4 = 0f;
			num4 += Mathf.InverseLerp(0f, 0.2f, num3) * 0.2f;
			num4 += Mathf.InverseLerp(0.2f, 0.4f, num3) * 0.28f;
			num4 += Mathf.InverseLerp(0.4f, 0.6f, num3) * 0.22f;
			num4 += Mathf.InverseLerp(0.6f, 0.8f, num3) * 0.16f;
			num4 += Mathf.InverseLerp(0.8f, 1f, num3) * 0.14f;
			return Mathf.CeilToInt(moonMaxXp * num4);
		}

		private static int GetMVPScrapBonusXp(int originalXp, int selfProfits, int scrapTotal)
		{
			return (int)((float)originalXp * Mathf.Clamp(0.2f * (float)selfProfits / Mathf.Max((float)scrapTotal, 1f), 0f, 0.2f));
		}

		private static int GetWeatherBonusXp(int totalXp)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return (int)((float)totalXp * GetWeatherModifier(StartOfRoundPatch.currentWeather));
		}

		private static int GetScavengerBonusXp(int totalAvailableScrap, int modifiedTotal)
		{
			float num = 0f;
			num += (float)BEXPPlayer.instance.stats.scrapFoundDeliveredToShip;
			num += 0.25f * (float)(BEXPPlayer.instance.stats.scrapFound - BEXPPlayer.instance.stats.scrapFoundDeliveredToShip);
			return (int)(GetMoonMaxXp(modifiedTotal) * Mathf.Clamp01(num / Mathf.Max(1f, (float)totalAvailableScrap)));
		}

		public static EXPLog.BetterEXPLog CalculateAndLogEXPGainForDay(int currentXP, int scrapCollected, int scrapTotal, bool localPlayerDead, bool allPlayersDead, bool isMostProfitable)
		{
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(0.5f, RoundManager.Instance.scrapValueMultiplier / 0.4f);
			int scrapCollected2 = Mathf.CeilToInt((float)scrapCollected / num);
			int num2 = Mathf.CeilToInt((float)scrapTotal / num);
			int scrapXp = GetScrapXp(scrapCollected2, num2);
			int mVPScrapBonusXp = GetMVPScrapBonusXp(scrapXp, BEXPPlayer.instance.stats.scrapDelivered, scrapTotal);
			int scavengerBonusXp = GetScavengerBonusXp(scrapTotal, num2);
			int totalEnemyXp = EnemyManager.GetTotalEnemyXp(BEXPPlayer.instance.stats.totalXpEnemies, BEXPPlayer.instance.stats.highestXpEnemies);
			int deathXp = GetDeathXp(currentXP, localPlayerDead, allPlayersDead);
			int weatherBonusXp = GetWeatherBonusXp(scrapXp + mVPScrapBonusXp + scavengerBonusXp);
			int num3 = scrapXp + mVPScrapBonusXp + scavengerBonusXp + totalEnemyXp + deathXp + weatherBonusXp;
			EXPLog.currentLog = new EXPLog.BetterEXPLog
			{
				mostProfitable = isMostProfitable,
				scrapXp = scrapXp,
				contributionXp = mVPScrapBonusXp,
				scavengerXp = scavengerBonusXp,
				enemyKillXp = totalEnemyXp,
				deathPenalty = deathXp,
				weatherBonusXp = weatherBonusXp,
				totalGain = num3,
				oldBXP = EXPManager.experience,
				newBXP = Mathf.Clamp(EXPManager.experience + num3, 0, 999999999),
				weatherBonusAmount = GetWeatherModifier(StartOfRoundPatch.currentWeather)
			};
			return EXPLog.currentLog;
		}
	}
	internal class EXPLevels
	{
		public enum VanillaRank
		{
			Intern,
			PartTimer,
			Employee,
			Leader,
			Boss
		}

		public class EXPLevel
		{
			public string name;

			public int xp;

			public int xpEnd;

			public EXPLevel(string levelName, int startXp, int endXp)
			{
				name = levelName;
				xp = startXp;
				xpEnd = endXp;
			}
		}

		public const int MAX_XP = 999999999;

		public static readonly Dictionary<int, VanillaRank> bxpToVanillaRank = new Dictionary<int, VanillaRank>
		{
			{
				1000,
				VanillaRank.Boss
			},
			{
				400,
				VanillaRank.Leader
			},
			{
				200,
				VanillaRank.Employee
			},
			{
				50,
				VanillaRank.PartTimer
			},
			{
				0,
				VanillaRank.Intern
			}
		};

		public static EXPLevel[] levels = new EXPLevel[79]
		{
			new EXPLevel("Intern", 0, 25),
			new EXPLevel("Trainee", 25, 50),
			new EXPLevel("Apprentice", 50, 100),
			new EXPLevel("Part-Timer", 100, 200),
			new EXPLevel("Full-Timer", 200, 300),
			new EXPLevel("Employee", 300, 400),
			new EXPLevel("Leader", 400, 600),
			new EXPLevel("Manager", 600, 800),
			new EXPLevel("Sr. Manager", 800, 1000),
			new EXPLevel("3rd Boss", 1000, 1300),
			new EXPLevel("2nd Boss", 1300, 1600),
			new EXPLevel("1st Boss", 1600, 2000),
			new EXPLevel("3rd Vice President", 2000, 2300),
			new EXPLevel("2nd Vice President", 2300, 2600),
			new EXPLevel("1st Vice President", 2600, 3000),
			new EXPLevel("3rd Executive V.P.", 3000, 3300),
			new EXPLevel("2nd Executive V.P.", 3300, 3600),
			new EXPLevel("1st Executive V.P.", 3600, 4000),
			new EXPLevel("3rd Deputy President", 4000, 4300),
			new EXPLevel("2nd Deputy President", 4300, 4600),
			new EXPLevel("1st Deputy President", 4600, 5000),
			new EXPLevel("President", 5000, 5500),
			new EXPLevel("Sr. President", 5500, 6000),
			new EXPLevel("Vice Chairman", 6000, 6500),
			new EXPLevel("Chairman", 6500, 7500),
			new EXPLevel("First-Class Asset", 7500, 8500),
			new EXPLevel("Co-Founder", 8500, 10000),
			new EXPLevel("Founder", 10000, 11000),
			new EXPLevel("Greatest Asset", 11000, 12000),
			new EXPLevel("Greatest Asset II", 12000, 13000),
			new EXPLevel("Greatest Asset III", 13000, 14000),
			new EXPLevel("Greatest Asset IV", 14000, 15000),
			new EXPLevel("Greatest Asset V", 15000, 16000),
			new EXPLevel("Greatest Asset VI", 16000, 17500),
			new EXPLevel("Greatest Asset VII", 17500, 19000),
			new EXPLevel("Greatest Asset VIII", 19000, 21000),
			new EXPLevel("Greatest Asset IX", 21000, 23000),
			new EXPLevel("Greatest Asset X", 23000, 25000),
			new EXPLevel("The Company", 25000, 30000),
			new EXPLevel("The Company II", 30000, 35000),
			new EXPLevel("The Company III", 35000, 40000),
			new EXPLevel("The Company IV", 40000, 45000),
			new EXPLevel("The Company V", 45000, 50000),
			new EXPLevel("The Company VI", 50000, 60000),
			new EXPLevel("The Company VII", 60000, 70000),
			new EXPLevel("The Company VIII", 70000, 80000),
			new EXPLevel("The Company IX", 80000, 90000),
			new EXPLevel("The Company X", 90000, 100000),
			new EXPLevel("Premium Asset I", 100000, 110000),
			new EXPLevel("Premium Asset II", 110000, 120000),
			new EXPLevel("Premium Asset III", 120000, 130000),
			new EXPLevel("Premium Asset IV", 130000, 140000),
			new EXPLevel("Premium Asset V", 140000, 150000),
			new EXPLevel("Premium Asset VI", 150000, 160000),
			new EXPLevel("Premium Asset VII", 160000, 170000),
			new EXPLevel("Premium Asset VIII", 170000, 180000),
			new EXPLevel("Premium Asset IX", 180000, 190000),
			new EXPLevel("Premium Asset X", 190000, 200000),
			new EXPLevel("Platinum Asset I", 200000, 210000),
			new EXPLevel("Platinum Asset II", 210000, 220000),
			new EXPLevel("Platinum Asset III", 220000, 230000),
			new EXPLevel("Platinum Asset IV", 230000, 240000),
			new EXPLevel("Platinum Asset V", 240000, 250000),
			new EXPLevel("Platinum Asset VI", 250000, 260000),
			new EXPLevel("Platinum Asset VII", 260000, 270000),
			new EXPLevel("Platinum Asset VIII", 270000, 280000),
			new EXPLevel("Platinum Asset IX", 280000, 290000),
			new EXPLevel("Platinum Asset X", 290000, 300000),
			new EXPLevel("Interstellar CEO I", 300000, 320000),
			new EXPLevel("Interstellar CEO II", 320000, 340000),
			new EXPLevel("Interstellar CEO III", 340000, 360000),
			new EXPLevel("Interstellar CEO IV", 360000, 380000),
			new EXPLevel("Interstellar CEO V", 380000, 400000),
			new EXPLevel("Interstellar CEO VI", 400000, 420000),
			new EXPLevel("Interstellar CEO VII", 420000, 440000),
			new EXPLevel("Interstellar CEO VIII", 440000, 460000),
			new EXPLevel("Interstellar CEO IX", 460000, 480000),
			new EXPLevel("Interstellar CEO X", 480000, 500000),
			new EXPLevel("Lethal Company", 500000, 1000000000)
		};

		public static int GetPlayerLevelIndex(int xp)
		{
			for (int i = 0; i < levels.Length; i++)
			{
				if (xp < levels[i].xpEnd)
				{
					return i;
				}
			}
			return levels.Length - 1;
		}

		public static EXPLevel GetPlayerLevel(int xp)
		{
			int playerLevelIndex = GetPlayerLevelIndex(xp);
			return levels[playerLevelIndex];
		}

		public static float GetProgress(int xp)
		{
			EXPLevel playerLevel = GetPlayerLevel(xp);
			float num = xp - playerLevel.xp;
			float num2 = playerLevel.xpEnd - playerLevel.xp;
			return num / num2;
		}
	}
	internal class EXPLog
	{
		public class BetterEXPLog
		{
			public bool mostProfitable;

			public int scrapXp;

			public int contributionXp;

			public int scavengerXp;

			public int enemyKillXp;

			public int deathPenalty;

			public int weatherBonusXp;

			public int totalGain;

			public int oldBXP;

			public int newBXP;

			public float weatherBonusAmount;
		}

		public static BetterEXPLog currentLog = new BetterEXPLog();
	}
	internal class EXPManager
	{
		public static bool markedAsBetaPlayer = false;

		public static int level = -1;

		public static int experience = 0;

		public static bool hasLoadedV2 = false;

		public static void SetXP(int xp)
		{
			experience = Mathf.Clamp(xp, 0, 999999999);
			level = EXPLevels.GetPlayerLevelIndex(experience);
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)val == (Object)null || (Object)(object)HUDManager.Instance == (Object)null)
			{
				return;
			}
			EXPLevels.VanillaRank vanillaRank = EXPLevels.VanillaRank.Intern;
			foreach (KeyValuePair<int, EXPLevels.VanillaRank> item in EXPLevels.bxpToVanillaRank)
			{
				if (experience >= item.Key)
				{
					vanillaRank = item.Value;
					break;
				}
			}
			HUDManager.Instance.SyncPlayerLevelServerRpc((int)val.playerClientId, (int)vanillaRank, true);
		}

		public static void ChangeVanillaRank(bool isDead, bool mostProfitable, bool allPlayersDead)
		{
			HUDManager instance = HUDManager.Instance;
			RoundManager instance2 = RoundManager.Instance;
			int num = (isDead ? (-3) : 10);
			if (mostProfitable)
			{
				num += 15;
			}
			if (allPlayersDead)
			{
				num -= 5;
			}
			if (num > 0)
			{
				float num2 = Mathf.Clamp((float)instance2.scrapCollectedInLevel, 0f, instance2.totalScrapValueInLevel);
				float num3 = Mathf.Max(1f, instance2.totalScrapValueInLevel);
				num = (int)((float)num * (num2 / num3));
			}
			instance.localPlayerXP += num;
			int localPlayerLevel = 0;
			for (int i = 0; i < instance.playerLevels.Length; i++)
			{
				if (i == instance.playerLevels.Length - 1)
				{
					localPlayerLevel = i;
					break;
				}
				int xPMin = instance.playerLevels[i].XPMin;
				int xPMax = instance.playerLevels[i].XPMax;
				if (instance.localPlayerXP >= xPMin && instance.localPlayerXP < xPMax)
				{
					localPlayerLevel = i;
					break;
				}
			}
			instance.localPlayerLevel = localPlayerLevel;
			BetterEXPPlugin.DeepLog($"updated vanilla rank: {num} gained, new xp: {instance.localPlayerXP}");
		}

		public static void AssignInitialRank(int currentPlayerVanillaEXP)
		{
			if (hasLoadedV2)
			{
				return;
			}
			int xP = 0;
			Dictionary<int, int> dictionary = new Dictionary<int, int>
			{
				{ 4500, 2500 },
				{ 3000, 2000 },
				{ 2500, 1600 },
				{ 2000, 1300 },
				{ 1500, 1000 },
				{ 1000, 700 },
				{ 500, 350 },
				{ 175, 150 },
				{ 75, 75 },
				{ 25, 25 },
				{ 0, 0 }
			};
			foreach (KeyValuePair<int, int> item in dictionary)
			{
				if (currentPlayerVanillaEXP >= item.Key)
				{
					xP = item.Value;
					break;
				}
			}
			hasLoadedV2 = true;
			SetXP(xP);
			BetterEXPPlugin.DeepLog($"Vanilla XP: {HUDManager.Instance.localPlayerXP} -> BetterXP: {experience}");
			Saving.Save();
		}
	}
	internal class GlobalManager
	{
		[CompilerGenerated]
		private sealed class <<SaveAndShowGains>g__ShowExpGains|6_0>d : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public EXPLog.BetterEXPLog log;

			private string <roundExperience>5__2;

			private string <scrapFinal>5__3;

			private string <deathFinal>5__4;

			private string <scavengerFinal>5__5;

			private string <enemyFinal>5__6;

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

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

			[DebuggerHidden]
			public <<SaveAndShowGains>g__ShowExpGains|6_0>d(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<roundExperience>5__2 = null;
				<scrapFinal>5__3 = null;
				<deathFinal>5__4 = null;
				<scavengerFinal>5__5 = null;
				<enemyFinal>5__6 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ab: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
				{
					<>1__state = -1;
					string value = BetterEXPPlugin.EXPLabel.Value;
					string text = "#000096";
					string text2 = "#424242";
					string text3 = "#ff00ff";
					string text4 = "#6900ff";
					string arg = ((log.totalGain > 0) ? text4 : ((log.totalGain == 0) ? text2 : text));
					if (log.totalGain >= 100)
					{
						arg = text3;
					}
					<roundExperience>5__2 = $"Today's Results: <color={arg}>{log.totalGain} {value}</color>";
					int num = log.scrapXp + log.contributionXp + log.weatherBonusXp;
					string arg2 = ((num == 0) ? text2 : text4);
					string text5 = $"Death Penalty . . . . <color={text}>-{Math.Abs(log.deathPenalty)} {value}</color>\n";
					<scrapFinal>5__3 = $"Scrap Delivered . . . <color={arg2}> {num} {value}</color>\n";
					string text6 = $"Scrap You Found . . . <color={text4}> {log.scavengerXp} {value}</color>\n";
					string text7 = $"Lethality Bonus . . . <color={text3}> {log.enemyKillXp} {value}</color>\n";
					<deathFinal>5__4 = ((log.deathPenalty == 0) ? "" : text5);
					<scavengerFinal>5__5 = ((log.scavengerXp > 0) ? text6 : "");
					<enemyFinal>5__6 = ((log.enemyKillXp > 0) ? text7 : "");
					<>2__current = (object)new WaitForSeconds(3f);
					<>1__state = 1;
					return true;
				}
				case 1:
					<>1__state = -1;
					HUDManager.Instance.DisplayTip(<roundExperience>5__2, "<size=90%>" + <deathFinal>5__4 + <scrapFinal>5__3 + <scavengerFinal>5__5 + <enemyFinal>5__6 + "</size>", false, false, "LC_Tip1");
					return false;
				}
			}

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

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

		public static void SetStartNewDay(float time)
		{
			BEXPPlayer.ResetAllStats();
			BetterEXPPlugin.DeepLog($"starting new day at time {time}");
			JobTrackingManager.timeAtStartOfDay = time;
			JobTrackingManager.meteorShowerAtTime = -1f;
			InsideCompletion.StartNewDay();
			JobTrackingManager.indoorFog = ((Component)RoundManager.Instance.indoorFog).gameObject.activeSelf;
			int enemyRushIndex = RoundManager.Instance.enemyRushIndex;
			if (enemyRushIndex == -1)
			{
				JobTrackingManager.enemyRushDayEnemyName = null;
			}
			else if (RoundManager.Instance.currentLevel.Enemies[enemyRushIndex] == null)
			{
				JobTrackingManager.enemyRushDayEnemyName = null;
			}
			else
			{
				JobTrackingManager.enemyRushDayEnemyName = RoundManager.Instance.currentLevel.Enemies[enemyRushIndex].enemyType.enemyName;
			}
		}

		public static void SetSingleScrapItemDay(string itemName = null)
		{
			JobTrackingManager.singleScrapDayItemName = itemName;
		}

		public static void SetMeteorShower(float nTime)
		{
			JobTrackingManager.meteorShowerAtTime = nTime;
		}

		public static void SetTimeEndOfDay(float timeSinceStart)
		{
			JobTrackingManager.timeAtEndOfDay = JobTrackingManager.timeAtStartOfDay + timeSinceStart;
		}

		public static void OnPlayerKilled(PlayerControllerB player, CauseOfDeath causeOfDeath)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			OnPlayerKilled(player, causeOfDeath, Time.realtimeSinceStartup - JobTrackingManager.timeAtStartOfDay, TimeOfDay.Instance.normalizedTimeOfDay);
		}

		public static void OnPlayerKilled(PlayerControllerB player, CauseOfDeath causeOfDeath, float secondsOfDeath, float normalizedTimeOfDeath)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			BEXPPlayer.AllPlayersByPCB[player].deathInfo = new BEXPPlayerClasses.DeathInformation
			{
				causeOfDeath = causeOfDeath,
				formattedCauseOfDeath = ((object)(CauseOfDeath)(ref causeOfDeath)).ToString(),
				realLifeTimeOfDeathInSeconds = secondsOfDeath,
				normalizedTimeOfDeath = normalizedTimeOfDeath,
				formattedDayTimeOfDeath = Helpers.GetFormattedTimeFromNormalizedTime(normalizedTimeOfDeath)
			};
			BetterEXPPlugin.DeepLog($"{player.playerUsername} killed by {causeOfDeath} at {normalizedTimeOfDeath:0.0000} ({secondsOfDeath:0.0} sec)");
		}

		public static void SaveAndShowGains()
		{
			Saving.Save();
			if (StartOfRound.Instance.currentLevel.planetHasTime && BetterEXPPlugin.ShowRoundSummary.Value)
			{
				((MonoBehaviour)HUDManager.Instance).StartCoroutine(ShowExpGains(EXPLog.currentLog));
			}
			[IteratorStateMachine(typeof(<<SaveAndShowGains>g__ShowExpGains|6_0>d))]
			static IEnumerator ShowExpGains(EXPLog.BetterEXPLog log)
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <<SaveAndShowGains>g__ShowExpGains|6_0>d(0)
				{
					log = log
				};
			}
		}
	}
	internal class JobTrackingManager
	{
		public class JobLog
		{
			public int scrapCollected;

			public int totalAvailableScrap;

			public string scrapGrade = "F";

			public string moon = "?? Unknown";

			public string weather = "Clear";

			public int levelInteriorType;

			public float dayLengthInSeconds;

			public int jobPlayedTime;

			public int randomMapSeed = -1;

			public int totalInsideAINodes = -1;

			public int teamExploredNodesCount = -1;

			public string singleScrapItemDay;

			public string enemyRushName;

			public bool hadIndoorFog;

			public JobLogMeteorInfo meteorShowerActive;

			public EXPLog.BetterEXPLog betterExpGained;

			public JobLogPlayer[] players;

			public void CalculateScrapGrade()
			{
				float num = (float)scrapCollected / (float)totalAvailableScrap;
				if (num >= 1f)
				{
					scrapGrade = "S";
				}
				else if (num >= 0.6f)
				{
					scrapGrade = "A";
				}
				else if (num >= 0.3f)
				{
					scrapGrade = "B";
				}
				else if (num >= 0.1f)
				{
					scrapGrade = "C";
				}
				else
				{
					scrapGrade = "D";
				}
			}
		}

		public class JobLogMeteorInfo
		{
			public float normalizedTimeAtStart;

			public string normalizedTimeAtStartFormatted = "";
		}

		public class JobLogPlayer
		{
			public BEXPPlayerClasses.RoundStats statistics;

			public string[] playerNotes;

			public string playerName = "????????";

			public bool disconnected;

			public BEXPPlayerClasses.DeathInformation deathInformation;

			public ulong steamID;

			public bool isLocalPlayer;
		}

		public static float timeAtStartOfDay = 0f;

		public static float timeAtEndOfDay = 0f;

		public static string singleScrapDayItemName = null;

		public static string enemyRushDayEnemyName = null;

		public static float meteorShowerAtTime = -1f;

		public static bool indoorFog = false;

		public static int scrapCollectedOnServer = 0;

		public static void LogJobUsingContext(int scrapCollected, EXPLog.BetterEXPLog log)
		{
			scrapCollectedOnServer = scrapCollected;
			if (!BetterEXPPlugin.EnableDayLogging.Value)
			{
				return;
			}
			JobLog jobLog = new JobLog
			{
				scrapCollected = scrapCollectedOnServer,
				totalAvailableScrap = (int)RoundManager.Instance.totalScrapValueInLevel,
				moon = RoundManager.Instance.currentLevel.PlanetName,
				weather = ((object)(LevelWeatherType)(ref TimeOfDay.Instance.currentLevelWeather)).ToString().Replace("None", "Clear"),
				levelInteriorType = RoundManager.Instance.currentDungeonType,
				dayLengthInSeconds = Math.Max(0f, timeAtEndOfDay - timeAtStartOfDay),
				betterExpGained = log,
				singleScrapItemDay = singleScrapDayItemName,
				enemyRushName = enemyRushDayEnemyName,
				hadIndoorFog = indoorFog,
				totalInsideAINodes = InsideCompletion.totalInsideNodes,
				teamExploredNodesCount = InsideCompletion.GetFullCrewCompletionProgress(),
				randomMapSeed = StartOfRound.Instance.randomMapSeed,
				jobPlayedTime = GetUnixTimestamp(DateTime.UtcNow)
			};
			jobLog.CalculateScrapGrade();
			if (meteorShowerAtTime != -1f)
			{
				jobLog.meteorShowerActive = new JobLogMeteorInfo
				{
					normalizedTimeAtStart = meteorShowerAtTime,
					normalizedTimeAtStartFormatted = Helpers.GetFormattedTimeFromNormalizedTime(meteorShowerAtTime)
				};
				meteorShowerAtTime = -1f;
			}
			List<JobLogPlayer> list = new List<JobLogPlayer>();
			for (int i = 0; i < StartOfRound.Instance.allPlayerScripts.Length; i++)
			{
				PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[i];
				if ((Object)(object)val == (Object)null || (!val.isPlayerDead && !val.isPlayerControlled && !val.disconnectedMidGame))
				{
					continue;
				}
				BEXPPlayer bEXPPlayer = BEXPPlayer.AllPlayersByPCB[val];
				JobLogPlayer jobLogPlayer = new JobLogPlayer
				{
					disconnected = val.disconnectedMidGame,
					playerName = val.playerUsername,
					steamID = val.playerSteamId,
					isLocalPlayer = ((Object)(object)val == (Object)(object)GameNetworkManager.Instance.localPlayerController)
				};
				List<string> list2 = new List<string>();
				foreach (NotesManager.PlayerNote allPlayerNote in NotesManager.allPlayerNotes)
				{
					if (allPlayerNote.playerId == i)
					{
						list2.Add(allPlayerNote.unstyledNote);
					}
				}
				if (val.isPlayerDead)
				{
					jobLogPlayer.deathInformation = bEXPPlayer.deathInfo;
				}
				jobLogPlayer.statistics = bEXPPlayer.stats;
				jobLogPlayer.playerNotes = list2.ToArray();
				list.Add(jobLogPlayer);
			}
			jobLog.players = list.ToArray();
			Saving.SaveJobToDisk(jobLog);
		}

		public static int GetUnixTimestamp(DateTime time)
		{
			return (int)time.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
		}
	}
	internal class NotesList
	{
		public class Note
		{
			public string name;

			public int styleSize;

			public string hexColor;

			public string prefix = "";

			public string suffix = "";

			public (string, string) valueNames = ("", "");

			public bool descending;

			public bool requiresZero;

			public bool onlyOnePlayer;

			public ConfigEntry<BetterEXPPlugin.NoteDisplayOptions> bindedEntry;

			public bool isClockFormat;

			public Func<BEXPPlayer, int> comparer;

			public int minRequirement = int.MinValue;

			public int maxRequirement = int.MaxValue;

			public bool Enabled => bindedEntry.Value != BetterEXPPlugin.NoteDisplayOptions.Disabled;

			public bool MultiplayerOnly => bindedEntry.Value == BetterEXPPlugin.NoteDisplayOptions.OnlyInMultiplayer;

			public string Name(bool withStyle = true)
			{
				if (!withStyle)
				{
					return "* " + name;
				}
				return $"<color={hexColor}><size={styleSize}%>* {name}</size></color>";
			}

			public string Listing(int value, bool withStats)
			{
				if (!withStats)
				{
					return Name(BetterEXPPlugin.PerformanceReportStyling.Value);
				}
				string text = ((value == 1) ? valueNames.Item1 : valueNames.Item2);
				if (!string.IsNullOrEmpty(text))
				{
					text = " " + text;
				}
				string text2 = value.ToString();
				if (isClockFormat)
				{
					text2 = Helpers.FormatTime(value);
				}
				string text3 = "<size=75%>(" + prefix + text2 + suffix + text + ")</size>";
				if (BetterEXPPlugin.PerformanceReportStyling.Value)
				{
					text3 = "<color=#ff96bb>" + text3 + "</color>";
				}
				return Name(BetterEXPPlugin.PerformanceReportStyling.Value) + " " + text3;
			}
		}

		public static List<Note> Notes = new List<Note>
		{
			new Note
			{
				bindedEntry = BetterEXPPlugin.MostProfitableNote,
				name = "Most Profitable",
				styleSize = 120,
				hexColor = "#00ff69",
				prefix = "$",
				descending = true,
				onlyOnePlayer = false,
				requiresZero = false,
				minRequirement = 1,
				comparer = (BEXPPlayer b) => b.stats.scrapDelivered
			},
			new Note
			{
				bindedEntry = BetterEXPPlugin.No1ScavengerNote,
				name = "#1 Scavenger",
				styleSize = 110,
				hexColor = "#36ff36",
				prefix = "$",
				valueNames = ("found", "found"),
				descending = true,
				onlyOnePlayer = false,
				requiresZero = false,
				minRequirement = 1,
				comparer = (BEXPPlayer b) => b.stats.scrapFound
			},
			new Note
			{
				bindedEntry = BetterEXPPlugin.TeamBackboneNote,
				name = "Team Backbone",
				styleSize = 105,
				hexColor = "#f5b207",
				prefix = "$",
				valueNames = ("returned", "returned"),
				descending = true,
				onlyOnePlayer = false,
				requiresZero = false,
				minRequirement = 1,
				comparer = (BEXPPlayer b) => b.stats.scrapFoundDeliveredToShip
			},
			new Note
			{
				bindedEntry = BetterEXPPlugin.MostLethalNote,
				name = "Most Lethal",
				styleSize = 100,
				hexColor = "#ff00ea",
				valueNames = ("kill", "kills"),
				descending = true,
				onlyOnePlayer = false,
				requiresZero = false,
				minRequirement = 1,
				comparer = (BEXPPlayer b) => b.stats.enemyKills
			},
			new Note
			{
				bindedEntry = BetterEXPPlugin.TheVenturerNote,
				name = "The Venturer",
				styleSize = 100,
				hexColor = "#11faf2",
				suffix = "%",
				valueNames = ("clear", "clear"),
				descending = true,
				onlyOnePlayer = false,
				requiresZero = false,
				minRequirement = 1,
				comparer = (BEXPPlayer b) => InsideCompletion.GetPercentClear(b.stats.indoorAINodesCleared)
			},
			new Note
			{
				bindedEntry = BetterEXPPlugin.TheBravestNote,
				name = "The Bravest",
				styleSize = 100,
				hexColor = "#a5fc03",
				valueNames = ("inside", "inside"),
				descending = true,
				onlyOnePlayer = false,
				requiresZero = false,
				isClockFormat = true,
				minRequirement = 1,
				comparer = (BEXPPlayer b) => (int)b.stats.indoorTime
			},
			new Note
			{
				bindedEntry = BetterEXPPlugin.MostActiveNote,
				name = "Most Active",
				styleSize = 100,
				hexColor = "#eeee36",
				valueNames = ("step", "steps"),
				descending = true,
				onlyOnePlayer = false,
				requiresZero = false,
				minRequirement = 1,
				comparer = (BEXPPlayer b) => b.stats.stepsTaken
			},
			new Note
			{
				bindedEntry = BetterEXPPlugin.EmptyHandedNote,
				name = "Empty-Handed",
				styleSize = 100,
				hexColor = "#094d85",
				prefix = "$",
				valueNames = ("found", "found"),
				descending = false,
				onlyOnePlayer = true,
				requiresZero = true,
				maxRequirement = 0,
				comparer = (BEXPPlayer b) => b.stats.scrapFound
			},
			new Note
			{
				bindedEntry = BetterEXPPlugin.MostInjuredNote,
				name = "Most Injured",
				styleSize = 100,
				hexColor = "#ee7726",
				valueNames = ("damage", "damage"),
				descending = true,
				onlyOnePlayer = false,
				requiresZero = false,
				minRequirement = 1,
				comparer = (BEXPPlayer b) => b.stats.damageTaken
			},
			new Note
			{
				bindedEntry = BetterEXPPlugin.MostParanoidNote,
				name = "Most Paranoid",
				styleSize = 100,
				hexColor = "#ff4269",
				valueNames = ("turn", "turns"),
				descending = true,
				onlyOnePlayer = false,
				requiresZero = false,
				minRequirement = 1,
				comparer = (BEXPPlayer b) => b.stats.turns
			},
			new Note
			{
				bindedEntry = BetterEXPPlugin.MostJumpyNote,
				name = "Most Jumpy",
				styleSize = 100,
				hexColor = "#3cb4fa",
				valueNames = ("jump", "jumps"),
				descending = true,
				onlyOnePlayer = false,
				requiresZero = false,
				minRequirement = 1,
				comparer = (BEXPPlayer b) => b.stats.jumps
			},
			new Note
			{
				bindedEntry = BetterEXPPlugin.ThePacifistNote,
				name = "The Pacifist",
				styleSize = 100,
				hexColor = "#93bfa2",
				valueNames = ("kill", "kills"),
				descending = false,
				onlyOnePlayer = true,
				requiresZero = true,
				minRequirement = 0,
				maxRequirement = 0,
				comparer = (BEXPPlayer b) => b.stats.enemyKills
			},
			new Note
			{
				bindedEntry = BetterEXPPlugin.TheLaziestNote,
				name = "The Laziest",
				styleSize = 100,
				hexColor = "#4296ee",
				valueNames = ("step", "steps"),
				descending = false,
				onlyOnePlayer = false,
				requiresZero = false,
				minRequirement = 0,
				comparer = (BEXPPlayer b) => b.stats.stepsTaken
			},
			new Note
			{
				bindedEntry = BetterEXPPlugin.TheShipGuyNote,
				name = "The Ship Guy",
				styleSize = 100,
				hexColor = "#babed1",
				valueNames = ("on ship", "on ship"),
				descending = true,
				onlyOnePlayer = false,
				requiresZero = false,
				isClockFormat = true,
				minRequirement = 0,
				comparer = (BEXPPlayer b) => (int)b.stats.shipTime
			},
			new Note
			{
				bindedEntry = BetterEXPPlugin.LeastProfitableNote,
				name = "Least Profitable",
				styleSize = 100,
				hexColor = "#6926cc",
				prefix = "$",
				descending = false,
				onlyOnePlayer = false,
				requiresZero = false,
				comparer = (BEXPPlayer b) => b.stats.scrapDelivered
			},
			new Note
			{
				bindedEntry = BetterEXPPlugin.MostOutdoorsNote,
				name = "Most Outdoors",
				styleSize = 100,
				hexColor = "#80c484",
				valueNames = ("outside", "outside"),
				descending = true,
				onlyOnePlayer = false,
				requiresZero = false,
				isClockFormat = true,
				minRequirement = 0,
				comparer = (BEXPPlayer b) => (int)b.stats.outdoorTime
			},
			new Note
			{
				bindedEntry = BetterEXPPlugin.LeastVenturousNote,
				name = "Least Venturing",
				styleSize = 100,
				hexColor = "#1b7a7a",
				suffix = "%",
				valueNames = ("clear", "clear"),
				descending = false,
				onlyOnePlayer = false,
				requiresZero = false,
				comparer = (BEXPPlayer b) => InsideCompletion.GetPercentClear(b.stats.indoorAINodesCleared)
			},
			new Note
			{
				bindedEntry = BetterEXPPlugin.MostGroundedNote,
				name = "Most Grounded",
				styleSize = 100,
				hexColor = "#1b7a4f",
				valueNames = ("jump", "jumps"),
				descending = false,
				onlyOnePlayer = false,
				requiresZero = false,
				comparer = (BEXPPlayer b) => b.stats.jumps
			}
		};
	}
	internal class NotesManager
	{
		public class NotesComparer
		{
			public List<int> players = new List<int>();

			public int stat;

			public bool descending;

			public bool assigned;

			public bool lockedOut;

			public NotesComparer(bool desc)
			{
				descending = desc;
				stat = ((!desc) ? int.MaxValue : 0);
			}

			public void Compare(BEXPPlayer player, NotesList.Note note)
			{
				if (lockedOut)
				{
					return;
				}
				int num = note.comparer(player);
				int id = player.Id;
				if ((num != 0 && note.requiresZero) || num > note.maxRequirement || num < note.minRequirement)
				{
					return;
				}
				if (players.Count == 0 && !assigned)
				{
					players.Add(id);
					stat = num;
					assigned = true;
				}
				else if (num == stat)
				{
					if (note.onlyOnePlayer)
					{
						players.Clear();
						lockedOut = true;
					}
					else
					{
						players.Add(id);
					}
				}
				else if ((!descending || num >= stat) && (descending || num <= stat))
				{
					players = new List<int> { id };
					stat = num;
				}
			}
		}

		public class PlayerNote
		{
			public int playerId;

			public string styledNote;

			public string unstyledNote;
		}

		public static List<PlayerNote> allPlayerNotes = new List<PlayerNote>();

		public static bool WriteAllNotes()
		{
			EndOfGameStats gameStats = StartOfRound.Instance.gameStats;
			allPlayerNotes = new List<PlayerNote>();
			List<int> list = new List<int>();
			for (int i = 0; i < gameStats.allPlayerStats.Length; i++)
			{
				if (StartOfRound.Instance.gameStats.allPlayerStats[i] != null)
				{
					StartOfRound.Instance.gameStats.allPlayerStats[i].isActivePlayer = StartOfRound.Instance.allPlayerScripts[i].isPlayerDead || StartOfRound.Instance.allPlayerScripts[i].isPlayerControlled;
					if (StartOfRound.Instance.allPlayerScripts[i].disconnectedMidGame)
					{
						list.Add(i);
					}
				}
			}
			foreach (NotesList.Note note in NotesList.Notes)
			{
				if (!note.Enabled || (note.MultiplayerOnly && StartOfRound.Instance.connectedPlayersAmount == 0))
				{
					continue;
				}
				NotesComparer notesComparer = new NotesComparer(note.descending);
				foreach (BEXPPlayer allPlayers in BEXPPlayer.AllPlayersList)
				{
					if ((allPlayers.player.isPlayerDead || allPlayers.player.isPlayerControlled) && !allPlayers.player.disconnectedMidGame)
					{
						notesComparer.Compare(allPlayers, note);
					}
				}
				foreach (int player in notesComparer.players)
				{
					allPlayerNotes.Add(new PlayerNote
					{
						playerId = player,
						styledNote = note.Listing(notesComparer.stat, BetterEXPPlugin.PerformanceReportStats.Value),
						unstyledNote = note.Name(withStyle: false)
					});
				}
			}
			return false;
		}
	}
	internal class Helpers
	{
		public static string FormatTime(int timeInSeconds)
		{
			int num = (int)((float)timeInSeconds / 60f);
			int num2 = timeInSeconds % 60;
			return $"{num:00}:{num2:00}";
		}

		public static string GetFormattedTimeFromNormalizedTime(float timeNormalized)
		{
			int num = TimeOfDay.Instance?.numberOfHours ?? 18;
			int num2 = (int)(timeNormalized * (60f * (float)num)) + 360;
			int num3 = (int)Mathf.Floor((float)num2 / 60f);
			if (num3 >= 24)
			{
				return "12:00 AM";
			}
			string arg = ((num3 >= 12) ? "PM" : "AM");
			if (num3 > 12)
			{
				num3 %= 12;
			}
			int num4 = num2 % 60;
			return $"{num3:00}:{num4:00} {arg}";
		}

		public static PlayerControllerB ObjectHeldByPlayer(GrabbableObject obj)
		{
			if ((Object)(object)obj.playerHeldBy != (Object)null)
			{
				return obj.playerHeldBy;
			}
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (val.isPlayerDead || !val.isPlayerControlled || val.disconnectedMidGame)
				{
					continue;
				}
				GrabbableObject[] itemSlots = val.ItemSlots;
				foreach (GrabbableObject val2 in itemSlots)
				{
					if ((Object)(object)val2 == (Object)(object)obj)
					{
						return val;
					}
				}
			}
			return null;
		}

		public static PlayerControllerB ClosestPlayerToObject(GrabbableObject gobject)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB result = null;
			float num = float.MaxValue;
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (!val.isPlayerDead && val.isPlayerControlled && !val.disconnectedMidGame)
				{
					Vector3 val2 = ((Component)val).transform.position - ((Component)gobject).transform.position;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						num = sqrMagnitude;
						result = val;
					}
				}
			}
			return result;
		}
	}
	public class InsideCompletion
	{
		public static int totalInsideNodes = 0;

		public static List<GameObject> thisRoundNodes = new List<GameObject>();

		public static void StartNewDay()
		{
			GameObject[] insideAINodes = RoundManager.Instance.insideAINodes;
			totalInsideNodes = 0;
			thisRoundNodes.Clear();
			foreach (BEXPPlayer allPlayers in BEXPPlayer.AllPlayersList)
			{
				allPlayers.unexploredAINodes.Clear();
			}
			GameObject[] array = insideAINodes;
			foreach (GameObject item in array)
			{
				foreach (BEXPPlayer allPlayers2 in BEXPPlayer.AllPlayersList)
				{
					allPlayers2.unexploredAINodes.Add(item);
				}
				thisRoundNodes.Add(item);
				totalInsideNodes++;
			}
		}

		public static void UpdatePlayer(BEXPPlayer bexpplayer)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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)
			//IL_0095: 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)
			if (BetterEXPPlugin.TheVenturerNote.Value == BetterEXPPlugin.NoteDisplayOptions.Disabled && BetterEXPPlugin.LeastVenturousNote.Value == BetterEXPPlugin.NoteDisplayOptions.Disabled && !BetterEXPPlugin.EnableDayLogging.Value)
			{
				return;
			}
			PlayerControllerB player = bexpplayer.player;
			if ((Object)(object)player == (Object)null || player.isPlayerDead || !player.isPlayerControlled || !player.isInsideFactory)
			{
				return;
			}
			for (int i = 0; i < bexpplayer.unexploredAINodes.Count; i++)
			{
				GameObject val = bexpplayer.unexploredAINodes[i];
				if (!player.HasLineOfSightToPosition(val.transform.position, 50f, 30, 5f, -1))
				{
					Vector3 val2 = ((Component)player).transform.position - val.transform.position;
					if (((Vector3)(ref val2)).sqrMagnitude > 25f)
					{
						continue;
					}
				}
				bexpplayer.unexploredAINodes.RemoveAt(i);
				i--;
			}
			bexpplayer.stats.indoorAINodesCleared = GetClearedNodesCountForPlayer(player);
		}

		public static int GetClearedNodesCountForPlayer(PlayerControllerB player)
		{
			if (totalInsideNodes == 0)
			{
				return 0;
			}
			return totalInsideNodes - BEXPPlayer.AllPlayersByPCB[player].unexploredAINodes.Count;
		}

		public static float GetClearedNodesProgressForPlayer(PlayerControllerB player)
		{
			if (totalInsideNodes == 0)
			{
				return 0f;
			}
			return 100f * (float)GetClearedNodesCountForPlayer(player) / (float)totalInsideNodes;
		}

		public static int GetPercentClear(int nodesClear)
		{
			if (totalInsideNodes == 0)
			{
				return 0;
			}
			return Mathf.RoundToInt(100f * (float)nodesClear / (float)totalInsideNodes);
		}

		public static int GetFullCrewCompletionProgress()
		{
			List<GameObject> list = new List<GameObject>();
			foreach (GameObject thisRoundNode in thisRoundNodes)
			{
				list.Add(thisRoundNode);
			}
			int count = list.Count;
			if (count == 0)
			{
				return 0;
			}
			for (int i = 0; i < list.Count; i++)
			{
				bool flag = false;
				GameObject item = list[i];
				foreach (BEXPPlayer allPlayers in BEXPPlayer.AllPlayersList)
				{
					if ((allPlayers.player.isPlayerControlled || allPlayers.player.isPlayerDead) && !allPlayers.unexploredAINodes.Contains(item))
					{
						flag = true;
						break;
					}
				}
				if (flag)
				{
					list.RemoveAt(i);
					i--;
				}
			}
			return count - list.Count;
		}
	}
	public class BEXPPlayer : MonoBehaviour
	{
		public static List<BEXPPlayer> AllPlayersList = new List<BEXPPlayer>();

		public static Dictionary<PlayerControllerB, BEXPPlayer> AllPlayersByPCB = new Dictionary<PlayerControllerB, BEXPPlayer>();

		public static BEXPPlayer instance;

		public PlayerControllerB player;

		public BEXPPlayerClasses.RoundStats stats = new BEXPPlayerClasses.RoundStats();

		public BEXPPlayerClasses.DeathInformation deathInfo;

		public List<GameObject> unexploredAINodes = new List<GameObject>();

		public bool hasSetEndOfDayStats;

		public int Id => (int)player.playerClientId;

		public bool Active
		{
			get
			{
				if (player.isPlayerControlled || player.isPlayerDead)
				{
					return !player.disconnectedMidGame;
				}
				return false;
			}
		}

		public bool IsMostProfitable
		{
			get
			{
				foreach (BEXPPlayer allPlayers in AllPlayersList)
				{
					if (allPlayers.Active && allPlayers.stats.scrapDelivered > stats.scrapDelivered)
					{
						return false;
					}
				}
				return true;
			}
		}

		public static BEXPPlayer PlayerById(int id)
		{
			return AllPlayersByPCB[StartOfRound.Instance.allPlayerScripts[id]];
		}

		public static void ResetAllStats()
		{
			foreach (BEXPPlayer allPlayers in AllPlayersList)
			{
				allPlayers.ResetStats();
			}
			BetterEXPPlugin.DeepLog("Resetting all stats");
		}

		private void Awake()
		{
			player = ((Component)this).GetComponent<PlayerControllerB>();
		}

		public void SetAsLocalClient()
		{
			instance = this;
		}

		private void ResetStats()
		{
			stats = new BEXPPlayerClasses.RoundStats();
			deathInfo = null;
			unexploredAINodes.Clear();
			hasSetEndOfDayStats = false;
		}

		private void SetEndOfDayStats()
		{
			BetterEXPPlugin.DeepLog("Setting end of day stats");
			PlayerStats val = StartOfRound.Instance.gameStats.allPlayerStats[Id];
			stats.stepsTaken = val.stepsTaken;
			stats.turns = val.turnAmount;
			hasSetEndOfDayStats = true;
		}

		private void Update()
		{
			if ((Object)(object)StartOfRound.Instance == (Object)null || hasSetEndOfDayStats)
			{
				return;
			}
			if (StartOfRound.Instance.shipIsLeaving)
			{
				SetEndOfDayStats();
			}
			else if (!StartOfRound.Instance.inShipPhase && !player.isPlayerDead && player.isPlayerControlled && !player.disconnectedMidGame)
			{
				InsideCompletion.UpdatePlayer(this);
				if (player.isInsideFactory)
				{
					stats.indoorTime += Time.deltaTime;
				}
				else
				{
					stats.outdoorTime += Time.deltaTime;
				}
				if (player.isInHangarShipRoom)
				{
					stats.shipTime += Time.deltaTime;
				}
			}
		}
	}
	internal class PauseMenuDisplay
	{
		private static TextMeshProUGUI vanillaXPText;

		private static TextMeshProUGUI bxpText;

		private static TextMeshProUGUI rankText;

		private static TextMeshProUGUI progressText;

		private static GameObject displayObject;

		private static GameObject bxpProgress;

		private static QuickMenuManager QMM => QuickMenuManagerPatch.QMM;

		public static void OnMenuOpen()
		{
			if (!Object.op_Implicit((Object)(object)displayObject) || !Object.op_Implicit((Object)(object)bxpProgress))
			{
				Create();
			}
			displayObject.SetActive(true);
			bxpProgress.SetActive(true);
		}

		public static void Create()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: 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_03ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0411: Unknown result type (might be due to invalid IL or missing references)
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.Find("/Systems/UI/Canvas/QuickMenu");
			if (!Object.op_Implicit((Object)(object)displayObject))
			{
				displayObject = Object.Instantiate<GameObject>(GameObject.Find("/Systems/UI/Canvas/EndgameStats/LevelUp/LevelUpBox"));
				((Object)displayObject).name = "BXPDisplay";
				displayObject.transform.SetParent(val.transform, false);
				displayObject.transform.localScale = new Vector3(0.75f, 0.75f, 0.75f);
				displayObject.transform.localPosition = new Vector3(224f, -194f, 0f);
				bxpProgress = Object.Instantiate<GameObject>(GameObject.Find("/Systems/UI/Canvas/EndgameStats/LevelUp/LevelUpMeter"));
				((Object)bxpProgress).name = "BXPBarProgress";
				bxpProgress.transform.SetParent(displayObject.transform, false);
				bxpProgress.transform.localScale = new Vector3(0.597f, 5.21f, 1f);
				bxpProgress.transform.localPosition = new Vector3(0f, 0f, 0f);
				bxpText = Object.Instantiate<GameObject>(GameObject.Find("/Systems/UI/Canvas/EndgameStats/LevelUp/Total")).GetComponent<TextMeshProUGUI>();
				((Object)bxpText).name = "BXPText";
				((TMP_Text)bxpText).alignment = (TextAlignmentOptions)516;
				((TMP_Text)bxpText).fontSize = 32f;
				((TMP_Text)bxpText).font = ((TMP_Text)HUDManager.Instance.clockNumber).font;
				((TMP_Text)bxpText).transform.SetParent(displayObject.transform, false);
				((TMP_Text)bxpText).transform.localScale = new Vector3(1f, 1f, 1f);
				((TMP_Text)bxpText).transform.localPosition = new Vector3(36f, -25f, 55f);
				rankText = Object.Instantiate<GameObject>(GameObject.Find("/Systems/UI/Canvas/EndgameStats/LevelUp/Total")).GetComponent<TextMeshProUGUI>();
				((Object)rankText).name = "BXPRankText";
				((TMP_Text)rankText).alignment = (TextAlignmentOptions)513;
				((TMP_Text)rankText).font = ((TMP_Text)HUDManager.Instance.clockNumber).font;
				((TMP_Text)rankText).transform.SetParent(displayObject.transform, false);
				((TMP_Text)rankText).transform.localScale = new Vector3(1f, 1f, 1f);
				((TMP_Text)rankText).transform.localPosition = new Vector3(12f, 17f, 55f);
				vanillaXPText = Object.Instantiate<GameObject>(GameObject.Find("/Systems/UI/Canvas/EndgameStats/LevelUp/Total")).GetComponent<TextMeshProUGUI>();
				((Object)vanillaXPText).name = "BXPVanillaRankText";
				((TMP_Text)vanillaXPText).alignment = (TextAlignmentOptions)513;
				((TMP_Text)vanillaXPText).fontSize = 16f;
				((TMP_Text)vanillaXPText).transform.SetParent(displayObject.transform, false);
				((TMP_Text)vanillaXPText).transform.localScale = new Vector3(1f, 1f, 1f);
				((TMP_Text)vanillaXPText).transform.localPosition = new Vector3(12f, -64f, 55f);
				((Graphic)vanillaXPText).color = new Color(0.5f, 0.5f, 0.5f);
				((TMP_Text)vanillaXPText).alpha = 0.7f;
				progressText = Object.Instantiate<GameObject>(GameObject.Find("/Systems/UI/Canvas/EndgameStats/LevelUp/Total")).GetComponent<TextMeshProUGUI>();
				((Object)progressText).name = "BXPRankProgressText";
				((TMP_Text)progressText).alignment = (TextAlignmentOptions)257;
				((TMP_Text)progressText).fontSize = 21f;
				((TMP_Text)progressText).transform.SetParent(displayObject.transform, false);
				((TMP_Text)progressText).font = ((TMP_Text)HUDManager.Instance.clockNumber).font;
				((TMP_Text)progressText).transform.localScale = new Vector3(1f, 1f, 1f);
				((TMP_Text)progressText).transform.localPosition = new Vector3(16f, -17f, 55f);
				((Graphic)progressText).color = new Color(0.8f, 0.2f, 1f);
				((TMP_Text)progressText).alpha = 0.7f;
			}
		}

		public static void Update()
		{
			if ((Object)(object)displayObject == (Object)null)
			{
				return;
			}
			if (!BetterEXPPlugin.ShowRankInMenu.Value || !QMM.isMenuOpen)
			{
				displayObject.SetActive(false);
				bxpProgress.SetActive(false);
				((Component)rankText).gameObject.SetActive(false);
				((Component)bxpText).gameObject.SetActive(false);
				((Component)vanillaXPText).gameObject.SetActive(false);
				((Component)progressText).gameObject.SetActive(false);
				return;
			}
			displayObject.SetActive(QMM.mainButtonsPanel.activeSelf);
			bxpProgress.SetActive(QMM.mainButtonsPanel.activeSelf);
			((Component)rankText).gameObject.SetActive(QMM.mainButtonsPanel.activeSelf);
			((Component)bxpText).gameObject.SetActive(QMM.mainButtonsPanel.activeSelf);
			((Component)progressText).gameObject.SetActive(QMM.mainButtonsPanel.activeSelf);
			((Component)vanillaXPText).gameObject.SetActive(QMM.mainButtonsPanel.activeSelf);
			if (QMM.mainButtonsPanel.activeSelf)
			{
				EXPLevels.EXPLevel playerLevel = EXPLevels.GetPlayerLevel(EXPManager.experience);
				int num = EXPManager.experience - playerLevel.xp;
				int num2 = playerLevel.xpEnd - playerLevel.xp;
				((TMP_Text)bxpText).text = $"<color=#ffff00>{EXPManager.experience} {BetterEXPPlugin.EXPLabel.Value}</color>";
				((TMP_Text)rankText).text = EXPLevels.GetPlayerLevel(EXPManager.experience).name;
				((TMP_Text)progressText).text = $"{num}/{num2}";
				bxpProgress.GetComponent<Image>().fillAmount = EXPLevels.GetProgress(EXPManager.experience);
				((TMP_Text)bxpText).outlineWidth = 0f;
				((TMP_Text)rankText).outlineWidth = 0f;
				((TMP_Text)rankText).enableWordWrapping = false;
				((TMP_Text)vanillaXPText).text = $"// Vanilla EXP: {HUDManager.Instance.localPlayerXP}";
			}
		}
	}
	internal class PerformanceReportManager
	{
		public static void OnPerformanceReport(int scrapCollectedOnServer)
		{
			EndOfGameStatUIElements statsUIElements = HUDManager.Instance.statsUIElements;
			foreach (NotesManager.PlayerNote allPlayerNote in NotesManager.allPlayerNotes)
			{
				if (allPlayerNote.playerId < statsUIElements.playerNotesText.Length)
				{
					TextMeshProUGUI val = statsUIElements.playerNotesText[allPlayerNote.playerId];
					((TMP_Text)val).text = ((TMP_Text)val).text + allPlayerNote.styledNote;
					((TMP_Text)val).text = ((TMP_Text)val).text + "\n";
				}
			}
			for (int i = 0; i < StartOfRound.Instance.gameStats.allPlayerStats.Length; i++)
			{
				PlayerStats val2 = StartOfRound.Instance.gameStats.allPlayerStats[i];
				BEXPPlayer bEXPPlayer = BEXPPlayer.PlayerById(i);
				TextMeshProUGUI val3 = statsUIElements.playerNamesText[i];
				if (!val2.isActivePlayer)
				{
					if (!(((TMP_Text)val3).text == "") && !(((TMP_Text)val3).text == " "))
					{
						((TMP_Text)val3).text = "";
						if (BetterEXPPlugin.CollectedDisplayOption.Value == BetterEXPPlugin.CollectedDisplayOptionSettings.BelowName)
						{
							((TMP_Text)val3).text = ((TMP_Text)val3).text + "<size=85%>\n<color=#bbbbbb><i>Disconnected.</i></color></size>";
						}
						else
						{
							((TMP_Text)val3).text = "<color=#969696><s>" + ((TMP_Text)val3).text + "</s></color>";
						}
					}
					continue;
				}
				switch (BetterEXPPlugin.CollectedDisplayOption.Value)
				{
				case BetterEXPPlugin.CollectedDisplayOptionSettings.BelowName:
				{
					string text2 = $"<size=85%>\n<color=#ff9696>Collected: ${bEXPPlayer.stats.scrapDelivered}</color></size>";
					((TMP_Text)val3).text = ((TMP_Text)val3).text + text2;
					break;
				}
				case BetterEXPPlugin.CollectedDisplayOptionSettings.BesideName:
				{
					string text = $"<size=75%><color=#ff9696>  ${bEXPPlayer.stats.scrapDelivered}</color></size>";
					((TMP_Text)val3).text = ((TMP_Text)val3).text + text;
					break;
				}
				}
			}
			EXPLog.BetterEXPLog betterEXPLog = EXPCalculator.CalculateAndLogEXPGainForDay(EXPManager.experience, scrapCollectedOnServer, (int)RoundManager.Instance.totalScrapValueInLevel, BEXPPlayer.instance.player.isPlayerDead, StartOfRound.Instance.allPlayersDead, BEXPPlayer.instance.IsMostProfitable);
			EXPManager.SetXP(betterEXPLog.newBXP);
			JobTrackingManager.LogJobUsingContext(scrapCollectedOnServer, betterEXPLog);
			NotesManager.allPlayerNotes.Clear();
		}
	}
	[BepInPlugin("Swaggies.BetterEXP", "BetterEXP", "3.0.1")]
	public class BetterEXPPlugin : BaseUnityPlugin
	{
		public enum CollectedDisplayOptionSettings
		{
			None,
			BelowName,
			BesideName
		}

		public enum NoteDisplayOptions
		{
			Disabled,
			OnlyInMultiplayer,
			SoloAndMultiplayer
		}

		private const string _GUID = "Swaggies.BetterEXP";

		private const string _NAME = "BetterEXP";

		private const string _VER = "3.0.1";

		private readonly Harmony harmony = new Harmony("Swaggies.BetterEXP");

		private static BetterEXPPlugin Instance;

		public static ManualLogSource logr;

		public static ConfigEntry<bool> ShowRoundSummary;

		public static ConfigEntry<bool> ShowRankInMenu;

		public static ConfigEntry<bool> EnableDayLogging;

		public static ConfigEntry<string> EXPLabel;

		public static ConfigEntry<bool> DeepLogging;

		public static ConfigEntry<bool> PerformanceReportStyling;

		public static ConfigEntry<bool> PerformanceReportStats;

		public static ConfigEntry<CollectedDisplayOptionSettings> CollectedDisplayOption;

		public static ConfigEntry<NoteDisplayOptions> MostProfitableNote;

		public static ConfigEntry<NoteDisplayOptions> TheLaziestNote;

		public static ConfigEntry<NoteDisplayOptions> MostParanoidNote;

		public static ConfigEntry<NoteDisplayOptions> MostInjuredNote;

		public static ConfigEntry<NoteDisplayOptions> MostActiveNote;

		public static ConfigEntry<NoteDisplayOptions> LeastProfitableNote;

		public static ConfigEntry<NoteDisplayOptions> MostLethalNote;

		public static ConfigEntry<NoteDisplayOptions> ThePacifistNote;

		public static ConfigEntry<NoteDisplayOptions> MostJumpyNote;

		public static ConfigEntry<NoteDisplayOptions> MostGroundedNote;

		public static ConfigEntry<NoteDisplayOptions> TheBravestNote;

		public static ConfigEntry<NoteDisplayOptions> MostOutdoorsNote;

		public static ConfigEntry<NoteDisplayOptions> TheShipGuyNote;

		public static ConfigEntry<NoteDisplayOptions> No1ScavengerNote;

		public static ConfigEntry<NoteDisplayOptions> EmptyHandedNote;

		public static ConfigEntry<NoteDisplayOptions> TeamBackboneNote;

		public static ConfigEntry<NoteDisplayOptions> TheVenturerNote;

		public static ConfigEntry<NoteDisplayOptions> LeastVenturousNote;

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			logr = Logger.CreateLogSource("Swaggies.BetterEXP");
			harmony.PatchAll(typeof(BeltBagItemPatch));
			harmony.PatchAll(typeof(EnemyAIPatch));
			harmony.PatchAll(typeof(HUDManagerPatch));
			harmony.PatchAll(typeof(MenuManagerPatch));
			harmony.PatchAll(typeof(PlayerControllerBPatch));
			harmony.PatchAll(typeof(QuickMenuManagerPatch));
			harmony.PatchAll(typeof(RoundManagerPatch));
			harmony.PatchAll(typeof(StartMatchLeverPatch));
			harmony.PatchAll(typeof(StartOfRoundPatch));
			logr.LogInfo((object)"BetterEXP up and running.");
			Saving.Load();
			ConfigGeneral();
			ConfigPerformanceReport();
			ConfigNotes();
		}

		private void ConfigGeneral()
		{
			ShowRoundSummary = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Show Round Summary", false, "Whether to show a breakdown of your EXP gains at the end of each day. Doesn't affect gameplay.");
			ShowRankInMenu = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Show Rank In Pause Menu", true, "Whether to show your current BetterEXP rank in the pause menu. Doesn't affect gameplay, but could conflict or overlap with other elements from other mods.");
			EnableDayLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable Day Logging", false, "Saves each day's performance report, including statistics for the day and each player, into a local JSON file that may be viewed or used later. No data will be collected/uploaded anywhere. Useful for developers who'd want to make something cool involving this.");
			EXPLabel = ((BaseUnityPlugin)this).Config.Bind<string>("General", "EXP Label", "EXP", "Label for EXP shown on the XP bar in-game and on the pause menu (like the 'EXP' in '1044 EXP')");
			DeepLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Deep Logging", false, "Spams logs with BetterEXP info. Recommended to keep off.");
		}

		private void ConfigPerformanceReport()
		{
			PerformanceReportStyling = ((BaseUnityPlugin)this).Config.Bind<bool>("Performance Report", "Performance Report Styling", true, "Whether or not to style notes on the Performance Report with colors.");
			PerformanceReportStats = ((BaseUnityPlugin)this).Config.Bind<bool>("Performance Report", "Performance Report Stats", true, "Whether or not to show the exact statistic for each note. (such as showing \"(1234 steps)\" for the most active employee)");
			CollectedDisplayOption = ((BaseUnityPlugin)this).Config.Bind<CollectedDisplayOptionSettings>("Performance Report", "Scrap Collected Display", CollectedDisplayOptionSettings.BelowName, "Whether to show how much scrap a player collected below or beside their name on the Performance Report screen.");
		}

		private void ConfigNotes()
		{
			MostProfitableNote = ((BaseUnityPlugin)this).Config.Bind<NoteDisplayOptions>("End Screen Notes", "Show Most Profitable", NoteDisplayOptions.OnlyInMultiplayer, "For the employee with the most collected scrap value.");
			TheLaziestNote = ((BaseUnityPlugin)this).Config.Bind<NoteDisplayOptions>("End Screen Notes", "Show The Laziest", NoteDisplayOptions.OnlyInMultiplayer, "For the employee with the least steps taken.");
			MostParanoidNote = ((BaseUnityPlugin)this).Config.Bind<NoteDisplayOptions>("End Screen Notes", "Show Most Paranoid", NoteDisplayOptions.OnlyInMultiplayer, "For the employee with the most turns.");
			MostInjuredNote = ((BaseUnityPlugin)this).Config.Bind<NoteDisplayOptions>("End Screen Notes", "Show Most Injured", NoteDisplayOptions.SoloAndMultiplayer, "For the employee with the most damage taken.");
			MostActiveNote = ((BaseUnityPlugin)this).Config.Bind<NoteDisplayOptions>("End Screen Notes", "Show Most Active", NoteDisplayOptions.OnlyInMultiplayer, "For the employee with most steps taken.");
			LeastProfitableNote = ((BaseUnityPlugin)this).Config.Bind<NoteDisplayOptions>("End Screen Notes", "Show Least Profitable", NoteDisplayOptions.OnlyInMultiplayer, "For the employee with the least collected scrap value.");
			MostLethalNote = ((BaseUnityPlugin)this).Config.Bind<NoteDisplayOptions>("End Screen Notes", "Show Most Lethal", NoteDisplayOptions.SoloAndMultiplayer, "For the employee with the most entity kills.");
			ThePacifistNote = ((BaseUnityPlugin)this).Config.Bind<NoteDisplayOptions>("End Screen Notes", "Show The Pacifist", NoteDisplayOptions.OnlyInMultiplayer, "For the ONLY employee with zero entity kills (if any).");
			MostJumpyNote = ((BaseUnityPlugin)this).Config.Bind<NoteDisplayOptions>("End Screen Notes", "Show Most Jumpy", NoteDisplayOptions.Disabled, "For the employee with the most jumps.");
			MostGroundedNote = ((BaseUnityPlugin)this).Config.Bind<NoteDisplayOptions>("End Screen Notes", "Show Most Grounded", NoteDisplayOptions.Disabled, "For the employee with the least jumps.");
			TheBravestNote = ((BaseUnityPlugin)this).Config.Bind<NoteDisplayOptions>("End Screen Notes", "Show The Bravest", NoteDisplayOptions.SoloAndMultiplayer, "For the employee with the longest time spent indoors.");
			MostOutdoorsNote = ((BaseUnityPlugin)this).Config.Bind<NoteDisplayOptions>("End Screen Notes", "Show Most Outdoors", NoteDisplayOptions.OnlyInMultiplayer, "For the employee with the longest time spent outdoors.");
			TheShipGuyNote = ((BaseUnityPlugin)this).Config.Bind<NoteDisplayOptions>("End Screen Notes", "Show The Ship Guy", NoteDisplayOptions.Disabled, "For the employee with the longest time spent inside the ship.");
			No1ScavengerNote = ((BaseUnityPlugin)this).Config.Bind<NoteDisplayOptions>("End Screen Notes", "Show #1 Scavenger", NoteDisplayOptions.SoloAndMultiplayer, "For the employee with the most scrap value found.");
			EmptyHandedNote = ((BaseUnityPlugin)this).Config.Bind<NoteDisplayOptions>("End Screen Notes", "Show Empty Handed", NoteDisplayOptions.OnlyInMultiplayer, "For the employee with zero scrap value found.");
			TeamBackboneNote = ((BaseUnityPlugin)this).Config.Bind<NoteDisplayOptions>("End Screen Notes", "Show Team Backbone", NoteDisplayOptions.Disabled, "For the employee with the most found scrap value that made it to ship in the end.");
			TheVenturerNote = ((BaseUnityPlugin)this).Config.Bind<NoteDisplayOptions>("End Screen Notes", "Show The Venturer", NoteDisplayOptions.SoloAndMultiplayer, "For the employee with the most facility exploration.");
			LeastVenturousNote = ((BaseUnityPlugin)this).Config.Bind<NoteDisplayOptions>("End Screen Notes", "Show Least Venturous", NoteDisplayOptions.Disabled, "For the employee with the least facility exploration.");
		}

		public static void DeepLog(object log)
		{
			if (DeepLogging.Value)
			{
				logr.LogMessage(log);
			}
		}
	}
	internal class Saving
	{
		public static readonly string bxpJobsFileLocation = GetSavePathLocation() + "/Jobs";

		public static string bxpJobsSessionLocation = bxpJobsFileLocation + "/session_unknown";

		public static string GetSavePathLocation()
		{
			return Application.persistentDataPath + "/swaggies/BetterEXP";
		}

		public static void Save()
		{
			BetterEXPPlugin.logr.LogInfo((object)"Saving data...");
			ES3.Save<int>("BetterXP", EXPManager.experience, "BetterEXP");
		}

		public static int Load()
		{
			BetterEXPPlugin.logr.LogMessage((object)"Attempting to load...");
			bxpJobsSessionLocation = $"{bxpJobsFileLocation}/session_{JobTrackingManager.GetUnixTimestamp(DateTime.UtcNow)}";
			int num = ES3.Load<int>("BetterXP", "BetterEXP", -1);
			EXPManager.markedAsBetaPlayer = ES3.Load<bool>("playedDuringBeta", "LCGeneralSaveData", false);
			if (num > -1)
			{
				EXPManager.SetXP(num);
				EXPManager.hasLoadedV2 = true;
				BetterEXPPlugin.logr.LogMessage((object)$"(V2.3+) Loaded {EXPManager.experience} BXP - rank {EXPLevels.GetPlayerLevel(EXPManager.experience).name}.");
				return 3;
			}
			return -1;
		}

		public static void SaveJobToDisk(JobTrackingManager.JobLog job)
		{
			if (!Directory.Exists(bxpJobsFileLocation))
			{
				Directory.CreateDirectory(bxpJobsFileLocation);
			}
			if (!Directory.Exists(bxpJobsSessionLocation))
			{
				Directory.CreateDirectory(bxpJobsSessionLocation);
			}
			string text = bxpJobsSessionLocation + $"/{job.jobPlayedTime}" + "_" + job.moon + $"_{job.scrapCollected}" + $"-{job.totalAvailableScrap}" + ".json";
			File.WriteAllText(text, JsonConvert.SerializeObject((object)job));
			BetterEXPPlugin.logr.LogMessage((object)("successfully saved today's stats to " + text + "."));
		}
	}
	internal class ScrapManager
	{
		public class BXPScrap
		{
			public bool isInShip;

			public GrabbableObject gObject;

			public PlayerControllerB playerFoundBy;

			public PlayerControllerB playerDeliveredBy;

			public BeltBagItem putInBeltBag;
		}

		public static Dictionary<GrabbableObject, BXPScrap> RoundScrap = new Dictionary<GrabbableObject, BXPScrap>();

		public static List<GrabbableObject> BlacklistedMoonObjects = new List<GrabbableObject>();

		public static void OnStartGame()
		{
			RoundScrap.Clear();
			BlacklistedMoonObjects.Clear();
			GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
			GrabbableObject[] array2 = array;
			foreach (GrabbableObject item in array2)
			{
				BlacklistedMoonObjects.Add(item);
			}
		}

		public static void OnObjectGrabbed(GrabbableObject obj, PlayerControllerB player, BeltBagItem bagPutInside = null)
		{
			if (obj.itemProperties.isScrap && !BlacklistedMoonObjects.Contains(obj))
			{
				if (!RoundScrap.ContainsKey(obj))
				{
					BetterEXPPlugin.DeepLog(obj.itemProperties.itemName + " scrap found by " + player.playerUsername);
					RoundScrap.Add(obj, new BXPScrap
					{
						gObject = obj,
						playerFoundBy = player
					});
					BEXPPlayer.AllPlayersByPCB[player].stats.scrapFound += obj.scrapValue;
				}
				if ((Object)(object)bagPutInside != (Object)null)
				{
					RoundScrap[obj].putInBeltBag = bagPutInside;
					BetterEXPPlugin.DeepLog($"{obj.itemProperties.itemName} scrap put inside belt bag #{((NetworkBehaviour)bagPutInside).NetworkObjectId}");
				}
			}
		}

		public static void OnShipStateChanged(GrabbableObject obj, bool setInShip)
		{
			if (!obj.itemProperties.isScrap || BlacklistedMoonObjects.Contains(obj) || !RoundScrap.TryGetValue(obj, out var value) || value.isInShip == setInShip)
			{
				return;
			}
			value.isInShip = setInShip;
			if (setInShip)
			{
				PlayerControllerB val = value.playerDeliveredBy;
				if ((Object)(object)val == (Object)null && (Object)(object)value.putInBeltBag != (Object)null)
				{
					val = ((GrabbableObject)value.putInBeltBag).playerHeldBy;
				}
				if ((Object)(object)val == (Object)null)
				{
					val = Helpers.ObjectHeldByPlayer(obj);
				}
				if ((Object)(object)val == (Object)null)
				{
					val = Helpers.ClosestPlayerToObject(obj);
				}
				BEXPPlayer bEXPPlayer = BEXPPlayer.AllPlayersByPCB[val];
				BEXPPlayer bEXPPlayer2 = BEXPPlayer.AllPlayersByPCB[value.playerFoundBy];
				if (!Object.op_Implicit((Object)(object)value.playerDeliveredBy))
				{
					value.playerDeliveredBy = val;
				}
				bEXPPlayer.stats.objectsDelivered++;
				bEXPPlayer.stats.scrapDelivered += obj.scrapValue;
				bEXPPlayer2.stats.scrapFoundDeliveredToShip += obj.scrapValue;
				BetterEXPPlugin.DeepLog(obj.itemProperties.itemName + " scrap delivered by " + val.playerUsername);
			}
			else
			{
				if ((Object)(object)value.playerDeliveredBy != (Object)null)
				{
					BEXPPlayer bEXPPlayer3 = BEXPPlayer.AllPlayersByPCB[value.playerDeliveredBy];
					bEXPPlayer3.stats.objectsDelivered--;
					bEXPPlayer3.stats.scrapDelivered -= obj.scrapValue;
				}
				BEXPPlayer.AllPlayersByPCB[value.playerFoundBy].stats.scrapFoundDeliveredToShip -= obj.scrapValue;
				BetterEXPPlugin.DeepLog(obj.itemProperties.itemName + " scrap removed from ship - delivered by " + (value.playerDeliveredBy?.playerUsername ?? "(no one)"));
			}
		}
	}
}
namespace LCBetterEXP.patches
{
	[HarmonyPatch(typeof(BeltBagItem))]
	internal class BeltBagItemPatch
	{
		[HarmonyPatch("PutObjectInBagLocalClient")]
		[HarmonyPostfix]
		private static void PutObjectInBagLocalClient(ref BeltBagItem __instance, ref GrabbableObject gObject)
		{
			if (!((Object)(object)((GrabbableObject)__instance).playerHeldBy == (Object)null))
			{
				ScrapManager.OnObjectGrabbed(gObject, ((GrabbableObject)__instance).playerHeldBy);
			}
		}
	}
	[HarmonyPatch(typeof(EnemyAI))]
	public class EnemyAIPatch
	{
		[HarmonyPatch("HitEnemy")]
		[HarmonyPrefix]
		private static void HitEnemy(ref EnemyAI __instance, ref PlayerControllerB playerWhoHit)
		{
			EnemyManager.OnEnemyHit(__instance, playerWhoHit);
		}

		[HarmonyPatch("KillEnemy")]
		[HarmonyPostfix]
		private static void KillEnemy(ref EnemyAI __instance, ref bool destroy)
		{
			if (!destroy)
			{
				EnemyManager.OnEnemyKilled(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	internal class HUDManagerPatch
	{
		[HarmonyPatch("SetPlayerLevelSmoothly")]
		[HarmonyPrefix]
		private static bool SetPlayerLevelSmoothlyPatch()
		{
			return false;
		}

		[HarmonyPatch(typeof(HUDManager), "MeteorShowerWarningHUD")]
		[HarmonyPostfix]
		private static void MeteorShowerWarningHUD()
		{
			GlobalManager.SetMeteorShower(TimeOfDay.Instance.normalizedTimeOfDay);
		}

		[HarmonyPatch("FillEndGameStats")]
		[HarmonyPostfix]
		private static void FillEndGameStats(ref int scrapCollected)
		{
			PerformanceReportManager.OnPerformanceReport(scrapCollected);
		}

		[HarmonyPatch("SetPlayerLevel")]
		[HarmonyPrefix]
		private static bool CancelOGExp(ref bool isDead, ref bool allPlayersDead)
		{
			EXPManager.ChangeVanillaRank(isDead, BEXPPlayer.instance.IsMostProfitable, allPlayersDead);
			EXPBarManager.StartEXPBarAnimation();
			return false;
		}

		[HarmonyPatch("SetSavedValues")]
		[HarmonyPostfix]
		private static void OnHudStart()
		{
			EXPManager.AssignInitialRank(HUDManager.Instance.localPlayerXP);
		}
	}
	[HarmonyPatch(typeof(MenuManager))]
	internal class MenuManagerPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void Start()
		{
			BEXPPlayer.AllPlayersByPCB.Clear();
			BEXPPlayer.AllPlayersList.Clear();
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal class PlayerControllerBPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void AwakeP(ref PlayerControllerB __instance)
		{
			BEXPPlayer bEXPPlayer = ((Component)__instance).gameObject.AddComponent<BEXPPlayer>();
			BEXPPlayer.AllPlayersByPCB.Add(__instance, bEXPPlayer);
			BEXPPlayer.AllPlayersList.Add(bEXPPlayer);
		}

		[HarmonyPatch("ConnectClientToPlayerObject")]
		[HarmonyPostfix]
		private static void ConnectClientToPlayerObjectP(ref PlayerControllerB __instance)
		{
			((Component)__instance).GetComponent<BEXPPlayer>()?.SetAsLocalClient();
		}

		[HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")]
		[HarmonyPrefix]
		private static void KillLocalPlayerPatch(ref PlayerControllerB __instance, ref CauseOfDeath causeOfDeath)
		{
			if (((NetworkBehaviour)__instance).IsOwner && !__instance.isPlayerDead && __instance.AllowPlayerDeath())
			{
				GlobalManager.OnPlayerKilled(__instance, causeOfDeath);
			}
		}

		[HarmonyPatch("KillPlayerClientRpc")]
		[HarmonyPrefix]
		private static void KillNonLocalPlayerPatch(ref PlayerControllerB __instance, ref int playerId, ref int causeOfDeath)
		{
			if (!((NetworkBehaviour)__instance).IsOwner && playerId != (int)GameNetworkManager.Instance.localPlayerController.playerClientId)
			{
				GlobalManager.OnPlayerKilled(__instance, (CauseOfDeath)causeOfDeath);
			}
		}

		[HarmonyPatch("PlayJumpAudio")]
		[HarmonyPrefix]
		private static void PlayerJumpSelf(ref PlayerControllerB __instance)
		{
			if (!__instance.isPlayerDead && __instance.isPlayerControlled && !__instance.disconnectedMidGame && !StartOfRound.Instance.inShipPhase && !StartOfRound.Instance.shipIsLeaving)
			{
				BEXPPlayer.AllPlayersByPCB[__instance].stats.jumps++;
			}
		}

		[HarmonyPatch("GrabObjectClientRpc")]
		[HarmonyPostfix]
		private static void GrabObjectClientRpc(ref PlayerControllerB __instance, ref bool grabValidated, ref NetworkObjectReference grabbedObject)
		{
			NetworkObject val = default(NetworkObject);
			if (grabValidated && ((NetworkObjectReference)(ref grabbedObject)).TryGet(ref val, (NetworkManager)null))
			{
				GrabbableObject componentInChildren = ((Component)val).gameObject.GetComponentInChildren<GrabbableObject>();
				if (!((Object)(object)componentInChildren == (Object)null))
				{
					ScrapManager.OnObjectGrabbed(componentInChildren, __instance);
				}
			}
		}

		[HarmonyPatch("SetItemInElevator")]
		[HarmonyPostfix]
		private static void SetObjectInShip(ref bool droppedInShipRoom, ref GrabbableObject gObject)
		{
			ScrapManager.OnShipStateChanged(gObject, droppedInShipRoom);
		}

		[HarmonyPatch("DamageOnOtherClients")]
		[HarmonyPostfix]
		private static void DamageOnOtherClients(ref PlayerControllerB __instance, ref int damageNumber)
		{
			if (!((NetworkBehaviour)__instance).IsOwner)
			{
				BEXPPlayer.AllPlayersByPCB[__instance].stats.damageTaken += damageNumber;
			}
		}

		[HarmonyPatch("DamagePlayer")]
		[HarmonyPostfix]
		private static void DamagePlayer(ref PlayerControllerB __instance, ref int damageNumber)
		{
			if (!__instance.isPlayerDead && __instance.AllowPlayerDeath() && ((NetworkBehaviour)__instance).IsOwner)
			{
				BEXPPlayer.AllPlayersByPCB[__instance].stats.damageTaken += damageNumber;
			}
		}
	}
	[HarmonyPatch(typeof(QuickMenuManager))]
	internal class QuickMenuManagerPatch
	{
		public static QuickMenuManager QMM;

		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void Start(ref QuickMenuManager __instance)
		{
			QMM = __instance;
		}

		[HarmonyPatch("OpenQuickMenu")]
		[HarmonyPostfix]
		private static void PauseMenuPatch(QuickMenuManager __instance)
		{
			if (__instance.isMenuOpen)
			{
				PauseMenuDisplay.OnMenuOpen();
			}
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void PauseMenuUpdatePatch()
		{
			PauseMenuDisplay.Update();
		}
	}
	[HarmonyPatch(typeof(RoundManager))]
	internal class RoundManagerPatch
	{
		[HarmonyPatch("SyncScrapValuesClientRpc")]
		[HarmonyPostfix]
		private static void CheckForSingleScrapDay(ref NetworkObjectReference[] spawnedScrap)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			string text = "";
			GrabbableObject val = null;
			NetworkObjectReference[] array = spawnedScrap;
			NetworkObject val3 = default(NetworkObject);
			for (int i = 0; i < array.Length; i++)
			{
				NetworkObjectReference val2 = array[i];
				if (!((NetworkObjectReference)(ref val2)).TryGet(ref val3, (NetworkManager)null))
				{
					continue;
				}
				GrabbableObject component = ((Component)val3).GetComponent<GrabbableObject>();
				if (!((Object)(object)component == (Object)null) && !((Object)(object)component.itemProperties == (Object)null) && !(component is KnifeItem) && !(component is ShotgunItem) && !(component is LungProp) && component.itemProperties.isScrap)
				{
					if (string.IsNullOrEmpty(text))
					{
						text = component.itemProperties.itemName;
						val = component;
					}
					if (component.itemProperties.itemName != text)
					{
						GlobalManager.SetSingleScrapItemDay();
						return;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				GlobalManager.SetSingleScrapItemDay();
				return;
			}
			ScanNodeProperties componentInChildren = ((Component)val).GetComponentInChildren<ScanNodeProperties>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				GlobalManager.SetSingleScrapItemDay(componentInChildren.headerText);
			}
			else
			{
				GlobalManager.SetSingleScrapItemDay(val.itemProperties.itemName);
			}
		}
	}
	[HarmonyPatch(typeof(StartMatchLever))]
	internal class StartMatchLeverPatch
	{
		[HarmonyPatch("PullLeverAnim")]
		[HarmonyPrefix]
		private static void StartGamePatch(ref bool leverPulled)
		{
			if (leverPulled)
			{
				ScrapManager.OnStartGame();
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal class StartOfRoundPatch
	{
		public static LevelWeatherType currentWeather = (LevelWeatherType)(-1);

		public static bool currentPlanetHasSnow = false;

		[HarmonyPatch("SyncShipUnlockablesClientRpc")]
		[HarmonyPostfix]
		private static void CollectAllAlreadyCollectedItems()
		{
			if (!NetworkManager.Singleton.IsHost)
			{
				GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
				foreach (GrabbableObject val in array)
				{
					GameNetworkManager.Instance.localPlayerController.SetItemInElevator(true, true, val);
				}
			}
		}

		[HarmonyPatch("WritePlayerNotes")]
		[HarmonyPrefix]
		private static bool NotesOverride()
		{
			return NotesManager.WriteAllNotes();
		}

		[HarmonyPatch("ShipHasLeft")]
		[HarmonyPrefix]
		private static void SetTimeAtEndOfDay()
		{
			GlobalManager.SetTimeEndOfDay(Time.realtimeSinceStartup - JobTrackingManager.timeAtStartOfDay);
		}

		[HarmonyPatch("PassTimeToNextDay")]
		[HarmonyPostfix]
		private static void BeginShowExpGains()
		{
			GlobalManager.SaveAndShowGains();
		}

		[HarmonyPatch("ResetStats")]
		[HarmonyPrefix]
		private static bool ResetStatsFix()
		{
			for (int i = 0; i < StartOfRound.Instance.gameStats.allPlayerStats.Length; i++)
			{
				StartOfRound.Instance.gameStats.allPlayerStats[i].damageTaken = 0;
				StartOfRound.Instance.gameStats.allPlayerStats[i].jumps = 0;
				StartOfRound.Instance.gameStats.allPlayerStats[i].stepsTaken = 0;
				StartOfRound.Instance.gameStats.allPlayerStats[i].profitable = 0;
				StartOfRound.Instance.gameStats.allPlayerStats[i].turnAmount = 0;
				StartOfRound.Instance.gameStats.allPlayerStats[i].playerNotes.Clear();
			}
			GlobalManager.SetStartNewDay(Time.realtimeSinceStartup);
			return false;
		}

		[HarmonyPatch("OnShipLandedMiscEvents")]
		[HarmonyPostfix]
		private static void SetWeatherType()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			currentWeather = TimeOfDay.Instance.currentLevelWeather;
			currentPlanetHasSnow = TimeOfDay.Instance.currentLevel.levelIncludesSnowFootprints;
		}
	}
}