Decompiled source of MoreChancesEn v5.2.4

MoreChances.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using MenuLib.MonoBehaviors;
using Microsoft.CodeAnalysis;
using MonoMod.RuntimeDetour;
using Photon.Pun;
using Steamworks;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("MoreChances")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MoreChances")]
[assembly: AssemblyTitle("MoreChances")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MoreChances
{
	[BepInPlugin("MoreChances", "MoreChances", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		public static ConfigEntry<bool> AllowArena;

		public static ConfigEntry<bool> GoArenaDelete;

		public static ConfigEntry<bool> AllDeadDelete;

		public static ConfigEntry<bool> ReviveHPEnable;

		public static ConfigEntry<bool> WhateverNoDelete;

		public static ConfigEntry<int> ReviveHP;

		public static ConfigEntry<bool> TruckHealEnable;

		public static ConfigEntry<int> TruckHealHP;

		public static ConfigEntry<bool> ChargingStationInfinityPower;

		private REPOButton reMapBtn;

		private REPOButton shopBtn;

		private REPOButton testBtn;

		private FieldRef<ChargingStation, float> charge = AccessTools.FieldRefAccess<ChargingStation, float>("charge");

		private void Awake()
		{
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Expected O, but got Unknown
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			Logger = ((BaseUnityPlugin)this).Logger;
			AllowArena = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Go to Arena", false, "Default: Off, Restart current progress after team wipe, will not go to arena");
			GoArenaDelete = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Arena (Delete Save)", false, "Default: Off, Even if you enter the arena, the save will not be deleted");
			AllDeadDelete = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Delete Save After Team Wipe", false, "Default: Off, Save will not be deleted after team wipe");
			ReviveHPEnable = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Adjust HP on Revive", true, "Default: On, Initial HP boost when restarting");
			WhateverNoDelete = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "When exiting (deleting archives)", false, "Default: Off, no matter what, the archive is not deleted");
			ReviveHP = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Revive HP (%)", 100, new ConfigDescription("Default: 100%, Full HP recovery", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>()));
			TruckHealEnable = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Adjust HP on Truck", true, "Default: On, HP recovery boost when driving the truck");
			TruckHealHP = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Truck Heal HP (%)", 100, new ConfigDescription("Default: 100%, Full HP recovery", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>()));
			ChargingStationInfinityPower = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Unlimited Charging (Truck)", true, "Default: On, the truck can be charged infinitely");
			Logger.LogInfo((object)"MoreChances loaded!");
			new Hook((MethodBase)AccessTools.Method(typeof(RunManager), "Awake", (Type[])null, (Type[])null), (Delegate)(Action<Action<RunManager>, RunManager>)delegate(Action<RunManager> orig, RunManager self)
			{
				orig(self);
				if ((Object)(object)((Component)self).gameObject.GetComponent<MoreChances>() == (Object)null)
				{
					((Component)self).gameObject.AddComponent<MoreChances>();
					((BaseUnityPlugin)this).Logger.LogInfo((object)"MoreChances Added!");
				}
			}).Apply();
		}

		public void Update()
		{
			if (ChargingStationInfinityPower.Value && Object.op_Implicit((Object)(object)ChargingStation.instance) && !SemiFunc.RunIsShop())
			{
				charge.Invoke(ChargingStation.instance) = 1f;
			}
		}
	}
	public class MoreChances : MonoBehaviour
	{
		private delegate void orig_RunManager_Update(RunManager self);

		private delegate void hook_RunManager_Update(orig_RunManager_Update orig, RunManager self);

		private delegate void orig_RunManager_ChangeLevel(RunManager self, bool _completedLevel, bool _levelFailed, ChangeLevelType _changeLevelType);

		private delegate void hook_RunManager_ChangeLevel(orig_RunManager_ChangeLevel orig, RunManager self, bool _completedLevel, bool _levelFailed, ChangeLevelType _changeLevelType);

		private delegate void orig_DataDirector_SaveDeleteCheck(DataDirector self, bool _leaveGame);

		private delegate void hook_DataDirector_SaveDeleteCheck(orig_DataDirector_SaveDeleteCheck orig, DataDirector self, bool _leaveGame);

		private delegate void orig_PlayerAvatar_ReviveRPC(PlayerAvatar self, bool _revivedByTruck);

		private delegate void hook_PlayerAvatar_ReviveRPC(orig_PlayerAvatar_ReviveRPC orig, PlayerAvatar self, bool _revivedByTruck);

		private delegate void orig_PlayerAvatar_FinalHealRPC(PlayerAvatar self);

		private delegate void hook_PlayerAvatar_FinalHealRPC(orig_PlayerAvatar_FinalHealRPC orig, PlayerAvatar self);

		private delegate IEnumerator orig_PlayerHealth_Fetch(PlayerHealth self);

		private delegate IEnumerator hook_PlayerHealth_Fetch(orig_PlayerHealth_Fetch orig, PlayerHealth self);

		private static bool isHooked;

		private FieldRef<RunManager, bool> restarting = AccessTools.FieldRefAccess<RunManager, bool>("restarting");

		private FieldRef<RunManager, bool> runStarted = AccessTools.FieldRefAccess<RunManager, bool>("runStarted");

		private FieldRef<RunManager, bool> allPlayersDead = AccessTools.FieldRefAccess<RunManager, bool>("allPlayersDead");

		private FieldRef<RunManager, bool> gameOver = AccessTools.FieldRefAccess<RunManager, bool>("gameOver");

		private FieldRef<RunManager, int> saveLevel = AccessTools.FieldRefAccess<RunManager, int>("saveLevel");

		private FieldRef<RunManager, RunManagerPUN> runManagerPUN = AccessTools.FieldRefAccess<RunManager, RunManagerPUN>("runManagerPUN");

		private FieldRef<RunManager, Level> levelPrevious = AccessTools.FieldRefAccess<RunManager, Level>("levelPrevious");

		private FieldRef<RunManager, Level> previousRunLevel = AccessTools.FieldRefAccess<RunManager, Level>("previousRunLevel");

		private FieldRef<RunManager, Level> debugLevel = AccessTools.FieldRefAccess<RunManager, Level>("debugLevel");

		private FieldRef<PlayerAvatar, bool> isDisabled = AccessTools.FieldRefAccess<PlayerAvatar, bool>("isDisabled");

		private FieldRef<PlayerAvatar, bool> finalHeal = AccessTools.FieldRefAccess<PlayerAvatar, bool>("finalHeal");

		private FieldRef<PlayerAvatar, string> playerName = AccessTools.FieldRefAccess<PlayerAvatar, string>("playerName");

		private FieldRef<PlayerHealth, int> maxHealth = AccessTools.FieldRefAccess<PlayerHealth, int>("maxHealth");

		private FieldRef<PlayerHealth, PhotonView> photonView = AccessTools.FieldRefAccess<PlayerHealth, PhotonView>("photonView");

		private FieldRef<PlayerHealth, PlayerAvatar> playerAvatar = AccessTools.FieldRefAccess<PlayerHealth, PlayerAvatar>("playerAvatar");

		private FieldRef<PlayerHealth, int> health = AccessTools.FieldRefAccess<PlayerHealth, int>("health");

		private FieldRef<PlayerHealth, bool> healthSet = AccessTools.FieldRefAccess<PlayerHealth, bool>("healthSet");

		private FieldRef<StatsManager, string> saveFileCurrent = AccessTools.FieldRefAccess<StatsManager, string>("saveFileCurrent");

		public void Awake()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			if (!isHooked)
			{
				new Hook((MethodBase)AccessTools.Method(typeof(RunManager), "Update", (Type[])null, (Type[])null), (Delegate)new hook_RunManager_Update(RunManager_Update)).Apply();
				new Hook((MethodBase)AccessTools.Method(typeof(RunManager), "ChangeLevel", (Type[])null, (Type[])null), (Delegate)new hook_RunManager_ChangeLevel(RunManager_ChangeLevel)).Apply();
				new Hook((MethodBase)AccessTools.Method(typeof(DataDirector), "SaveDeleteCheck", (Type[])null, (Type[])null), (Delegate)new hook_DataDirector_SaveDeleteCheck(DataDirector_SaveDeleteCheck)).Apply();
				new Hook((MethodBase)AccessTools.Method(typeof(PlayerAvatar), "ReviveRPC", (Type[])null, (Type[])null), (Delegate)new hook_PlayerAvatar_ReviveRPC(PlayerAvatar_ReviveRPC)).Apply();
				new Hook((MethodBase)AccessTools.Method(typeof(PlayerHealth), "Fetch", (Type[])null, (Type[])null), (Delegate)new hook_PlayerHealth_Fetch(PlayerAvatar_Fetch)).Apply();
				new Hook((MethodBase)AccessTools.Method(typeof(PlayerAvatar), "FinalHealRPC", (Type[])null, (Type[])null), (Delegate)new hook_PlayerAvatar_FinalHealRPC(PlayerAvatar_FinalHealRPC)).Apply();
				isHooked = true;
			}
		}

		private void PlayerAvatar_FinalHealRPC(orig_PlayerAvatar_FinalHealRPC orig, PlayerAvatar self)
		{
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			if (finalHeal.Invoke(self))
			{
				return;
			}
			if (self.photonView.IsMine)
			{
				self.playerHealth.EyeMaterialOverride((EyeOverrideState)2, 2f, 1);
				TruckScreenText.instance.MessageSendCustom("", playerName.Invoke(self) + " {arrowright}{truck}{check}\n {point}{shades}{pointright}<b><color=#00FF00>+25</color></b>{heart}", 0);
				if (Plugin.TruckHealEnable.Value)
				{
					int num = Mathf.RoundToInt((float)(maxHealth.Invoke(self.playerHealth) * Plugin.TruckHealHP.Value) / 100f);
					self.playerHealth.Heal(num, true);
				}
				else
				{
					self.playerHealth.Heal(25, true);
				}
			}
			TruckHealer.instance.Heal(self);
			self.truckReturn.Play(self.PlayerVisionTarget.VisionTransform.position, 1f, 1f, 1f, 1f);
			self.truckReturnGlobal.Play(self.PlayerVisionTarget.VisionTransform.position, 1f, 1f, 1f, 1f);
			((Component)self.playerAvatarVisuals.effectGetIntoTruck).gameObject.SetActive(true);
			finalHeal.Invoke(self) = true;
		}

		private IEnumerator PlayerAvatar_Fetch(orig_PlayerHealth_Fetch orig, PlayerHealth self)
		{
			while (!LevelGenerator.Instance.Generated)
			{
				yield return (object)new WaitForSeconds(0.1f);
			}
			maxHealth.Invoke(self) = 100 + StatsManager.instance.GetPlayerMaxHealth(SemiFunc.PlayerGetSteamID(playerAvatar.Invoke(self)));
			int num = StatsManager.instance.GetPlayerHealth(SemiFunc.PlayerGetSteamID(playerAvatar.Invoke(self)));
			if (num <= 0)
			{
				num = ((!Plugin.ReviveHPEnable.Value) ? 1 : Mathf.RoundToInt((float)(maxHealth.Invoke(self) * Plugin.ReviveHP.Value) / 100f));
			}
			health.Invoke(self) = Mathf.Clamp(num, 0, maxHealth.Invoke(self));
			if (SemiFunc.RunIsArena())
			{
				health.Invoke(self) = maxHealth.Invoke(self);
			}
			StatsManager.instance.SetPlayerHealth(SemiFunc.PlayerGetSteamID(playerAvatar.Invoke(self)), health.Invoke(self), false);
			if (GameManager.Multiplayer())
			{
				photonView.Invoke(self).RPC("UpdateHealthRPC", (RpcTarget)1, new object[3]
				{
					health.Invoke(self),
					maxHealth.Invoke(self),
					true
				});
			}
			healthSet.Invoke(self) = true;
		}

		private void PlayerAvatar_ReviveRPC(orig_PlayerAvatar_ReviveRPC orig, PlayerAvatar self, bool _revivedByTruck)
		{
			orig(self, _revivedByTruck);
			HealPlayer(self);
		}

		private void HealPlayer(PlayerAvatar self)
		{
			if (self.photonView.IsMine && Plugin.ReviveHPEnable.Value)
			{
				int num = Mathf.RoundToInt((float)(maxHealth.Invoke(self.playerHealth) * Plugin.ReviveHP.Value) / 100f);
				self.playerHealth.HealOther(num, true);
				Plugin.Logger.LogInfo((object)$"HealPlayer Called. heal +{num}hp");
			}
		}

		private void DataDirector_SaveDeleteCheck(orig_DataDirector_SaveDeleteCheck orig, DataDirector self, bool _leaveGame)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer() && !((Object)(object)levelPrevious.Invoke(RunManager.instance) == (Object)(object)RunManager.instance.levelTutorial) && !((Object)(object)levelPrevious.Invoke(RunManager.instance) == (Object)(object)RunManager.instance.levelLobbyMenu) && !((Object)(object)levelPrevious.Invoke(RunManager.instance) == (Object)(object)RunManager.instance.levelMainMenu) && !((Object)(object)levelPrevious.Invoke(RunManager.instance) == (Object)(object)RunManager.instance.levelRecording))
			{
				bool flag = false;
				if (SemiFunc.RunIsArena())
				{
					flag = Plugin.GoArenaDelete.Value;
				}
				else if (allPlayersDead.Invoke(RunManager.instance) && (Object)(object)levelPrevious.Invoke(RunManager.instance) != (Object)(object)RunManager.instance.levelMainMenu && (Object)(object)levelPrevious.Invoke(RunManager.instance) != (Object)(object)RunManager.instance.levelLobbyMenu && (Object)(object)levelPrevious.Invoke(RunManager.instance) != (Object)(object)RunManager.instance.levelTutorial && (Object)(object)levelPrevious.Invoke(RunManager.instance) != (Object)(object)RunManager.instance.levelLobby && (Object)(object)levelPrevious.Invoke(RunManager.instance) != (Object)(object)RunManager.instance.levelShop && (Object)(object)levelPrevious.Invoke(RunManager.instance) != (Object)(object)RunManager.instance.levelRecording)
				{
					flag = Plugin.AllDeadDelete.Value;
				}
				else if (_leaveGame && RunManager.instance.levelsCompleted == 0)
				{
					flag = Plugin.WhateverNoDelete.Value;
				}
				if (flag)
				{
					SemiFunc.SaveFileDelete(saveFileCurrent.Invoke(StatsManager.instance));
				}
			}
		}

		private void RunManager_ChangeLevel(orig_RunManager_ChangeLevel orig, RunManager self, bool _completedLevel, bool _levelFailed, ChangeLevelType _changeLevelType)
		{
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Invalid comparison between Unknown and I4
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Invalid comparison between Unknown and I4
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Invalid comparison between Unknown and I4
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Invalid comparison between Unknown and I4
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Invalid comparison between Unknown and I4
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Invalid comparison between Unknown and I4
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Invalid comparison between Unknown and I4
			if ((!SemiFunc.MenuLevel() && !SemiFunc.IsMasterClientOrSingleplayer()) || restarting.Invoke(self))
			{
				return;
			}
			gameOver.Invoke(self) = false;
			if (_levelFailed && (Object)(object)self.levelCurrent != (Object)(object)self.levelLobby && (Object)(object)self.levelCurrent != (Object)(object)self.levelShop)
			{
				if ((Object)(object)self.levelCurrent == (Object)(object)self.levelArena)
				{
					if (Plugin.GoArenaDelete.Value)
					{
						self.ResetProgress();
					}
					if (SemiFunc.IsMultiplayer())
					{
						self.levelCurrent = self.levelLobbyMenu;
					}
					else
					{
						self.SetRunLevel();
					}
					gameOver.Invoke(self) = true;
				}
				else
				{
					self.levelCurrent = self.levelArena;
				}
			}
			if (!gameOver.Invoke(self) && (Object)(object)self.levelCurrent != (Object)(object)self.levelArena)
			{
				if ((int)_changeLevelType == 1)
				{
					self.SetRunLevel();
				}
				else if ((int)_changeLevelType == 3)
				{
					self.levelCurrent = self.levelLobbyMenu;
				}
				else if ((int)_changeLevelType == 4)
				{
					self.levelCurrent = self.levelMainMenu;
				}
				else if ((int)_changeLevelType == 2)
				{
					self.levelCurrent = self.levelTutorial;
				}
				else if ((int)_changeLevelType == 6)
				{
					self.levelCurrent = self.levelRecording;
				}
				else if ((int)_changeLevelType == 5)
				{
					self.levelCurrent = self.levelShop;
				}
				else if ((Object)(object)self.levelCurrent == (Object)(object)self.levelMainMenu || (Object)(object)self.levelCurrent == (Object)(object)self.levelLobbyMenu)
				{
					self.levelCurrent = self.levelLobby;
				}
				else if (_completedLevel && (Object)(object)self.levelCurrent != (Object)(object)self.levelLobby && (Object)(object)self.levelCurrent != (Object)(object)self.levelShop)
				{
					previousRunLevel.Invoke(self) = self.levelCurrent;
					self.levelsCompleted++;
					SemiFunc.StatSetRunLevel(self.levelsCompleted);
					SemiFunc.LevelSuccessful();
					self.levelCurrent = self.levelShop;
				}
				else if ((Object)(object)self.levelCurrent == (Object)(object)self.levelLobby)
				{
					self.SetRunLevel();
				}
				else if ((Object)(object)self.levelCurrent == (Object)(object)self.levelShop)
				{
					self.levelCurrent = self.levelLobby;
				}
			}
			if (Object.op_Implicit((Object)(object)debugLevel.Invoke(self)) && (Object)(object)self.levelCurrent != (Object)(object)self.levelMainMenu && (Object)(object)self.levelCurrent != (Object)(object)self.levelLobbyMenu)
			{
				self.levelCurrent = debugLevel.Invoke(self);
			}
			if (GameManager.Multiplayer())
			{
				((Component)runManagerPUN.Invoke(self)).GetComponent<PhotonView>().RPC("UpdateLevelRPC", (RpcTarget)4, new object[3]
				{
					((Object)self.levelCurrent).name,
					self.levelsCompleted,
					gameOver.Invoke(self)
				});
			}
			Debug.Log((object)("Changed level to: " + ((Object)self.levelCurrent).name));
			if ((Object)(object)self.levelCurrent == (Object)(object)self.levelShop)
			{
				saveLevel.Invoke(self) = 1;
			}
			else
			{
				saveLevel.Invoke(self) = 0;
			}
			SemiFunc.StatSetSaveLevel(saveLevel.Invoke(self));
			self.RestartScene();
			if ((int)_changeLevelType != 2)
			{
				SemiFunc.OnSceneSwitch(gameOver.Invoke(self), false);
			}
		}

		private void RunManager_Update(orig_RunManager_Update orig, RunManager self)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Invalid comparison between Unknown and I4
			if (GameManager.Multiplayer() && !PhotonNetwork.IsMasterClient)
			{
				return;
			}
			if (LevelGenerator.Instance.Generated && !SteamClient.IsValid && !((Behaviour)SteamManager.instance).enabled)
			{
				Debug.LogError((object)"Steam not initialized. Quitting game.");
				Application.Quit();
			}
			if (restarting.Invoke(self))
			{
				self.RestartScene();
			}
			if (restarting.Invoke(self) || !runStarted.Invoke(self) || GameDirector.instance.PlayerList.Count <= 0 || SemiFunc.RunIsArena() || (int)GameDirector.instance.currentState != 2)
			{
				return;
			}
			bool flag = true;
			using (List<PlayerAvatar>.Enumerator enumerator = GameDirector.instance.PlayerList.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					if (!isDisabled.Invoke(enumerator.Current))
					{
						flag = false;
						break;
					}
				}
			}
			if (!flag)
			{
				return;
			}
			allPlayersDead.Invoke(self) = true;
			if (Object.op_Implicit((Object)(object)SpectateCamera.instance) && SpectateCamera.instance.CheckState((State)1))
			{
				if (Plugin.AllowArena.Value)
				{
					self.ChangeLevel(false, true, (ChangeLevelType)0);
				}
				else
				{
					self.ChangeLevel(false, false, (ChangeLevelType)1);
				}
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "MoreChances";

		public const string PLUGIN_NAME = "MoreChances";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}