Decompiled source of Metalbound v0.20.3

plugins/Metalbound/Metalbound.dll

Decompiled 7 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Metalbound")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.20.3.0")]
[assembly: AssemblyInformationalVersion("0.20.3")]
[assembly: AssemblyProduct("Metalbound")]
[assembly: AssemblyTitle("Metalbound")]
[assembly: AssemblyVersion("0.20.3.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 Metalbound
{
	[BepInPlugin("com.keeto.valheim.metalbound", "Metalbound", "0.20.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		private enum MetalType
		{
			Iron,
			Steel,
			Pewter,
			Tin,
			Copper,
			Combined
		}

		private enum AllomancerType
		{
			Unawakened,
			IronMisting,
			SteelMisting,
			PewterMisting,
			TinMisting,
			CopperMisting,
			Mistborn
		}

		private enum CoinshotAmmoType
		{
			Coin,
			BronzeNail,
			IronNail
		}

		[HarmonyPatch(typeof(Player), "PlayerAttackInput")]
		private static class PlayerAttackInputPatch
		{
			private static bool Prefix(Player __instance)
			{
				return !ShouldBlockVanillaAttacks(__instance);
			}
		}

		[HarmonyPatch(typeof(Character), "UpdateGroundContact")]
		private static class LandingRollGroundContactPatch
		{
			private static void Prefix(Character __instance)
			{
				if (!((Object)(object)Instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !(GroundContactField == null) && (bool)GroundContactField.GetValue(__instance))
				{
					Instance.ActivateBufferedLandingRoll(Player.m_localPlayer);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "ConsumeItem")]
		private static class ConsumeTincturePatch
		{
			private static bool Prefix(Player __instance, ItemData item, ref bool __result)
			{
				if (IsLerasium(item) && (Object)(object)Instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
				{
					Instance.EnsureAllomancerTypeLoaded(__instance);
					if (Instance.allomancerType == AllomancerType.Mistborn)
					{
						ShowCenterMessage("You are already Mistborn.");
						__result = false;
						return false;
					}
					return true;
				}
				MetalType? consumableMetal = GetConsumableMetal(item);
				if (!consumableMetal.HasValue || (Object)(object)Instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return true;
				}
				Instance.EnsureAllomancerTypeLoaded(__instance);
				if (consumableMetal.Value != MetalType.Combined && !Instance.HasMetalAccess(consumableMetal.Value))
				{
					ShowCenterMessage(consumableMetal.Value.ToString() + " is not one of your Allomantic metals.");
					__result = false;
					return false;
				}
				if (consumableMetal.Value == MetalType.Combined && Instance.allomancerType == AllomancerType.Unawakened)
				{
					ShowCenterMessage("You have not awakened Allomancy.");
					__result = false;
					return false;
				}
				Instance.EnsureReserveLoaded(__instance);
				if (!((consumableMetal.Value == MetalType.Combined) ? Instance.AllReservesFull() : (Instance.GetReserve(consumableMetal.Value) >= Instance.maximumReserve.Value - 0.01f)))
				{
					return true;
				}
				ShowCenterMessage((consumableMetal.Value == MetalType.Combined) ? "All metal reserves are already full." : (consumableMetal.Value.ToString() + " reserve is already full."));
				__result = false;
				return false;
			}

			private static void Postfix(Player __instance, ItemData item, bool __result)
			{
				if (__result && IsLerasium(item) && (Object)(object)Instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
				{
					Instance.BeginLerasiumAscension(__instance);
					return;
				}
				MetalType? consumableMetal = GetConsumableMetal(item);
				if (__result && consumableMetal.HasValue && (Object)(object)Instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
				{
					Instance.EnsureReserveLoaded(__instance);
					Instance.RestoreReserve(consumableMetal.Value);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "OnDeath")]
		private static class AllomanticDeathPatch
		{
			private static void Prefix(Player __instance)
			{
				if ((Object)(object)Instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
				{
					Instance.HandleAllomanticDeath(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(Container), "AddDefaultItems")]
		private static class LerasiumChestLootPatch
		{
			private static void Postfix(Container __instance)
			{
				if ((Object)(object)Instance == (Object)null || (Object)(object)ObjectDB.instance == (Object)null || Random.value > Instance.lerasiumChestChance.Value)
				{
					return;
				}
				string text = ((Object)__instance).name.ToLowerInvariant();
				if (!text.Contains("chest") && !text.Contains("treasure"))
				{
					return;
				}
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				if (!((Object)(object)component != (Object)null) || !component.IsValid() || component.IsOwner())
				{
					GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("MetalboundLerasiumNugget");
					Inventory inventory = __instance.GetInventory();
					if ((Object)(object)itemPrefab != (Object)null && inventory != null && inventory.AddItem(itemPrefab, 1))
					{
						((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Added a Lerasium Bead to " + ((Object)__instance).name + "."));
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "GetRunSpeedFactor")]
		private static class PewterRunSpeedPatch
		{
			private static void Postfix(Player __instance, ref float __result)
			{
				if ((Object)(object)Instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && Instance.IsPewterActive())
				{
					__result *= 1f + Instance.pewterRunSpeedBonus.Value * Instance.GetPewterBonusMultiplier();
				}
			}
		}

		[HarmonyPatch(typeof(Player), "GetStealthFactor")]
		private static class CoppercloudStealthPatch
		{
			private static void Postfix(Player __instance, ref float __result)
			{
				if ((Object)(object)Instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && Instance.IsCopperActive())
				{
					__result *= Instance.GetCopperVisibilityMultiplier();
				}
			}
		}

		[HarmonyPatch(typeof(Player), "GetJogSpeedFactor")]
		private static class PewterJogSpeedPatch
		{
			private static void Postfix(Player __instance, ref float __result)
			{
				if ((Object)(object)Instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && Instance.IsPewterActive())
				{
					__result *= 1f + Instance.pewterRunSpeedBonus.Value * Instance.GetPewterBonusMultiplier();
				}
			}
		}

		[HarmonyPatch(typeof(Player), "UseStamina")]
		private static class PewterStaminaPatch
		{
			private static void Prefix(Player __instance, ref float v)
			{
				if ((Object)(object)Instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && Instance.IsPewterActive())
				{
					float num = Mathf.Clamp(Instance.pewterStaminaReduction.Value * Instance.GetPewterBonusMultiplier(), 0f, 0.9f);
					v *= 1f - num;
				}
			}
		}

		[HarmonyPatch(typeof(Player), "GetMaxCarryWeight")]
		private static class PewterCarryWeightPatch
		{
			private static void Postfix(Player __instance, ref float __result)
			{
				if ((Object)(object)Instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && Instance.IsPewterActive())
				{
					__result += Instance.pewterCarryWeightBonus.Value * Instance.GetPewterBonusMultiplier();
				}
			}
		}

		[HarmonyPatch(typeof(Character), "Jump")]
		private static class PewterJumpPatch
		{
			private static void Prefix(Character __instance, ref float ___m_jumpForce, out float __state)
			{
				__state = ___m_jumpForce;
				if ((Object)(object)Instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && Instance.IsPewterActive())
				{
					___m_jumpForce *= 1f + Instance.pewterJumpBonus.Value * Instance.GetPewterBonusMultiplier();
				}
			}

			private static void Postfix(ref float ___m_jumpForce, float __state)
			{
				___m_jumpForce = __state;
			}
		}

		[HarmonyPatch(typeof(Character), "Damage")]
		private static class PewterPhysicalDamagePatch
		{
			private static void Prefix(Character __instance, HitData hit)
			{
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Invalid comparison between Unknown and I4
				if ((Object)(object)Instance == (Object)null || hit == null)
				{
					return;
				}
				Character attacker = hit.GetAttacker();
				bool flag = (Object)(object)__instance == (Object)(object)Player.m_localPlayer && Instance.IsPewterActive() && (int)hit.m_hitType == 3 && hit.m_damage.m_damage > 0f;
				Instance.ApplyLandingRollDamageReduction(__instance, hit);
				if (flag)
				{
					float num = Mathf.Clamp(Instance.pewterFallDamageReduction.Value * Instance.GetPewterBonusMultiplier(), 0f, 0.95f);
					hit.m_damage.m_damage *= 1f - num;
				}
				if ((Object)(object)attacker == (Object)(object)Player.m_localPlayer && Instance.IsPewterActive())
				{
					ScalePhysicalDamage(hit, 1f + Instance.pewterMeleeDamageBonus.Value * Instance.GetPewterBonusMultiplier());
				}
				if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && Instance.IsPewterActive())
				{
					float num2 = Mathf.Clamp(Instance.pewterPoisonResistance.Value * Instance.GetPewterBonusMultiplier(), 0f, 0.95f);
					hit.m_damage.m_poison *= 1f - num2;
					if (!flag)
					{
						float num3 = Mathf.Clamp(Instance.pewterPhysicalResistance.Value * Instance.GetPewterBonusMultiplier(), 0f, 0.9f);
						ScalePhysicalDamage(hit, 1f - num3);
					}
					float num4 = Mathf.Clamp(Instance.pewterKnockbackResistance.Value * Instance.GetPewterBonusMultiplier(), 0f, 0.95f);
					hit.m_pushForce *= 1f - num4;
				}
			}
		}

		public const string PluginGuid = "com.keeto.valheim.metalbound";

		public const string PluginName = "Metalbound";

		public const string PluginVersion = "0.20.3";

		private const string ReserveDataKey = "com.keeto.valheim.metalbound.reserve";

		private const string TincturePrefabName = "MetalboundTincture";

		private const string IronVialPrefabName = "MetalboundIronVial";

		private const string SteelVialPrefabName = "MetalboundSteelVial";

		private const string PewterVialPrefabName = "MetalboundPewterVial";

		private const string TinVialPrefabName = "MetalboundTinVial";

		private const string CopperVialPrefabName = "MetalboundCopperVial";

		private const string LerasiumPrefabName = "MetalboundLerasiumNugget";

		private const string AllomancerTypeDataKey = "com.keeto.valheim.metalbound.allomancer_type";

		private const string LerasiumPendingDataKey = "com.keeto.valheim.metalbound.lerasium_pending";

		private const string LerasiumRespawnMessageDataKey = "com.keeto.valheim.metalbound.lerasium_respawn_message";

		private const string IronReserveDataKey = "com.keeto.valheim.metalbound.reserve.iron";

		private const string SteelReserveDataKey = "com.keeto.valheim.metalbound.reserve.steel";

		private const string PewterReserveDataKey = "com.keeto.valheim.metalbound.reserve.pewter";

		private const string TinReserveDataKey = "com.keeto.valheim.metalbound.reserve.tin";

		private const string CopperReserveDataKey = "com.keeto.valheim.metalbound.reserve.copper";

		private static readonly FieldInfo MaxAirAltitudeField = typeof(Character).GetField("m_maxAirAltitude", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly MethodInfo DodgeMethod = typeof(Player).GetMethod("Dodge", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(Vector3) }, null);

		private static readonly FieldInfo GroundContactField = typeof(Character).GetField("m_groundContact", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly string[] DefaultMetalTokens = new string[11]
		{
			"copper", "tin", "bronze", "iron", "silver", "black metal", "blackmetal", "flametal", "metal", "chain",
			"coin"
		};

		private ConfigEntry<KeyboardShortcut> modeKey;

		private ConfigEntry<KeyboardShortcut> pushKey;

		private ConfigEntry<KeyboardShortcut> pullKey;

		private ConfigEntry<KeyboardShortcut> throwCoinKey;

		private ConfigEntry<KeyboardShortcut> coinshotKey;

		private ConfigEntry<KeyboardShortcut> refillReserveKey;

		private ConfigEntry<KeyboardShortcut> metalWheelKey;

		private ConfigEntry<KeyboardShortcut> tinFocusKey;

		private ConfigEntry<KeyboardShortcut> flareKey;

		private ConfigEntry<float> targetRange;

		private ConfigEntry<float> acceleration;

		private ConfigEntry<float> maximumSpeed;

		private ConfigEntry<float> coinThrowSpeed;

		private ConfigEntry<float> coinshotSpeed;

		private ConfigEntry<float> coinshotDamage;

		private ConfigEntry<float> bronzeNailDamage;

		private ConfigEntry<float> ironNailDamage;

		private ConfigEntry<float> coinshotLifetime;

		private ConfigEntry<float> coinshotCooldown;

		private ConfigEntry<float> maximumReserve;

		private ConfigEntry<float> startingReserve;

		private ConfigEntry<float> metalSightDrain;

		private ConfigEntry<float> lockedTargetDrain;

		private ConfigEntry<float> pushPullDrain;

		private ConfigEntry<float> coinshotReserveCost;

		private ConfigEntry<float> pewterDrain;

		private ConfigEntry<float> tinDrain;

		private ConfigEntry<float> copperDrain;

		private ConfigEntry<float> copperVisibilityMultiplier;

		private ConfigEntry<float> tinVisionRange;

		private ConfigEntry<float> tinVisionIntensity;

		private ConfigEntry<float> tinEnemySenseRange;

		private ConfigEntry<int> tinEnemySenseLimit;

		private ConfigEntry<float> tinEnemyGlowScale;

		private ConfigEntry<float> tinFocusZoom;

		private ConfigEntry<float> tinProjectileSenseRange;

		private ConfigEntry<float> flarePowerMultiplier;

		private ConfigEntry<float> flarePewterMultiplier;

		private ConfigEntry<float> flareTinMultiplier;

		private ConfigEntry<float> flareDrainMultiplier;

		private ConfigEntry<float> pewterRunSpeedBonus;

		private ConfigEntry<float> pewterJumpBonus;

		private ConfigEntry<float> pewterStaminaReduction;

		private ConfigEntry<float> pewterMeleeDamageBonus;

		private ConfigEntry<float> pewterPhysicalResistance;

		private ConfigEntry<float> pewterCarryWeightBonus;

		private ConfigEntry<float> pewterKnockbackResistance;

		private ConfigEntry<float> pewterFallDamageReduction;

		private ConfigEntry<float> pewterPoisonResistance;

		private ConfigEntry<bool> showReserveBar;

		private ConfigEntry<bool> soundsEnabled;

		private ConfigEntry<float> soundVolume;

		private ConfigEntry<bool> windEffectEnabled;

		private ConfigEntry<float> windEffectIntensity;

		private ConfigEntry<float> looseCoinFlightSpeed;

		private ConfigEntry<float> coinBraceDistance;

		private ConfigEntry<float> safeDescentSpeed;

		private ConfigEntry<float> fallProtectionGrace;

		private ConfigEntry<float> landingRollGroundWindow;

		private ConfigEntry<float> landingRollInputBuffer;

		private ConfigEntry<float> landingRollFullReductionHeight;

		private ConfigEntry<float> landingRollBaseReduction;

		private ConfigEntry<float> landingRollStepDistance;

		private ConfigEntry<float> landingRollStepReduction;

		private ConfigEntry<float> landingRollMinimumReduction;

		private ConfigEntry<float> mistingChanceOnDeath;

		private ConfigEntry<float> lerasiumChestChance;

		private ConfigEntry<float> targetingConeDegrees;

		private ConfigEntry<int> maximumVisibleLines;

		private ConfigEntry<float> lineChestOffset;

		private ConfigEntry<string> extraMetalTokens;

		private LineRenderer anchorLine;

		private readonly List<LineRenderer> ambientLines = new List<LineRenderer>();

		private readonly List<Character> sensedTinEnemies = new List<Character>();

		private readonly List<Transform> sensedIncomingProjectiles = new List<Transform>();

		private Material lineMaterial;

		private ParticleSystem windParticles;

		private Material windMaterial;

		private Transform currentAnchor;

		private Transform lockedAnchor;

		private bool wasPushHeld;

		private bool wasPullHeld;

		private float lastUpwardAssistTime = float.NegativeInfinity;

		private float ironReserve;

		private float steelReserve;

		private float pewterReserve;

		private float tinReserve;

		private float copperReserve;

		private float lastReserveSaveTime;

		private float lastEmptyMessageTime = float.NegativeInfinity;

		private float lastCoinshotTime = float.NegativeInfinity;

		private bool landingRollArmed;

		private float landingRollExpiresAt = float.NegativeInfinity;

		private float armedLandingRollReduction;

		private bool landingRollRequested;

		private float landingRollRequestExpiresAt = float.NegativeInfinity;

		private Player reserveOwner;

		private Player allomancerOwner;

		private Player awakeningMessageOwner;

		private float awakeningMessageReadyTime = float.PositiveInfinity;

		private AllomancerType allomancerType;

		private bool reserveDirty;

		private bool steelBurning = true;

		private bool ironBurning = true;

		private bool pewterBurning;

		private bool tinBurning;

		private bool copperBurning;

		private GameObject tinVisionObject;

		private GameObject tinDemisterObject;

		private StatusEffect tinFinderEffect;

		private bool tinFinderAdded;

		private Camera tinFocusCamera;

		private float tinFocusBaseFov;

		private bool tinFocusActive;

		private CoinshotAmmoType selectedCoinshotAmmo;

		private bool metalWheelWasHeld;

		private Texture2D metalWheelTexture;

		private Texture2D tinSenseGlowTexture;

		private Vector2 metalWheelSelector;

		private readonly HashSet<string> missingSoundPrefabs = new HashSet<string>();

		private Harmony harmony;

		internal static Plugin Instance { get; private set; }

		private void Awake()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Expected O, but got Unknown
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Expected O, but got Unknown
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Expected O, but got Unknown
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Expected O, but got Unknown
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Expected O, but got Unknown
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Expected O, but got Unknown
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Expected O, but got Unknown
			//IL_037f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0389: Expected O, but got Unknown
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c7: Expected O, but got Unknown
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Expected O, but got Unknown
			//IL_0439: Unknown result type (might be due to invalid IL or missing references)
			//IL_0443: Expected O, but got Unknown
			//IL_0477: Unknown result type (might be due to invalid IL or missing references)
			//IL_0481: Expected O, but got Unknown
			//IL_04b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bf: Expected O, but got Unknown
			//IL_04e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f3: Expected O, but got Unknown
			//IL_0527: Unknown result type (might be due to invalid IL or missing references)
			//IL_0531: Expected O, but got Unknown
			//IL_0565: Unknown result type (might be due to invalid IL or missing references)
			//IL_056f: Expected O, but got Unknown
			//IL_05a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ad: Expected O, but got Unknown
			//IL_05e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_05eb: Expected O, but got Unknown
			//IL_061f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0629: Expected O, but got Unknown
			//IL_065d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0667: Expected O, but got Unknown
			//IL_069b: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a5: Expected O, but got Unknown
			//IL_06d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e3: Expected O, but got Unknown
			//IL_0717: Unknown result type (might be due to invalid IL or missing references)
			//IL_0721: Expected O, but got Unknown
			//IL_0755: Unknown result type (might be due to invalid IL or missing references)
			//IL_075f: Expected O, but got Unknown
			//IL_0793: Unknown result type (might be due to invalid IL or missing references)
			//IL_079d: Expected O, but got Unknown
			//IL_07d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07db: Expected O, but got Unknown
			//IL_080f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0819: Expected O, but got Unknown
			//IL_084d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0857: Expected O, but got Unknown
			//IL_088b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0895: Expected O, but got Unknown
			//IL_08c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_08d3: Expected O, but got Unknown
			//IL_0949: Unknown result type (might be due to invalid IL or missing references)
			//IL_0953: Expected O, but got Unknown
			//IL_09a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_09b2: Expected O, but got Unknown
			//IL_09e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_09f0: Expected O, but got Unknown
			//IL_0a24: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a2e: Expected O, but got Unknown
			//IL_0a62: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a6c: Expected O, but got Unknown
			//IL_0aa0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0aaa: Expected O, but got Unknown
			//IL_0ade: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ae8: Expected O, but got Unknown
			//IL_0b1c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b26: Expected O, but got Unknown
			//IL_0b5a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b64: Expected O, but got Unknown
			//IL_0b98: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ba2: Expected O, but got Unknown
			//IL_0bd6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0be0: Expected O, but got Unknown
			//IL_0c14: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c1e: Expected O, but got Unknown
			//IL_0c52: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c5c: Expected O, but got Unknown
			//IL_0c90: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c9a: Expected O, but got Unknown
			//IL_0cce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cd8: Expected O, but got Unknown
			//IL_0d0c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d16: Expected O, but got Unknown
			//IL_0d4a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d54: Expected O, but got Unknown
			//IL_0d88: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d92: Expected O, but got Unknown
			//IL_0dc6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0dd0: Expected O, but got Unknown
			//IL_0e04: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e0e: Expected O, but got Unknown
			//IL_0e42: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e4c: Expected O, but got Unknown
			//IL_0e80: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e8a: Expected O, but got Unknown
			//IL_0ebe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ec8: Expected O, but got Unknown
			//IL_0efc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f06: Expected O, but got Unknown
			//IL_0f3a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f44: Expected O, but got Unknown
			//IL_0f78: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f82: Expected O, but got Unknown
			//IL_0faf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fb9: Expected O, but got Unknown
			//IL_0fed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ff7: Expected O, but got Unknown
			Instance = this;
			modeKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "Allomancy mode", new KeyboardShortcut((KeyCode)308, Array.Empty<KeyCode>()), "Hold this key to reveal and use metal anchors.");
			pushKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "Push", new KeyboardShortcut((KeyCode)323, Array.Empty<KeyCode>()), "Push away from the selected metal anchor while Allomancy mode is held.");
			pullKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "Pull", new KeyboardShortcut((KeyCode)324, Array.Empty<KeyCode>()), "Pull toward the selected metal anchor while Allomancy mode is held.");
			throwCoinKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "Throw coin", new KeyboardShortcut((KeyCode)103, Array.Empty<KeyCode>()), "Throw one coin as a temporary metal anchor.");
			coinshotKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "Coinshot", new KeyboardShortcut((KeyCode)114, Array.Empty<KeyCode>()), "While Allomancy mode is held, fire one selected ammunition item as a damaging projectile.");
			refillReserveKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "Refill metal reserve", new KeyboardShortcut((KeyCode)118, Array.Empty<KeyCode>()), "Consume one Allomantic Tincture from inventory to refill all accessible reserves.");
			metalWheelKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "Metal wheel", new KeyboardShortcut((KeyCode)113, Array.Empty<KeyCode>()), "Hold to open the wheel, then click an unlocked metal to toggle it.");
			tinFocusKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "Tin focus", new KeyboardShortcut((KeyCode)122, Array.Empty<KeyCode>()), "Hold while burning Tin to focus and zoom your vision.");
			flareKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "Flare metals", new KeyboardShortcut((KeyCode)301, Array.Empty<KeyCode>()), "Hold to flare every currently burning accessible metal.");
			maximumReserve = ((BaseUnityPlugin)this).Config.Bind<float>("Reserve", "Maximum reserve (base)", 120f, new ConfigDescription("Maximum amount of metal reserve.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 1000f), Array.Empty<object>()));
			startingReserve = ((BaseUnityPlugin)this).Config.Bind<float>("Reserve", "Starting reserve (new characters)", 120f, new ConfigDescription("Reserve given the first time Metalbound stores data on a character.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f), Array.Empty<object>()));
			metalSightDrain = ((BaseUnityPlugin)this).Config.Bind<float>("Reserve", "Metal sight drain per second", 0.25f, new ConfigDescription("Reserve burned per second while metal lines are active.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			lockedTargetDrain = ((BaseUnityPlugin)this).Config.Bind<float>("Reserve", "Locked target drain per second", 0.1f, new ConfigDescription("Additional reserve burned per second while an anchor is locked.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			pushPullDrain = ((BaseUnityPlugin)this).Config.Bind<float>("Reserve", "Push pull drain per second", 4f, new ConfigDescription("Reserve burned per second while Push or Pull applies force.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			coinshotReserveCost = ((BaseUnityPlugin)this).Config.Bind<float>("Reserve", "Coinshot reserve cost", 6f, new ConfigDescription("Reserve burned by each Coinshot in addition to its ammunition.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f), Array.Empty<object>()));
			pewterDrain = ((BaseUnityPlugin)this).Config.Bind<float>("Pewter", "Reserve drain per second", 1.5f, new ConfigDescription("Pewter reserve burned continuously while Pewter is active.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			tinDrain = ((BaseUnityPlugin)this).Config.Bind<float>("Tin", "Reserve drain per second", 0.25f, new ConfigDescription("Tin reserve burned continuously while enhanced senses are active.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			copperDrain = ((BaseUnityPlugin)this).Config.Bind<float>("Copper", "Reserve drain per second", 0.4f, new ConfigDescription("Copper reserve burned continuously while the Coppercloud is active.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			copperVisibilityMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Copper", "Enemy visibility multiplier", 0.35f, new ConfigDescription("Multiplier applied to enemy detection visibility while burning Copper.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>()));
			tinVisionRange = ((BaseUnityPlugin)this).Config.Bind<float>("Tin", "Vision range", 18f, new ConfigDescription("Range of the local low-light vision effect while burning Tin.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 40f), Array.Empty<object>()));
			tinVisionIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Tin", "Vision intensity", 0.8f, new ConfigDescription("Brightness of the local low-light vision effect while burning Tin.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>()));
			tinEnemySenseRange = ((BaseUnityPlugin)this).Config.Bind<float>("Tin", "Enemy sense range", 30f, new ConfigDescription("Range at which burning Tin reveals nearby hostile creatures.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 80f), Array.Empty<object>()));
			tinEnemySenseLimit = ((BaseUnityPlugin)this).Config.Bind<int>("Tin", "Enemy sense limit", 12, new ConfigDescription("Maximum nearby hostile creatures shown by Tin senses.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 40), Array.Empty<object>()));
			tinEnemyGlowScale = ((BaseUnityPlugin)this).Config.Bind<float>("Tin", "Enemy glow scale", 1.6f, new ConfigDescription("Size multiplier for Tin's through-wall enemy sensory glows.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 4f), Array.Empty<object>()));
			tinFocusZoom = ((BaseUnityPlugin)this).Config.Bind<float>("Tin", "Focus zoom", 0.55f, new ConfigDescription("Field-of-view multiplier while holding Tin Focus.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 0.95f), Array.Empty<object>()));
			tinProjectileSenseRange = ((BaseUnityPlugin)this).Config.Bind<float>("Tin", "Projectile sense range", 25f, new ConfigDescription("Range at which burning Tin warns about incoming projectiles.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 80f), Array.Empty<object>()));
			flarePowerMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Flaring", "Iron and Steel force multiplier", 1.6f, new ConfigDescription("Push and Pull force multiplier while flaring.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 4f), Array.Empty<object>()));
			flarePewterMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Flaring", "Pewter bonus multiplier", 1.75f, new ConfigDescription("Multiplier applied to Pewter bonuses while flaring.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 4f), Array.Empty<object>()));
			flareTinMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Flaring", "Tin senses multiplier", 1.5f, new ConfigDescription("Multiplier applied to Tin vision and awareness ranges while flaring.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 4f), Array.Empty<object>()));
			flareDrainMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Flaring", "Reserve drain multiplier", 3.5f, new ConfigDescription("Multiplier applied to reserve consumption while flaring.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
			pewterRunSpeedBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Pewter", "Run speed bonus", 0.3f, new ConfigDescription("Fractional run and jog speed bonus while burning Pewter.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			pewterJumpBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Pewter", "Jump height bonus", 0.15f, new ConfigDescription("Fractional jump-force bonus while burning Pewter.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			pewterStaminaReduction = ((BaseUnityPlugin)this).Config.Bind<float>("Pewter", "Stamina use reduction", 0.2f, new ConfigDescription("Fractional reduction to stamina costs while burning Pewter.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.9f), Array.Empty<object>()));
			pewterMeleeDamageBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Pewter", "Physical damage bonus", 0.15f, new ConfigDescription("Fractional bonus to physical damage dealt while burning Pewter.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			pewterPhysicalResistance = ((BaseUnityPlugin)this).Config.Bind<float>("Pewter", "Physical damage resistance", 0.15f, new ConfigDescription("Fraction of incoming physical damage prevented while burning Pewter.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.9f), Array.Empty<object>()));
			pewterCarryWeightBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Pewter", "Carry weight bonus", 75f, new ConfigDescription("Additional carry weight while burning Pewter.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f), Array.Empty<object>()));
			pewterKnockbackResistance = ((BaseUnityPlugin)this).Config.Bind<float>("Pewter", "Knockback resistance", 0.3f, new ConfigDescription("Fraction of incoming knockback prevented while burning Pewter.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.9f), Array.Empty<object>()));
			pewterFallDamageReduction = ((BaseUnityPlugin)this).Config.Bind<float>("Pewter", "Fall damage reduction", 0.65f, new ConfigDescription("Fraction of fall damage prevented while burning Pewter.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			pewterPoisonResistance = ((BaseUnityPlugin)this).Config.Bind<float>("Pewter", "Poison damage resistance", 0.75f, new ConfigDescription("Fraction of poison damage prevented while burning Pewter.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.95f), Array.Empty<object>()));
			showReserveBar = ((BaseUnityPlugin)this).Config.Bind<bool>("Reserve", "Show reserve bar", true, "Show the reserve bar while Metalbound mode is active or the reserve is not full.");
			soundsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "Enable sounds", true, "Play Metalbound feedback using referenced vanilla Valheim sound prefabs.");
			soundVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "Sound volume", 0.55f, new ConfigDescription("Volume multiplier applied to Metalbound sound cues.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			windEffectEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "Enable movement wind", true, "Show wind streaks while Push or Pull moves the player.");
			windEffectIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "Movement wind intensity", 0.1014084f, new ConfigDescription("Density of the Push/Pull wind streaks.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f), Array.Empty<object>()));
			targetRange = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "Target range", 40f, new ConfigDescription("Maximum metal-anchor range in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 100f), Array.Empty<object>()));
			acceleration = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "Acceleration", 28f, new ConfigDescription("Push/pull acceleration.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>()));
			maximumSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "Maximum speed", 24f, new ConfigDescription("Velocity cap while using Allomancy.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 60f), Array.Empty<object>()));
			coinThrowSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "Coin throw speed", 18f, new ConfigDescription("Initial speed of a thrown coin.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 40f), Array.Empty<object>()));
			coinshotSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Combat", "Coinshot speed", 80f, new ConfigDescription("Initial speed of a fired coin projectile.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 200f), Array.Empty<object>()));
			coinshotDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Combat", "Coinshot damage", 10f, new ConfigDescription("Piercing damage dealt by a coin projectile.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			bronzeNailDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Combat", "Bronze nail damage", 18f, new ConfigDescription("Piercing damage dealt by a Bronze Nail projectile.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 200f), Array.Empty<object>()));
			ironNailDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Combat", "Iron nail damage", 28f, new ConfigDescription("Piercing damage dealt by an Iron Nail projectile.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 200f), Array.Empty<object>()));
			coinshotLifetime = ((BaseUnityPlugin)this).Config.Bind<float>("Combat", "Coinshot flight time", 4f, new ConfigDescription("Seconds a coin flies straight before becoming a normal dropped coin.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 10f), Array.Empty<object>()));
			coinshotCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Combat", "Coinshot cooldown", 0.5f, new ConfigDescription("Minimum seconds between successful Coin or Nail shots.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			looseCoinFlightSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "Loose coin flight speed", 32f, new ConfigDescription("Straight-line speed applied to an unbraced coin while Pushing or Pulling.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 100f), Array.Empty<object>()));
			coinBraceDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "Coin brace distance", 0.35f, new ConfigDescription("Distance behind a coin checked for terrain or a solid brace.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>()));
			safeDescentSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "Safe descent speed", 8f, new ConfigDescription("Maximum downward speed at which an upward Allomantic assist cancels accumulated fall height.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f), Array.Empty<object>()));
			fallProtectionGrace = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "Fall protection grace", 0.4f, new ConfigDescription("Seconds after an upward push or pull in which controlled descent can cancel fall height.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1.5f), Array.Empty<object>()));
			landingRollGroundWindow = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "Landing roll ground window", 1.1f, new ConfigDescription("Maximum ground distance at which Space can arm a landing roll.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 4f), Array.Empty<object>()));
			landingRollInputBuffer = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "Landing roll input buffer", 0.6f, new ConfigDescription("Seconds a valid airborne Space press waits for the imminent landing.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1.5f), Array.Empty<object>()));
			landingRollFullReductionHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "Landing roll full tier height", 10f, new ConfigDescription("Fall distance receiving the strongest landing-roll reduction.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>()));
			landingRollBaseReduction = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "Landing roll base reduction", 0.5f, new ConfigDescription("Fall-damage reduction at or below the full-tier height.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			landingRollStepDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "Landing roll tier distance", 6f, new ConfigDescription("Additional fall distance required to lower reduction by one tier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f), Array.Empty<object>()));
			landingRollStepReduction = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "Landing roll reduction per tier", 0.1f, new ConfigDescription("Reduction lost for each distance tier above the full tier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f), Array.Empty<object>()));
			landingRollMinimumReduction = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "Landing roll minimum reduction", 0.3f, new ConfigDescription("Minimum fall-damage reduction from any successful landing roll.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			mistingChanceOnDeath = ((BaseUnityPlugin)this).Config.Bind<float>("Progression", "Misting chance on death", 0.08f, new ConfigDescription("Chance that an Unawakened character becomes a random Misting on death.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			lerasiumChestChance = ((BaseUnityPlugin)this).Config.Bind<float>("Progression", "Lerasium chest chance", 0.03f, new ConfigDescription("Chance that a newly generated world chest contains one Lerasium Bead.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			targetingConeDegrees = ((BaseUnityPlugin)this).Config.Bind<float>("Targeting", "Aim cone", 18f, new ConfigDescription("Maximum angle away from the centre of the camera.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 60f), Array.Empty<object>()));
			maximumVisibleLines = ((BaseUnityPlugin)this).Config.Bind<int>("Targeting", "Maximum visible lines", 64, new ConfigDescription("Maximum faint metal-source lines rendered at once.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 256), Array.Empty<object>()));
			lineChestOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Targeting", "Line chest offset", 0.45f, new ConfigDescription("Vertical offset from the character center used as the blue-line origin.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.5f, 1.5f), Array.Empty<object>()));
			extraMetalTokens = ((BaseUnityPlugin)this).Config.Bind<string>("Targeting", "Additional metal names", string.Empty, "Comma-separated material or prefab-name fragments treated as metal.");
			PrefabManager.OnVanillaPrefabsAvailable += AddMetallicTincture;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Metalbound 0.20.3 loaded");
			harmony = Harmony.CreateAndPatchAll(typeof(Plugin).Assembly, "com.keeto.valheim.metalbound");
			if (MaxAirAltitudeField == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Fall-height field was not found; controlled-descent protection is unavailable.");
			}
			if (DodgeMethod == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Native dodge method was not found; Allomantic landing rolls are unavailable.");
			}
		}

		private void AddMetallicTincture()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Expected O, but got Unknown
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Expected O, but got Unknown
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Expected O, but got Unknown
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: 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_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Expected O, but got Unknown
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Expected O, but got Unknown
			ItemConfig val = new ItemConfig
			{
				Name = "Iron Vial",
				Description = "A prepared metal vial that completely replenishes Iron reserve.",
				CraftingStation = "piece_cauldron",
				MinStationLevel = 1,
				Amount = 5
			};
			val.AddRequirement("Iron", 2, 0);
			val.AddRequirement("Honey", 2, 0);
			RegisterMetalConsumable("MetalboundIronVial", val);
			ItemConfig val2 = new ItemConfig
			{
				Name = "Steel Vial",
				Description = "A prepared alloy vial that completely replenishes Steel reserve.",
				CraftingStation = "piece_cauldron",
				MinStationLevel = 1,
				Amount = 5
			};
			val2.AddRequirement("Iron", 2, 0);
			val2.AddRequirement("Coal", 2, 0);
			val2.AddRequirement("Honey", 2, 0);
			RegisterMetalConsumable("MetalboundSteelVial", val2);
			ItemConfig val3 = new ItemConfig
			{
				Name = "Pewter Vial",
				Description = "A tin-silver alloy vial that completely replenishes Pewter reserve.",
				CraftingStation = "piece_cauldron",
				MinStationLevel = 1,
				Amount = 5
			};
			val3.AddRequirement("Tin", 4, 0);
			val3.AddRequirement("Silver", 1, 0);
			val3.AddRequirement("Coal", 1, 0);
			val3.AddRequirement("Honey", 2, 0);
			RegisterMetalConsumable("MetalboundPewterVial", val3);
			ItemConfig val4 = new ItemConfig
			{
				Name = "Tin Vial",
				Description = "A prepared metal vial that completely replenishes Tin reserve.",
				CraftingStation = "piece_cauldron",
				MinStationLevel = 1,
				Amount = 5
			};
			val4.AddRequirement("Tin", 2, 0);
			val4.AddRequirement("Honey", 2, 0);
			RegisterMetalConsumable("MetalboundTinVial", val4);
			ItemConfig val5 = new ItemConfig
			{
				Name = "Copper Vial",
				Description = "A prepared metal vial that completely replenishes Copper reserve.",
				CraftingStation = "piece_cauldron",
				MinStationLevel = 1,
				Amount = 5
			};
			val5.AddRequirement("Copper", 2, 0);
			val5.AddRequirement("Honey", 2, 0);
			RegisterMetalConsumable("MetalboundCopperVial", val5);
			ItemConfig val6 = new ItemConfig
			{
				Name = "Allomantic Tincture",
				Description = "A combined tincture that completely replenishes every metal reserve.",
				CraftingStation = "piece_cauldron",
				MinStationLevel = 1,
				Amount = 1
			};
			val6.AddRequirement("MetalboundIronVial", 1, 0);
			val6.AddRequirement("MetalboundSteelVial", 1, 0);
			val6.AddRequirement("MetalboundPewterVial", 1, 0);
			val6.AddRequirement("MetalboundTinVial", 1, 0);
			val6.AddRequirement("MetalboundCopperVial", 1, 0);
			RegisterMetalConsumable("MetalboundTincture", val6);
			CustomItem val7 = new CustomItem("MetalboundLerasiumNugget", "MeadTasty");
			PrepareMetalConsumable(val7);
			val7.ItemDrop.m_itemData.m_shared.m_name = "Lerasium Bead";
			val7.ItemDrop.m_itemData.m_shared.m_description = "Something stirs within, yet you are cautious. This bead is life altering.";
			val7.ItemDrop.m_itemData.m_shared.m_maxStackSize = 10;
			ItemManager.Instance.AddItem(val7);
			PrefabManager.OnVanillaPrefabsAvailable -= AddMetallicTincture;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Registered metal vials, the combined Allomantic Tincture, and Lerasium Bead.");
		}

		private static void PrepareMetalConsumable(CustomItem item)
		{
			SharedData shared = item.ItemDrop.m_itemData.m_shared;
			shared.m_consumeStatusEffect = null;
			shared.m_food = 0f;
			shared.m_foodStamina = 0f;
			shared.m_foodEitr = 0f;
			shared.m_foodBurnTime = 0f;
			shared.m_foodRegen = 0f;
			shared.m_maxStackSize = 20;
			shared.m_weight = 0.3f;
		}

		private static void RegisterMetalConsumable(string prefabName, ItemConfig config)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			CustomItem val = new CustomItem(prefabName, "MeadTasty", config);
			PrepareMetalConsumable(val);
			ItemManager.Instance.AddItem(val);
		}

		private void Update()
		{
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()) || ((Object)(object)Console.instance != (Object)null && Console.IsVisible()))
			{
				CloseMetalWheelIfNeeded();
				HideAnchorLine();
				return;
			}
			EnsureAllomancerTypeLoaded(localPlayer);
			TryShowAwakeningMessage(localPlayer);
			EnsureReserveLoaded(localPlayer);
			ironReserve = Mathf.Clamp(ironReserve, 0f, maximumReserve.Value);
			steelReserve = Mathf.Clamp(steelReserve, 0f, maximumReserve.Value);
			pewterReserve = Mathf.Clamp(pewterReserve, 0f, maximumReserve.Value);
			tinReserve = Mathf.Clamp(tinReserve, 0f, maximumReserve.Value);
			copperReserve = Mathf.Clamp(copperReserve, 0f, maximumReserve.Value);
			bool num = UpdateMetalWheel(localPlayer);
			UpdatePewterBurn(localPlayer);
			UpdateTinBurn(localPlayer);
			UpdateCopperBurn();
			if (num)
			{
				currentAnchor = null;
				lockedAnchor = null;
				wasPushHeld = false;
				wasPullHeld = false;
				HideAnchorLine();
				return;
			}
			if (IsShortcutDown(refillReserveKey.Value))
			{
				RefillReserve(localPlayer);
			}
			PersistReserveIfNeeded();
			if (IsShortcutDown(throwCoinKey.Value))
			{
				ThrowCoin(localPlayer);
			}
			UpdateLandingRoll(localPlayer);
			UpdateControlledDescent(localPlayer);
			if (!IsShortcutHeld(modeKey.Value))
			{
				currentAnchor = null;
				lockedAnchor = null;
				wasPushHeld = false;
				wasPullHeld = false;
				HideAnchorLine();
				return;
			}
			if (!TryConsumeSightReserve(metalSightDrain.Value * Time.deltaTime * GetFlareDrainMultiplier()))
			{
				currentAnchor = null;
				lockedAnchor = null;
				wasPushHeld = false;
				wasPullHeld = false;
				HideAnchorLine();
				ShowCenterMessage("Burn Iron or Steel with available reserve to see metal lines.");
				return;
			}
			if (IsShortcutDown(coinshotKey.Value))
			{
				if (!HasMetalAccess(MetalType.Steel))
				{
					ShowCenterMessage("Steel is not one of your Allomantic metals.");
				}
				else if (steelBurning)
				{
					FireCoinshot(localPlayer);
				}
				else
				{
					ShowCenterMessage("Burn Steel to fire a Coinshot.");
				}
			}
			currentAnchor = FindBestAnchor(localPlayer, out var visibleAnchors);
			bool flag = IsShortcutHeld(pushKey.Value);
			bool flag2 = IsShortcutHeld(pullKey.Value);
			if (flag && !wasPushHeld && !HasMetalAccess(MetalType.Steel))
			{
				ShowCenterMessage("Steel is not one of your Allomantic metals.");
			}
			else if (flag && !wasPushHeld && !steelBurning)
			{
				ShowCenterMessage("Burn Steel to Push.");
			}
			if (flag2 && !wasPullHeld && !HasMetalAccess(MetalType.Iron))
			{
				ShowCenterMessage("Iron is not one of your Allomantic metals.");
			}
			else if (flag2 && !wasPullHeld && !ironBurning)
			{
				ShowCenterMessage("Burn Iron to Pull.");
			}
			if (flag && !wasPushHeld)
			{
				lockedAnchor = currentAnchor;
				if ((Object)(object)lockedAnchor != (Object)null)
				{
					PlaySound("sfx_metal_blocked", lockedAnchor.position);
				}
			}
			else if (flag2 && !wasPullHeld)
			{
				lockedAnchor = currentAnchor;
				if ((Object)(object)lockedAnchor != (Object)null)
				{
					PlaySound("sfx_metal_blocked", lockedAnchor.position);
				}
			}
			if (!flag && !flag2)
			{
				lockedAnchor = null;
			}
			if ((Object)(object)lockedAnchor != (Object)null && !IsAnchorInRange(localPlayer, lockedAnchor))
			{
				lockedAnchor = null;
			}
			if ((Object)(object)lockedAnchor != (Object)null)
			{
				if (flag && steelBurning && HasMetalAccess(MetalType.Steel))
				{
					TryConsumeReserve(MetalType.Steel, lockedTargetDrain.Value * Time.deltaTime * GetFlareDrainMultiplier());
				}
				else if (flag2 && ironBurning && HasMetalAccess(MetalType.Iron))
				{
					TryConsumeReserve(MetalType.Iron, lockedTargetDrain.Value * Time.deltaTime * GetFlareDrainMultiplier());
				}
			}
			Transform selectedAnchor = (((Object)(object)lockedAnchor != (Object)null) ? lockedAnchor : currentAnchor);
			DrawAnchorLines(localPlayer, visibleAnchors, selectedAnchor);
			if ((Object)(object)lockedAnchor != (Object)null)
			{
				if (flag && steelBurning && HasMetalAccess(MetalType.Steel))
				{
					if (TryConsumeReserve(MetalType.Steel, pushPullDrain.Value * Time.deltaTime * GetFlareDrainMultiplier()))
					{
						ApplyForce(localPlayer, lockedAnchor, push: true);
					}
					else
					{
						NotifyReserveEmpty(MetalType.Steel);
					}
				}
				else if (flag2 && ironBurning && HasMetalAccess(MetalType.Iron))
				{
					if (TryConsumeReserve(MetalType.Iron, pushPullDrain.Value * Time.deltaTime * GetFlareDrainMultiplier()))
					{
						ApplyForce(localPlayer, lockedAnchor, push: false);
					}
					else
					{
						NotifyReserveEmpty(MetalType.Iron);
					}
				}
			}
			wasPushHeld = flag;
			wasPullHeld = flag2;
		}

		private bool IsMetalWheelOpen()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (metalWheelKey != null)
			{
				return IsShortcutHeld(metalWheelKey.Value);
			}
			return false;
		}

		private void LateUpdate()
		{
			if (IsMetalWheelOpen())
			{
				Cursor.lockState = (CursorLockMode)1;
				Cursor.visible = false;
			}
			UpdateTinFocus();
		}

		private void UpdateTinFocus()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			Camera main = Camera.main;
			if (tinBurning && HasMetalAccess(MetalType.Tin) && tinReserve > 0.0001f && tinFocusKey != null && IsShortcutHeld(tinFocusKey.Value) && (Object)(object)main != (Object)null && ((Object)(object)Chat.instance == (Object)null || !Chat.instance.HasFocus()) && ((Object)(object)Console.instance == (Object)null || !Console.IsVisible()))
			{
				if (!tinFocusActive || (Object)(object)tinFocusCamera != (Object)(object)main)
				{
					tinFocusCamera = main;
					tinFocusBaseFov = main.fieldOfView;
					tinFocusActive = true;
				}
				float num = tinFocusZoom.Value / GetTinSenseMultiplier();
				float num2 = Mathf.Clamp(tinFocusBaseFov * num, 15f, tinFocusBaseFov);
				main.fieldOfView = Mathf.Lerp(main.fieldOfView, num2, 10f * Time.unscaledDeltaTime);
			}
			else if (tinFocusActive)
			{
				if ((Object)(object)tinFocusCamera != (Object)null)
				{
					tinFocusCamera.fieldOfView = tinFocusBaseFov;
				}
				tinFocusCamera = null;
				tinFocusActive = false;
			}
		}

		private void UpdatePewterBurn(Player player)
		{
			if (!HasMetalAccess(MetalType.Pewter))
			{
				pewterBurning = false;
			}
			else if (pewterBurning && !TryConsumeReserve(MetalType.Pewter, pewterDrain.Value * Time.deltaTime * GetFlareDrainMultiplier()))
			{
				pewterBurning = false;
				NotifyReserveEmpty(MetalType.Pewter);
			}
		}

		private void UpdateTinBurn(Player player)
		{
			if (!HasMetalAccess(MetalType.Tin))
			{
				tinBurning = false;
			}
			if (tinBurning && !TryConsumeReserve(MetalType.Tin, tinDrain.Value * Time.deltaTime * GetFlareDrainMultiplier()))
			{
				tinBurning = false;
				NotifyReserveEmpty(MetalType.Tin);
			}
			if (tinBurning)
			{
				EnsureTinEffects(player);
				UpdateTinEnemySense(player);
			}
			else
			{
				RemoveTinEffects(player);
				HideTinSenseLines();
			}
		}

		private void UpdateCopperBurn()
		{
			if (!HasMetalAccess(MetalType.Copper))
			{
				copperBurning = false;
			}
			if (copperBurning && !TryConsumeReserve(MetalType.Copper, copperDrain.Value * Time.deltaTime * GetFlareDrainMultiplier()))
			{
				copperBurning = false;
				NotifyReserveEmpty(MetalType.Copper);
			}
		}

		private void UpdateTinEnemySense(Player player)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			sensedTinEnemies.Clear();
			sensedIncomingProjectiles.Clear();
			float tinSenseMultiplier = GetTinSenseMultiplier();
			float num = tinEnemySenseRange.Value * tinSenseMultiplier;
			float num2 = tinProjectileSenseRange.Value * tinSenseMultiplier;
			float num3 = Mathf.Max(num, num2);
			Collider[] array = Physics.OverlapSphere(((Character)player).GetCenterPoint(), num3, -1, (QueryTriggerInteraction)1);
			HashSet<Character> hashSet = new HashSet<Character>();
			HashSet<Projectile> hashSet2 = new HashSet<Projectile>();
			List<Character> list = new List<Character>();
			Collider[] array2 = array;
			foreach (Collider val in array2)
			{
				Character val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponentInParent<Character>() : null);
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)player && !val2.IsDead() && Vector3.Distance(((Character)player).GetCenterPoint(), val2.GetCenterPoint()) <= num && hashSet.Add(val2) && BaseAI.IsEnemy((Character)(object)player, val2))
				{
					list.Add(val2);
				}
				Projectile val3 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponentInParent<Projectile>() : null);
				if ((Object)(object)val3 == (Object)null || !hashSet2.Add(val3))
				{
					continue;
				}
				Rigidbody val4 = ((Component)val3).GetComponent<Rigidbody>();
				if ((Object)(object)val4 == (Object)null)
				{
					val4 = ((Component)val3).GetComponentInChildren<Rigidbody>();
				}
				if ((Object)(object)val4 == (Object)null)
				{
					continue;
				}
				Vector3 linearVelocity = val4.linearVelocity;
				if (((Vector3)(ref linearVelocity)).sqrMagnitude < 9f)
				{
					continue;
				}
				Vector3 val5 = ((Character)player).GetCenterPoint() - ((Component)val3).transform.position;
				if (!(((Vector3)(ref val5)).magnitude > num2))
				{
					linearVelocity = val4.linearVelocity;
					if (!(Vector3.Dot(((Vector3)(ref linearVelocity)).normalized, ((Vector3)(ref val5)).normalized) < 0.72f))
					{
						sensedIncomingProjectiles.Add(((Component)val3).transform);
					}
				}
			}
			Vector3 origin = ((Character)player).GetCenterPoint() + Vector3.up * lineChestOffset.Value;
			list.Sort((Character left, Character right) => Vector3.SqrMagnitude(((Component)left).transform.position - origin).CompareTo(Vector3.SqrMagnitude(((Component)right).transform.position - origin)));
			int num4 = Mathf.Min(list.Count, tinEnemySenseLimit.Value);
			for (int num5 = 0; num5 < num4; num5++)
			{
				sensedTinEnemies.Add(list[num5]);
			}
		}

		private void HideTinSenseLines()
		{
			sensedTinEnemies.Clear();
			sensedIncomingProjectiles.Clear();
		}

		private void EnsureTinEffects(Player player)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Expected O, but got Unknown
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)tinVisionObject == (Object)null)
			{
				tinVisionObject = new GameObject("MetalboundTinVision");
				tinVisionObject.transform.SetParent(((Component)player).transform, false);
				tinVisionObject.transform.localPosition = Vector3.up * 1.6f;
				Light obj = tinVisionObject.AddComponent<Light>();
				obj.type = (LightType)2;
				obj.color = new Color(0.68f, 0.82f, 1f);
				obj.range = tinVisionRange.Value * GetTinSenseMultiplier();
				obj.intensity = tinVisionIntensity.Value * GetTinSenseMultiplier();
				obj.shadows = (LightShadows)0;
			}
			else
			{
				Light component = tinVisionObject.GetComponent<Light>();
				if ((Object)(object)component != (Object)null)
				{
					component.range = tinVisionRange.Value * GetTinSenseMultiplier();
					component.intensity = tinVisionIntensity.Value * GetTinSenseMultiplier();
				}
			}
			if ((Object)(object)tinDemisterObject == (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab("Demister");
				Demister val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponentInChildren<Demister>(true) : null);
				if ((Object)(object)val != (Object)null)
				{
					tinDemisterObject = new GameObject("MetalboundTinDemister");
					tinDemisterObject.transform.SetParent(((Component)player).transform, false);
					tinDemisterObject.transform.localPosition = Vector3.up * 1.2f;
					Demister val2 = tinDemisterObject.AddComponent<Demister>();
					JsonUtility.FromJsonOverwrite(JsonUtility.ToJson((object)val), (object)val2);
				}
			}
			if ((Object)(object)tinFinderEffect == (Object)null && (Object)(object)ObjectDB.instance != (Object)null)
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Wishbone");
				ItemDrop val3 = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
				StatusEffect val4 = (((Object)(object)val3 != (Object)null) ? val3.m_itemData.m_shared.m_equipStatusEffect : null);
				if ((Object)(object)val4 != (Object)null)
				{
					tinFinderEffect = Object.Instantiate<StatusEffect>(val4);
					((Object)tinFinderEffect).name = "SE_MetalboundTinFinder";
					tinFinderEffect.m_name = "Tin Senses";
				}
			}
			if (!tinFinderAdded && (Object)(object)tinFinderEffect != (Object)null)
			{
				tinFinderAdded = InvokeAddStatusEffect(((Character)player).GetSEMan(), tinFinderEffect);
			}
		}

		private void RemoveTinEffects(Player player)
		{
			if ((Object)(object)tinVisionObject != (Object)null)
			{
				Object.Destroy((Object)(object)tinVisionObject);
				tinVisionObject = null;
			}
			if ((Object)(object)tinDemisterObject != (Object)null)
			{
				Object.Destroy((Object)(object)tinDemisterObject);
				tinDemisterObject = null;
			}
			if (tinFinderAdded && (Object)(object)tinFinderEffect != (Object)null && (Object)(object)player != (Object)null)
			{
				InvokeRemoveStatusEffect(((Character)player).GetSEMan(), GetStableHashCode(((Object)tinFinderEffect).name));
				tinFinderAdded = false;
			}
		}

		private static bool InvokeAddStatusEffect(SEMan manager, StatusEffect effect)
		{
			if (manager == null || (Object)(object)effect == (Object)null)
			{
				return false;
			}
			MethodInfo[] methods = typeof(SEMan).GetMethods(BindingFlags.Instance | BindingFlags.Public);
			foreach (MethodInfo methodInfo in methods)
			{
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (!(methodInfo.Name != "AddStatusEffect") && parameters.Length != 0 && !(parameters[0].ParameterType != typeof(StatusEffect)))
				{
					object[] array = BuildDefaultArguments(parameters);
					array[0] = effect;
					methodInfo.Invoke(manager, array);
					return true;
				}
			}
			return false;
		}

		private static void InvokeRemoveStatusEffect(SEMan manager, int nameHash)
		{
			if (manager == null)
			{
				return;
			}
			MethodInfo[] methods = typeof(SEMan).GetMethods(BindingFlags.Instance | BindingFlags.Public);
			foreach (MethodInfo methodInfo in methods)
			{
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (!(methodInfo.Name != "RemoveStatusEffect") && parameters.Length != 0 && !(parameters[0].ParameterType != typeof(int)))
				{
					object[] array = BuildDefaultArguments(parameters);
					array[0] = nameHash;
					methodInfo.Invoke(manager, array);
					break;
				}
			}
		}

		private static object[] BuildDefaultArguments(ParameterInfo[] parameters)
		{
			object[] array = new object[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				if (parameters[i].HasDefaultValue)
				{
					array[i] = parameters[i].DefaultValue;
					continue;
				}
				Type parameterType = parameters[i].ParameterType;
				array[i] = (parameterType.IsValueType ? Activator.CreateInstance(parameterType) : null);
			}
			return array;
		}

		private static int GetStableHashCode(string value)
		{
			int num = 5381;
			int num2 = num;
			for (int i = 0; i < value.Length && value[i] != 0; i += 2)
			{
				num = ((num << 5) + num) ^ value[i];
				if (i == value.Length - 1 || value[i + 1] == '\0')
				{
					break;
				}
				num2 = ((num2 << 5) + num2) ^ value[i + 1];
			}
			return num + num2 * 1566083941;
		}

		private bool UpdateMetalWheel(Player player)
		{
			//IL_0006: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			bool flag = IsShortcutHeld(metalWheelKey.Value);
			if (flag)
			{
				if (!metalWheelWasHeld)
				{
					metalWheelSelector = Vector2.zero;
				}
				metalWheelSelector += new Vector2(Input.GetAxisRaw("Mouse X"), 0f - Input.GetAxisRaw("Mouse Y")) * 12f;
				metalWheelSelector = Vector2.ClampMagnitude(metalWheelSelector, 184f);
				if (Input.GetMouseButtonDown(0))
				{
					Vector2 val = new Vector2((float)Screen.width * 0.5f, (float)Screen.height * 0.5f) + metalWheelSelector;
					GetMetalWheelOptionRects(out var ironRect, out var steelRect, out var pewterRect, out var tinRect, out var copperRect);
					GetAmmoWheelOptionRects(out var coinRect, out var bronzeNailRect, out var ironNailRect);
					if (((Rect)(ref ironRect)).Contains(val))
					{
						ToggleMetalBurn(MetalType.Iron);
					}
					else if (((Rect)(ref steelRect)).Contains(val))
					{
						ToggleMetalBurn(MetalType.Steel);
					}
					else if (((Rect)(ref pewterRect)).Contains(val))
					{
						ToggleMetalBurn(MetalType.Pewter);
					}
					else if (((Rect)(ref tinRect)).Contains(val))
					{
						ToggleMetalBurn(MetalType.Tin);
					}
					else if (((Rect)(ref copperRect)).Contains(val))
					{
						ToggleMetalBurn(MetalType.Copper);
					}
					else if (((Rect)(ref coinRect)).Contains(val))
					{
						SelectCoinshotAmmo(CoinshotAmmoType.Coin);
					}
					else if (((Rect)(ref bronzeNailRect)).Contains(val))
					{
						SelectCoinshotAmmo(CoinshotAmmoType.BronzeNail);
					}
					else if (((Rect)(ref ironNailRect)).Contains(val))
					{
						SelectCoinshotAmmo(CoinshotAmmoType.IronNail);
					}
				}
				if (Input.GetMouseButtonDown(1))
				{
					Vector2 val2 = new Vector2((float)Screen.width * 0.5f, (float)Screen.height * 0.5f) + metalWheelSelector;
					GetMetalWheelOptionRects(out var ironRect2, out var steelRect2, out var pewterRect2, out var tinRect2, out var copperRect2);
					if (((Rect)(ref ironRect2)).Contains(val2))
					{
						TryRefillAccessibleReserve(player, MetalType.Iron);
					}
					else if (((Rect)(ref steelRect2)).Contains(val2))
					{
						TryRefillAccessibleReserve(player, MetalType.Steel);
					}
					else if (((Rect)(ref pewterRect2)).Contains(val2))
					{
						TryRefillAccessibleReserve(player, MetalType.Pewter);
					}
					else if (((Rect)(ref tinRect2)).Contains(val2))
					{
						TryRefillAccessibleReserve(player, MetalType.Tin);
					}
					else if (((Rect)(ref copperRect2)).Contains(val2))
					{
						TryRefillAccessibleReserve(player, MetalType.Copper);
					}
				}
			}
			else if (metalWheelWasHeld)
			{
				CloseMetalWheelIfNeeded();
			}
			metalWheelWasHeld = flag;
			return flag;
		}

		private void ToggleMetalBurn(MetalType metal)
		{
			if (!HasMetalAccess(metal))
			{
				ShowCenterMessage(metal.ToString() + " is locked for " + GetAllomancerTitle(allomancerType) + ".");
				return;
			}
			switch (metal)
			{
			case MetalType.Iron:
				ironBurning = !ironBurning;
				ShowCenterMessage("Iron " + (ironBurning ? "burning" : "off"));
				break;
			case MetalType.Steel:
				steelBurning = !steelBurning;
				ShowCenterMessage("Steel " + (steelBurning ? "burning" : "off"));
				break;
			case MetalType.Pewter:
				if (!pewterBurning && pewterReserve <= 0.0001f)
				{
					NotifyReserveEmpty(MetalType.Pewter);
					break;
				}
				pewterBurning = !pewterBurning;
				ShowCenterMessage("Pewter " + (pewterBurning ? "burning" : "off"));
				break;
			case MetalType.Tin:
				if (!tinBurning && tinReserve <= 0.0001f)
				{
					NotifyReserveEmpty(MetalType.Tin);
					break;
				}
				tinBurning = !tinBurning;
				ShowCenterMessage("Tin " + (tinBurning ? "burning" : "off"));
				break;
			default:
				if (!copperBurning && copperReserve <= 0.0001f)
				{
					NotifyReserveEmpty(MetalType.Copper);
					break;
				}
				copperBurning = !copperBurning;
				ShowCenterMessage("Copper " + (copperBurning ? "burning" : "off"));
				break;
			}
		}

		private void SelectCoinshotAmmo(CoinshotAmmoType ammoType)
		{
			selectedCoinshotAmmo = ammoType;
			ShowCenterMessage(GetCoinshotAmmoDisplayName(ammoType) + " selected.");
		}

		private void TryRefillAccessibleReserve(Player player, MetalType metal)
		{
			if (!HasMetalAccess(metal))
			{
				ShowCenterMessage(metal.ToString() + " is locked for " + GetAllomancerTitle(allomancerType) + ".");
			}
			else
			{
				RefillSingleReserve(player, metal);
			}
		}

		private void CloseMetalWheelIfNeeded()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if (metalWheelWasHeld)
			{
				metalWheelWasHeld = false;
				metalWheelSelector = Vector2.zero;
			}
		}

		private static void GetMetalWheelOptionRects(out Rect ironRect, out Rect steelRect, out Rect pewterRect, out Rect tinRect, out Rect copperRect)
		{
			//IL_0020: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor((float)Screen.width * 0.5f, (float)Screen.height * 0.5f);
			ironRect = new Rect(val.x - 157f, val.y - 69f, 86f, 64f);
			steelRect = new Rect(val.x + 71f, val.y - 69f, 86f, 64f);
			pewterRect = new Rect(val.x + 27f, val.y + 65f, 86f, 64f);
			tinRect = new Rect(val.x - 43f, val.y - 152f, 86f, 64f);
			copperRect = new Rect(val.x - 113f, val.y + 65f, 86f, 64f);
		}

		private static void GetAmmoWheelOptionRects(out Rect coinRect, out Rect bronzeNailRect, out Rect ironNailRect)
		{
			//IL_0020: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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)
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor((float)Screen.width * 0.5f, (float)Screen.height * 0.5f);
			coinRect = new Rect(val.x - 126f, val.y + 145f, 80f, 52f);
			bronzeNailRect = new Rect(val.x - 40f, val.y + 145f, 80f, 52f);
			ironNailRect = new Rect(val.x + 46f, val.y + 145f, 80f, 52f);
		}

		private bool IsAnchorInRange(Player player, Transform anchor)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)anchor == (Object)null)
			{
				return false;
			}
			float num = Vector3.Distance(((Character)player).GetCenterPoint(), anchor.position);
			if (num >= 0.5f)
			{
				return num <= targetRange.Value;
			}
			return false;
		}

		private Transform FindBestAnchor(Player player, out List<Transform> visibleAnchors)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			visibleAnchors = new List<Transform>();
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				return null;
			}
			Vector3 origin = ((Character)player).GetCenterPoint();
			Vector3 forward = ((Component)main).transform.forward;
			Collider[] array = Physics.OverlapSphere(origin, targetRange.Value);
			HashSet<int> hashSet = new HashSet<int>();
			Transform result = null;
			float num = float.MaxValue;
			Collider[] array2 = array;
			foreach (Collider collider in array2)
			{
				Transform metalAnchor = GetMetalAnchor(collider);
				if ((Object)(object)metalAnchor == (Object)null || !hashSet.Add(((Object)((Component)metalAnchor).gameObject).GetInstanceID()))
				{
					continue;
				}
				Vector3 val = metalAnchor.position - origin;
				float magnitude = ((Vector3)(ref val)).magnitude;
				if (magnitude < 0.75f || magnitude > targetRange.Value)
				{
					continue;
				}
				visibleAnchors.Add(metalAnchor);
				float num2 = Vector3.Angle(forward, val);
				if (!(num2 > targetingConeDegrees.Value))
				{
					float num3 = num2 * 4f + magnitude * 0.15f;
					if (num3 < num)
					{
						num = num3;
						result = metalAnchor;
					}
				}
			}
			visibleAnchors.Sort((Transform left, Transform right) => Vector3.SqrMagnitude(left.position - origin).CompareTo(Vector3.SqrMagnitude(right.position - origin)));
			return result;
		}

		private static bool IsShortcutHeld(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey))
			{
				return false;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			return true;
		}

		internal static bool ShouldBlockVanillaAttacks(Player player)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Instance != (Object)null && (Object)(object)player == (Object)(object)Player.m_localPlayer)
			{
				if (!IsShortcutHeld(Instance.modeKey.Value))
				{
					return Instance.IsMetalWheelOpen();
				}
				return true;
			}
			return false;
		}

		private static bool IsShortcutDown(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey))
			{
				return false;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			return true;
		}

		private void ThrowCoin(Player player)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: 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_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null || !inventory.HaveItem("$item_coins", true))
			{
				ShowCenterMessage("You need a coin to throw.");
			}
			else
			{
				if ((Object)(object)ZNetScene.instance == (Object)null)
				{
					return;
				}
				GameObject prefab = ZNetScene.instance.GetPrefab("Coins");
				Camera main = Camera.main;
				if ((Object)(object)prefab == (Object)null || (Object)(object)main == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not find the vanilla Coins prefab or main camera.");
					return;
				}
				inventory.RemoveItem("$item_coins", 1, -1, true);
				Vector3 forward = ((Component)main).transform.forward;
				Vector3 normalized = ((Vector3)(ref forward)).normalized;
				Vector3 val = ((Character)player).GetEyePoint() + normalized * 0.8f;
				GameObject val2 = Object.Instantiate<GameObject>(prefab, val, Random.rotation);
				PlaySound("sfx_coins_placed", val);
				ItemDrop component = val2.GetComponent<ItemDrop>();
				if ((Object)(object)component != (Object)null)
				{
					component.m_itemData.m_stack = 1;
				}
				Rigidbody val3 = val2.GetComponent<Rigidbody>();
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = val2.GetComponentInChildren<Rigidbody>();
				}
				if ((Object)(object)val3 != (Object)null)
				{
					Rigidbody component2 = ((Component)player).GetComponent<Rigidbody>();
					Vector3 val4 = (((Object)(object)component2 != (Object)null) ? component2.linearVelocity : Vector3.zero);
					val3.linearVelocity = normalized * coinThrowSpeed.Value + val4;
					val3.angularVelocity = Random.onUnitSphere * 18f;
					((Component)val3).gameObject.AddComponent<DownwardAnchorSettler>().Configure(normalized, stickOnAnySurface: false);
				}
			}
		}

		private void FireCoinshot(Player player)
		{
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time - lastCoinshotTime < coinshotCooldown.Value)
			{
				return;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			string coinshotAmmoItemName = GetCoinshotAmmoItemName(selectedCoinshotAmmo);
			string coinshotAmmoDisplayName = GetCoinshotAmmoDisplayName(selectedCoinshotAmmo);
			if (inventory == null || !inventory.HaveItem(coinshotAmmoItemName, true))
			{
				ShowCenterMessage("You need " + GetCoinshotAmmoArticle(selectedCoinshotAmmo) + " " + coinshotAmmoDisplayName + " to fire.");
			}
			else
			{
				if ((Object)(object)ZNetScene.instance == (Object)null)
				{
					return;
				}
				string coinshotAmmoPrefabName = GetCoinshotAmmoPrefabName(selectedCoinshotAmmo);
				GameObject prefab = ZNetScene.instance.GetPrefab(coinshotAmmoPrefabName);
				Camera main = Camera.main;
				if ((Object)(object)prefab == (Object)null || (Object)(object)main == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not find the vanilla " + coinshotAmmoPrefabName + " prefab or main camera."));
					return;
				}
				if (!TryConsumeReserve(MetalType.Steel, coinshotReserveCost.Value * GetFlareDrainMultiplier()))
				{
					NotifyReserveEmpty(MetalType.Steel);
					return;
				}
				inventory.RemoveItem(coinshotAmmoItemName, 1, -1, true);
				Vector3 forward = ((Component)main).transform.forward;
				Vector3 normalized = ((Vector3)(ref forward)).normalized;
				Vector3 val = ((Character)player).GetEyePoint() + normalized * 1.1f;
				GameObject val2 = Object.Instantiate<GameObject>(prefab, val, Random.rotation);
				PlaySound("sfx_arbalest_fire", val);
				ItemDrop component = val2.GetComponent<ItemDrop>();
				if ((Object)(object)component != (Object)null)
				{
					component.m_itemData.m_stack = 1;
				}
				Rigidbody val3 = val2.GetComponent<Rigidbody>();
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = val2.GetComponentInChildren<Rigidbody>();
				}
				if ((Object)(object)val3 == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("The spawned " + coinshotAmmoDisplayName + " has no Rigidbody."));
					return;
				}
				Rigidbody component2 = ((Component)player).GetComponent<Rigidbody>();
				Vector3 val4 = (((Object)(object)component2 != (Object)null) ? component2.linearVelocity : Vector3.zero);
				val3.collisionDetectionMode = (CollisionDetectionMode)2;
				val3.interpolation = (RigidbodyInterpolation)1;
				val3.useGravity = false;
				val3.linearVelocity = normalized * coinshotSpeed.Value + val4;
				val3.angularVelocity = Random.onUnitSphere * 30f;
				((Component)val3).gameObject.AddComponent<DownwardAnchorSettler>().Configure(normalized, selectedCoinshotAmmo != CoinshotAmmoType.Coin);
				((Component)val3).gameObject.AddComponent<CoinshotProjectile>().Configure(player, GetCoinshotAmmoDamage(selectedCoinshotAmmo), normalized, coinshotSpeed.Value, coinshotLifetime.Value);
				lastCoinshotTime = Time.time;
			}
		}

		private float GetCoinshotAmmoDamage(CoinshotAmmoType ammoType)
		{
			return ammoType switch
			{
				CoinshotAmmoType.BronzeNail => bronzeNailDamage.Value, 
				CoinshotAmmoType.IronNail => ironNailDamage.Value, 
				_ => coinshotDamage.Value, 
			};
		}

		private static string GetCoinshotAmmoPrefabName(CoinshotAmmoType ammoType)
		{
			return ammoType switch
			{
				CoinshotAmmoType.BronzeNail => "BronzeNails", 
				CoinshotAmmoType.IronNail => "IronNails", 
				_ => "Coins", 
			};
		}

		private static string GetCoinshotAmmoItemName(CoinshotAmmoType ammoType)
		{
			return ammoType switch
			{
				CoinshotAmmoType.BronzeNail => "$item_bronzenails", 
				CoinshotAmmoType.IronNail => "$item_ironnails", 
				_ => "$item_coins", 
			};
		}

		private static string GetCoinshotAmmoDisplayName(CoinshotAmmoType ammoType)
		{
			return ammoType switch
			{
				CoinshotAmmoType.BronzeNail => "Bronze Nail", 
				CoinshotAmmoType.IronNail => "Iron Nail", 
				_ => "Coin", 
			};
		}

		private static string GetCoinshotAmmoArticle(CoinshotAmmoType ammoType)
		{
			if (ammoType != CoinshotAmmoType.IronNail)
			{
				return "a";
			}
			return "an";
		}

		private static void ShowCenterMessage(string message)
		{
			if ((Object)(object)MessageHud.instance != (Object)null)
			{
				MessageHud.instance.ShowMessage((MessageType)2, message, 0, (Sprite)null, false);
			}
		}

		private void PlaySound(string prefabName, Vector3 position, float cueVolume = 1f)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			if (soundsEnabled == null || !soundsEnabled.Value || soundVolume.Value <= 0f || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(prefabName);
			if ((Object)(object)prefab == (Object)null)
			{
				if (missingSoundPrefabs.Add(prefabName))
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Sound prefab not found: " + prefabName));
				}
				return;
			}
			GameObject val = Object.Instantiate<GameObject>(prefab, position, Quaternion.identity);
			float num = Mathf.Clamp01(soundVolume.Value * cueVolume);
			AudioSource[] componentsInChildren = val.GetComponentsInChildren<AudioSource>(true);
			foreach (AudioSource obj in componentsInChildren)
			{
				obj.volume *= num;
			}
			Object.Destroy((Object)(object)val, 10f);
		}

		private void EnsureReserveLoaded(Player player)
		{
			if (!((Object)(object)reserveOwner == (Object)(object)player))
			{
				if ((Object)(object)reserveOwner != (Object)null)
				{
					PersistReserve();
				}
				reserveOwner = player;
				float value;
				float num = (TryLoadReserve(player, "com.keeto.valheim.metalbound.reserve", out value) ? value : Mathf.Clamp(startingReserve.Value, 0f, maximumReserve.Value));
				bool flag = TryLoadReserve(player, "com.keeto.valheim.metalbound.reserve.iron", out ironReserve);
				bool flag2 = TryLoadReserve(player, "com.keeto.valheim.metalbound.reserve.steel", out steelReserve);
				bool flag3 = TryLoadReserve(player, "com.keeto.valheim.metalbound.reserve.pewter", out pewterReserve);
				bool flag4 = TryLoadReserve(player, "com.keeto.valheim.metalbound.reserve.tin", out tinReserve);
				bool flag5 = TryLoadReserve(player, "com.keeto.valheim.metalbound.reserve.copper", out copperReserve);
				if (!flag)
				{
					ironReserve = num;
				}
				if (!flag2)
				{
					steelReserve = num;
				}
				if (!flag3)
				{
					pewterReserve = num;
				}
				if (!flag4)
				{
					tinReserve = num;
				}
				if (!flag5)
				{
					copperReserve = num;
				}
				ironReserve = Mathf.Clamp(ironReserve, 0f, maximumReserve.Value);
				steelReserve = Mathf.Clamp(steelReserve, 0f, maximumReserve.Value);
				pewterReserve = Mathf.Clamp(pewterReserve, 0f, maximumReserve.Value);
				tinReserve = Mathf.Clamp(tinReserve, 0f, maximumReserve.Value);
				copperReserve = Mathf.Clamp(copperReserve, 0f, maximumReserve.Value);
				reserveDirty = !flag || !flag2 || !flag3 || !flag4 || !flag5;
				if (reserveDirty)
				{
					PersistReserve();
				}
			}
		}

		private void EnsureAllomancerTypeLoaded(Player player)
		{
			if (!((Object)(object)allomancerOwner == (Object)(object)player))
			{
				allomancerOwner = player;
				if (player.m_customData.TryGetValue("com.keeto.valheim.metalbound.allomancer_type", out var value) && Enum.TryParse<AllomancerType>(value, ignoreCase: true, out var result))
				{
					allomancerType = result;
					return;
				}
				bool flag = player.m_customData.ContainsKey("com.keeto.valheim.metalbound.reserve.iron") || player.m_customData.ContainsKey("com.keeto.valheim.metalbound.reserve.steel") ||