Decompiled source of MaxAxe v0.4.6

MaxAxe.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("MaxAxe")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MaxAxe")]
[assembly: AssemblyCopyright("Copyright ©  2022")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("9f8a1b6e-6d0e-4dab-bbd8-9ed433836544")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
internal sealed class ConfigurationManagerAttributes
{
	public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput);

	public bool? ShowRangeAsPercent;

	public Action<ConfigEntryBase> CustomDrawer;

	public CustomHotkeyDrawerFunc CustomHotkeyDrawer;

	public bool? Browsable;

	public string Category;

	public object DefaultValue;

	public bool? HideDefaultButton;

	public bool? HideSettingName;

	public string Description;

	public string DispName;

	public int? Order;

	public bool? ReadOnly;

	public bool? IsAdvanced;

	public Func<object, string> ObjToStr;

	public Func<string, object> StrToObj;
}
namespace neobotics.ValheimMods;

public class ConfigMock
{
	public bool Value { get; set; }
}
internal class CustomDataWrapper
{
	private Dictionary<string, string> playerData;

	private CustomDataWrapper instance;

	private Dictionary<string, string> Data { get; set; }

	public CustomDataWrapper(Dictionary<string, string> sourceData, string keyPrefix)
	{
		CustomDataWrapper customDataWrapper = this;
		playerData = sourceData;
		Data = new Dictionary<string, string>();
		sourceData.Keys.ToList().ForEach(delegate(string key)
		{
			if (key.StartsWith(keyPrefix))
			{
				customDataWrapper.Data.Add(key, sourceData[key]);
			}
		});
	}

	public void Add(string key, string value)
	{
		Data.Add(key, value);
		playerData.Add(key, value);
	}

	public bool Remove(string key)
	{
		return Data.Remove(key) & playerData.Remove(key);
	}

	public void Set(string key, string value)
	{
		if (Data.ContainsKey(key))
		{
			Data[key] = value;
		}
		else
		{
			Data.Add(key, value);
		}
		if (playerData.ContainsKey(key))
		{
			playerData[key] = value;
		}
		else
		{
			playerData.Add(key, value);
		}
	}

	public string Get(string key)
	{
		if (Data.ContainsKey(key))
		{
			return Data[key];
		}
		return null;
	}

	public bool ContainsKey(string key)
	{
		return Data.ContainsKey(key);
	}

	public void PreSaveSync()
	{
		foreach (KeyValuePair<string, string> datum in Data)
		{
			if (!playerData.ContainsKey(datum.Key))
			{
				playerData.Add(datum.Key, datum.Value);
			}
		}
	}
}
internal class CustomSkill
{
	[HarmonyPatch(typeof(Skills), "Load")]
	private static class Skills_Load_Patch
	{
		private static void Prefix(Skills __instance)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			if (__instance?.m_skills != null && cSkillDef != null && !__instance.m_skills.Contains(cSkillDef))
			{
				Logging.GetLogger().Debug("Adding custom skill definition");
				Sprite prefabIcon = Utils.GetPrefabIcon(cIconPrefab);
				if ((Object)(object)prefabIcon != (Object)null)
				{
					cSkillDef.m_icon = prefabIcon;
				}
				cSkill = new Skill(cSkillDef);
				__instance.m_skills.Add(cSkillDef);
			}
		}

		private static void Postfix(Skills __instance, Dictionary<SkillType, Skill> ___m_skillData)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			if (__instance?.m_skills == null || ___m_skillData == null || cSkillDef == null)
			{
				return;
			}
			Logging.GetLogger().Debug("Skills Load Postfix");
			if (!___m_skillData.ContainsKey(cSkillType))
			{
				Logging.GetLogger().Debug("No custom skill in the player profile");
				if (Cfg.useSkill.Value)
				{
					Logging.GetLogger().Debug("Adding custom skill to player profile");
					cSkill.m_accumulator = 0f;
					cSkill.m_level = 0f;
					___m_skillData.Add(cSkillType, cSkill);
				}
			}
			else
			{
				cSkill = ___m_skillData[cSkillType];
				Logging.GetLogger().Debug("Custom skill is already in the player profile");
				if (!Cfg.useSkill.Value)
				{
					Logging.GetLogger().Debug("...but it's not enabled");
					___m_skillData.Remove(cSkillType);
				}
			}
		}
	}

	[HarmonyPatch(typeof(Skills), "Save")]
	private static class Skills_Save_Patch
	{
		private static void Prefix(Skills __instance, ZPackage pkg, Dictionary<SkillType, Skill> ___m_skillData)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)__instance == (Object)null) && ___m_skillData != null && ___m_skillData.Count != 0)
			{
				Logging.GetLogger().Debug("Skills Save Prefix");
				if (!___m_skillData.ContainsKey(cSkillType))
				{
					Logging.GetLogger().Debug("Saving custom skill");
					___m_skillData.Add(cSkillType, cSkill);
				}
				string value = $"{cSkill.m_level}:{cSkill.m_accumulator}";
				if (__instance.m_player.m_customData.ContainsKey(saveName))
				{
					__instance.m_player.m_customData[saveName] = value;
				}
				else
				{
					__instance.m_player.m_customData.Add(saveName, value);
				}
			}
		}

		private static void Postfix(Skills __instance, ZPackage pkg, Dictionary<SkillType, Skill> ___m_skillData)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)__instance == (Object)null) && ___m_skillData != null && ___m_skillData.Count != 0)
			{
				Logging.GetLogger().Debug("Skills Save Postfix");
				if (!Cfg.useSkill.Value)
				{
					Logging.GetLogger().Debug("Removing disabled custom skill from the player profile");
					___m_skillData.Remove(cSkillType);
				}
			}
		}
	}

	[HarmonyPatch(typeof(Skills), "RaiseSkill")]
	private static class Skills_RaiseSkill_Patch
	{
		[HarmonyPrefix]
		private static void Skills_RaiseSkill_Prefix(Skills __instance, ref SkillType skillType, float factor)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between I4 and Unknown
			if ((int)skillType == (int)cSkillType && !Cfg.useSkill.Value)
			{
				skillType = (SkillType)0;
			}
		}
	}

	[HarmonyPatch(typeof(Skills), "IsSkillValid")]
	private static class Skills_IsSkillValid_Patch
	{
		private static void Postfix(ref bool __result, SkillType type)
		{
			//IL_0004: 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)
			if (!__result && type == cSkillType)
			{
				Logging.GetLogger().Debug("Skill type matches custom skill");
				__result = true;
			}
		}
	}

	[HarmonyPatch(typeof(Skills), "CheatRaiseSkill")]
	private static class Skills_CheatRaiseSkill_Patch
	{
		private static bool Prefix(Skills __instance, string name, float value, Dictionary<SkillType, Skill> ___m_skillData)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected I4, but got Unknown
			Logging.GetLogger().Debug("Skills CheatRaiseSkill Prefix");
			if (Cfg.useSkill.Value && name.ToLower().Equals(cSkillName.ToLower()) && ___m_skillData.TryGetValue(cSkillType, out var value2))
			{
				Logging.GetLogger().Debug($"Skill {value2.m_info} found");
				Skill obj = value2;
				obj.m_level += value;
				value2.m_level = Mathf.Clamp(value2.m_level, 0f, 100f);
				if (__instance.m_useSkillCap)
				{
					__instance.RebalanceSkills(cSkillType);
				}
				if (value2.m_info != null)
				{
					((Character)Player.m_localPlayer).Message((MessageType)1, $"Skill increased {Utils.GetTranslated((int)value2.m_info.m_skill)}: {(int)value2.m_level}", 0, (Sprite)null);
					Console.instance.Print($"Skill {cSkillName} = {value2.m_level}");
				}
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Skills), "CheatResetSkill")]
	private static class Skills_CheatResetSkill_Patch
	{
		private static bool Prefix(string name, Skills __instance, Dictionary<SkillType, Skill> ___m_skillData)
		{
			//IL_0033: 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_0071: Expected I4, but got Unknown
			Logging.GetLogger().Debug("Skills CheatResetSkill Prefix");
			if (Cfg.useSkill.Value && name.ToLower().Equals(cSkillName.ToLower()))
			{
				if (___m_skillData.TryGetValue(cSkillType, out var value))
				{
					value.m_accumulator = 0f;
					value.m_level = 0f;
				}
				Console.instance.Print("Skill " + Utils.GetTranslated((int)value.m_info.m_skill) + " reset");
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(SkillsDialog), "Setup")]
	private static class SkillsDialog_Setup_Patch
	{
		private static void Postfix(Player player, ref List<GameObject> ___m_elements)
		{
			Logging logger = Logging.GetLogger();
			logger.Debug("SkillsDialog Setup Postfix");
			if (!Cfg.useSkill.Value)
			{
				return;
			}
			object obj;
			if (player == null)
			{
				obj = null;
			}
			else
			{
				Skills skills = ((Character)player).GetSkills();
				obj = ((skills != null) ? skills.GetSkillList() : null);
			}
			List<Skill> list = (List<Skill>)obj;
			if (list == null)
			{
				logger.Debug("Can't get player skill list");
				return;
			}
			int num = list.FindIndex((Skill s) => s.m_info == cSkillDef);
			if (num < 0)
			{
				logger.Debug("Can't find custom skill");
				return;
			}
			GameObject val = ___m_elements[num];
			if ((Object)(object)val == (Object)null)
			{
				logger.Debug("Skill game object is null");
				return;
			}
			Transform obj2 = Utils.FindChild(val.transform, "name");
			object obj3;
			if (obj2 == null)
			{
				obj3 = null;
			}
			else
			{
				Text component = ((Component)obj2).GetComponent<Text>();
				obj3 = ((component != null) ? component.text : null);
			}
			if (obj3 == null)
			{
				logger.Debug("Can't find and set custom skill text");
			}
			else
			{
				_ = cSkillName;
			}
		}
	}

	public static SkillType cSkillType = (SkillType)0;

	public static SkillDef cSkillDef = null;

	public static Skill cSkill = null;

	private static string cSkillName = "";

	private static string cIconPrefab = null;

	private static string saveName;

	public static SkillType GetCustomSkillType()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		return cSkillType;
	}

	public static SkillDef GetCustomSkillDef()
	{
		return cSkillDef;
	}

	public static Skill GetCustomSkill()
	{
		return cSkill;
	}

	public static void CheckForPreExistingCustomSkill(Player player)
	{
		if (cSkill == null || cSkill.m_level != 0f || cSkill.m_accumulator != 0f)
		{
			return;
		}
		Logging.GetLogger().Debug("Looking for pre-existing skill");
		if (player.m_customData.TryGetValue(saveName, out var value))
		{
			Logging.GetLogger().Debug("Found pre-existing skill values");
			string[] array = value.Split(new char[1] { ':' });
			if (array.Length == 2 && float.TryParse(array[0], out var result) && float.TryParse(array[1], out var result2))
			{
				cSkill.m_level = result;
				cSkill.m_accumulator = result2;
			}
		}
	}

	public static void ToggleCustomSkill(bool enable)
	{
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		Skills val = ((localPlayer != null) ? ((Character)localPlayer).GetSkills() : null);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Dictionary<SkillType, Skill> skillData = val.m_skillData;
		if (skillData == null)
		{
			return;
		}
		if (enable)
		{
			if (skillData.ContainsKey(cSkillType))
			{
				skillData[cSkillType] = cSkill;
			}
			else
			{
				skillData.Add(cSkillType, cSkill);
			}
		}
		else
		{
			skillData.Remove(cSkillType);
		}
	}

	public static void ConfigureSkillDef(string name, string descrip, string iconPrefabName)
	{
		//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_001b: Expected O, but got Unknown
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		int num = Math.Abs(StringExtensionMethods.GetStableHashCode(name));
		cSkillType = (SkillType)num;
		cSkillDef = new SkillDef();
		cSkillDef.m_description = descrip;
		cSkillDef.m_increseStep = 1f;
		cSkillDef.m_skill = cSkillType;
		cSkillName = name;
		cIconPrefab = iconPrefabName;
		saveName = "NEObotics_" + cSkillName;
		Utils.SetTranslator(num, name);
	}
}
internal class DebugUtils
{
	public static void ObjectInspector(object o)
	{
		if (o == null)
		{
			Debug.Log((object)"Object is null");
			return;
		}
		BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
		Type type = o.GetType();
		Debug.Log((object)(o.ToString() + " Type " + type.Name));
		PropertyInfo[] properties = type.GetProperties(bindingAttr);
		foreach (PropertyInfo propertyInfo in properties)
		{
			Debug.Log((object)$"{type.Name}.{propertyInfo.Name} = {propertyInfo.GetValue(o)}");
		}
		FieldInfo[] fields = type.GetFields(bindingAttr);
		foreach (FieldInfo field in fields)
		{
			FieldPrinter(o, type, field);
		}
	}

	public static void MethodInspector(object o)
	{
		if (o == null)
		{
			Debug.Log((object)"Object is null");
			return;
		}
		BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
		Type type = o.GetType();
		Debug.Log((object)(o.ToString() + " Type " + type.Name));
		MethodInfo[] methods = type.GetMethods(bindingAttr);
		foreach (MethodInfo methodInfo in methods)
		{
			methodInfo.GetParameters();
			string arg = string.Join(", ", (from x in methodInfo.GetParameters()
				select x.ParameterType?.ToString() + " " + x.Name).ToArray());
			Debug.Log((object)$"{methodInfo.ReturnType} {methodInfo.Name} ({arg})");
		}
	}

	private static void ItemDataInspector(ItemData item)
	{
		ObjectInspector(item);
		ObjectInspector(item.m_shared);
	}

	private static void FieldPrinter(object o, Type t, FieldInfo field)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Expected O, but got Unknown
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Expected O, but got Unknown
		try
		{
			if (field.FieldType == typeof(ItemData))
			{
				ItemData val = (ItemData)field.GetValue(o);
				if (val != null)
				{
					ItemDataInspector(val);
				}
				else
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]");
				}
			}
			else if (field.FieldType == typeof(Transform))
			{
				Transform val2 = (Transform)field.GetValue(o);
				if ((Object)(object)val2 != (Object)null)
				{
					Debug.Log((object)("\tTransform.parent = " + ((Object)val2.parent).name));
				}
				else
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]");
				}
			}
			else if (field.FieldType == typeof(EffectList))
			{
				EffectList val3 = (EffectList)field.GetValue(o);
				if (val3 != null)
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)}:");
					EffectData[] effectPrefabs = val3.m_effectPrefabs;
					foreach (EffectData val4 in effectPrefabs)
					{
						Debug.Log((object)("\tEffectData.m_prefab = " + ((Object)val4.m_prefab).name));
					}
				}
				else
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]");
				}
			}
			else
			{
				Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)}");
			}
		}
		catch (Exception)
		{
			Debug.Log((object)("Exception accessing " + t?.Name + "." + field?.Name));
		}
	}

	public static void GameObjectInspector(GameObject go)
	{
		Debug.Log((object)("\n\nInspecting GameObject " + ((Object)go).name));
		ObjectInspector(go);
		Component[] componentsInChildren = go.GetComponentsInChildren<Component>();
		foreach (Component val in componentsInChildren)
		{
			try
			{
				string obj = ((val != null) ? ((Object)val).name : null);
				object obj2;
				if (val == null)
				{
					obj2 = null;
				}
				else
				{
					Transform transform = val.transform;
					if (transform == null)
					{
						obj2 = null;
					}
					else
					{
						Transform parent = transform.parent;
						obj2 = ((parent != null) ? ((Object)parent).name : null);
					}
				}
				Debug.Log((object)("\n\nInspecting Component " + obj + " with parent " + (string?)obj2));
				ObjectInspector(val);
			}
			catch (Exception)
			{
			}
		}
	}

	public static void ComponentInspector(Component c)
	{
		Debug.Log((object)("\n\nInspecting Component " + ((Object)c).name));
		ObjectInspector(c);
	}

	public static void EffectsInspector(EffectList e)
	{
		EffectData[] effectPrefabs = e.m_effectPrefabs;
		Debug.Log((object)$"Effect list has effects {e.HasEffects()} count {effectPrefabs.Length}");
		EffectData[] array = effectPrefabs;
		foreach (EffectData val in array)
		{
			Debug.Log((object)$"Effect Data {val} prefab name {((Object)val.m_prefab).name} prefab GameObject name {((Object)val.m_prefab.gameObject).name}");
		}
	}

	public static void PrintInventory()
	{
		foreach (ItemData allItem in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems())
		{
			Debug.Log((object)allItem.m_shared.m_name);
		}
	}

	public static void PrintAllObjects()
	{
		ZNetScene.instance.m_prefabs.ForEach(delegate(GameObject x)
		{
			Debug.Log((object)("GameObject " + ((Object)x).name));
		});
	}

	public static void PrintAllCharacters()
	{
		Character.GetAllCharacters().ForEach(delegate(Character x)
		{
			Debug.Log((object)("Character " + ((Object)x).name));
		});
	}
}
public class DelegatedConfigEntry<T> : DelegatedConfigEntryBase
{
	private ConfigEntry<T> _entry;

	private EventHandler rootHandler;

	private Action<object, EventArgs> clientDelegate;

	private Logging Log;

	public ConfigEntry<T> ConfigEntry
	{
		get
		{
			return _entry;
		}
		set
		{
			_entry = value;
			if (_entry != null && rootHandler != null)
			{
				_entry.SettingChanged += rootHandler;
			}
			Name = ((ConfigEntryBase)_entry).Definition.Key;
			Section = ((ConfigEntryBase)_entry).Definition.Section;
			ServerValue = ((ConfigEntryBase)_entry).GetSerializedValue();
			Log.Trace("Set " + Section + " " + Name + " to serialized value " + ServerValue);
		}
	}

	public T Value
	{
		get
		{
			return _entry.Value;
		}
		set
		{
			_entry.Value = value;
		}
	}

	public DelegatedConfigEntry(bool useServerDelegate = false)
		: this((Action<object, EventArgs>)null, useServerDelegate)
	{
	}

	public DelegatedConfigEntry(Action<object, EventArgs> delegateHandler, bool useServerDelegate = false)
	{
		Log = Logging.GetLogger();
		Log.Trace("DelegatedConfigEntry");
		if (delegateHandler != null)
		{
			clientDelegate = delegateHandler;
		}
		if (useServerDelegate)
		{
			Log.Trace("Configuring server delegate");
			rootHandler = delegate(object s, EventArgs e)
			{
				ServerDelegate(s, e);
			};
			ServerConfiguration.ServerDelegatedEntries.Add(this);
		}
		else if (clientDelegate != null)
		{
			rootHandler = delegate(object s, EventArgs e)
			{
				clientDelegate(s, e);
			};
		}
	}

	private void ServerDelegate(object sender, EventArgs args)
	{
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Expected O, but got Unknown
		Logging.GetLogger().Trace("ServerDelegate");
		_entry.SettingChanged -= rootHandler;
		ZNet instance = ZNet.instance;
		bool? flag = ((instance != null) ? new bool?(instance.IsServer()) : null);
		if (flag.HasValue)
		{
			if (flag == false)
			{
				if (ServerValue != null)
				{
					((ConfigEntryBase)_entry).SetSerializedValue(ServerValue);
				}
			}
			else
			{
				ServerValue = ((ConfigEntryBase)_entry).GetSerializedValue();
				ServerConfiguration.Instance.SendConfigToAllClients(sender, (SettingChangedEventArgs)args);
			}
		}
		if (clientDelegate != null)
		{
			clientDelegate(sender, args);
		}
		_entry.SettingChanged += rootHandler;
	}

	public void EnableHandler(bool setActive)
	{
		if (setActive)
		{
			_entry.SettingChanged += rootHandler;
		}
		else
		{
			_entry.SettingChanged -= rootHandler;
		}
	}

	public bool IsKeyPressed()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
		{
			KeyboardShortcut value = val.Value;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			if (!Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			return true;
		}
		Log.Error("Keyboard read attempted on non-KeyboardShortcut config.");
		return false;
	}

	public bool IsKeyDown()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
		{
			KeyboardShortcut value = val.Value;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			if (!Input.GetKey(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			return true;
		}
		Log.Error("Keyboard read attempted on non-KeyboardShortcut config.");
		return false;
	}

	public bool IsKeyReleased()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
		{
			KeyboardShortcut value = val.Value;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKeyUp(modifier))
				{
					return false;
				}
			}
			if (!Input.GetKeyUp(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			return true;
		}
		Log.Error("Keyboard read attempted on non-KeyboardShortcut config.");
		return false;
	}
}
public class DelegatedConfigEntryBase
{
	public string Name;

	public string Section;

	public string ServerValue;
}
internal class HarmonyHelper
{
	public enum PatchType
	{
		Prefix,
		Postfix,
		Transpiler,
		Finalizer
	}

	private static Dictionary<string, string> detectionSet = new Dictionary<string, string>();

	private static Dictionary<string, string> unpatchMods = new Dictionary<string, string>();

	public static void GetDetectionSet(Dictionary<string, string> harmonyIds)
	{
		Logging logger = Logging.GetLogger();
		foreach (KeyValuePair<string, string> harmonyId in harmonyIds)
		{
			if (Harmony.HasAnyPatches(harmonyId.Key))
			{
				logger.Debug("Detected " + harmonyId.Value + " from Harmony");
				if (!detectionSet.ContainsKey(harmonyId.Key))
				{
					detectionSet.Add(harmonyId.Key, harmonyId.Value);
				}
			}
			else if (Chainloader.PluginInfos.ContainsKey(harmonyId.Key))
			{
				logger.Debug("Detected " + harmonyId.Value + " from BepInEx");
				if (!detectionSet.ContainsKey(harmonyId.Key))
				{
					detectionSet.Add(harmonyId.Key, harmonyId.Value);
				}
			}
		}
	}

	public static void AddExclusion(string key)
	{
		if (detectionSet.ContainsKey(key))
		{
			unpatchMods.Add(key, detectionSet[key]);
		}
	}

	public static void UnpatchMods(Harmony harmony)
	{
		Logging logger = Logging.GetLogger();
		foreach (KeyValuePair<string, string> unpatchMod in unpatchMods)
		{
			logger.Warning("Not compatible with " + unpatchMod.Value);
			harmony.UnpatchAll(unpatchMod.Key);
			detectionSet.Remove(unpatchMod.Key);
			logger.Warning("Disabled " + unpatchMod.Value);
		}
	}

	public static bool IsModDetected(string key)
	{
		return detectionSet.ContainsKey(key);
	}

	public static bool IsModNameDetected(string value)
	{
		return detectionSet.ContainsValue(value);
	}

	public static bool TryGetDetectedModName(string key, out string mod)
	{
		return detectionSet.TryGetValue(key, out mod);
	}

	public static bool TryGetDetectedModKey(string value, out string key)
	{
		key = null;
		foreach (string key2 in detectionSet.Keys)
		{
			if (detectionSet[key2] == value)
			{
				key = key2;
				return true;
			}
		}
		return false;
	}

