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();
}
}
}