Decompiled source of SkipGroal v0.1.0

SkipGroal.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using HutongGames.PlayMaker;
using Microsoft.CodeAnalysis;
using TeamCherry.SharedUtils;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SkipGroal")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("SkipGroal")]
[assembly: AssemblyTitle("SkipGroal")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[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 BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace EasierGroal
{
	[BepInPlugin("pizzaman.skipgroal", "SkipGroal", "0.1.0")]
	public class EasierGroalPlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> SkipWaves;

		internal static ConfigEntry<int> GroalHpPercent;

		internal static ConfigEntry<bool> RespawnAtArena;

		internal static ConfigEntry<bool> SkipGroal;

		internal static ConfigEntry<KeyboardShortcut> WarpKey;

		public const string Id = "pizzaman.skipgroal";

		public static string Name => "SkipGroal";

		public static string Version => "0.1.0";

		private void Awake()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			SkipWaves = ((BaseUnityPlugin)this).Config.Bind<bool>("Groal", "SkipWaves", true, "Skip the five enemy waves before Groal. The fight starts with Groal himself.");
			GroalHpPercent = ((BaseUnityPlugin)this).Config.Bind<int>("Groal", "GroalHpPercent", 50, new ConfigDescription("Groal's HP as a percent of normal (normal is 650).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 100), Array.Empty<object>()));
			RespawnAtArena = ((BaseUnityPlugin)this).Config.Bind<bool>("Groal", "RespawnAtArena", true, "Dying in Groal's room before he is beaten wakes you at the arena's left door instead of your bench.");
			SkipGroal = ((BaseUnityPlugin)this).Config.Bind<bool>("Groal", "SkipGroal", true, "Count Groal as beaten as soon as you enter his room: the bench is there and his Hunter's Journal kill is recorded.");
			WarpKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Testing", "WarpToGroalKey", KeyboardShortcut.Empty, "Test only: this key loads Groal's room at the arena door from any save. Leave empty to turn it off.");
			new Harmony("pizzaman.skipgroal").PatchAll(typeof(GroalPatches));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Plugin " + Name + " (pizzaman.skipgroal) has loaded!"));
		}

		private void Update()
		{
			//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)
			KeyboardShortcut value = WarpKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				GroalRoom.WarpToArenaDoor();
			}
		}
	}
	internal static class GroalRoom
	{
		internal const string GroalScene = "Shadow_18";

		internal const string GroalName = "Swamp Shaman";

		internal const string DefeatedBool = "DefeatedSwampShaman";

		internal const string BellCamLock = "CamLock BellSequence";

		internal const string ArenaDoor = "door1";

		internal const string RegisteredRespawnPoint = "RestBench";

		internal static bool PendingArenaRespawn;

		private static RespawnMarker? arenaDoorMarker;

		internal static bool IsGroalBattle(BattleScene battle)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (battle.setPDBoolOnEnd == "DefeatedSwampShaman")
			{
				Scene scene = ((Component)battle).gameObject.scene;
				return ((Scene)(ref scene)).name == "Shadow_18";
			}
			return false;
		}

		internal static void RecordGroalKill(BattleScene battle)
		{
			List<BattleWave> waves = battle.waves;
			Transform val = ((Component)waves[waves.Count - 1]).transform.Find("Swamp Shaman");
			PlayMakerFSM obj = (Object.op_Implicit((Object)(object)val) ? FSMUtility.LocateFSM(((Component)val).gameObject, "Control") : null);
			object obj2;
			if (obj == null)
			{
				obj2 = null;
			}
			else
			{
				FsmState state = obj.Fsm.GetState("Death Hit");
				obj2 = ((state != null) ? state.Actions.OfType<RecordJournalKill>().FirstOrDefault() : null);
			}
			Object obj3 = ((obj2 != null) ? ((RecordJournalKill)obj2).Record.Value : null);
			EnemyJournalRecord val2 = (EnemyJournalRecord)(object)((obj3 is EnemyJournalRecord) ? obj3 : null);
			if (val2 != null)
			{
				EnemyJournalManager.RecordKill(val2, true);
			}
			else
			{
				EasierGroalPlugin.Log.LogWarning((object)"Groal's journal record not found; journal kill not recorded");
			}
		}

		internal static RespawnMarker? ArenaDoorMarker()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)arenaDoorMarker))
			{
				return arenaDoorMarker;
			}
			TransitionPoint val = ((IEnumerable<TransitionPoint>)TransitionPoint.TransitionPoints).FirstOrDefault((Func<TransitionPoint, bool>)delegate(TransitionPoint t)
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				if (((Object)t).name == "door1")
				{
					Scene scene = ((Component)t).gameObject.scene;
					return ((Scene)(ref scene)).name == "Shadow_18";
				}
				return false;
			});
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			GameObject val2 = new GameObject("EasierGroal Arena Respawn");
			val2.transform.SetParent(((Component)val).transform, false);
			val2.transform.position = (Object.op_Implicit((Object)(object)val.respawnMarker) ? ((Component)val.respawnMarker).transform.position : ((Component)val).transform.position);
			arenaDoorMarker = val2.AddComponent<RespawnMarker>();
			arenaDoorMarker.respawnFacingRight = true;
			RespawnMarker val3 = arenaDoorMarker;
			if (val3.customFadeDuration == null)
			{
				val3.customFadeDuration = new OverrideFloat();
			}
			val3 = arenaDoorMarker;
			if (val3.overrideMapZone == null)
			{
				val3.overrideMapZone = new OverrideMapZone();
			}
			return arenaDoorMarker;
		}

		internal static void WarpToArenaDoor()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Invalid comparison between Unknown and I4
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			GameManager instance = GameManager.instance;
			HeroController instance2 = HeroController.instance;
			if (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance2) && (int)instance.GameState == 4 && !instance.IsInSceneTransition && instance2.acceptingInput)
			{
				EasierGroalPlugin.Log.LogInfo((object)("Warping from " + instance.sceneName + " to Shadow_18 door1"));
				instance2.RecordLeaveSceneCState();
				instance2.IgnoreInput();
				instance.BeginSceneTransition(new SceneLoadInfo
				{
					SceneName = "Shadow_18",
					EntryGateName = "door1",
					WaitForSceneTransitionCameraFade = true,
					Visualization = (SceneLoadVisualizations)0,
					AlwaysUnloadUnusedAssets = true
				});
			}
		}

		internal static Transform? FindInScene(Scene scene, string name)
		{
			return ((Scene)(ref scene)).GetRootGameObjects().SelectMany((GameObject root) => root.GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == name));
		}
	}
	[HarmonyPatch]
	internal static class GroalPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(BattleScene), "Start")]
		private static void SkipGroalOnLoad(BattleScene __instance)
		{
			if (EasierGroalPlugin.SkipGroal.Value && GroalRoom.IsGroalBattle(__instance) && !PlayerData.instance.DefeatedSwampShaman)
			{
				GroalRoom.RecordGroalKill(__instance);
				PlayerData.instance.DefeatedSwampShaman = true;
				EasierGroalPlugin.Log.LogInfo((object)"Groal skipped");
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(BattleScene), "DoStartBattle")]
		private static void SkipAddWaves(BattleScene __instance)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (EasierGroalPlugin.SkipWaves.Value && !__instance.started && __instance.waves.Count >= 2 && GroalRoom.IsGroalBattle(__instance))
			{
				Transform? obj = GroalRoom.FindInScene(((Component)__instance).gameObject.scene, "CamLock BellSequence");
				if (obj != null)
				{
					((Component)obj).gameObject.SetActive(true);
				}
				List<BattleWave> list = new List<BattleWave>();
				List<BattleWave> waves = __instance.waves;
				list.Add(waves[waves.Count - 1]);
				__instance.waves = list;
				EasierGroalPlugin.Log.LogInfo((object)"Groal add waves skipped");
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(HealthManager), "OnAwake")]
		private static void ScaleGroalHp(HealthManager __instance)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			int value = EasierGroalPlugin.GroalHpPercent.Value;
			if (!__instance.hasAwaken && value < 100 && !(((Object)((Component)__instance).gameObject).name != "Swamp Shaman"))
			{
				Scene scene = ((Component)__instance).gameObject.scene;
				if (!(((Scene)(ref scene)).name != "Shadow_18"))
				{
					int hp = __instance.hp;
					__instance.hp = Mathf.Max(1, Mathf.RoundToInt((float)(hp * value) / 100f));
					EasierGroalPlugin.Log.LogInfo((object)$"Groal HP {hp} -> {__instance.hp}");
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(GameManager), "PlayerDead")]
		private static void SendDeathToArena(GameManager __instance)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Invalid comparison between Unknown and I4
			PlayerData playerData = __instance.playerData;
			if (EasierGroalPlugin.RespawnAtArena.Value && !(__instance.sceneName != "Shadow_18") && !playerData.DefeatedSwampShaman && (int)playerData.permadeathMode != 2)
			{
				playerData.tempRespawnScene = "Shadow_18";
				playerData.tempRespawnMarker = "RestBench";
				playerData.tempRespawnType = 0;
				GroalRoom.PendingArenaRespawn = true;
				EasierGroalPlugin.Log.LogInfo((object)"Died in Groal's room; respawning at the arena door");
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(HeroController), "LocateSpawnPoint")]
		private static void SpawnAtArenaDoor(ref Transform __result)
		{
			if (GroalRoom.PendingArenaRespawn)
			{
				RespawnMarker val = GroalRoom.ArenaDoorMarker();
				if ((Object)(object)val != (Object)null)
				{
					__result = ((Component)val).transform;
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(HeroController), "Respawn")]
		private static void ClearPendingRespawn()
		{
			GroalRoom.PendingArenaRespawn = false;
		}
	}
}