	public static string AddAnonymousPatch(string baseMethodName, PatchType patchType, string modName, string patchMethodName = null)
	{
		string text = null;
		int num = 0;
		Logging logger = Logging.GetLogger();
		foreach (MethodBase item in Harmony.GetAllPatchedMethods().ToList())
		{
			MethodBaseExtensions.HasMethodBody(item);
			Patches patchInfo = Harmony.GetPatchInfo(item);
			ReadOnlyCollection<Patch> readOnlyCollection = patchInfo.Prefixes;
			switch (patchType)
			{
			case PatchType.Postfix:
				readOnlyCollection = patchInfo.Postfixes;
				break;
			case PatchType.Prefix:
				readOnlyCollection = patchInfo.Prefixes;
				break;
			case PatchType.Transpiler:
				readOnlyCollection = patchInfo.Transpilers;
				break;
			case PatchType.Finalizer:
				readOnlyCollection = patchInfo.Finalizers;
				break;
			}
			foreach (Patch item2 in readOnlyCollection)
			{
				if (!item2.owner.StartsWith("harmony-auto") || !(item.Name == baseMethodName))
				{
					continue;
				}
				if (patchMethodName != null)
				{
					if (item2.PatchMethod.Name == patchMethodName)
					{
						num++;
						text = item2.owner;
					}
				}
				else
				{
					num++;
					text = item2.owner;
				}
			}
			if (num == 1)
			{
				detectionSet.Add(text, modName);
				logger.Info($"Added unique anonymous {baseMethodName} {patchType}: {text} as {modName}");
			}
			else if (num > 1)
			{
				text = null;
				logger.Warning($"Found multiple anonymous {baseMethodName} {patchType} entries. Can't identify correct patch to remove or modify.");
			}
		}
		if (num == 0)
		{
			logger.Info("No patch found for " + modName);
		}
		return text;
	}
}
public class Logging
{
	public enum LogLevels
	{
		Critical,
		Error,
		Warning,
		Info,
		Debug,
		Trace
	}

	private static Logging _logger;

	public LogLevels LogLevel { get; set; }

	public string ModName { get; set; }

	private Logging(LogLevels level, string name)
	{
		LogLevel = level;
		ModName = name;
	}

	public static Logging GetLogger(LogLevels level, string name)
	{
		if (_logger == null)
		{
			_logger = new Logging(level, name);
		}
		return _logger;
	}

	public static Logging GetLogger()
	{
		if (_logger == null)
		{
			throw new NullReferenceException("Logger not initialized");
		}
		return _logger;
	}

	public void Trace(string msg)
	{
		if (LogLevel >= LogLevels.Trace)
		{
			Debug.Log((object)Message(msg));
		}
	}

	public void Debug(string msg)
	{
		if (LogLevel >= LogLevels.Debug)
		{
			Debug.Log((object)Message(msg));
		}
	}

	public void Info(string msg)
	{
		if (LogLevel >= LogLevels.Info)
		{
			Debug.Log((object)Message(msg));
		}
	}

	public void Warning(string msg)
	{
		if (LogLevel >= LogLevels.Warning)
		{
			Debug.LogWarning((object)Message(msg));
		}
	}

	public void Error(string msg)
	{
		if (LogLevel >= LogLevels.Error)
		{
			Debug.LogWarning((object)Message(msg));
		}
	}

	public void Error(Exception e)
	{
		Error(e, stackTrace: false);
	}

	public void Error(Exception e, bool stackTrace)
	{
		if (LogLevel >= LogLevels.Error)
		{
			Warning(Message(e.Message));
			if (stackTrace)
			{
				Warning(e.StackTrace);
			}
		}
	}

	public void Critical(Exception e)
	{
		if (LogLevel >= LogLevels.Critical)
		{
			Debug(Message(e.Message));
			Error(e.StackTrace);
		}
	}

	private string Message(string msg)
	{
		return ModName + ": " + msg;
	}

	public static void ChangeLogging(object s, EventArgs e)
	{
		SettingChangedEventArgs val = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null);
		GetLogger().Debug($"ChangeLog {val.ChangedSetting.Definition.Key} to {val.ChangedSetting.BoxedValue}");
		GetLogger().LogLevel = Cfg.debugLevel.Value;
	}
}
public class ServerConfiguration
{
	[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
	private static class ZNet_OnNewConnection_Patch
	{
		private static void Postfix(ZNet __instance, ZNetPeer peer)
		{
			Log.Debug("ZNet OnNewConnection postfix");
			if (!__instance.IsServer())
			{
				try
				{
					Log.Debug("PlayerChoice registered RPC_ClientConfigReceiver");
					peer.m_rpc.Register<ZPackage>("ClientConfigReceiver." + GetPluginGuid(), (Action<ZRpc, ZPackage>)RPC_ClientConfigReceiver);
					return;
				}
				catch (Exception)
				{
					Log.Warning("Failed to register RPC");
					return;
				}
			}
			try
			{
				SendConfigToClient(peer);
			}
			catch (Exception)
			{
				Log.Warning("Error sending server configuration to client");
			}
		}
	}

	public static List<DelegatedConfigEntryBase> ServerDelegatedEntries = new List<DelegatedConfigEntryBase>();

	private static ConfigFile LocalConfig;

	private static BaseUnityPlugin Mod;

	private static string ConfigFileName;

	private static ServerConfiguration _instance;

	private static Logging Log;

	public static bool IsSetup = false;

	private const string NOT_CONFIGURED = "ServerConfiguration not initialized. Setup first.";

	public static ServerConfiguration Instance
	{
		get
		{
			if (_instance == null)
			{
				_instance = new ServerConfiguration();
			}
			return _instance;
		}
	}

	private ServerConfiguration()
	{
	}

	public void Setup(ConfigFile config, BaseUnityPlugin modInstance)
	{
		LocalConfig = config;
		Log = Logging.GetLogger();
		Log.Trace("ServerConfiguration Setup");
		Mod = modInstance;
		ConfigFileName = Path.GetFileName(LocalConfig.ConfigFilePath);
		IsSetup = true;
	}

	public void CreateConfigWatcher()
	{
		string configFilePath = LocalConfig.ConfigFilePath;
		string fileName = Path.GetFileName(LocalConfig.ConfigFilePath);
		Log.Trace("Configuration File Watcher Setup");
		FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(configFilePath.Substring(0, configFilePath.Length - fileName.Length), fileName);
		fileSystemWatcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime;
		fileSystemWatcher.Changed += LoadConfig;
		fileSystemWatcher.Created += LoadConfig;
		fileSystemWatcher.IncludeSubdirectories = false;
		fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
		fileSystemWatcher.EnableRaisingEvents = true;
	}

	private void LoadConfig(object sender, FileSystemEventArgs e)
	{
		if (!File.Exists(LocalConfig.ConfigFilePath))
		{
			return;
		}
		try
		{
			Log.Debug($"Loading configuration {e.ChangeType}");
			LocalConfig.Reload();
		}
		catch
		{
			Log.Error("Error loading configuration file " + ConfigFileName);
		}
	}

	public static string GetPluginGuid()
	{
		return Mod.Info.Metadata.GUID;
	}

	public static void RPC_ClientConfigReceiver(ZRpc zrpc, ZPackage package)
	{
		if (!IsSetup)
		{
			Log.Error("ServerConfiguration not initialized. Setup first.");
			return;
		}
		Log.Debug("ClientConfigReceiver");
		string section;
		string name;
		while (package.GetPos() < package.Size())
		{
			section = package.ReadString();
			name = package.ReadString();
			string text = package.ReadString();
			Log.Trace("Reading " + section + " " + name + " value " + text + " from ZPackage");
			DelegatedConfigEntryBase delegatedConfigEntryBase = ServerDelegatedEntries.Find((DelegatedConfigEntryBase e) => e.Name == name && e.Section == section);
			if (delegatedConfigEntryBase != null)
			{
				Log.Trace("Found DCEB on client and setting to server value " + text);
				delegatedConfigEntryBase.ServerValue = text;
			}
			ConfigEntryBase val = LocalConfig[section, name];
			if (val != null)
			{
				Log.Trace("Found local CEB and setting underlying config value " + text);
				val.SetSerializedValue(text);
			}
		}
	}

	internal static void WriteConfigEntries(ZPackage zpkg)
	{
		foreach (DelegatedConfigEntryBase serverDelegatedEntry in ServerDelegatedEntries)
		{
			Log.Trace("Writing " + serverDelegatedEntry.Section + " " + serverDelegatedEntry.Name + " value " + serverDelegatedEntry.ServerValue + " to ZPackage");
			zpkg.Write(serverDelegatedEntry.Section);
			zpkg.Write(serverDelegatedEntry.Name);
			zpkg.Write(serverDelegatedEntry.ServerValue);
		}
	}

	internal static void SendConfigToClient(ZNetPeer peer)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		if (!IsSetup)
		{
			Log.Error("ServerConfiguration not initialized. Setup first.");
			return;
		}
		Log.Debug("ServerSendConfigToClient");
		ZPackage val = new ZPackage();
		WriteConfigEntries(val);
		peer.m_rpc.Invoke("ClientConfigReceiver." + GetPluginGuid(), new object[1] { val });
	}

	public void SendConfigToAllClients(object o, SettingChangedEventArgs e)
	{
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		if (!IsSetup)
		{
			Log.Error("ServerConfiguration not initialized. Setup first.");
		}
		else if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && ZNet.instance.GetPeerConnections() > 0)
		{
			Log.Debug("SendConfigToAllClients");
			ZPackage zpkg = new ZPackage();
			WriteConfigEntries(zpkg);
			((MonoBehaviour)Mod).StartCoroutine(_instance.Co_BroadcastConfig(zpkg));
		}
	}

	private IEnumerator Co_BroadcastConfig(ZPackage zpkg)
	{
		Log.Debug("Co_BroadcastConfig");
		List<ZNetPeer> connectedPeers = ZNet.instance.GetConnectedPeers();
		foreach (ZNetPeer item in connectedPeers)
		{
			if (item != ZNet.instance.GetServerPeer())
			{
				item.m_rpc.Invoke("ClientConfigReceiver." + GetPluginGuid(), new object[1] { zpkg });
			}
			yield return null;
		}
	}
}
internal class Utils
{
	public static TEnum Guardrails<TEnum>(string value, TEnum enumDefault) where TEnum : struct
	{
		if (Enum.TryParse<TEnum>(value, ignoreCase: true, out var result))
		{
			return result;
		}
		return enumDefault;
	}

	public static int Guardrails(int value, int lbound, int ubound)
	{
		if (value < lbound)
		{
			return lbound;
		}
		if (value > ubound)
		{
			return ubound;
		}
		return value;
	}

	public static float Guardrails(float value, float lbound, float ubound)
	{
		if (value < lbound)
		{
			return lbound;
		}
		if (value > ubound)
		{
			return ubound;
		}
		return value;
	}

	public static string UnClonifiedName(string name)
	{
		if (name == null)
		{
			return null;
		}
		int num = name.IndexOf("(Clone)");
		if (num < 1)
		{
			return name;
		}
		return name.Substring(0, num);
	}

	public static void SetTranslator(int id, string idText)
	{
		typeof(Localization).GetMethod("AddWord", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(Localization.instance, new object[2]
		{
			"skill_" + id,
			idText
		});
	}

	public static string GetTranslated(int id)
	{
		Logging.GetLogger().Debug(string.Format("Got translation for id {0} to {1}", id, Localization.instance.Localize("skill_" + id)));
		return Localization.instance.Localize("$skill_" + id);
	}

	public static Sprite GetPrefabIcon(string prefabName)
	{
		Sprite result = null;
		GameObject prefab = GetPrefab(prefabName);
		ItemDrop val = default(ItemDrop);
		if ((Object)(object)prefab != (Object)null && prefab.TryGetComponent<ItemDrop>(ref val))
		{
			result = val.m_itemData.GetIcon();
		}
		return result;
	}

	public static Player GetPlayerByZDOID(ZDOID zid)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		foreach (Player allPlayer in Player.GetAllPlayers())
		{
			ZDOID zDOID = ((Character)allPlayer).GetZDOID();
			if (((ZDOID)(ref zDOID)).Equals(zid))
			{
				return allPlayer;
			}
		}
		return null;
	}

