Decompiled source of PerkPredictor v1.0.1

WK Perk Predictor/Nebulaetrix.WK_Perk_Predictor.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using DG.Tweening;
using DG.Tweening.Core;
using DG.Tweening.Plugins.Options;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using WK_Perk_Predictor.Core;
using WK_Perk_Predictor.Helpers;
using WK_Perk_Predictor.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Nebulaetrix.WK_Perk_Predictor")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+727e94a82ade1f2ea71d0c2a41837bb821131287")]
[assembly: AssemblyProduct("Nebulaetrix.WK_Perk_Predictor")]
[assembly: AssemblyTitle("Nebulaetrix.WK_Perk_Predictor")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.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 WK_Perk_Predictor
{
	[BepInPlugin("Nebulaetrix.WK_Perk_Predictor", "Nebulaetrix.WK_Perk_Predictor", "1.0.1")]
	public class PerkPredictor : BaseUnityPlugin
	{
		private bool patched;

		private static Harmony _harmony;

		internal static GameObject PerkObj;

		internal static GameObject PerkPane;

		internal static TitleTween TitleTween;

		internal static GameObject PerkCard;

		internal static PerkGenerator PerkGenerator;

		internal static readonly List<GameObject> TerminalList = new List<GameObject>();

		internal static int TerminalNumber = 0;

		internal static int Seed;

		internal static ManualLogSource Logger { get; private set; }

		private void Awake()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (patched)
			{
				Logger.LogWarning((object)"Already Patched");
			}
			Logger = ((BaseUnityPlugin)this).Logger;
			_harmony = new Harmony("Nebulaetrix.WK_Perk_Predictor");
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
			SceneManager.sceneLoaded += OnSceneLoad;
			if (Assets.Load())
			{
				Logger.LogInfo((object)"Plugin Nebulaetrix.WK_Perk_Predictor is loaded!");
				patched = true;
			}
		}

		private void OnSceneLoad(Scene scene, LoadSceneMode mode)
		{
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			TerminalList.Clear();
			TerminalNumber = 0;
			if (!(((Scene)(ref scene)).name != "Game-Main"))
			{
				CommandConsole.hasCheated = true;
				if ((Object)(object)PerkPane == (Object)null)
				{
					PerkObj = Object.Instantiate<GameObject>(Assets.PerkPredictor, GameObject.Find("GameManager/Canvas/Game UI").transform);
					PerkObj.AddComponent<UIFader>();
					PerkPane = ((Component)PerkObj.transform.Find("PerkPane")).gameObject;
					PerkPane.SetActive(true);
					TitleTween = ((Component)PerkObj.transform.Find("Header")).gameObject.AddComponent<TitleTween>();
					TitleTween.TitleText = ((Component)TitleTween).GetComponent<RectTransform>();
					PerkCard = ((Component)PerkPane.transform.Find("Perk_Card")).gameObject;
					PerkGenerator = PerkPane.AddComponent<PerkGenerator>();
					PerkPane.SetActive(true);
				}
				if ((Object)(object)CoroutineRunner.Instance == (Object)null)
				{
					new GameObject("CoroutineRunner").AddComponent<CoroutineRunner>();
				}
				((MonoBehaviour)CoroutineRunner.Instance).StartCoroutine(HandlePerkGenerationAfterDelay());
			}
		}

		private IEnumerator HandlePerkGenerationAfterDelay()
		{
			yield return (object)new WaitForSeconds(1f);
			GameObject root = GameObject.Find("World_Root(Clone)");
			if (!((Object)(object)root != (Object)null))
			{
				yield break;
			}
			List<GameObject> allObjects = GetAllChildren(root);
			foreach (GameObject obj in allObjects)
			{
				if (((Object)obj).name.Contains("Prop_UpgradeConsole"))
				{
					Logger.LogInfo((object)("Found object with 'Prop_UpgradeConsole' in the name: " + ((Object)obj).name));
					TerminalList.Add(obj);
				}
			}
			if (TerminalList.Count > 0)
			{
				((MonoBehaviour)CoroutineRunner.Instance).StartCoroutine(PerkManager.LogPredictedPerks());
			}
			else
			{
				Logger.LogWarning((object)"No terminals found for perk prediction.");
			}
		}

		private static List<GameObject> GetAllChildren(GameObject parent)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			List<GameObject> list = new List<GameObject>();
			foreach (Transform item in parent.transform)
			{
				Transform val = item;
				list.Add(((Component)val).gameObject);
				list.AddRange(GetAllChildren(((Component)val).gameObject));
			}
			return list;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "Nebulaetrix.WK_Perk_Predictor";

		public const string PLUGIN_NAME = "Nebulaetrix.WK_Perk_Predictor";

		public const string PLUGIN_VERSION = "1.0.1";
	}
}
namespace WK_Perk_Predictor.UI
{
	public class TitleTween : MonoBehaviour
	{
		public RectTransform TitleText;

