using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using LimitPerkPool.UI;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("LimitPerkPool")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LimitPerkPool")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("fcd0a3b8-5916-4304-b2af-f66fbc68ff14")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace LimitPerkPool
{
[BepInPlugin("nachariah.whiteknuckle.limitperkpool", "LimitPerkPool", "2.0.0")]
[BepInProcess("White Knuckle.exe")]
public class Plugin : BaseUnityPlugin
{
public const string GUID = "nachariah.whiteknuckle.limitperkpool";
public static Plugin Instance;
public MenuUI drawer;
public Dictionary<string, bool> AllowedPerks = new Dictionary<string, bool>();
private void Awake()
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected O, but got Unknown
Instance = this;
((BaseUnityPlugin)this).Logger.LogInfo((object)"[LimitPerkPool] Patching...");
Harmony val = new Harmony("nachariah.whiteknuckle.limitperkpool");
val.PatchAll();
SceneManager.sceneLoaded += OnSceneLoaded;
((BaseUnityPlugin)this).Logger.LogInfo((object)"[LimitPerkPool] Loaded");
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
if ((Object)(object)drawer == (Object)null)
{
drawer = MenuUI.Create();
}
if ((Object)(object)drawer != (Object)null)
{
((Behaviour)drawer.rootCanvas).enabled = ((Scene)(ref scene)).name == "Main-Menu";
}
if (((Scene)(ref scene)).name == "Game-Main")
{
CommandConsole.hasCheated = true;
CL_GameManager.gamemode.allowAchievements = false;
CL_GameManager.gamemode.allowCheatedScores = false;
UpdateAllowedPerks();
}
else if (((Scene)(ref scene)).name == "Main-Menu" && (Object)(object)drawer != (Object)null)
{
drawer.CloseDrawer();
drawer.PopulatePerkToggles(UpdateAllowedPerks());
}
}
public Dictionary<string, bool> UpdateAllowedPerks()
{
Debug.Log((object)"[LimitPerkPool] Updating Perks");
List<Perk> perkAssets = CL_AssetManager.GetFullCombinedAssetDatabase().perkAssets;
if (perkAssets == null || perkAssets.Count == 0)
{
Debug.LogError((object)"[LimitPerkPool] Perk Update fail due to no/null perks");
return null;
}
foreach (Perk item in perkAssets)
{
string name = ((Object)item).name;
ConfigEntry<bool> val = ((BaseUnityPlugin)Instance).Config.Bind<bool>("PerkToggles", name, true, "Enable or disable '" + name + "'");
AllowedPerks[name] = val.Value;
}
return AllowedPerks;
}
}
}
namespace LimitPerkPool.UI
{
public class MenuUI : MonoBehaviour
{
public Canvas rootCanvas;
public RectTransform drawerPanel;
public RectTransform handleRect;
public Button handleButton;
private RectTransform scrollContent;
private bool isOpen = false;
private float drawerWidth = 400f;
private float speed = 1800f;
public static MenuUI Create()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
GameObject val = new GameObject("PerkDrawer");
Object.DontDestroyOnLoad((Object)(object)val);
MenuUI menuUI = val.AddComponent<MenuUI>();
menuUI.BuildUI();
return menuUI;
}
private void BuildUI()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Expected O, but got Unknown
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: 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)
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_012f: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Unknown result type (might be due to invalid IL or missing references)
//IL_0191: Unknown result type (might be due to invalid IL or missing references)
//IL_0197: Expected O, but got Unknown
//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
//IL_0201: Unknown result type (might be due to invalid IL or missing references)
//IL_021c: Unknown result type (might be due to invalid IL or missing references)
//IL_0239: Unknown result type (might be due to invalid IL or missing references)
//IL_024a: Unknown result type (might be due to invalid IL or missing references)
//IL_025d: Unknown result type (might be due to invalid IL or missing references)
//IL_0273: Unknown result type (might be due to invalid IL or missing references)
//IL_029c: Unknown result type (might be due to invalid IL or missing references)
//IL_02a6: Expected O, but got Unknown
//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
//IL_02d2: Expected O, but got Unknown
//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0309: Unknown result type (might be due to invalid IL or missing references)
//IL_0316: Unknown result type (might be due to invalid IL or missing references)
//IL_0341: Unknown result type (might be due to invalid IL or missing references)
//IL_038d: Unknown result type (might be due to invalid IL or missing references)
//IL_0394: Expected O, but got Unknown
//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
//IL_03da: Unknown result type (might be due to invalid IL or missing references)
//IL_0417: Unknown result type (might be due to invalid IL or missing references)
//IL_043f: Unknown result type (might be due to invalid IL or missing references)
//IL_0456: Unknown result type (might be due to invalid IL or missing references)
//IL_046d: Unknown result type (might be due to invalid IL or missing references)
//IL_047a: Unknown result type (might be due to invalid IL or missing references)
//IL_0487: Unknown result type (might be due to invalid IL or missing references)
//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
//IL_04f8: Unknown result type (might be due to invalid IL or missing references)
//IL_04ff: Expected O, but got Unknown
//IL_052c: Unknown result type (might be due to invalid IL or missing references)
//IL_0547: Unknown result type (might be due to invalid IL or missing references)
//IL_0562: Unknown result type (might be due to invalid IL or missing references)
//IL_0573: Unknown result type (might be due to invalid IL or missing references)
//IL_058e: Unknown result type (might be due to invalid IL or missing references)
rootCanvas = new GameObject("DrawerCanvas").AddComponent<Canvas>();
rootCanvas.renderMode = (RenderMode)0;
rootCanvas.sortingOrder = 1;
((Component)rootCanvas).gameObject.AddComponent<CanvasScaler>();
((Component)rootCanvas).gameObject.AddComponent<GraphicRaycaster>();
Object.DontDestroyOnLoad((Object)(object)((Component)rootCanvas).gameObject);
GameObject val = new GameObject("DrawerPanel", new Type[2]
{
typeof(RectTransform),
typeof(Image)
});
val.transform.SetParent(((Component)rootCanvas).transform, false);
drawerPanel = val.GetComponent<RectTransform>();
drawerPanel.anchorMin = new Vector2(1f, 0f);
drawerPanel.anchorMax = new Vector2(1f, 1f);
drawerPanel.pivot = new Vector2(1f, 0.5f);
drawerPanel.sizeDelta = new Vector2(drawerWidth, 0f);
drawerPanel.anchoredPosition = new Vector2(0f, 0f);
((Graphic)val.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.7f);
GameObject val2 = new GameObject("HandleButton", new Type[3]
{
typeof(RectTransform),
typeof(Image),
typeof(Button)
});
val2.transform.SetParent(((Component)rootCanvas).transform, false);
handleRect = val2.GetComponent<RectTransform>();
handleRect.sizeDelta = new Vector2(30f, 100f);
handleRect.anchorMin = new Vector2(1f, 0.5f);
handleRect.anchorMax = new Vector2(1f, 0.5f);
handleRect.pivot = new Vector2(0f, 0.5f);
handleRect.anchoredPosition = new Vector2(0f - drawerWidth, 0f);
((Graphic)val2.GetComponent<Image>()).color = Color.black;
Outline val3 = val2.AddComponent<Outline>();
((Shadow)val3).effectColor = Color.white;
((Shadow)val3).effectDistance = new Vector2(1f, -1f);
handleButton = val2.GetComponent<Button>();
((UnityEvent)handleButton.onClick).AddListener(new UnityAction(ToggleDrawer));
GameObject val4 = new GameObject("HandleLabel", new Type[2]
{
typeof(RectTransform),
typeof(Text)
});
val4.transform.SetParent((Transform)(object)handleRect, false);
RectTransform component = val4.GetComponent<RectTransform>();
component.anchorMin = Vector2.zero;
component.anchorMax = Vector2.one;
component.offsetMin = Vector2.zero;
component.offsetMax = Vector2.zero;
Text component2 = val4.GetComponent<Text>();
component2.text = "P\nE\nR\nK\nS";
component2.alignment = (TextAnchor)4;
((Graphic)component2).color = Color.white;
component2.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
component2.fontSize = 14;
GameObject val5 = new GameObject("ScrollView", new Type[2]
{
typeof(RectTransform),
typeof(ScrollRect)
});
val5.transform.SetParent((Transform)(object)drawerPanel, false);
RectTransform component3 = val5.GetComponent<RectTransform>();
component3.anchorMin = Vector2.zero;
component3.anchorMax = Vector2.one;
component3.offsetMin = Vector2.zero;
component3.offsetMax = Vector2.zero;
RectTransform component4 = new GameObject("Viewport", new Type[3]
{
typeof(RectTransform),
typeof(Image),
typeof(Mask)
}).GetComponent<RectTransform>();
((Transform)component4).SetParent(((Component)component3).transform, false);
component4.anchorMin = new Vector2(0f, 0f);
component4.anchorMax = new Vector2(1f, 1f);
component4.pivot = new Vector2(0.5f, 0.5f);
component4.offsetMin = Vector2.zero;
component4.offsetMax = Vector2.zero;
((Graphic)((Component)component4).GetComponent<Image>()).color = new Color(1f, 1f, 1f, 0.05f);
((Component)component4).GetComponent<Mask>().showMaskGraphic = false;
GameObject val6 = new GameObject("Content", new Type[3]
{
typeof(RectTransform),
typeof(VerticalLayoutGroup),
typeof(ContentSizeFitter)
});
val6.transform.SetParent((Transform)(object)component4, false);
scrollContent = val6.GetComponent<RectTransform>();
scrollContent.anchorMin = new Vector2(0f, 1f);
scrollContent.anchorMax = new Vector2(1f, 1f);
scrollContent.pivot = new Vector2(0.5f, 1f);
scrollContent.anchoredPosition = Vector2.zero;
scrollContent.sizeDelta = new Vector2(0f, 0f);
VerticalLayoutGroup component5 = val6.GetComponent<VerticalLayoutGroup>();
((HorizontalOrVerticalLayoutGroup)component5).childControlHeight = true;
((HorizontalOrVerticalLayoutGroup)component5).childControlWidth = true;
((HorizontalOrVerticalLayoutGroup)component5).childForceExpandHeight = false;
((HorizontalOrVerticalLayoutGroup)component5).childForceExpandWidth = true;
((HorizontalOrVerticalLayoutGroup)component5).spacing = 5f;
ContentSizeFitter val7 = val6.AddComponent<ContentSizeFitter>();
val7.verticalFit = (FitMode)2;
val7.horizontalFit = (FitMode)0;
ScrollRect component6 = val5.GetComponent<ScrollRect>();
component6.viewport = component4;
component6.content = scrollContent;
component6.horizontal = false;
component6.vertical = true;
component6.movementType = (MovementType)1;
component6.inertia = false;
}
private void Update()
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
Vector2 val = (isOpen ? new Vector2(0f, 0f) : new Vector2(drawerWidth, 0f));
drawerPanel.anchoredPosition = Vector2.MoveTowards(drawerPanel.anchoredPosition, val, speed * Time.deltaTime);
handleRect.anchoredPosition = Vector2.MoveTowards(handleRect.anchoredPosition, val - new Vector2(handleRect.sizeDelta.x + drawerWidth + 1f, 0f), speed * Time.deltaTime);
}
public void ToggleDrawer()
{
isOpen = !isOpen;
}
public void OpenDrawer()
{
isOpen = true;
}
public void CloseDrawer()
{
isOpen = false;
}
public void PopulatePerkToggles(Dictionary<string, bool> perks)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Expected O, but got Unknown
//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
//IL_011f: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Expected O, but got Unknown
//IL_0150: Unknown result type (might be due to invalid IL or missing references)
//IL_0167: Unknown result type (might be due to invalid IL or missing references)
//IL_017e: Unknown result type (might be due to invalid IL or missing references)
//IL_0195: Unknown result type (might be due to invalid IL or missing references)
//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
//IL_01f9: Expected O, but got Unknown
//IL_0219: Unknown result type (might be due to invalid IL or missing references)
//IL_0226: Unknown result type (might be due to invalid IL or missing references)
//IL_0233: Unknown result type (might be due to invalid IL or missing references)
//IL_0240: Unknown result type (might be due to invalid IL or missing references)
//IL_0256: Unknown result type (might be due to invalid IL or missing references)
//IL_0286: Unknown result type (might be due to invalid IL or missing references)
//IL_028d: Expected O, but got Unknown
//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
//IL_0320: Unknown result type (might be due to invalid IL or missing references)
//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
//IL_03d7: Expected O, but got Unknown
foreach (Transform item in (Transform)scrollContent)
{
Transform val = item;
Object.Destroy((Object)(object)((Component)val).gameObject);
}
foreach (KeyValuePair<string, bool> perk in perks)
{
string perkName = perk.Key;
bool value = perk.Value;
GameObject val2 = new GameObject(perkName, new Type[2]
{
typeof(RectTransform),
typeof(Toggle)
});
val2.transform.SetParent((Transform)(object)scrollContent, false);
RectTransform component = val2.GetComponent<RectTransform>();
component.sizeDelta = new Vector2(0f, 30f);
Toggle component2 = val2.GetComponent<Toggle>();
LayoutElement val3 = val2.AddComponent<LayoutElement>();
val3.preferredHeight = 30f;
GameObject val4 = new GameObject("Background", new Type[2]
{
typeof(RectTransform),
typeof(Image)
});
val4.transform.SetParent(val2.transform, false);
RectTransform component3 = val4.GetComponent<RectTransform>();
component3.anchorMin = new Vector2(0f, 0f);
component3.anchorMax = new Vector2(0f, 1f);
component3.pivot = new Vector2(0f, 0.5f);
component3.sizeDelta = new Vector2(20f, 0f);
component3.anchoredPosition = new Vector2(10f, 0f);
Image component4 = val4.GetComponent<Image>();
((Graphic)component4).color = Color.white;
GameObject val5 = new GameObject("Checkmark", new Type[2]
{
typeof(RectTransform),
typeof(Image)
});
val5.transform.SetParent(val4.transform, false);
RectTransform component5 = val5.GetComponent<RectTransform>();
component5.anchorMin = Vector2.zero;
component5.anchorMax = Vector2.one;
component5.offsetMin = Vector2.zero;
component5.offsetMax = Vector2.zero;
Image component6 = val5.GetComponent<Image>();
((Graphic)component6).color = Color.green;
GameObject val6 = new GameObject("Label", new Type[2]
{
typeof(RectTransform),
typeof(Text)
});
val6.transform.SetParent(val2.transform, false);
RectTransform component7 = val6.GetComponent<RectTransform>();
component7.anchorMin = new Vector2(0f, 0f);
component7.anchorMax = new Vector2(1f, 1f);
component7.offsetMin = new Vector2(40f, 0f);
component7.offsetMax = Vector2.zero;
Text component8 = val6.GetComponent<Text>();
component8.text = perkName;
component8.alignment = (TextAnchor)3;
((Graphic)component8).color = Color.white;
component8.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
((Selectable)component2).targetGraphic = (Graphic)(object)component4;
component2.graphic = (Graphic)(object)component6;
component2.isOn = value;
((UnityEvent<bool>)(object)component2.onValueChanged).AddListener((UnityAction<bool>)delegate(bool newValue)
{
((BaseUnityPlugin)Plugin.Instance).Config["PerkToggles", perkName].BoxedValue = newValue;
});
Debug.Log((object)$"[LimitPerkPool] Added toggle for {perkName}, {value}");
}
Canvas.ForceUpdateCanvases();
LayoutRebuilder.ForceRebuildLayoutImmediate(scrollContent);
LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)((Transform)scrollContent).parent);
}
}
}
namespace LimitPerkPool.Patches
{
[HarmonyPatch(typeof(App_PerkPage), "GenerateCards")]
public static class App_PerkPage_GenerateCards_Patcher
{
[HarmonyPrefix]
public static bool GenerateCards_Limit(App_PerkPage __instance)
{
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Expected O, but got Unknown
//IL_010e: Unknown result type (might be due to invalid IL or missing references)
//IL_0114: Invalid comparison between Unknown and I4
//IL_0142: Unknown result type (might be due to invalid IL or missing references)
//IL_0148: Invalid comparison between Unknown and I4
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: Invalid comparison between Unknown and I4
//IL_015a: Unknown result type (might be due to invalid IL or missing references)
//IL_0160: Invalid comparison between Unknown and I4
//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
//IL_0258: Unknown result type (might be due to invalid IL or missing references)
//IL_025e: Invalid comparison between Unknown and I4
if (Plugin.Instance.UpdateAllowedPerks() == null)
{
return true;
}
FieldInfo field = typeof(App_PerkPage).GetField("os", BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo field2 = typeof(App_PerkPage).GetField("cards", BindingFlags.Instance | BindingFlags.NonPublic);
OS_Manager val = (OS_Manager)field.GetValue(__instance);
List<App_PerkPage_Card> list = (List<App_PerkPage_Card>)field2.GetValue(__instance);
OS_Computer_Interface worldInterface = val.worldInterface;
Debug.Log((object)"[LimitPerkPool] Generating Perks...");
SessionFlag gameFlag = CL_GameManager.GetGameFlag("recieved-" + worldInterface.computerID + "-perk");
if (gameFlag != null && gameFlag.state)
{
return false;
}
if (worldInterface.GetSeed() != -1)
{
Random.InitState(worldInterface.GetSeed());
}
int num = Random.Range(__instance.minCards, __instance.maxCards + 1);
List<Perk> list2 = new List<Perk>(CL_AssetManager.GetFullCombinedAssetDatabase().perkAssets);
for (int num2 = list2.Count - 1; num2 >= 0; num2--)
{
if ((int)__instance.perkPageType == 0)
{
if ((int)list2[num2].spawnPool > 0)
{
list2.RemoveAt(num2);
}
}
else if ((int)__instance.perkPageType == 1 && (int)list2[num2].spawnPool != 1)
{
list2.RemoveAt(num2);
}
}
Dictionary<string, bool> allowed = Plugin.Instance.AllowedPerks;
list2.RemoveAll((Perk p) => !allowed.TryGetValue(((Object)p).name, out var value) || !value);
Debug.Log((object)$"[LimitPerkPool] {list2.Count} perk(s) in perk pool");
for (int i = 0; i < num; i++)
{
App_PerkPage_Card component = ((Component)Object.Instantiate<App_PerkPage_Card>(__instance.cardAsset, __instance.cardParent.position, Quaternion.identity, __instance.cardParent)).GetComponent<App_PerkPage_Card>();
bool flag = false;
Perk val2 = null;
int num3 = 0;
while (!flag && num3 < 100)
{
num3++;
val2 = list2[Random.Range(0, list2.Count)];
if (!val2.CanSpawn())
{
Debug.Log((object)("[LimitPerkPool] '" + ((Object)val2).name + "' cannot spawn"));
}
else if ((int)__instance.perkPageType == 1)
{
flag = true;
}
else if ((i < num - 1 && val2.cost == 0) || (i == num - 1 && val2.cost > 0))
{
flag = true;
}
}
list2.Remove(val2);
val2 = Object.Instantiate<Perk>(val2);
int num4 = 0;
if (CL_GameManager.gMan.GetPlayerAscent() > 2000f)
{
num4 = Mathf.RoundToInt((CL_GameManager.gMan.GetPlayerAscent() - 2000f) / 200f);
}
Perk obj = val2;
obj.cost += num4;
val2.cost = Mathf.Min(val2.cost, 99);
component.Initialize(__instance, val2);
list.Add(component);
}
__instance.SubmitCard(list[0]);
return false;
}
}
}