	public static Character GetCharacterByZDOID(string cid)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			ZDOID zDOID = allCharacter.GetZDOID();
			if (((object)(ZDOID)(ref zDOID)).ToString().Equals(cid))
			{
				return allCharacter;
			}
		}
		return null;
	}

	public static Character GetCharacterByZDOID(ZDOID cid)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			ZDOID zDOID = allCharacter.GetZDOID();
			if (((ZDOID)(ref zDOID)).Equals(cid))
			{
				return allCharacter;
			}
		}
		return null;
	}

	public static ZNetPeer GetPeerByRPC(ZRpc rpc)
	{
		foreach (ZNetPeer peer in ZNet.instance.GetPeers())
		{
			if (peer.m_rpc == rpc)
			{
				return peer;
			}
		}
		return null;
	}

	public static List<GameObject> GetGameObjectsOfType(Type t)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		List<GameObject> list = new List<GameObject>();
		Object[] array = Object.FindObjectsOfType(t);
		foreach (Object val in array)
		{
			list.Add(((Component)val).gameObject);
		}
		return list;
	}

	public static GameObject GetClosestGameObjectOfType(Type t, Vector3 point, float radius)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return GetGameObjectsOfTypeInRangeByDistance(t, point, radius)?[0];
	}

	public static List<GameObject> GetGameObjectsOfTypeInRangeByDistance(Type t, Vector3 point, float radius)
	{
		//IL_0007: 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_0039: Unknown result type (might be due to invalid IL or missing references)
		List<KeyValuePair<GameObject, float>> list = new List<KeyValuePair<GameObject, float>>();
		List<GameObject> gameObjectsOfTypeInRange = GetGameObjectsOfTypeInRange(t, point, radius);
		if (gameObjectsOfTypeInRange.Count > 0)
		{
			foreach (GameObject item in gameObjectsOfTypeInRange)
			{
				list.Add(new KeyValuePair<GameObject, float>(item, Vector3.Distance(item.transform.position, point)));
			}
			list.Sort((KeyValuePair<GameObject, float> pair1, KeyValuePair<GameObject, float> pair2) => pair1.Value.CompareTo(pair2.Value));
			return list.ConvertAll((KeyValuePair<GameObject, float> x) => x.Key);
		}
		return null;
	}

	public static List<GameObject> GetGameObjectsOfTypeInRange(Type t, Vector3 point, float radius)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		return (from x in GetGameObjectsOfType(t)
			where Vector3.Distance(x.transform.position, point) < radius
			select x).ToList();
	}

	public static float GetPointDepth(Vector3 p)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		return ZoneSystem.instance.m_waterLevel - GetSolidHeight(p);
	}

	public static List<string> GetDelimitedStringAsList(string delimitedString, char delimiter)
	{
		List<string> list = new List<string>();
		string[] array = delimitedString.Split(new char[1] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
		foreach (string text in array)
		{
			list.Add(text.Trim());
		}
		return list;
	}

	public static float GetSolidHeight(Vector3 p)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		int solidRayMask = ZoneSystem.instance.m_solidRayMask;
		float result = 0f;
		p.y += 1000f;
		RaycastHit val = default(RaycastHit);
		if (Physics.Raycast(p, Vector3.down, ref val, 2000f, solidRayMask) && !Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider.attachedRigidbody))
		{
			result = ((RaycastHit)(ref val)).point.y;
		}
		return result;
	}

	public static Transform FindChild(Transform aParent, string aName)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Expected O, but got Unknown
		foreach (Transform item in aParent)
		{
			Transform val = item;
			if (((Object)val).name == aName)
			{
				return val;
			}
			Transform val2 = FindChild(val, aName);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2;
			}
		}
		return null;
	}

	public static Transform FindParent(Transform go)
	{
		while ((Object)(object)go.parent != (Object)null)
		{
			go = go.parent;
		}
		return go;
	}

	public static GameObject GetPrefab(int prefabHash)
	{
		return GetPrefabByHash(prefabHash);
	}

	public static GameObject GetPrefabByHash(int prefabHash)
	{
		GameObject val = ObjectDB.instance.GetItemPrefab(prefabHash);
		Logging logger = Logging.GetLogger();
		if ((Object)(object)val != (Object)null)
		{
			logger.Debug("Found prefab in ObjectDB");
		}
		else
		{
			ZNetScene instance = ZNetScene.instance;
			val = ((instance != null) ? instance.GetPrefab(prefabHash) : null);
			if ((Object)(object)val != (Object)null)
			{
				logger.Debug("Found prefab in Scene");
			}
		}
		return val;
	}

	public static GameObject GetPrefab(string prefabName)
	{
		GameObject val = ObjectDB.instance.GetItemPrefab(prefabName);
		Logging logger = Logging.GetLogger();
		if ((Object)(object)val != (Object)null)
		{
			logger.Debug("Found " + prefabName + " in ObjectDB");
		}
		else
		{
			ZNetScene instance = ZNetScene.instance;
			val = ((instance != null) ? instance.GetPrefab(prefabName) : null);
			if ((Object)(object)val != (Object)null)
			{
				logger.Debug("Found " + prefabName + " in Scene");
			}
		}
		return val;
	}

	public static string SerializeFromDictionary<K, V>(string delimp, string delimc, IDictionary<K, V> dict)
	{
		if (dict == null)
		{
			return null;
		}
		IEnumerable<string> values = dict.Select(delegate(KeyValuePair<K, V> kvp)
		{
			KeyValuePair<K, V> keyValuePair = kvp;
			string? obj = keyValuePair.Key?.ToString();
			string text = delimc;
			keyValuePair = kvp;
			return obj + text + keyValuePair.Value;
		});
		return string.Join(delimp, values);
	}

	public static void DeserializeToDictionary<K, V>(string serializedString, string delimp, string delimc, ref IDictionary<K, V> dict)
	{
		if (dict == null)
		{
			return;
		}
		dict.Clear();
		string[] separator = new string[1] { delimp };
		string[] separator2 = new string[1] { delimc };
		string[] array = serializedString.Split(separator, StringSplitOptions.RemoveEmptyEntries);
		for (int i = 0; i < array.Length; i++)
		{
			string[] array2 = array[i].Split(separator2, StringSplitOptions.RemoveEmptyEntries);
			if (array2.Length == 2)
			{
				dict.Add(TypedValue<K>(array2[0]), TypedValue<V>(array2[1]));
			}
		}
	}

	public static T TypedValue<T>(object a)
	{
		return (T)Convert.ChangeType(a, typeof(T));
	}

	public static float TimeAdjustedRamp(float maxValue, float duration, float elapsedTime, float pctFromStartRise, float pctFromEndFall)
	{
		float num = elapsedTime / duration;
		if (num <= pctFromStartRise)
		{
			return maxValue * (num / pctFromStartRise);
		}
		if (num >= 1f - pctFromEndFall)
		{
			return maxValue * ((1f - num) / pctFromEndFall);
		}
		return maxValue;
	}

	public static bool CopyComponentToGameObject(Component original, ref GameObject destination)
	{
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Expected O, but got Unknown
		Logging logger = Logging.GetLogger();
		Type type = ((object)original).GetType();
		logger.Debug($"Original Type is {type}");
		GameObject obj = destination;
		logger.Debug("Destination GameObject " + ((obj != null) ? ((Object)obj).name : null));
		Component val = destination.GetComponent(type);
		if ((Object)(object)val == (Object)null)
		{
			val = destination.AddComponent(type);
		}
		if ((Object)(object)val == (Object)null)
		{
			logger.Debug("Destination component is null");
			return false;
		}
		Component val2 = (Component)Activator.CreateInstance(type);
		if ((Object)(object)val2 == (Object)null)
		{
			logger.Debug("Destination component is null");
			return false;
		}
		if ((Object)(object)val2 == (Object)null)
		{
			logger.Debug("Boxed component is null");
			return false;
		}
		FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (FieldInfo fieldInfo in fields)
		{
			fieldInfo.SetValue(val2, fieldInfo.GetValue(original));
		}
		val = val2;
		return true;
	}

	public static bool CopyObject(object original, object target)
	{
		Logging logger = Logging.GetLogger();
		Type type = original.GetType();
		Type type2 = target.GetType();
		if (type == null)
		{
			logger.Warning("Copy Object: Source object is null");
			Activator.CreateInstance(type);
			return false;
		}
		if (type2 == null)
		{
			logger.Warning("Copy Object: Destination object is null");
			return false;
		}
		if (type2 != type)
		{
			logger.Warning("Copy Object: Source and destination components are different types");
			return false;
		}
		FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (FieldInfo fieldInfo in fields)
		{
			fieldInfo.SetValue(target, fieldInfo.GetValue(original));
		}
		return true;
	}
}
internal class AtgeirBuilder
{
	public static SecondaryAttacks GetSecondaryAttacks(ItemData item)
	{
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		SecondaryAttacks secondaryAttacks = new SecondaryAttacks();
		AttackPrototype attackPrototype = Prototypes.GetAttackPrototype("AtgeirBronze");
		Logging logger = Logging.GetLogger();
		logger.Debug("Using atgeir secondary melee attack");
		secondaryAttacks.melee = item.m_shared.m_secondaryAttack.Clone();
		logger.Debug("Creating atgeir secondary projectile attack");
		secondaryAttacks.projectile = attackPrototype.secondaryAttack.Clone();
		secondaryAttacks.projectile.m_attackType = (AttackType)2;
		secondaryAttacks.projectile.m_consumeItem = true;
		secondaryAttacks.projectile.m_projectileAccuracy = 1f;
		Prototypes.ConfigAttackForWeapon(secondaryAttacks.projectile, item, item.m_shared.m_secondaryAttack, 2f, 1f, 2f, 1.5f);
		secondaryAttacks.projectile.m_attackProjectile = null;
		return secondaryAttacks;
	}
}
public class AttackPrototype
{
	public ItemData item;

	public Attack secondaryAttack;

	public Attack primaryAttack;

	public CharacterAnimEvent secondaryAnimationEvent;

	public CharacterAnimEvent primaryAnimationEvent;
}
internal class AxeBuilder2H
{
	public static SecondaryAttacks GetSecondaryAttacks(ItemData item)
	{
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		SecondaryAttacks secondaryAttacks = new SecondaryAttacks();
		AttackPrototype attackPrototype = Prototypes.GetAttackPrototype("Battleaxe");
		AttackPrototype attackPrototype2 = Prototypes.GetAttackPrototype("PickaxeBronze");
		Logging logger = Logging.GetLogger();
		logger.Debug("Using 2H axe secondary melee attack");
		secondaryAttacks.melee = item.m_shared.m_secondaryAttack.Clone();
		logger.Debug("Creating 2H axe secondary projectile attack");
		secondaryAttacks.projectile = attackPrototype.secondaryAttack.Clone();
		secondaryAttacks.projectile.m_attackAnimation = attackPrototype2.primaryAttack.m_attackAnimation;
		secondaryAttacks.projectile.m_animEvent = attackPrototype2.primaryAnimationEvent;
		secondaryAttacks.projectile.m_attackType = (AttackType)2;
		secondaryAttacks.projectile.m_consumeItem = true;
		secondaryAttacks.projectile.m_projectileAccuracy = 1f;
		Prototypes.ConfigAttackForWeapon(secondaryAttacks.projectile, item, item.m_shared.m_attack, 1.5f, 1f, 2f, 1.5f, 2f);
		secondaryAttacks.projectile.m_attackProjectile = null;
		return secondaryAttacks;
	}
}
internal class AxeBuilder
{
	public static SecondaryAttacks GetSecondaryAttacks(ItemData item)
	{
		SecondaryAttacks secondaryAttacks = new SecondaryAttacks();
		AttackPrototype attackPrototype = Prototypes.GetAttackPrototype("SpearBronze");
		Logging logger = Logging.GetLogger();
		logger.Debug("Using axe secondary melee attack");
		secondaryAttacks.melee = item.m_shared.m_secondaryAttack.Clone();
		logger.Debug("Creating axe secondary projectile attack");
		secondaryAttacks.projectile = attackPrototype.secondaryAttack.Clone();
		Prototypes.ConfigAttackForWeapon(secondaryAttacks.projectile, item, item.m_shared.m_secondaryAttack);
		secondaryAttacks.projectile.m_attackProjectile = null;
		return secondaryAttacks;
	}
}
internal class Cfg
{
	public static DelegatedConfigEntry<bool> enableAxes = null;

