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 VargheimProfessionPack v1.0.1
VargheimProfessionPack.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using Splatform; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; using VargheimProfessions; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] [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 VargheimWeaponsmithing { [BepInPlugin("digi.vargheim.weaponsmithing", "VargheimWeaponsmithing", "1.0.0")] [BepInDependency("digi.vargheim.professions", "0.4.0")] public class Plugin : BaseUnityPlugin { internal sealed class Craft { public string Name; public HashSet<ItemData> Before; } [HarmonyPatch] internal static class Patches { [HarmonyPatch(typeof(Humanoid), "UseItem")] [HarmonyPrefix] private static bool UseItem(Humanoid __instance, Inventory inventory, ItemData item) { if (item == null || (Object)(object)item.m_dropPrefab == (Object)null || ((Object)item.m_dropPrefab).name != "VP_Whetstone" || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } try { Sharpened.m_ttl = StoneMinutes.Value * 60f; ((Character)__instance).GetSEMan().AddStatusEffect(Sharpened, true, 0, 0f, (short)0); (inventory ?? __instance.GetInventory()).RemoveItem(item, 1); Api.Note("Your weapons are sharpened."); } catch (Exception ex) { Debug.LogWarning((object)("VargheimWeaponsmithing: " + ex.Message)); } return false; } [HarmonyPatch(typeof(SEMan), "ModifyAttack")] [HarmonyPostfix] private static void ModifyAttack(SEMan __instance, ref HitData hitData) { try { float num = 1f; if (__instance.HaveStatusEffect(Sharpened.NameHash())) { num += StoneBonus.Value; } Character value = Traverse.Create((object)__instance).Field("m_character").GetValue<Character>(); Humanoid val = (Humanoid)(object)((value is Humanoid) ? value : null); if (Tag(((Object)(object)val != (Object)null) ? val.GetCurrentWeapon() : null, "vp_masterwork") != null) { num += MasterBonus.Value; } if (num != 1f) { ((DamageTypes)(ref hitData.m_damage)).Modify(num); } } catch { } } [HarmonyPatch(typeof(Attack), "GetAttackStamina")] [HarmonyPostfix] private static void Stamina(Attack __instance, ref float __result) { try { if (Tag(Traverse.Create((object)__instance).Field("m_weapon").GetValue<ItemData>(), "vp_balanced") != null) { __result *= 1f - BalanceCut.Value; } } catch { } } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] [HarmonyPrefix] private static void CraftPre(InventoryGui __instance, Player player, out Craft __state) { __state = null; try { Recipe value = Traverse.Create((object)__instance).Field("m_craftRecipe").GetValue<Recipe>(); ItemData value2 = Traverse.Create((object)__instance).Field("m_craftUpgradeItem").GetValue<ItemData>(); if (!((Object)(object)value == (Object)null) && !((Object)(object)value.m_item == (Object)null) && value2 == null && !((Object)(object)player != (Object)(object)Player.m_localPlayer) && IsWeapon(value.m_item.m_itemData) && value.m_item.m_itemData.m_shared.m_maxStackSize <= 1) { __state = new Craft { Name = value.m_item.m_itemData.m_shared.m_name, Before = new HashSet<ItemData>(((Humanoid)player).GetInventory().GetAllItems()) }; } } catch { } } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] [HarmonyPostfix] private static void CraftPost(Player player, Craft __state) { if (__state == null || (Object)(object)player == (Object)null) { return; } try { bool flag = Api.HasPerk("Weaponsmithing", BalanceLevel.Value); bool flag2 = Api.HasPerk("Weaponsmithing", MasterLevel.Value); if (!flag && !flag2) { return; } foreach (ItemData allItem in ((Humanoid)player).GetInventory().GetAllItems()) { if (allItem != null && !__state.Before.Contains(allItem) && !(allItem.m_shared.m_name != __state.Name)) { if (flag) { allItem.m_customData["vp_balanced"] = "1"; } if (flag2) { allItem.m_customData["vp_masterwork"] = player.GetPlayerName(); } } } } catch { } } } public const string Guid = "digi.vargheim.weaponsmithing"; public const string Version = "1.0.0"; private const string Prof = "Weaponsmithing"; internal const string Stone = "VP_Whetstone"; internal static ConfigEntry<int> StoneLevel; internal static ConfigEntry<int> BalanceLevel; internal static ConfigEntry<int> FieldLevel; internal static ConfigEntry<int> MasterLevel; internal static ConfigEntry<float> StoneBonus; internal static ConfigEntry<float> StoneMinutes; internal static ConfigEntry<float> BalanceCut; internal static ConfigEntry<float> MasterBonus; internal static ConfigEntry<string> StoneRecipe; internal static StatusEffect Sharpened; private void Awake() { //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Expected O, but got Unknown //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Expected O, but got Unknown //IL_03a0: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Expected O, but got Unknown //IL_03e3: Unknown result type (might be due to invalid IL or missing references) //IL_03e9: Expected O, but got Unknown //IL_03f3: Unknown result type (might be due to invalid IL or missing references) StoneLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "WhetstonesLevel", 30, "Whetstones: level to craft them (anyone can use them)."); StoneRecipe = ((BaseUnityPlugin)this).Config.Bind<string>("Perks", "WhetstoneRecipe", "Stone:2,Flint:2", "Materials for two whetstones (crafted at the workbench)."); StoneBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "WhetstoneDamageBonus", 0.1f, "Whetstone: extra weapon damage."); StoneMinutes = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "WhetstoneMinutes", 10f, "Whetstone: how long it lasts (real minutes)."); BalanceLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "BalancedMakeLevel", 50, "Balanced make level."); BalanceCut = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "BalancedMakeStaminaReduction", 0.1f, "Balanced make: weapons you craft use this much less stamina per swing."); FieldLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "FieldSharpeningLevel", 70, "Field sharpening: repair the weapons in your inventory anywhere (button in the Professions window)."); MasterLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "MasterworkLevel", 90, "Masterwork level."); MasterBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "MasterworkDamageBonus", 0.05f, "Masterwork: extra damage for weapons you craft."); Sharpened = ScriptableObject.CreateInstance<StatusEffect>(); ((Object)Sharpened).name = "VP_Sharpened"; Sharpened.m_name = "Sharpened"; Sharpened.m_tooltip = "+" + Mathf.RoundToInt(StoneBonus.Value * 100f) + "% weapon damage."; Sharpened.m_ttl = StoneMinutes.Value * 60f; Content.AddStatusEffect(Sharpened); Content.AddItem("Flint", "VP_Whetstone", "Whetstone", "A weaponsmith's sharpening stone. Use it for +" + Mathf.RoundToInt(StoneBonus.Value * 100f) + "% weapon damage for " + StoneMinutes.Value + " minutes.", (Action<SharedData>)delegate(SharedData s) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) s.m_itemType = (ItemType)2; s.m_maxStackSize = 20; s.m_weight = 0.5f; s.m_consumeStatusEffect = null; if (s.m_icons != null && s.m_icons.Length != 0) { Sharpened.m_icon = s.m_icons[0]; } }); Content.AddRecipe("VP_Whetstone", "piece_workbench", 1, 2, StoneRecipe.Value, "Weaponsmithing", StoneLevel.Value); Content.AddTooltip((Func<ItemData, string>)Tooltip); Content.AddAction("Weaponsmithing", FieldLevel.Value, "Field sharpening: repair my weapons", (Func<string>)FieldSharpen); Api.RegisterLadder("Weaponsmithing", "VargheimWeaponsmithing 1.0.0", "Crafts and upgrades modded weapons, shields, bows, crossbows and ammo by tier. Gains experience from crafting and upgrading them.", (Perk[])(object)new Perk[4] { new Perk(StoneLevel.Value, "Whetstones", "Craft whetstones: +" + Mathf.RoundToInt(StoneBonus.Value * 100f) + "% damage for " + StoneMinutes.Value + " minutes. Anyone can use them."), new Perk(BalanceLevel.Value, "Balanced make", "Weapons you craft use " + Mathf.RoundToInt(BalanceCut.Value * 100f) + "% less stamina per swing."), new Perk(FieldLevel.Value, "Field sharpening", "Repair the weapons in your inventory anywhere (button below)."), new Perk(MasterLevel.Value, "Masterwork", "Weapons you craft get +" + Mathf.RoundToInt(MasterBonus.Value * 100f) + "% damage and show \"Forged by <name>\".") }); new Harmony("digi.vargheim.weaponsmithing").PatchAll(typeof(Patches)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"VargheimWeaponsmithing 1.0.0 loaded."); } internal static bool IsWeapon(ItemData i) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_001c: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Invalid comparison between Unknown and I4 //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 if (i == null || i.m_shared == null) { return false; } ItemType itemType = i.m_shared.m_itemType; if ((int)itemType <= 14) { if (itemType - 3 <= 2 || (int)itemType == 14) { goto IL_0035; } } else if ((int)itemType == 19 || (int)itemType == 22) { goto IL_0035; } return false; IL_0035: return true; } private static string Tag(ItemData i, string key) { if (i == null || i.m_customData == null || !i.m_customData.TryGetValue(key, out var value)) { return null; } return value; } private static string Tooltip(ItemData i) { string text = ""; if (Tag(i, "vp_balanced") != null) { text = text + "<color=#ffd27a>Balanced</color>: " + Mathf.RoundToInt(BalanceCut.Value * 100f) + "% less stamina per swing"; } string text2 = Tag(i, "vp_masterwork"); if (text2 != null) { text = text + ((text.Length > 0) ? "\n" : "") + "<color=#ffd27a>Masterwork</color>: +" + Mathf.RoundToInt(MasterBonus.Value * 100f) + "% damage. Forged by " + text2; } return text; } private static string FieldSharpen() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return null; } int num = 0; foreach (ItemData allItem in ((Humanoid)localPlayer).GetInventory().GetAllItems()) { if (IsWeapon(allItem) && allItem.m_shared.m_useDurability && allItem.m_durability < allItem.GetMaxDurability()) { allItem.m_durability = allItem.GetMaxDurability(); num++; } } if (num != 0) { return "Sharpened and repaired " + num + " weapon" + ((num == 1) ? "" : "s") + "."; } return "Your weapons are already sharp."; } } } namespace VargheimSailing { [BepInPlugin("digi.vargheim.sailing", "VargheimSailing", "1.0.6")] [BepInDependency("digi.vargheim.professions", "0.4.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { [HarmonyPatch] internal static class Patches { private static string s_rowList; private static readonly HashSet<string> s_rows = new HashSet<string>(StringComparer.Ordinal); [HarmonyPatch(typeof(Piece), "SetCreator")] [HarmonyPostfix] private static void SetCreator(Piece __instance) { try { Ship component = ((Component)__instance).GetComponent<Ship>(); Player localPlayer = Player.m_localPlayer; ZDO val = Zdo((Component)(object)__instance); if ((Object)(object)component == (Object)null || (Object)(object)localPlayer == (Object)null || val == null) { return; } val.Set("vp_builder", localPlayer.GetPlayerName()); if (Api.HasPerk("Sailing", IceLevel.Value) && LargeSet.Contains(PrefabName(((Component)__instance).gameObject))) { val.Set("vp_icebreaker", true); } if (Api.HasPerk("Sailing", AdmiralLevel.Value)) { val.Set("vp_admiral", true); WearNTear component2 = ((Component)__instance).GetComponent<WearNTear>(); if ((Object)(object)component2 != (Object)null) { component2.m_health *= 1f + AdmiralHealth.Value; } } } catch { } } [HarmonyPatch(typeof(WearNTear), "Awake")] [HarmonyPostfix] private static void WearAwake(WearNTear __instance) { try { if (!((Object)(object)((Component)__instance).GetComponent<Ship>() == (Object)null)) { ZDO val = Zdo((Component)(object)__instance); if (val != null && val.GetBool("vp_admiral", false)) { __instance.m_health *= 1f + AdmiralHealth.Value; } } } catch { } } [HarmonyPatch(typeof(WearNTear), "RPC_Damage")] [HarmonyPrefix] private static bool ShipDamage(WearNTear __instance, HitData hit) { //IL_0026: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Invalid comparison between Unknown and I4 //IL_0073: Unknown result type (might be due to invalid IL or missing references) try { if (hit == null || Seasons.FloeType == null || (Object)(object)hit.GetAttacker() != (Object)null) { return true; } HitType hitType = hit.m_hitType; if ((int)hitType != 0 && (int)hitType != 11 && (int)hitType != 17) { return true; } if (hit.m_dir == Vector3.up) { return true; } Ship component = ((Component)__instance).GetComponent<Ship>(); if ((Object)(object)component == (Object)null || !IsIcebreaker(component)) { return true; } Collider[] array = Physics.OverlapSphere(hit.m_point, 4f); foreach (Collider val in array) { if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).GetComponentInParent(Seasons.FloeType) != (Object)null) { return false; } } } catch { } return true; } internal static bool IsRowboatName(string name) { IsRowboat(null); if (name != null) { return s_rows.Contains(name); } return false; } private static bool IsRowboat(Ship s) { string text = Rowboats.Value ?? string.Empty; if ((object)text != s_rowList) { s_rowList = text; s_rows.Clear(); string[] array = text.Split(','); foreach (string text2 in array) { if (text2.Trim().Length > 0) { s_rows.Add(text2.Trim()); } } } if (s_rows.Count > 0 && (Object)(object)s != (Object)null) { return s_rows.Contains(Utils.GetPrefabName(((Component)s).gameObject)); } return false; } private static bool IsRowTarget(Ship s) { return ShipSpeed.IsRow(s); } [HarmonyPatch(typeof(Ship), "GetWindAngle")] [HarmonyPostfix] [HarmonyPriority(0)] private static void WindAngle(Ship __instance, ref float __result) { try { if (IsRowboat(__instance) || IsRowTarget(__instance)) { __result = 0f; } } catch { } } [HarmonyPatch(typeof(Ship), "GetWindAngleFactor")] [HarmonyPostfix] [HarmonyPriority(0)] private static void WindAngleFactor(Ship __instance, ref float __result) { try { if (IsRowboat(__instance) || IsRowTarget(__instance)) { __result = 1f; } } catch { } } [HarmonyPatch(typeof(Ship), "GetSailForce")] [HarmonyPostfix] private static void SailForce(Ship __instance, float sailSize, ref Vector3 __result) { //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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) try { ShipSpeed.Apply(__instance); if (IsRowboat(__instance) || IsRowTarget(__instance)) { float num = ((sailSize >= 0.99f) ? RowboatFull.Value : RowboatHalf.Value); __result = ((Component)__instance).transform.forward * (__instance.m_backwardForce * num); } int num2 = SteerLevel(__instance); float num3 = 1f; if (num2 >= CrewLevel.Value) { List<Player> list = s_players.Invoke(__instance); int num4 = ((list != null) ? Math.Max(0, list.Count - 1) : 0); num3 += Mathf.Min(CrewMax.Value, (float)num4 * CrewPer.Value); } if (num2 >= StormLevel.Value && (Object)(object)EnvMan.instance != (Object)null) { EnvSetup currentEnvironment = EnvMan.instance.GetCurrentEnvironment(); if ((currentEnvironment != null && currentEnvironment.m_name != null && currentEnvironment.m_name.IndexOf("storm", StringComparison.OrdinalIgnoreCase) >= 0) || EnvMan.instance.GetWindIntensity() >= StormWind.Value) { num3 += StormBonus.Value; } } if (IsIcebreaker(__instance) && Seasons.Frozen()) { num3 *= IceSpeed.Value; } __result *= num3; } catch { } } [HarmonyPatch(typeof(ShipControlls), "Interact")] [HarmonyPrefix] private static bool Interact(ShipControlls __instance, Humanoid character, bool alt, ref bool __result) { try { if (!alt || (Object)(object)character != (Object)(object)Player.m_localPlayer || !Api.HasPerk("Sailing", NameLevel.Value)) { return true; } ZDO val = Zdo((Component)(object)__instance.m_ship); if (val == null || val.GetString("vp_builder", "") != Player.m_localPlayer.GetPlayerName()) { return true; } if (__instance.HaveValidUser()) { Api.Message("You can only name the ship while nobody is steering."); __result = false; return false; } TextInput.instance.RequestText((TextReceiver)(object)new Namer(__instance.m_ship), "Name your ship", 32); __result = true; return false; } catch { return true; } } [HarmonyPatch(typeof(ShipControlls), "GetHoverText")] [HarmonyPostfix] private static void Hover(ShipControlls __instance, ref string __result) { try { ZDO val = Zdo((Component)(object)__instance.m_ship); if (val != null) { string text = val.GetString("vp_shipname", ""); string text2 = val.GetString("vp_builder", ""); string text3 = ""; if (text.Length > 0) { text3 = text3 + "\n<color=#ffd27a>" + text + "</color>"; } if (val.GetBool("vp_admiral", false) && text2.Length > 0) { text3 = text3 + "\nBuilt by " + text2; } if (val.GetBool("vp_icebreaker", false)) { text3 += "\n<color=#9fd8ff>Icebreaker</color>"; } if ((Object)(object)Player.m_localPlayer != (Object)null && text2 == Player.m_localPlayer.GetPlayerName() && Api.HasPerk("Sailing", NameLevel.Value)) { text3 += "\n[<color=yellow><b>Shift + $KEY_Use</b></color>] Name ship"; } if (text3.Length > 0) { __result += Localization.instance.Localize(text3); } } } catch { } } } internal sealed class Namer : TextReceiver { private readonly Ship _ship; public Namer(Ship ship) { _ship = ship; } public string GetText() { ZDO val = Zdo((Component)(object)_ship); if (val == null) { return ""; } return val.GetString("vp_shipname", ""); } public void SetText(string text) { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) ZNetView val = (((Object)(object)_ship != (Object)null) ? ((Component)_ship).GetComponent<ZNetView>() : null); if (!((Object)(object)val == (Object)null) && val.IsValid()) { text = (text ?? "").Replace("<", "").Replace(">", "").Trim(); if (text.Length > 32) { text = text.Substring(0, 32); } val.ClaimOwnership(); val.GetZDO().Set("vp_shipname", text); Pins.Remember(val.GetZDO().m_uid, text, ((Component)_ship).transform.position); Api.Message((text.Length > 0) ? ("This ship is now the " + text + ".") : "Name removed."); } } } internal static class Pins { private static readonly Dictionary<string, PinData> s_pins = new Dictionary<string, PinData>(); private static Dictionary<string, string> Store(Player p) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (p.m_customData != null && p.m_customData.TryGetValue("vp_ships", out var value)) { string[] array = value.Split(';'); foreach (string text in array) { int num = text.IndexOf('='); if (num > 0) { dictionary[text.Substring(0, num)] = text.Substring(num + 1); } } } return dictionary; } private static void Save(Player p, Dictionary<string, string> d) { List<string> list = new List<string>(); foreach (KeyValuePair<string, string> item in d) { list.Add(item.Key + "=" + item.Value); } p.m_customData["vp_ships"] = string.Join(";", list.ToArray()); } private static string Key(ZDOID id) { return ((ZDOID)(ref id)).UserID.ToString(CultureInfo.InvariantCulture) + ":" + ((ZDOID)(ref id)).ID.ToString(CultureInfo.InvariantCulture); } internal static void Remember(ZDOID id, string name, Vector3 pos) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && localPlayer.m_customData != null) { Dictionary<string, string> dictionary = Store(localPlayer); if (name.Length == 0) { dictionary.Remove(Key(id)); } else { dictionary[Key(id)] = name.Replace(";", "").Replace("=", "").Replace("|", "") + "|" + pos.x.ToString("0", CultureInfo.InvariantCulture) + "|" + pos.z.ToString("0", CultureInfo.InvariantCulture); } Save(localPlayer, dictionary); } } internal static void Update(Player p) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Minimap.instance == (Object)null || p.m_customData == null) { return; } Dictionary<string, string> dictionary = Store(p); bool flag = false; foreach (IMonoUpdater item in new List<IMonoUpdater>(Ship.Instances)) { Ship val = (Ship)(object)((item is Ship) ? item : null); ZDO val2 = (((Object)(object)val != (Object)null) ? Zdo((Component)(object)val) : null); if (val2 == null) { continue; } string key = Key(val2.m_uid); if (dictionary.TryGetValue(key, out var value)) { string text = val2.GetString("vp_shipname", ""); string text2 = text + "|" + ((Component)val).transform.position.x.ToString("0", CultureInfo.InvariantCulture) + "|" + ((Component)val).transform.position.z.ToString("0", CultureInfo.InvariantCulture); if (text.Length == 0) { dictionary.Remove(key); flag = true; } else if (text2 != value) { dictionary[key] = text2; flag = true; } } } if (flag) { Save(p, dictionary); } foreach (KeyValuePair<string, PinData> item2 in new Dictionary<string, PinData>(s_pins)) { Minimap.instance.RemovePin(item2.Value); } s_pins.Clear(); foreach (KeyValuePair<string, string> item3 in dictionary) { string[] array = item3.Value.Split('|'); if (array.Length == 3 && float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && float.TryParse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { s_pins[item3.Key] = Minimap.instance.AddPin(new Vector3(result, 0f, result2), (PinType)6, array[0], false, false, 0L, default(PlatformUserID)); } } } } internal static class Seasons { internal static Type FloeType; private static MethodInfo s_frozen; internal static bool Frozen() { try { return s_frozen != null && (bool)s_frozen.Invoke(null, null); } catch { return false; } } internal static void Patch(Harmony h) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown Type type = AccessTools.TypeByName("Seasons.ZoneSystemVariantController"); FloeType = AccessTools.TypeByName("Seasons.IceFloe"); if (!(type == null)) { s_frozen = AccessTools.Method(type, "IsWaterSurfaceFrozen", (Type[])null, (Type[])null); MethodInfo methodInfo = AccessTools.Method(type, "PlaceShip", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(type, "ShouldSkipFrozenShipPhysics", (Type[])null, (Type[])null); if (methodInfo != null) { h.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Seasons), "PlacePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (methodInfo2 != null) { h.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(Seasons), "SkipPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } ((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Seasons found: icebreaker hooks " + ((methodInfo != null) ? "on" : "missing") + "/" + ((methodInfo2 != null) ? "on" : "missing") + ".")); } } private static bool PlacePrefix(Ship ship) { try { if ((Object)(object)ship != (Object)null && IsIcebreaker(ship)) { Rigidbody component = ((Component)ship).GetComponent<Rigidbody>(); if ((Object)(object)component != (Object)null && component.isKinematic) { component.isKinematic = false; } return false; } } catch { } return true; } private static void SkipPostfix(Ship ship, ref bool __result) { if (__result && (Object)(object)ship != (Object)null && IsIcebreaker(ship)) { __result = false; } } } public const string Guid = "digi.vargheim.sailing"; public const string Version = "1.0.6"; private const string Prof = "Sailing"; internal static ConfigEntry<int> CrewLevel; internal static ConfigEntry<int> NameLevel; internal static ConfigEntry<int> PatchLevel; internal static ConfigEntry<int> StormLevel; internal static ConfigEntry<int> IceLevel; internal static ConfigEntry<int> ChartLevel; internal static ConfigEntry<int> AdmiralLevel; internal static ConfigEntry<float> CrewPer; internal static ConfigEntry<float> CrewMax; internal static ConfigEntry<float> StormBonus; internal static ConfigEntry<float> StormWind; internal static ConfigEntry<float> IceSpeed; internal static ConfigEntry<float> ChartMult; internal static ConfigEntry<float> AdmiralHealth; internal static ConfigEntry<string> PatchCost; internal static ConfigEntry<string> LargeShips; internal static ConfigEntry<string> Rowboats; internal static ConfigEntry<float> RowboatHalf; internal static ConfigEntry<float> RowboatFull; internal static HashSet<string> LargeSet = new HashSet<string>(StringComparer.Ordinal); internal static Plugin Instance; private float _next; private float _nextPins; private static readonly FieldRef<Ship, List<Player>> s_players = AccessTools.FieldRefAccess<Ship, List<Player>>("m_players"); private static MethodInfo s_explore; internal static void Log(string msg) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)msg); } } private void Awake() { //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0364: Expected O, but got Unknown //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_0380: Expected O, but got Unknown //IL_03c8: Unknown result type (might be due to invalid IL or missing references) //IL_03ce: Expected O, but got Unknown //IL_03fd: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Expected O, but got Unknown //IL_0419: Unknown result type (might be due to invalid IL or missing references) //IL_041f: Expected O, but got Unknown //IL_0435: Unknown result type (might be due to invalid IL or missing references) //IL_043b: Expected O, but got Unknown //IL_046a: Unknown result type (might be due to invalid IL or missing references) //IL_0470: Expected O, but got Unknown //IL_04b9: Unknown result type (might be due to invalid IL or missing references) //IL_04bf: Expected O, but got Unknown Instance = this; CrewLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "CrewBonusLevel", 30, "Crew bonus level."); CrewPer = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "CrewBonusPerPlayer", 0.03f, "Crew bonus: extra sail speed per other player aboard while a sailor steers."); CrewMax = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "CrewBonusMax", 0.15f, "Crew bonus: most extra sail speed."); NameLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "ChristeningLevel", 35, "Christening: name ships you built (Shift + use on the rudder)."); PatchLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "HullPatchLevel", 40, "Hull patch: repair the ship you're on, at sea (button in the Professions window)."); PatchCost = ((BaseUnityPlugin)this).Config.Bind<string>("Perks", "HullPatchCost", "Wood:10,Resin:5", "Materials for one hull patch."); StormLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "StormRiderLevel", 50, "Storm rider level."); StormBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "StormRiderBonus", 0.15f, "Storm rider: extra sail speed in storms and strong wind."); StormWind = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "StormRiderWind", 0.7f, "Storm rider: wind strength (0-1) that counts as rough weather."); IceLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "IcebreakerLevel", 60, "Icebreaker: larger ships a sailor of this level builds break Seasons ice."); Rowboats = ((BaseUnityPlugin)this).Config.Bind<string>("Rowboats", "Rowboats", "BBA_Canoe", "Ship prefabs that are rowed, not sailed: half and full speed ignore the wind and push straight ahead at a steady strength. Separated by ','."); RowboatHalf = ((BaseUnityPlugin)this).Config.Bind<float>("Rowboats", "HalfSpeed", 1.4f, "Rowboat push at half speed, as a multiple of its paddle (slow) push. Wind is ignored."); RowboatFull = ((BaseUnityPlugin)this).Config.Bind<float>("Rowboats", "FullSpeed", 1.8f, "Rowboat push at full speed, as a multiple of its paddle (slow) push. Wind is ignored."); LargeShips = ((BaseUnityPlugin)this).Config.Bind<string>("Perks", "IcebreakerShips", "VikingShip,VikingShip_Ashlands,KnarrBal,BigCargoShip,CargoShip,WarShip,MercantShip,HerculeShip,BBA_Knarr,BBA_LargeRaft", "Ship prefabs that count as larger ships."); IceSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "IcebreakerFrozenSpeed", 0.5f, "Icebreaker: sail speed while the ocean is frozen (0.5 = half)."); ChartLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "SeaChartLevel", 75, "Sea chart level."); ChartMult = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "SeaChartRadiusMultiplier", 2f, "Sea chart: map reveal radius for everyone aboard, as a multiple of the normal reveal radius."); AdmiralLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "AdmiralLevel", 100, "Admiral level."); AdmiralHealth = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "AdmiralHealthBonus", 0.25f, "Admiral: extra health for ships the admiral builds."); LargeSet = new HashSet<string>(LargeShips.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal); ((BaseUnityPlugin)this).Config.SettingChanged += delegate { LargeSet = new HashSet<string>(LargeShips.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal); }; Api.RegisterLadder("Sailing", "VargheimSailing 1.0.6", "Smoothbrain Sailing: faster ships, less ship damage and a bigger map reveal at sea. Ships added by mods are built by sailors, by tier.", (Perk[])(object)new Perk[7] { new Perk(CrewLevel.Value, "Crew bonus", "When you steer, +" + P(CrewPer.Value) + " speed for each other player aboard, up to +" + P(CrewMax.Value) + "."), new Perk(NameLevel.Value, "Christening", "Name ships you built: Shift + use on the rudder. The name shows on hover and on your map."), new Perk(PatchLevel.Value, "Hull patch", "Repair the ship you're on, at sea, for " + PatchCost.Value.Replace(":", " ").Replace(",", ", ") + " (button below)."), new Perk(StormLevel.Value, "Storm rider", "+" + P(StormBonus.Value) + " sail speed in storms and strong wind while you steer."), new Perk(IceLevel.Value, "Icebreaker", "Larger ships you build smash winter ice floes without damage and can keep sailing through the frozen ocean at reduced speed."), new Perk(ChartLevel.Value, "Sea chart", "While you steer, everyone aboard reveals the map at your radius."), new Perk(AdmiralLevel.Value, "Admiral", "Ships you build have +" + P(AdmiralHealth.Value) + " health and show \"Built by <name>\".") }); Content.AddAction("Sailing", PatchLevel.Value, "Patch the hull of this ship", (Func<string>)HullPatch); ShipSpeed.Bind(((BaseUnityPlugin)this).Config); Harmony val = new Harmony("digi.vargheim.sailing"); val.PatchAll(typeof(Patches)); val.PatchAll(typeof(ShipSpeed.Patches)); try { Seasons.Patch(val); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Seasons icebreaker hooks skipped: " + ex.Message)); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"VargheimSailing 1.0.6 loaded."); } internal static string P(float f) { return Mathf.RoundToInt(f * 100f) + "%"; } internal static string PrefabName(GameObject go) { string name = ((Object)go).name; int num = name.IndexOf("(Clone)", StringComparison.Ordinal); return ((num >= 0) ? name.Substring(0, num) : name).Trim(); } internal static ZDO Zdo(Component c) { ZNetView val = (((Object)(object)c != (Object)null) ? c.GetComponent<ZNetView>() : null); if (!((Object)(object)val != (Object)null) || !val.IsValid()) { return null; } return val.GetZDO(); } internal static Ship Steering() { Player localPlayer = Player.m_localPlayer; ShipControlls val = (ShipControlls)(((Object)(object)localPlayer != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); if (!((Object)(object)val != (Object)null)) { return null; } return val.m_ship; } internal static Player Steerer(Ship s) { if ((Object)(object)s == (Object)null || (Object)(object)s.m_shipControlls == (Object)null) { return null; } long user = s.m_shipControlls.GetUser(); if (user == 0L) { return null; } Player player = Player.GetPlayer(user); if (!((Object)(object)player != (Object)null) || !s.IsPlayerInBoat(player)) { return null; } return player; } internal static int SteerLevel(Ship s) { Player val = Steerer(s); if (!((Object)(object)val != (Object)null)) { return 0; } return Api.PerkLevelOf(val, "Sailing"); } internal static Ship ShipUnder(Player p) { //IL_004b: 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) Ship localShip = Ship.GetLocalShip(); if ((Object)(object)localShip != (Object)null && (Object)(object)p == (Object)(object)Player.m_localPlayer) { return localShip; } Ship result = null; float num = 20f; Ship[] array = Object.FindObjectsOfType<Ship>(); foreach (Ship val in array) { if (val.IsPlayerInBoat(p)) { return val; } float num2 = Vector3.Distance(((Component)val).transform.position, ((Component)p).transform.position); if (num2 < num) { result = val; num = num2; } } return result; } internal static bool IsIcebreaker(Ship s) { ZDO val = Zdo((Component)(object)s); if (val != null) { return val.GetBool("vp_icebreaker", false); } return false; } private static string HullPatch() { Player localPlayer = Player.m_localPlayer; Ship val = (((Object)(object)localPlayer != (Object)null) ? ShipUnder(localPlayer) : null); if ((Object)(object)val == (Object)null) { return "Stand on (or next to) the ship you want to patch."; } WearNTear component = ((Component)val).GetComponent<WearNTear>(); if ((Object)(object)component == (Object)null) { return "This ship can't be patched."; } if (component.GetHealthPercentage() >= 0.999f) { return "The hull is already sound."; } Inventory inventory = ((Humanoid)localPlayer).GetInventory(); List<KeyValuePair<string, int>> list = new List<KeyValuePair<string, int>>(); string[] array = PatchCost.Value.Split(','); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(':'); if (array2.Length == 2 && int.TryParse(array2[1].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { list.Add(new KeyValuePair<string, int>(array2[0].Trim(), result)); } } foreach (KeyValuePair<string, int> item in list) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item.Key); string text = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_name : item.Key); if (inventory.CountItems(text, -1, true) < item.Value) { return "You need " + PatchCost.Value.Replace(":", " ").Replace(",", ", ") + " to patch the hull."; } } if (!component.Repair()) { return "Couldn't patch the hull right now."; } foreach (KeyValuePair<string, int> item2 in list) { GameObject itemPrefab2 = ObjectDB.instance.GetItemPrefab(item2.Key); inventory.RemoveItem(itemPrefab2.GetComponent<ItemDrop>().m_itemData.m_shared.m_name, item2.Value, -1, true); } return "Hull patched."; } private void Update() { //IL_00e0: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || Time.time < _next) { return; } _next = Time.time + 1f; try { Ship s = Steering(); Ship localShip = Ship.GetLocalShip(); if ((Object)(object)localShip != (Object)null && (Object)(object)Minimap.instance != (Object)null && SteerLevel(localShip) >= ChartLevel.Value) { float num = Minimap.instance.m_exploreRadius * ChartMult.Value; if (s_explore == null) { s_explore = AccessTools.Method(typeof(Minimap), "Explore", new Type[2] { typeof(Vector3), typeof(float) }, (Type[])null); } s_explore.Invoke(Minimap.instance, new object[2] { ((Component)localPlayer).transform.position, num }); } Icebreak(s); if (Time.time > _nextPins) { _nextPins = Time.time + 5f; Pins.Update(localPlayer); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)ex.Message); } } private static void Icebreak(Ship s) { //IL_0025: 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) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)s == (Object)null || !IsIcebreaker(s) || Seasons.FloeType == null) { return; } Collider[] array = Physics.OverlapSphere(((Component)s).transform.position + ((Component)s).transform.forward * 4f, 9f); foreach (Collider val in array) { Component val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponentInParent(Seasons.FloeType) : null); if (!((Object)(object)val2 == (Object)null)) { IDestructible component = val2.GetComponent<IDestructible>(); if (component != null) { HitData val3 = new HitData(); val3.m_damage.m_blunt = 10000f; val3.m_damage.m_chop = 10000f; val3.m_damage.m_pickaxe = 10000f; val3.m_toolTier = 100; val3.m_point = val2.transform.position; val3.m_dir = ((Component)s).transform.forward; val3.SetAttacker((Character)(object)Player.m_localPlayer); component.Damage(val3); } } } } } internal static class ShipSpeed { private sealed class Ref { public float Length; public float Sail; public float Paddle; } internal sealed class Target { public float Sail; public float Paddle; public bool Row; } [HarmonyPatch] internal static class Patches { [HarmonyPatch(typeof(Ship), "Awake")] [HarmonyPostfix] [HarmonyPriority(0)] private static void Awake(Ship __instance) { try { Apply(__instance); } catch { } } [HarmonyPatch(typeof(ZNetScene), "Awake")] [HarmonyPostfix] [HarmonyPriority(0)] private static void Scene() { try { Reset(); Log(); } catch (Exception ex) { Plugin.Log("ship speed table: " + ex.Message); } } } internal static ConfigEntry<bool> Normalize; internal static ConfigEntry<bool> AutoRowboats; internal static ConfigEntry<float> Tune; internal static ConfigEntry<string> Exclude; internal static ConfigEntry<string> Vanilla; private static List<Ref> s_refs; private static readonly Dictionary<string, Target> s_targets = new Dictionary<string, Target>(StringComparer.Ordinal); private static bool s_logged; internal static void Bind(ConfigFile cfg) { Normalize = cfg.Bind<bool>("Ship Speed", "MatchVanilla", true, "Modded ships get the sail and paddle push of a vanilla ship of the same length (Raft, Karve, Longship, Drakkar). Multi-player bonuses (Oarsmen, Crew bonus) still apply on top."); Tune = cfg.Bind<float>("Ship Speed", "Tune", 1f, "Extra multiplier on the matched push of modded ships (1 = same as vanilla of that size)."); Exclude = cfg.Bind<string>("Ship Speed", "Exclude", "Trailership", "Ship prefabs left exactly as their mod made them, separated by ','."); Vanilla = cfg.Bind<string>("Ship Speed", "VanillaShips", "Raft,Karve,VikingShip,VikingShip_Ashlands", "The vanilla ships used as the yardstick (left untouched)."); cfg.SettingChanged += delegate { Reset(); }; cfg.ConfigReloaded += delegate { Reset(); }; AutoRowboats = cfg.Bind<bool>("Rowboats", "AutoDetect", true, "Ships without a sail count as rowboats: half and full speed ignore the wind."); } private static HashSet<string> List(string s) { HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); string[] array = (s ?? string.Empty).Split(','); foreach (string text in array) { if (text.Trim().Length > 0) { hashSet.Add(text.Trim()); } } return hashSet; } private static float Length(Ship s) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)s.m_floatCollider != (Object)null) { return Mathf.Abs(s.m_floatCollider.size.z * ((Component)s.m_floatCollider).transform.lossyScale.z); } } catch { } return 0f; } private static float Damp(Ship s) { return Mathf.Max(0.0001f, s.m_dampingForward); } private static void BuildRefs() { if (s_refs != null || (Object)(object)ZNetScene.instance == (Object)null) { return; } List<Ref> list = new List<Ref>(); foreach (string item in List(Vanilla.Value)) { GameObject prefab = ZNetScene.instance.GetPrefab(item); Ship val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Ship>() : null); float num = (((Object)(object)val != (Object)null) ? Length(val) : 0f); if ((Object)(object)val != (Object)null && num > 0f) { list.Add(new Ref { Length = num, Sail = val.m_sailForceFactor / Damp(val), Paddle = val.m_backwardForce / Damp(val) }); } } list.Sort((Ref a, Ref b) => a.Length.CompareTo(b.Length)); s_refs = list; } private static void Interp(float len, out float sail, out float paddle) { sail = (paddle = 0f); if (s_refs == null || s_refs.Count == 0) { return; } if (len <= s_refs[0].Length) { sail = s_refs[0].Sail; paddle = s_refs[0].Paddle; return; } for (int i = 1; i < s_refs.Count; i++) { if (len <= s_refs[i].Length) { Ref obj = s_refs[i - 1]; Ref obj2 = s_refs[i]; float num = (len - obj.Length) / Mathf.Max(0.001f, obj2.Length - obj.Length); sail = Mathf.Lerp(obj.Sail, obj2.Sail, num); paddle = Mathf.Lerp(obj.Paddle, obj2.Paddle, num); return; } } Ref obj3 = s_refs[s_refs.Count - 1]; sail = obj3.Sail; paddle = obj3.Paddle; } internal static Target For(Ship s) { if ((Object)(object)s == (Object)null) { return null; } string prefabName = Utils.GetPrefabName(((Component)s).gameObject); if (s_targets.TryGetValue(prefabName, out var value)) { return value; } BuildRefs(); value = null; bool flag = List(Vanilla.Value).Contains(prefabName); bool flag2 = List(Exclude.Value).Contains(prefabName); if (!flag2 && (Plugin.Patches.IsRowboatName(prefabName) || (AutoRowboats.Value && !s.m_hasSail && !flag))) { value = new Target { Sail = -1f, Paddle = -1f, Row = true }; } else if (Normalize.Value && !flag && !flag2 && s_refs != null && s_refs.Count > 0) { Interp(Length(s), out var sail, out var paddle); value = new Target { Sail = sail * Damp(s) * Tune.Value, Paddle = paddle * Damp(s) * Tune.Value, Row = false }; } if (s_refs != null) { s_targets[prefabName] = value; } return value; } internal static bool IsRow(Ship s) { return For(s)?.Row ?? false; } internal static void Apply(Ship s) { Target target = For(s); if (target != null) { if (target.Sail >= 0f && !Mathf.Approximately(s.m_sailForceFactor, target.Sail)) { s.m_sailForceFactor = target.Sail; } if (target.Paddle >= 0f && !Mathf.Approximately(s.m_backwardForce, target.Paddle)) { s.m_backwardForce = target.Paddle; } } } internal static void Reset() { s_targets.Clear(); s_refs = null; } internal static void Log() { if (s_logged || (Object)(object)ZNetScene.instance == (Object)null) { return; } s_logged = true; BuildRefs(); StringBuilder stringBuilder = new StringBuilder("VargheimSailing ship speeds (prefab | length | sail x damping-ratio before -> after | paddle before -> after | rowboat):"); foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { Ship val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Ship>() : null); if (!((Object)(object)val == (Object)null)) { Target target = For(val); stringBuilder.Append("\n ").Append(((Object)prefab).name).Append(" | ") .Append(Length(val).ToString("0.0", CultureInfo.InvariantCulture)) .Append(" | ") .Append(val.m_sailForceFactor.ToString("0.###", CultureInfo.InvariantCulture)) .Append(" -> ") .Append((target != null && target.Sail >= 0f) ? target.Sail.ToString("0.###", CultureInfo.InvariantCulture) : "same") .Append(" | ") .Append(val.m_backwardForce.ToString("0.###", CultureInfo.InvariantCulture)) .Append(" -> ") .Append((target != null && target.Paddle >= 0f) ? target.Paddle.ToString("0.###", CultureInfo.InvariantCulture) : "same") .Append(" | damp ") .Append(val.m_dampingForward.ToString("0.###", CultureInfo.InvariantCulture)) .Append(" | ") .Append((target != null && target.Row) ? "row" : (val.m_hasSail ? "sail" : "no sail")); } } Plugin.Log(stringBuilder.ToString()); } } } namespace VargheimRanching { [BepInPlugin("digi.vargheim.ranching", "VargheimRanching", "1.1.3")] [BepInDependency("digi.vargheim.professions", "0.4.0")] public class Plugin : BaseUnityPlugin { private sealed class Orig { public float Run; public float Speed; public float Swim; public float Stamina; public float Regen; } private sealed class Saved { public float A; public float B; } [HarmonyPatch] internal static class Patches { private static float s_nextTameMsg; [HarmonyPatch(typeof(Procreation), "Awake")] [HarmonyPostfix] private static void ProcAwake(Procreation __instance) { if (__instance.m_partnerCheckRange < PartnerRange.Value) { __instance.m_partnerCheckRange = PartnerRange.Value; } } [HarmonyPatch(typeof(Tameable), "GetHoverText")] [HarmonyPostfix] private static void Hover(Tameable __instance, ref string __result) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) try { if (__result != null && Api.Active && !__instance.IsTamed() && !Content.IsVanillaPrefab(PrefabName(((Component)__instance).gameObject)) && BestRancherNear(((Component)__instance).transform.position, NearRange.Value) < StockLevel.Value) { __result = __result + "\n<color=#ffb060>Needs a Rancher (level " + StockLevel.Value + ") nearby to tame</color>"; } } catch { } } [HarmonyPatch(typeof(Tameable), "Tame")] [HarmonyPrefix] private static bool Tame(Tameable __instance) { //IL_0027: 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_0067: Unknown result type (might be due to invalid IL or missing references) try { string text = PrefabName(((Component)__instance).gameObject); if (Api.Active && !Content.IsVanillaPrefab(text) && BestRancherNear(((Component)__instance).transform.position, NearRange.Value) < StockLevel.Value) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && Vector3.Distance(((Component)localPlayer).transform.position, ((Component)__instance).transform.position) < 30f && Time.time >= s_nextTameMsg) { s_nextTameMsg = Time.time + 8f; ((Character)localPlayer).Message((MessageType)2, "It won't settle: a Rancher of level " + StockLevel.Value + " must be nearby to tame it.", 0, (Sprite)null, false); } return false; } } catch { } return true; } [HarmonyPatch(typeof(Character), "RPC_Damage")] [HarmonyPrefix] private static void Damage(Character __instance, HitData hit) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) try { if (hit != null && !(__instance is Player) && __instance.IsTamed() && BestRancherNear(((Component)__instance).transform.position, NearRange.Value) >= GentleLevel.Value) { hit.ApplyModifier(1f - GentleCut.Value); } } catch { } } [HarmonyPatch(typeof(Procreation), "Procreate")] [HarmonyPrefix] [HarmonyPriority(800)] private static void ProcPre(Procreation __instance, out Saved __state) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) __state = null; s_cur = __instance; try { int num = BestRancherNear(((Component)__instance).transform.position, BreedRange.Value); if (num >= BreedLevel.Value) { __state = new Saved { A = __instance.m_pregnancyDuration, B = __instance.m_pregnancyChance }; __instance.m_pregnancyDuration *= 1f - BreedFaster.Value; __instance.m_pregnancyChance = Mathf.Min(1f, __instance.m_pregnancyChance / Mathf.Max(0.05f, 1f - BreedFaster.Value)); } s_birth = num >= BloodLevel.Value; } catch { } } [HarmonyPatch(typeof(Procreation), "Procreate")] [HarmonyFinalizer] private static void ProcPost(Procreation __instance, Saved __state) { s_birth = false; s_cur = null; if (__state != null) { __instance.m_pregnancyDuration = __state.A; __instance.m_pregnancyChance = __state.B; } } [HarmonyPatch(typeof(Character), "SetLevel")] [HarmonyPrefix] private static void SetLevel(ref int level) { if (s_birth && Random.value < BloodChance.Value) { level++; s_birth = false; } } [HarmonyPatch(typeof(Growup), "GrowUpdate")] [HarmonyPrefix] private static void GrowPre(Growup __instance, out float __state) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) __state = -1f; try { if (BestRancherNear(((Component)__instance).transform.position, BreedRange.Value) >= BreedLevel.Value) { __state = __instance.m_growTime; __instance.m_growTime *= 1f - BreedFaster.Value; } } catch { } } [HarmonyPatch(typeof(Growup), "GrowUpdate")] [HarmonyFinalizer] private static void GrowPost(Growup __instance, float __state) { if (__state >= 0f) { __instance.m_growTime = __state; } } [HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")] [HarmonyPostfix] private static void Butcher(CharacterDrop __instance, List<KeyValuePair<GameObject, int>> __result) { try { Character value = Traverse.Create((object)__instance).Field("m_character").GetValue<Character>(); if ((Object)(object)value == (Object)null || !value.IsTamed() || __result == null) { return; } HitData val = s_lastHit.Invoke(value); Player val2 = (Player)((val != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val2 == (Object)null || Api.PerkLevelOf(val2, "Ranching") < ButcherLevel.Value) { return; } for (int i = 0; i < __result.Count; i++) { KeyValuePair<GameObject, int> keyValuePair = __result[i]; if (!((Object)(object)keyValuePair.Key == (Object)null) && ButcherItem(((Object)keyValuePair.Key).name)) { float num = (float)keyValuePair.Value * ButcherBonus.Value; int num2 = Mathf.FloorToInt(num) + ((Random.value < num - Mathf.Floor(num)) ? 1 : 0); if (num2 > 0) { __result[i] = new KeyValuePair<GameObject, int>(keyValuePair.Key, keyValuePair.Value + num2); } } } } catch { } } } public const string Guid = "digi.vargheim.ranching"; public const string Version = "1.1.3"; private const string Prof = "Ranching"; internal static ConfigEntry<float> PartnerRange; internal static ConfigEntry<float> NearRange; internal static ConfigEntry<float> GentleCut; internal static ConfigEntry<float> BreedFaster; internal static ConfigEntry<float> BreedRange; internal static ConfigEntry<float> RiderBonus; internal static ConfigEntry<float> ButcherBonus; internal static ConfigEntry<float> BloodChance; internal static ConfigEntry<float> WinterMult; internal static ConfigEntry<int> StockLevel; internal static ConfigEntry<int> GentleLevel; internal static ConfigEntry<int> BreedLevel; internal static ConfigEntry<int> RiderLevel; internal static ConfigEntry<int> ButcherLevel; internal static ConfigEntry<int> BloodLevel; internal static ConfigEntry<int> WinterLevel; internal static ConfigEntry<string> RancherItems; internal static ConfigEntry<string> ButcherItems; internal static ConfigEntry<string> HideRecipe; internal const string Hide = "VP_TannedHide"; internal static ConfigEntry<int> HideLevel; internal static ConfigEntry<int> HideAmount; internal static HashSet<string> ButcherSet = new HashSet<string>(StringComparer.Ordinal); [ThreadStatic] internal static Procreation s_cur; private static readonly Dictionary<Sadle, Orig> s_boosted = new Dictionary<Sadle, Orig>(); private float _next; [ThreadStatic] private static bool s_birth; private static readonly FieldRef<Character, HitData> s_lastHit = AccessTools.FieldRefAccess<Character, HitData>("m_lastHit"); private void Awake() { //IL_03bf: Unknown result type (might be due to invalid IL or missing references) //IL_03c5: Expected O, but got Unknown //IL_03d3: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Expected O, but got Unknown //IL_0442: Unknown result type (might be due to invalid IL or missing references) //IL_0448: Expected O, but got Unknown //IL_04b1: Unknown result type (might be due to invalid IL or missing references) //IL_04b7: Expected O, but got Unknown //IL_0520: Unknown result type (might be due to invalid IL or missing references) //IL_0526: Expected O, but got Unknown //IL_0563: Unknown result type (might be due to invalid IL or missing references) //IL_0569: Expected O, but got Unknown //IL_05a6: Unknown result type (might be due to invalid IL or missing references) //IL_05ac: Expected O, but got Unknown //IL_05e4: Unknown result type (might be due to invalid IL or missing references) //IL_05ea: Expected O, but got Unknown //IL_05f4: Unknown result type (might be due to invalid IL or missing references) //IL_05fa: Expected O, but got Unknown PartnerRange = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "MinimumPartnerRange", 5f, "Every animal looks for a breeding partner at least this far away (metres). Applies to everyone."); NearRange = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "RancherNearRange", 30f, "How close a rancher must be for Stockman and Gentle hand."); StockLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "StockmanLevel", 25, "Stockman: creatures added by mods can only be tamed with a rancher of this level nearby."); RancherItems = ((BaseUnityPlugin)this).Config.Bind<string>("Perks", "RancherCraftedItems", "rae_SaddleHorse,rae_saddlebags", "Items only ranchers (Stockman level) can craft."); HideLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "TannedHideLevel", 35, "Tanned hide: level to make Tanned Hide, which smiths need for modded armor."); HideRecipe = ((BaseUnityPlugin)this).Config.Bind<string>("Perks", "TannedHideRecipe", "DeerHide:2,LeatherScraps:2,Resin:2", "Materials for Tanned Hide (at a workbench)."); HideAmount = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "TannedHideAmount", 2, "Tanned Hide per craft."); Content.AddItem("DeerHide", "VP_TannedHide", "Tanned Hide", "Hide scraped, cured and worked soft. Smiths need it for modded armor. Only a rancher can tan it.", (Action<SharedData>)delegate(SharedData s) { s.m_weight = 1f; s.m_maxStackSize = 50; }); Content.AddRecipe("VP_TannedHide", "piece_workbench", 1, Math.Max(1, HideAmount.Value), HideRecipe.Value, "Ranching", HideLevel.Value); GentleLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "GentleHandLevel", 35, "Gentle hand level."); GentleCut = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "GentleHandDamageReduction", 0.15f, "Gentle hand: tamed animals near a rancher take this much less damage."); BreedLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "HerdBreederLevel", 45, "Herd breeder level."); BreedRange = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "HerdBreederRange", 10f, "Herd breeder range."); BreedFaster = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "HerdBreederSpeedup", 0.25f, "Herd breeder: breeding and growing up this much faster."); WinterLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "WinterHerdLevel", 25, "Winter herd: when Seasons sets the winter breeding rate to 0, animals within Herd breeder range of a rancher of this level still breed."); WinterMult = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "WinterHerdMultiplier", 0.5f, "Winter herd: breeding rate used in winter near a rancher (1 = normal, 0.5 = half as often). Only applies when Seasons has winter breeding at 0."); RiderLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "TrailRiderLevel", 60, "Trail rider level."); RiderBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "TrailRiderBonus", 0.15f, "Trail rider: mount speed and stamina bonus while the rancher rides."); ButcherLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "ButcherLevel", 75, "Butcher level."); ButcherBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "ButcherBonus", 0.25f, "Butcher: extra meat, leather and hides from tamed animals the rancher slaughters."); ButcherItems = ((BaseUnityPlugin)this).Config.Bind<string>("Perks", "ButcherExtraItems", "LeatherScraps,DeerHide,TrollHide,WolfPelt,LoxPelt,ScaleHide,AskHide,BjornHide,Feathers,NeckTail,Entrails", "Items Butcher adds to, besides anything with Meat, Hide or Pelt in its name."); BloodLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "BloodlineLevel", 100, "Bloodline level."); BloodChance = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "BloodlineChance", 0.1f, "Bloodline: chance an animal born near the rancher gets one more star."); Load(); ((BaseUnityPlugin)this).Config.SettingChanged += delegate { Load(); }; Api.RegisterLadder("Ranching", "VargheimRanching 1.1.3", "Smoothbrain Ranching: faster taming and more drops from tamed animals. Every animal needs a partner within " + PartnerRange.Value + " m to breed.", (Perk[])(object)new Perk[8] { new Perk(StockLevel.Value, "Stockman", "Creatures added by mods (horses and others) can only be tamed with you nearby. You craft saddles and saddlebags. Riding stays open to everyone."), new Perk(10, "Tier hides", "Make the Rancher's tier material at a workbench, one per biome from that biome's hides (Tanned Hide at 10, Troll Leather at 25, Draugr Sinew at 35, Frost Pelt at 45 ...). Smiths need it for every modded armor piece and cape of that tier."), new Perk(GentleLevel.Value, "Gentle hand", "Tamed animals within " + NearRange.Value + " m of you take " + Mathf.RoundToInt(GentleCut.Value * 100f) + "% less damage."), new Perk(WinterLevel.Value, "Winter herd", "Animals do not breed in winter unless a rancher is within " + BreedRange.Value + " m; near you they breed at " + Mathf.RoundToInt(WinterMult.Value * 100f) + "% of the normal rate."), new Perk(BreedLevel.Value, "Herd breeder", "Animals within " + BreedRange.Value + " m of you breed " + Mathf.RoundToInt(BreedFaster.Value * 100f) + "% faster and their young grow up faster."), new Perk(RiderLevel.Value, "Trail rider", "+" + Mathf.RoundToInt(RiderBonus.Value * 100f) + "% speed and stamina for the mount you ride."), new Perk(ButcherLevel.Value, "Butcher", "Tamed animals you slaughter drop " + Mathf.RoundToInt(ButcherBonus.Value * 100f) + "% more meat, leather and hides."), new Perk(BloodLevel.Value, "Bloodline", Mathf.RoundToInt(BloodChance.Value * 100f) + "% chance an animal born near you comes out one star higher.") }); Harmony val = new Harmony("digi.vargheim.ranching"); val.PatchAll(typeof(Patches)); PatchSeasons(val); ((BaseUnityPlugin)this).Logger.LogInfo((object)"VargheimRanching 1.1.3 loaded."); } private static void Load() { ButcherSet = new HashSet<string>(ButcherItems.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal); string[] array = RancherItems.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { Content.SetGate(array[i].Trim(), "Ranching", StockLevel.Value); } } private void PatchSeasons(Harmony h) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown try { Type type = AccessTools.TypeByName("Seasons.SeasonState"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "GetLivestockProcreationMultiplier", (Type[])null, (Type[])null)); if (!(methodInfo == null)) { h.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "SeasonsMult", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"VargheimRanching: Seasons found, winter herd hook on."); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("VargheimRanching: Seasons hook failed: " + ex.Message)); } } private static void SeasonsMult(ref float __result) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)s_cur != (Object)null && __result <= 0.0001f && WinterMult.Value > 0f && BestRancherNear(((Component)s_cur).transform.position, BreedRange.Value) >= WinterLevel.Value) { __result = WinterMult.Value; } } catch { } } internal static int BestRancherNear(Vector3 pos, float range) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) List<Player> list = new List<Player>(); Player.GetPlayersInRange(pos, range, list); int num = 0; foreach (Player item in list) { num = Math.Max(num, Api.PerkLevelOf(item, "Ranching")); } return num; } private static string PrefabName(GameObject go) { string name = ((Object)go).name; int num = name.IndexOf("(Clone)", StringComparison.Ordinal); return ((num >= 0) ? name.Substring(0, num) : name).Trim(); } internal static bool ButcherItem(string name) { if (!ButcherSet.Contains(name) && name.IndexOf("Meat", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Hide", StringComparison.OrdinalIgnoreCase) < 0) { return name.IndexOf("Pelt", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private void Update() { if (Time.time < _next) { return; } _next = Time.time + 0.5f; try { Player localPlayer = Player.m_localPlayer; Sadle val = (Sadle)(((Object)(object)localPlayer != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val != (Object)null && !Api.HasPerk("Ranching", RiderLevel.Value)) { val = null; } List<Sadle> list = new List<Sadle>(); foreach (KeyValuePair<Sadle, Orig> item in s_boosted) { if ((Object)(object)item.Key != (Object)(object)val) { list.Add(item.Key); } } foreach (Sadle item2 in list) { Restore(item2); } if ((Object)(object)val != (Object)null && !s_boosted.ContainsKey(val)) { Boost(val); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)ex.Message); } } private static void Boost(Sadle s) { Character value = Traverse.Create((object)s).Field("m_character").GetValue<Character>(); if (!((Object)(object)value == (Object)null)) { Orig value2 = new Orig { Run = value.m_runSpeed, Speed = value.m_speed, Swim = value.m_swimSpeed, Stamina = s.m_maxStamina, Regen = s.m_staminaRegen }; float num = 1f + RiderBonus.Value; value.m_runSpeed *= num; value.m_speed *= num; value.m_swimSpeed *= num; s.m_maxStamina *= num; s.m_staminaRegen *= num; s_boosted[s] = value2; } } private static void Restore(Sadle s) { if ((Object)(object)s == (Object)null || !s_boosted.TryGetValue(s, out var value)) { s_boosted.Remove(s); return; } s_boosted.Remove(s); Character value2 = Traverse.Create((object)s).Field("m_character").GetValue<Character>(); if ((Object)(object)value2 != (Object)null) { value2.m_runSpeed = value.Run; value2.m_speed = value.Speed; value2.m_swimSpeed = value.Swim; } s.m_maxStamina = value.Stamina; s.m_staminaRegen = value.Regen; } } } namespace VargheimMysticCrafting { [BepInPlugin("digi.vargheim.mysticcrafting", "VargheimMysticCrafting", "1.0.1")] [BepInDependency("digi.vargheim.professions", "0.4.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { internal sealed class Craft { public string Item; public bool Magic; public HashSet<ItemData> Before; public string SimpleName; public int SimpleCount; } [HarmonyPatch] internal static class Patches { [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Recipe), typeof(bool), typeof(int), typeof(int) })] [HarmonyPostfix] private static void Have(Player __instance, Recipe recipe, ref bool __result) { try { if (__result && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !((Object)(object)recipe == (Object)null) && !((Object)(object)recipe.m_item == (Object)null) && Api.Active) { int num = GemGate(((Object)((Component)recipe.m_item).gameObject).name); if (num > 0 && Api.PerkLevel("Jewelcrafting") < num) { __result = false; } } } catch { } } [HarmonyPatch(typeof(Smelter), "OnAddOre")] [HarmonyPrefix] private static bool FurnaceAdd(Smelter __instance, Humanoid user, ref ItemData item, ref bool __result) { try { if ((Object)(object)user != (Object)(object)Player.m_localPlayer || (Object)(object)user == (Object)null || !Api.Active || Utils.GetPrefabName(((Component)__instance).gameObject) != "JC_Gemstone_Furnace") { return true; } int num = Api.PerkLevel("Jewelcrafting"); int num2 = 0; if (item == null) { Inventory inventory = user.GetInventory(); foreach (ItemConversion item3 in __instance.m_conversion) { if (item3 == null || (Object)(object)item3.m_from == (Object)null || (Object)(object)item3.m_to == (Object)null) { continue; } ItemData item2 = inventory.GetItem(item3.m_from.m_itemData.m_shared.m_name, -1, false); if (item2 != null) { int num3 = GemGate(((Object)((Component)item3.m_to).gameObject).name); if (num3 <= num) { item = item2; return true; } num2 = Math.Max(num2, num3); } } if (num2 == 0) { return true; } } else { num2 = FurnaceGate(__instance, item); if (num2 <= num) { return true; } } if (Time.time - s_lastFurnaceMsg > 2f) { s_lastFurnaceMsg = Time.time; Api.Message("You need Mystic Crafting " + num2 + " to refine that gem."); } __result = false; return false; } catch { return true; } } [HarmonyPatch(typeof(Attack), "GetAttackEitr", new Type[] { })] [HarmonyPostfix] private static void Eitr(Attack __instance, ref float __result) { try { ItemData value = Traverse.Create((object)__instance).Field("m_weapon").GetValue<ItemData>(); if (value != null && value.m_customData != null && value.m_customData.ContainsKey("vp_attuned")) { __result *= 1f - FocusCut.Value; } } catch { } } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] [HarmonyPrefix] private static void CraftPre(InventoryGui __instance, Player player, out Craft __state) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Invalid comparison between Unknown and I4 //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Invalid comparison between Unknown and I4 __state = null; try { Recipe value = Traverse.Create((object)__instance).Field("m_craftRecipe").GetValue<Recipe>(); ItemData value2 = Traverse.Create((object)__instance).Field("m_craftUpgradeItem").GetValue<ItemData>(); if ((Object)(object)value == (Object)null || (Object)(object)value.m_item == (Object)null || value2 != null || (Object)(object)player != (Object)(object)Player.m_localPlayer) { return; } SharedData shared = value.m_item.m_itemData.m_shared; bool flag = ((int)shared.m_skillType == 9 || (int)shared.m_skillType == 10) && shared.m_maxStackSize == 1; bool flag2 = ((Object)((Component)value.m_item).gameObject).name.StartsWith("Simple_", StringComparison.Ordinal); if ((flag && Api.HasPerk("Jewelcrafting", FocusLevel.Value)) || (flag2 && Api.HasPerk("Jewelcrafting", CutterLevel.Value))) { __state = new Craft { Item = ((Object)((Component)value.m_item).gameObject).name, Magic = flag, Before = new HashSet<ItemData>(((Humanoid)player).GetInventory().GetAllItems()) }; if (flag2 && !flag) { __state.SimpleName = shared.m_name; __state.SimpleCount = ((Humanoid)player).GetInventory().CountItems(shared.m_name, -1, true); } } } catch { } } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] [HarmonyPostfix] private static void CraftPost(Player player, Craft __state) { if (__state == null || (Object)(object)player == (Object)null) { return; } try { Inventory inventory = ((Humanoid)player).GetInventory(); if (__state.Magic) { foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem != null && !__state.Before.Contains(allItem) && (Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == __state.Item) { allItem.m_customData["vp_attuned"] = player.GetPlayerName(); } } return; } if (__state.SimpleName == null || inventory.CountItems(__state.SimpleName, -1, true) <= __state.SimpleCount || Random.value >= CutterChance.Value) { return; } string text = "Perfect_" + __state.Item.Substring("Simple_".Length); GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text); GameObject itemPrefab2 = ObjectDB.instance.GetItemPrefab(__state.Item); if (!((Object)(object)itemPrefab == (Object)null) && !((Object)(object)itemPrefab2 == (Object)null)) { string name = itemPrefab2.GetComponent<ItemDrop>().m_itemData.m_shared.m_name; if (inventory.CountItems(name, -1, true) > 0) { inventory.RemoveItem(name, 1, -1, true); inventory.AddItem(itemPrefab, 1); Api.Message("Master cutter: a perfect gem!"); } } } catch { } } } public const string Guid = "digi.vargheim.mysticcrafting"; public const string Version = "1.0.1"; private const string Prof = "Jewelcrafting"; internal static ConfigEntry<int> AdvancedLevel; internal static ConfigEntry<int> FusionLevel; internal static ConfigEntry<int> PerfectLevel; internal static ConfigEntry<int> FocusLevel; internal static ConfigEntry<int> AppraiserLevel; internal static ConfigEntry<int> CutterLevel; internal static ConfigEntry<string> SocketLevels; internal static ConfigEntry<float> FocusCut; internal static ConfigEntry<float> AppraiserBoost; internal static ConfigEntry<float> CutterChance; internal static Plugin Instance; private static float s_lastSocketMsg; internal const string GemFurnace = "JC_Gemstone_Furnace"; private static float s_lastFurnaceMsg; private void Awake() { //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Expected O, but got Unknown //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Expected O, but got Unknown //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Expected O, but got Unknown //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Expected O, but got Unknown //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Expected O, but got Unknown //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Expected O, but got Unknown //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Expected O, but got Unknown //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Expected O, but got Unknown //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Expected O, but got Unknown //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Expected O, but got Unknown Instance = this; AdvancedLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "AdvancedGemsLevel", 35, "Level to cut and upgrade advanced gems."); FusionLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "GemFusionLevel", 50, "Level to craft merged (fused) gems."); PerfectLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "PerfectGemsLevel", 55, "Level to craft perfect gems."); SocketLevels = ((BaseUnityPlugin)this).Config.Bind<string>("Perks", "SocketLevels", "0:1,35:2,55:3", "Most sockets a player can add to an item, by Mystic Crafting level: 'level:sockets', separated by ','."); FocusLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "AttunedFocusLevel", 60, "Attuned focus level."); FocusCut = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "AttunedFocusEitrReduction", 0.1f, "Attuned focus: staffs and magic weapons you craft use this much less eitr."); AppraiserLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "AppraiserLevel", 75, "Appraiser level."); AppraiserBoost = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "AppraiserFusionBoost", 0.25f, "Appraiser: fusion boxes you carry fill this much faster."); CutterLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "MasterCutterLevel", 100, "Master cutter level."); CutterChance = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "MasterCutterChance", 0.1f, "Master cutter: chance a gem you cut comes out perfect."); Content.AddTooltip((Func<ItemData, string>)Tooltip); Api.RegisterLadder("Jewelcrafting", "VargheimMysticCrafting 1.0.1", "Jewelcrafting and Wizardry. Everyone can cut and socket simple gems and add the first socket. Modded mage gear, staffs, wands, rings and necklaces are crafted by mystics, by tier.", (Perk[])(object)new Perk[9] { new Perk(25, "Mystic gear", "All Wizardry gear by tier (staffs, wands, mage armor, robes); rings and necklaces."), new Perk(AdvancedLevel.Value, "Advanced gems", "Cut and upgrade advanced gems; add a second socket."), new Perk(35, "Steady hand", "Better socket success with level (Jewelcrafting)."), new Perk(45, "Careful salvage", "Failed sockets return materials near where the item was made (Jewelcrafting)."), new Perk(FusionLevel.Value, "Gem fusion", "Merge gems into stronger ones."), new Perk(PerfectLevel.Value, "Perfect gems", "Craft perfect gems; add a third socket."), new Perk(FocusLevel.Value, "Attuned focus", "Staffs and magic weapons you craft use " + Mathf.RoundToInt(FocusCut.Value * 100f) + "% less eitr."), new Perk(AppraiserLevel.Value, "Appraiser", "Fusion boxes you carry fill " + Mathf.RoundToInt(AppraiserBoost.Value * 100f) + "% faster."), new Perk(CutterLevel.Value, "Master cutter", Mathf.RoundToInt(CutterChance.Value * 100f) + "% chance a gem you cut comes out perfect.") }); Harmony val = new Harmony("digi.vargheim.mysticcrafting"); val.PatchAll(typeof(Patches)); try { PatchJewelcrafting(val); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Jewelcrafting hooks skipped: " + ex.Message)); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"VargheimMysticCrafting 1.0.1 loaded."); } internal static int GemGate(string prefab) { if (prefab == null) { return 0; } if (prefab.StartsWith("Perfect_", StringComparison.Ordinal)) { return PerfectLevel.Value; } if (prefab.IndexOf("Merged", StringComparison.Ordinal) >= 0) { return FusionLevel.Value; } if (prefab.StartsWith("Advanced_", StringComparison.Ordinal)) { return AdvancedLevel.Value; } return 0; } internal static int SocketCap() { int num = (Api.Active ? Api.PerkLevel("Jewelcrafting") : 100); int num2 = 1; string[] array = SocketLevels.Value.Split(','); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(':'); if (array2.Length == 2 && int.TryParse(array2[0].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && int.TryParse(array2[1].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2) && num >= result) { num2 = Math.Max(num2, result2); } } return num2; } internal static int SocketCount(ItemData item) { if (item == null || item.m_customData == null) { return 0; } foreach (KeyValuePair<string, string> customDatum in item.m_customData) { if (customDatum.Key.EndsWith("Jewelcrafting.Sockets", StringComparison.Ordinal)) { return string.IsNullOrEmpty(customDatum.Value) ? 1 : customDatum.Value.Split(',').Length; } } return 0; } private static string Tooltip(ItemData i) { if (i == null || i.m_customData == null || !i.m_customData.TryGetValue("vp_attuned", out var value)) { return null; } return "<color=#b9a3ff>Attuned</color>: " + Mathf.RoundToInt(FocusCut.Value * 100f) + "% less eitr. Made by " + value; } private static void PatchJewelcrafting(Harmony h) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown Type type = AccessTools.TypeByName("Jewelcrafting.GemStones"); Type type2 = AccessTools.TypeByName("Jewelcrafting.FusionBoxSetup"); MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "CanAddMoreSockets", (Type[])null, (Type[])null) : null); MethodInfo methodInfo2 = ((type2 != null) ? AccessTools.Method(type2, "IncreaseBoxProgress", (Type[])null, (Type[])null) : null); if (methodInfo != null) { h.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "CanAddPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (methodInfo2 != null) { h.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(Plugin), "ProgressPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (type != null) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Jewelcrafting found: socket limit " + ((methodInfo != null) ? "on" : "missing") + ", appraiser " + ((methodInfo2 != null) ? "on" : "missing") + ".")); } } private static void CanAddPostfix(ItemData item, ref bool __result) { try { if (!__result) { return; } int num = SocketCap(); if (SocketCount(item) >= num) { __result = false; if (Time.time - s_lastSocketMsg > 3f) { s_lastSocketMsg = Time.time; Api.Message("You can add " + num + " socket" + ((num == 1) ? "" : "s") + " at your Mystic Crafting level."); } } } catch { } } private static void ProgressPrefix(ref IEnumerable<float> progress) { try { if (progress == null || !Api.HasPerk("Jewelcrafting", AppraiserLevel.Value)) { return; } List<float> list = new List<float>(); foreach (float item in progress) { list.Add(item * (1f + AppraiserBoost.Value)); } progress = list; } catch { } } internal static int FurnaceGate(Smelter s, ItemData item) { if ((Object)(object)s == (Object)null || item == null || s.m_conversion == null) { return 0; } foreach (ItemConversion item2 in s.m_conversion) { if (item2 != null && (Object)(object)item2.m_from != (Object)null && (Object)(object)item2.m_to != (Object)null && item2.m_from.m_itemData.m_shared.m_name == item.m_shared.m_name) { return GemGate(((Object)((Component)item2.m_to).gameObject).name); } } return 0; } } } namespace VargheimMining { [BepInPlugin("digi.vargheim.mining", "VargheimMining", "1.2.0")] [BepInDependency("digi.vargheim.professions", "0.4.0")] public class Plugin : BaseUnityPlugin { [HarmonyPatch] internal static class Patches { [HarmonyPatch(typeof(MineRock5), "DamageArea")] [HarmonyPrefix] private static void Rock5Pre(HitData hit) { s_digger = ((hit != null) ? hit.GetAttacker() : null); } [HarmonyPatch(typeof(MineRock5), "DamageArea")] [HarmonyFinalizer] private static void Rock5Post() { s_digger = null; } [HarmonyPatch(typeof(MineRock), "RPC_Hit")] [HarmonyPrefix] private static void RockPre(HitData hit) { s_digger = ((hit != null) ? hit.GetAttacker() : null); } [HarmonyPatch(typeof(MineRock), "RPC_Hit")] [HarmonyFinalizer] private static void RockPost() { s_digger = null; } [HarmonyPatch(typeof(Destructible), "Destroy")] [HarmonyPrefix] private static void DestrPre(HitData hit) { s_digger = ((hit != null) ? hit.GetAttacker() : null); } [HarmonyPatch(typeof(Destructible), "Destroy")] [HarmonyFinalizer] private static void DestrPost() { s_digger = null; } [HarmonyPatch(typeof(DropTable), "GetDropList", new Type[] { })] [HarmonyPostfix] private static void Drops(List<GameObject> __result) { if ((Object)(object)s_digger == (Object)null) { return; } try { BonusOre(__result); } catch { } } [HarmonyPatch(typeof(Attack), "DoMeleeAttack")] [HarmonyPrefix] private static void MeleePre(Attack __instance, out float __state) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Invalid comparison between Unknown and I4 __state = -1f; ItemData value = Traverse.Create((object)__instance).Field("m_weapon").GetValue<ItemData>(); Humanoid value2 = Traverse.Create((object)__instance).Field("m_character").GetValue<Humanoid>(); if (value != null && (Object)(object)value2 != (Object)null && (Object)(object)value2 == (Object)(object)Player.m_localPlayer && (int)value.m_shared.m_skillType == 12 && Api.HasPerk("Mining", PickLevel.Value)) { __state = value.m_durability; } } [HarmonyPatch(typeof(Attack), "DoMeleeAttack")] [HarmonyPostfix] private static void MeleePost(Attack __instance, float __state) { if (!(__state < 0f)) { ItemData value = Traverse.Create((object)__instance).Field("m_weapon").GetValue<ItemData>(); if (value != null && value.m_durability < __state) { value.m_durability += (__state - value.m_durability) * PickWear.Value; } } } [HarmonyPatch(typeof(Player), "GetMaxCarryWeight")] [HarmonyPostfix] private static void Carry(Player __instance, ref float __result) { if ((Object)(object)__instance == (Object)null || BackWeight.Value <= 0f) { return; } float num = 0f; int num2 = Mathf.Max(1, BackFull.Value - BackStart.Value); for (int i = 0; i < BackList.Length; i++) { float num3 = Mathf.Clamp01((float)(Api.PerkLevelOf(__instance, BackList[i]) - BackStart.Value) / (float)num2); if (num3 > num) { num = num3; } } if (num > 0f) { __result += BackWeight.Value * num; } } [HarmonyPatch(typeof(Inventory), "UpdateTotalWeight")] [HarmonyPostfix] private static void Weight(Inventory __instance, ref float ___m_totalWeight) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || __instance != ((Humanoid)localPlayer).GetInventory() || !Api.HasPerk("Mining", HaulLevel.Value)) { return; } float num = 0f; foreach (ItemData allItem in __instance.GetAllItems()) { if (allItem != null && (Object)(object)allItem.m_dropPrefab != (Object)null && HaulSet.Contains(((Object)allItem.m_dropPrefab).name)) { num += allItem.GetWeight(-1) * HaulFactor.Value; } } ___m_totalWeight = Mathf.Max(0f, ___m_totalWeight - num); } } public const string Guid = "digi.vargheim.mining"; public const string Version = "1.2.0"; internal const string Flux = "VP_TemperingFlux"; internal static ConfigEntry<int> FluxLevel; internal static ConfigEntry<int> FluxAmount; internal static ConfigEntry<string> FluxRecipe; private const string Prof = "Mining"; internal static ConfigEntry<int> ProspectLevel; internal static ConfigEntry<int> RichLevel; internal static ConfigEntry<int> PickLevel; internal static ConfigEntry<int> HaulLevel; internal static ConfigEntry<int> CrewLevel; internal static ConfigEntry<int> MotherLevel; internal static ConfigEntry<float> ProspectRange; internal static ConfigEntry<float> RichChance; internal static ConfigEntry<float> PickWear; internal static ConfigEntry<float> HaulFactor; internal static ConfigEntry<float> CrewRange; internal static ConfigEntry<float> CrewChance; internal static ConfigEntry<float> MotherChance; internal static ConfigEntry<string> Ores; internal static ConfigEntry<string> Bars; internal static ConfigEntry<string> BackProfs; internal static ConfigEntry<int> BackStart; internal static ConfigEntry<int> BackFull; internal static ConfigEntry<float> BackWeight; internal static string[] BackList = new string[0]; internal static HashSet<string> OreSet = new HashSet<string>(StringComparer.Ordinal); internal static HashSet<string> HaulSet = new HashSet<string>(StringComparer.Ordinal); internal static Plugin Instance; private float _next; private readonly Dictionary<int, GameObject> _glows = new Dictionary<int, GameObject>(); [ThreadStatic] internal static Character s_digger; private void Awake() { //IL_03e7: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Expected O, but got Unknown //IL_03fb: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Expected O, but got Unknown //IL_0481: Unknown result type (might be due to invalid IL or missing references) //IL_0487: Expected O, but got Unknown //IL_04b1: Unknown result type (might be due to invalid IL or missing references) //IL_04b7: Expected O, but got Unknown //IL_04e6: Unknown result type (might be due to invalid IL or missing references) //IL_04ec: Expected O, but got Unknown //IL_04fa: Unknown result type (might be due to invalid IL or missing references) //IL_0500: Expected O, but got Unknown //IL_052f: Unknown result type (might be due to invalid IL or missing references) //IL_0535: Expected O, but got Unknown //IL_0590: Unknown result type (might be due to invalid IL or missing references) //IL_0596: Expected O, but got Unknown //IL_05c0: Unknown result type (might be due to invalid IL or missing references) //IL_05c6: Expected O, but got Unknown //IL_05d0: Unknown result type (might be due to invalid IL or missing references) Instance = this; ProspectLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "ProspectorLevel", 25, "Prospector: ore deposits near you glow while you hold a pickaxe."); ProspectRange = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "ProspectorRange", 30f, "Prospector range in metres."); FluxLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "TemperingFluxLevel", 35, "Tempering flux: level to make Tempering Flux, which smiths need to upgrade modded weapons and armor."); FluxRecipe = ((BaseUnityPlugin)this).Config.Bind<string>("Perks", "TemperingFluxRecipe", "Coal:4,Resin:2,Stone:4", "Materials for Tempering Flux (at a workbench)."); FluxAmount = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "TemperingFluxAmount", 4, "Tempering Flux per craft."); Content.AddItem("Coal", "VP_TemperingFlux", "Tempering Flux", "Crushed coal and stone bound with resin. Smiths need it to upgrade modded weapons and armor. Only a miner can make it.", (Action<SharedData>)delegate(SharedData s) { s.m_weight = 0.5f; s.m_maxStackSize = 50; }); Content.AddRecipe("VP_TemperingFlux", "piece_workbench", 1, Math.Max(1, FluxAmount.Value), FluxRecipe.Value, "Mining", FluxLevel.Value); RichLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "RichVeinLevel", 35, "Rich vein level."); RichChance = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "RichVeinChance", 0.15f, "Rich vein: chance of one extra ore per ore drop."); PickLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "ToughPickLevel", 45, "Tough pick level."); PickWear = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "ToughPickWearReduction", 0.3f, "Tough pick: pickaxe wear reduced by this much (0.3 = 30% less)."); HaulLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "OreHaulerLevel", 60, "Ore hauler level."); HaulFactor = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "OreHaulerWeightReduction", 0.25f, "Ore hauler: ore and bars weigh this much less in the miner's inventory."); CrewLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "CrewBossLevel", 75, "Crew boss level."); CrewRange = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "CrewBossRange", 15f, "Crew boss: group members within this range get the bonus."); CrewChance = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "CrewBossChance", 0.25f, "Crew boss: chance of one extra ore per ore drop for group members near a crew boss."); MotherLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "MotherlodeLevel", 100, "Motherlode level."); MotherChance = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "MotherlodeChance", 0.25f, "Motherlode: chance that a piece of a deposit you break drops double ore."); Ores = ((BaseUnityPlugin)this).Config.Bind<string>("Perks", "OreItems", "CopperOre,TinOre,IronScrap,IronOre,SilverOre,BlackMetalScrap,FlametalOre,FlametalOreNew,CopperScrap,Obsidian", "Items that count as ore for these perks."); Bars = ((BaseUnityPlugin)this).Config.Bind<string>("Perks", "HaulItems", "Copper,Tin,Bronze,Iron,Silver,BlackMetal,Flametal,FlametalNew,CopperOre,TinOre,IronScrap,IronOre,SilverOre,BlackMetalScrap,FlametalOre,FlametalOreNew,CopperScrap", "Items made lighter by Ore hauler."); BackStart = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "StrongBackStartLevel", 20, "Strong back: carry weight starts growing at this level."); BackFull = ((BaseUnityPlugin)this).Config.Bind<int>("Perks", "StrongBackFullLevel", 50, "Strong back: level where the full bonus is reached."); BackWeight = ((BaseUnityPlugin)this).Config.Bind<float>("Perks", "StrongBackWeight", 150f, "Strong back: carry weight added at the full level (a Ymir's Belt is +150)."); BackProfs = ((BaseUnityPlugin)this).Config.Bind<string>("Perks", "StrongBackProfessions", "Mining,Lumberjacking,Farming", "Professions that get Strong back. The best one counts; they don't stack."); Load(); ((BaseUnityPlugin)this).Config.SettingChanged += delegate { Load(); }; Api.RegisterLadder("Mining", "VargheimMining 1.2.0", "Smoothbrain Mining: up to x3 damage and x2 yield at 100; deposits can break apart from level 50.", (Perk[])(object)new Perk[9] { new Perk(ProspectLevel.Value, "Prospector", "With a pickaxe in hand, ore deposits within " + ProspectRange.Value + " m glow faintly."), new Perk(10, "Tier flux", "Make the Miner's tier material at a workbench, one per biome from that biome's ore and coal (Flint Grit at 10, Copper Flux at 25, Bog Iron Flux at 35 ...). Smiths need it for every modded weapon, shield and metal armor of that tier, plus 1 per upgrade."), new Perk(BackStart.Value, "Strong back", "Carry weight grows from level " + BackStart.Value + " to +" + Mathf.RoundToInt(BackWeight.Value) + " at " + BackFull.Value + " (a Ymir's Belt worth). Lumberjacks and Farmers get the same; the best one counts."), new Perk(RichLevel.Value, "Rich vein", Pct(RichChance.Value) + " chance of one extra ore per piece mined."), new Perk(PickLevel.Value, "Tough pick", "Pickaxe wear " + Pct(PickWear.Value) + " lower."), new Perk(50, "Break apart", "Deposits can break apart in one go (Smoothbrain Mining)."), new Perk(HaulLevel.Value, "Ore hauler", "Ore and bars weigh " + Pct(HaulFactor.Value) + " less in your inventory."), new Perk(CrewLevel.Value, "Crew boss", "Group members mining within " + CrewRange.Value + " m of you get " + Pct(CrewChance.Value) + " more ore."), new Perk(MotherLevel.Value, "Motherlode", Pct(MotherChance.Value) + " chance a piece of a deposit you break drops double ore.") }); new Harmony("digi.vargheim.mining").PatchAll(typeof(Patches)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"VargheimMining 1.2.0 loaded."); } internal static string Pct(float f) { return Mathf.RoundToInt(f * 100f) + "%"; } private static void Load() { BackList = (BackProfs.Value ?? "").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntri