Decompiled source of TeleportFromAnywhere v1.1.0

TeleportFromAnywhere.dll

Decompiled 4 months 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 BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using RCGFSM.Items;
using UnityEngine;

[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("TeleportFromAnywhere")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A Nine Sols mod that allows the player to use the \"Teleport\" menu from anywhere in the game, not just the Pavilion root node.")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+c7536facce8f6923b2828ef6a3537e33583dd08c")]
[assembly: AssemblyProduct("TeleportFromAnywhere")]
[assembly: AssemblyTitle("TeleportFromAnywhere")]
[assembly: AssemblyVersion("1.1.0.0")]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 TeleportFromAnywhere
{
	internal static class Log
	{
		private static ManualLogSource? logSource;

		internal static void Init(ManualLogSource logSource)
		{
			Log.logSource = logSource;
		}

		internal static void Debug(object data)
		{
			ManualLogSource? obj = logSource;
			if (obj != null)
			{
				obj.LogDebug(data);
			}
		}

		internal static void Error(object data)
		{
			ManualLogSource? obj = logSource;
			if (obj != null)
			{
				obj.LogError(data);
			}
		}

		internal static void Fatal(object data)
		{
			ManualLogSource? obj = logSource;
			if (obj != null)
			{
				obj.LogFatal(data);
			}
		}

		internal static void Info(object data)
		{
			ManualLogSource? obj = logSource;
			if (obj != null)
			{
				obj.LogInfo(data);
			}
		}

		internal static void Message(object data)
		{
			ManualLogSource? obj = logSource;
			if (obj != null)
			{
				obj.LogMessage(data);
			}
		}

		internal static void Warning(object data)
		{
			ManualLogSource? obj = logSource;
			if (obj != null)
			{
				obj.LogWarning(data);
			}
		}
	}
	[HarmonyPatch]
	internal class PauseMenuTeleportTab
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(TabsUI), "PrepareValidTab")]
		public static void TabsUI_PrepareValidTab_Postfix(TabsUI __instance)
		{
			List<UITabsItem> list = AccessTools.FieldRefAccess<TabsUI, List<UITabsItem>>("items").Invoke(__instance);
			Log.Debug(string.Format("TabsUI_PrepareValidTab_Postfix {0} {1}", list, string.Join("|", list.Select((UITabsItem i) => ((Object)((Component)i).gameObject).name))));
			if (!(((Object)list[0]).name != "TeleportPanel Tab") && SingletonBehaviour<GameCore>.IsAvailable() && SingletonBehaviour<GameFlagManager>.IsAvailable())
			{
				if (SingletonBehaviour<GameCore>.Instance.CurrentSceneName == "A5_S2_Jail_Remake_Final" && !((FlagField<bool>)(object)((GameFlagDescriptable)SingletonBehaviour<GameFlagManager>.Instance.GetTeleportPointWithPath("28a1908d9e21d4136b8c903e2b92b0afTeleportPointData")).unlocked).CurrentValue)
				{
					Log.Info("TeleportFromAnywhere: Keeping Teleport menu hidden because we're in Prison and its node hasn't been activated yet. If the player teleported out now, they'd never be able to get back in.");
				}
				else if (!list[0].IsAllValid)
				{
					Log.Debug("TabsUI_PrepareValidTab_Postfix forcing TeleportTab into the list of 'valid' menu tabs");
					AccessTools.FieldRefAccess<TabsUI, List<UITabsItem>>("validItems").Invoke(__instance).Add(list[0]);
					((Component)list[0]).gameObject.SetActive(true);
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TeleportPointButton), "SubmitImplementation")]
		public static bool TeleportPointButton_SubmitImplementation(TeleportPointButton __instance)
		{
			Log.Info("TeleportPointButton_SubmitImplementation called for button '" + ((__instance != null) ? ((Object)__instance).name : null) + "'");
			if (!SingletonBehaviour<GameCore>.IsAvailable() || !SingletonBehaviour<ApplicationUIGroupManager>.IsAvailable())
			{
				return true;
			}
			GameCore instance = SingletonBehaviour<GameCore>.Instance;
			object obj;
			if (instance == null)
			{
				obj = null;
			}
			else
			{
				SavePanel savePanelUiController = instance.savePanelUiController;
				obj = ((savePanelUiController != null) ? savePanelUiController.CurrentSavePointGameObjectOnScene : null);
			}
			if ((Object)obj != (Object)null)
			{
				return true;
			}
			Log.Info("Yi is not sitting at the Pavilion root node. Using mod impl of teleportation to avoid errors.");
			SingletonBehaviour<GameCore>.Instance.savePanelUiController.ToMenu = false;
			SingletonBehaviour<ApplicationUIGroupManager>.Instance.PopAll();
			SingletonBehaviour<GameCore>.Instance.savePanelUiController.ClearCurrentSavePoint();
			SingletonBehaviour<GameCore>.Instance.SetReviveSavePoint(__instance?.teleportPoint);
			SingletonBehaviour<GameCore>.Instance.TeleportToSavePoint(__instance?.teleportPoint, false, 0f);
			return false;
		}

		[HarmonyPostfix]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		public static void TeleportPointButton_get_IsNotAcquired(TeleportPointButton __instance, ref bool __result)
		{
			if (__result)
			{
				Log.Info("TeleportPointButton_get_IsNotAcquired enabling '" + ((__instance != null) ? ((Object)__instance).name : null) + "' button, so the player can teleport there despite it being their 'current node'");
				__result = false;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TeleportPointButton), "GetInstructionData")]
		public static bool TeleportPointButton_GetInstructionData(TeleportPointButton __instance, ref ButtonInstructionData __result)
		{
			__result = AccessTools.FieldRefAccess<UIControlButton, ButtonInstructionData>("InstructionData").Invoke((UIControlButton)(object)__instance);
			return false;
		}
	}
	[HarmonyPatch]
	internal class RootNodeMenu
	{
		[HarmonyPostfix]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		public static void TreeGotMadCondition_get_isValid(TreeGotMadCondition __instance, ref bool __result)
		{
			if (__result)
			{
				Log.Info("forcing TreeGotMadCondition to pass so the Root Node menus will continue to display [Pavilion]/[Last Node] options");
				__result = false;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		public static void PlayerInPrisionCondition_get_isValid(PlayerInPrisionCondition __instance, ref bool __result)
		{
			if (__result)
			{
				Log.Info("forcing PlayerInPrisionCondition_get_isValid to return true so the Root Node menus will continue to display [Pavilion]/[Last Node] options");
				__result = false;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		public static void TeleportPointMatchSavePanelCondition_get_isValid(TeleportPointMatchSavePanelCondition __instance, ref bool __result)
		{
			Transform parent = ((Component)__instance).transform.parent;
			if (((parent != null) ? ((Object)parent).name : null) == "Teleport 神遊" && !__result)
			{
				__result = true;
			}
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("TeleportFromAnywhere", "TeleportFromAnywhere", "1.1.0")]
	public class TeleportFromAnywhere : BaseUnityPlugin
	{
		private Harmony harmony;

		private void Awake()
		{
			Log.Init(((BaseUnityPlugin)this).Logger);
			RCGLifeCycle.DontDestroyForever(((Component)this).gameObject);
			harmony = Harmony.CreateAndPatchAll(typeof(TeleportFromAnywhere).Assembly, (string)null);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin TeleportFromAnywhere is loaded!");
		}

		private void OnDestroy()
		{
			harmony.UnpatchSelf();
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "TeleportFromAnywhere";

		public const string PLUGIN_NAME = "TeleportFromAnywhere";

		public const string PLUGIN_VERSION = "1.1.0";
	}
}
namespace TeleportFromAnywhere.Bugfixes
{
	[HarmonyPatch]
	internal class BossArenas
	{
		public static string GetGOPath(GameObject go)
		{
			Transform val = go.transform;
			List<string> list = new List<string>();
			while ((Object)(object)val != (Object)null)
			{
				list.Add(((Object)val).name);
				val = val.parent;
			}
			list.Reverse();
			return string.Join("/", list);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GeneralState), "OnStateEnter")]
		private static void GeneralState_OnStateEnter(GeneralState __instance)
		{
			if (!(((Object)__instance).name == "[State] Closed"))
			{
				return;
			}
			Transform parent = ((Component)__instance).transform.parent;
			bool? obj;
			if (parent == null)
			{
				obj = null;
			}
			else
			{
				Transform parent2 = parent.parent;
				if (parent2 == null)
				{
					obj = null;
				}
				else
				{
					Transform parent3 = parent2.parent;
					obj = ((parent3 != null) ? new bool?(((Object)parent3).name.Contains("[Mech]BossDoorx6_FSM Variant")) : null);
				}
			}
			bool? flag = obj;
			if (flag.GetValueOrDefault())
			{
				string gOPath = GetGOPath(((Component)__instance).gameObject);
				Log.Info("BossArena::GeneralState_OnStateEnter detected a closed Sol arena door: " + gOPath);
				string text = null;
				switch (gOPath)
				{
				case "A2_S5_ BossHorseman_GameLevel/Room/Simple Binding Tool/Boss_SpearHorse_Logic/[Mech]BossDoorx6_FSM Variant/--[States]/FSM/[State] Closed":
					text = "Yingzhao arena front door";
					break;
				case "A2_S5_ BossHorseman_GameLevel/Room/Simple Binding Tool/Boss_SpearHorse_Logic/[Mech]BossDoorx6_FSM Variant (1)/--[States]/FSM/[State] Closed":
					text = "Yingzhao arena back door";
					break;
				case "A3_S5_BossGouMang_GameLevel/Room/[Mech]BossDoorx6_FSM Variant/--[States]/FSM/[State] Closed":
					text = "Goumang arena back door";
					break;
				case "A3_S5_BossGouMang_GameLevel/Room/[Mech]BossDoorx6_FSM Variant (1)/--[States]/FSM/[State] Closed":
					text = "Goumang arena front door";
					break;
				case "A5_S5/Room/EventBinder/[Mech]BossDoorx6_FSM Variant/--[States]/FSM/[State] Closed":
					text = "Jiequan arena door";
					break;
				case "P2_R22_Savepoint_GameLevel/Room/Prefab/EventBinder (Boss Fight 相關)/[Mech]BossDoorx6_FSM Variant (1)/--[States]/FSM/[State] Closed":
					text = "Fengs arena front door";
					break;
				case "P2_R22_Savepoint_GameLevel/Room/Prefab/EventBinder (Boss Fight 相關)/[Mech]BossDoorx6_FSM Variant (2)/--[States]/FSM/[State] Closed":
					text = "Fengs arena back door";
					break;
				case "A10S5/Room/Boss And Environment Binder/[Mech]BossDoorx6_FSM Variant 大柱子/--[States]/FSM/[State] Closed":
					text = "Ji arena door";
					break;
				}
				if (text != null)
				{
					Transform val = ((Component)__instance).transform.parent.Find("[State] Opened");
					AccessTools.Method(typeof(GeneralState), "OnStateEnter", Array.Empty<Type>(), (Type[])null).Invoke((val != null) ? ((Component)val).GetComponent<GeneralState>() : null, Array.Empty<object>());
					Log.Info("BossArena::GeneralState_OnStateEnter forced open the " + text);
				}
			}
		}
	}
	[HarmonyPatch]
	internal class Nymph
	{
		private static string NymphAbilitySaveFlagId = "be31937c6691a44d88d3d70ac2f62cc9PlayerAbilityData";

		public static string GetGOPath(GameObject go)
		{
			Transform val = go.transform;
			List<string> list = new List<string>();
			while ((Object)(object)val != (Object)null)
			{
				list.Add(((Object)val).name);
				val = val.parent;
			}
			list.Reverse();
			return string.Join("/", list);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(PickItemAction), "OnStateEnterImplement")]
		private static bool PickItemAction_OnStateEnterImplement(PickItemAction __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			if ((int)__instance.scheme == 1 && ((GameFlagBase)__instance.pickItemData).FinalSaveID == NymphAbilitySaveFlagId && GetGOPath(((Component)__instance).gameObject) == "A2_Stage_Remake/Room/Prefab/FallingTeleportTrickBackgroundProvider/A7_HotSpring/溫泉場景Setting FSM Object/FSM Animator/LogicRoot/SectionA/[CutScene] Portal 第一次來到 A7/--[States]/FSM/[State] PlayCutSceneEnd/[Action] DisableButterfly")
			{
				GameFlagInt val = (GameFlagInt)SingletonBehaviour<SaveManager>.Instance.allFlags.FlagDict["abf251f7-ed0d-437e-8797-34946931068c_93653f615d5940a409fffdcecb72ec43GameFlagInt"];
				if (((AbstractScriptableData<FlagFieldInt, int>)(object)val).CurrentValue > 0)
				{
					Log.Info($"resetting the 'escort nymph' back to its initial position, since it was at position {((AbstractScriptableData<FlagFieldInt, int>)(object)val).CurrentValue} which would make the soulscape impossible to finish");
					((AbstractScriptableData<FlagFieldInt, int>)(object)val).CurrentValue = 0;
				}
				Log.Info("preventing Lady E's soulscape from disabling the nymph, so you can safely teleport out without losing it");
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal class OperaTheater
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(GameLevel), "Awake")]
		private static void GameLevel_Awake(GameLevel __instance)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			if (!(((Object)__instance).name != "A9_S2") && !(SingletonBehaviour<GameCore>.Instance.PreviousScene == "VR_Memory_伏羲"))
			{
				Dictionary<string, GameFlagBase> flagDict = SingletonBehaviour<SaveManager>.Instance.allFlags.FlagDict;
				ScriptableDataBool val = (ScriptableDataBool)flagDict["1e9feef9-1dc2-4f83-9554-d32780aebfd0_348738fb5673845a6aa8b023a95252cfScriptableDataBool"];
				ScriptableDataBool val2 = (ScriptableDataBool)flagDict["708d79555a8b54472988d75ac5ba8823ScriptableDataBool"];
				if (val.CurrentValue && !val2.CurrentValue)
				{
					Log.Info("OperaTheater GameLevel_Awake detected the EDLA theater is stuck playing the opera and darkening nearby rooms. Turning off the opera so you can get back inside, and see where you're going in nearby rooms.");
					val.CurrentValue = false;
				}
			}
		}
	}
}