	public static DelegatedConfigEntry<bool> enableKnives = null;

	public static DelegatedConfigEntry<bool> enableSpears = null;

	public static DelegatedConfigEntry<bool> enableClubs = null;

	public static DelegatedConfigEntry<bool> enableSwords = null;

	public static DelegatedConfigEntry<bool> enablePickaxes = null;

	public static DelegatedConfigEntry<bool> weaponStones = null;

	public static DelegatedConfigEntry<bool> weaponWisps = null;

	public static DelegatedConfigEntry<bool> weaponEitr = null;

	public static DelegatedConfigEntry<bool> weaponEggs = null;

	public static DelegatedConfigEntry<bool> weaponTankards = null;

	public static DelegatedConfigEntry<bool> enableShields = null;

	public static DelegatedConfigEntry<bool> throwUnderhand = null;

	public static DelegatedConfigEntry<int> targetAdjustment = null;

	public static DelegatedConfigEntry<Logging.LogLevels> debugLevel = null;

	public static DelegatedConfigEntry<MaxAxe.Dynamics> gravity = null;

	public static DelegatedConfigEntry<bool> useSkill = null;

	public static DelegatedConfigEntry<string> externalExclude = null;

	public static DelegatedConfigEntry<bool> stackableWeapons = null;

	public static DelegatedConfigEntry<bool> mjolnirMode = null;

	public static DelegatedConfigEntry<bool> enablePolearms = null;

	public static DelegatedConfigEntry<bool> allow2Handed = null;

	public static ConfigEntry<bool> useMelee = null;

	public static ConfigEntry<bool> autoMelee = null;

	public static ConfigEntry<bool> autoEquip = null;

	public static ConfigEntry<bool> throwingStatus = null;

	public static ConfigEntry<MaxAxe.Finders> weaponFinder = null;

	public static ConfigEntry<Color> itemAmountColor = null;

	public static ConfigEntry<bool> forceSimpleTrail = null;

	public static ConfigEntry<bool> useKeyRelease = null;

	public static ConfigEntry<bool> disableIncompatible = null;

	public static ConfigEntry<bool> autoEquipShields = null;

	public static ConfigEntry<bool> saveSlotForFrostner = null;

	private static KeyCode[] keyModifiers = (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 };

	private static KeyboardShortcut toggleMeleeKeyDefault = new KeyboardShortcut((KeyCode)98, keyModifiers);

	public static DelegatedConfigEntry<KeyboardShortcut> toggleMeleeKey = null;

	private static KeyboardShortcut throwOneKeyDefault = new KeyboardShortcut((KeyCode)116, Array.Empty<KeyCode>());

	public static DelegatedConfigEntry<KeyboardShortcut> throwOneKey = null;

	private static KeyboardShortcut throwShieldKeyDefault = new KeyboardShortcut((KeyCode)103, Array.Empty<KeyCode>());

	public static DelegatedConfigEntry<KeyboardShortcut> throwShieldKey = null;

	public static void BepInExConfig(BaseUnityPlugin _instance)
	{
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Expected O, but got Unknown
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Expected O, but got Unknown
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: Expected O, but got Unknown
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0177: Expected O, but got Unknown
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Expected O, but got Unknown
		//IL_0213: Unknown result type (might be due to invalid IL or missing references)
		//IL_021d: Expected O, but got Unknown
		//IL_0264: Unknown result type (might be due to invalid IL or missing references)
		//IL_026e: Expected O, but got Unknown
		//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bf: Expected O, but got Unknown
		//IL_0306: Unknown result type (might be due to invalid IL or missing references)
		//IL_0310: Expected O, but got Unknown
		//IL_0357: Unknown result type (might be due to invalid IL or missing references)
		//IL_0361: Expected O, but got Unknown
		//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b2: Expected O, but got Unknown
		//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0403: Expected O, but got Unknown
		//IL_044a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0454: Expected O, but got Unknown
		//IL_049b: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a5: Expected O, but got Unknown
		//IL_04f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0502: Expected O, but got Unknown
		//IL_0555: Unknown result type (might be due to invalid IL or missing references)
		//IL_055f: Expected O, but got Unknown
		//IL_05b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_05bc: Expected O, but got Unknown
		//IL_060f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0619: Expected O, but got Unknown
		//IL_066c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0676: Expected O, but got Unknown
		//IL_06bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_06c7: Expected O, but got Unknown
		//IL_070e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0718: Expected O, but got Unknown
		//IL_076b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0775: Expected O, but got Unknown
		//IL_07ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_07b5: Expected O, but got Unknown
		//IL_0807: Unknown result type (might be due to invalid IL or missing references)
		//IL_0811: Expected O, but got Unknown
		//IL_0847: Unknown result type (might be due to invalid IL or missing references)
		//IL_0851: Expected O, but got Unknown
		//IL_0887: Unknown result type (might be due to invalid IL or missing references)
		//IL_0891: Expected O, but got Unknown
		//IL_08c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_08d1: Expected O, but got Unknown
		//IL_0920: Unknown result type (might be due to invalid IL or missing references)
		//IL_092a: Expected O, but got Unknown
		//IL_0970: Unknown result type (might be due to invalid IL or missing references)
		//IL_097a: Expected O, but got Unknown
		//IL_09b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_09ba: Expected O, but got Unknown
		//IL_09ef: Unknown result type (might be due to invalid IL or missing references)
		debugLevel = new DelegatedConfigEntry<Logging.LogLevels>(MaxAxe.LogChange);
		debugLevel.ConfigEntry = _instance.Config.Bind<Logging.LogLevels>("Utility", "LogLevel", Logging.LogLevels.Info, "Controls the level of information contained in the log. Set to 'Info' for normal use.");
		MaxAxe.Log.LogLevel = debugLevel.Value;
		useMelee = _instance.Config.Bind<bool>("General", "MeleeAttack", true, new ConfigDescription("When True, uses a melee secondary attack. Toggled in-game using the ToggleMeleeAttack key.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 30
			}
		}));
		toggleMeleeKey = new DelegatedConfigEntry<KeyboardShortcut>();
		toggleMeleeKey.ConfigEntry = _instance.Config.Bind<KeyboardShortcut>("General", "ToggleMeleeAttack", toggleMeleeKeyDefault, new ConfigDescription("Press this key to toggle in-game between Throw and Melee mode for enabled weapons.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 29
			}
		}));
		throwOneKey = new DelegatedConfigEntry<KeyboardShortcut>();
		throwOneKey.ConfigEntry = _instance.Config.Bind<KeyboardShortcut>("General", "ThrowOne", throwOneKeyDefault, new ConfigDescription("Press this key to throw the current weapon, regardless of Melee or Throw mode.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 28
			}
		}));
		useKeyRelease = _instance.Config.Bind<bool>("General", "ThrowOnRelease", false, new ConfigDescription("Set to True to throw when the ThrowOne or ThrowShield keys are released instead of pressed.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 27
			}
		}));
		throwShieldKey = new DelegatedConfigEntry<KeyboardShortcut>();
		throwShieldKey.ConfigEntry = _instance.Config.Bind<KeyboardShortcut>("General", "ThrowShield", throwShieldKeyDefault, new ConfigDescription("Press this key to throw an equipped round shield.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 26
			}
		}));
		throwUnderhand = new DelegatedConfigEntry<bool>();
		throwUnderhand.ConfigEntry = _instance.Config.Bind<bool>("General", "UnderhandShield", false, new ConfigDescription("Set to True to throw your shield using an underhand throw. Shields must also be enabled.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 25
			}
		}));
		enableAxes = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		enableAxes.ConfigEntry = _instance.Config.Bind<bool>("General", "EnableAxes", true, new ConfigDescription("Set to True to enable secondary throwing attacks for one-handed axes.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 24
			}
		}));
		enableClubs = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		enableClubs.ConfigEntry = _instance.Config.Bind<bool>("General", "EnableClubs", true, new ConfigDescription("Set to True to enable secondary throwing attacks for blunt weapons & torches. Torches, stones, sledges & wooden clubs also get secondary melee attacks.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 23
			}
		}));
		enableKnives = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		enableKnives.ConfigEntry = _instance.Config.Bind<bool>("General", "EnableKnives", true, new ConfigDescription("Set to True to enable secondary throwing attacks for knives.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 22
			}
		}));
		enablePolearms = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		enablePolearms.ConfigEntry = _instance.Config.Bind<bool>("General", "EnablePolearms", true, new ConfigDescription("Set to True to enable secondary throwing attacks for polearms. AllowTwoHandedWeapons must also be true.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 21
			}
		}));
		enableSpears = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		enableSpears.ConfigEntry = _instance.Config.Bind<bool>("General", "EnableSpears", true, new ConfigDescription("Set to True to enable secondary melee attack for spears.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 20
			}
		}));
		enableSwords = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		enableSwords.ConfigEntry = _instance.Config.Bind<bool>("General", "EnableSwords", true, new ConfigDescription("Set to True to enable secondary throwing attacks for swords.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 19
			}
		}));
		enablePickaxes = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		enablePickaxes.ConfigEntry = _instance.Config.Bind<bool>("General", "EnablePickaxes", true, new ConfigDescription("Set to True to enable secondary throwing and melee attacks for pickaxes. AllowTwoHandedWeapons must also be true.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 18
			}
		}));
		enableShields = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		enableShields.ConfigEntry = _instance.Config.Bind<bool>("General", "EnableShields", true, new ConfigDescription("Set to True to enable throwing round shields, by using the ThrowShield key.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 17
			}
		}));
		weaponStones = new DelegatedConfigEntry<bool>(MaxAxe.GroupsChange, useServerDelegate: true);
		weaponStones.ConfigEntry = _instance.Config.Bind<bool>("General", "WeaponStones", true, new ConfigDescription("Set to True to enable equipping and attacking with stones.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 16
			}
		}));
		weaponWisps = new DelegatedConfigEntry<bool>(MaxAxe.GroupsChange, useServerDelegate: true);
		weaponWisps.ConfigEntry = _instance.Config.Bind<bool>("General", "WeaponWisps", true, new ConfigDescription("Set to True to enable equipping and attacking with Wisps.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 15
			}
		}));
		weaponEitr = new DelegatedConfigEntry<bool>(MaxAxe.GroupsChange, useServerDelegate: true);
		weaponEitr.ConfigEntry = _instance.Config.Bind<bool>("General", "WeaponEitr", true, new ConfigDescription("Set to True to enable equipping and attacking with refined Eitr.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 14
			}
		}));
		weaponEggs = new DelegatedConfigEntry<bool>(MaxAxe.GroupsChange, useServerDelegate: true);
		weaponEggs.ConfigEntry = _instance.Config.Bind<bool>("General", "WeaponEggs", true, new ConfigDescription("Set to True to enable equipping and attacking with Eggs.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 13
			}
		}));
		weaponTankards = new DelegatedConfigEntry<bool>(MaxAxe.GroupsChange, useServerDelegate: true);
		weaponTankards.ConfigEntry = _instance.Config.Bind<bool>("General", "WeaponTankards", true, new ConfigDescription("Set to True to enable equipping and attacking with Tankards.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 12
			}
		}));
		mjolnirMode = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		mjolnirMode.ConfigEntry = _instance.Config.Bind<bool>("General", "MjolnirMode", false, new ConfigDescription("Set to True to enable Frostner returning to your hand after throwing.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 11
			}
		}));
		allow2Handed = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		allow2Handed.ConfigEntry = _instance.Config.Bind<bool>("General", "AllowTwoHandedWeapons", false, new ConfigDescription("Set to True to allow two-handed weapons to be thrown.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 10
			}
		}));
		stackableWeapons = new DelegatedConfigEntry<bool>(MaxAxe.StackableChange, useServerDelegate: true);
		stackableWeapons.ConfigEntry = _instance.Config.Bind<bool>("General", "StackableWeapons", false, new ConfigDescription("Set to True to allow throwable weapons to stack. See documentation for details before enabling stackable weapons.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 9
			}
		}));
		throwingStatus = _instance.Config.Bind<bool>("General", "ThrowingStatus", true, new ConfigDescription("Set to True to display a status effect if throwing is active.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 8
			}
		}));
		useSkill = new DelegatedConfigEntry<bool>(MaxAxe.ToggleSkill, useServerDelegate: true);
		useSkill.ConfigEntry = _instance.Config.Bind<bool>("Skill", "UseThrowingSkill", false, new ConfigDescription("Set to True to enable the Throwing skill. Used in place of specific weapon skills to improve stats for all thrown items.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 7
			}
		}));
		autoMelee = _instance.Config.Bind<bool>("General", "AutoMelee", false, new ConfigDescription("Set to True to automatically switch to melee mode after throwing a weapon, OR if last weapon in a stack (if StackableWeapons is True).", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 6
			}
		}));
		autoEquip = _instance.Config.Bind<bool>("General", "AutoEquip", true, new ConfigDescription("Set to True to automatically equip another weapon after throwing a weapon.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 5
			}
		}));
		autoEquipShields = _instance.Config.Bind<bool>("General", "AutoEquipShields", true, new ConfigDescription("Set to True to automatically equip shields after picking them up.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 4
			}
		}));
		targetAdjustment = new DelegatedConfigEntry<int>();
		targetAdjustment.ConfigEntry = _instance.Config.Bind<int>("General", "TargetAdjustment", -7, new ConfigDescription("Adjusts the throwing impact point in relation to the target reticle (the +). Set _instanced upon your 'typical' throwing distance. Default is -7.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-20, 20), new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 3
			}
		}));
		gravity = new DelegatedConfigEntry<MaxAxe.Dynamics>(useServerDelegate: true);
		gravity.ConfigEntry = _instance.Config.Bind<MaxAxe.Dynamics>("Throwing Dynamics", "ThrowingMode", MaxAxe.Dynamics.Default, new ConfigDescription("Sets the type of weapon dynamics in flight. Better uses earth nominal gravity and applies inertia and drag to thrown weapons.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 2
			}
		}));
		weaponFinder = _instance.Config.Bind<MaxAxe.Finders>("General", "WeaponFinder", MaxAxe.Finders.Wishbone, new ConfigDescription("Type of 'locator' effect added to thrown weapon to make it easier to find.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 1
			}
		}));
		saveSlotForFrostner = _instance.Config.Bind<bool>("Utility", "SaveSpaceForFrostner", false, "Set to True to ensure autopickup doesn't use up the last inventory slot for a returning weapon. Only active if Mjolnir mode is also on.");
		itemAmountColor = _instance.Config.Bind<Color>("Utility", "ItemAmountColor", Color.yellow, "Color of item quantity text in hotbar and inventory.");
		forceSimpleTrail = _instance.Config.Bind<bool>("Utility", "ForceSimpleTrail", false, "Set to True for MaxAxe to use the 'simple' trail of earlier releases.");
		externalExclude = new DelegatedConfigEntry<string>(MaxAxe.ExcludeChange, useServerDelegate: true);
		externalExclude.ConfigEntry = _instance.Config.Bind<string>("Mod Compatibility", "ExcludePrefabs", "", "A comma delimited string of prefabs to exclude from being thrown. Example: PrefabNameA,PrefabNameB");
		disableIncompatible = _instance.Config.Bind<bool>("Mod Compatibility", "DisableIncompatibleMods", true, "Automatically disable incompatible mods. Only those fully incompatible without a workaround will be disabled. See log file for warnings.");
	}
}
internal class ClubBuilder
{
	public static SecondaryAttacks GetSecondaryAttacks(ItemData item)
	{
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		SecondaryAttacks secondaryAttacks = new SecondaryAttacks();
		AttackPrototype attackPrototype = Prototypes.GetAttackPrototype("SpearBronze");
		AttackPrototype attackPrototype2 = Prototypes.GetAttackPrototype("MaceBronze");
		Logging logger = Logging.GetLogger();
		if (!string.IsNullOrEmpty(item.m_shared.m_secondaryAttack.m_attackAnimation))
		{
			logger.Debug("Using club secondary melee attack");
			secondaryAttacks.melee = item.m_shared.m_secondaryAttack.Clone();
		}
		else
		{
			logger.Debug("Creating club secondary melee attack");
			secondaryAttacks.melee = item.m_shared.m_attack.Clone();
			Prototypes.ConfigAttackForWeapon(secondaryAttacks.melee, item, item.m_shared.m_attack, 2f, 2f, 2f, 2f, 2f);
			secondaryAttacks.melee.m_attackAnimation = attackPrototype2.secondaryAttack.m_attackAnimation;
			secondaryAttacks.melee.m_animEvent = attackPrototype2.secondaryAnimationEvent;
			secondaryAttacks.melee.m_attackType = attackPrototype2.secondaryAttack.m_attackType;
			secondaryAttacks.melee.m_attackAngle = attackPrototype2.secondaryAttack.m_attackAngle;
		}
		logger.Debug("Creating club secondary projectile attack");
		secondaryAttacks.projectile = attackPrototype.secondaryAttack.Clone();
		Prototypes.ConfigAttackForWeapon(secondaryAttacks.projectile, item, item.m_shared.m_secondaryAttack);
		secondaryAttacks.projectile.m_attackProjectile = null;
		return secondaryAttacks;
	}
}
public class DynamicProps
{
	public float Vel { get; set; }

