Decompiled source of MaceThunderbrand v1.0.0

MaceThunderbrand.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("MaceThunderbrand")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Thunderbrand versions of the vanilla maces, clubs and sledges with lightning damage, electric glow and arcs, throw and recall, a leap, and lightning strikes.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Mace Thunderbrand")]
[assembly: AssemblyTitle("MaceThunderbrand")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MaceThunderbrand
{
	internal sealed class GearGroup
	{
		public string Tag;

		public ConfigEntry<bool> CrackTexture;

		public ConfigEntry<float> CrackIntensity;

		public ConfigEntry<float> GlowIntensity;

		public ConfigEntry<float> CrackTiles;
	}
	[BepInPlugin("brett.macethunderbrand", "Mace Thunderbrand", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal struct Span
		{
			public bool Valid;

			public int Axis;

			public float Min;

			public float Max;

			public Vector3 Center;

			public Vector3 Size;

			public float Width
			{
				get
				{
					float num = 0f;
					for (int i = 0; i < 3; i++)
					{
						if (i != Axis && ((Vector3)(ref Size))[i] > num)
						{
							num = ((Vector3)(ref Size))[i];
						}
					}
					return num;
				}
			}
		}

		internal struct HeadInfo
		{
			public bool Valid;

			public Span Span;

			public float TipSign;

			public float Start;

			public Vector3 Base;

			public Vector3 Tip;

			public Vector3 Center;

			public float Radius;

			public Vector3[] Points;
		}

		internal static GearGroup ArmorSettings;

		internal static GearGroup CapeSettings;

		internal static ConfigEntry<bool> CloneModdedItems;

		internal static ConfigEntry<bool> CloneRequireRecipe;

		internal static ConfigEntry<string> CloneExclude;

		internal static ConfigEntry<bool> MacesCloneAll;

		internal static ConfigEntry<string> MacesExtra;

		private static Dictionary<string, GameObject> itemIndex;

		private static Dictionary<string, Recipe> recipeIndex;

		private static bool itemSourcesLogged;

		internal static readonly Dictionary<string, string> AutoBases = new Dictionary<string, string>();

		private static bool stationsFixLogged;

		private static bool dedupeLogged;

		private static Type localizationType;

		private static PropertyInfo localizationInstanceProp;

		private static FieldInfo localizationInstanceField;

		private static MethodInfo localizeMethod;

		private static bool localizationLooked;

		internal static ConfigEntry<bool> GearWithMace;

		internal static ConfigEntry<bool> GearFlare;

		internal static ConfigEntry<bool> BodyArcs;

		internal static ConfigEntry<int> BodyArcCount;

		internal static ConfigEntry<float> BodyLight;

		internal static ConfigEntry<bool> SkinCracks;

		internal static ConfigEntry<float> SkinCrackIntensity;

		internal static ConfigEntry<float> SkinGlowIntensity;

		internal static ConfigEntry<float> SkinCrackTiles;

		private static float shieldTarget = -1f;

		private static readonly Dictionary<string, float> shieldFactors = new Dictionary<string, float>();

		internal static ConfigEntry<bool> LeapEnabled;

		internal static ConfigEntry<float> LeapHeight;

		internal static ConfigEntry<float> LeapForward;

		internal static ConfigEntry<float> LeapStamina;

		internal static ConfigEntry<float> LeapCooldown;

		internal static ConfigEntry<bool> LeapLanding;

		internal static ConfigEntry<bool> LeapTrailOn;

		internal static ConfigEntry<float> LeapTrailSize;

		internal static ConfigEntry<float> LeapLight;

		internal static ConfigEntry<bool> ShareMyEffects;

		internal static ConfigEntry<bool> ShowOthersEffects;

		public const string PluginGuid = "brett.macethunderbrand";

		public const string PluginName = "Mace Thunderbrand";

		public const string PluginVersion = "1.0.0";

		internal static Plugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<float> LightningRatio;

		internal static ConfigEntry<float> FlatLightningBonus;

		internal static ConfigEntry<string> RecipeItem1;

		internal static ConfigEntry<int> RecipeAmount1;

		internal static ConfigEntry<int> RecipePerLevel1;

		internal static ConfigEntry<string> RecipeItem2;

		internal static ConfigEntry<int> RecipeAmount2;

		internal static ConfigEntry<int> RecipePerLevel2;

		internal static ConfigEntry<bool> GlowHeads;

		internal static ConfigEntry<float> GlowIntensity;

		internal static ConfigEntry<bool> CrackTexture;

		internal static ConfigEntry<float> CrackIntensity;

		internal static ConfigEntry<float> LightMultiplier;

		internal static ConfigEntry<bool> ArcsEnabled;

		internal static ConfigEntry<int> ArcCount;

		internal static ConfigEntry<float> ArcScale;

		internal static ConfigEntry<float> SparkAmount;

		internal static ConfigEntry<bool> VerboseLog;

		internal static Material SparkMaterial;

		internal static ConfigEntry<bool> TrailEnabled;

		internal static ConfigEntry<float> TrailMinSpeed;

		internal static ConfigEntry<float> TrailSize;

		internal static ConfigEntry<float> TrailLifetime;

		internal static ConfigEntry<float> TrailDensity;

		internal static ConfigEntry<bool> ImpactEnabled;

		internal static ConfigEntry<int> ImpactParticles;

		internal static ConfigEntry<float> ImpactLight;

		internal static ConfigEntry<bool> ThrowEnabled;

		internal static ConfigEntry<KeyboardShortcut> ThrowKey;

		internal static ConfigEntry<KeyboardShortcut> RecallKey;

		internal static ConfigEntry<bool> ThrowKeyAlsoRecalls;

		internal static ConfigEntry<float> ThrowStamina;

		internal static ConfigEntry<float> ThrowSpeed;

		internal static ConfigEntry<float> ThrowRange;

		internal static ConfigEntry<float> ReturnSpeed;

		internal static ConfigEntry<float> ThrowDamageMultiplier;

		internal static ConfigEntry<float> SpinSpeed;

		internal static ConfigEntry<float> AutoRecallSeconds;

		internal static ConfigEntry<bool> ThrowAnimationEnabled;

		internal static ConfigEntry<string> ThrowAnimationName;

		internal static ConfigEntry<float> ThrowReleaseDelay;

		internal static ConfigEntry<string> RecallEmote;

		internal static ConfigEntry<float> RecallDelay;

		internal static ConfigEntry<bool> StrikeEnabled;

		internal static ConfigEntry<bool> StrikeOnSecondary;

		internal static ConfigEntry<bool> StrikeOnThrow;

		internal static ConfigEntry<bool> MaceImpactOnThrow;

		internal static ConfigEntry<float> StrikeRadius;

		internal static ConfigEntry<float> StrikeDamageMultiplier;

		internal static ConfigEntry<float> StrikePush;

		internal static ConfigEntry<float> StrikeLight;

		internal static ConfigEntry<float> StrikeEffectLifetime;

		internal static ConfigEntry<bool> StrikeUseVanillaEffects;

		internal static ConfigEntry<string> StrikeVanillaEffects;

		private static bool macesLeftLogged;

		private static readonly HashSet<string> shownNames = new HashSet<string>();

		private static readonly List<string> madeNames = new List<string>();

		private static readonly HashSet<string> recipesMade = new HashSet<string>();

		private static readonly HashSet<string> missingMaterials = new HashSet<string>();

		internal static ConfigEntry<bool> SecondaryPriority;

		internal static ConfigEntry<string> TwoHandedSecondaryFrom;

		internal static ConfigEntry<string> TwoHandedMainAttack;

		private static bool twoHandedLogged;

		internal static ConfigEntry<bool> ShieldCrackTexture;

		internal static ConfigEntry<float> ShieldCrackIntensity;

		internal static ConfigEntry<float> ShieldGlowIntensity;

		internal static ConfigEntry<float> ShieldCrackTiles;

		internal static ConfigEntry<bool> ShieldResize;

		internal static ConfigEntry<float> ShieldSizeBetween;

		internal static ConfigEntry<float> ShieldBackOffset;

		internal static ConfigEntry<float> ShieldBackLift;

		internal static ConfigEntry<float> ShieldBackSide;

		internal static ConfigEntry<bool> ShieldDefer;

		internal static ConfigEntry<bool> ShieldShockOnBlock;

		internal static ConfigEntry<float> ShieldShockRatio;

		internal static ConfigEntry<float> ShieldShockMax;

		private const float RoundAspect = 0.85f;

		private static int firebrandState;

		internal static ConfigEntry<bool> ShockEnemies;

		internal static ConfigEntry<float> ShockSeconds;

		internal static ConfigEntry<float> ShockLight;

		internal static ConfigEntry<float> ShockSize;

		internal static bool ShieldsLeftToFirebrand
		{
			get
			{
				if (ShieldDefer == null || !ShieldDefer.Value)
				{
					return false;
				}
				if (firebrandState == 0)
				{
					bool flag = false;
					try
					{
						flag = Chainloader.PluginInfos.ContainsKey("brett.swordfirebrand");
					}
					catch (Exception)
					{
						flag = false;
					}
					firebrandState = (flag ? 1 : 2);
					if (flag)
					{
						Log.LogInfo((object)"[Shields] SwordFirebrand is installed: it sizes the round shields and moves the back-carried shields, so this mod leaves that to it (Shields > LeaveToSwordFirebrand).");
					}
				}
				return firebrandState == 1;
			}
		}

		private void BindArmor()
		{
			ArmorSettings = new GearGroup
			{
				Tag = "Armor"
			};
			ArmorSettings.CrackTexture = ((BaseUnityPlugin)this).Config.Bind<bool>("Armor", "CrackTexture", true, "Glowing electric cracks (the same pattern as on the maces) across the armor you wear while a Thunderbrand mace is held.");
			ArmorSettings.CrackIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Armor", "CrackIntensity", 0.45f, "How brightly the electric cracks glow on armor.");
			ArmorSettings.GlowIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Armor", "GlowIntensity", 0.04f, "A faint even charge under the cracks. 0 = none.");
			ArmorSettings.CrackTiles = ((BaseUnityPlugin)this).Config.Bind<float>("Armor", "CrackTiles", 1.5f, "How many crack strips fit across the armor's texture. Higher = finer, more repeated cracks.");
			CapeSettings = new GearGroup
			{
				Tag = "Capes"
			};
			CapeSettings.CrackTexture = ((BaseUnityPlugin)this).Config.Bind<bool>("Capes", "CrackTexture", true, "Glowing electric cracks (the same pattern as on the maces) across the cape you wear while a Thunderbrand mace is held.");
			CapeSettings.CrackIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Capes", "CrackIntensity", 0.45f, "How brightly the electric cracks glow on capes.");
			CapeSettings.GlowIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Capes", "GlowIntensity", 0.04f, "A faint even charge under the cracks. 0 = none.");
			CapeSettings.CrackTiles = ((BaseUnityPlugin)this).Config.Bind<float>("Capes", "CrackTiles", 1.5f, "How many crack strips fit across the cape's texture. Higher = finer, more repeated cracks.");
		}

		private void BindCloning()
		{
			CloneModdedItems = ((BaseUnityPlugin)this).Config.Bind<bool>("Cloning", "CloneModdedItems", false, "Off (default): only the vanilla maces, clubs and sledges get Thunderbrand versions, plus anything named in Maces/ExtraMaces. On: also look for maces that other mods add and clone those too (needs Maces/CloneEveryMace on as well). Takes effect on the next start of the game.");
			CloneRequireRecipe = ((BaseUnityPlugin)this).Config.Bind<bool>("Cloning", "RequireRecipe", false, "Only clone maces that already have a crafting recipe when this mod looks. Off by default, because mods add their recipes later and would look uncraftable, and because some vanilla maces are not crafted at all. On = leaves out weapons only monsters carry.");
			CloneExclude = ((BaseUnityPlugin)this).Config.Bind<string>("Cloning", "ExcludeNames", "Cheat,Debug", "Comma separated name fragments; any mace whose prefab name contains one is never cloned (items already named Thunderbrand never are). Applies to the maces found automatically, not to the ones on the built-in list or in Maces/ExtraMaces. Maces that already do lightning damage (the Thunderblood ones, Storm Star) are always left alone.");
			MacesCloneAll = ((BaseUnityPlugin)this).Config.Bind<bool>("Maces", "CloneEveryMace", true, "Besides the built-in list of vanilla maces, clone every other one-handed and two-handed club-skill weapon in the game, including ones other mods add. Takes effect on the next start of the game.");
			MacesExtra = ((BaseUnityPlugin)this).Config.Bind<string>("Maces", "ExtraMaces", "", "Comma separated prefab names of more weapons to clone (for example a weapon that doesn't use the club skill). The log lists the maces that were left alone as [Maces].");
		}

		internal static List<GameObject> AllItemPrefabs()
		{
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			List<GameObject> list = new List<GameObject>();
			HashSet<string> hashSet = new HashSet<string>();
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			if ((Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items != null)
			{
				foreach (GameObject item in ObjectDB.instance.m_items)
				{
					if ((Object)(object)item != (Object)null && hashSet.Add(((Object)item).name))
					{
						list.Add(item);
						num++;
					}
				}
			}
			try
			{
				object value = Traverse.Create((object)ItemManager.Instance).Field("Items").GetValue();
				object obj;
				if (!(value is IDictionary dictionary))
				{
					obj = value as IEnumerable;
				}
				else
				{
					IEnumerable values = dictionary.Values;
					obj = values;
				}
				IEnumerable enumerable = (IEnumerable)obj;
				if (enumerable != null)
				{
					foreach (object item2 in enumerable)
					{
						CustomItem val = (CustomItem)((item2 is CustomItem) ? item2 : null);
						GameObject val2 = ((val != null) ? val.ItemPrefab : null);
						if ((Object)(object)val2 != (Object)null && hashSet.Add(((Object)val2).name))
						{
							list.Add(val2);
							num2++;
						}
					}
				}
			}
			catch (Exception)
			{
			}
			try
			{
				ItemDrop[] array = Resources.FindObjectsOfTypeAll<ItemDrop>();
				foreach (ItemDrop val3 in array)
				{
					if ((Object)(object)val3 == (Object)null)
					{
						continue;
					}
					GameObject gameObject = ((Component)val3).gameObject;
					Scene scene = gameObject.scene;
					if (((Scene)(ref scene)).IsValid())
					{
						scene = gameObject.scene;
						if (((Scene)(ref scene)).name != "DontDestroyOnLoad")
						{
							continue;
						}
					}
					if (hashSet.Add(((Object)gameObject).name))
					{
						list.Add(gameObject);
						num3++;
					}
				}
			}
			catch (Exception ex2)
			{
				Log.LogInfo((object)("[Items] could not scan the loaded prefabs: " + ex2.GetType().Name + ": " + ex2.Message));
			}
			itemIndex = new Dictionary<string, GameObject>();
			foreach (GameObject item3 in list)
			{
				itemIndex[((Object)item3).name] = item3;
			}
			if (!itemSourcesLogged)
			{
				itemSourcesLogged = true;
				Verbose("[Items] " + list.Count + " item prefabs: " + num + " from the item database, " + num2 + " from other Jotunn mods, " + num3 + " more loaded from asset bundles");
			}
			return list;
		}

		internal static GameObject FindItemLoose(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return null;
			}
			GameObject val = FindItemPrefab(name);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			string text = LooseKey(name);
			foreach (GameObject item in AllItemPrefabs())
			{
				if ((Object)(object)item != (Object)null && LooseKey(((Object)item).name) == text)
				{
					return item;
				}
			}
			return null;
		}

		private static string LooseKey(string s)
		{
			return s.Replace("_", "").Replace(" ", "").ToLowerInvariant();
		}

		internal static GameObject FindItemPrefab(string name)
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(name);
			if ((Object)(object)prefab != (Object)null)
			{
				return prefab;
			}
			if (itemIndex == null)
			{
				AllItemPrefabs();
			}
			if (itemIndex == null || !itemIndex.TryGetValue(name, out var value))
			{
				return null;
			}
			return value;
		}

		internal static GameObject CloneItem(string newName, string baseName, GameObject basePrefab)
		{
			if ((Object)(object)PrefabManager.Instance.GetPrefab(baseName) != (Object)null)
			{
				return PrefabManager.Instance.CreateClonedPrefab(newName, baseName);
			}
			return PrefabManager.Instance.CreateClonedPrefab(newName, basePrefab);
		}

		internal static Dictionary<string, Recipe> RecipeIndex()
		{
			if (recipeIndex != null)
			{
				return recipeIndex;
			}
			Dictionary<string, Recipe> dictionary = new Dictionary<string, Recipe>();
			if ((Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_recipes != null)
			{
				foreach (Recipe recipe in ObjectDB.instance.m_recipes)
				{
					if (!((Object)(object)recipe == (Object)null) && !((Object)(object)recipe.m_item == (Object)null))
					{
						string name = ((Object)((Component)recipe.m_item).gameObject).name;
						if (!dictionary.ContainsKey(name))
						{
							dictionary[name] = recipe;
						}
					}
				}
			}
			if (dictionary.Count > 0)
			{
				recipeIndex = dictionary;
			}
			return dictionary;
		}

		internal static void StationFor(string baseName, string defaultStation, int defaultLevel, out string station, out int level)
		{
			station = defaultStation;
			level = defaultLevel;
			if (RecipeIndex().TryGetValue(baseName, out var value) && (Object)(object)value.m_craftingStation != (Object)null && (Object)(object)((Component)value.m_craftingStation).gameObject != (Object)null)
			{
				station = ((Object)((Component)value.m_craftingStation).gameObject).name;
				level = Mathf.Max(1, value.m_minStationLevel);
			}
		}

		internal static void FixRecipeStations()
		{
			if (AutoBases.Count == 0 || (Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_recipes == null)
			{
				return;
			}
			Dictionary<string, Recipe> dictionary = new Dictionary<string, Recipe>();
			foreach (Recipe recipe in ObjectDB.instance.m_recipes)
			{
				if (!((Object)(object)recipe == (Object)null) && !((Object)(object)recipe.m_item == (Object)null))
				{
					string name = ((Object)((Component)recipe.m_item).gameObject).name;
					if (!dictionary.ContainsKey(name))
					{
						dictionary[name] = recipe;
					}
				}
			}
			int num = 0;
			foreach (KeyValuePair<string, string> autoBasis in AutoBases)
			{
				if (dictionary.TryGetValue(autoBasis.Key, out var value) && dictionary.TryGetValue(autoBasis.Value, out var value2) && !((Object)(object)value2.m_craftingStation == (Object)null))
				{
					int num2 = Mathf.Max(1, value2.m_minStationLevel);
					if (!((Object)(object)value.m_craftingStation == (Object)(object)value2.m_craftingStation) || value.m_minStationLevel != num2)
					{
						value.m_craftingStation = value2.m_craftingStation;
						value.m_repairStation = (((Object)(object)value2.m_repairStation != (Object)null) ? value2.m_repairStation : value2.m_craftingStation);
						value.m_minStationLevel = num2;
						num++;
					}
				}
			}
			if (num > 0 && !stationsFixLogged)
			{
				stationsFixLogged = true;
				Verbose("[Cloning] set the forging station of " + num + " Thunderbrand recipes to match the items they are made from");
			}
		}

		internal static void DedupeRecipes()
		{
			if ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_recipes == null)
			{
				return;
			}
			List<Recipe> recipes = ObjectDB.instance.m_recipes;
			HashSet<string> hashSet = new HashSet<string>();
			List<int> list = new List<int>();
			for (int i = 0; i < recipes.Count; i++)
			{
				Recipe val = recipes[i];
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.m_item == (Object)null))
				{
					string name = ((Object)((Component)val.m_item).gameObject).name;
					if (name.EndsWith("_Thunderbrand") && !hashSet.Add(name))
					{
						list.Add(i);
					}
				}
			}
			for (int num = list.Count - 1; num >= 0; num--)
			{
				recipes.RemoveAt(list[num]);
			}
			if (list.Count > 0 && !dedupeLogged)
			{
				dedupeLogged = true;
				Log.LogInfo((object)("[Cloning] took " + list.Count + " duplicate Thunderbrand recipes out of the crafting list"));
			}
		}

		internal static bool NameExcluded(string prefab)
		{
			if (prefab.IndexOf("Thunderbrand", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			string text = ((CloneExclude != null) ? CloneExclude.Value : "");
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			string[] array = text.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (text2.Length > 0 && prefab.IndexOf(text2, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return true;
				}
			}
			return false;
		}

		internal static string LocalizedName(GameObject basePrefab)
		{
			try
			{
				ItemDrop val = (((Object)(object)basePrefab != (Object)null) ? basePrefab.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val == (Object)null || val.m_itemData == null || val.m_itemData.m_shared == null)
				{
					return null;
				}
				string name = val.m_itemData.m_shared.m_name;
				if (string.IsNullOrEmpty(name))
				{
					return null;
				}
				string text = Translate(name);
				if (string.IsNullOrEmpty(text) || text.IndexOf('$') >= 0 || text.StartsWith("["))
				{
					return null;
				}
				return TitleCase(text.Trim());
			}
			catch (Exception)
			{
				return null;
			}
		}

		private static string Translate(string token)
		{
			try
			{
				if (!localizationLooked)
				{
					localizationLooked = true;
					localizationType = AccessTools.TypeByName("Localization");
					if (localizationType != null)
					{
						localizationInstanceProp = AccessTools.Property(localizationType, "instance");
						if (localizationInstanceProp == null)
						{
							localizationInstanceField = AccessTools.Field(localizationType, "instance");
						}
						localizeMethod = AccessTools.Method(localizationType, "Localize", new Type[1] { typeof(string) }, (Type[])null);
					}
				}
				if (localizeMethod == null)
				{
					return token;
				}
				object obj = ((localizationInstanceProp != null) ? localizationInstanceProp.GetValue(null, null) : ((localizationInstanceField != null) ? localizationInstanceField.GetValue(null) : null));
				if (obj == null)
				{
					return token;
				}
				return (localizeMethod.Invoke(obj, new object[1] { token }) as string) ?? token;
			}
			catch (Exception)
			{
				return token;
			}
		}

		internal static string AutoDisplayName(GameObject basePrefab, string baseName)
		{
			string text = LocalizedName(basePrefab);
			if (!string.IsNullOrEmpty(text))
			{
				return "Thunderbrand " + text;
			}
			string text2 = Humanize(baseName);
			return "Thunderbrand " + ((text2.Length > 0) ? text2 : baseName);
		}

		private static string TitleCase(string text)
		{
			string[] array = text.Split(new char[1] { ' ' });
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i];
				if (text2.Length == 0)
				{
					continue;
				}
				if (i > 0)
				{
					switch (text2)
					{
					case "of":
					case "the":
					case "and":
					case "in":
						continue;
					}
					if (text2 == "on")
					{
						continue;
					}
				}
				if (char.IsLower(text2[0]))
				{
					array[i] = char.ToUpperInvariant(text2[0]) + text2.Substring(1);
				}
			}
			return string.Join(" ", array);
		}

		internal static string Humanize(string prefab)
		{
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < prefab.Length; i++)
			{
				char c = prefab[i];
				if (c == '_' || c == '-')
				{
					stringBuilder.Append(' ');
					continue;
				}
				if (i > 0 && char.IsUpper(c) && char.IsLower(prefab[i - 1]))
				{
					stringBuilder.Append(' ');
				}
				stringBuilder.Append(c);
			}
			return stringBuilder.ToString().Trim();
		}

		private void BindGear()
		{
			GearWithMace = ((BaseUnityPlugin)this).Config.Bind<bool>("Gear", "ElectricWhileHoldingThunderbrand", true, "While a Thunderbrand mace is held, the armor, capes, shield and skin being worn get the electric cracks, arcs of lightning crawl over the body, and the shield shocks what strikes it. Settings for the look are in the Armor, Capes, Shields and Skin sections. Off = nothing changes on the player when a mace is drawn.");
			GearFlare = ((BaseUnityPlugin)this).Config.Bind<bool>("Gear", "FlashWhenDrawn", true, "Lightning cracks out around a player when they take up a Thunderbrand mace, so the electric look on their gear doesn't just appear. Every player with the mod sees it on everybody.");
			BodyArcs = ((BaseUnityPlugin)this).Config.Bind<bool>("Gear", "BodyArcs", true, "Arcs of lightning crawl over the body of a player holding a Thunderbrand mace, with sparks flying off. Every player with the mod sees them on everybody.");
			BodyArcCount = ((BaseUnityPlugin)this).Config.Bind<int>("Gear", "BodyArcCount", 3, "How many arcs can be alive on one player at a time.");
			BodyLight = ((BaseUnityPlugin)this).Config.Bind<float>("Gear", "BodyLight", 0.5f, "Brightness of the faint blue light around a player holding a Thunderbrand mace. 0 = no light.");
			SkinCracks = ((BaseUnityPlugin)this).Config.Bind<bool>("Skin", "Cracks", true, "While a Thunderbrand mace is held, the skin of the character gets the same glowing electric cracks as the gear. It needs the skin's material to have a place for glow; the BepInEx log says as [Skin] whether it does (with Debug/VerboseLog on). The body arcs play either way. Off = no change to the skin.");
			SkinCrackIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Skin", "CrackIntensity", 0.4f, "How brightly the electric cracks glow on skin.");
			SkinGlowIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Skin", "GlowIntensity", 0.03f, "A faint even charge under the cracks. 0 = none.");
			SkinCrackTiles = ((BaseUnityPlugin)this).Config.Bind<float>("Skin", "CrackTiles", 1.5f, "How many crack strips fit across the skin's texture. Higher = finer, more repeated cracks.");
		}

		internal static float RoundShieldFactor(GameObject shieldPrefab)
		{
			if ((Object)(object)shieldPrefab == (Object)null || !ShieldResize.Value || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return 1f;
			}
			if (shieldFactors.TryGetValue(((Object)shieldPrefab).name, out var value))
			{
				return value;
			}
			if (shieldTarget < 0f)
			{
				float roundness;
				float num = FaceSize(ObjectDB.instance.GetItemPrefab("ShieldSilver"), out roundness);
				float num2 = FaceSize(ObjectDB.instance.GetItemPrefab("ShieldBanded"), out roundness);
				shieldTarget = 0f;
				if (num > 0f && num2 > 0f)
				{
					shieldTarget = Mathf.Lerp(num, num2, Mathf.Clamp(ShieldSizeBetween.Value, 0f, 1.5f));
					Verbose("[Shields] Silver face " + num.ToString("0.000") + ", Banded face " + num2.ToString("0.000") + " -> round shields are brought to " + shieldTarget.ToString("0.000"));
				}
				else
				{
					Log.LogWarning((object)"[Shields] could not measure the Silver and Banded shields; round shields keep their size.");
				}
			}
			float num3 = 1f;
			float roundness2;
			float num4 = FaceSize(shieldPrefab, out roundness2);
			if (shieldTarget > 0f && num4 > 0f && roundness2 >= 0.85f)
			{
				num3 = Mathf.Clamp(shieldTarget / num4, 0.5f, 2f);
			}
			shieldFactors[((Object)shieldPrefab).name] = num3;
			Verbose("[Shields] " + ((Object)shieldPrefab).name + ": size " + num4.ToString("0.000") + ", roundness " + roundness2.ToString("0.00") + ((Mathf.Abs(num3 - 1f) > 0.005f) ? (" -> round, scaled x" + num3.ToString("0.00")) : " -> size kept"));
			return num3;
		}

		private void BindLeap()
		{
			LeapEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Leap", "Enabled", true, "Jumping while a Thunderbrand mace is in your hand launches you high into the air. Off = normal jumps.");
			LeapHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Leap", "HeightMeters", 7.1f, "How high the leap carries you, in meters, measured from where you took off. 7.1 m is about 23 feet.");
			LeapForward = ((BaseUnityPlugin)this).Config.Bind<float>("Leap", "ForwardSpeed", 10f, "Extra speed (m/s) added in the direction you are moving, or facing if you stand still, when you leap, so it is a bound forward and not just a jump straight up. 0 = the leap goes as far sideways as your normal jump would.");
			LeapStamina = ((BaseUnityPlugin)this).Config.Bind<float>("Leap", "ExtraStaminaCost", 0f, "Stamina a leap costs on top of the normal jump. If you don't have it you get a normal jump instead. 0 = free.");
			LeapCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Leap", "CooldownSeconds", 0.5f, "Seconds after landing before the next jump can leap again (a jump in between is a normal jump). 0 = none.");
			LeapLanding = ((BaseUnityPlugin)this).Config.Bind<bool>("Leap", "StrikeOnLanding", true, "Where you land, the same bolt of lightning (and mace impact) as the secondary attack and the thrown mace, with the same radius and lightning damage. Turn the strike itself off under [Strike] Enabled.");
			LeapTrailOn = ((BaseUnityPlugin)this).Config.Bind<bool>("Leap", "Trail", true, "Arcs of lightning and sparks trail behind you during the leap. Other players who run this mod see it too (Multiplayer settings).");
			LeapTrailSize = ((BaseUnityPlugin)this).Config.Bind<float>("Leap", "TrailSize", 1.5f, "Size of the trail. 1 = about the size of your body; lower is slimmer, higher is bigger.");
			LeapLight = ((BaseUnityPlugin)this).Config.Bind<float>("Leap", "TrailLight", 3f, "Brightness of the blue light that travels with you during the leap. 0 = none.");
		}

		private void BindNet()
		{
			ShareMyEffects = ((BaseUnityPlugin)this).Config.Bind<bool>("Multiplayer", "ShareMyEffects", true, "Send my thrown mace, lightning strikes, hit sparks, leap trail and shocked enemies to the other players so they see them too.");
			ShowOthersEffects = ((BaseUnityPlugin)this).Config.Bind<bool>("Multiplayer", "ShowOthersEffects", true, "Show the effects other players send me: their thrown maces, strikes, hit sparks, leap trails and shocked enemies.");
		}

		internal static void Verbose(string message)
		{
			if (VerboseLog != null && VerboseLog.Value && Log != null)
			{
				Log.LogInfo((object)message);
			}
		}

		private void Awake()
		{
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0749: Unknown result type (might be due to invalid IL or missing references)
			//IL_074e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0759: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			VerboseLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "VerboseLog", false, "Write detailed diagnostic lines to the BepInEx log (what the mod found in the game, which other mods hook attacks, every strike and leap). Turn on when reporting a problem; leave off otherwise.");
			LightningRatio = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "LightningRatio", 0.5f, "Lightning damage added = this fraction of the base mace's total vanilla damage (blunt + slash + pierce + true). Same ratio is applied to damage per upgrade level.");
			FlatLightningBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "FlatLightningBonus", 0f, "Extra flat lightning damage added on top of the ratio-based amount.");
			RecipeItem1 = ((BaseUnityPlugin)this).Config.Bind<string>("Recipe", "Material1", "Thunderstone", "Item (prefab name) needed besides the base mace: Thunder Stones, which Haldor sells. Empty = not used. Every Thunderbrand mace is forged at the same station and level as the mace it comes from, and needs that mace as well.");
			RecipeAmount1 = ((BaseUnityPlugin)this).Config.Bind<int>("Recipe", "Amount1", 3, "How many of Material1.");
			RecipePerLevel1 = ((BaseUnityPlugin)this).Config.Bind<int>("Recipe", "AmountPerUpgrade1", 1, "Extra Material1 per upgrade level.");
			RecipeItem2 = ((BaseUnityPlugin)this).Config.Bind<string>("Recipe", "Material2", "TrophyEikthyr", "Second item (prefab name) needed: Eikthyr's trophy, the stag of lightning. Empty = not used.");
			RecipeAmount2 = ((BaseUnityPlugin)this).Config.Bind<int>("Recipe", "Amount2", 1, "How many of Material2.");
			RecipePerLevel2 = ((BaseUnityPlugin)this).Config.Bind<int>("Recipe", "AmountPerUpgrade2", 0, "Extra Material2 per upgrade level.");
			GlowHeads = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "GlowHeads", true, "Add a faint electric glow to the mace head only (the handle is left untouched).");
			GlowIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "GlowIntensity", 0.12f, "Head glow strength. ~0.1 is a faint blue charge, ~0.3 a clear glow, 1+ starts to look like a lightsaber.");
			CrackTexture = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "CrackTexture", true, "Head glow as glowing electric cracks (a web of branching bolts) instead of one even tint. Needs GlowHeads on.");
			CrackIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "CrackIntensity", 0.5f, "Brightness of the electric cracks. GlowIntensity still sets the faint even charge underneath them. ~0.5 = subtle glowing cracks, ~1 = bright, 1.5+ gets very bright.");
			LightMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "LightMultiplier", 1f, "Brightness of the flickering blue light a mace gives off. 0 removes the light.");
			ArcsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "Arcs", true, "Arcs of lightning that jump off the mace head all the time, and flare up in a swing.");
			ArcCount = ((BaseUnityPlugin)this).Config.Bind<int>("Visuals", "ArcCount", 3, "How many arcs can be alive on one mace at a time.");
			ArcScale = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "ArcScale", 1f, "Length and width of the arcs. Lower = small crackles, higher = long bolts.");
			SparkAmount = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "SparkAmount", 1f, "How many sparks the mace head throws off. 0 = none.");
			TrailEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Trail", "Enabled", true, "Sparks and crackling bolts behind the head during swings (and while a thrown mace flies).");
			TrailMinSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Trail", "MinHeadSpeed", 3f, "Head speed (m/s) needed before the trail shows. Lower = trail appears earlier in a swing.");
			TrailSize = ((BaseUnityPlugin)this).Config.Bind<float>("Trail", "ParticleSize", 0.06f, "Size of each trail spark.");
			TrailLifetime = ((BaseUnityPlugin)this).Config.Bind<float>("Trail", "Lifetime", 0.3f, "How long trail sparks linger, in seconds.");
			TrailDensity = ((BaseUnityPlugin)this).Config.Bind<float>("Trail", "Density", 1f, "How many trail particles are spawned. 2 = twice as thick.");
			ImpactEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Impact", "Enabled", true, "Burst of sparks, a crack of lightning and a quick flash where a swing (or throw) connects. Other players see yours too (Multiplayer settings).");
			ImpactParticles = ((BaseUnityPlugin)this).Config.Bind<int>("Impact", "Particles", 28, "Sparks per impact.");
			ImpactLight = ((BaseUnityPlugin)this).Config.Bind<float>("Impact", "FlashLight", 2.5f, "Brightness of the impact flash. 0 = no light.");
			ThrowEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Throw", "Enabled", true, "Allow throwing and recalling Thunderbrand maces.");
			ThrowKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Throw", "ThrowKey", new KeyboardShortcut((KeyCode)102, Array.Empty<KeyCode>()), "Throws the Thunderbrand mace in your hand. Press it again while the mace is out to call it back. Any key or mouse button (e.g. Mouse3, Mouse4). Set to None to disable.");
			RecallKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Throw", "RecallKey", new KeyboardShortcut((KeyCode)102, Array.Empty<KeyCode>()), "Calls the thrown mace back to your hand; it hits enemies on the way. Same key as the throw by default; give it its own key to separate them. Set to None to disable.");
			ThrowKeyAlsoRecalls = ((BaseUnityPlugin)this).Config.Bind<bool>("Throw", "ThrowKeyAlsoRecalls", true, "Pressing the throw key while a mace is out also calls it back.");
			ThrowStamina = ((BaseUnityPlugin)this).Config.Bind<float>("Throw", "StaminaCost", 15f, "Stamina used per throw.");
			ThrowSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Throw", "ThrowSpeed", 32f, "Flight speed in m/s.");
			ThrowRange = ((BaseUnityPlugin)this).Config.Bind<float>("Throw", "Range", 40f, "Distance in meters before the mace drops.");
			ReturnSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Throw", "ReturnSpeed", 45f, "Top speed of the mace flying home, in m/s.");
			ThrowDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Throw", "DamageMultiplier", 1f, "Thrown hit damage relative to a normal swing of the same mace (lightning included).");
			SpinSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Throw", "SpinDegreesPerSecond", 540f, "Tumble speed while flying. 0 = flies head-first.");
			AutoRecallSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Throw", "AutoRecallSeconds", 15f, "A mace stuck in the ground flies back by itself after this many seconds. 0 = only when you recall it.");
			ThrowAnimationEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Throw", "PlayThrowAnimation", true, "Play a throwing animation and release the mace at the end of it.");
			ThrowAnimationName = ((BaseUnityPlugin)this).Config.Bind<string>("Throw", "ThrowAnimation", "spear_throw", "Animator trigger used for the throw. spear_throw is vanilla's spear throw.");
			ThrowReleaseDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Throw", "ReleaseDelay", 0.7f, "Seconds between the throw animation starting and the mace leaving your hand.");
			RecallEmote = ((BaseUnityPlugin)this).Config.Bind<string>("Throw", "RecallEmote", "point", "Emote played while you call the mace back: an arm stretched out to catch it. Vanilla emote names: point, wave, challenge, cheer, comfort, flex... Empty = no animation. Standing still lets it play fully; moving ends an emote.");
			RecallDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Throw", "RecallDelay", 0.3f, "Seconds the mace hangs and shudders before it flies back, so the arm is out first.");
			StrikeEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Strike", "Enabled", true, "A bolt of lightning (with thunder) where the secondary attack lands and where a thrown mace first hits something.");
			StrikeOnSecondary = ((BaseUnityPlugin)this).Config.Bind<bool>("Strike", "OnSecondaryAttack", true, "Strike where the secondary (smash) attack lands.");
			StrikeOnThrow = ((BaseUnityPlugin)this).Config.Bind<bool>("Strike", "OnThrownHit", true, "Strike where a thrown mace first touches an enemy or the world.");
			MaceImpactOnThrow = ((BaseUnityPlugin)this).Config.Bind<bool>("Strike", "MaceImpactOnThrownHit", true, "Where a thrown mace first lands (or a leap comes down) also play the mace's own smash effects: its ground and hit effects and whatever the smash spawns. They always lie flat (horizontal), whatever the ground or the mace's angle. The log lists them as [MaceImpact].");
			StrikeRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Strike", "Radius", 4f, "Strike radius in meters.");
			StrikeDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Strike", "DamageMultiplier", 1f, "Strike lightning damage as a multiple of the mace's own lightning damage. Enemies at the edge of the strike take less.");
			StrikePush = ((BaseUnityPlugin)this).Config.Bind<float>("Strike", "PushForce", 40f, "How hard the strike shoves enemies away.");
			StrikeLight = ((BaseUnityPlugin)this).Config.Bind<float>("Strike", "FlashLight", 5f, "Brightness of the flash. 0 = none.");
			StrikeEffectLifetime = ((BaseUnityPlugin)this).Config.Bind<float>("Strike", "EffectLifetime", 5f, "How long the ground a strike hits keeps crackling with electricity, in seconds.");
			StrikeUseVanillaEffects = ((BaseUnityPlugin)this).Config.Bind<bool>("Strike", "UseVanillaEffects", true, "Also play the sounds and effects of the game's own lightning (see VanillaEffects) on top of the strike.");
			StrikeVanillaEffects = ((BaseUnityPlugin)this).Config.Bind<string>("Strike", "VanillaEffects", "fx_eikthyr_stomp,fx_Lightning", "Comma separated names of the game's effect prefabs to play at a strike. Names the game doesn't have are skipped (the log says so with Debug/VerboseLog on). Empty = none.");
			Harmony val = new Harmony("brett.macethunderbrand");
			val.PatchAll();
			ShieldAttachPatch.Apply(val);
			BindCloning();
			BindShields();
			BindArmor();
			BindGear();
			BindSecondary();
			BindNet();
			BindShock();
			BindLeap();
			ResetLookSettingsOnce();
			PrefabManager.OnVanillaPrefabsAvailable += AddMaces;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Mace Thunderbrand loaded. Maces register through Jotunn.");
		}

		private void ResetLookSettingsOnce()
		{
			try
			{
				ConfigEntry<int> val = ((BaseUnityPlugin)this).Config.Bind<int>("Debug", "ConfigVersion", 0, "Internal: used to bring old saved settings up to date after an update. Leave it alone.");
				if (val.Value >= 3)
				{
					return;
				}
				List<ConfigEntryBase> list = new List<ConfigEntryBase>();
				if (val.Value < 2)
				{
					list.Add((ConfigEntryBase)(object)GlowIntensity);
					list.Add((ConfigEntryBase)(object)CrackIntensity);
					list.Add((ConfigEntryBase)(object)ArmorSettings.CrackTiles);
					list.Add((ConfigEntryBase)(object)CapeSettings.CrackTiles);
					list.Add((ConfigEntryBase)(object)ShieldCrackTiles);
					list.Add((ConfigEntryBase)(object)SkinCrackTiles);
				}
				list.Add((ConfigEntryBase)(object)ArmorSettings.CrackIntensity);
				list.Add((ConfigEntryBase)(object)ArmorSettings.GlowIntensity);
				list.Add((ConfigEntryBase)(object)CapeSettings.CrackIntensity);
				list.Add((ConfigEntryBase)(object)CapeSettings.GlowIntensity);
				list.Add((ConfigEntryBase)(object)ShieldCrackIntensity);
				list.Add((ConfigEntryBase)(object)ShieldGlowIntensity);
				list.Add((ConfigEntryBase)(object)SkinCrackIntensity);
				list.Add((ConfigEntryBase)(object)SkinGlowIntensity);
				foreach (ConfigEntryBase item in list)
				{
					if (item != null)
					{
						item.BoxedValue = item.DefaultValue;
					}
				}
				val.Value = 3;
				((BaseUnityPlugin)this).Config.Save();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Brought the saved glow and crack settings up to this version's defaults.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not update old saved settings: " + ex.GetType().Name + ": " + ex.Message));
			}
		}

		private void LateUpdate()
		{
			GearGlow.Size();
		}

		private void FixedUpdate()
		{
			Leap.FixedTick();
		}

		private void Update()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			SecondaryPriorityPatch.RestoreStale();
			ThunderbrandNet.Tick();
			GearGlow.Tick();
			Leap.Tick();
			if (!ThrowEnabled.Value || !ThrowSystem.InputAllowed())
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			ThrownThunderbrand active = ThrowSystem.Active;
			KeyboardShortcut value = ThrowKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				if ((Object)(object)active != (Object)null)
				{
					if (ThrowKeyAlsoRecalls.Value)
					{
						active.StartRecall();
					}
				}
				else
				{
					ThrowSystem.TryThrow(localPlayer);
				}
			}
			if ((Object)(object)active != (Object)null)
			{
				value = RecallKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					active.StartRecall();
				}
			}
		}

		private void AddMaces()
		{
			if (!CloneModdedItems.Value)
			{
				PrefabManager.OnVanillaPrefabsAvailable -= AddMaces;
			}
			List<MaceDef> list = new List<MaceDef>(MaceDef.All);
			HashSet<string> hashSet = new HashSet<string>();
			foreach (MaceDef item in list)
			{
				hashSet.Add(item.BaseName);
			}
			DiscoverMaces(list, hashSet);
			List<MaceDef> list2 = new List<MaceDef>();
			foreach (MaceDef item2 in list)
			{
				if ((Object)(object)FindItemPrefab(item2.BaseName) != (Object)null && (Object)(object)PrefabManager.Instance.GetPrefab(item2.BaseName + "_Thunderbrand") == (Object)null)
				{
					list2.Add(item2);
				}
			}
			if (list2.Count == 0)
			{
				return;
			}
			SparkMaterial = PickMaterial(PrefabManager.Instance.GetPrefab("Torch"));
			int num = 0;
			int num2 = 0;
			foreach (MaceDef item3 in list2)
			{
				try
				{
					if (MakeMace(item3))
					{
						num++;
						if (!item3.Known)
						{
							num2++;
						}
					}
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[Maces] " + item3.BaseName + " could not be cloned: " + ex.GetType().Name + ": " + ex.Message));
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Registered " + num + " thunderbrand maces (" + num2 + " found in the game, the rest from the built-in list)."));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[Maces] " + string.Join("; ", madeNames.ToArray())));
		}

		private static bool VanillaMaceName(string name)
		{
			if (!(name == "Club") && !name.StartsWith("Mace"))
			{
				return name.StartsWith("Sledge");
			}
			return true;
		}

		private void DiscoverMaces(List<MaceDef> defs, HashSet<string> known)
		{
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Invalid comparison between Unknown and I4
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Invalid comparison between Unknown and I4
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Invalid comparison between Unknown and I4
			List<string> list = new List<string>();
			string[] array = (MacesExtra.Value ?? "").Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length != 0 && !known.Contains(text))
				{
					GameObject val = FindItemPrefab(text);
					if ((Object)(object)val == (Object)null)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("[Maces] ExtraMaces: " + text + " is not in this game"));
						continue;
					}
					defs.Add(MaceDef.Auto(text, AutoDisplayName(val, text)));
					known.Add(text);
				}
			}
			if (!MacesCloneAll.Value)
			{
				return;
			}
			Dictionary<string, Recipe> dictionary = RecipeIndex();
			List<GameObject> list2 = AllItemPrefabs();
			foreach (GameObject item in list2)
			{
				ItemDrop val2 = (((Object)(object)item != (Object)null) ? item.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val2 == (Object)null || val2.m_itemData == null || val2.m_itemData.m_shared == null)
				{
					continue;
				}
				SharedData shared = val2.m_itemData.m_shared;
				if (((int)shared.m_itemType == 3 || (int)shared.m_itemType == 14) && (int)shared.m_skillType == 3 && !known.Contains(((Object)item).name) && !((Object)item).name.EndsWith("_Thunderbrand") && (VanillaMaceName(((Object)item).name) || CloneModdedItems.Value) && !AlreadyElectric(shared))
				{
					bool flag = dictionary.ContainsKey(((Object)item).name);
					if (NameExcluded(((Object)item).name) || (CloneRequireRecipe.Value && !flag))
					{
						list.Add(((Object)item).name);
						continue;
					}
					defs.Add(MaceDef.Auto(((Object)item).name, AutoDisplayName(item, ((Object)item).name)));
					known.Add(((Object)item).name);
				}
			}
			Verbose("[Maces] looked through " + list2.Count + " item prefabs: " + (defs.Count - MaceDef.All.Length) + " more maces to clone");
			if (list.Count > 0 && !macesLeftLogged)
			{
				macesLeftLogged = true;
				if (list.Count > 60)
				{
					list.RemoveRange(60, list.Count - 60);
				}
				Verbose("[Maces] club-skill weapons left alone (add a name to Maces/ExtraMaces to clone one anyway): " + string.Join(" ", list.ToArray()));
			}
		}

		private static bool AlreadyElectric(SharedData sh)
		{
			if (!(sh.m_damages.m_lightning > 0.01f))
			{
				return sh.m_damagesPerLevel.m_lightning > 0.01f;
			}
			return true;
		}

		private bool MakeMace(MaceDef def)
		{
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Expected O, but got Unknown
			GameObject val = FindItemPrefab(def.BaseName);
			if ((Object)(object)val == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Missing base mace " + def.BaseName));
				return false;
			}
			string text = def.BaseName + "_Thunderbrand";
			if ((Object)(object)PrefabManager.Instance.GetPrefab(text) != (Object)null)
			{
				return false;
			}
			ItemDrop component = val.GetComponent<ItemDrop>();
			if ((Object)(object)component != (Object)null && component.m_itemData != null && component.m_itemData.m_shared != null && AlreadyElectric(component.m_itemData.m_shared))
			{
				Verbose("[Maces] " + def.BaseName + " already does lightning damage; left alone");
				return false;
			}
			if (!def.Known)
			{
				Transform val2 = val.transform.Find("attach");
				if ((Object)(object)val2 == (Object)null || !Measure(val2, -1).Valid)
				{
					Verbose("[Maces] " + def.BaseName + " has no mace model this mod can use; skipped");
					return false;
				}
			}
			GameObject val3 = CloneItem(text, def.BaseName, val);
			if ((Object)(object)val3 == (Object)null)
			{
				return false;
			}
			ItemDrop component2 = val3.GetComponent<ItemDrop>();
			if ((Object)(object)component2 == (Object)null || component2.m_itemData == null || component2.m_itemData.m_shared == null)
			{
				return false;
			}
			SharedData shared = component2.m_itemData.m_shared;
			float num = TotalPhysical(shared.m_damages);
			float num2 = TotalPhysical(shared.m_damagesPerLevel);
			float num3 = num * LightningRatio.Value + FlatLightningBonus.Value;
			if (num3 < 1f)
			{
				num3 = 1f;
			}
			float num4 = num2 * LightningRatio.Value;
			shared.m_damages.m_lightning += num3;
			shared.m_damagesPerLevel.m_lightning += num4;
			string text2 = (def.Known ? LocalizedName(val) : null);
			string text3 = ((!string.IsNullOrEmpty(text2)) ? ("Thunderbrand " + text2) : def.DisplayName);
			if (!shownNames.Add(text3))
			{
				string text4 = text3 + " (" + Humanize(def.BaseName) + ")";
				int num5 = 2;
				while (!shownNames.Add(text4))
				{
					text4 = text3 + " (" + Humanize(def.BaseName) + " " + num5++ + ")";
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[Maces] " + def.BaseName + " has the same name as another Thunderbrand mace; it is listed as '" + text4 + "'"));
				text3 = text4;
			}
			madeNames.Add(text3 + " <- " + def.BaseName);
			shared.m_name = text3;
			shared.m_description = text3 + ": the weight and reach of the mace it was made from, charged with lightning.";
			MaceShape maceShape = MaceShape.Read(AttachRoot(val3), def.HeadStart);
			float start = maceShape.Start;
			if (def.Known && maceShape.Valid)
			{
				start = ((BaseUnityPlugin)this).Config.Bind<float>("HeadGlow", def.BaseName + "_HeadStart", maceShape.Start, "Where the head begins along the mace (0 = handle end, 1 = the striking end). Glow starts here, so the handle stays unlit. Raise it if the handle glows, lower it if the base of the head doesn't.").Value;
			}
			HeadInfo head = maceShape.Head(start);
			if (GlowHeads.Value)
			{
				Verbose(text + ": head glow parts " + GlowHeadOnly(AttachRoot(val3), head));
			}
			AddHeadComponents(val3, head);
			ItemManager.Instance.AddItem(new CustomItem(val3, true));
			StationFor(def.BaseName, def.Station, def.StationLevel, out var station, out var level);
			AddThunderbrandRecipe(component2, def.BaseName, station, level);
			AutoBases[text] = def.BaseName;
			Verbose("Registered " + text + ": base " + num + " -> +" + shared.m_damages.m_lightning + " lightning.");
			return true;
		}

		private static float TotalPhysical(DamageTypes d)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			return d.m_damage + d.m_blunt + d.m_slash + d.m_pierce;
		}

		private void AddThunderbrandRecipe(ItemDrop result, string baseName, string stationName, int stationLevel)
		{
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Expected O, but got Unknown
			ItemDrop val = Item(baseName);
			CraftingStation val2 = Station(stationName);
			if ((Object)(object)val2 == (Object)null && stationName != "forge")
			{
				val2 = Station("forge");
			}
			if ((Object)(object)result == (Object)null || (Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Recipe skipped for " + baseName));
				return;
			}
			List<Requirement> list = new List<Requirement> { Req(val, 1, 0) };
			AddMaterial(list, RecipeItem1.Value, RecipeAmount1.Value, RecipePerLevel1.Value);
			AddMaterial(list, RecipeItem2.Value, RecipeAmount2.Value, RecipePerLevel2.Value);
			string text = ((Object)((Component)result).gameObject).name + "_recipe";
			if (recipesMade.Add(text))
			{
				Recipe val3 = ScriptableObject.CreateInstance<Recipe>();
				((Object)val3).name = text;
				val3.m_item = result;
				val3.m_amount = 1;
				val3.m_enabled = true;
				val3.m_resources = list.ToArray();
				val3.m_craftingStation = val2;
				val3.m_minStationLevel = stationLevel;
				val3.m_repairStation = val2;
				ItemManager.Instance.AddRecipe(new CustomRecipe(val3, true, true));
			}
		}

		private static void AddMaterial(List<Requirement> reqs, string name, int amount, int perLevel)
		{
			if (string.IsNullOrEmpty(name) || name.Trim().Length == 0 || amount <= 0)
			{
				return;
			}
			GameObject val = FindItemLoose(name.Trim());
			ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val2 == (Object)null)
			{
				if (missingMaterials.Add(name))
				{
					Log.LogWarning((object)("[Recipe] the item '" + name + "' is not in this game; it is left out of the Thunderbrand recipes (change it under [Recipe])."));
				}
			}
			else
			{
				reqs.Add(Req(val2, amount, perLevel));
			}
		}

		private static ItemDrop Item(string name)
		{
			GameObject val = FindItemPrefab(name);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.GetComponent<ItemDrop>();
		}

		private static CraftingStation Station(string name)
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(name);
			if (!((Object)(object)prefab != (Object)null))
			{
				return null;
			}
			return prefab.GetComponent<CraftingStation>();
		}

		private static Requirement Req(ItemDrop item, int amount, int perLevel)
		{
			//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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			return new Requirement
			{
				m_resItem = item,
				m_amount = amount,
				m_amountPerLevel = perLevel
			};
		}

		internal static Material PickMaterial(GameObject root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			Material val = null;
			ParticleSystemRenderer[] componentsInChildren = root.GetComponentsInChildren<ParticleSystemRenderer>(true);
			foreach (ParticleSystemRenderer val2 in componentsInChildren)
			{
				if (!((Object)(object)((Renderer)val2).sharedMaterial == (Object)null))
				{
					string text = ((Object)val2).name.ToLowerInvariant();
					if (text.Contains("flame") || text.Contains("fire"))
					{
						return ((Renderer)val2).sharedMaterial;
					}
					if ((Object)(object)val == (Object)null)
					{
						val = ((Renderer)val2).sharedMaterial;
					}
				}
			}
			return val;
		}

		private void AddHeadComponents(GameObject mace, HeadInfo head)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			Transform val = AttachRoot(mace);
			if (!head.Valid)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)(((Object)mace).name + ": could not measure the head; no arcs, trail or throw for it."));
				return;
			}
			ThunderbrandHead thunderbrandHead = ((Component)val).gameObject.GetComponent<ThunderbrandHead>();
			if ((Object)(object)thunderbrandHead == (Object)null)
			{
				thunderbrandHead = ((Component)val).gameObject.AddComponent<ThunderbrandHead>();
			}
			thunderbrandHead.BaseLocal = head.Base;
			thunderbrandHead.TipLocal = head.Tip;
			ThunderbrandArcs thunderbrandArcs = ((Component)val).gameObject.GetComponent<ThunderbrandArcs>();
			if ((Object)(object)thunderbrandArcs == (Object)null)
			{
				thunderbrandArcs = ((Component)val).gameObject.AddComponent<ThunderbrandArcs>();
			}
			thunderbrandArcs.Points = (Vector3[])(((object)head.Points) ?? ((object)new Vector3[0]));
			thunderbrandArcs.Center = head.Center;
			thunderbrandArcs.Radius = head.Radius;
		}

		internal static bool TrailHead(Transform attach, out Vector3 b, out Vector3 t)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			b = Vector3.zero;
			t = Vector3.zero;
			if ((Object)(object)attach == (Object)null)
			{
				return false;
			}
			Transform val = attach.Find("equiped/trail/base");
			Transform val2 = attach.Find("equiped/trail/tip");
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				return false;
			}
			Matrix4x4 worldToLocalMatrix = attach.worldToLocalMatrix;
			b = ((Matrix4x4)(ref worldToLocalMatrix)).MultiplyPoint3x4(val.position);
			t = ((Matrix4x4)(ref worldToLocalMatrix)).MultiplyPoint3x4(val2.position);
			Vector3 val3 = t - b;
			return ((Vector3)(ref val3)).sqrMagnitude > 0.0001f;
		}

		internal static Transform AttachRoot(GameObject item)
		{
			Transform val = item.transform.Find("attach");
			if ((Object)(object)val == (Object)null)
			{
				val = item.transform.Find("attach_skin");
			}
			if ((Object)(object)val == (Object)null && item.transform.childCount > 0)
			{
				val = item.transform.GetChild(0);
			}
			if (!((Object)(object)val != (Object)null))
			{
				return item.transform;
			}
			return val;
		}

		internal static Span Measure(Transform root, int axis)
		{
			//IL_000c: 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_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: 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_01b6: 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_007f: 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_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_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			Span result = default(Span);
			bool flag = false;
			Bounds val = default(Bounds);
			MeshFilter[] componentsInChildren = ((Component)root).GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val2 in componentsInChildren)
			{
				if ((Object)(object)val2.sharedMesh == (Object)null || (Object)(object)((Component)val2).GetComponentInParent<ParticleSystem>() != (Object)null)
				{
					continue;
				}
				Matrix4x4 val3 = root.worldToLocalMatrix * ((Component)val2).transform.localToWorldMatrix;
				Bounds bounds = val2.sharedMesh.bounds;
				for (int j = 0; j < 8; j++)
				{
					Vector3 val4 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3(((j & 1) == 0) ? (-1f) : 1f, ((j & 2) == 0) ? (-1f) : 1f, ((j & 4) == 0) ? (-1f) : 1f));
					Vector3 val5 = ((Matrix4x4)(ref val3)).MultiplyPoint3x4(val4);
					if (!flag)
					{
						((Bounds)(ref val))..ctor(val5, Vector3.zero);
						flag = true;
					}
					else
					{
						((Bounds)(ref val)).Encapsulate(val5);
					}
				}
			}
			if (!flag)
			{
				return result;
			}
			Vector3 size = ((Bounds)(ref val)).size;
			if (axis < 0)
			{
				axis = 0;
				if (size.y > ((Vector3)(ref size))[axis])
				{
					axis = 1;
				}
				if (size.z > ((Vector3)(ref size))[axis])
				{
					axis = 2;
				}
			}
			if (((Vector3)(ref size))[axis] < 0.01f)
			{
				return result;
			}
			result.Valid = true;
			result.Axis = axis;
			Vector3 val6 = ((Bounds)(ref val)).min;
			result.Min = ((Vector3)(ref val6))[axis];
			val6 = ((Bounds)(ref val)).max;
			result.Max = ((Vector3)(ref val6))[axis];
			result.Center = ((Bounds)(ref val)).center;
			result.Size = size;
			return result;
		}

		private int GlowHeadOnly(Transform attach, HeadInfo head)
		{
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: 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_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: 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_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_0356: Unknown result type (might be due to invalid IL or missing references)
			//IL_036e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Expected O, but got Unknown
			//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_043d: Unknown result type (might be due to invalid IL or missing references)
			//IL_047d: Unknown result type (might be due to invalid IL or missing references)
			if (!head.Valid)
			{
				return 0;
			}
			Span span = head.Span;
			float num = span.Max - span.Min;
			float num2 = ((head.TipSign >= 0f) ? (span.Min + head.Start * num) : (span.Max - head.Start * num));
			int num3 = 0;
			CrackMap crackMap = (CrackTexture.Value ? CrackSource.Get() : null);
			foreach (MeshFilter item in new List<MeshFilter>(((Component)attach).GetComponentsInChildren<MeshFilter>(true)))
			{
				MeshRenderer component = ((Component)item).GetComponent<MeshRenderer>();
				Mesh val = item.sharedMesh;
				if ((Object)(object)component == (Object)null || (Object)(object)val == (Object)null || (Object)(object)((Component)item).GetComponentInParent<ParticleSystem>() != (Object)null)
				{
					continue;
				}
				if (!val.isReadable)
				{
					Mesh val2 = MeshReadback.MakeReadable(val);
					if ((Object)(object)val2 == (Object)null)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)("Mesh " + ((Object)val).name + " is not readable and could not be read back; head glow skipped for it."));
						continue;
					}
					Verbose("[Readback] " + ((Object)val).name + ": rebuilt " + val2.vertexCount + " vertices, " + val2.subMeshCount + " submeshes");
					val = val2;
				}
				Matrix4x4 val3 = attach.worldToLocalMatrix * ((Component)item).transform.localToWorldMatrix;
				Vector3[] vertices = val.vertices;
				float[] array = new float[vertices.Length];
				for (int i = 0; i < vertices.Length; i++)
				{
					int num4 = i;
					Vector3 val4 = ((Matrix4x4)(ref val3)).MultiplyPoint3x4(vertices[i]);
					array[num4] = ((Vector3)(ref val4))[span.Axis];
				}
				Mesh val5 = Object.Instantiate<Mesh>(val);
				Mesh val6 = Object.Instantiate<Mesh>(val);
				((Object)val5).name = ((Object)val).name + "_thunderbrand_handle";
				((Object)val6).name = ((Object)val).name + "_thunderbrand_head";
				((Object)val5).hideFlags = (HideFlags)(((Object)val5).hideFlags | 0x20);
				((Object)val6).hideFlags = (HideFlags)(((Object)val6).hideFlags | 0x20);
				bool flag = false;
				for (int j = 0; j < val.subMeshCount; j++)
				{
					int[] triangles = val.GetTriangles(j);
					List<int> list = new List<int>();
					List<int> list2 = new List<int>();
					for (int k = 0; k + 2 < triangles.Length; k += 3)
					{
						float num5 = (array[triangles[k]] + array[triangles[k + 1]] + array[triangles[k + 2]]) / 3f;
						List<int> obj = (((head.TipSign >= 0f) ? (num5 >= num2) : (num5 <= num2)) ? list2 : list);
						obj.Add(triangles[k]);
						obj.Add(triangles[k + 1]);
						obj.Add(triangles[k + 2]);
					}
					val5.SetTriangles(list, j);
					val6.SetTriangles(list2, j);
					if (list2.Count > 0)
					{
						flag = true;
					}
				}
				if (!flag)
				{
					continue;
				}
				item.sharedMesh = val5;
				GameObject val7 = new GameObject("ThunderbrandHeadGlow")
				{
					layer = ((Component)item).gameObject.layer
				};
				val7.transform.SetParent(((Component)item).transform, false);
				val7.AddComponent<MeshFilter>().sharedMesh = val6;
				MeshRenderer val8 = val7.AddComponent<MeshRenderer>();
				((Renderer)val8).shadowCastingMode = ((Renderer)component).shadowCastingMode;
				((Renderer)val8).receiveShadows = ((Renderer)component).receiveShadows;
				Material[] sharedMaterials = ((Renderer)component).sharedMaterials;
				Material[] array2 = (Material[])(object)new Material[sharedMaterials.Length];
				Color val9 = new Color(0.25f, 0.55f, 1f) * GlowIntensity.Value;
				Color baseGlow = val9 * 0.5f;
				for (int l = 0; l < sharedMaterials.Length; l++)
				{
					if ((Object)(object)sharedMaterials[l] == (Object)null)
					{
						continue;
					}
					Material val10 = new Material(sharedMaterials[l]);
					((Object)val10).hideFlags = (HideFlags)(((Object)val10).hideFlags | 0x20);
					val10.EnableKeyword("_EMISSION");
					bool flag2 = false;
					if (crackMap != null && l < val6.subMeshCount && val10.HasProperty("_EmissionMap"))
					{
						Texture2D val11 = UvPaint.BuildEmission(sharedMaterials[l].mainTexture, val6, l, crackMap, baseGlow, CrackIntensity.Value);
						if ((Object)(object)val11 != (Object)null)
						{
							val10.SetTexture("_EmissionMap", (Texture)(object)val11);
							if (val10.HasProperty("_EmissionColor"))
							{
								val10.SetColor("_EmissionColor", Color.white);
							}
							flag2 = true;
						}
					}
					if (!flag2 && val10.HasProperty("_EmissionColor"))
					{
						val10.SetColor("_EmissionColor", val9);
					}
					if (crackMap != null)
					{
						Verbose("[Crack] " + ((Object)val).name + " material " + l + " (" + ((Object)sharedMaterials[l]).name + "): " + (flag2 ? "electric cracks applied" : "no emission map on this shader, using the even tint"));
					}
					array2[l] = val10;
				}
				((Renderer)val8).sharedMaterials = array2;
				num3++;
			}
			return num3;
		}

		private void BindSecondary()
		{
			SecondaryPriority = ((BaseUnityPlugin)this).Config.Bind<bool>("Secondary", "PriorityOverOtherMods", true, "While a Thunderbrand mace is held, the secondary attack button (middle mouse) always swings the mace's own secondary attack. Other mods' special attacks that take over that button (NorseDemigods' Crush, Ice Shards and so on) are skipped. Off = those mods may take it over, as before.");
			TwoHandedSecondaryFrom = ((BaseUnityPlugin)this).Config.Bind<string>("Secondary", "TwoHandedSecondaryFrom", "auto", "Where the two-handed Thunderbrand maces (the sledges) get their secondary attack, the one on the middle mouse button. auto = the secondary attack of the Flametal Sledgehammer, found in the game by name. Or give the prefab name of another item to copy its secondary attack, or none to leave the sledges' secondary as the game has it. Applies each time you enter a world.");
			TwoHandedMainAttack = ((BaseUnityPlugin)this).Config.Bind<string>("Secondary", "TwoHandedMainAttack", "auto", "Which main attack (left mouse) the two-handed Thunderbrand maces swing. auto = the one of the plain sledge they were made from, except that a sledge whose main attack is just the ground slam, or which holds its weapon differently from the Flametal Sledgehammer, gets the Flametal Sledgehammer's main attack so both buttons play. flametal = always the Flametal Sledgehammer's. own = always the plain sledge's. Applies each time you enter a world.");
		}

		internal static string AttackName(Attack attack)
		{
			if (attack != null && !string.IsNullOrEmpty(attack.m_attackAnimation))
			{
				return attack.m_attackAnimation;
			}
			return "none";
		}

		internal static void SyncTwoHanded()
		{
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Invalid comparison between Unknown and I4
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: 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_0223: Unknown result type (might be due to invalid IL or missing references)
			ObjectDB instance = ObjectDB.instance;
			if ((Object)(object)instance == (Object)null || instance.m_items == null || AutoBases.Count == 0)
			{
				return;
			}
			string text = ((TwoHandedSecondaryFrom != null && TwoHandedSecondaryFrom.Value != null) ? TwoHandedSecondaryFrom.Value.Trim() : "auto");
			bool flag = text.Equals("none", StringComparison.OrdinalIgnoreCase);
			string text2 = ((TwoHandedMainAttack != null && TwoHandedMainAttack.Value != null) ? TwoHandedMainAttack.Value.Trim().ToLowerInvariant() : "auto");
			SharedData val = null;
			string foundName = null;
			if (!flag)
			{
				val = FindSecondarySource(instance, text, out foundName);
			}
			bool flag2 = val != null && val.m_attack != null && !string.IsNullOrEmpty(val.m_attack.m_attackAnimation);
			int num = 0;
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, string> autoBasis in AutoBases)
			{
				GameObject itemPrefab = instance.GetItemPrefab(autoBasis.Key);
				GameObject itemPrefab2 = instance.GetItemPrefab(autoBasis.Value);
				ItemDrop val2 = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
				ItemDrop val3 = (((Object)(object)itemPrefab2 != (Object)null) ? itemPrefab2.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || val2.m_itemData == null || val3.m_itemData == null)
				{
					continue;
				}
				SharedData shared = val2.m_itemData.m_shared;
				SharedData shared2 = val3.m_itemData.m_shared;
				if (shared == null || shared2 == null || (int)shared.m_itemType != 14)
				{
					continue;
				}
				num++;
				bool flag3 = shared2.m_attack != null && !string.IsNullOrEmpty(shared2.m_attack.m_attackAnimation);
				bool flag4 = false;
				string text3 = "the plain sledge's";
				if (val != null && flag2)
				{
					if (text2 == "flametal")
					{
						flag4 = true;
						text3 = "chosen in the config";
					}
					else if (text2 != "own")
					{
						if (!flag3)
						{
							flag4 = true;
							text3 = "the plain sledge has none";
						}
						else if (shared2.m_animationState != val.m_animationState)
						{
							flag4 = true;
							text3 = "the plain sledge is held differently (" + ((object)Unsafe.As<AnimationState, AnimationState>(ref shared2.m_animationState)/*cast due to .constrained prefix*/).ToString() + " against " + ((object)Unsafe.As<AnimationState, AnimationState>(ref val.m_animationState)/*cast due to .constrained prefix*/).ToString() + ")";
						}
						else if (shared2.m_attack.m_attackAnimation == val.m_secondaryAttack.m_attackAnimation)
						{
							flag4 = true;
							text3 = "the plain sledge's main attack is the ground slam";
						}
					}
				}
				if (flag4)
				{
					shared.m_attack = val.m_attack.Clone();
					shared.m_animationState = val.m_animationState;
				}
				else if (flag3)
				{
					shared.m_attack = shared2.m_attack.Clone();
					shared.m_animationState = shared2.m_animationState;
				}
				if (val != null)
				{
					shared.m_secondaryAttack = val.m_secondaryAttack.Clone();
					if (shared.m_animationState != val.m_animationState)
					{
						text3 = text3 + "; held differently from " + foundName + ", so its secondary may not play";
					}
				}
				list.Add(autoBasis.Key + ": main " + AttackName(shared.m_attack) + " (" + text3 + "), secondary " + AttackName(shared.m_secondaryAttack) + ", held as " + ((object)Unsafe.As<AnimationState, AnimationState>(ref shared.m_animationState)/*cast due to .constrained prefix*/).ToString());
			}
			if (twoHandedLogged)
			{
				return;
			}
			twoHandedLogged = true;
			if (num == 0)
			{
				return;
			}
			if (val != null)
			{
				Log.LogInfo((object)("[TwoHanded] " + num + " two-handed Thunderbrand maces use the secondary attack of " + foundName + " (main " + AttackName(val.m_attack) + ", secondary " + AttackName(val.m_secondaryAttack) + ", held as " + ((object)Unsafe.As<AnimationState, AnimationState>(ref val.m_animationState)/*cast due to .constrained prefix*/).ToString() + ")"));
			}
			else if (!flag)
			{
				LogSecondaryCandidates(instance, text);
			}
			foreach (string item in list)
			{
				Log.LogInfo((object)("[TwoHanded] " + item));
			}
		}

		private static SharedData FindSecondarySource(ObjectDB db, string setting, out string foundName)
		{
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Invalid comparison between Unknown and I4
			foundName = null;
			bool flag = setting.Length == 0 || setting.Equals("auto", StringComparison.OrdinalIgnoreCase);
			SharedData result = null;
			int num = 0;
			foreach (GameObject item in db.m_items)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				ItemDrop component = item.GetComponent<ItemDrop>();
				if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null)
				{
					continue;
				}
				string name = ((Object)item).name;
				if (name.EndsWith("_Thunderbrand"))
				{
					continue;
				}
				SharedData shared = component.m_itemData.m_shared;
				if (shared.m_secondaryAttack == null || string.IsNullOrEmpty(shared.m_secondaryAttack.m_attackAnimation))
				{
					continue;
				}
				int num2 = 0;
				if (!flag)
				{
					if (name.Equals(setting, StringComparison.OrdinalIgnoreCase))
					{
						num2 = 100;
					}
				}
				else
				{
					string text = (name + " " + Translate(shared.m_name)).ToLowerInvariant();
					if (text.Contains("flametal") && text.Contains("sledge"))
					{
						num2 = 60;
					}
					else if (text.Contains("flametal") && text.Contains("hammer"))
					{
						num2 = 50;
					}
					if (num2 > 0 && (int)shared.m_itemType == 14)
					{
						num2 += 10;
					}
				}
				if (num2 > num)
				{
					num = num2;
					result = shared;
					foundName = name;
				}
			}
			return result;
		}

		private static void LogSecondaryCandidates(ObjectDB db, string setting)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Invalid comparison between Unknown and I4
			List<string> list = new List<string>();
			foreach (GameObject item in db.m_items)
			{
				if ((Object)(object)item == (Object)null || ((Object)item).name.EndsWith("_Thunderbrand"))
				{
					continue;
				}
				ItemDrop component = item.GetComponent<ItemDrop>();
				if (!((Object)(object)component == (Object)null) && component.m_itemData != null && component.m_itemData.m_shared != null)
				{
					SharedData shared = component.m_itemData.m_shared;
					if ((int)shared.m_itemType == 14 && shared.m_secondaryAttack != null && !string.IsNullOrEmpty(shared.m_secondaryAttack.m_attackAnimation))
					{
						list.Add(((Object)item).name + " (" + Translate(shared.m_name) + ")");
					}
				}
			}
			Log.LogWarning((object)("[TwoHanded] no item with a secondary attack was found for '" + setting + "' (auto looks for the Flametal Sledgehammer); the two-handed Thunderbrand maces keep their own secondary. Two-handed items that do have one: " + ((list.Count > 0) ? string.Join("; ", list.ToArray()) : "none") + ". Put the prefab name of the one you want in Secondary -> TwoHandedSecondaryFrom."));
		}

		private void BindShields()
		{
			ShieldCrackTexture = ((BaseUnityPlugin)this).Config.Bind<bool>("Shields", "CrackTexture", true, "Glowing electric cracks (the same pattern as on the maces) across the shield you carry while a Thunderbrand mace is held. Off = plain shields.");
			ShieldCrackIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Shields", "CrackIntensity", 0.5f, "How brightly the electric cracks glow on shields.");
			ShieldGlowIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Shields", "GlowIntensity", 0.05f, "A faint even charge under the cracks. 0 = none.");
			ShieldCrackTiles = ((BaseUnityPlugin)this).Config.Bind<float>("Shields", "CrackTiles", 2f, "How many crack strips fit across the shield. Higher = finer, more repeated cracks.");
			ShieldResize = ((BaseUnityPlugin)this).Config.Bind<bool>("Shields", "ResizeRoundShields", true, "Bring all round shields (round shield, bucklers, banded, ...) to one size between the Silver and the Banded shield, always, whatever you hold. Takes effect on the next start of the game.");
			ShieldSizeBetween = ((BaseUnityPlugin)this).Config.Bind<float>("Shields", "RoundShieldSize", 0.75f, "Where that size sits: 0 = as big as the Silver shield, 1 = as big as the Banded shield, 0.75 = three quarters of the way to Banded. Takes effect on the next start of the game.");
			ShieldBackOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Shields", "BackDistance", 0.09f, "How far a shield carried on your back sits behind your back, in meters, so it clears your cape. Raise it if it still clips. Changes apply live.");
			ShieldBackLift = ((BaseUnityPlugin)this).Config.Bind<float>("Shields", "BackLift", 0f, "Raise (+) or lower (-) the shield on your back, in meters. Changes apply live.");
			ShieldBackSide = ((BaseUnityPlugin)this).Config.Bind<float>("Shields", "BackSide", 0f, "Move the shield on your back to your right (+) or left (-), in meters. Changes apply live.");
			ShieldDefer = ((BaseUnityPlugin)this).Config.Bind<bool>("Shields", "LeaveToSwordFirebrand", true, "If the sword mod SwordFirebrand is installed too, it already resizes round shields and moves back-carried shields the same way, so this mod leaves that to it (the shields would otherwise be resized twice). Turn this off only if you switch the shield changes off in SwordFirebrand and want them from this mod instead.");
			ShieldShockOnBlock = ((BaseUnityPlugin)this).Config.Bind<bool>("Shields", "ShockOnBlock", true, "Blocking an attack with a shield while a Thunderbrand mace is held shocks the attacker a little. Only affects melee attackers close to you. Off = the shield does nothing extra.");
			ShieldShockRatio = ((BaseUnityPlugin)this).Config.Bind<float>("Shields", "ShockOnBlockRatio", 0.2f, "Lightning damage dealt back, as a fraction of the damage of the attack you blocked. 0 = none.");
			ShieldShockMax = ((BaseUnityPlugin)this).Config.Bind<float>("Shields", "ShockOnBlockMax", 25f, "The most lightning damage one block can deal back.");
		}

		private static float FaceSize(GameObject prefab, out float roundness)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			roundness = 0f;
			if ((Object)(object)prefab == (Object)null)
			{
				return 0f;
			}
			Transform val = AttachRoot(prefab);
			Span span = Measure(val, -1);
			if (!span.Valid)
			{
				return 0f;
			}
			Vector3 lossyScale = val.lossyScale;
			float[] array = new float[3]
			{
				Mathf.Abs(span.Size.x * lossyScale.x),
				Mathf.Abs(span.Size.y * lossyScale.y),
				Mathf.Abs(span.Size.z * lossyScale.z)
			};
			Array.Sort(array);
			if (array[2] < 0.01f || array[1] < 0.01f)
			{
				return 0f;
			}
			roundness = array[1] / array[2];
			return Mathf.Sqrt(array[2] * array[1]);
		}

		private void BindShock()
		{
			ShockEnemies = ((BaseUnityPlugin)this).Config.Bind<bool>("Shock", "ShockEnemies", true, "Enemies hit by a Thunderbrand mace's lightning (a swing, a thrown mace, the strike) or shocked by a shield on block crackle with electricity. Only the look; it adds no damage.");
			ShockSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Shock", "ShockSeconds", 4f, "How long an enemy keeps crackling after the last lightning hit.");
			ShockLight = ((BaseUnityPlugin)this).Config.Bind<float>("Shock", "ShockLight", 0.7f, "Brightness of the flickering blue light on a shocked enemy. 0 = no light (cheaper with many enemies).");
			ShockSize = ((BaseUnityPlugin)this).Config.Bind<float>("Shock", "ShockArcSize", 1f, "Size of the arcs on a shocked enemy. 1 = sized to the creature; raise it for bigger arcs, lower it for smaller ones.");
		}
	}
	[HarmonyPatch]
	internal static class RecipeStationPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(Player), "OnSpawned", (Type[])null, (Type[])null);
		}

		private static bool Prepare()
		{
			return TargetMethod() != null;
		}

		private static void Postfix()
		{
			try
			{
				Plugin.DedupeRecipes();
				Plugin.FixRecipeStations();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[Cloning] could not line up the forging stations: " + ex.GetType().Name + ": " + ex.Message));
			}
			try
			{
				Plugin.SyncTwoHanded();
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogWarning((object)("[TwoHanded] could not set up the two-handed maces' attacks: " + ex2.GetType().Name + ": " + ex2.Message));
			}
			try
			{
				MaceImpact.LogAnimatorOnce();
				SecondaryPriorityPatch.LogPatchOwnersOnce();
			}
			catch (Exception)
			{
			}
		}
	}
	public class ThunderbrandHead : MonoBehaviour
	{
		public Vector3 BaseLocal;

		public Vector3 TipLocal;

		public bool ForceEmit;

		private ParticleSystem ps;

		private ThunderbrandArcs arcs;

		private Character owner;

		private float nextOwnerCheck;

		private float nextBolt;

		private Vector3 lastBase;

		private Vector3 lastTip;

		private bool hasLast;

		private void Awake()
		{
			arcs = ((Component)this).GetComponent<ThunderbrandArcs>();
			if (!Volt.Ready)
			{
				((Behaviour)this).enabled = false;
			}
			else
			{
				ps = ThunderbrandFX.CreateTrailSystem(((Component)this).transform);
			}
		}

		private void LateUpdate()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: 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_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: 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_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: 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_01a5: 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_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)this).transform.TransformPoint(BaseLocal);
			Vector3 val2 = ((Component)this).transform.TransformPoint(TipLocal);
			if (!hasLast)
			{
				lastBase = val;
				lastTip = val2;
				hasLast = true;
				return;
			}
			bool flag = false;
			Vector3 val3;
			if (ForceEmit)
			{
				flag = true;
			}
			else
			{
				if ((Object)(object)owner == (Object)null && Time.time >= nextOwnerCheck)
				{
					owner = ((Component)this).GetComponentInParent<Character>();
					nextOwnerCheck = Time.time + 1f;
				}
				if ((Object)(object)owner != (Object)null && owner.InAttack())
				{
					float deltaTime = Time.deltaTime;
					float num;
					if (!(deltaTime > 0f))
					{
						num = 0f;
					}
					else
					{
						val3 = val2 - lastTip;
						num = ((Vector3)(ref val3)).magnitude / deltaTime;
					}
					flag = num >= Plugin.TrailMinSpeed.Value;
				}
			}
			if ((Object)(object)arcs != (Object)null)
			{
				arcs.Boost = flag;
			}
			if (flag && (Object)(object)ps != (Object)null && Plugin.TrailEnabled.Value)
			{
				val3 = val2 - lastTip;
				float magnitude = ((Vector3)(ref val3)).magnitude;
				val3 = val - lastBase;
				int num2 = Mathf.Clamp(Mathf.CeilToInt(Mathf.Max(magnitude, ((Vector3)(ref val3)).magnitude) / 0.12f), 1, 16);
				int num3 = Mathf.Max(1, Mathf.RoundToInt(3f * Plugin.TrailDensity.Value));
				for (int i = 1; i <= num2; i++)
				{
					float num4 = (float)i / (float)num2;
					Vector3 val4 = Vector3.Lerp(lastBase, val, num4);
					Vector3 val5 = Vector3.Lerp(lastTip, val2, num4);
					for (int j = 0; j < num3; j++)
					{
						EmitParams val6 = default(EmitParams);
						((EmitParams)(ref val6)).position = Vector3.Lerp(val4, val5, Random.Range(0f, 1f)) + Random.insideUnitSphere * 0.04f;
						((EmitParams)(ref val6)).velocity = Random.insideUnitSphere * 0.6f;
						((EmitParams)(ref val6)).startSize = Plugin.TrailSize.Value * Random.Range(0.6f, 1.3f);
						((EmitParams)(ref val6)).startLifetime = Plugin.TrailLifetime.Value * Random.Range(0.6f, 1.1f);
						ps.Emit(val6, 1);
					}
				}
				if (Plugin.ArcsEnabled.Value && Time.time >= nextBolt)
				{
					nextBolt = Time.time + Random.Range(0.06f, 0.15f);
					Vector3 val7 = Vector3.Lerp(val, val2, Random.value);
					float num5 = Random.Range(0.3f, 0.7f) * Mathf.Clamp(Plugin.ArcScale.Value, 0.3f, 3f);
					BoltFlash.Spawn(val7, val7 + Random.onUnitSphere * num5, 0.02f, 0.12f, num5 * 0.2f, 6);
				}
			}
			lastBase = val;
			lastTip = val2;
		}
	}
	public class ThunderbrandArcs : MonoBehaviour
	{
		public Vector3[] Points = (Vector3[])(object)new Vector3[0];

		public Vector3 Center;

		public float Radius = 0.08f;

		public bool Boost;

		private ArcEmitter emitter;

		private ParticleSystem sparks;

		private Light glow;

		private float seed;

		private float flash;

		private bool built;

		private bool lastBoost;

		private void Awake()
		{
			seed = Random.value * 100f;
		}

		private void Build()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Expected O, but got Unknown
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: 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_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: 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_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: 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_0237: 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_024d: Unknown result type (might be due to invalid IL or missing references)
			built = true;
			if (Plugin.ArcsEnabled.Value && Volt.Ready)
			{
				GameObject val = new GameObject("ThunderbrandArcFX");
				val.transform.SetParent(((Component)this).transform, false);
				emitter = val.AddComponent<ArcEmitter>();
				emitter.Picker = PickArc;
				emitter.Rolled = OnRolled;
				emitter.Count = Mathf.Clamp(Plugin.ArcCount.Value, 1, 8);
				emitter.Segments = 6;
				emitter.Interval = 0.085f;
				emitter.Chance = 0.7f;
				emitter.Width = 0.014f * Mathf.Clamp(Plugin.ArcScale.Value, 0.3f, 3f);
				emitter.Jitter = 0.22f;
			}
			if (Plugin.SparkAmount.Value > 0f)
			{
				sparks = Volt.NewSystem(((Component)this).transform, "ThunderbrandHeadSparks", stretch: true);
				if ((Object)(object)sparks != (Object)null)
				{
					((Component)sparks).transform.localPosition = Center;
					MainModule main = sparks.main;
					((MainModule)(ref main)).loop = true;
					((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1;
					((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)0;
					((MainModule)(ref main)).startLifetime = new MinMaxCurve(0.2f, 0.5f);
					((MainModule)(ref main)).startSpeed = new MinMaxCurve(0.3f, 1.2f);
					((MainModule)(ref main)).startSize = new MinMaxCurve(0.012f, 0.035f);
					((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(0.1f);
					((MainModule)(ref main)).maxParticles = 150;
					EmissionModule emission = sparks.emission;
					((EmissionModule)(ref emission)).enabled = true;
					((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(8f * Plugin.SparkAmount.Value);
					ShapeModule shape = sparks.shape;
					((ShapeModule)(ref shape)).enabled = true;
					((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0;
					((ShapeModule)(ref shape)).radius = Mathf.Max(0.02f, Radius);
					ColorOverLifetimeModule colorOverLifetime = sparks.colorOverLifetime;
					((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true;
					((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(Volt.SparkGradient());
					sparks.Play();
				}
			}
			if (Plugin.LightMultiplier.Value > 0f)
			{
				GameObject val2 = new GameObject("ThunderbrandLight");
				val2.transform.SetParent(((Component)this).transform, false);
				val2.transform.localPosition = Center;
				glow = val2.AddComponent<Light>();
				glow.type = (LightType)2;
				glow.color = Volt.LightColor;
				glow.range = 3.5f;
				glow.intensity = 0f;
				glow.shadows = (LightShadows)0;
			}
		}

		private bool PickArc(out Vector3 from, out Vector3 to)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missi