		public float tweenDuration = 3f;

		public float stayDuration = 2.5f;

		public Vector3 centerPosition = new Vector3(-80f, 155f, 0f);

		public Vector3 offLeftPosition = new Vector3(-110f, 155f, 0f);

		public Vector3 offRightPosition = new Vector3(0f, 155f, 0f);

		private void Start()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			TitleText.anchoredPosition = Vector2.op_Implicit(offLeftPosition);
		}

		public void TweenInAndOut()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			TweenSettingsExtensions.OnComplete<TweenerCore<Vector3, Vector3, VectorOptions>>(TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOLocalMove((Transform)(object)TitleText, centerPosition, tweenDuration, false), (Ease)9), (TweenCallback)delegate
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Expected O, but got Unknown
				DOVirtual.DelayedCall(stayDuration, (TweenCallback)delegate
				{
					//IL_0008: Unknown result type (might be due to invalid IL or missing references)
					TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOLocalMove((Transform)(object)TitleText, offRightPosition, tweenDuration, false), (Ease)8);
				}, true);
			});
		}
	}
	public class UIFader : MonoBehaviour
	{
		public CanvasGroup canvasGroup;

		public float fadeDuration = 1f;

		private void Awake()
		{
			if ((Object)(object)canvasGroup == (Object)null)
			{
				canvasGroup = ((Component)this).GetComponent<CanvasGroup>();
			}
		}

		public void FadeIn()
		{
			((MonoBehaviour)this).StartCoroutine(FadeCanvasGroup(0f, 1f));
		}

		public void FadeOut()
		{
			((MonoBehaviour)this).StartCoroutine(FadeCanvasGroup(1f, 0f));
		}

		private IEnumerator FadeCanvasGroup(float start, float end)
		{
			float elapsed = 0f;
			while (elapsed < fadeDuration)
			{
				elapsed += Time.deltaTime;
				canvasGroup.alpha = Mathf.Lerp(start, end, elapsed / fadeDuration);
				yield return null;
			}
			canvasGroup.alpha = end;
		}
	}
}
namespace WK_Perk_Predictor.Patches
{
	[HarmonyPatch(typeof(App_PerkPage))]
	public class AppPerkPagePatch
	{
		[HarmonyPatch("GenerateCards")]
		[HarmonyPrefix]
		private static void SetSeed(App_PerkPage __instance)
		{
			Random.InitState(PerkPredictor.Seed);
		}

		[HarmonyPatch("GenerateCards")]
		[HarmonyPostfix]
		private static void ResetSeed(App_PerkPage __instance)
		{
			Random.InitState(0);
		}

		[HarmonyPatch("CheckIronKnuckle")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> CheckIronKnuckleTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			for (int i = 0; i < list.Count - 1; i++)
			{
				if (list[i].opcode == OpCodes.Ldstr && list[i].operand == "You are playing in IRON KNUCKLE mode. No perks for you!")
				{
					list[i] = new CodeInstruction(OpCodes.Ldstr, (object)"Get yo dumb ahh knuckles out this terminal, you're playing iron knuckle!!");
				}
			}
			PerkPredictor.Logger.LogInfo((object)"Terminal patched!");
			return list;
		}
	}
	[HarmonyPatch(typeof(WorldLoader))]
	public class WorldLoaderPatch
	{
		private static HashSet<string> TrackedLevels;

		private static string _lastLevelName;

		[HarmonyPatch("GenerateLevels")]
		[HarmonyPostfix]
		private static void SetSeed(WorldLoader __instance)
		{
			PerkPredictor.Seed = __instance.seed;
			TrackedLevels = new HashSet<string> { "M1_Silos_SafeArea_01", "M1_Campaign_Transition_Silo_To_Pipeworks_01", "M3_Habitation_Shaft_Intro", "M1_Silos_SafeArea_Endless_01", "M2_Pipeworks_Break_01", "M3_Habitation_Endless_Breakroom_01" };
		}

		[HarmonyPatch(typeof(WorldLoader), "GetClosestLevelToPosition")]
		[HarmonyPostfix]
		private static void GetCurrentLevel(LevelInfo __result)
		{
			if (__result != null)
			{
				string levelName = __result.level.levelName;
				if (_lastLevelName != null && TrackedLevels.Contains(_lastLevelName) && _lastLevelName != levelName)
				{
					PerkPredictor.Logger.LogInfo((object)("Player left tracked level: " + _lastLevelName));
					TrackedLevels.Remove(_lastLevelName);
					HandleLevelExit();
				}
				_lastLevelName = levelName;
			}
		}

		private static void HandleLevelExit()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			PerkPredictor.Seed++;
			PerkPredictor.TerminalNumber++;
			if (PerkPredictor.TerminalNumber < 3)
			{
				Scene activeScene = SceneManager.GetActiveScene();
				if (!(((Scene)(ref activeScene)).name != "Game-Main"))
				{
					((MonoBehaviour)CoroutineRunner.Instance).StartCoroutine(PerkManager.LogPredictedPerks());
				}
			}
		}
	}
}
namespace WK_Perk_Predictor.Helpers
{
	public class CoroutineRunner : MonoBehaviour
	{
		public static CoroutineRunner Instance { get; private set; }

		private void Awake()
		{
			if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		}
	}
}
namespace WK_Perk_Predictor.Core
{
	internal static class Assets
	{
		private static AssetBundle _assets;

		internal static GameObject PerkPredictor;

		internal static bool Load()
		{
			_assets = AssetBundle.LoadFromFile(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/Assets/perk_predictor_assets");
			if ((Object)(object)_assets == (Object)null)
			{
				WK_Perk_Predictor.PerkPredictor.Logger.LogError((object)"Failed to load AssetBundle, aborting!");
				return false;
			}
			List<bool> source = new List<bool>(1) { LoadFile<GameObject>(_assets, "Assets/Neb.Assets/PerkPredictor.prefab", out PerkPredictor) };
			if (source.Any((bool result) => !result))
			{
				WK_Perk_Predictor.PerkPredictor.Logger.LogWarning((object)"Failed to load one or more assets, aborting!");
				return false;
			}
			return true;
		}

		private static bool LoadFile<T>(AssetBundle assets, string path, out T loadedObject) where T : Object
		{
			loadedObject = assets.LoadAsset<T>(path);
			if (!Object.op_Implicit((Object)(object)loadedObject))
			{
				WK_Perk_Predictor.PerkPredictor.Logger.LogError((object)("Failed to load '" + path + "'"));
				return false;
			}
			return true;
		}
	}
	public class PerkGenerator : MonoBehaviour
	{
		private const int MaxAttempts = 100;

		internal List<Perk> GenerateUpcomingPerks(GameObject currentTerminal)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			List<Perk> list = new List<Perk>();
			PerkPageType perkPageType = GetPerkPageType(currentTerminal);
			var (num, num2) = GetPageRanges(perkPageType);
			Random.InitState(PerkPredictor.Seed);
			int num3 = Random.Range(num, num2 + 1);
			List<Perk> list2 = new List<Perk>(CL_AssetManager.instance.assetDatabase.perkAssets);
			if (list2.Count == 0)
			{
				Debug.LogWarning((object)"Perk pool is empty — cannot generate perks.");
				return list;
			}
			FilterPerkPool(list2, perkPageType);
			for (int i = 0; i < num3; i++)
			{
				TryAddPerk(list2, list, perkPageType, i == num3 - 1);
			}
			return list;
		}

		private PerkPageType GetPerkPageType(GameObject terminal)
		{
			//IL_0018: 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)
			return (PerkPageType)(((Object)terminal).name.Contains("Experimental", StringComparison.OrdinalIgnoreCase) ? 1 : 0);
		}

		private (int minPages, int maxPages) GetPageRanges(PerkPageType type)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return ((int)type == 0) ? (3, 3) : (2, 2);
		}

		private void FilterPerkPool(List<Perk> pool, PerkPageType type)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			pool.RemoveAll((Perk perk) => ((int)type == 0 && (int)perk.spawnPool != 0) || ((int)type == 1 && (int)perk.spawnPool != 1));
		}

		private void TryAddPerk(List<Perk> pool, List<Perk> upcomingPerks, PerkPageType type, bool isFinalPerk)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Invalid comparison between Unknown and I4
			bool flag = false;
			int num = 0;
			while (!flag && num < 100)
			{
				num++;
				Perk val = pool[Random.Range(0, pool.Count)];
				if (val.CanSpawn() && ((int)type == 1 || (!isFinalPerk && val.cost == 0) || (isFinalPerk && val.cost > 0)))
				{
					flag = true;
					upcomingPerks.Add(val);
					pool.Remove(val);
				}
			}
		}
	}
	public class PerkManager : MonoBehaviour
	{
		private static readonly List<GameObject> ActivePerkList = new List<GameObject>();

		private static List<Perk> _activePerks = new List<Perk>();

		internal static IEnumerator LogPredictedPerks()
		{
			if (ActivePerkList.Count != 0)
			{
				foreach (GameObject perk in ActivePerkList)
				{
					Object.Destroy((Object)(object)perk);
				}
			}
			yield return (object)new WaitForSeconds(1f);
			try
			{
				PerkPredictor.PerkObj.GetComponent<UIFader>().FadeIn();
				PerkPredictor.TitleTween.TweenInAndOut();
				_activePerks = PerkPredictor.PerkGenerator.GenerateUpcomingPerks(PerkPredictor.TerminalList[PerkPredictor.TerminalNumber]);
				PerkPredictor.Logger.LogInfo((object)"Upcoming perks:");
				foreach (Perk perk2 in _activePerks)
				{
					AddPerkToDisplay(perk2);
					PerkPredictor.Logger.LogInfo((object)perk2.title);
					StartFadeOut();
				}
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Error predicting perks: " + ex.Message));
				Debug.Log((object)"No more terminals left!");
			}
		}

		private static void AddPerkToDisplay(Perk currentPerk)
		{
			GameObject val = Object.Instantiate<GameObject>(PerkPredictor.PerkCard, PerkPredictor.PerkPane.transform);
			SetCardImage(val, currentPerk.perkCard);
			SetTitleText(val, currentPerk.title);
			val.SetActive(true);
			ActivePerkList.Add(val);
		}

		private static void SetCardImage(GameObject perkObject, Sprite perkCard)
		{
			Transform obj = perkObject.transform.Find("Perk_Card_Art_Root/Perk_Card_Art");
			Image val = ((obj != null) ? ((Component)obj).GetComponent<Image>() : null);
			if ((Object)(object)val != (Object)null && (Object)(object)perkCard != (Object)null)
			{
				val.sprite = perkCard;
			}
		}

		private static void SetTitleText(GameObject perkObject, string title)
		{
			Transform obj = perkObject.transform.Find("Title Text");
			TextMeshProUGUI val = ((obj != null) ? ((Component)obj).GetComponent<TextMeshProUGUI>() : null);
			if ((Object)(object)val != (Object)null)
			{
				((TMP_Text)val).text = title;
			}
		}

		private static void StartFadeOut()
		{
			((MonoBehaviour)CoroutineRunner.Instance).StartCoroutine(FadeOutPane());
		}

		private static IEnumerator FadeOutPane()
		{
			yield return (object)new WaitForSeconds(7f);
			PerkPredictor.PerkObj.GetComponent<UIFader>().FadeOut();
		}
	}
}