	public float Drag { get; set; }

	internal DynamicProps(float v, float d)
	{
		Vel = v;
		Drag = d;
	}
}
public class EffectGroup
{
	public float scale { get; }

	public HashSet<string> effects { get; }

	public EffectGroup(float scale, HashSet<string> effects)
	{
		this.effects = effects;
		this.scale = scale;
	}
}
internal class EggBuilder
{
	public static SecondaryAttacks GetSecondaryAttacks(ItemData item)
	{
		SecondaryAttacks secondaryAttacks = new SecondaryAttacks();
		AttackPrototype attackPrototype = Prototypes.GetAttackPrototype("SpearBronze");
		Logging logger = Logging.GetLogger();
		secondaryAttacks.melee = null;
		logger.Debug("Creating egg secondary projectile attack");
		secondaryAttacks.projectile = attackPrototype.secondaryAttack.Clone();
		secondaryAttacks.projectile.m_attackStamina = 2f;
		secondaryAttacks.projectile.m_attackAnimation = attackPrototype.secondaryAttack.m_attackAnimation;
		secondaryAttacks.projectile.m_animEvent = attackPrototype.secondaryAnimationEvent;
		secondaryAttacks.projectile.m_attackProjectile = null;
		return secondaryAttacks;
	}
}
internal class Finder
{
	private GameObject _finderEffect;

	private string PrefabName { get; }

	internal Vector3 Offset { get; }

	internal GameObject FinderEffect
	{
		get
		{
			if ((Object)(object)_finderEffect == (Object)null)
			{
				_finderEffect = Utils.GetPrefab(PrefabName);
			}
			return _finderEffect;
		}
	}

	internal Finder(string name, Vector3 offset)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		PrefabName = name;
		Offset = offset;
	}
}
internal class KnifeBuilder
{
	public static SecondaryAttacks GetSecondaryAttacks(ItemData item)
	{
		SecondaryAttacks secondaryAttacks = new SecondaryAttacks();
		AttackPrototype attackPrototype = Prototypes.GetAttackPrototype("SpearBronze");
		Logging logger = Logging.GetLogger();
		logger.Debug("Using knife secondary melee attack");
		secondaryAttacks.melee = item.m_shared.m_secondaryAttack.Clone();
		logger.Debug("Creating knife secondary projectile attack");
		secondaryAttacks.projectile = attackPrototype.secondaryAttack.Clone();
		Prototypes.ConfigAttackForWeapon(secondaryAttacks.projectile, item, item.m_shared.m_secondaryAttack);
		secondaryAttacks.projectile.m_attackProjectile = null;
		return secondaryAttacks;
	}
}
internal class MagicBuilder
{
	public static SecondaryAttacks GetSecondaryAttacks(ItemData item)
	{
		SecondaryAttacks secondaryAttacks = new SecondaryAttacks();
		AttackPrototype attackPrototype = Prototypes.GetAttackPrototype("SpearBronze");
		Logging logger = Logging.GetLogger();
		secondaryAttacks.melee = null;
		logger.Debug("Creating magic secondary projectile attack");
		secondaryAttacks.projectile = attackPrototype.secondaryAttack.Clone();
		secondaryAttacks.projectile.m_attackStamina = 3f;
		secondaryAttacks.projectile.m_attackAnimation = attackPrototype.secondaryAttack.m_attackAnimation;
		secondaryAttacks.projectile.m_animEvent = attackPrototype.secondaryAnimationEvent;
		secondaryAttacks.projectile.m_attackProjectile = null;
		return secondaryAttacks;
	}
}
[BepInPlugin("neobotics.valheim_mod.maxaxe", "MaxAxe", "0.4.6")]
[BepInProcess("valheim.exe")]
[BepInProcess("valheim_server.exe")]
public class MaxAxe : BaseUnityPlugin
{
	public enum Finders
	{
		Wishbone,
		Autopick,
		None
	}

	public enum Dynamics
	{
		Default,
		Better
	}

