Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of AeresProfessions v0.1.0
AeresProfessions.dll
Decompiled 3 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("AeresProfessions")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0")] [assembly: AssemblyProduct("AeresProfessions")] [assembly: AssemblyTitle("AeresProfessions")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 ValheimProfessions { internal static class Crafting { private enum Mode { None, Crafting, Building } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] private static class DoCraftingPatch { private static void Prefix(InventoryGui __instance, Player player) { _mode = Mode.Crafting; CraftingStation val = (((Object)(object)player != (Object)null) ? player.GetCurrentCraftingStation() : null); _station = (((Object)(object)val != (Object)null) ? val.m_name.ToLowerInvariant() : ""); Recipe craftRecipe = __instance.m_craftRecipe; _craftsFood = (Object)(object)craftRecipe != (Object)null && (Object)(object)craftRecipe.m_item != (Object)null && IsFood(craftRecipe.m_item.m_itemData.m_shared); } private static Exception Finalizer(Exception __exception) { _mode = Mode.None; return __exception; } } [HarmonyPatch(typeof(Player), "UpdatePlacement")] private static class UpdatePlacementPatch { private static void Prefix() { if (_mode == Mode.None) { _mode = Mode.Building; } } private static Exception Finalizer(Exception __exception) { if (_mode == Mode.Building) { _mode = Mode.None; } return __exception; } } [HarmonyPatch(typeof(Player), "ConsumeResources")] private static class ConsumeResourcesPatch { private static void Postfix(Player __instance, Requirement[] requirements, int qualityLevel, int multiplier) { if (_mode == Mode.None || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || __instance.NoCostCheat()) { return; } ProfessionType? professionType = Resolve(requirements); if (!professionType.HasValue) { return; } int num = 0; Requirement[] array = requirements; foreach (Requirement val in array) { if ((Object)(object)val.m_resItem != (Object)null) { num += val.GetAmount(qualityLevel) * multiplier; } } ProfessionManager.AddXp(__instance, professionType.Value, (float)num * 1.5f); if (!ProfessionInfo.SavesMaterials(professionType.Value) || Random.value >= ProfessionManager.UtilityBonus(__instance, professionType.Value)) { return; } Inventory inventory = ((Humanoid)__instance).GetInventory(); array = requirements; foreach (Requirement val2 in array) { if (!((Object)(object)val2.m_resItem == (Object)null)) { int num2 = val2.GetAmount(qualityLevel) * multiplier; if (num2 > 0) { inventory.AddItem(((Component)val2.m_resItem).gameObject, num2); } } } ((Character)__instance).Message((MessageType)1, "Materials saved!", 0, (Sprite)null, false); } } private static Mode _mode; private static string _station = ""; private static bool _craftsFood; private static readonly string[] StoneItems = new string[3] { "Stone", "BlackMarble", "Grausten" }; private static bool IsFood(SharedData shared) { if (shared != null) { if (!(shared.m_food > 0f) && !(shared.m_foodStamina > 0f)) { return shared.m_foodEitr > 0f; } return true; } return false; } private static ProfessionType? Resolve(Requirement[] requirements) { if (_mode == Mode.Crafting) { if (_craftsFood) { return ProfessionType.TavernKeeper; } if (_station.Contains("forge")) { return ProfessionType.Blacksmith; } if (_station.Contains("cauldron") || _station.Contains("mead")) { return ProfessionType.Alchemist; } if (_station.Contains("stonecutter")) { return ProfessionType.Mason; } } else if (_mode == Mode.Building) { foreach (Requirement val in requirements) { if (!((Object)(object)val.m_resItem == (Object)null) && Array.IndexOf(StoneItems, ((Object)val.m_resItem).name) >= 0) { return ProfessionType.Mason; } } } return null; } } internal static class Patches { [HarmonyPatch(typeof(MineRock5), "Damage")] private static class MineRock5Patch { private static void Prefix(HitData hit) { Player val = LocalAttacker(hit); if (!((Object)(object)val == (Object)null) && !(hit.m_damage.m_pickaxe <= 0f)) { hit.m_damage.m_pickaxe *= ProfessionManager.PerkMultiplier(val, ProfessionType.Miner); Apply(hit, ProfessionType.Miner, hit.m_damage.m_pickaxe); } } } [HarmonyPatch(typeof(MineRock), "Damage")] private static class MineRockPatch { private static void Prefix(HitData hit) { Player val = LocalAttacker(hit); if (!((Object)(object)val == (Object)null) && !(hit.m_damage.m_pickaxe <= 0f)) { hit.m_damage.m_pickaxe *= ProfessionManager.PerkMultiplier(val, ProfessionType.Miner); Apply(hit, ProfessionType.Miner, hit.m_damage.m_pickaxe); } } } [HarmonyPatch(typeof(TreeBase), "Damage")] private static class TreeBasePatch { private static void Prefix(HitData hit) { Player val = LocalAttacker(hit); if (!((Object)(object)val == (Object)null) && !(hit.m_damage.m_chop <= 0f)) { hit.m_damage.m_chop *= ProfessionManager.PerkMultiplier(val, ProfessionType.Woodcutter); Apply(hit, ProfessionType.Woodcutter, hit.m_damage.m_chop); } } } [HarmonyPatch(typeof(TreeLog), "Damage")] private static class TreeLogPatch { private static void Prefix(HitData hit) { Player val = LocalAttacker(hit); if (!((Object)(object)val == (Object)null) && !(hit.m_damage.m_chop <= 0f)) { hit.m_damage.m_chop *= ProfessionManager.PerkMultiplier(val, ProfessionType.Woodcutter); Apply(hit, ProfessionType.Woodcutter, hit.m_damage.m_chop); } } } [HarmonyPatch(typeof(Character), "Damage")] private static class CharacterDamagePatch { private static void Prefix(Character __instance, HitData hit) { if (__instance is Player) { return; } Player val = LocalAttacker(hit); if (!((Object)(object)val == (Object)null)) { float num = ProfessionManager.PerkMultiplier(val, ProfessionType.Hunter); if (num != 1f) { hit.ApplyModifier(num); } Apply(hit, ProfessionType.Hunter, hit.GetTotalDamage()); } } } [HarmonyPatch(typeof(Pickable), "Interact")] private static class PickableInteractPatch { private static void Prefix(Pickable __instance, Humanoid character, out bool __state) { __state = (Object)(object)character == (Object)(object)Player.m_localPlayer && !__instance.m_picked && __instance.m_enabled != 0 && (Object)(object)__instance.m_itemPrefab != (Object)null && Harvestables.Contains(((Object)__instance.m_itemPrefab).name); if (__state && IsRepeat(((Object)__instance).GetInstanceID())) { __state = false; } } private static void Postfix(Pickable __instance, bool __state) { if (__state) { Player localPlayer = Player.m_localPlayer; ProfessionManager.AddXp(localPlayer, ProfessionType.Farmer, 4f); if (Random.value < ProfessionManager.UtilityBonus(localPlayer, ProfessionType.Farmer)) { ((Humanoid)localPlayer).GetInventory().AddItem(__instance.m_itemPrefab, __instance.m_amount); ((Character)localPlayer).Message((MessageType)1, "Double harvest!", 0, (Sprite)null, false); } } } } [HarmonyPatch(typeof(Player), "PlacePiece")] private static class PlantingPatch { private static void Postfix(Player __instance, Piece piece, bool cheated) { if (!cheated && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && (Object)(object)piece != (Object)null && (Object)(object)((Component)piece).GetComponent<Plant>() != (Object)null) { ProfessionManager.AddXp(__instance, ProfessionType.Farmer, 3f); } } } [HarmonyPatch(typeof(CookingStation), "OnInteract")] private static class CookingCollectPatch { private static void Prefix(CookingStation __instance, Humanoid user, out bool __state) { __state = (Object)(object)user == (Object)(object)Player.m_localPlayer && __instance.HaveDoneItem() && !IsRepeat(((Object)__instance).GetInstanceID()); } private static void Postfix(bool __state) { if (__state) { ProfessionManager.AddXp(Player.m_localPlayer, ProfessionType.TavernKeeper, 8f); } } } [HarmonyPatch(typeof(Player), "EatFood")] private static class EatFoodPatch { private static void Postfix(Player __instance, ItemData item, bool __result) { if (!__result || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } float num = ProfessionManager.UtilityBonus(__instance, ProfessionType.TavernKeeper); if (num <= 0f) { return; } foreach (Food food in __instance.GetFoods()) { if (food.m_item.m_shared.m_name == item.m_shared.m_name) { food.m_time = item.m_shared.m_foodBurnTime * (1f + num); } } } } [HarmonyPatch(typeof(Ship), "CustomFixedUpdate")] private static class ShipXpPatch { private static void Postfix(Ship __instance, float fixedDeltaTime) { if (!IsControlledByLocalPlayer(__instance)) { return; } _sailTimer += fixedDeltaTime; if (!(_sailTimer < 1f)) { _sailTimer -= 1f; float num = Mathf.Abs(__instance.GetSpeed()); if (!(num < 1f)) { ProfessionManager.AddXp(Player.m_localPlayer, ProfessionType.Mariner, num * 0.5f); } } } } [HarmonyPatch(typeof(FishingFloat), "Catch")] private static class FishingCatchPatch { private static void Postfix(Fish fish, Character owner) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)owner != (Object)(object)localPlayer)) { ItemDrop val = (((Object)(object)fish != (Object)null) ? ((Component)fish).GetComponent<ItemDrop>() : null); int num = ((!((Object)(object)val != (Object)null)) ? 1 : val.m_itemData.m_quality); ProfessionManager.AddXp(localPlayer, ProfessionType.Mariner, 12f + 4f * (float)num); } } } [HarmonyPatch(typeof(Ship), "GetSailForce")] private static class SailForcePatch { private static void Postfix(Ship __instance, ref Vector3 __result) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (IsControlledByLocalPlayer(__instance)) { float num = ProfessionManager.UtilityBonus(Player.m_localPlayer, ProfessionType.Mariner); if (num > 0f) { __result *= 1f + num; } } } } private static readonly HashSet<string> Harvestables = new HashSet<string> { "Carrot", "CarrotSeeds", "Turnip", "TurnipSeeds", "Onion", "OnionSeeds", "Barley", "Flax", "Raspberry", "Blueberries", "Cloudberry", "Mushroom", "MushroomYellow", "MushroomBlue", "MushroomJotunPuffs", "MushroomMagecap", "Dandelion", "Thistle" }; private static int _lastTouchedId; private static float _lastTouchedAt; private static float _sailTimer; private static Player LocalAttacker(HitData hit) { Character obj = ((hit != null) ? hit.GetAttacker() : null); Player val = (Player)(object)((obj is Player) ? obj : null); if (!((Object)(object)val != (Object)null) || !((Object)(object)val == (Object)(object)Player.m_localPlayer)) { return null; } return val; } private static void Apply(HitData hit, ProfessionType type, float baseDamage) { Player val = LocalAttacker(hit); if (!((Object)(object)val == (Object)null)) { ProfessionManager.AddXp(val, type, baseDamage * 0.1f); } } private static bool IsRepeat(int instanceId) { if (instanceId == _lastTouchedId && Time.time - _lastTouchedAt < 0.75f) { return true; } _lastTouchedId = instanceId; _lastTouchedAt = Time.time; return false; } private static bool IsControlledByLocalPlayer(Ship ship) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { return (Object)(object)localPlayer.GetControlledShip() == (Object)(object)ship; } return false; } } [BepInPlugin("com.danle.professions", "Professions", "0.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.danle.professions"; public const string PluginName = "Professions"; public const string PluginVersion = "0.1.0"; public static ConfigEntry<int> MaxLevel; public static ConfigEntry<float> BaseXp; public static ConfigEntry<float> XpMultiplier; public static ConfigEntry<float> PerkPercentPerLevel; public static ConfigEntry<float> UtilityPercentPerLevel; public static ConfigEntry<bool> AllowSwitching; public static ConfigEntry<KeyboardShortcut> MenuKey; public static ConfigEntry<bool> ShowHint; private void Awake() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) MenuKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Menu", "OpenKey", new KeyboardShortcut((KeyCode)107, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Opens and closes the professions menu. Supports modifiers, e.g. LeftAlt + K. Change it if it conflicts with another mod."); ShowHint = ((BaseUnityPlugin)this).Config.Bind<bool>("Menu", "ShowHint", true, "Show a one-time reminder of the menu key after spawning while no profession is chosen."); MaxLevel = SyncedConfig("Progression", "MaxLevel", 50, "Highest reachable profession level."); BaseXp = SyncedConfig("Progression", "BaseXp", 60f, "Scales the XP curve. Higher = slower leveling."); XpMultiplier = SyncedConfig("Progression", "XpMultiplier", 1f, "Multiplier applied to all XP gained."); PerkPercentPerLevel = SyncedConfig("Perks", "PercentPerLevel", 1f, "Damage bonus (percent) gained per level above 1 (Miner, Woodcutter, Hunter)."); UtilityPercentPerLevel = SyncedConfig("Perks", "UtilityPercentPerLevel", 0.5f, "Chance or speed bonus (percent) gained per level above 1 (Farmer, Blacksmith, Alchemist, Mason, Mariner)."); AllowSwitching = SyncedConfig("Rules", "AllowSwitching", value: true, "Whether players may change profession after choosing one."); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new ProfessionCommand()); ((Component)this).gameObject.AddComponent<ProfessionMenu>(); new Harmony("com.danle.professions").PatchAll(); } private ConfigEntry<T> SyncedConfig<T>(string section, string key, T value, string description) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown return ((BaseUnityPlugin)this).Config.Bind<T>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); } } public class ProfessionCommand : ConsoleCommand { public override string Name => "profession"; public override string Help => "profession [choose <" + string.Join("|", Enum.GetNames(typeof(ProfessionType))).ToLowerInvariant() + ">] - show or choose your profession"; public override void Run(string[] args) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { Console.instance.Print("Load into a world first."); return; } if (args.Length >= 2 && args[0].ToLowerInvariant() == "choose") { if (!Enum.TryParse<ProfessionType>(args[1], ignoreCase: true, out var result)) { Console.instance.Print("Unknown profession '" + args[1] + "'."); return; } if (!ProfessionManager.TryChoose(localPlayer, result, out var error)) { Console.instance.Print(error); return; } } Console.instance.Print(ProfessionManager.Describe(localPlayer)); } public override List<string> CommandOptionList() { return new List<string> { "choose" }; } } public static class ProfessionManager { private const string ActiveKey = "Professions.Active"; private const string XpKeyPrefix = "Professions.XP."; public static ProfessionType? GetActive(Player player) { if ((Object)(object)player == (Object)null) { return null; } if (player.m_customData.TryGetValue("Professions.Active", out var value) && Enum.TryParse<ProfessionType>(value, out var result)) { return result; } return null; } public static bool TryChoose(Player player, ProfessionType type, out string error) { error = null; ProfessionType? active = GetActive(player); if (active == type) { error = $"You are already a {type}."; return false; } if (active.HasValue && !Plugin.AllowSwitching.Value) { error = $"You are already a {active}; switching is disabled on this server."; return false; } player.m_customData["Professions.Active"] = type.ToString(); return true; } public static long GetXp(Player player, ProfessionType type) { if (player.m_customData.TryGetValue("Professions.XP." + type, out var value) && long.TryParse(value, out var result)) { return result; } return 0L; } public static long XpForLevel(int level) { if (level <= 1) { return 0L; } return (long)((double)Plugin.BaseXp.Value * Math.Pow(level - 1, 1.6)); } public static int GetLevel(Player player, ProfessionType type) { long xp = GetXp(player, type); int i; for (i = 1; i < Plugin.MaxLevel.Value && xp >= XpForLevel(i + 1); i++) { } return i; } public static void AddXp(Player player, ProfessionType type, float amount) { if (!((Object)(object)player == (Object)null) && !(amount <= 0f) && GetActive(player) == type) { int level = GetLevel(player, type); long num = Math.Max(1L, (long)Math.Round(amount * Plugin.XpMultiplier.Value)); player.m_customData["Professions.XP." + type] = (GetXp(player, type) + num).ToString(); int level2 = GetLevel(player, type); if (level2 > level) { ((Character)player).Message((MessageType)2, $"{ProfessionInfo.DisplayName(type)} level {level2}!", 0, (Sprite)null, false); } } } public static float PerkMultiplier(Player player, ProfessionType type) { if (GetActive(player) != type) { return 1f; } int level = GetLevel(player, type); return 1f + (float)(level - 1) * Plugin.PerkPercentPerLevel.Value / 100f; } public static float UtilityBonus(Player player, ProfessionType type) { if (GetActive(player) != type) { return 0f; } return (float)(GetLevel(player, type) - 1) * Plugin.UtilityPercentPerLevel.Value / 100f; } public static float BonusPercent(Player player, ProfessionType type) { float num = (ProfessionInfo.IsDamagePerk(type) ? Plugin.PerkPercentPerLevel.Value : Plugin.UtilityPercentPerLevel.Value); return (float)(GetLevel(player, type) - 1) * num; } public static bool CanChoose(Player player, ProfessionType type) { ProfessionType? active = GetActive(player); if (active != type) { if (active.HasValue) { return Plugin.AllowSwitching.Value; } return true; } return false; } public static string Describe(Player player) { ProfessionType? active = GetActive(player); if (!active.HasValue) { string text = string.Join("|", Enum.GetNames(typeof(ProfessionType))).ToLowerInvariant(); return "No profession chosen. Use: profession choose <" + text + ">"; } ProfessionType value = active.Value; int level = GetLevel(player, value); long xp = GetXp(player, value); string text2 = ((level >= Plugin.MaxLevel.Value) ? "max level" : $"{XpForLevel(level + 1) - xp} XP to next"); string text3 = BonusPercent(player, value).ToString("0.#"); return $"{ProfessionInfo.DisplayName(value)} level {level} ({xp} XP, {text2}): +{text3}% {ProfessionInfo.Perk(value)}"; } } public class ProfessionMenu : MonoBehaviour { private static class Styles { public static GUIStyle Panel; public static GUIStyle Title; public static GUIStyle Subtitle; public static GUIStyle Warning; public static GUIStyle Message; public static GUIStyle Row; public static GUIStyle RowActive; public static GUIStyle Name; public static GUIStyle Level; public static GUIStyle ActiveTag; public static GUIStyle Small; public static GUIStyle Perk; public static GUIStyle Button; public static Texture2D BarBack; public static Texture2D BarFill; private static Texture2D _panelTex; private static readonly Color Gold = new Color(0.96f, 0.76f, 0.3f); private static readonly Color Text = new Color(0.93f, 0.9f, 0.84f); private static readonly Color Muted = new Color(0.68f, 0.64f, 0.58f); private static Texture2D Tex(Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown Texture2D val = new Texture2D(1, 1); val.SetPixel(0, 0, color); val.Apply(); ((Object)val).hideFlags = (HideFlags)61; return val; } public static void Ensure() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Expected O, but got Unknown //IL_012c: Expected O, but got Unknown //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Expected O, but got Unknown //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Expected O, but got Unknown //IL_02b6: Expected O, but got Unknown //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Expected O, but got Unknown //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: 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_0304: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Expected O, but got Unknown //IL_0326: Expected O, but got Unknown //IL_03ad: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_panelTex != (Object)null) || Panel == null) { _panelTex = Tex(new Color(0.07f, 0.06f, 0.05f, 0.97f)); BarBack = Tex(new Color(0.2f, 0.18f, 0.15f)); BarFill = Tex(Gold); Texture2D background = Tex(new Color(0.15f, 0.13f, 0.11f, 0.95f)); Texture2D background2 = Tex(new Color(0.27f, 0.2f, 0.08f, 0.97f)); Texture2D background3 = Tex(new Color(0.3f, 0.23f, 0.1f)); Texture2D background4 = Tex(new Color(0.45f, 0.33f, 0.12f)); Texture2D background5 = Tex(new Color(0.6f, 0.44f, 0.15f)); RectOffset border = new RectOffset(0, 0, 0, 0); Panel = new GUIStyle(GUI.skin.window) { border = border, padding = new RectOffset(18, 18, 16, 16) }; GUIStyleState[] array = (GUIStyleState[])(object)new GUIStyleState[8] { Panel.normal, Panel.onNormal, Panel.hover, Panel.onHover, Panel.active, Panel.onActive, Panel.focused, Panel.onFocused }; for (int i = 0; i < array.Length; i++) { array[i].background = _panelTex; } Title = Label(26, (FontStyle)1, Gold); Subtitle = Label(14, (FontStyle)0, Text); Warning = Label(13, (FontStyle)2, new Color(0.95f, 0.55f, 0.4f)); Message = Label(14, (FontStyle)1, Gold); Name = Label(18, (FontStyle)1, Text); Level = Label(16, (FontStyle)1, Gold); ActiveTag = Label(13, (FontStyle)1, Gold); ActiveTag.alignment = (TextAnchor)4; Small = Label(13, (FontStyle)0, Muted); Perk = Label(13, (FontStyle)0, Text); Row = new GUIStyle(GUI.skin.box) { border = border, padding = new RectOffset(12, 12, 8, 8), margin = new RectOffset(0, 6, 0, 6) }; Row.normal.background = background; RowActive = new GUIStyle(Row); RowActive.normal.background = background2; Button = new GUIStyle(GUI.skin.button) { border = border, fontSize = 14, fontStyle = (FontStyle)1, alignment = (TextAnchor)4, padding = new RectOffset(8, 8, 6, 6) }; Button.normal.background = background3; Button.hover.background = background4; Button.active.background = background5; Button.focused.background = background3; array = (GUIStyleState[])(object)new GUIStyleState[4] { Button.normal, Button.hover, Button.active, Button.focused }; for (int i = 0; i < array.Length; i++) { array[i].textColor = Text; } } } private static GUIStyle Label(int size, FontStyle fontStyle, Color color) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_0031: Expected O, but got Unknown GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = size, fontStyle = fontStyle, wordWrap = true }; val.normal.textColor = color; return val; } } private static readonly int WindowId = "com.danle.professions".GetHashCode(); private const float WindowWidth = 580f; private const float MaxWindowHeight = 680f; private bool _visible; private bool _blocking; private Rect _window; private Vector2 _scroll; private string _message = ""; private float _spawnedAt = -1f; private bool _hintShown; private void Update() { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { if (_visible) { Close(); } _spawnedAt = -1f; _hintShown = false; return; } if (_spawnedAt < 0f) { _spawnedAt = Time.time; } if (!_hintShown && Time.time - _spawnedAt > 6f) { _hintShown = true; if (Plugin.ShowHint.Value && !ProfessionManager.GetActive(localPlayer).HasValue) { ((Character)localPlayer).Message((MessageType)2, "Press " + KeyLabel() + " to choose a profession", 0, (Sprite)null, false); } } KeyboardShortcut value = Plugin.MenuKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { if (_visible) { Close(); } else if (CanOpen()) { Open(); } } else if (_visible && (Input.GetKeyDown((KeyCode)27) || ((Character)localPlayer).IsDead())) { Close(); } } private void OnDestroy() { if (_blocking) { _blocking = false; GUIManager.BlockInput(false); } } private static bool CanOpen() { if (!Console.IsVisible() && (!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !TextInput.IsVisible() && !Menu.IsVisible() && !InventoryGui.IsVisible() && !Minimap.IsOpen() && !StoreGui.IsVisible() && (!((Object)(object)TextViewer.instance != (Object)null) || !TextViewer.instance.IsVisible())) { return !Hud.IsPieceSelectionVisible(); } return false; } private void Open() { _visible = true; _message = ""; if (!_blocking) { _blocking = true; GUIManager.BlockInput(true); } } private void Close() { _visible = false; if (_blocking) { _blocking = false; ((MonoBehaviour)this).StartCoroutine(ReleaseNextFrame()); } } private static IEnumerator ReleaseNextFrame() { yield return null; GUIManager.BlockInput(false); } private static string KeyLabel() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = Plugin.MenuKey.Value; List<string> list = new List<string>(); foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers) { list.Add(((object)modifier/*cast due to .constrained prefix*/).ToString()); } list.Add(((object)((KeyboardShortcut)(ref value)).MainKey/*cast due to .constrained prefix*/).ToString()); return string.Join(" + ", list); } private void OnGUI() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Expected O, but got Unknown //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) Player player = Player.m_localPlayer; if (_visible && !((Object)(object)player == (Object)null)) { Styles.Ensure(); float num = Mathf.Clamp((float)Screen.height / 1080f, 0.75f, 2.5f); Matrix4x4 matrix = GUI.matrix; GUI.matrix = Matrix4x4.Scale(new Vector3(num, num, 1f)); float num2 = (float)Screen.width / num; float num3 = (float)Screen.height / num; float num4 = Mathf.Min(680f, num3 - 40f); if (((Rect)(ref _window)).width < 1f) { _window = new Rect((num2 - 580f) / 2f, (num3 - num4) / 2f, 580f, num4); } ((Rect)(ref _window)).height = num4; ((Rect)(ref _window)).x = Mathf.Clamp(((Rect)(ref _window)).x, 0f, Mathf.Max(0f, num2 - 580f)); ((Rect)(ref _window)).y = Mathf.Clamp(((Rect)(ref _window)).y, 0f, Mathf.Max(0f, num3 - num4)); _window = GUI.Window(WindowId, _window, (WindowFunction)delegate { DrawWindow(player); }, GUIContent.none, Styles.Panel); GUI.matrix = matrix; } } private void DrawWindow(Player player) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) GUILayout.Label("Professions", Styles.Title, Array.Empty<GUILayoutOption>()); ProfessionType? active = ProfessionManager.GetActive(player); GUILayout.Label((!active.HasValue) ? "Choose a profession. Only your active one earns XP and gives its perk." : ("Active: " + ProfessionInfo.DisplayName(active.Value) + ". Other professions keep their XP while you're away."), Styles.Subtitle, Array.Empty<GUILayoutOption>()); if (!Plugin.AllowSwitching.Value && active.HasValue) { GUILayout.Label("Switching professions is disabled on this server.", Styles.Warning, Array.Empty<GUILayoutOption>()); } GUILayout.Space(6f); _scroll = GUILayout.BeginScrollView(_scroll, false, false, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) }); ProfessionType[] array = (ProfessionType[])Enum.GetValues(typeof(ProfessionType)); foreach (ProfessionType professionType in array) { DrawRow(player, professionType, active == professionType); } GUILayout.EndScrollView(); if (_message.Length > 0) { GUILayout.Space(4f); GUILayout.Label(_message, Styles.Message, Array.Empty<GUILayoutOption>()); } GUILayout.Space(6f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(KeyLabel() + " or Esc to close", Styles.Small, Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); if (GUILayout.Button("Close", Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) })) { Close(); } GUILayout.EndHorizontal(); GUI.DragWindow(new Rect(0f, 0f, 10000f, 44f)); } private void DrawRow(Player player, ProfessionType type, bool isActive) { //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Invalid comparison between Unknown and I4 //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) int level = ProfessionManager.GetLevel(player, type); long xp = ProfessionManager.GetXp(player, type); bool flag = level >= Plugin.MaxLevel.Value; long num = ProfessionManager.XpForLevel(level); long num2 = ProfessionManager.XpForLevel(level + 1); float num3 = ((flag || num2 <= num) ? 1f : Mathf.Clamp01((float)(xp - num) / (float)(num2 - num))); GUILayout.BeginVertical(isActive ? Styles.RowActive : Styles.Row, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(ProfessionInfo.DisplayName(type), Styles.Name, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) }); GUILayout.Label($"Lv {level}", Styles.Level, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }); GUILayout.FlexibleSpace(); if (isActive) { GUILayout.Label("ACTIVE", Styles.ActiveTag, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) }); } else { bool enabled = GUI.enabled; GUI.enabled = ProfessionManager.CanChoose(player, type); if (GUILayout.Button("Choose", Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) })) { Choose(player, type); } GUI.enabled = enabled; } GUILayout.EndHorizontal(); GUILayout.Label(ProfessionInfo.Summary(type), Styles.Small, Array.Empty<GUILayoutOption>()); GUILayout.Label($"Perk: +{ProfessionManager.BonusPercent(player, type):0.#}% {ProfessionInfo.Perk(type)}", Styles.Perk, Array.Empty<GUILayoutOption>()); Rect rect = GUILayoutUtility.GetRect(1f, 8f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); if ((int)Event.current.type == 7) { GUI.DrawTexture(rect, (Texture)(object)Styles.BarBack); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width * num3, ((Rect)(ref rect)).height), (Texture)(object)Styles.BarFill); } GUILayout.Label(flag ? $"{xp} XP (max level)" : $"{xp} / {num2} XP", Styles.Small, Array.Empty<GUILayoutOption>()); GUILayout.EndVertical(); } private void Choose(Player player, ProfessionType type) { if (ProfessionManager.TryChoose(player, type, out var error)) { _message = "You are now a " + ProfessionInfo.DisplayName(type) + "."; ((Character)player).Message((MessageType)1, _message, 0, (Sprite)null, false); } else { _message = error; } } } public enum ProfessionType { Miner, Woodcutter, Hunter, Farmer, Blacksmith, Alchemist, Mason, Mariner, TavernKeeper } public static class ProfessionInfo { public static bool IsDamagePerk(ProfessionType type) { if (type != ProfessionType.Miner && type != ProfessionType.Woodcutter) { return type == ProfessionType.Hunter; } return true; } public static bool SavesMaterials(ProfessionType type) { if (type != ProfessionType.Blacksmith && type != ProfessionType.Alchemist) { return type == ProfessionType.Mason; } return true; } public static string DisplayName(ProfessionType type) { if (type != ProfessionType.TavernKeeper) { return type.ToString(); } return "Tavern Keeper"; } public static string Summary(ProfessionType type) { return type switch { ProfessionType.Miner => "Mining rock and ore with a pickaxe", ProfessionType.Woodcutter => "Chopping trees and logs", ProfessionType.Hunter => "Fighting creatures and monsters", ProfessionType.Farmer => "Harvesting crops and forage, and planting", ProfessionType.Blacksmith => "Crafting and upgrading at forges", ProfessionType.Alchemist => "Brewing meads and potions", ProfessionType.Mason => "Stonework: stone building and the stonecutter", ProfessionType.Mariner => "Sailing ships and fishing", ProfessionType.TavernKeeper => "Cooking: crafting food and using cooking stations", _ => "", }; } public static string Perk(ProfessionType type) { return type switch { ProfessionType.Miner => "pickaxe damage", ProfessionType.Woodcutter => "axe chop damage", ProfessionType.Hunter => "damage against creatures", ProfessionType.Farmer => "chance of a double harvest", ProfessionType.Blacksmith => "chance to save materials at forges", ProfessionType.Alchemist => "chance to save materials when brewing meads and potions", ProfessionType.Mason => "chance to save materials on stone building and stonecutting", ProfessionType.Mariner => "sail speed", ProfessionType.TavernKeeper => "longer-lasting food", _ => "", }; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }