Decompiled source of KeenCombat v1.1.0

KeenCombat.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
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 System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using KeenCombat.HUD;
using KeenCombat.Patches;
using KeenCombat.Skills;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("KeenCombat")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("KeenCombat")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("d7d97222-a81d-4684-bd01-f7d0b9549eb5")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace KeenCombat
{
	public class Class1
	{
	}
	public static class KC_Log
	{
		public static bool VerboseLogging;

		public static void Info(string msg)
		{
			Plugin.Log.LogInfo((object)msg);
		}

		public static void Warn(string msg)
		{
			Plugin.Log.LogWarning((object)msg);
		}

		public static void Error(string msg)
		{
			Plugin.Log.LogError((object)msg);
		}

		public static void Debug(string msg)
		{
			if (VerboseLogging)
			{
				Plugin.Log.LogInfo((object)("[DEBUG] " + msg));
			}
		}
	}
	public static class NetworkedEffects
	{
		private const string RpcVfxSfx = "KeenCombat_VfxSfx";

		private const string RpcVfx = "KeenCombat_Vfx";

		private const string RpcSfx = "KeenCombat_Sfx";

		private const string RpcOgg = "KeenCombat_Ogg";

		private const string RpcAnimTrig = "KeenCombat_AnimTrigger";

		private const string RpcAnimSpeed = "KeenCombat_AnimSpeed";

		private const string RpcMeteor = "KeenCombat_Meteor";

		private const string RpcIceFreeze = "KeenCombat_IceFreeze";

		private const string RpcVfxAttached = "KeenCombat_VfxAttached";

		private const string RpcSanctuary = "KeenCombat_Sanctuary";

		private const string RpcRegen = "KeenCombat_Regeneration";

		private const string RpcAnimPlay = "KeenCombat_AnimPlay";

		private const string RpcTracer = "KeenCombat_Tracer";

		private static ZRoutedRpc? _registeredOn = null;

		private static readonly Dictionary<string, AudioClip> _oggCache = new Dictionary<string, AudioClip>();

		public static void ResetRegistration()
		{
		}

		public static void Register()
		{
			if (ZRoutedRpc.instance != null && _registeredOn != ZRoutedRpc.instance)
			{
				ZRoutedRpc.instance.Register<string, string, Vector3, Quaternion, float>("KeenCombat_VfxSfx", (Method<string, string, Vector3, Quaternion, float>)OnReceiveVfxSfx);
				ZRoutedRpc.instance.Register<string, Vector3, Quaternion, float>("KeenCombat_Vfx", (Method<string, Vector3, Quaternion, float>)OnReceiveVfx);
				ZRoutedRpc.instance.Register<string, Vector3, Quaternion>("KeenCombat_Sfx", (Action<long, string, Vector3, Quaternion>)OnReceiveSfx);
				ZRoutedRpc.instance.Register<string, Vector3>("KeenCombat_Ogg", (Action<long, string, Vector3>)OnReceiveOgg);
				ZRoutedRpc.instance.Register<ZPackage>("KeenCombat_AnimTrigger", (Action<long, ZPackage>)OnReceiveAnimTrigger);
				ZRoutedRpc.instance.Register<ZPackage>("KeenCombat_AnimSpeed", (Action<long, ZPackage>)OnReceiveAnimSpeed);
				ZRoutedRpc.instance.Register<ZPackage>("KeenCombat_Meteor", (Action<long, ZPackage>)OnReceiveMeteor);
				ZRoutedRpc.instance.Register<ZPackage>("KeenCombat_IceFreeze", (Action<long, ZPackage>)OnReceiveIceFreeze);
				ZRoutedRpc.instance.Register<ZPackage>("KeenCombat_VfxAttached", (Action<long, ZPackage>)OnReceiveVfxAttached);
				ZRoutedRpc.instance.Register<ZPackage>("KeenCombat_Sanctuary", (Action<long, ZPackage>)OnReceiveSanctuary);
				ZRoutedRpc.instance.Register<ZPackage>("KeenCombat_Regeneration", (Action<long, ZPackage>)OnReceiveRegeneration);
				ZRoutedRpc.instance.Register<ZPackage>("KeenCombat_AnimPlay", (Action<long, ZPackage>)OnReceiveAnimPlay);
				ZRoutedRpc.instance.Register<ZPackage>("KeenCombat_Tracer", (Action<long, ZPackage>)OnReceiveTracer);
				_registeredOn = ZRoutedRpc.instance;
				KC_Log.Debug("NetworkedEffects: RPCs registered.");
			}
		}

		public static void BroadcastVfxSfx(string vfxName, string sfxName, Vector3 pos, Quaternion rot, float scale = 1f)
		{
			//IL_002b: 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)
			if (ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "KeenCombat_VfxSfx", new object[5] { vfxName, sfxName, pos, rot, scale });
			}
		}

		public static void BroadcastVfxSilent(string vfxName, Vector3 pos, Quaternion rot, float scale = 1f)
		{
			//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)
			BroadcastVfxSfx(vfxName, "", pos, rot, scale);
		}

		public static void BroadcastVfx(string vfxName, Vector3 pos, Quaternion rot, float scale = 1f)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "KeenCombat_Vfx", new object[4] { vfxName, pos, rot, scale });
			}
		}

		public static void BroadcastVfxOnCharacter(Character character, string vfxName, bool suppressAudio = false, float scale = 1f, string tintHex = "", float heightOffset = 0f)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (ZRoutedRpc.instance != null && !((Object)(object)character == (Object)null))
			{
				ZPackage val = new ZPackage();
				val.Write(character.GetZDOID());
				val.Write(vfxName);
				val.Write(suppressAudio);
				val.Write(scale);
				val.Write(tintHex ?? "");
				val.Write(heightOffset);
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "KeenCombat_VfxAttached", new object[1] { val });
			}
		}

		public static void BroadcastSanctuary(ZDOID caster, Vector3 center, float radius, float duration, float slow)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0016: 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)
			if (ZRoutedRpc.instance != null)
			{
				ZPackage val = new ZPackage();
				val.Write(caster);
				val.Write(center);
				val.Write(radius);
				val.Write(duration);
				val.Write(slow);
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "KeenCombat_Sanctuary", new object[1] { val });
			}
		}

		public static void BroadcastRegeneration(ZDOID target, float healPercent, float duration)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if (ZRoutedRpc.instance != null)
			{
				ZPackage val = new ZPackage();
				val.Write(target);
				val.Write(healPercent);
				val.Write(duration);
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "KeenCombat_Regeneration", new object[1] { val });
			}
		}

		public static void BroadcastTracer(string vfxName, Vector3 from, Vector3 to, float speed)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if (ZRoutedRpc.instance != null)
			{
				ZPackage val = new ZPackage();
				val.Write(vfxName);
				val.Write(from);
				val.Write(to);
				val.Write(speed);
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "KeenCombat_Tracer", new object[1] { val });
			}
		}

		public static void BroadcastSfx(string sfxName, Vector3 pos, Quaternion rot)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "KeenCombat_Sfx", new object[3] { sfxName, pos, rot });
			}
		}

		public static void BroadcastOgg(string filename, Vector3 pos)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "KeenCombat_Ogg", new object[2] { filename, pos });
			}
		}

		public static void BroadcastAnimationTrigger(Player player, string triggerName)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (ZRoutedRpc.instance != null)
			{
				ZPackage val = new ZPackage();
				val.Write(((Character)player).GetZDOID());
				val.Write(triggerName);
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "KeenCombat_AnimTrigger", new object[1] { val });
			}
		}

		public static void BroadcastAnimationPlay(Character character, string stateName, int layer = 0, float normalizedTime = 0f)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (ZRoutedRpc.instance != null && !((Object)(object)character == (Object)null))
			{
				ZPackage val = new ZPackage();
				val.Write(character.GetZDOID());
				val.Write(stateName);
				val.Write(layer);
				val.Write(normalizedTime);
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "KeenCombat_AnimPlay", new object[1] { val });
			}
		}

		public static void BroadcastAnimatorSpeed(Player player, float speed)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (ZRoutedRpc.instance != null)
			{
				ZPackage val = new ZPackage();
				val.Write(((Character)player).GetZDOID());
				val.Write(speed);
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "KeenCombat_AnimSpeed", new object[1] { val });
			}
		}

		public static void BroadcastMeteor(Vector3 spawnPos, Vector3 targetPos, float damage, float damageRadius, ZDOID attackerZdoid)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if (ZRoutedRpc.instance != null)
			{
				ZPackage val = new ZPackage();
				val.Write(spawnPos);
				val.Write(targetPos);
				val.Write(damage);
				val.Write(damageRadius);
				val.Write(attackerZdoid);
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "KeenCombat_Meteor", new object[1] { val });
			}
		}

		public static void BroadcastIceFreeze(ZDOID characterZdoid, Vector3 pos, float freezeDuration, float slowDuration)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0016: 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)
			if (ZRoutedRpc.instance != null)
			{
				ZPackage val = new ZPackage();
				val.Write(characterZdoid);
				val.Write(pos);
				val.Write(freezeDuration);
				val.Write(slowDuration);
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "KeenCombat_IceFreeze", new object[1] { val });
			}
		}

		private static void OnReceiveVfxSfx(long sender, string vfxName, string sfxName, Vector3 pos, Quaternion rot, float scale)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			SpawnVfx(vfxName, pos, rot, scale, suppressAudio: true);
			if (!string.IsNullOrEmpty(sfxName))
			{
				SpawnSfx(sfxName, pos, rot);
			}
		}

		private static void OnReceiveVfx(long sender, string vfxName, Vector3 pos, Quaternion rot, float scale)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			SpawnVfx(vfxName, pos, rot, scale);
		}

		private static void OnReceiveRegeneration(long sender, ZPackage pkg)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			ZDOID id = pkg.ReadZDOID();
			float healPercent = pkg.ReadSingle();
			float duration = pkg.ReadSingle();
			Character val = FindCharacterByZDOID(id);
			if (!((Object)(object)val == (Object)null))
			{
				ZNetView component = ((Component)val).GetComponent<ZNetView>();
				if (!((Object)(object)component == (Object)null) && component.IsOwner())
				{
					SE_RegenerationBuff.Apply(val, healPercent, duration);
				}
			}
		}

		private static void OnReceiveSanctuary(long sender, ZPackage pkg)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			ZDOID caster = pkg.ReadZDOID();
			Vector3 center = pkg.ReadVector3();
			float radius = pkg.ReadSingle();
			float duration = pkg.ReadSingle();
			float slow = pkg.ReadSingle();
			SanctuaryDome.Begin(caster, center, radius, duration, slow);
		}

		private static void OnReceiveVfxAttached(long sender, ZPackage pkg)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			ZDOID id = pkg.ReadZDOID();
			string vfxName = pkg.ReadString();
			bool suppressAudio = pkg.ReadBool();
			float scale = pkg.ReadSingle();
			string text = pkg.ReadString();
			float num = pkg.ReadSingle();
			Character val = FindCharacterByZDOID(id);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			GameObject val2 = SpawnVfx(vfxName, ((Component)val).transform.position + Vector3.up * num, ((Component)val).transform.rotation, scale, suppressAudio);
			if (!((Object)(object)val2 == (Object)null))
			{
				val2.transform.SetParent(((Component)val).transform, true);
				Color tint = default(Color);
				if (!string.IsNullOrEmpty(text) && ColorUtility.TryParseHtmlString(text, ref tint))
				{
					TintVfx(val2, tint);
				}
			}
		}

		public static void TintVfx(GameObject go, Color tint)
		{
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				Material[] materials = val.materials;
				foreach (Material val2 in materials)
				{
					string[] array = new string[3] { "_Color", "_TintColor", "_BaseColor" };
					foreach (string text in array)
					{
						if (val2.HasProperty(text))
						{
							Color color = val2.GetColor(text);
							val2.SetColor(text, new Color(tint.r, tint.g, tint.b, color.a));
						}
					}
					if (val2.HasProperty("_EmissionColor"))
					{
						Color color2 = val2.GetColor("_EmissionColor");
						float num = Mathf.Max(new float[3] { color2.r, color2.g, color2.b });
						if (num > 0f)
						{
							val2.SetColor("_EmissionColor", new Color(tint.r * num, tint.g * num, tint.b * num, color2.a));
						}
					}
				}
			}
			ParticleSystem[] componentsInChildren2 = go.GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem val3 in componentsInChildren2)
			{
				MainModule main = val3.main;
				MinMaxGradient startColor = ((MainModule)(ref main)).startColor;
				Color color3 = ((MinMaxGradient)(ref startColor)).color;
				((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(tint.r, tint.g, tint.b, color3.a));
			}
		}

		private static void OnReceiveSfx(long sender, string sfxName, Vector3 pos, Quaternion rot)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			SpawnSfx(sfxName, pos, rot);
		}

		private static void OnReceiveOgg(long sender, string filename, Vector3 pos)
		{
			//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)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (_oggCache.TryGetValue(filename, out AudioClip value) && (Object)(object)value != (Object)null)
			{
				PlayOggAt(value, filename, pos);
				return;
			}
			((MonoBehaviour)Plugin.instance).StartCoroutine(Plugin.LoadAudioClip(filename, delegate(AudioClip? clip)
			{
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)clip == (Object)null))
				{
					_oggCache[filename] = clip;
					PlayOggAt(clip, filename, pos);
				}
			}));
		}

		private static void PlayOggAt(AudioClip clip, string filename, Vector3 pos)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("KC_Audio_" + filename);
			val.transform.position = pos;
			AudioSource val2 = val.AddComponent<AudioSource>();
			val2.spatialBlend = 1f;
			val2.maxDistance = 40f;
			val2.rolloffMode = (AudioRolloffMode)1;
			val2.PlayOneShot(clip);
			Object.Destroy((Object)(object)val, clip.length + 0.5f);
		}

		private static void OnReceiveAnimTrigger(long sender, ZPackage pkg)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			ZDOID id = pkg.ReadZDOID();
			string trigger = pkg.ReadString();
			Character val = FindCharacterByZDOID(id);
			if (!((Object)(object)val == (Object)null))
			{
				Animator componentInChildren = ((Component)val).GetComponentInChildren<Animator>();
				if (componentInChildren != null)
				{
					componentInChildren.SetTrigger(trigger);
				}
			}
		}

		private static void OnReceiveAnimPlay(long sender, ZPackage pkg)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			ZDOID id = pkg.ReadZDOID();
			string text = pkg.ReadString();
			int num = pkg.ReadInt();
			float num2 = pkg.ReadSingle();
			Character val = FindCharacterByZDOID(id);
			if (!((Object)(object)val == (Object)null))
			{
				Animator componentInChildren = ((Component)val).GetComponentInChildren<Animator>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.Play(text, num, num2);
				}
			}
		}

		private static void OnReceiveTracer(long sender, ZPackage pkg)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			string vfxName = pkg.ReadString();
			Vector3 val = pkg.ReadVector3();
			Vector3 to = pkg.ReadVector3();
			float speed = pkg.ReadSingle();
			((MonoBehaviour)Plugin.instance).StartCoroutine(TracerRoutine(vfxName, val, to, speed));
		}

		private static IEnumerator TracerRoutine(string vfxName, Vector3 from, Vector3 to, float speed)
		{
			//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)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			ZNetScene instance = ZNetScene.instance;
			GameObject prefab = ((instance != null) ? instance.GetPrefab(vfxName) : null);
			if ((Object)(object)prefab == (Object)null)
			{
				KC_Log.Warn("NetworkedEffects: tracer VFX '" + vfxName + "' not found!");
				yield break;
			}
			Vector3 dir = to - from;
			float distance = ((Vector3)(ref dir)).magnitude;
			if (distance < 0.01f)
			{
				yield break;
			}
			GameObject go = SpawnLocal(prefab, from, Quaternion.LookRotation(dir));
			float duration = distance / Mathf.Max(1f, speed);
			float elapsed = 0f;
			while (elapsed < duration)
			{
				if ((Object)(object)go == (Object)null)
				{
					yield break;
				}
				go.transform.position = Vector3.Lerp(from, to, elapsed / duration);
				elapsed += Time.deltaTime;
				yield return null;
			}
			if ((Object)(object)go != (Object)null)
			{
				Object.Destroy((Object)(object)go);
			}
		}

		private static void OnReceiveAnimSpeed(long sender, ZPackage pkg)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			ZDOID id = pkg.ReadZDOID();
			float speed = pkg.ReadSingle();
			Character val = FindCharacterByZDOID(id);
			if (!((Object)(object)val == (Object)null))
			{
				Animator componentInChildren = ((Component)val).GetComponentInChildren<Animator>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.speed = speed;
				}
			}
		}

		private static void OnReceiveMeteor(long sender, ZPackage pkg)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			Vector3 spawnPos = pkg.ReadVector3();
			Vector3 targetPos = pkg.ReadVector3();
			float damage = pkg.ReadSingle();
			float damageRadius = pkg.ReadSingle();
			ZDOID attackerZdoid = pkg.ReadZDOID();
			bool applyDamage = sender == ZNet.GetUID();
			((MonoBehaviour)Plugin.instance).StartCoroutine(MeteorFallRoutine(spawnPos, targetPos, damage, damageRadius, attackerZdoid, applyDamage));
		}

		private static void OnReceiveIceFreeze(long sender, ZPackage pkg)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			ZDOID val = pkg.ReadZDOID();
			Vector3 pos = pkg.ReadVector3();
			float freezeDuration = pkg.ReadSingle();
			float slowDuration = pkg.ReadSingle();
			((MonoBehaviour)Plugin.instance).StartCoroutine(IceBlockerRoutine(val, pos, freezeDuration));
			Character val2 = FindCharacterByZDOID(val);
			ZNetView val3 = ((val2 != null) ? ((Component)val2).GetComponent<ZNetView>() : null);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null && val3.IsOwner())
			{
				((MonoBehaviour)Plugin.instance).StartCoroutine(StaffIceShardsSkill.FreezeEnemy(val2, freezeDuration, slowDuration));
			}
		}

		private static IEnumerator IceBlockerRoutine(ZDOID characterZdoid, Vector3 pos, float freezeDuration)
		{
			//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)
			//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)
			ZNetScene instance = ZNetScene.instance;
			GameObject iceBlockerPrefab = ((instance != null) ? instance.GetPrefab("IceBlocker") : null);
			if ((Object)(object)iceBlockerPrefab == (Object)null)
			{
				KC_Log.Warn("NetworkedEffects: IceBlocker prefab not found!");
				yield break;
			}
			GameObject iceBlock = SpawnLocal(iceBlockerPrefab, pos, Quaternion.identity);
			if (!((Object)(object)iceBlock == (Object)null))
			{
				iceBlock.transform.localScale = Vector3.one * 0.7f;
				yield return (object)new WaitForSeconds(freezeDuration);
				Character character = FindCharacterByZDOID(characterZdoid);
				Vector3 shatterPos = (((Object)(object)character != (Object)null) ? ((Component)character).transform.position : pos);
				if ((Object)(object)iceBlock != (Object)null)
				{
					Object.Destroy((Object)(object)iceBlock);
				}
				ZNetScene instance2 = ZNetScene.instance;
				GameObject shatterPrefab = ((instance2 != null) ? instance2.GetPrefab("fx_DvergerMage_Ice_hit") : null);
				if ((Object)(object)shatterPrefab != (Object)null)
				{
					SpawnLocal(shatterPrefab, shatterPos, Quaternion.identity);
				}
			}
		}

		private static IEnumerator MeteorFallRoutine(Vector3 spawnPos, Vector3 targetPos, float damage, float damageRadius, ZDOID attackerZdoid, bool applyDamage)
		{
			//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)
			//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)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			ZNetScene instance = ZNetScene.instance;
			GameObject meteorPrefab = ((instance != null) ? instance.GetPrefab("projectile_meteor") : null);
			if ((Object)(object)meteorPrefab == (Object)null)
			{
				KC_Log.Warn("NetworkedEffects: projectile_meteor not found!");
				yield break;
			}
			Vector3 val = targetPos - spawnPos;
			Vector3 fallDir = ((Vector3)(ref val)).normalized;
			float fallDistance = Vector3.Distance(spawnPos, targetPos);
			float fallSpeed = 30f;
			float fallDuration = fallDistance / fallSpeed;
			GameObject meteor = SpawnLocal(meteorPrefab, spawnPos, Quaternion.LookRotation(fallDir));
			float elapsed = 0f;
			while (elapsed < fallDuration)
			{
				if ((Object)(object)meteor == (Object)null)
				{
					yield break;
				}
				meteor.transform.position = Vector3.Lerp(spawnPos, targetPos, elapsed / fallDuration);
				elapsed += Time.deltaTime;
				yield return null;
			}
			if ((Object)(object)meteor != (Object)null)
			{
				Object.Destroy((Object)(object)meteor);
			}
			ZNetScene instance2 = ZNetScene.instance;
			GameObject hitPrefab = ((instance2 != null) ? instance2.GetPrefab("fx_goblinking_meteor_hit") : null);
			if ((Object)(object)hitPrefab != (Object)null)
			{
				GameObject hitVfx = SpawnLocal(hitPrefab, targetPos, Quaternion.identity);
				if ((Object)(object)hitVfx == (Object)null)
				{
					yield break;
				}
			}
			if (!applyDamage)
			{
				yield break;
			}
			Character attacker = FindCharacterByZDOID(attackerZdoid);
			Collider[] cols = Physics.OverlapSphere(targetPos, damageRadius, SkillMasks.Characters);
			HashSet<Character> alreadyHit = new HashSet<Character>();
			Collider[] array = cols;
			foreach (Collider col in array)
			{
				Character character = ((Component)col).GetComponentInParent<Character>();
				if ((Object)(object)character == (Object)null || !alreadyHit.Add(character) || (Object)(object)character == (Object)(object)attacker)
				{
					continue;
				}
				int num;
				if (character.IsPlayer())
				{
					Player p = (Player)(object)((attacker is Player) ? attacker : null);
					if (p != null)
					{
						num = ((!((Character)p).IsPVPEnabled()) ? 1 : 0);
						goto IL_02f5;
					}
				}
				num = 0;
				goto IL_02f5;
				IL_02f5:
				if (num == 0 && (int)character.m_faction != 0)
				{
					HitData hit = new HitData();
					hit.m_damage.m_fire = damage;
					hit.m_pushForce = 5f;
					hit.m_staggerMultiplier = 2f;
					hit.m_point = ((Component)character).transform.position;
					hit.m_dir = Vector3.down;
					hit.m_attacker = attackerZdoid;
					character.Damage(hit);
				}
			}
		}

		private static Character? FindCharacterByZDOID(ZDOID id)
		{
			//IL_0035: 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)
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				ZNetView component = ((Component)allCharacter).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null)
				{
					ZDO zDO = component.GetZDO();
					if (zDO != null && zDO.m_uid == id)
					{
						return allCharacter;
					}
				}
			}
			return null;
		}

		private static GameObject? SpawnVfx(string vfxName, Vector3 pos, Quaternion rot, float scale, bool suppressAudio = false)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.GetPrefab(vfxName) : null);
			if ((Object)(object)val == (Object)null)
			{
				KC_Log.Warn("NetworkedEffects: VFX '" + vfxName + "' not found!");
				return null;
			}
			GameObject val2 = SpawnLocal(val, pos, rot);
			if (scale != 1f)
			{
				ParticleSystem[] componentsInChildren = val2.GetComponentsInChildren<ParticleSystem>();
				foreach (ParticleSystem val3 in componentsInChildren)
				{
					ShapeModule shape = val3.shape;
					((ShapeModule)(ref shape)).radius = ((ShapeModule)(ref shape)).radius * scale;
					MainModule main = val3.main;
					MinMaxCurve startSize = ((MainModule)(ref main)).startSize;
					float num = ((MinMaxCurve)(ref startSize)).constantMin * scale;
					startSize = ((MainModule)(ref main)).startSize;
					((MainModule)(ref main)).startSize = new MinMaxCurve(num, ((MinMaxCurve)(ref startSize)).constantMax * scale);
				}
			}
			if (suppressAudio)
			{
				ZSFX[] componentsInChildren2 = val2.GetComponentsInChildren<ZSFX>();
				foreach (ZSFX val4 in componentsInChildren2)
				{
					Object.Destroy((Object)(object)val4);
				}
				AudioSource[] componentsInChildren3 = val2.GetComponentsInChildren<AudioSource>();
				foreach (AudioSource val5 in componentsInChildren3)
				{
					val5.Stop();
					val5.mute = true;
				}
			}
			Aoe[] componentsInChildren4 = val2.GetComponentsInChildren<Aoe>();
			foreach (Aoe val6 in componentsInChildren4)
			{
				Object.Destroy((Object)(object)val6);
			}
			return val2;
		}

		public static GameObject SpawnLocal(GameObject prefab, Vector3 pos, Quaternion rot)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			bool activeSelf = prefab.activeSelf;
			prefab.SetActive(false);
			GameObject val = Object.Instantiate<GameObject>(prefab, pos, rot);
			prefab.SetActive(activeSelf);
			ZSyncTransform[] componentsInChildren = val.GetComponentsInChildren<ZSyncTransform>(true);
			foreach (ZSyncTransform val2 in componentsInChildren)
			{
				Object.DestroyImmediate((Object)(object)val2);
			}
			ZSyncAnimation[] componentsInChildren2 = val.GetComponentsInChildren<ZSyncAnimation>(true);
			foreach (ZSyncAnimation val3 in componentsInChildren2)
			{
				Object.DestroyImmediate((Object)(object)val3);
			}
			Projectile[] componentsInChildren3 = val.GetComponentsInChildren<Projectile>(true);
			foreach (Projectile val4 in componentsInChildren3)
			{
				Object.DestroyImmediate((Object)(object)val4);
			}
			Aoe[] componentsInChildren4 = val.GetComponentsInChildren<Aoe>(true);
			foreach (Aoe val5 in componentsInChildren4)
			{
				Object.DestroyImmediate((Object)(object)val5);
			}
			CinderSpawner[] componentsInChildren5 = val.GetComponentsInChildren<CinderSpawner>(true);
			foreach (CinderSpawner val6 in componentsInChildren5)
			{
				Object.DestroyImmediate((Object)(object)val6);
			}
			ZNetView[] componentsInChildren6 = val.GetComponentsInChildren<ZNetView>(true);
			foreach (ZNetView val7 in componentsInChildren6)
			{
				Object.DestroyImmediate((Object)(object)val7);
			}
			Collider[] componentsInChildren7 = val.GetComponentsInChildren<Collider>(true);
			foreach (Collider val8 in componentsInChildren7)
			{
				Object.DestroyImmediate((Object)(object)val8);
			}
			Rigidbody[] componentsInChildren8 = val.GetComponentsInChildren<Rigidbody>(true);
			foreach (Rigidbody val9 in componentsInChildren8)
			{
				Object.DestroyImmediate((Object)(object)val9);
			}
			val.SetActive(true);
			return val;
		}

		private static void SpawnSfx(string sfxName, Vector3 pos, Quaternion rot)
		{
			//IL_0039: 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)
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.GetPrefab(sfxName) : null);
			if ((Object)(object)val == (Object)null)
			{
				KC_Log.Warn("NetworkedEffects: SFX '" + sfxName + "' not found!");
			}
			else
			{
				SpawnLocal(val, pos, rot);
			}
		}
	}
	public enum KeyboardHeavyAttackMode
	{
		HoldAttack,
		Vanilla
	}
	[BepInPlugin("Bhimas.KeenCombat", "KeenCombat", "1.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		private sealed class ConfigurationManagerAttributes
		{
			public bool? Browsable;
		}

		public const string PluginGUID = "Bhimas.KeenCombat";

		public const string PluginName = "KeenCombat";

		public const string PluginVersion = "1.1.0";

		internal static ManualLogSource Log;

		internal static Plugin instance;

		internal static ConfigEntry<bool> AutoShieldEnabled;

		internal static ConfigEntry<bool> ExcludeAxe;

		internal static ConfigEntry<bool> ExcludeKnife;

		internal static ConfigEntry<float> HoldThreshold;

		internal static ConfigEntry<KeyCode> SkillKey;

		internal static ConfigEntry<KeyboardShortcut> SkillKeybind;

		internal static ConfigEntry<KeyboardHeavyAttackMode> KeyboardHeavyMode;

		internal static ConfigEntry<float> HoldAxe;

		internal static ConfigEntry<float> HoldMace;

		internal static ConfigEntry<float> HoldSword;

		internal static ConfigEntry<float> HoldSpear;

		internal static ConfigEntry<float> HoldAtgeir;

		internal static ConfigEntry<float> HoldTwoHandedMace;

		internal static ConfigEntry<float> HoldKnife;

		internal static ConfigEntry<float> HoldGreatsword;

		internal static ConfigEntry<float> SkillWidgetX;

		internal static ConfigEntry<float> SkillWidgetY;

		internal static ConfigEntry<float> SwordSkillCooldown;

		internal static ConfigEntry<float> SwordSkillDamage;

		internal static ConfigEntry<float> SwordBlinkDistance;

		internal static ConfigEntry<float> SwordAnimSpeed;

		internal static ConfigEntry<string> SwordAnimName;

		internal static ConfigEntry<float> SwordHitRadius;

		internal static ConfigEntry<float> SwordHitExtendFront;

		internal static ConfigEntry<float> SwordHitExtendBack;

		internal static ConfigEntry<float> SwordHitHeightTop;

		internal static ConfigEntry<float> SwordHitHeightBottom;

		internal static ConfigEntry<float> MaceSkillCooldown;

		internal static ConfigEntry<float> MaceBuffDuration;

		internal static ConfigEntry<float> MaceDamageReduction;

		internal static ConfigEntry<float> MaceRegenPerSec;

		internal static ConfigEntry<float> AxeSkillCooldown;

		internal static ConfigEntry<float> AxeBuffDuration;

		internal static ConfigEntry<float> AxeAttackSpeedBonus;

		internal static ConfigEntry<float> AxeMoveSpeedBonus;

		internal static ConfigEntry<float> AtgeirSkillCooldown;

		internal static ConfigEntry<float> AtgeirSkillDamage;

		internal static ConfigEntry<float> CrossbowSkillCooldown;

		internal static ConfigEntry<float> CrossbowSkillDamage;

		internal static ConfigEntry<string> CrossbowProjectileVfx;

		internal static ConfigEntry<float> CrossbowProjectileSpeed;

		internal static ConfigEntry<float> KnifeSkillCooldown;

		internal static ConfigEntry<float> KnifeSkillDamage;

		internal static ConfigEntry<float> KnifeStealthDuration;

		internal static ConfigEntry<float> GreatswordSkillCooldown;

		internal static ConfigEntry<float> GreatswordSkillDamage;

		internal static ConfigEntry<float> GreatswordAnimSpeed;

		internal static ConfigEntry<float> GreatswordStartSpeed;

		internal static ConfigEntry<float> GreatswordHoldDuration;

		internal static ConfigEntry<float> GreatswordSecondSpin;

		internal static ConfigEntry<float> GreatswordMoveDistance;

		internal static ConfigEntry<float> BowSkillCooldown;

		internal static ConfigEntry<float> BowSummonDuration;

		internal static ConfigEntry<string> BowCreatureMap;

		internal static ConfigEntry<string> CreatureScaleMap;

		internal static ConfigEntry<float> DualKnifeSkillCooldown;

		internal static ConfigEntry<float> DualKnifeSkillDamage;

		internal static ConfigEntry<float> DualKnifeLeapBack;

		internal static ConfigEntry<float> DualKnifeLeapUp;

		internal static ConfigEntry<int> DualKnifeNumBombs;

		internal static ConfigEntry<float> DualKnifeSpread;

		internal static ConfigEntry<float> FistSkillCooldown;

		internal static ConfigEntry<float> FistSkillDamage;

		internal static ConfigEntry<float> TwoHandedMaceSkillCooldown;

		internal static ConfigEntry<float> TwoHandedMaceSkillDamage;

		internal static ConfigEntry<string> TwoHandedMaceSwingOgg;

		internal static ConfigEntry<float> StaffFireballEitrCost;

		internal static ConfigEntry<float> StaffFireballDamageMultiplier;

		internal static ConfigEntry<float> StaffFireballDamageRadius;

		internal static ConfigEntry<float> StaffFireballRadius;

		internal static ConfigEntry<float> StaffFireballDuration;

		internal static ConfigEntry<float> StaffFireballIntervalMin;

		internal static ConfigEntry<float> StaffFireballIntervalMax;

		internal static ConfigEntry<float> StaffIceShardsEitrCost;

		internal static ConfigEntry<float> StaffIceShardsDamageMultiplier;

		internal static ConfigEntry<float> StaffIceShardsRadius;

		internal static ConfigEntry<float> StaffIceShardsDuration;

		internal static ConfigEntry<float> StaffIceShardsSlowDuration;

		internal static ConfigEntry<float> StaffClusterbombMinEitr;

		internal static ConfigEntry<float> StaffClusterbombMaxEitr;

		internal static ConfigEntry<float> StaffClusterbombMaxChargeTime;

		internal static ConfigEntry<float> StaffClusterbombMinDamageMult;

		internal static ConfigEntry<float> StaffClusterbombMaxDamageMult;

		internal static ConfigEntry<float> StaffGreenRootsEitrCost;

		internal static ConfigEntry<float> StaffGreenRootsHealPercent;

		internal static ConfigEntry<float> StaffGreenRootsDuration;

		internal static ConfigEntry<float> StaffGreenRootsRadius;

		internal static ConfigEntry<float> StaffThunderbloodEitrCost;

		internal static ConfigEntry<float> StaffThunderbloodDamagePercent;

		internal static ConfigEntry<float> StaffThunderbloodRadius;

		internal static ConfigEntry<float> StaffThunderbloodIntervalMin;

		internal static ConfigEntry<float> StaffThunderbloodIntervalMax;

		internal static ConfigEntry<float> StaffThunderbloodDuration;

		internal static ConfigEntry<string> StaffThunderbloodCastVfx;

		internal static ConfigEntry<string> StaffThunderbloodCastSfx;

		internal static ConfigEntry<string> StaffThunderbloodStrikeVfx;

		internal static ConfigEntry<string> StaffThunderbloodStrikeSfx;

		internal static ConfigEntry<float> StaffThunderbloodStrikeHeight;

		internal static ConfigEntry<float> StaffShieldEitrCost;

		internal static ConfigEntry<float> StaffShieldHealthPercent;

		internal static ConfigEntry<float> StaffShieldRadius;

		internal static ConfigEntry<float> StaffShieldDuration;

		internal static ConfigEntry<float> StaffShieldSlowPercent;

		internal static ConfigEntry<string> StaffShieldCastVfx;

		internal static ConfigEntry<string> StaffShieldCastSfx;

		internal static ConfigEntry<string> StaffShieldDomeVfx;

		internal static ConfigEntry<string> StaffShieldDomeColor;

		internal static ConfigEntry<float> StaffShieldDomeHeightOffset;

		internal static ConfigEntry<float> StaffShieldDomeInsideBoost;

		internal static ConfigEntry<float> StaffShieldCastVfxHeight;

		internal static ConfigEntry<float> StaffShieldBubbleDelay;

		internal static ConfigEntry<float> StaffShieldDomeFadeTime;

		internal static ConfigEntry<bool> MagicCostScalingEnabled;

		internal static ConfigEntry<float> MagicCostPenaltyPerStep;

		internal static ConfigEntry<float> MagicCostLevelsPerStep;

		internal static ConfigEntry<string> StaffSkeletonLevelTiers;

		internal static ConfigEntry<float> StaffSkeletonDuration;

		internal static ConfigEntry<string> StaffSkeletonPrefab;

		internal static ConfigEntry<bool> TestMode;

		internal static ConfigEntry<float> GlobalAttackSpeed;

		internal static InputAction? RightTriggerAction;

		private Harmony _harmony = null;

		internal static Harmony? HarmonyInstance;

		private void Awake()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"KeenCombat v1.1.0 loading...");
			BindConfig();
			RightTriggerAction = new InputAction("RightTrigger", (InputActionType)0, "<Gamepad>/rightTrigger", (string)null, (string)null, (string)null);
			RightTriggerAction.Enable();
			_harmony = new Harmony("Bhimas.KeenCombat");
			_harmony.PatchAll();
			HarmonyInstance = _harmony;
			((MonoBehaviour)this).StartCoroutine(PatchGuard.Loop());
			Log.LogInfo((object)"KeenCombat loaded successfully.");
		}

		private void BindConfig()
		{
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Expected O, but got Unknown
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Expected O, but got Unknown
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Expected O, but got Unknown
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Expected O, but got Unknown
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Expected O, but got Unknown
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Expected O, but got Unknown
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b1: Expected O, but got Unknown
			//IL_03db: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e5: Expected O, but got Unknown
			//IL_040f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0419: Expected O, but got Unknown
			//IL_06ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f9: Expected O, but got Unknown
			//IL_0723: Unknown result type (might be due to invalid IL or missing references)
			//IL_072d: Expected O, but got Unknown
			//IL_0757: Unknown result type (might be due to invalid IL or missing references)
			//IL_0761: Expected O, but got Unknown
			//IL_078b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0795: Expected O, but got Unknown
			//IL_07bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c9: Expected O, but got Unknown
			//IL_08cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_08d5: Expected O, but got Unknown
			//IL_08ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0909: Expected O, but got Unknown
			//IL_092f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0939: Expected O, but got Unknown
			//IL_0963: Unknown result type (might be due to invalid IL or missing references)
			//IL_096d: Expected O, but got Unknown
			//IL_1193: Unknown result type (might be due to invalid IL or missing references)
			//IL_119d: Expected O, but got Unknown
			//IL_11eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_11f5: Expected O, but got Unknown
			//IL_121f: Unknown result type (might be due to invalid IL or missing references)
			//IL_1229: Expected O, but got Unknown
			ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes
			{
				Browsable = false
			};
			AutoShieldEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Shield", "AutoEquipShield", true, "Automatically equip the best shield when equipping a one-handed weapon.");
			ExcludeAxe = ((BaseUnityPlugin)this).Config.Bind<bool>("Shield", "ExcludeAxe", true, "Don't auto-equip a shield when equipping an axe.");
			ExcludeKnife = ((BaseUnityPlugin)this).Config.Bind<bool>("Shield", "ExcludeKnife", true, "Don't auto-equip a shield when equipping a knife or dual knife.");
			HoldThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("Hold To Heavy Timing", "Default", 0.25f, "Seconds to hold Attack before a heavy attack, for weapons without their own setting below (e.g. fist weapons). Applies to controller, and to mouse & keyboard when KeyboardHeavyAttack = HoldAttack.");
			HoldAxe = ((BaseUnityPlugin)this).Config.Bind<float>("Hold To Heavy Timing", "Axe", 0.2f, "Hold time for axes and dual axes.");
			HoldMace = ((BaseUnityPlugin)this).Config.Bind<float>("Hold To Heavy Timing", "Mace", 0.2f, "Hold time for one-handed maces.");
			HoldSword = ((BaseUnityPlugin)this).Config.Bind<float>("Hold To Heavy Timing", "Sword", 0.2f, "Hold time for one-handed swords.");
			HoldSpear = ((BaseUnityPlugin)this).Config.Bind<float>("Hold To Heavy Timing", "Spear", 0.15f, "Hold time for spears.");
			HoldAtgeir = ((BaseUnityPlugin)this).Config.Bind<float>("Hold To Heavy Timing", "Atgeir", 0.15f, "Hold time for atgeirs.");
			HoldTwoHandedMace = ((BaseUnityPlugin)this).Config.Bind<float>("Hold To Heavy Timing", "TwoHandedMace", 0.15f, "Hold time for two-handed maces and sledges.");
			HoldKnife = ((BaseUnityPlugin)this).Config.Bind<float>("Hold To Heavy Timing", "Knife", 0.15f, "Hold time for knives and dual knives.");
			HoldGreatsword = ((BaseUnityPlugin)this).Config.Bind<float>("Hold To Heavy Timing", "Greatsword", 0.2f, "Hold time for two-handed swords and two-handed axes.");
			SkillKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Input", "SkillKey", (KeyCode)325, new ConfigDescription("Legacy setting — replaced by SkillKeybind.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			SkillKeybind = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Input", "SkillKeybind", new KeyboardShortcut((KeyCode)122, Array.Empty<KeyCode>()), "Mouse & keyboard key for the equipped weapon's KeenCombat skill. Controller always uses Right Trigger.");
			KeyboardHeavyMode = ((BaseUnityPlugin)this).Config.Bind<KeyboardHeavyAttackMode>("Input", "KeyboardHeavyAttack", KeyboardHeavyAttackMode.Vanilla, "How mouse & keyboard players heavy attack. HoldAttack = hold the attack button. Vanilla = Valheim's own heavy attack button (middle mouse by default). Controller always uses hold-to-heavy.");
			SwordSkillCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Sword Blink Strike", "Cooldown", 15f, "Cooldown in seconds for Sword Blink Strike.");
			SwordSkillDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Sword Blink Strike", "DamageMultiplier", 1.1f, "Damage multiplier (1.0 = weapon base damage).");
			SwordBlinkDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Sword Blink Strike", "BlinkDistance", 8f, new ConfigDescription("Maximum blink distance in meters.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			SwordAnimSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Sword Blink Strike", "AnimationSpeed", 1.2f, new ConfigDescription("Speed multiplier for the blink animation.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			SwordAnimName = ((BaseUnityPlugin)this).Config.Bind<string>("Sword Blink Strike", "AnimationName", "battleaxe_secondary", new ConfigDescription("Animator state name for the blink animation.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			SwordHitRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Sword Blink Strike", "HitboxRadius", 2.5f, new ConfigDescription("Width (radius in meters) of the blink damage capsule.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			SwordHitExtendFront = ((BaseUnityPlugin)this).Config.Bind<float>("Sword Blink Strike", "HitboxExtendFront", 3f, new ConfigDescription("How far the hitbox extends past the blink end point.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			SwordHitExtendBack = ((BaseUnityPlugin)this).Config.Bind<float>("Sword Blink Strike", "HitboxExtendBack", 2f, new ConfigDescription("How far the hitbox extends behind the blink start point.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			SwordHitHeightTop = ((BaseUnityPlugin)this).Config.Bind<float>("Sword Blink Strike", "HitboxHeightTop", 4.2f, new ConfigDescription("Height of the hitbox above the end position.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			SwordHitHeightBottom = ((BaseUnityPlugin)this).Config.Bind<float>("Sword Blink Strike", "HitboxHeightBottom", 2f, new ConfigDescription("How far below ground the hitbox extends.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			MaceSkillCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Mace Bulwark", "Cooldown", 30f, "Cooldown in seconds for Bulwark.");
			MaceBuffDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Mace Bulwark", "BuffDuration", 10f, "Duration of the Mace Bulwark buff in seconds.");
			MaceDamageReduction = ((BaseUnityPlugin)this).Config.Bind<float>("Mace Bulwark", "DamageReduction", 0.2f, "Damage reduction while Bulwark is active (0.20 = 20% less damage taken).");
			MaceRegenPerSec = ((BaseUnityPlugin)this).Config.Bind<float>("Mace Bulwark", "RegenPerSec", 5f, "HP regeneration per second granted by Bulwark.");
			AxeSkillCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Axe Frenzy", "Cooldown", 25f, "Cooldown in seconds for Frenzy.");
			AxeBuffDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Axe Frenzy", "BuffDuration", 8f, "Duration of the Axe Frenzy buff in seconds.");
			AxeAttackSpeedBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Axe Frenzy", "AttackSpeedBonus", 0.3f, "Attack speed bonus while Frenzy is active (0.30 = 30% faster attacks).");
			AxeMoveSpeedBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Axe Frenzy", "MoveSpeedBonus", 0.2f, "Move speed bonus while Frenzy is active (0.20 = 20% faster movement).");
			AtgeirSkillCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Atgeir Falcon Blitz", "Cooldown", 20f, "Cooldown in seconds for Falcon Blitz.");
			AtgeirSkillDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Atgeir Falcon Blitz", "DamageMultiplier", 0.5f, "Damage multiplier per hit (0.50 = 50% of normal attack damage).");
			CrossbowSkillCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Crossbow Rapid Fire", "Cooldown", 20f, "Cooldown in seconds for Rapid Fire.");
			CrossbowSkillDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Crossbow Rapid Fire", "DamageMultiplier", 0.3f, "Damage multiplier per shot (0.30 = 30% of normal bolt damage).");
			CrossbowProjectileVfx = ((BaseUnityPlugin)this).Config.Bind<string>("Crossbow Rapid Fire", "ProjectileVfx", "auto", "Visible projectile for each shot — damage lands when it arrives. 'auto' = the bolt you have loaded (or a default bolt if none). Enter a prefab name to use a specific projectile, or leave blank for instant hitscan.");
			CrossbowProjectileSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Crossbow Rapid Fire", "ProjectileSpeed", 80f, "Projectile travel speed in meters per second.");
			KnifeSkillCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Knife Assassination", "Cooldown", 20f, "Cooldown in seconds for Assassination.");
			KnifeSkillDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Knife Assassination", "DamageMultiplier", 2f, "Damage multiplier for the assassination strike (2.0 = 2x normal damage).");
			KnifeStealthDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Knife Assassination", "StealthDuration", 8f, "How long stealth lasts before expiring (seconds).");
			GreatswordSkillCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Greatsword Whirlwind", "Cooldown", 15f, "Cooldown in seconds for Whirlwind.");
			GreatswordSkillDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Greatsword Whirlwind", "DamageMultiplier", 0.8f, "Damage multiplier per spin hit (0.80 = 80% of normal weapon damage).");
			GreatswordStartSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Greatsword Whirlwind", "StartSpeed", 1f, new ConfigDescription("Starting animation speed for the whirlwind.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			GreatswordAnimSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Greatsword Whirlwind", "PeakAnimSpeed", 4f, new ConfigDescription("Peak animation speed for the whirlwind spin.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			GreatswordHoldDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Greatsword Whirlwind", "SpinDuration", 1.2f, new ConfigDescription("Duration of the first spin in seconds.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			GreatswordSecondSpin = ((BaseUnityPlugin)this).Config.Bind<float>("Greatsword Whirlwind", "SecondSpinDuration", 1f, new ConfigDescription("Duration of the second spin in seconds.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			GreatswordMoveDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Greatsword Whirlwind", "MoveDistance", 10f, new ConfigDescription("How far the player moves forward during Whirlwind (meters).", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			BowSkillCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Bow Primal Rally", "Cooldown", 120f, "Cooldown in seconds for Primal Rally (default 2 minutes).");
			BowSummonDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Bow Primal Rally", "SummonDuration", 60f, "How long the summoned creature lasts before despawning (seconds).");
			BowCreatureMap = ((BaseUnityPlugin)this).Config.Bind<string>("Bow Primal Rally", "BowCreatureMap", "$item_bow:Neck:2,$item_bow_finewood:Boar:2:0:0:3.0,$item_bow_huntsman:Bjorn:0,$item_bow_draugrfang:Abomination:0:0:0.5,$item_bow_snipesnap:Lox:0,$item_bow_ashlands:Morgen:0:0:0.5,$item_bow_ashlandsstorm:FallenValkyrie:0,$item_bow_ashlandsroot:Asksvin:1,$item_bow_ashlandsblood:Fenring_Cultist:2,$item_bow_gold_frostfire:StoneGolem:2,$item_bow_gold_bloodlightning:Morgen:0,$bow_trollbone_tw:Troll:0,$bow_blackmetal_tw:Lox:0,$greatbow_blackmetal_tw:Lox:1,$greatbow_dvergr_tw:Dverger:0,$greatbow_moder_tw:Hatchling:2,$blackbow_tca:SeekerBrute:1,$thoridal_tca:Gjall:2", "Comma-separated bow→creature mappings. Format: bowItemName:CreaturePrefab:starLevel[:scale[:damageMult[:hpMult]]].");
			CreatureScaleMap = ((BaseUnityPlugin)this).Config.Bind<string>("Bow Primal Rally", "CreatureScaleMap", "Troll:0.5,Bjorn:0.7,Lox:0.5,Abomination:0.4,StoneGolem:0.5,FulingBerserker:0.6,Gjall:0.4,Volture:0.6,Morgen:0.6,Barka:0.3,GammelTroll:0.5,Eikthyr:0.6,gd_king:0.4,Bonemass:0.4,Dragon:0.5,GoblinKing:0.3,SeaderQueen:0.3,Fader:0.4,FimbulBringer:0.25,FallenValkyrie:0.5", "Default scale per creature prefab name. Format: CreaturePrefab:scale.");
			DualKnifeSkillCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Dual Knife Poison Mayhem", "Cooldown", 20f, "Cooldown in seconds for Poison Mayhem.");
			DualKnifeSkillDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Dual Knife Poison Mayhem", "DamageMultiplier", 0.4f, "Damage multiplier per bomb hit.");
			DualKnifeLeapBack = ((BaseUnityPlugin)this).Config.Bind<float>("Dual Knife Poison Mayhem", "LeapBackSpeed", 4.5f, new ConfigDescription("Backward leap distance in meters.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			DualKnifeLeapUp = ((BaseUnityPlugin)this).Config.Bind<float>("Dual Knife Poison Mayhem", "LeapUpSpeed", 1.25f, new ConfigDescription("Upward leap height in meters.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			DualKnifeNumBombs = ((BaseUnityPlugin)this).Config.Bind<int>("Dual Knife Poison Mayhem", "NumBombs", 3, new ConfigDescription("Number of ooze bombs dropped.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			DualKnifeSpread = ((BaseUnityPlugin)this).Config.Bind<float>("Dual Knife Poison Mayhem", "BombSpread", 1.5f, new ConfigDescription("Spread radius of the bomb cluster in meters.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			FistSkillCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Fist Onslaught", "Cooldown", 20f, "Cooldown in seconds for Onslaught.");
			FistSkillDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Fist Onslaught", "DamageMultiplier", 1f, "Base damage multiplier. Combo hits use 50%, finisher uses 100%.");
			TwoHandedMaceSkillCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("2H Mace Earthquake", "Cooldown", 15f, "Cooldown in seconds for Earthquake.");
			TwoHandedMaceSkillDamage = ((BaseUnityPlugin)this).Config.Bind<float>("2H Mace Earthquake", "DamageMultiplier", 0.6f, "Damage multiplier per stomp explosion.");
			TwoHandedMaceSwingOgg = ((BaseUnityPlugin)this).Config.Bind<string>("2H Mace Earthquake", "SwingOgg", "2hMaceSwing.ogg", "Custom OGG played on each normal-attack swing of a two-handed mace. Leave blank (or if the file is missing) to use the greatsword swing sounds. Requires a game restart to change.");
			StaffFireballEitrCost = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of Embers Meteor Strike", "EitrCost", 50f, "Eitr cost to cast Meteor Strike.");
			StaffFireballDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of Embers Meteor Strike", "DamageMultiplier", 1f, "Multiplier applied to each meteor's fire damage.");
			StaffFireballDamageRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of Embers Meteor Strike", "DamageRadius", 12f, "Radius in meters of each meteor's damage on impact.");
			StaffFireballRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of Embers Meteor Strike", "FieldRadius", 4.5f, "Radius of the meteor strike field around the cast position.");
			StaffFireballDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of Embers Meteor Strike", "Duration", 12f, "How long the meteor field lasts in seconds.");
			StaffFireballIntervalMin = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of Embers Meteor Strike", "IntervalMin", 0.5f, "Minimum seconds between meteor impacts.");
			StaffFireballIntervalMax = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of Embers Meteor Strike", "IntervalMax", 1.25f, "Maximum seconds between meteor impacts.");
			StaffIceShardsEitrCost = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of Frost Ice Nova", "EitrCost", 30f, "Eitr cost to cast Ice Nova.");
			StaffIceShardsDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of Frost Ice Nova", "DamageMultiplier", 2f, "Multiplier applied to weapon frost damage.");
			StaffIceShardsRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of Frost Ice Nova", "Radius", 12f, "Radius of the Ice Nova AOE in meters.");
			StaffIceShardsDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of Frost Ice Nova", "FreezeDuration", 8f, "How long enemies are frozen in place (seconds).");
			StaffIceShardsSlowDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of Frost Ice Nova", "SlowDuration", 3f, "How long the post-freeze movement slow lasts (seconds). Set to 0 to disable.");
			StaffClusterbombMinEitr = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of Fracturing Ragnarok", "MinEitrCost", 35f, "Eitr cost for an instant cast (no charge).");
			StaffClusterbombMaxEitr = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of Fracturing Ragnarok", "MaxEitrCost", 60f, "Eitr cost for a fully charged cast (3 seconds).");
			StaffClusterbombMaxChargeTime = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of Fracturing Ragnarok", "MaxChargeTime", 3f, "Time in seconds to reach full charge.");
			StaffClusterbombMinDamageMult = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of Fracturing Ragnarok", "MinDamageMultiplier", 1.2f, "Damage multiplier for an instant cast.");
			StaffClusterbombMaxDamageMult = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of Fracturing Ragnarok", "MaxDamageMultiplier", 3f, "Damage multiplier for a fully charged cast.");
			StaffGreenRootsEitrCost = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of the Wild Regeneration", "EitrCost", 60f, "Eitr cost to cast Regeneration.");
			StaffGreenRootsHealPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of the Wild Regeneration", "HealPercent", 0.3f, "Total HP healed as a percent of max HP (0.30 = 30% max HP healed over duration).");
			StaffGreenRootsDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of the Wild Regeneration", "Duration", 6f, "Duration in seconds over which the total heal is applied. HealPerSecond = (MaxHP * HealPercent) / Duration.");
			StaffGreenRootsRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Staff of the Wild Regeneration", "Radius", 12f, "Radius in meters to heal friendly players, summons and tamed creatures.");
			StaffThunderbloodEitrCost = ((BaseUnityPlugin)this).Config.Bind<float>("Thunderblood Staff Thunderstruck", "EitrCost", 100f, "Eitr cost to cast Thunderstruck.");
			StaffThunderbloodDamagePercent = ((BaseUnityPlugin)this).Config.Bind<float>("Thunderblood Staff Thunderstruck", "DamagePercent", 0.3f, "Lightning damage per strike as a fraction of the staff's total weapon damage (0.3 = 30%).");
			StaffThunderbloodRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Thunderblood Staff Thunderstruck", "Radius", 30f, "Radius in meters around the player in which enemies can be struck.");
			StaffThunderbloodIntervalMin = ((BaseUnityPlugin)this).Config.Bind<float>("Thunderblood Staff Thunderstruck", "IntervalMin", 8f, "Minimum seconds an enemy must stay in range before each strike.");
			StaffThunderbloodIntervalMax = ((BaseUnityPlugin)this).Config.Bind<float>("Thunderblood Staff Thunderstruck", "IntervalMax", 15f, "Maximum seconds an enemy must stay in range before each strike.");
			StaffThunderbloodDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Thunderblood Staff Thunderstruck", "Duration", 600f, "How long Thunderstruck lasts in seconds (600 = 10 minutes).");
			StaffThunderbloodCastVfx = ((BaseUnityPlugin)this).Config.Bind<string>("Thunderblood Staff Thunderstruck", "CastVfx", "vfx_shieldgenerator_startup", "VFX attached to the caster when cast (its built-in audio is removed). Leave blank for none.");
			StaffThunderbloodCastSfx = ((BaseUnityPlugin)this).Config.Bind<string>("Thunderblood Staff Thunderstruck", "CastSfx", "", "Optional extra vanilla SFX prefab played on cast, alongside the custom OGG. Leave blank for none.");
			StaffThunderbloodStrikeVfx = ((BaseUnityPlugin)this).Config.Bind<string>("Thunderblood Staff Thunderstruck", "StrikeVfx", "fx_eikthyr_forwardshockwave", "VFX played on each strike, spawned above the enemy and pointed straight down. Leave blank for none.");
			StaffThunderbloodStrikeSfx = ((BaseUnityPlugin)this).Config.Bind<string>("Thunderblood Staff Thunderstruck", "StrikeSfx", "", "SFX prefab played on each strike. If set, StrikeVfx's built-in audio is replaced. Leave blank for none.");
			StaffThunderbloodStrikeHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Thunderblood Staff Thunderstruck", "StrikeHeight", 15f, "How high above the enemy the strike VFX spawns before travelling down to the ground.");
			StaffShieldEitrCost = ((BaseUnityPlugin)this).Config.Bind<float>("Shield Staff Sanctuary", "EitrCost", 60f, "Eitr cost to cast Sanctuary.");
			StaffShieldHealthPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Shield Staff Sanctuary", "HealthPercent", 0.25f, "Health cost as a fraction of max HP (0.25 = 25%). Cast is blocked if it would kill you.");
			StaffShieldRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Shield Staff Sanctuary", "Radius", 7f, "Radius of the dome in meters.");
			StaffShieldDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Shield Staff Sanctuary", "Duration", 10f, "How long the dome lasts in seconds.");
			StaffShieldSlowPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Shield Staff Sanctuary", "SlowPercent", 0.7f, "How much enemies and enemy projectiles inside are slowed (0.70 = 70% slower). Max 0.95.");
			StaffShieldCastVfx = ((BaseUnityPlugin)this).Config.Bind<string>("Shield Staff Sanctuary", "CastVfx", "vfx_shieldgenerator_refuel", "VFX attached to the caster on cast, tinted to DomeColor with its built-in audio removed. Leave blank for none.");
			StaffShieldCastSfx = ((BaseUnityPlugin)this).Config.Bind<string>("Shield Staff Sanctuary", "CastSfx", "", "Optional extra vanilla SFX prefab played on cast, alongside the custom sounds. Leave blank for none.");
			StaffShieldCastVfxHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Shield Staff Sanctuary", "CastVfxHeight", -0.5f, "Height offset in meters for the cast VFX relative to the caster. Negative = lower.");
			StaffShieldBubbleDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Shield Staff Sanctuary", "BubbleDelay", 1f, "Seconds after casting before the dome appears.");
			StaffShieldDomeFadeTime = ((BaseUnityPlugin)this).Config.Bind<float>("Shield Staff Sanctuary", "DomeFadeTime", 0.25f, "Seconds the dome takes to fade in when it appears and fade out when it ends. 0 = no fade.");
			StaffShieldDomeVfx = ((BaseUnityPlugin)this).Config.Bind<string>("Shield Staff Sanctuary", "DomeVfx", "vfx_StaffShield", "VFX prefab used as the dome visual.");
			StaffShieldDomeColor = ((BaseUnityPlugin)this).Config.Bind<string>("Shield Staff Sanctuary", "DomeColor", "#00E4FF", "Dome tint as a hex color (#RRGGBB). Original transparency is kept.");
			StaffShieldDomeHeightOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Shield Staff Sanctuary", "DomeHeightOffset", -0.2f, "Height of the dome's center relative to the ground, as a fraction of its radius. 0 = half dome, 0.3 = more of the sphere visible, -0.2 = flatter dome.");
			StaffShieldDomeInsideBoost = ((BaseUnityPlugin)this).Config.Bind<float>("Shield Staff Sanctuary", "DomeInsideBoost", 2f, "Opacity and glow multiplier for the dome as seen from inside. 1 = same as outside, higher = more visible from inside.");
			MagicCostScalingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Magic Cost Scaling", "Enabled", true, "Increase staff skill Eitr and Blood Magic HP costs when the caster's magic skill (Elemental Magic or Blood Magic) is below 100. All staff skill cost defaults are balanced for skill level 100.");
			MagicCostPenaltyPerStep = ((BaseUnityPlugin)this).Config.Bind<float>("Magic Cost Scaling", "PenaltyPerStep", 0.01f, "Extra cost added per step below skill level 100 (0.01 = 1%).");
			MagicCostLevelsPerStep = ((BaseUnityPlugin)this).Config.Bind<float>("Magic Cost Scaling", "LevelsPerStep", 5f, "Skill levels per step. With defaults, skill 1 costs +20% and skill 100 costs +0%.");
			StaffSkeletonLevelTiers = ((BaseUnityPlugin)this).Config.Bind<string>("Skeleton Staff Charred Requiem", "LevelTiers", "80:0.30:1,75:0.25:1,65:0.25:1,60:0.25:2", "Cost and summon count per weapon upgrade level, comma separated, starting at level 1. Format per level: eitrCost:healthPercent:summonCount. healthPercent is a fraction of max HP (0.25 = 25%). Levels above the last entry use the last entry.");
			StaffSkeletonDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Skeleton Staff Charred Requiem", "SummonDuration", 600f, "How long the Charred Archers last in seconds (600 = 10 minutes).");
			StaffSkeletonPrefab = ((BaseUnityPlugin)this).Config.Bind<string>("Skeleton Staff Charred Requiem", "SummonPrefab", "Charred_Archer", "Creature prefab to summon.");
			TestMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "TestMode", false, new ConfigDescription("When true, enemies hit by skills survive at 1hp.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			GlobalAttackSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Debug", "GlobalAttackSpeed", 1f, "Global attack animation speed multiplier. 1.0 = normal.");
			SkillWidgetX = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "SkillWidgetX", 605f, new ConfigDescription("Horizontal position of the skill slot widget.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			SkillWidgetY = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "SkillWidgetY", -44f, new ConfigDescription("Vertical position of the skill slot widget.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
		}

		internal static Sprite? LoadEmbeddedSprite(string filename)
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			string path = Path.Combine(directoryName, "icons", filename);
			if (!File.Exists(path))
			{
				path = Path.Combine(directoryName, filename);
			}
			if (!File.Exists(path))
			{
				path = Path.Combine(directoryName, "KeenCombat", "icons", filename);
			}
			if (!File.Exists(path))
			{
				path = Path.Combine(directoryName, "KeenCombat", filename);
			}
			if (!File.Exists(path))
			{
				Log.LogWarning((object)("Icon file not found: " + filename));
				return null;
			}
			byte[] array = File.ReadAllBytes(path);
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
			MethodInfo methodInfo = null;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				Type type = assembly.GetType("UnityEngine.ImageConversion");
				if (!(type == null))
				{
					methodInfo = type.GetMethod("LoadImage", new Type[2]
					{
						typeof(Texture2D),
						typeof(byte[])
					});
					if (methodInfo != null)
					{
						break;
					}
				}
			}
			if (methodInfo == null)
			{
				Log.LogWarning((object)"UnityEngine.ImageConversion.LoadImage not found.");
				return null;
			}
			methodInfo.Invoke(null, new object[2] { val, array });
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
		}

		internal static string? FindAudioFile(string filename)
		{
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			string[] array = new string[4]
			{
				Path.Combine(directoryName, "audio", filename),
				Path.Combine(directoryName, filename),
				Path.Combine(directoryName, "KeenCombat", "audio", filename),
				Path.Combine(directoryName, "KeenCombat", filename)
			};
			string[] array2 = array;
			foreach (string text in array2)
			{
				if (File.Exists(text))
				{
					return text;
				}
			}
			return null;
		}

		internal static IEnumerator LoadAudioClip(string filename, Action<AudioClip?> onLoaded)
		{
			string path = FindAudioFile(filename);
			if (path == null)
			{
				Log.LogWarning((object)("Audio file not found: " + filename));
				onLoaded(null);
				yield break;
			}
			string uri = "file:///" + path.Replace("\\", "/");
			UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(uri, (AudioType)14);
			try
			{
				yield return request.SendWebRequest();
				if ((int)request.result != 1)
				{
					Log.LogWarning((object)("Failed to load audio clip: " + filename + " — " + request.error));
					onLoaded(null);
				}
				else
				{
					AudioClip clip = DownloadHandlerAudioClip.GetContent(request);
					((Object)clip).name = Path.GetFileNameWithoutExtension(filename);
					onLoaded(clip);
				}
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
		}
	}
	public static class SkillMasks
	{
		private static int _characters = -1;

		public static int Characters
		{
			get
			{
				if (_characters == -1)
				{
					_characters = LayerMask.GetMask(new string[4] { "character", "character_net", "character_ghost", "character_noenv" });
				}
				return _characters;
			}
		}
	}
}
namespace KeenCombat.Skills
{
	public class AtgeirSkill : IWeaponSkill
	{
		private static Sprite? _icon;

		private static bool _iconLoaded;

		public string SkillName => "Falcon Blitz";

		public string Description => "Unleash a rapid flurry of strikes, hitting your target six times in quick succession.";

		public float Cooldown => Plugin.AtgeirSkillCooldown.Value;

		public string CooldownSEName => "SE_Cooldown_Atgeir";

		public Sprite? Icon
		{
			get
			{
				if (!_iconLoaded)
				{
					_icon = Plugin.LoadEmbeddedSprite("FalconBlitzIcon.png");
					_iconLoaded = true;
				}
				return _icon;
			}
		}

		public bool IsOnCooldown(Player player)
		{
			return SE_SkillCooldown.IsOnCooldown(player, CooldownSEName);
		}

		public void OnPress(Player player, ItemData weapon)
		{
			SE_SkillCooldown.Apply(player, Cooldown, CooldownSEName);
			if (((Humanoid)player).m_currentAttack != null)
			{
				((Humanoid)player).m_currentAttack.Stop();
				((Humanoid)player).m_previousAttack = ((Humanoid)player).m_currentAttack;
				((Humanoid)player).m_currentAttack = null;
			}
			((Humanoid)player).ClearActionQueue();
			((MonoBehaviour)player).StartCoroutine(FlurryRoutine(player, weapon));
		}

		public void OnHold(Player player, ItemData weapon, float heldDuration)
		{
		}

		public void OnRelease(Player player, ItemData weapon, float heldDuration)
		{
		}

		private static IEnumerator FlurryRoutine(Player player, ItemData weapon)
		{
			bool isSpear = (int)weapon.m_shared.m_skillType == 5;
			float hitInterval = (isSpear ? 0.25f : 0.33f);
			float rangeMultiplier = (isSpear ? 2f : 1f);
			float savedSpeed = ((Character)player).m_speed;
			float savedRunSpeed = ((Character)player).m_runSpeed;
			float savedTurnSpeed = ((Character)player).m_turnSpeed;
			Vector3 lockedLookDir = ((Component)player).transform.forward;
			((Character)player).m_speed = 0f;
			((Character)player).m_runSpeed = 0f;
			((Character)player).m_turnSpeed = 0f;
			ZSyncAnimation zsync = ((Component)player).GetComponent<ZSyncAnimation>();
			for (int i = 0; i < 6; i++)
			{
				if ((Object)(object)player == (Object)null)
				{
					break;
				}
				if (((Character)player).IsDead())
				{
					break;
				}
				((Component)player).transform.forward = lockedLookDir;
				((Character)player).m_lookDir = lockedLookDir;
				if ((Object)(object)zsync != (Object)null)
				{
					if (isSpear)
					{
						zsync.SetTrigger("spear_poke");
					}
					else
					{
						zsync.SetTrigger($"atgeir_attack{i % 3}");
					}
				}
				Vector3 vfxPos = ((Component)player).transform.position + lockedLookDir * (1.5f * rangeMultiplier) + Vector3.up;
				NetworkedEffects.BroadcastVfx("vfx_crossbow_lightning_fire", vfxPos, ((Component)player).transform.rotation);
				NetworkedEffects.BroadcastSfx("sfx_sword_swing", ((Component)player).transform.position, ((Component)player).transform.rotation);
				ApplyHit(player, weapon, lockedLookDir, rangeMultiplier);
				yield return (object)new WaitForSeconds(hitInterval);
			}
			if ((Object)(object)player != (Object)null)
			{
				((Character)player).m_speed = savedSpeed;
				((Character)player).m_runSpeed = savedRunSpeed;
				((Character)player).m_turnSpeed = savedTurnSpeed;
			}
		}

		private static void ApplyHit(Player player, ItemData weapon, Vector3 direction, float rangeMultiplier = 1f)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Invalid comparison between Unknown and I4
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Expected O, but got Unknown
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			float num = ((weapon.m_shared.m_attack.m_attackRange > 0f) ? (weapon.m_shared.m_attack.m_attackRange * rangeMultiplier) : (3f * rangeMultiplier));
			Collider[] array = Physics.OverlapSphere(((Component)player).transform.position + direction * (num * 0.5f) + Vector3.up, num * 0.5f, SkillMasks.Characters);
			HashSet<Character> hashSet = new HashSet<Character>();
			Collider[] array2 = array;
			foreach (Collider val in array2)
			{
				Character componentInParent = ((Component)val).GetComponentInParent<Character>();
				if ((Object)(object)componentInParent == (Object)null || (Object)(object)componentInParent == (Object)(object)player || (componentInParent.IsPlayer() && !((Character)player).IsPVPEnabled()) || (int)componentInParent.m_faction == 0 || !hashSet.Add(componentInParent))
				{
					continue;
				}
				Vector3 val2 = ((Component)componentInParent).transform.position - ((Component)player).transform.position;
				Vector3 normalized = ((Vector3)(ref val2)).normalized;
				if (!(Vector3.Dot(direction, normalized) < 0.3f))
				{
					HitData val3 = new HitData();
					val3.m_damage = weapon.GetDamage();
					((DamageTypes)(ref val3.m_damage)).Modify(Plugin.AtgeirSkillDamage.Value);
					val3.m_pushForce = 1f;
					val3.m_staggerMultiplier = 1f;
					val3.m_dir = direction;
					val3.m_attacker = ((Character)player).GetZDOID();
					val3.m_point = ((Component)componentInParent).transform.position;
					componentInParent.Damage(val3);
					if (Plugin.TestMode.Value && componentInParent.GetHealth() <= 0f)
					{
						componentInParent.SetHealth(1f);
					}
				}
			}
		}
	}
	public class AxeSkill : IWeaponSkill
	{
		private static Sprite? _icon;

		private static bool _iconLoaded;

		public string SkillName => "Frenzy";

		public string Description => "Let out a battle roar, boosting your attack and movement speed.";

		public float Cooldown => Plugin.AxeSkillCooldown.Value;

		public string CooldownSEName => "SE_Cooldown_Axe";

		public Sprite? Icon
		{
			get
			{
				if (!_iconLoaded)
				{
					_icon = Plugin.LoadEmbeddedSprite("FrenzyIcon.png");
					_iconLoaded = true;
				}
				return _icon;
			}
		}

		public bool IsOnCooldown(Player player)
		{
			return SE_SkillCooldown.IsOnCooldown(player, CooldownSEName);
		}

		public void OnPress(Player player, ItemData weapon)
		{
			SE_SkillCooldown.Apply(player, Cooldown, CooldownSEName);
			((MonoBehaviour)player).StartCoroutine(FrenzyRoutine(player));
		}

		public void OnHold(Player player, ItemData weapon, float heldDuration)
		{
		}

		public void OnRelease(Player player, ItemData weapon, float heldDuration)
		{
		}

		private static IEnumerator FrenzyRoutine(Player player)
		{
			if (!((Object)(object)player == (Object)null) && !((Character)player).IsDead())
			{
				NetworkedEffects.BroadcastAnimatorSpeed(player, 1.5f);
				ZSyncAnimation zsync = ((Component)player).GetComponent<ZSyncAnimation>();
				if ((Object)(object)zsync != (Object)null)
				{
					zsync.SetTrigger("emote_roar");
				}
				NetworkedEffects.BroadcastOgg("FrenzyRoar.ogg", ((Component)player).transform.position);
				NetworkedEffects.BroadcastVfxOnCharacter((Character)(object)player, "fx_Fader_Roar", suppressAudio: false, 1f, "#FF6600");
				yield return (object)new WaitForSeconds(1.3333334f);
				NetworkedEffects.BroadcastAnimatorSpeed(player, 1f);
				if (!((Object)(object)player == (Object)null) && !((Character)player).IsDead())
				{
					SE_AxeSkillBuff.Apply(player, Plugin.AxeBuffDuration.Value, Plugin.AxeAttackSpeedBonus.Value, Plugin.AxeMoveSpeedBonus.Value);
				}
			}
		}
	}
	public class BowSkill : IWeaponSkill
	{
		private const string ZdoKeyPrimalRally = "KeenCombat_PrimalRally";

		private const string ZdoKeyScale = "KeenCombat_SummonScale";

		private const string ZdoKeyDamageMult = "KeenCombat_SummonDamageMult";

		private const string ZdoKeyHpMult = "KeenCombat_SummonHpMult";

		private const string ZdoKeyOwner = "KeenCombat_SummonOwner";

		private static Character? _activeSummon;

		private static Coroutine? _summonCoroutine;

		private static Sprite? _icon;

		private static bool _iconLoaded;

		public string SkillName => "Primal Rally";

		public string Description => "Call upon a wild beast to fight by your side.";

		public float Cooldown => Plugin.BowSkillCooldown.Value;

		public string CooldownSEName => "SE_Cooldown_Bow";

		public Sprite? Icon
		{
			get
			{
				if (!_iconLoaded)
				{
					_icon = Plugin.LoadEmbeddedSprite("PrimalRallyIcon.png");
					_iconLoaded = true;
				}
				return _icon;
			}
		}

		public bool IsOnCooldown(Player player)
		{
			return SE_SkillCooldown.IsOnCooldown(player, CooldownSEName);
		}

		public void OnPress(Player player, ItemData weapon)
		{
			SE_SkillCooldown.Apply(player, Cooldown, CooldownSEName);
			((MonoBehaviour)player).StartCoroutine(PrimalRallyRoutine(player, weapon));
		}

		public void OnHold(Player player, ItemData weapon, float heldDuration)
		{
		}

		public void OnRelease(Player player, ItemData weapon, float heldDuration)
		{
		}

		private static IEnumerator PrimalRallyRoutine(Player player, ItemData weapon)
		{
			if ((Object)(object)_activeSummon != (Object)null && !_activeSummon.IsDead())
			{
				DespawnSummon(_activeSummon);
			}
			ZSyncAnimation zsync = ((Component)player).GetComponent<ZSyncAnimation>();
			if ((Object)(object)zsync != (Object)null)
			{
				zsync.SetTrigger("emote_comehere");
			}
			NetworkedEffects.BroadcastOgg("PetCall.ogg", ((Component)player).transform.position);
			yield return (object)new WaitForSeconds(1f);
			if ((Object)(object)player == (Object)null || ((Character)player).IsDead())
			{
				yield break;
			}
			(string, int, float, float, float) creatureForBow = GetCreatureForBow(weapon);
			string prefabName = creatureForBow.Item1;
			int starLevel = creatureForBow.Item2;
			float bowScale = creatureForBow.Item3;
			float bowDamageMult = creatureForBow.Item4;
			float bowHpMult = creatureForBow.Item5;
			float finalScale = ((bowScale > 0f) ? bowScale : GetCreatureScale(prefabName));
			float finalDamageMult = ((bowDamageMult > 0f) ? bowDamageMult : 1f);
			float finalHpMult = ((bowHpMult > 0f) ? bowHpMult : 1f);
			KC_Log.Debug("PrimalRally: spawning " + prefabName + " " + $"(star {starLevel}, scale {finalScale}, " + $"dmg {finalDamageMult}, hp {finalHpMult})");
			ZNetScene instance = ZNetScene.instance;
			GameObject creaturePrefab = ((instance != null) ? instance.GetPrefab(prefabName) : null);
			if ((Object)(object)creaturePrefab == (Object)null)
			{
				KC_Log.Warn("PrimalRally: prefab '" + prefabName + "' not found!");
				yield break;
			}
			Vector3 spawnPos = ((Component)player).transform.position + ((Component)player).transform.right * 1.5f - ((Component)player).transform.forward * 1.5f;
			GameObject spawnedObj = Object.Instantiate<GameObject>(creaturePrefab, spawnPos, Quaternion.identity);
			Character character = spawnedObj.GetComponent<Character>();
			if ((Object)(object)character == (Object)null)
			{
				KC_Log.Warn("PrimalRally: '" + prefabName + "' has no Character!");
				Object.Destroy((Object)(object)spawnedObj);
				yield break;
			}
			if (starLevel > 0)
			{
				character.SetLevel(starLevel + 1);
				ZNetView nviewLevel = spawnedObj.GetComponent<ZNetView>();
				if (nviewLevel != null)
				{
					ZDO zDO = nviewLevel.GetZDO();
					if (zDO != null)
					{
						zDO.Set(ZDOVars.s_level, starLevel + 1, false);
					}
				}
			}
			if (finalHpMult != 1f)
			{
				float newMaxHp = character.GetMaxHealth() * finalHpMult;
				character.SetMaxHealth(newMaxHp);
				character.SetHealth(newMaxHp);
			}
			character.m_faction = (Faction)0;
			ZNetView nview = spawnedObj.GetComponent<ZNetView>();
			if ((Object)(object)nview != (Object)null && nview.GetZDO() != null)
			{
				nview.GetZDO().Set(ZDOVars.s_tamed, true);
				nview.GetZDO().Set(ZDOVars.s_tamedName, "Ally");
				nview.GetZDO().Set(ZDOVars.s_follow, player.GetPlayerName());
				nview.GetZDO().Set("KeenCombat_PrimalRally", true);
				nview.GetZDO().Set("KeenCombat_SummonScale", finalScale);
				nview.GetZDO().Set("KeenCombat_SummonDamageMult", finalDamageMult);
				nview.GetZDO().Set("KeenCombat_SummonHpMult", finalHpMult);
				nview.GetZDO().Set("KeenCombat_SummonOwner", player.GetPlayerName());
			}
			if (finalScale > 0f && finalScale != 1f)
			{
				spawnedObj.transform.localScale = Vector3.one * finalScale;
			}
			Tameable tameable = spawnedObj.GetComponent<Tameable>();
			if ((Object)(object)tameable != (Object)null)
			{
				tameable.Tame();
			}
			else
			{
				spawnedObj.AddComponent<Tameable>();
			}
			MonsterAI monsterAI = spawnedObj.GetComponent<MonsterAI>();
			AnimalAI animalAI = spawnedObj.GetComponent<AnimalAI>();
			if ((Object)(object)monsterAI != (Object)null)
			{
				monsterAI.SetFollowTarget(((Component)player).gameObject);
				monsterAI.m_enableHuntPlayer = false;
				monsterAI.m_alertRange = 60f;
				((BaseAI)monsterAI).m_viewRange = 60f;
				((BaseAI)monsterAI).m_viewAngle = 180f;
				((BaseAI)monsterAI).m_hearRange = 60f;
				((MonoBehaviour)player).StartCoroutine(ResetAwarenessAfterDelay(monsterAI, null, 10f));
			}
			else if ((Object)(object)animalAI != (Object)null)
			{
				Object.Destroy((Object)(object)animalAI);
				MonsterAI newMonsterAI = spawnedObj.AddComponent<MonsterAI>();
				newMonsterAI.SetFollowTarget(((Component)player).gameObject);
				newMonsterAI.m_enableHuntPlayer = false;
				newMonsterAI.m_alertRange = 60f;
				((BaseAI)newMonsterAI).m_viewRange = 60f;
				((BaseAI)newMonsterAI).m_viewAngle = 180f;
				((BaseAI)newMonsterAI).m_hearRange = 60f;
				((MonoBehaviour)player).StartCoroutine(ResetAwarenessAfterDelay(null, newMonsterAI, 10f));
			}
			_activeSummon = character;
			KC_Log.Debug("PrimalRally: " + prefabName + " summoned.");
			if (_summonCoroutine != null)
			{
				((MonoBehaviour)player).StopCoroutine(_summonCoroutine);
			}
			_summonCoroutine = ((MonoBehaviour)player).StartCoroutine(SummonTimer(player, character, Plugin.BowSummonDuration.Value));
		}

		public static float GetCreatureScale(string prefabName)
		{
			string value = Plugin.CreatureScaleMap.Value;
			string[] array = value.Split(new char[1] { ',' });
			foreach (string text in array)
			{
				string[] array2 = text.Trim().Split(new char[1] { ':' });
				if (array2.Length >= 2 && array2[0].Trim().Equals(prefabName, StringComparison.OrdinalIgnoreCase) && float.TryParse(array2[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					return result;
				}
			}
			return 1f;
		}

		private static IEnumerator ResetAwarenessAfterDelay(MonsterAI? ai1, MonsterAI? ai2, float delay)
		{
			yield return (object)new WaitForSeconds(delay);
			MonsterAI ai3 = ai1 ?? ai2;
			if (!((Object)(object)ai3 == (Object)null))
			{
				ai3.m_alertRange = 20f;
				((BaseAI)ai3).m_viewRange = 20f;
				((BaseAI)ai3).m_viewAngle = 90f;
				((BaseAI)ai3).m_hearRange = 20f;
			}
		}

		private static IEnumerator SummonTimer(Player player, Character summon, float duration)
		{
			float elapsed = 0f;
			while (elapsed < duration)
			{
				if ((Object)(object)summon == (Object)null || summon.IsDead())
				{
					_activeSummon = null;
					yield break;
				}
				elapsed += Time.deltaTime;
				yield return null;
			}
			if ((Object)(object)summon != (Object)null && !summon.IsDead())
			{
				DespawnSummon(summon);
			}
		}

		public static void DespawnActiveSummon()
		{
			if ((Object)(object)_activeSummon != (Object)null && !_activeSummon.IsDead())
			{
				DespawnSummon(_activeSummon);
			}
		}

		private static void DespawnSummon(Character summon)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)summon == (Object)null))
			{
				ZNetScene instance = ZNetScene.instance;
				GameObject val = ((instance != null) ? instance.GetPrefab("fx_perfectdodge") : null);
				if ((Object)(object)val != (Object)null)
				{
					Object.Instantiate<GameObject>(val, ((Component)summon).transform.position, ((Component)summon).transform.rotation);
				}
				ZNetView component = ((Component)summon).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
				{
					ZNetScene.instance.Destroy(((Component)summon).gameObject);
				}
				else
				{
					Object.Destroy((Object)(object)((Component)summon).gameObject);
				}
				_activeSummon = null;
			}
		}

		private static (string prefab, int star, float scale, float damageMult, float hpMult) GetCreatureForBow(ItemData weapon)
		{
			string text = weapon.m_shared.m_name.ToLowerInvariant();
			string value = Plugin.BowCreatureMap.Value;
			Dictionary<string, (string, int, float, float, float)> dictionary = new Dictionary<string, (string, int, float, float, float)>();
			string[] array = value.Split(new char[1] { ',' });
			foreach (string text2 in array)
			{
				string[] array2 = text2.Trim().Split(new char[1] { ':' });
				if (array2.Length >= 2)
				{
					string key = array2[0].Trim().ToLowerInvariant();
					string item = array2[1].Trim();
					int result;
					int item2 = ((array2.Length >= 3 && int.TryParse(array2[2].Trim(), out result)) ? result : 0);
					float item3 = ParseFloat(array2, 3);
					float item4 = ParseFloat(array2, 4);
					float item5 = ParseFloat(array2, 5);
					dictionary[key] = (item, item2, item3, item4, item5);
				}
			}
			if (dictionary.TryGetValue(text, out var value2))
			{
				return value2;
			}
			KC_Log.Warn("PrimalRally: no mapping for '" + text + "' — spawning Neck.");
			return (prefab: "Neck", star: 0, scale: 1f, damageMult: 1f, hpMult: 1f);
		}

		private static float ParseFloat(string[] parts, int index)
		{
			if (parts.Length <= index)
			{
				return 0f;
			}
			float result;
			return float.TryParse(parts[index].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out result) ? result : 0f;
		}
	}
	[HarmonyPatch(typeof(Character), "Start")]
	public static class Character_Start_PrimalRallySync
	{
		private static void Postfix(Character __instance)
		{
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if (!((Object)(object)component == (Object)null) && component.GetZDO() != null && component.GetZDO().GetBool("KeenCombat_PrimalRally", false))
			{
				ApplySync(__instance, component);
				((MonoBehaviour)Plugin.instance).StartCoroutine(ApplySyncDelayed(__instance, component));
			}
		}

		private static void ApplySync(Character character, ZNetView nview)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)character == (Object)null) && !((Object)(object)nview == (Object)null) && nview.GetZDO() != null)
			{
				float num = nview.GetZDO().GetFloat("KeenCombat_SummonScale", 1f);
				if (num > 0f && num != 1f)
				{
					((Component)character).transform.localScale = Vector3