	[HarmonyPatch(typeof(Inventory), "HaveEmptySlot")]
	private static class Inventory_HaveEmptySlot_Patch
	{
		[HarmonyPostfix]
		private static void Inventory_HaveEmptySlot_Postfix(Inventory __instance, ref bool __result)
		{
			Player localPlayer = Player.m_localPlayer;
			if (__instance == ((Humanoid)(localPlayer?)).m_inventory && Cfg.mjolnirMode.Value && Cfg.saveSlotForFrostner.Value && ((Humanoid)localPlayer).GetCurrentWeapon() == ((Humanoid)localPlayer).m_unarmedWeapon.m_itemData && __instance.GetEmptySlots() <= 1)
			{
				Log.Debug("Saving space for returning weapons");
				__result = false;
			}
		}
	}

	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
	{
		typeof(string),
		typeof(int),
		typeof(float),
		typeof(Vector2i),
		typeof(bool),
		typeof(int),
		typeof(int),
		typeof(long),
		typeof(string),
		typeof(Dictionary<string, string>),
		typeof(int),
		typeof(bool)
	})]
	private static class Inventory_AddItem_AddOnLoad_Patch
	{
		private static void Prefix(Inventory __instance, string name, int stack, float durability, Vector2i pos, bool equipped, int quality, int variant, long crafterID, string crafterName, Dictionary<string, string> customData)
		{
			Log.Trace($"AddItem_OnLoad prefix {name} stack {stack}");
			if (stack > 1)
			{
				if (customData == null)
				{
					customData = new Dictionary<string, string>();
				}
				customData.Add(Z_MAXAXE.ToString(), stack.ToString());
			}
		}
	}

	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
	private static class Inventory_AddItem_AddNew_Patch
	{
		private static bool Prefix(Inventory __instance, ItemData item, string ___m_name, out bool __result)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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)
			Log.Trace("InventoryAddItem_AddNew prefix " + __instance.GetName());
			__result = true;
			if (item != null && !Cfg.stackableWeapons.Value && IsStackableWeapon(item) && item.m_stack > 1)
			{
				__result = false;
				int stack = item.m_stack;
				bool flag = false;
				for (int i = 0; i < stack; i++)
				{
					Vector2i val = __instance.FindEmptySlot(true);
					if (val.x >= 0)
					{
						flag = __instance.AddItem(item, 1, val.x, val.y);
					}
					if (!flag)
					{
						break;
					}
				}
				if (flag)
				{
					item.m_shared.m_maxStackSize = Math.Max(item.m_stack, 1);
				}
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
	{
		typeof(ItemData),
		typeof(int),
		typeof(int),
		typeof(int)
	})]
	private static class Inventory_AddItem_ToSlot_Patch
	{
		private static bool Prefix(Inventory __instance, ItemData item, ref int amount, int x, int y, string ___m_name)
		{
			Log.Trace("AddItem_ToSlot prefix " + __instance.GetName());
			string key = Z_MAXAXE.ToString();
			if (item != null && item.m_customData.TryGetValue(key, out var value))
			{
				if (IsStackableWeapon(item))
				{
					int num = (amount = (item.m_stack = int.Parse(value)));
					if (item.m_shared.m_maxStackSize < num)
					{
						item.m_shared.m_maxStackSize = num;
					}
				}
				item.m_customData.Remove(key);
			}
			if (item != null && Cfg.stackableWeapons.Value && stackables.ContainsKey(item.m_shared.m_name))
			{
				ItemData itemAt = __instance.GetItemAt(x, y);
				if (itemAt == null)
				{
					if (Cfg.stackableWeapons.Value && stackables.ContainsKey(item.m_shared.m_name))
					{
						item.m_shared.m_maxStackSize = stackables[item.m_shared.m_name];
					}
					return true;
				}
				if (itemAt != null && item.m_durability <= 0f && itemAt.m_durability <= 0f)
				{
					return true;
				}
				if (itemAt != null && item.m_durability <= 0f)
				{
					return false;
				}
				if (itemAt != null && itemAt.m_durability <= 0f)
				{
					return false;
				}
				if (itemAt != null && item.m_durability > 0f && itemAt.m_durability > 0f)
				{
					itemAt.m_durability = Mathf.Min(item.m_durability, itemAt.m_durability);
					return true;
				}
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Inventory), "MoveItemToThis", new Type[]
	{
		typeof(Inventory),
		typeof(ItemData),
		typeof(int),
		typeof(int),
		typeof(int)
	})]
	private static class Inventory_MoveItemToThis_Slot_Patch
	{
		private static void Prefix(Inventory __instance, Inventory fromInventory, ItemData item, ref int amount, int x, int y, string ___m_name)
		{
			Log.Trace("MoveItemToThis_Slot to " + __instance.GetName() + " from " + fromInventory.GetName() + " item " + item?.m_shared.m_name);
			if (item != null && !Cfg.stackableWeapons.Value && IsStackableWeapon(item))
			{
				amount = 1;
			}
		}
	}

	[HarmonyPatch(typeof(Inventory), "MoveItemToThis", new Type[]
	{
		typeof(Inventory),
		typeof(ItemData)
	})]
	private static class Inventory_MoveItemToThis_Patch
	{
		private static bool Prefix(Inventory __instance, Inventory fromInventory, ItemData item, string ___m_name)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			Log.Trace("MoveItemToThis to " + __instance.GetName() + " from " + ((fromInventory != null) ? fromInventory.GetName() : null) + " item " + item?.m_shared.m_name);
			if (item != null && !Cfg.stackableWeapons.Value && IsStackableWeapon(item) && item.m_stack > 1)
			{
				int stack = item.m_stack;
				bool flag = false;
				for (int i = 0; i < stack; i++)
				{
					Vector2i val = __instance.FindEmptySlot(true);
					if (val.x >= 0)
					{
						flag = __instance.MoveItemToThis(fromInventory, item, 1, val.x, val.y);
					}
					if (!flag)
					{
						break;
					}
				}
				if (flag)
				{
					item.m_shared.m_maxStackSize = Math.Max(item.m_stack, 1);
				}
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(VisEquipment), "AttachItem")]
	private static class VisEquipment_AttachItem_Patch
	{
		private static void Postfix(VisEquipment __instance, int itemHash, int variant, Transform joint, bool enableEquipEffects, GameObject __result)
		{
			if (shieldVariant != 0 && __instance.m_isPlayer)
			{
				ItemStyle componentInChildren = __result.GetComponentInChildren<ItemStyle>();
				if (componentInChildren != null)
				{
					componentInChildren.Setup(shieldVariant);
				}
				shieldVariant = 0;
			}
		}
	}

	[HarmonyPatch(typeof(VisEquipment), "SetRightHandEquipped")]
	private static class VisEquipment_SetRightHandEquiped_Patch
	{
		[HarmonyAfter(new string[] { "blacks7ar.WeaponHolsterOverhaul" })]
		private static void Postfix(int hash, GameObject ___m_rightItemInstance, int ___m_currentRightItemHash, bool __result)
		{
			//IL_001c: 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)
			if (TryGetActiveNonWeapon(hash, out var nonWeapon) && __result && (Object)(object)___m_rightItemInstance != (Object)null)
			{
				___m_rightItemInstance.transform.localScale = nonWeapon.localScale;
				___m_rightItemInstance.transform.localPosition = nonWeapon.rightHandOffset;
				MeshRenderer val = default(MeshRenderer);
				if (___m_rightItemInstance.TryGetComponent<MeshRenderer>(ref val))
				{
					((Renderer)val).enabled = true;
				}
			}
		}
	}

	[HarmonyPatch(typeof(VisEquipment), "SetLeftHandEquipped")]
	private static class VisEquipment_SetLeftHandEquiped_Patch
	{
		[HarmonyAfter(new string[] { "blacks7ar.WeaponHolsterOverhaul" })]
		private static void Postfix(int hash, GameObject ___m_leftItemInstance, bool __result)
		{
			//IL_001c: 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)
			if (TryGetActiveNonWeapon(hash, out var nonWeapon) && __result && (Object)(object)___m_leftItemInstance != (Object)null)
			{
				___m_leftItemInstance.transform.localScale = nonWeapon.localScale;
				___m_leftItemInstance.transform.localPosition = nonWeapon.leftHandOffset;
				MeshRenderer val = default(MeshRenderer);
				if (___m_leftItemInstance.TryGetComponent<MeshRenderer>(ref val))
				{
					((Renderer)val).enabled = true;
				}
			}
		}
	}

	[HarmonyPatch(typeof(VisEquipment), "AttachBackItem")]
	private static class VisEquipment_AttachBackItem_Patch
	{
		[HarmonyAfter(new string[] { "blacks7ar.WeaponHolsterOverhaul" })]
		private static void Postfix(GameObject __result, int hash, int variant, bool rightHand)
		{
			Log.Debug("VisEquipment AttachBackItem postfix");
			if (TryGetActiveNonWeapon(hash, out var _))
			{
				Log.Debug("Attaching back item");
				__result.SetActive(false);
			}
		}
	}

	[HarmonyPatch(typeof(SEMan), "GetHUDStatusEffects")]
	private static class Hud_GetHUDStatusEffects_Patch
	{
		private static void Prefix(List<StatusEffect> effects)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Invalid comparison between Unknown and I4
			if (!Cfg.throwingStatus.Value || Cfg.useMelee.Value || ((Character)Player.m_localPlayer).InPlaceMode())
			{
				return;
			}
			if ((Object)(object)throwingSE == (Object)null)
			{
				CreateThrowingStatusEffect();
			}
			ItemData currentWeapon = ((Humanoid)Player.m_localPlayer).GetCurrentWeapon();
			if (currentWeapon == null)
			{
				return;
			}
			if ((int)currentWeapon.m_shared.m_skillType == 11)
			{
				((StatusEffect)throwingSE).m_icon = unarmedIcon;
				((StatusEffect)throwingSE).m_flashIcon = false;
			}
			else
			{
				((StatusEffect)throwingSE).m_icon = currentWeapon.GetIcon();
				DelegatedConfigEntry<bool> dce;
				if (IsExcluded(currentWeapon) || ((int)currentWeapon.m_shared.m_itemType == 14 && !Cfg.allow2Handed.Value))
				{
					((StatusEffect)throwingSE).m_flashIcon = true;
				}
				else if (TryGetWeaponGroup(currentWeapon, out dce))
				{
					((StatusEffect)throwingSE).m_flashIcon = !dce.Value;
				}
				else if (IsActiveWeapon(currentWeapon))
				{
					((StatusEffect)throwingSE).m_flashIcon = false;
				}
				else
				{
					((StatusEffect)throwingSE).m_flashIcon = true;
				}
			}
			effects.Add((StatusEffect)(object)throwingSE);
		}
	}

	[HarmonyPatch(typeof(Humanoid), "DrainEquipedItemDurability")]
	private static class Humanoid_DrainEquipedItemDurability_Patch
	{
		private static bool Prefix(Humanoid __instance, ItemData item, float dt)
		{
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			if (item != null && Cfg.stackableWeapons.Value && stackables.ContainsKey(item.m_shared.m_name) && item.m_stack > 1)
			{
				item.m_durability -= item.m_shared.m_durabilityDrain * dt;
				if (item.m_durability <= 0f && (Object)(object)item.m_lastProjectile == (Object)null)
				{
					Inventory inventory = __instance.m_inventory;
					((Character)__instance).Message((MessageType)1, Localization.instance.Localize("$msg_broke", new string[1] { item.m_shared.m_name }), 0, item.GetIcon());
					ItemData val = item.Clone();
					val.m_equipped = false;
					Log.Debug("Removing broken item from stack");
					inventory.RemoveItem(item, 1);
					item.m_durability = MaxLeveledDurability(item);
					Log.Debug("Set remaining stack durability to max");
					if (!item.m_shared.m_destroyBroken)
					{
						List<ItemData> inventory2 = inventory.m_inventory;
						ItemData val2 = FindAvailableBrokenStack(inventory2, item);
						if (val2 != null)
						{
							val2.m_stack++;
							Log.Debug("Broken item added to existing stack");
						}
						else if (inventory.HaveEmptySlot())
						{
							Vector2i gridPos = inventory.FindEmptySlot(false);
							val.m_gridPos = gridPos;
							inventory2.Add(val);
							val.m_stack = 1;
							inventory.Changed();
							Log.Debug("Broken item was added to new slot");
						}
						else
						{
							wasDropped = true;
							__instance.DropItem(inventory, val, 1);
							Log.Debug("Broken item was dropped");
						}
					}
				}
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Humanoid), "StartAttack")]
	private static class Humanoid_StartAttack_Patch
	{
		[HarmonyPriority(700)]
		private static bool Prefix(Humanoid __instance, Character target, bool secondaryAttack, out StateResult __state, float ___m_timeSinceLastAttack, ref ItemData ___m_rightItem)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Invalid comparison between Unknown and I4
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Invalid comparison between Unknown and I4
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			__state = new StateResult();
			Log.Trace("Humanoid_StartAttack_Patch prefix");
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				Attack val = null;
				if (!((Character)__instance).InAttack() && secondaryAttack)
				{
					ItemData val2 = ___m_rightItem;
					if ((Object)(object)val2?.m_dropPrefab != (Object)null)
					{
						if ((Object)(object)returningWeapon != (Object)null)
						{
							return false;
						}
						if ((int)val2.m_shared.m_itemType == 5)
						{
							val2.m_shared.m_itemType = (ItemType)3;
						}
						if (Prototypes.IsConfigured(val2.m_shared.m_name) || IsThrowable(val2))
						{
							Log.Debug("Humanoid StartAttack");
							val = Prototypes.GetSecondaryAttack(val2, !IsThrow());
							if (val == null || !((Object)(object)val2.m_dropPrefab != (Object)null))
							{
								Log.Debug("Item does not have special attack");
								return false;
							}
							Logging log = Log;
							GameObject dropPrefab = val2.m_dropPrefab;
							log.Debug("Attacking with prefab " + ((dropPrefab != null) ? ((Object)dropPrefab).name : null));
							if ((int)val.m_attackType == 2 && ___m_timeSinceLastAttack < 0.3f)
							{
								Log.Trace("Aborting secondary spammed throwing attack");
								return false;
							}
							if (((Object)val2.m_dropPrefab).name.StartsWith("Shield"))
							{
								ShieldBuilder.SetShieldThrowType(val, Cfg.throwUnderhand.Value);
							}
							if (((Object)val2.m_dropPrefab).name.Contains("Tankard"))
							{
								Log.Debug("Tankard secondary attack");
								val2.m_shared.m_ammoType = null;
								tankardEffectList = val2.m_shared.m_startEffect;
								val2.m_shared.m_startEffect = emptyTankardEffectList;
							}
							val2.m_shared.m_secondaryAttack = val;
							Log.Debug($"Initiating {val.m_attackType} secondary attack");
							if (EpicLootDetected())
							{
								Log.Debug("Bypassing EpicLoot Humanoid StartAttack patch");
								__state.Result = ReversePatches.HumanoidStartAttack.RunUnpatched(__instance, target, secondaryAttack);
								__state.UseState = true;
							}
						}
						else
						{
							Log.Debug("Using default secondary attack");
						}
					}
				}
			}
			return true;
		}

		[HarmonyPriority(100)]
		private static void Postfix(Humanoid __instance, Character target, bool secondaryAttack, StateResult __state, ref bool __result, ref ItemData ___m_rightItem)
		{
			Log.Trace("Humanoid_StartAttack_Patch postfix");
			if (__state.UseState)
			{
				__result = __state.Result;
			}
		}
	}

	[HarmonyPatch(typeof(Attack), "OnAttackTrigger")]
	private static class Attack_OnAttackTrigger_Patch
	{
		[HarmonyPrefix]
		private static void Attack_OnAttackTrigger_Prefix(Attack __instance, ItemData ___m_weapon, Humanoid ___m_character, out EffectData[] __state)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Invalid comparison between Unknown and I4
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Invalid comparison between Unknown and I4
			Log.Debug("Attack_OnAttackTrigger_Patch_Prefix");
			__state = null;
			if ((Object)(object)___m_character == (Object)(object)Player.m_localPlayer && Cfg.allow2Handed.Value && (int)___m_weapon.m_shared.m_skillType == 3 && (int)___m_weapon.m_shared.m_itemType == 14 && __instance.m_attackAnimation != "swing_sledge")
			{
				__state = ___m_weapon.m_shared.m_triggerEffect.m_effectPrefabs.Clone() as EffectData[];
				Log.Debug("Removing sledge AOE effects");
				___m_weapon.m_shared.m_triggerEffect.m_effectPrefabs = Prototypes.FilterEffectData(___m_weapon.m_shared.m_triggerEffect.m_effectPrefabs, sledgeAnimationExcludes);
			}
		}

		[HarmonyPostfix]
		private static void Attack_OnAttackTrigger_Postfix(Attack __instance, ItemData ___m_weapon, EffectData[] __state)
		{
			Log.Debug("Attack_OnAttackTrigger_Patch_Postfix");
			if (__state != null)
			{
				Log.Debug("Replacing sledge AOE effects");
				___m_weapon.m_shared.m_triggerEffect.m_effectPrefabs = __state;
			}
		}
	}

	[HarmonyPatch(typeof(Attack), "ProjectileAttackTriggered")]
	[HarmonyPriority(700)]
	private static class Attack_ProjectileAttackTriggered_Patch
	{
		private static void Prefix(Attack __instance, ItemData ___m_weapon, Humanoid ___m_character)
		{
			Log.Trace("Attack_ProjectileAttackTriggered_Patch prefix");
			if ((Object)(object)___m_character == (Object)(object)Player.m_localPlayer && ___m_weapon != null && Prototypes.IsConfigured(___m_weapon.m_shared.m_name) && IsThrow() && (Object)(object)__instance.m_attackProjectile == (Object)null && (Object)(object)___m_weapon?.m_dropPrefab != (Object)null)
			{
				__instance.m_attackProjectile = Prototypes.GetProjectileizedPrefab(___m_weapon, TryGetActiveNonWeapon(((Object)___m_weapon.m_dropPrefab).name, out var _));
			}
		}
	}

	[HarmonyPatch(typeof(Attack), "FireProjectileBurst")]
	private static class Attack_FireProjectileBurst_Patch
	{
		[HarmonyPriority(100)]
		private static bool Prefix(Attack __instance, Character ___m_character, ItemData ___m_weapon, ref bool __state)
		{
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			Log.Trace("Attack_FireProjectileBurst_Patch prefix");
			__state = false;
			if ((Object)(object)___m_character == (Object)(object)Player.m_localPlayer && ___m_weapon != null && Prototypes.IsConfigured(___m_weapon.m_shared.m_name) && IsThrow())
			{
				Log.Debug("Attack_FireProjectileBurst");
				if (!((Object)(object)__instance.m_attackProjectile != (Object)null) || !((Object)(object)__instance.m_attackProjectile.GetComponent<Projectile>() != (Object)null))
				{
					Log.Warning("Projectile is missing or invalid");
					__state = false;
					return false;
				}
				__state = true;
				returnSpeed = __instance.m_projectileVel;
				__instance.m_launchAngle = Cfg.targetAdjustment.Value;
				if (Cfg.gravity.Value == Dynamics.Better)
				{
					__instance.m_projectileVel = 28f;
					__instance.m_projectileVel -= ___m_weapon.m_shared.m_weight;
					__instance.m_launchAngle -= 5f * GetDragFactor(___m_weapon);
				}
				else
				{
					__instance.m_projectileVel = 20f;
				}
				if (Cfg.useSkill.Value)
				{
					Log.Debug("Using throwing skill");
					throwingSkill = null;
					throwingSkill = new ThrowingSkillHelper(___m_character.GetSkillLevel(CustomSkill.GetCustomSkillType()), ___m_weapon.m_shared.m_skillType);
					__instance.m_skillAccuracy = true;
					__instance.m_projectileAccuracy = 0f;
					__instance.m_projectileAccuracyMin = 2f + (float)rand.NextDouble();
					float num = Mathf.Lerp(0f, 3f, throwingSkill.ThrowingFactor);
					__instance.m_projectileVel += num;
				}
				else
				{
					__instance.m_skillAccuracy = false;
				}
				if (Log.LogLevel >= Logging.LogLevels.Trace)
				{
					Logging log = Log;
					object obj;
					if (__instance == null)
					{
						obj = null;
					}
					else
					{
						GameObject attackProjectile = __instance.m_attackProjectile;
						obj = ((attackProjectile != null) ? ((Object)attackProjectile).name : null);
					}
					log.Trace("Projectile m_attackProjectile " + (string?)obj + " is configured");
				}
				if (EpicLootDetected())
				{
					Log.Debug("Skipping other Attack FireProjectileBurst patches");
					ReversePatches.FireProjectile_Burst.RunUnpatched(__instance);
					return false;
				}
			}
			return true;
		}

		[HarmonyPriority(700)]
		private static void Postfix(Attack __instance, Character ___m_character, ItemData ___m_weapon, ref bool __state)
		{
			Log.Trace("Attack_FireProjectileBurst_Patch postfix");
			if (__state && ___m_weapon != null && IsThrow())
			{
				ActivateProjectile(___m_weapon.m_lastProjectile.gameObject);
			}
		}
	}

	[HarmonyPatch(typeof(Projectile), "Setup")]
	private static class Projectile_Setup_Patch
	{
		private static void Postfix(Projectile __instance, Character owner, Vector3 velocity, float hitNoise, HitData hitData, ItemData item, ZNetView ___m_nview)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Invalid comparison between Unknown and I4
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Invalid comparison between Unknown and I4
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			Log.Trace("Projectile_Setup_Patch postfix");
			if (!((Object)(object)owner == (Object)(object)Player.m_localPlayer) || item == null)
			{
				return;
			}
			GameObject gameObject = ((Component)__instance).gameObject;
			if (TryGetActiveNonWeapon(item, out var nonWeapon))
			{
				Log.Debug("Setting local scale for non-item types");
				gameObject.transform.localScale = nonWeapon.localScale;
			}
			if (!Prototypes.IsConfigured(item.m_shared.m_name) || !IsThrow())
			{
				return;
			}
			Log.Debug("Projectile Setup postfix");
			if ((int)item.m_shared.m_skillType == 6)
			{
				Log.Debug("Set Shield orientation");
				Transform transform = ((Component)__instance).transform;
				transform.rotation *= Quaternion.Euler(new Vector3(0f, 0f, Cfg.throwUnderhand.Value ? (-70f) : 15f));
				__instance.m_rotateVisual = -720f;
			}
			if ((int)item.m_shared.m_itemType == 15)
			{
				Transform val = gameObject.transform.Find("attach").Find("equiped");
				if ((Object)(object)val != (Object)null)
				{
					((Component)val).gameObject.SetActive(true);
				}
			}
		}
	}

	[HarmonyPatch(typeof(Skills), "GetSkillLevel")]
	private static class Skills_GetSkillLevel_Patch
	{
		[HarmonyPostfix]
		private static void Skills_GetSkillLevel_Postfix(Skills __instance, SkillType skillType, ref float __result, Player ___m_player)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)___m_player != (Object)(object)Player.m_localPlayer) && Cfg.useSkill.Value && throwingSkill != null && throwingSkill.CurrentAttackSkill == skillType && !(throwingSkill.ThrowingLevel <= 0f))
			{
				__result = (__result + throwingSkill.ThrowingLevel * 2f) / 3f;
			}
		}
	}

	[HarmonyPatch(typeof(SEMan), "ModifyAttack")]
	private static class SEMan_ModifyAttack_Patch
	{
		private static void Postfix(SEMan __instance, ref SkillType skill, ref HitData hitData, Character ___m_character)
		{
			//IL_0057: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected I4, but got Unknown
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Invalid comparison between Unknown and I4
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Invalid comparison between Unknown and I4
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Invalid comparison between Unknown and I4
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Invalid comparison between Unknown and I4
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Invalid comparison between Unknown and I4
			Log.Trace("SEMan_ModifyAttack_Patch_Postfix");
			if (!((Object)(object)___m_character == (Object)(object)Player.m_localPlayer))
			{
				return;
			}
			Character character = __instance.m_character;
			Character obj = ((character is Player) ? character : null);
			bool currentAttackIsSecondary = ((Humanoid)obj).m_currentAttackIsSecondary;
			Attack currentAttack = ((Humanoid)obj).m_currentAttack;
			ItemData val = ((currentAttack != null) ? currentAttack.GetWeapon() : null);
			if (!(currentAttack != null && val != null && currentAttackIsSecondary))
			{
				return;
			}