using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Linq.Expressions; 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.Configuration; using CookieFx; using CookieFx.Client; using CookieFx.Network; using CookieFx.Network.Payloads; using CookieFx.Platform; using CookieFx.Players; using CookieFx.Server; using CookieFx.Skills; using CookieProgression; using CookieProgression.Experience; using CookieProgression.Patches; using CookieProgression.Payloads; using CookieProgression.Skills; using CookieProgression.UI; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; 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: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("ClientNetworkTransform")] [assembly: IgnoresAccessChecksTo("DissonanceVoip")] [assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")] [assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")] [assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")] [assembly: IgnoresAccessChecksTo("Unity.Burst")] [assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")] [assembly: IgnoresAccessChecksTo("Unity.Collections")] [assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")] [assembly: IgnoresAccessChecksTo("Unity.Jobs")] [assembly: IgnoresAccessChecksTo("Unity.Mathematics")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")] [assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")] [assembly: IgnoresAccessChecksTo("Unity.Services.QoS")] [assembly: IgnoresAccessChecksTo("Unity.Services.Relay")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("Unity.Timeline")] [assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")] [assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("CookieSylvia")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.1.2.0")] [assembly: AssemblyInformationalVersion("0.1.2")] [assembly: AssemblyProduct("CookieProgression")] [assembly: AssemblyTitle("CookieProgression")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.2.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 CookieFx.Skills { public enum SkillFormat { Modifier, Mulitply, SubtractSeconds, Value } } namespace CookieFx.Patches { [HarmonyPatch] [HarmonyWrapSafe] internal static class DoorLockPatch { [HarmonyPatch(typeof(DoorLock), "Update")] [HarmonyTranspiler] private static IEnumerable OnUpdate(IEnumerable instructions) { FieldInfo lockPickTimeLeft = AccessTools.DeclaredField(typeof(DoorLock), "lockPickTimeLeft"); MethodInfo deltaTime = AccessTools.DeclaredPropertyGetter(typeof(Time), "deltaTime"); MethodInfo getMul = AccessUtils.MethodInfo((LambdaExpression)(Expression>>)(() => SkillManager.GetTeamMultiplier)); int step = 0; foreach (CodeInstruction instruction in instructions) { yield return instruction; if (CodeInstructionExtensions.IsLdarg(instruction, (int?)0)) { step = 1; continue; } if (step == 1 && CodeInstructionExtensions.LoadsField(instruction, lockPickTimeLeft, false)) { step = 2; continue; } if (step == 2 && CodeInstructionExtensions.Calls(instruction, deltaTime)) { yield return new CodeInstruction(OpCodes.Ldc_I4, (object)18); yield return new CodeInstruction(OpCodes.Call, (object)getMul); yield return new CodeInstruction(OpCodes.Conv_R4, (object)null); yield return new CodeInstruction(OpCodes.Ldc_R4, (object)1f); yield return new CodeInstruction(OpCodes.Add, (object)null); yield return new CodeInstruction(OpCodes.Mul, (object)null); } step = 0; } } } [HarmonyPatch] [HarmonyWrapSafe] internal static class ExpPatches { [HarmonyPatch(typeof(TimeOfDay), "SetNewProfitQuota")] [HarmonyTranspiler] private static IEnumerable OnQuotaChange(IEnumerable instructions) { MethodInfo original = AccessUtils.MethodInfo((LambdaExpression)(Expression>>)(() => ((TimeOfDay)null).SyncNewProfitQuotaClientRpc)); MethodInfo target = AccessUtils.MethodInfo((LambdaExpression)(Expression>>)(() => OnQuotaChangeRedirect)); bool found = false; foreach (CodeInstruction instruction in instructions) { if (CodeInstructionExtensions.Calls(instruction, original)) { yield return new CodeInstruction(OpCodes.Call, (object)target); found = true; } else { yield return instruction; } } if (!found) { Logger.Error("[Patch] Unable to patch quota change."); } } private static void OnQuotaChangeRedirect(TimeOfDay script, int newProfitQuota, int overtimeBonus, int fulfilledQuota) { int num = overtimeBonus; try { num = (int)((double)overtimeBonus * (1.0 + SkillManager.GetTeamMultiplier(SkillType.OvertimeBonus))); } finally { script.SyncNewProfitQuotaClientRpc(newProfitQuota, num, fulfilledQuota); } } } } namespace CookieProgression { internal static class Config { private record BoundSkill(ConfigEntry Enabled, ConfigEntry MaxLevel, ConfigEntry Multiplier); private record BoundEnemy(ConfigEntry ExpType, ConfigEntry Range, ConfigEntry BaseExp); public enum EnemyExpType { Disabled, AoE, Attacker } private static readonly Dictionary SkillBindings = new Dictionary(); private static readonly Dictionary EnemyBindings = new Dictionary(); private static bool s_dirty = false; internal static void Setup(ConfigFile file) { Guard.NotNull(file, "file"); foreach (BoundSkill value in SkillBindings.Values) { value.Enabled.SettingChanged -= OnSkillChanged; value.MaxLevel.SettingChanged -= OnSkillChanged; value.Multiplier.SettingChanged -= OnSkillChanged; } SkillBindings.Clear(); SkillType[] array = (SkillType[])Enum.GetValues(typeof(SkillType)); foreach (SkillType skill in array) { BindSkill(file, skill); } foreach (BoundSkill value2 in SkillBindings.Values) { value2.Enabled.SettingChanged += OnSkillChanged; value2.MaxLevel.SettingChanged += OnSkillChanged; value2.Multiplier.SettingChanged += OnSkillChanged; } EnemyBindings.Clear(); foreach (Type item in (from type in Reflect.AllTypesAssignableTo(typeof(EnemyAI)) where type != typeof(EnemyAI) select type).OrderBy(GetEnemyFriendlyName)) { BindEnemy(file, item); } } private static void OnSkillChanged(object? sender, EventArgs e) { if (!Networking.IsConnected || !Networking.Instance.IsServer) { return; } s_dirty = true; Networking.EnqueueTask((Action)delegate(Networking instance) { if (!s_dirty || !instance.IsServer) { return; } s_dirty = false; AbstractServer server = instance.Server; SkillManager skills = default(SkillManager); foreach (ServerPlayer player in server.Players) { if (((AbstractPlayer)player).TryGet(ref skills)) { SetSkills(skills); } } }); } internal static void SetSkills(SkillManager manager) { manager.SetDefinitions(from x in SkillBindings where x.Value.Enabled.Value select (Key: x.Key, Math.Clamp(x.Value.MaxLevel.Value, 1, 99999), Math.Clamp(x.Value.Multiplier.Value, 1, 1000000))); } internal static (EnemyExpType, int Range, int BaseExp) GetEnemyExp(Type enemy) { if (EnemyBindings.TryGetValue(enemy, out BoundEnemy value)) { return (value.ExpType.Value, Range: Math.Max(value.Range.Value, 0), BaseExp: Math.Max(value.BaseExp.Value, 0)); } Logger.Warning("Enemy [" + enemy.FullName + "] doesn't have a bound config entry."); return (EnemyExpType.Disabled, Range: 0, BaseExp: 0); } private static void BindSkill(ConfigFile file, SkillType skill) { string name = skill.GetName(); Logger.Info("Found skill type [" + name + "]"); int defaultMaxLevel = skill.GetDefaultMaxLevel(); int defaultMultiplier = skill.GetDefaultMultiplier(); ConfigEntry enabled = file.Bind(name, "Enable " + name, true, "Enable the " + name + " skill."); ConfigEntry maxLevel = file.Bind(name, name + " Max Level", defaultMaxLevel, "Maximum level for " + name); ConfigEntry multiplier = file.Bind(name, name + " Multiplier", defaultMultiplier, $"How much does the {name} skill increase per level? ({10000:N0} = 100% or 100s)"); SkillBindings[skill] = new BoundSkill(enabled, maxLevel, multiplier); } private static void BindEnemy(ConfigFile file, Type enemy) { string enemyFriendlyName = GetEnemyFriendlyName(enemy); Logger.Info("Found enemy type [" + enemyFriendlyName + "] (aka. " + enemy.FullName + ")"); string text2 = default(string); string text = (PluginUtils.TryGetPluginId(enemy.Assembly, ref text2) ? ("Internal: " + enemy.FullName + "\nModded Enemy from " + text2 + "\n\n") : ((!(enemy.Assembly == typeof(EnemyAI).Assembly)) ? ("Internal: " + enemy.FullName + "\nUnknown Enemy in " + enemy.Assembly.FullName + "\n\n") : ("Internal: " + enemy.FullName + "\nVanilla Enemy\n\n"))); ConfigEntry expType = file.Bind(enemyFriendlyName, enemyFriendlyName + " Mode", GetDefaultEnemyMode(enemy), text + "Exp distribution from killing " + enemyFriendlyName + ".\n\nDisabled = Does not award exp.\nAoE = Awards exp within a range.\nAttacker = Awards exp to the attacker."); ConfigEntry range = file.Bind(enemyFriendlyName, enemyFriendlyName + " Range", GetDefaultEnemyExpRange(enemy), text + "Exp distribution range in units, only used if mode is [AoE]"); ConfigEntry baseExp = file.Bind(enemyFriendlyName, enemyFriendlyName + " Base Exp", GetDefaultEnemyBaseExp(enemy), text + "The base exp that " + enemyFriendlyName + " awards when killed."); EnemyBindings[enemy] = new BoundEnemy(expType, range, baseExp); } internal static string GetEnemyFriendlyName(Type type) { string fullName = type.FullName; if (1 == 0) { } string result = fullName switch { "BaboonBirdAI" => "Baboon Hawk", "BushWolfEnemy" => "Kidnapper Fox", "ButlerBeesEnemyAI" => "Butler Bees", "ButlerEnemyAI" => "Butler", "CaveDwellerAI" => "Maneater", "ClaySurgeonAI" => "Barber", "DocileLocustBeesAI" => "Roaming Locust", "DoublewingAI" => "Manticoil", "FlowerSnakeEnemy" => "Tulip Snake", "JesterAI" => "Jester", "LassoManAI" => "Lasso (Unused)", "MaskedPlayerEnemy" => "Masked", "NutcrackerEnemyAI" => "Nutcracker", "PufferAI" => "Puffer", "RadMechAI" => "Old Bird", "SandSpiderAI" => "Spider", "SandWormAI" => "Earth Leviathan", "BlobAI" => "Hygrodere", "CentipedeAI" => "Snare Flea", "CrawlerAI" => "Thumper", "RedLocustBees" => "Circuit Bee", "DressGirlAI" => "Ghost Girl", "FlowermanAI" => "Bracken", "ForestGiantAI" => "Forest Keeper", "HoarderBugAI" => "Hoarding Bug", "MouthDogAI" => "Eyeless Dog", "SpringManAI" => "Coil-Head", "TestEnemy" => "Test (Unused)", "Kittenji.HerobrineMod.HerobrineAI" => "Herobrine", "LethalCompanyVileVendingMachine.VileVendingMachineServer" => "Vile Vending Machine", "BaldiEnemy.BaldiEnemy" => "Baldi", "LethalCompanyHarpGhost.HarpGhost.HarpGhostAIServer" => "Harp Ghost", "LethalCompanyHarpGhost.EnforcerGhost.EnforcerGhostAIServer" => "Enforcer Ghost", "LethalCompanyHarpGhost.BagpipesGhost.BagpipesGhostAIServer" => "Bagpipes Ghost", "ScarletMansion.KnightGhostVariant" => "Knight (Ghost)", "ScarletMansion.KnightVariant" => "Knight", "ScarletMansion.GamePatch.Enemies.KnightV2Variant" => "Knight (v2)", "ScarletMansion.GamePatch.Enemies.MaidVariant" => "Sakuya (Maid)", "ImmortalSnail.SnailAI" => "Immortal Snail", "HarbingerBehaviour.AICode.HarbingerAI" => "Harbinger", "ShyGuy.AI.ShyGuyAI" => "Shy Guy", "DontTouchMe.DTMEntityAI" => "Dont Touch Me", "Moonswept.CleanerAI" => "Cleaner", "Moonswept.MobileTurretAI" => "Mobile Turret", "LCOffice.Patches.ShrimpEnemyAI" => "Shrimp (Enemy)", "LCOffice.Patches.ShrimpAI" => "Shrimp", "SmallfryEnemy.SmallfryEnemy" => "Smallfry", "LCPeeper.PeeperAI" => "Peeper", "Menstalker_ybdkSKB.Menstalker_ybdkSKB" => "Menstalker", "Locker.MonoBehaviours.LockerAI" => "Locker", "LethalThings.RoombaAI" => "Roomba", "LethalThings.MonoBehaviours.FishFriend" => "Fish Friend", "LethalThings.MonoBehaviours.Maggie" => "Maggie", "LethalThings.MonoBehaviours.RobotAI" => "Robot", "NightmareFoxyLC.FoxyAi" => "Nightmare Foxy", "NightmareFreddy.NightmareFreddy.NightmareFreddyAi" => "Nightmare Freddy", "NightmareFreddy.Freddles.FreddlesAi" => "Freddles", "GiantSpecimens.Enemy.DriftwoodGiantAI" => "Driftwood Giant", "GiantSpecimens.Enemy.PinkGiantAI" => "Pink Giant", "GiantSpecimens.Enemy.StellarSovereignAI" => "Stellar Sovereign", _ => type.Name, }; if (1 == 0) { } return result; } internal static int GetDefaultEnemyBaseExp(Type type) { string fullName = type.FullName; if (1 == 0) { } int result = fullName switch { "BaboonBirdAI" => 30, "BushWolfEnemy" => 75, "ButlerEnemyAI" => 75, "CaveDwellerAI" => 250, "DoublewingAI" => 20, "FlowerSnakeEnemy" => 10, "MaskedPlayerEnemy" => 40, "NutcrackerEnemyAI" => 80, "SandSpiderAI" => 60, "CentipedeAI" => 30, "CrawlerAI" => 75, "FlowermanAI" => 80, "ForestGiantAI" => 200, "HoarderBugAI" => 30, "MouthDogAI" => 120, "LethalCompanyHarpGhost.HarpGhost.HarpGhostAIServer" => 60, "LethalCompanyHarpGhost.EnforcerGhost.EnforcerGhostAIServer" => 175, "LethalCompanyHarpGhost.BagpipesGhost.BagpipesGhostAIServer" => 100, "SmallfryEnemy.SmallfryEnemy" => 30, "LCPeeper.PeeperAI" => 10, "LethalThings.RoombaAI" => 50, "NightmareFreddy.Freddles.FreddlesAi" => 15, _ => 0, }; if (1 == 0) { } return result; } internal static int GetDefaultEnemyExpRange(Type type) { string fullName = type.FullName; if (1 == 0) { } int result = fullName switch { "ForestGiantAI" => 20, "LCPeeper.PeeperAI" => 1, "LethalThings.RoombaAI" => 15, "NightmareFreddy.Freddles.FreddlesAi" => 15, "SmallfryEnemy.SmallfryEnemy" => 5, _ => (GetDefaultEnemyMode(type) == EnemyExpType.AoE) ? 10 : 0, }; if (1 == 0) { } return result; } internal static EnemyExpType GetDefaultEnemyMode(Type type) { string fullName = type.FullName; if (1 == 0) { } EnemyExpType result = fullName switch { "BaboonBirdAI" => EnemyExpType.AoE, "BushWolfEnemy" => EnemyExpType.AoE, "ButlerEnemyAI" => EnemyExpType.AoE, "CaveDwellerAI" => EnemyExpType.AoE, "DoublewingAI" => EnemyExpType.Attacker, "FlowerSnakeEnemy" => EnemyExpType.Attacker, "MaskedPlayerEnemy" => EnemyExpType.AoE, "NutcrackerEnemyAI" => EnemyExpType.AoE, "SandSpiderAI" => EnemyExpType.AoE, "CentipedeAI" => EnemyExpType.AoE, "CrawlerAI" => EnemyExpType.AoE, "FlowermanAI" => EnemyExpType.AoE, "ForestGiantAI" => EnemyExpType.AoE, "HoarderBugAI" => EnemyExpType.AoE, "MouthDogAI" => EnemyExpType.AoE, "LethalCompanyHarpGhost.HarpGhost.HarpGhostAIServer" => EnemyExpType.AoE, "LethalCompanyHarpGhost.EnforcerGhost.EnforcerGhostAIServer" => EnemyExpType.AoE, "LethalCompanyHarpGhost.BagpipesGhost.BagpipesGhostAIServer" => EnemyExpType.AoE, "SmallfryEnemy.SmallfryEnemy" => EnemyExpType.AoE, "LCPeeper.PeeperAI" => EnemyExpType.AoE, "LethalThings.RoombaAI" => EnemyExpType.AoE, "NightmareFreddy.Freddles.FreddlesAi" => EnemyExpType.AoE, _ => EnemyExpType.Disabled, }; if (1 == 0) { } return result; } } internal static class Logger { private static ILogger s_logger = (ILogger)(object)Unity.Shared; public static ILogger Source { get { return s_logger; } [param: AllowNull] set { s_logger = (ILogger)(((object)value) ?? ((object)Unity.Shared)); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Debug(object message) { Source.Debug(message); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Info(object message) { Source.Info(message); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Warning(object message) { Source.Warning(message); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Error(object message) { Source.Error(message); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Fatal(object message) { Source.Fatal(message); } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("CookieProgression", "CookieProgression", "0.1.2")] public sealed class Plugin : BaseUnityPlugin, ICookieDependency { private static AssetBundle? s_menuBundle; public static AssetBundle MenuBundle => s_menuBundle ?? throw new InvalidOperationException("Use before initialize."); bool ICookieDependency.TrackOtherClients => false; private void Awake() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) Logger.Source = (ILogger)new BepInLoggerSource(((BaseUnityPlugin)this).Logger); using Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream("CookieProgression.res.skillmenu") ?? throw new InvalidOperationException("Embedded resource returned null."); s_menuBundle = AssetBundle.LoadFromStream(stream); new Harmony("CookieProgression").PatchAll(typeof(Plugin).Assembly); PluginUtils.Register((ICookieDependency)(object)this); Config.Setup(((BaseUnityPlugin)this).Config); SkillManager.Bootstrap(); for (int i = 1; i <= 20; i++) { int experience = ExperienceGroups.Lethal.GetExperience(i); int level = ExperienceGroups.Lethal.GetLevel(experience); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Lvl. {level} = {experience}"); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"CookieProgression v0.1.2 loaded."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Icon, Ideas and Game Balance by Kaede"); GameClient.OnShutdown += delegate { SkillMenu.OnDestroy(); }; } void ICookieDependency.OnPlayerTracked(AbstractPlayer player) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Started tracking {player}"); player.Attach(new SkillManager(player)); } } internal static class PluginInfo { public const string Guid = "CookieProgression"; public const string Name = "CookieProgression"; public const string Version = "0.1.2"; } } namespace CookieProgression.UI { [HarmonyPatch] [HarmonyWrapSafe] public sealed class SkillMenu { internal static bool IsMenuOpen; internal static SkillMenu? Instance; private readonly GameObject _mainPanel; private readonly GameObject _infoPanel; private readonly List _skillButtons = new List(); public SkillManager Manager { get; } internal static void OnInitialize(SkillManager client) { if (IsMenuOpen) { try { Instance?.OnBackButton(); } catch { } IsMenuOpen = false; } Instance = new SkillMenu(client); } internal static void OnDestroy() { if (Instance != null && IsMenuOpen) { try { Instance.OnBackButton(); } catch { } IsMenuOpen = false; } Instance = null; } public void OpenSkillMenu() { if (!Object.op_Implicit((Object)(object)_mainPanel)) { OnDestroy(); return; } IsMenuOpen = true; _mainPanel.SetActive(true); } private SkillMenu(SkillManager manager) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00c7: Expected O, but got Unknown //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown Guard.NotNull(manager, "manager"); Guard.IsTrue(manager.Player.IsClient, (string)null, "manager.Player.IsClient"); Manager = manager; _mainPanel = Object.Instantiate(Plugin.MenuBundle.LoadAsset("SkillMenu")); ((Object)_mainPanel).name = "SkillMenu"; _mainPanel.SetActive(false); _infoPanel = ((Component)_mainPanel.transform.GetChild(1)).gameObject; _infoPanel.SetActive(false); GameObject gameObject = ((Component)_mainPanel.transform.GetChild(4)).gameObject; Button component = gameObject.GetComponent