Decompiled source of EnhancedVanillaWeapons v1.1.0

EnhancedVanillaWeapons.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("EnhancedVanillaWeapons")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("EnhancedVanillaWeapons")]
[assembly: AssemblyTitle("EnhancedVanillaWeapons")]
[assembly: AssemblyVersion("1.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace EnhancedVanillaWeapons
{
	internal static class JotunBane
	{
		internal enum PoisonMode
		{
			Vanilla,
			Add,
			Skip
		}

		private class RuptureMark
		{
			internal Character Target;

			internal ZDOID Attacker;

			internal float CloudPoison;

			internal float Time;
		}

		private class PendingCloud
		{
			internal Vector3 Center;

			internal HitPlan Plan;

			internal float Radius;

			internal int StacksEach;
		}

		internal class HitPlan
		{
			internal bool Rupture;

			internal int Stacks;

			internal int Previous;

			internal float CloudPoison;

			internal ZDOID Attacker;
		}

		private class PendingBurst
		{
			internal Vector3 At;

			internal int Stacks;

			internal ZDOID Attacker;
		}

		private const string AxeName = "$item_axe_jotunbane";

		internal const int FullStacks = 3;

		internal const int MaxStacks = 15;

		private const string RuptureRpc = "EnhancedVanillaWeapons_JotunRupture";

		private const string BurstRpc = "EnhancedVanillaWeapons_JotunBurst";

		private const string MilestoneRpc = "EnhancedVanillaWeapons_JotunMilestone";

		private const string StacksKey = "EnhancedVanillaWeapons_JotunStacks";

		private const string StacksUntilKey = "EnhancedVanillaWeapons_JotunStacksUntil";

		private const float RuptureMarkSeconds = 1f;

		internal const float StackSeconds = 8f;

		private static readonly FieldRef<SE_Poison, float> DamageLeft = AccessTools.FieldRefAccess<SE_Poison, float>("m_damageLeft");

		private static readonly FieldRef<SE_Poison, float> DamagePerHit = AccessTools.FieldRefAccess<SE_Poison, float>("m_damagePerHit");

		internal static PoisonMode s_poisonMode;

		private static float s_addPools;

		private static bool s_ruptureSwing;

		private static float s_swingPoison;

		private static readonly List<RuptureMark> s_marks = new List<RuptureMark>();

		private static readonly HashSet<Character> s_popped = new HashSet<Character>();

		private static readonly List<PendingCloud> s_pendingClouds = new List<PendingCloud>();

		private static bool s_inCloud;

		internal static int Ruptures;

		internal static int FullRuptures;

		internal static int BiggestRupture;

		private static readonly List<PendingBurst> s_pendingBursts = new List<PendingBurst>();

		internal static bool IsBane(ItemData weapon)
		{
			return weapon?.m_shared.m_name == "$item_axe_jotunbane";
		}

		internal static void BeforeAttackTrigger(Attack attack, Humanoid character)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			s_ruptureSwing = false;
			if (Plugin.BaneEnabled.Value && !((Object)(object)character == (Object)null) && !((Object)(object)character != (Object)(object)Player.m_localPlayer))
			{
				ItemData weapon = attack.GetWeapon();
				if (IsBane(weapon) && !(attack.m_attackAnimation != weapon.m_shared.m_secondaryAttack.m_attackAnimation))
				{
					s_ruptureSwing = true;
					s_swingPoison = weapon.GetDamage().m_poison;
				}
			}
		}

		internal static void AfterAttackTrigger()
		{
			s_ruptureSwing = false;
		}

		internal static void OnDamage(Character victim, HitData hit)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if (s_ruptureSwing && !s_inCloud && !((Object)(object)victim == (Object)null) && !victim.IsPlayer() && !((Object)(object)hit.GetAttacker() != (Object)(object)Player.m_localPlayer))
			{
				ZNetView component = ((Component)victim).GetComponent<ZNetView>();
				if (!((Object)(object)component == (Object)null) && component.IsValid())
				{
					component.InvokeRPC("EnhancedVanillaWeapons_JotunRupture", new object[2] { hit.m_attacker, s_swingPoison });
				}
			}
		}

		internal static void Register(Character character, ZNetView nview)
		{
			if (!(character is Player) && !((Object)(object)nview == (Object)null) && nview.IsValid())
			{
				nview.Register<ZDOID, float>("EnhancedVanillaWeapons_JotunRupture", (Action<long, ZDOID, float>)delegate(long sender, ZDOID attacker, float cloudPoison)
				{
					//IL_000c: Unknown result type (might be due to invalid IL or missing references)
					OnRuptureMark(character, nview, attacker, cloudPoison);
				});
				nview.Register<Vector3, int, ZDOID>("EnhancedVanillaWeapons_JotunBurst", (Action<long, Vector3, int, ZDOID>)delegate(long sender, Vector3 at, int stacks, ZDOID attacker)
				{
					//IL_0000: Unknown result type (might be due to invalid IL or missing references)
					//IL_0002: Unknown result type (might be due to invalid IL or missing references)
					OnBurst(at, stacks, attacker);
				});
				nview.Register<int>("EnhancedVanillaWeapons_JotunMilestone", (Action<long, int>)delegate(long sender, int stacks)
				{
					StackCues.OnMilestone(character, stacks);
				});
			}
		}

		internal static int GetStacks(Character character)
		{
			ZNetView component = ((Component)character).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || (Object)(object)ZNet.instance == (Object)null)
			{
				return 0;
			}
			ZDO zDO = component.GetZDO();
			int num = zDO.GetInt("EnhancedVanillaWeapons_JotunStacks", 0);
			if (num <= 0 || NowMs() >= zDO.GetLong("EnhancedVanillaWeapons_JotunStacksUntil", 0L))
			{
				return 0;
			}
			return num;
		}

		private static void OnRuptureMark(Character character, ZNetView nview, ZDOID attacker, float cloudPoison)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)character == (Object)null) && nview.IsOwner())
			{
				TakeMark(character, attacker);
				s_marks.Add(new RuptureMark
				{
					Target = character,
					Attacker = attacker,
					CloudPoison = cloudPoison,
					Time = Time.time
				});
			}
		}

		private static RuptureMark TakeMark(Character target, ZDOID attacker)
		{
			//IL_001f: 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)
			for (int i = 0; i < s_marks.Count; i++)
			{
				RuptureMark ruptureMark = s_marks[i];
				if (!((Object)(object)ruptureMark.Target != (Object)(object)target) && !(ruptureMark.Attacker != attacker))
				{
					s_marks.RemoveAt(i);
					return ruptureMark;
				}
			}
			return null;
		}

		internal static HitPlan PlanHit(Character target, ZNetView nview, HitData hit)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Invalid comparison between Unknown and I4
			//IL_0084: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			s_poisonMode = PoisonMode.Vanilla;
			if (!Plugin.BaneEnabled.Value || (Object)(object)nview == (Object)null || !nview.IsOwner() || target.IsPlayer() || target.IsDead() || target.GetHealth() <= 0f)
			{
				return null;
			}
			if ((int)hit.m_skill == 7 && !(hit.m_damage.m_poison <= 0f))
			{
				Character attacker = hit.GetAttacker();
				Player val = (Player)(object)((attacker is Player) ? attacker : null);
				if (val != null && HoldsBane(val))
				{
					int stacks = GetStacks(target);
					HitPlan hitPlan = new HitPlan
					{
						Attacker = hit.m_attacker,
						Previous = stacks
					};
					RuptureMark ruptureMark = TakeMark(target, hit.m_attacker);
					if (ruptureMark != null && Time.time - ruptureMark.Time < 1f && stacks > 0)
					{
						hitPlan.Rupture = true;
						hitPlan.Stacks = stacks;
						hitPlan.CloudPoison = ruptureMark.CloudPoison;
						s_poisonMode = PoisonMode.Skip;
						return hitPlan;
					}
					hitPlan.Stacks = Mathf.Min(stacks + 1, 15);
					s_poisonMode = PoisonMode.Add;
					int num = Mathf.Max(0, hitPlan.Stacks - 3);
					s_addPools = (float)Mathf.Min(hitPlan.Stacks, 3) * (1f + (float)(num * Plugin.BaneExtraDotPercent.Value) / 100f);
					return hitPlan;
				}
			}
			return null;
		}

		private static bool HoldsBane(Player attacker)
		{
			ZNetView component = ((Component)attacker).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return false;
			}
			ZDO zDO = component.GetZDO();
			if (!IsBanePrefab(zDO.GetInt(ZDOVars.s_rightItem, 0)))
			{
				return IsBanePrefab(zDO.GetInt(ZDOVars.s_leftItem, 0));
			}
			return true;
		}

		private static bool IsBanePrefab(int hash)
		{
			if (hash == 0)
			{
				return false;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(hash);
			ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val != (Object)null)
			{
				return IsBane(val.m_itemData);
			}
			return false;
		}

		internal static void FinishHit(Character target, ZNetView nview, HitPlan plan)
		{
			s_poisonMode = PoisonMode.Vanilla;
			if (plan == null || (Object)(object)target == (Object)null || !nview.IsValid())
			{
				return;
			}
			if (plan.Rupture)
			{
				Rupture(target, nview, plan);
				return;
			}
			SetStacks(nview, plan.Stacks, StacksUntil());
			if (target.GetHealth() > 0f)
			{
				for (int i = 3; i <= 15; i += 3)
				{
					if (plan.Stacks >= i && plan.Previous < i)
					{
						nview.InvokeRPC(ZNetView.Everybody, "EnhancedVanillaWeapons_JotunMilestone", new object[1] { i });
					}
				}
			}
			if (Plugin.LogBane.Value)
			{
				Plugin.Log.LogInfo((object)$"Jotun Bane: {target.m_name} at {plan.Stacks} stack(s)");
			}
		}

		internal static bool AddPoison(Character target, SEMan seman, float damage, short variant)
		{
			PoisonMode poisonMode = s_poisonMode;
			s_poisonMode = PoisonMode.Vanilla;
			switch (poisonMode)
			{
			case PoisonMode.Skip:
				return false;
			case PoisonMode.Add:
				if (!(damage <= 0f))
				{
					StatusEffect statusEffect = seman.GetStatusEffect(SEMan.s_statusEffectPoison);
					SE_Poison val = (SE_Poison)(object)((statusEffect is SE_Poison) ? statusEffect : null);
					if ((Object)(object)val == (Object)null)
					{
						StatusEffect obj = seman.AddStatusEffect(SEMan.s_statusEffectPoison, false, 0, 0f, variant);
						val = (SE_Poison)(object)((obj is SE_Poison) ? obj : null);
					}
					if ((Object)(object)val == (Object)null)
					{
						return true;
					}
					float num = DamageLeft.Invoke(val);
					float num2 = s_addPools * damage;
					if (num2 < num && ((StatusEffect)val).m_ttl != 8f)
					{
						return false;
					}
					SetPoison(val, num2);
					return false;
				}
				goto default;
			default:
				return true;
			}
		}

		private static void SetPoison(SE_Poison poison, float total)
		{
			DamageLeft.Invoke(poison) = total;
			((StatusEffect)poison).m_ttl = 8f;
			int num = Mathf.Max(1, (int)(8f / poison.m_damageInterval));
			DamagePerHit.Invoke(poison) = total / (float)num;
			((StatusEffect)poison).ResetTime();
		}

		private static long StacksUntil()
		{
			return NowMs() + 8000;
		}

		private static void Rupture(Character target, ZNetView nview, HitPlan plan)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: 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_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Expected O, but got Unknown
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: 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_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			Vector3 centerPoint = target.GetCenterPoint();
			SetStacks(nview, 0, 0L);
			s_popped.Add(target);
			bool flag = plan.Stacks >= 3;
			StatusEffect statusEffect = target.GetSEMan().GetStatusEffect(SEMan.s_statusEffectPoison);
			SE_Poison val = (SE_Poison)(object)((statusEffect is SE_Poison) ? statusEffect : null);
			float num = (((Object)(object)val != (Object)null) ? DamageLeft.Invoke(val) : 0f) * Plugin.BanePoisonMultiplier.Value;
			if ((Object)(object)val != (Object)null)
			{
				target.GetSEMan().RemoveStatusEffect((StatusEffect)(object)val, true);
			}
			if (num > 0f)
			{
				HitData val2 = new HitData
				{
					m_point = centerPoint,
					m_hitType = (HitType)7,
					m_attacker = plan.Attacker
				};
				val2.m_damage.m_poison = num;
				target.ApplyDamage(val2, true, false, (DamageModifier)0);
			}
			float num2 = 1f + (float)(Mathf.Max(0, plan.Stacks - 3) * Plugin.BaneRuptureGrowthPercent.Value) / 100f;
			float num3 = (float)(Plugin.BaneBluntPerStack.Value * plan.Stacks) * num2;
			float num4 = (float)(Plugin.BaneExtraPoison.Value * plan.Stacks) * num2;
			if (num3 > 0f || num4 > 0f)
			{
				HitData val3 = new HitData
				{
					m_point = centerPoint,
					m_hitType = (HitType)2,
					m_attacker = plan.Attacker,
					m_skill = (SkillType)7
				};
				val3.m_damage.m_blunt = num3;
				val3.m_damage.m_poison = num4;
				DamageModifier val4 = default(DamageModifier);
				val3.ApplyResistance(target.GetDamageModifiers((WeakSpot)null), ref val4);
				target.ApplyDamage(val3, true, true, val4);
			}
			nview.InvokeRPC(ZNetView.Everybody, "EnhancedVanillaWeapons_JotunBurst", new object[3] { centerPoint, plan.Stacks, plan.Attacker });
			float num5 = CloudRadius(plan.Stacks);
			if (Plugin.LogBane.Value)
			{
				Plugin.Log.LogInfo((object)($"Jotun Bane: ruptured {target.m_name} at {plan.Stacks} stack(s): {num:0} poison, {num4:0} extra poison, {num3:0} blunt before resistance" + (flag ? $", rot cloud {num5:0.#} m" : "")));
			}
			if (flag)
			{
				s_pendingClouds.Add(new PendingCloud
				{
					Center = centerPoint,
					Plan = plan,
					Radius = num5,
					StacksEach = CloudStacks(plan.Stacks)
				});
			}
		}

		internal static int CloudStacks(int stacks)
		{
			return Mathf.Max(1, stacks / 3);
		}

		internal static float CloudRadius(int stacks)
		{
			return Plugin.BaneCloudRadius.Value + (float)Mathf.Max(0, stacks - 3) * Plugin.BaneCloudRadiusPerExtra.Value;
		}

		private static void RotCloud(Vector3 center, HitPlan plan, float radius, int stacksEach)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: 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_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: 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_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Expected O, but got Unknown
			if (plan.CloudPoison <= 0f)
			{
				return;
			}
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.FindInstance(plan.Attacker) : null);
			Character val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Character>() : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			List<Character> list = new List<Character>();
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (!((Object)(object)allCharacter == (Object)null) && !s_popped.Contains(allCharacter) && !allCharacter.IsDead() && !allCharacter.IsPlayer() && BaseAI.IsEnemy(val2, allCharacter) && !(Vector3.Distance(center, allCharacter.GetCenterPoint()) > radius + allCharacter.GetRadius()))
				{
					list.Add(allCharacter);
				}
			}
			s_inCloud = true;
			try
			{
				foreach (Character item in list)
				{
					Vector3 centerPoint = item.GetCenterPoint();
					for (int i = 0; i < stacksEach; i++)
					{
						HitData val3 = new HitData
						{
							m_point = centerPoint
						};
						Vector3 val4 = centerPoint - center;
						val3.m_dir = ((Vector3)(ref val4)).normalized;
						val3.m_hitType = (HitType)2;
						val3.m_skill = (SkillType)7;
						val3.m_attacker = plan.Attacker;
						HitData val5 = val3;
						val5.m_damage.m_poison = plan.CloudPoison;
						item.Damage(val5);
					}
				}
			}
			finally
			{
				s_inCloud = false;
			}
		}

		private static void SetStacks(ZNetView nview, int stacks, long until)
		{
			ZDO zDO = nview.GetZDO();
			zDO.Set("EnhancedVanillaWeapons_JotunStacks", stacks);
			zDO.Set("EnhancedVanillaWeapons_JotunStacksUntil", until);
		}

		private static long NowMs()
		{
			return (long)(ZNet.instance.GetTimeSeconds() * 1000.0);
		}

		internal static void Update()
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if (s_marks.Count > 0)
			{
				s_marks.RemoveAll((RuptureMark mark) => (Object)(object)mark.Target == (Object)null || Time.time - mark.Time > 1f);
			}
			if (s_pendingClouds.Count > 0)
			{
				List<PendingCloud> list = new List<PendingCloud>(s_pendingClouds);
				s_pendingClouds.Clear();
				foreach (PendingCloud item in list)
				{
					RotCloud(item.Center, item.Plan, item.Radius, item.StacksEach);
				}
			}
			s_popped.Clear();
			if (s_pendingBursts.Count > 0)
			{
				List<PendingBurst> bursts = new List<PendingBurst>(s_pendingBursts);
				s_pendingBursts.Clear();
				SpawnBursts(bursts);
			}
			RotCloudVisual.Update();
			StackCues.Update();
		}

		private static void OnBurst(Vector3 at, int stacks, ZDOID attacker)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			s_pendingBursts.Add(new PendingBurst
			{
				At = at,
				Stacks = stacks,
				Attacker = attacker
			});
		}

		private static void SpawnBursts(List<PendingBurst> bursts)
		{
			//IL_0021: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			PendingBurst pendingBurst = bursts[0];
			ZDOID val = (((Object)(object)Player.m_localPlayer != (Object)null) ? ((Character)Player.m_localPlayer).GetZDOID() : ZDOID.None);
			foreach (PendingBurst burst in bursts)
			{
				if (burst.Stacks > pendingBurst.Stacks)
				{
					pendingBurst = burst;
				}
				if (!(val == ZDOID.None) && !(burst.Attacker != val))
				{
					Ruptures++;
					if (burst.Stacks >= 3)
					{
						FullRuptures++;
					}
					BiggestRupture = Mathf.Max(BiggestRupture, burst.Stacks);
				}
			}
			ModSounds.PlayPop(pendingBurst.At, pendingBurst.Stacks);
			if (Plugin.LogBane.Value)
			{
				Plugin.Log.LogInfo((object)$"Jotun Bane: pop sound for {pendingBurst.Stacks} stack(s), {bursts.Count} pop(s) at once");
			}
			foreach (PendingBurst burst2 in bursts)
			{
				if (burst2.Stacks >= 3)
				{
					RotCloudVisual.Spawn(burst2.At, CloudRadius(burst2.Stacks), Mathf.InverseLerp(3f, 15f, (float)burst2.Stacks));
				}
			}
		}
	}
	internal static class RotCloudVisual
	{
		private class Cloud
		{
			internal ParticleSystem[] Systems;

			internal Light[] Lights;

			internal float[] Intensities;

			internal Light Flash;

			internal float Start;

			internal Transform Holder;

			internal float Spin;

			internal float SpinSeconds;
		}

		private const string Prefab = "bonemass_aoe";

		private const string ParticlesChild = "particles";

		private const float BonemassRadius = 9f;

		private const string GasMaterial = "aoe_smoke";

		private const string MistMaterial = "heavymist_mistlands";

		private static Material s_mist;

		private static bool s_mistMissing;

		private static readonly Color GasColor = new Color(0.25f, 0.5f, 0.1f, 0.6f);

		private const int BasePuffs = 22;

		private const int MaxPuffs = 72;

		private const float BaseGasLifetime = 4f;

		private const float MaxGasLifetime = 6.5f;

		private const float MaxGasAlpha = 0.75f;

		private const float BaseRise = -0.02f;

		private const float MaxRise = -0.15f;

		private const float MaxSpinDegrees = 140f;

		private const float DayDarken = 0.7f;

		private const float NightAlphaBoost = 0.1f;

		private const float NightPuffBoost = 1.35f;

		private const float BlastReach = 0.6f;

		private const float RingReach = 0.9f;

		private const float RingPuffShare = 0.4f;

		private const float EmitSeconds = 1f;

		private const float Lifetime = 10f;

		private static readonly Color FlashColor = new Color(0.6f, 0.9f, 0.25f, 1f);

		private const float FlashIntensity = 2.5f;

		private const float FlashSeconds = 0.6f;

		private static readonly List<Cloud> s_clouds = new List<Cloud>();

		internal static void Spawn(Vector3 position, float radius, float over)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			ZNetScene instance = ZNetScene.instance;
			object obj;
			if (instance == null)
			{
				obj = null;
			}
			else
			{
				GameObject prefab = instance.GetPrefab("bonemass_aoe");
				obj = ((prefab != null) ? prefab.transform.Find("particles") : null);
			}
			Transform val = (Transform)obj;
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"bonemass_aoe/particles not found (game update?); the rot cloud won't show.");
				return;
			}
			GameObject val2 = new GameObject("EnhancedVanillaWeapons_RotCloud");
			val2.SetActive(false);
			val2.transform.position = position;
			Object.Instantiate<GameObject>(((Component)val).gameObject, val2.transform, false);
			if ((Object)(object)val2.GetComponentInChildren<Aoe>(true) != (Object)null || (Object)(object)val2.GetComponentInChildren<ZNetView>(true) != (Object)null)
			{
				Plugin.Log.LogWarning((object)"bonemass_aoe/particles has gameplay parts now; the rot cloud won't show.");
				Object.Destroy((Object)(object)val2);
				return;
			}
			float num = radius / 9f;
			bool daylight = EnvMan.IsDaylight();
			ParticleSystem val3 = null;
			ParticleSystem[] componentsInChildren = val2.GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem val4 in componentsInChildren)
			{
				MainModule main = val4.main;
				((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)0;
				ParticleSystemRenderer component = ((Component)val4).GetComponent<ParticleSystemRenderer>();
				if ((((Object)(object)component != (Object)null && (Object)(object)((Renderer)component).sharedMaterial != (Object)null) ? ((Object)((Renderer)component).sharedMaterial).name : "").Contains("aoe_smoke"))
				{
					ShapeBlast(val4, radius, num, over, daylight);
					val3 = val4;
					continue;
				}
				EmissionModule emission = val4.emission;
				((EmissionModule)(ref emission)).enabled = false;
				SubEmittersModule subEmitters = val4.subEmitters;
				((SubEmittersModule)(ref subEmitters)).enabled = false;
				if ((Object)(object)component != (Object)null)
				{
					((Renderer)component).enabled = false;
				}
			}
			if ((Object)(object)val3 != (Object)null)
			{
				ShapeRing(Object.Instantiate<GameObject>(((Component)val3).gameObject, ((Component)val3).transform.parent).GetComponent<ParticleSystem>(), radius, num, over, daylight);
			}
			ParticleSystem[] componentsInChildren2 = val2.GetComponentsInChildren<ParticleSystem>(true);
			val2.transform.localScale = Vector3.one * num;
			Light val5 = val2.AddComponent<Light>();
			val5.type = (LightType)2;
			val5.color = FlashColor;
			val5.range = radius * 1.5f;
			val5.intensity = 2.5f;
			val5.shadows = (LightShadows)0;
			Light[] componentsInChildren3 = val2.GetComponentsInChildren<Light>(true);
			Cloud cloud = new Cloud
			{
				Systems = componentsInChildren2,
				Lights = componentsInChildren3,
				Intensities = new float[componentsInChildren3.Length],
				Flash = val5,
				Start = Time.time,
				Holder = val2.transform,
				Spin = 140f * over,
				SpinSeconds = Mathf.Lerp(4f, 6.5f, over)
			};
			for (int j = 0; j < componentsInChildren3.Length; j++)
			{
				cloud.Intensities[j] = componentsInChildren3[j].intensity;
			}
			val2.SetActive(true);
			Object.Destroy((Object)(object)val2, 10f);
			s_clouds.Add(cloud);
		}

		private static void ShapeBlast(ParticleSystem system, float radius, float scale, float over, bool daylight)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Expected O, but got Unknown
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Lerp(4f, 6.5f, over);
			MainModule main = system.main;
			((MainModule)(ref main)).startDelay = MinMaxCurve.op_Implicit(0f);
			((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0;
			((MainModule)(ref main)).startLifetime = new MinMaxCurve(num * 0.8f, num);
			float num2 = (daylight ? 0.7f : 1f);
			float num3 = Mathf.Lerp(GasColor.a, 0.75f, over) + (daylight ? 0f : 0.1f);
			((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(GasColor.r * num2, GasColor.g * num2, GasColor.b * num2, Mathf.Clamp01(num3)));
			((MainModule)(ref main)).startSize = new MinMaxCurve(radius * 0.35f / scale, radius * 0.55f / scale);
			((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(Mathf.Lerp(-0.02f, -0.15f, over));
			EmissionModule emission = system.emission;
			((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(0f);
			int num4 = Mathf.RoundToInt(Mathf.Lerp(22f, 72f, over) * (daylight ? 1f : 1.35f));
			((EmissionModule)(ref emission)).SetBursts((Burst[])(object)new Burst[1]
			{
				new Burst(0f, (short)num4)
			});
			((MainModule)(ref main)).maxParticles = Mathf.Max(((MainModule)(ref main)).maxParticles, num4);
			SubEmittersModule subEmitters = system.subEmitters;
			((SubEmittersModule)(ref subEmitters)).enabled = false;
			ShapeModule shape = system.shape;
			((ShapeModule)(ref shape)).enabled = true;
			((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)2;
			((ShapeModule)(ref shape)).radius = 0.5f / scale;
			((ShapeModule)(ref shape)).rotation = new Vector3(-90f, 0f, 0f);
			AnimationCurve val = new AnimationCurve((Keyframe[])(object)new Keyframe[4]
			{
				new Keyframe(0f, 1f),
				new Keyframe(0.15f, 0.35f),
				new Keyframe(0.5f, 0.08f),
				new Keyframe(1f, 0f)
			});
			float num5 = 0.6f * radius / (num * 0.9f * 0.25f) / scale;
			((MainModule)(ref main)).startSpeed = new MinMaxCurve(num5 * 0.8f, num5 * 1.1f);
			VelocityOverLifetimeModule velocityOverLifetime = system.velocityOverLifetime;
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled = true;
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).speedModifier = new MinMaxCurve(1f, val);
			SizeOverLifetimeModule sizeOverLifetime = system.sizeOverLifetime;
			((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = true;
			((SizeOverLifetimeModule)(ref sizeOverLifetime)).size = new MinMaxCurve(1f, AnimationCurve.EaseInOut(0f, 0.5f, 1f, 1.6f));
			Material mist = GetMist();
			ParticleSystemRenderer component = ((Component)system).GetComponent<ParticleSystemRenderer>();
			if ((Object)(object)mist != (Object)null && (Object)(object)component != (Object)null)
			{
				((Renderer)component).sharedMaterial = mist;
			}
		}

		private static void ShapeRing(ParticleSystem system, float radius, float scale, float over, bool daylight)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Lerp(4f, 6.5f, over);
			MainModule main = system.main;
			((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(-0.02f);
			float num2 = 0.9f * radius / (num * 0.9f * 0.25f) / scale;
			((MainModule)(ref main)).startSpeed = new MinMaxCurve(num2 * 0.8f, num2 * 1.1f);
			int num3 = Mathf.RoundToInt(Mathf.Lerp(22f, 72f, over) * 0.4f * (daylight ? 1f : 1.35f));
			((MainModule)(ref main)).maxParticles = Mathf.Max(((MainModule)(ref main)).maxParticles, num3);
			EmissionModule emission = system.emission;
			((EmissionModule)(ref emission)).SetBursts((Burst[])(object)new Burst[1]
			{
				new Burst(0f, (short)num3)
			});
			ShapeModule shape = system.shape;
			((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)10;
			((ShapeModule)(ref shape)).radius = 0.5f / scale;
			((ShapeModule)(ref shape)).arc = 360f;
			((ShapeModule)(ref shape)).rotation = new Vector3(-90f, 0f, 0f);
			((ShapeModule)(ref shape)).randomDirectionAmount = 0.1f;
		}

		private static Material GetMist()
		{
			if ((Object)(object)s_mist != (Object)null || s_mistMissing)
			{
				return s_mist;
			}
			Material[] array = Resources.FindObjectsOfTypeAll<Material>();
			foreach (Material val in array)
			{
				if (((Object)val).name == "heavymist_mistlands")
				{
					s_mist = val;
					break;
				}
			}
			s_mistMissing = (Object)(object)s_mist == (Object)null;
			if (s_mistMissing)
			{
				Plugin.Log.LogWarning((object)"Material heavymist_mistlands not found (game update?); the rot cloud keeps Bonemass's texture.");
			}
			return s_mist;
		}

		internal static void Update()
		{
			for (int num = s_clouds.Count - 1; num >= 0; num--)
			{
				Cloud cloud = s_clouds[num];
				float num2 = Time.time - cloud.Start;
				if ((Object)(object)cloud.Flash == (Object)null)
				{
					s_clouds.RemoveAt(num);
				}
				else
				{
					float num3 = Mathf.Clamp01(1f - num2 / 0.6f);
					if (cloud.Systems != null && num2 >= 1f)
					{
						ParticleSystem[] systems = cloud.Systems;
						foreach (ParticleSystem val in systems)
						{
							if ((Object)(object)val != (Object)null)
							{
								val.Stop(false, (ParticleSystemStopBehavior)1);
							}
						}
						cloud.Systems = null;
						LightFlicker[] componentsInChildren = ((Component)cloud.Flash).GetComponentsInChildren<LightFlicker>(true);
						for (int i = 0; i < componentsInChildren.Length; i++)
						{
							Object.Destroy((Object)(object)componentsInChildren[i]);
						}
					}
					float num4 = Mathf.Clamp01(1f - (num2 - 1f) / 0.6f);
					for (int j = 0; j < cloud.Lights.Length; j++)
					{
						Light val2 = cloud.Lights[j];
						if (!((Object)(object)val2 == (Object)null))
						{
							val2.intensity = (((Object)(object)val2 == (Object)(object)cloud.Flash) ? (2.5f * num3 * num3) : ((num2 < 1f) ? val2.intensity : (cloud.Intensities[j] * num4)));
						}
					}
					float num5 = Mathf.Clamp01(1f - num2 / cloud.SpinSeconds);
					if (cloud.Spin > 0f && num5 > 0f && (Object)(object)cloud.Holder != (Object)null)
					{
						cloud.Holder.Rotate(0f, cloud.Spin * num5 * num5 * Time.deltaTime, 0f, (Space)0);
					}
					if (cloud.Systems == null && num4 <= 0f && num3 <= 0f && (cloud.Spin <= 0f || num5 <= 0f))
					{
						s_clouds.RemoveAt(num);
					}
				}
			}
		}
	}
	internal static class StackTiers
	{
		private static readonly Color[] Colors = (Color[])(object)new Color[5]
		{
			new Color(0.45f, 0.9f, 0.2f, 1f),
			new Color(1f, 0.85f, 0.15f, 1f),
			new Color(1f, 0.5f, 0.05f, 1f),
			new Color(1f, 0.1f, 0.08f, 1f),
			new Color(0.6f, 0.15f, 0.85f, 1f)
		};

		internal static int Tier(int stacks)
		{
			return Mathf.Clamp((stacks - 1) / 3, 0, Colors.Length - 1);
		}

		internal static Color Color(int tier)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			return Colors[Mathf.Clamp(tier, 0, Colors.Length - 1)];
		}
	}
	internal static class StackCues
	{
		private class Glow
		{
			internal Light Light;

			internal int Tier;
		}

		private const float ReadyGap = 0.25f;

		private static bool s_readyPending;

		private static int s_readyStacks;

		private static Vector3 s_readyAt;

		private static float s_nextReady;

		private const float GlowIntensity = 0.8f;

		private const float GlowPerTier = 0.25f;

		private const float GlowPulse = 0.6f;

		private const float GlowPulseSpeed = 4f;

		private const float ScanInterval = 0.2f;

		private const float ScanRange = 40f;

		private const float FlashSeconds = 0.4f;

		private static readonly Dictionary<Character, Glow> s_glows = new Dictionary<Character, Glow>();

		private static readonly Dictionary<Character, float> s_flashes = new Dictionary<Character, float>();

		private static readonly List<Character> s_drop = new List<Character>();

		private static float s_nextScan;

		internal static void OnMilestone(Character character, int stacks)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)character == (Object)null))
			{
				s_flashes[character] = Time.time;
				if (!s_readyPending || stacks > s_readyStacks)
				{
					s_readyPending = true;
					s_readyStacks = stacks;
					s_readyAt = character.GetCenterPoint();
				}
			}
		}

		internal static float Flash(Character character)
		{
			if (!s_flashes.TryGetValue(character, out var value))
			{
				return 0f;
			}
			float num = (Time.time - value) / 0.4f;
			if (num < 1f)
			{
				return (1f - num) * (1f - num);
			}
			s_flashes.Remove(character);
			return 0f;
		}

		internal static void Update()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			if (s_readyPending)
			{
				s_readyPending = false;
				if (Time.time >= s_nextReady)
				{
					s_nextReady = Time.time + 0.25f;
					ModSounds.PlayReady(s_readyAt, s_readyStacks);
				}
			}
			if (Time.time >= s_nextScan)
			{
				s_nextScan = Time.time + 0.2f;
				Scan();
			}
			if (s_glows.Count == 0)
			{
				return;
			}
			float num = 0.5f + 0.5f * Mathf.Sin(Time.time * 4f);
			foreach (Glow value in s_glows.Values)
			{
				if (!((Object)(object)value.Light == (Object)null))
				{
					value.Light.color = StackTiers.Color(value.Tier);
					value.Light.intensity = 0.8f + 0.25f * (float)value.Tier + 0.6f * num;
				}
			}
		}

		private static void Scan()
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			bool flag = Plugin.BaneEnabled.Value && (Object)(object)localPlayer != (Object)null;
			if (flag)
			{
				foreach (Character allCharacter in Character.GetAllCharacters())
				{
					if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.IsPlayer() && !s_glows.ContainsKey(allCharacter) && !allCharacter.IsDead() && !(Vector3.Distance(((Component)localPlayer).transform.position, ((Component)allCharacter).transform.position) > 40f) && JotunBane.GetStacks(allCharacter) >= 3)
					{
						s_glows[allCharacter] = new Glow
						{
							Light = AddGlow(allCharacter)
						};
					}
				}
			}
			s_drop.Clear();
			foreach (KeyValuePair<Character, Glow> s_glow in s_glows)
			{
				Character key = s_glow.Key;
				int num = ((flag && (Object)(object)key != (Object)null && !key.IsDead()) ? JotunBane.GetStacks(key) : 0);
				if (num >= 3)
				{
					s_glow.Value.Tier = StackTiers.Tier(num);
					continue;
				}
				if ((Object)(object)s_glow.Value.Light != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)s_glow.Value.Light).gameObject);
				}
				s_drop.Add(key);
			}
			foreach (Character item in s_drop)
			{
				s_glows.Remove(item);
			}
			s_drop.Clear();
			foreach (KeyValuePair<Character, float> s_flash in s_flashes)
			{
				if ((Object)(object)s_flash.Key == (Object)null || Time.time - s_flash.Value >= 0.4f)
				{
					s_drop.Add(s_flash.Key);
				}
			}
			foreach (Character item2 in s_drop)
			{
				s_flashes.Remove(item2);
			}
		}

		private static Light AddGlow(Character character)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("EnhancedVanillaWeapons_FullGlow");
			val.transform.SetParent(((Component)character).transform, false);
			val.transform.position = character.GetCenterPoint();
			Light obj = val.AddComponent<Light>();
			obj.type = (LightType)2;
			obj.color = StackTiers.Color(0);
			obj.range = Mathf.Clamp(character.GetRadius() * 4f, 3f, 8f);
			obj.intensity = 0.8f;
			obj.shadows = (LightShadows)0;
			return obj;
		}
	}
	internal static class StackPips
	{
		private const string RowName = "EnhancedVanillaWeapons_JotunPips";

		private const string CountName = "Count";

		private const int Slots = 3;

		private const float PulseSpeed = 9f;

		private const float PulseGrowth = 0.35f;

		private const float HaloScale = 2.2f;

		private const float HaloAlpha = 0.25f;

		private const float HaloAlphaPulse = 0.35f;

		private const float GlowyTier = 3f;

		private const float GlowyHaloBonus = 0.25f;

		private const float PeakWhiten = 0.4f;

		private const float FlashGrowth = 1f;

		private const float Gap = 3f;

		private const float CountFontScale = 0.8f;

		private static readonly FieldInfo HudsField = AccessTools.Field(typeof(EnemyHud), "m_huds");

		private static readonly FieldInfo GuiField = AccessTools.Field(AccessTools.Inner(typeof(EnemyHud), "HudData"), "m_gui");

		internal static void Update(EnemyHud hud)
		{
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Expected O, but got Unknown
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			if (GuiField == null || !(HudsField?.GetValue(hud) is IDictionary dictionary))
			{
				return;
			}
			bool value = Plugin.BaneEnabled.Value;
			float num = 0.5f + 0.5f * Mathf.Sin(Time.time * 9f);
			foreach (DictionaryEntry item in dictionary)
			{
				object key = item.Key;
				Character val = (Character)((key is Character) ? key : null);
				object? value2 = GuiField.GetValue(item.Value);
				GameObject val2 = (GameObject)((value2 is GameObject) ? value2 : null);
				if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || !val2.activeSelf || val.IsPlayer())
				{
					continue;
				}
				Transform val3 = val2.transform.Find("Health");
				if ((Object)(object)val3 == (Object)null)
				{
					continue;
				}
				int num2 = (value ? JotunBane.GetStacks(val) : 0);
				Transform val4 = val3.Find("EnhancedVanillaWeapons_JotunPips");
				if ((Object)(object)val4 == (Object)null)
				{
					if (num2 == 0)
					{
						continue;
					}
					val4 = BuildRow((RectTransform)val3, val2.transform);
				}
				bool flag = num2 >= 3;
				int num3 = StackTiers.Tier(num2);
				int num4 = ((num2 > 0) ? ((num2 - 1) % 3 + 1) : 0);
				float num5 = (flag ? StackCues.Flash(val) : 0f);
				float num6 = (flag ? (Mathf.Max(num, num5) * 0.4f) : 0f);
				float num7 = (flag ? (1f + 0.35f * num + 1f * num5) : 1f);
				float num8 = Mathf.Clamp01(0.25f + 0.35f * Mathf.Max(num, num5) + (((float)num3 >= 3f) ? 0.25f : 0f));
				for (int i = 0; i < 3; i++)
				{
					Transform child = val4.GetChild(i);
					bool flag2 = i < num4 || num3 > 0;
					((Component)child).gameObject.SetActive(flag2);
					if (flag2)
					{
						Color val5 = StackTiers.Color((i < num4) ? num3 : (num3 - 1));
						Color color = Color.Lerp(val5, Color.white, num6);
						child.localScale = Vector3.one * num7;
						Transform child2 = child.GetChild(0);
						((Component)child2).gameObject.SetActive(flag);
						if (flag)
						{
							((Graphic)((Component)child2).GetComponent<Image>()).color = new Color(val5.r, val5.g, val5.b, num8);
						}
						((Graphic)((Component)child.GetChild(1)).GetComponent<Image>()).color = color;
					}
				}
				Transform obj = val4.Find("Count");
				TMP_Text val6 = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null);
				if ((Object)(object)val6 != (Object)null)
				{
					bool flag3 = num2 > 3;
					((Component)val6).gameObject.SetActive(flag3);
					if (flag3)
					{
						val6.text = "x" + num2;
						((Graphic)val6).color = Color.Lerp(StackTiers.Color(num3), Color.white, 0.25f);
					}
				}
			}
		}

		private static Transform BuildRow(RectTransform health, Transform gui)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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)
			//IL_0046: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Expected O, but got Unknown
			//IL_0196: Expected O, but got Unknown
			Rect rect = health.rect;
			float num = Mathf.Clamp(((Rect)(ref rect)).height, 6f, 14f);
			RectTransform val = (RectTransform)new GameObject("EnhancedVanillaWeapons_JotunPips", new Type[1] { typeof(RectTransform) }).transform;
			((Transform)val).SetParent((Transform)(object)health, false);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(1f, 0.5f);
			val.anchorMax = val2;
			val.anchorMin = val2;
			val.pivot = new Vector2(0f, 0.5f);
			val.anchoredPosition = new Vector2(3f + num * 0.2f, 0f);
			val.sizeDelta = new Vector2(3f * (num + 3f), num);
			for (int i = 0; i < 3; i++)
			{
				GameObject val3 = new GameObject("Pip" + i, new Type[1] { typeof(RectTransform) });
				RectTransform val4 = (RectTransform)val3.transform;
				((Transform)val4).SetParent((Transform)(object)val, false);
				((Vector2)(ref val2))..ctor(0f, 0.5f);
				val4.anchorMax = val2;
				val4.anchorMin = val2;
				val4.sizeDelta = new Vector2(num * 0.75f, num * 0.75f);
				val4.anchoredPosition = new Vector2((float)i * (num + 3f) + num * 0.5f, 0f);
				((Transform)val4).localRotation = Quaternion.Euler(0f, 0f, 45f);
				AddDiamond(val4, "Halo", 2.2f).SetActive(false);
				AddDiamond(val4, "Core", 1f);
				val3.SetActive(false);
			}
			AddCount(val, gui, num);
			return (Transform)(object)val;
		}

		private static void AddCount(RectTransform row, Transform gui, float size)
		{
			//IL_0056: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			Transform val = gui.Find("Name");
			TMP_Text val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<TMP_Text>() : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			GameObject val3 = Object.Instantiate<GameObject>(((Component)val).gameObject, (Transform)(object)row, false);
			((Object)val3).name = "Count";
			foreach (Transform item in val3.transform)
			{
				Object.Destroy((Object)(object)((Component)item).gameObject);
			}
			RectTransform val4 = (RectTransform)val3.transform;
			Vector2 val5 = default(Vector2);
			((Vector2)(ref val5))..ctor(0f, 0.5f);
			val4.anchorMax = val5;
			val4.anchorMin = val5;
			val4.pivot = new Vector2(0f, 0.5f);
			val4.anchoredPosition = new Vector2(3f * (size + 3f) + 3f, 0f);
			val4.sizeDelta = new Vector2(size * 4f, size * 2f);
			((Transform)val4).localRotation = Quaternion.identity;
			((Transform)val4).localScale = Vector3.one;
			TMP_Text component = val3.GetComponent<TMP_Text>();
			component.fontSize = val2.fontSize * 0.8f;
			component.enableAutoSizing = false;
			component.alignment = (TextAlignmentOptions)513;
			component.textWrappingMode = (TextWrappingModes)0;
			((Graphic)component).raycastTarget = false;
			val3.SetActive(false);
		}

		private static GameObject AddDiamond(RectTransform pip, string name, float scale)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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)
			//IL_002c: 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_0037: 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)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)pip, false);
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			val2.sizeDelta = Vector2.zero;
			((Transform)val2).localScale = Vector3.one * scale;
			Image obj = val.AddComponent<Image>();
			((Graphic)obj).color = StackTiers.Color(0);
			((Graphic)obj).raycastTarget = false;
			return val;
		}
	}
	[HarmonyPatch(typeof(Character), "Awake")]
	internal static class CharacterAwakePatch
	{
		private static void Postfix(Character __instance, ZNetView ___m_nview)
		{
			JotunBane.Register(__instance, ___m_nview);
		}
	}
	[HarmonyPatch(typeof(Attack), "OnAttackTrigger")]
	internal static class BaneAttackTriggerPatch
	{
		private static void Prefix(Attack __instance, Humanoid ___m_character)
		{
			JotunBane.BeforeAttackTrigger(__instance, ___m_character);
		}

		private static void Finalizer()
		{
			JotunBane.AfterAttackTrigger();
		}
	}
	[HarmonyPatch(typeof(Character), "Damage")]
	internal static class BaneDamagePatch
	{
		private static void Prefix(Character __instance, HitData hit)
		{
			JotunBane.OnDamage(__instance, hit);
		}
	}
	[HarmonyPatch(typeof(Character), "RPC_Damage")]
	internal static class BaneRpcDamagePatch
	{
		private static void Prefix(Character __instance, HitData hit, ZNetView ___m_nview, out JotunBane.HitPlan __state)
		{
			__state = JotunBane.PlanHit(__instance, ___m_nview, hit);
		}

		private static void Postfix(Character __instance, ZNetView ___m_nview, JotunBane.HitPlan __state)
		{
			JotunBane.FinishHit(__instance, ___m_nview, __state);
		}

		private static void Finalizer()
		{
			JotunBane.s_poisonMode = JotunBane.PoisonMode.Vanilla;
		}
	}
	[HarmonyPatch(typeof(Character), "AddPoisonDamage")]
	internal static class BaneAddPoisonPatch
	{
		private static bool Prefix(Character __instance, SEMan ___m_seman, float damage, short variant)
		{
			return JotunBane.AddPoison(__instance, ___m_seman, damage, variant);
		}
	}
	[HarmonyPatch(typeof(EnemyHud), "UpdateHuds")]
	internal static class EnemyHudPatch
	{
		private static void Postfix(EnemyHud __instance)
		{
			StackPips.Update(__instance);
		}
	}
	[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[]
	{
		typeof(ItemData),
		typeof(int),
		typeof(bool),
		typeof(float),
		typeof(int),
		typeof(bool)
	})]
	internal static class BaneTooltipPatch
	{
		private const string Line = "\n\n<color=orange>Rot</color>: every hit adds a rot stack, making the poison stronger.\n\n<color=orange>Rupture</color> (secondary attack): bursts it all at once, harder per stack, and from 3+ stacks releases a rot cloud explosion.";

		private static void Postfix(ItemData item, bool appending, ref string __result)
		{
			if (!appending && Plugin.BaneEnabled.Value && JotunBane.IsBane(item))
			{
				string description = item.m_shared.m_description;
				if (__result.StartsWith(description, StringComparison.Ordinal))
				{
					__result = __result.Insert(description.Length, "\n\n<color=orange>Rot</color>: every hit adds a rot stack, making the poison stronger.\n\n<color=orange>Rupture</color> (secondary attack): bursts it all at once, harder per stack, and from 3+ stacks releases a rot cloud explosion.");
				}
			}
		}
	}
	internal static class ModSounds
	{
		private class Fade
		{
			internal AudioSource Source;

			internal float StartVolume;

			internal float Progress;

			internal float Seconds;
		}

		private const string MixerSourcePrefab = "sfx_perfect_dodge";

		private const float GlideVolume = 0.24f;

		private static readonly MethodInfo SetData = typeof(AudioClip).GetMethod("SetData", new Type[2]
		{
			typeof(float[]),
			typeof(int)
		});

		private static AudioClip s_glide;

		private static AudioMixerGroup s_sfxGroup;

		private static readonly List<Fade> s_fades = new List<Fade>();

		private static readonly float[] PopVolumes = new float[3] { 0.6f, 0.85f, 1f };

		private static readonly float[] PopPitches = new float[3] { 1.15f, 1f, 0.92f };

		private static AudioClip s_pop;

		private static AudioClip s_popFull;

		private const float MaxStacksPitch = 0.8f;

		private const float MaxLayerVolume = 0.75f;

		private const float MaxBoomVolume = 0.5f;

		private const float MaxDoubleVolume = 0.8f;

		private const float HeavyPitchAtMax = 0.94f;

		private static AudioClip s_popHeavy;

		private static AudioClip s_popBoom;

		private const float ReadyVolume = 0.5f;

		private const float MaxReadyVolume = 0.7f;

		private static AudioClip s_ready;

		private static AudioClip s_readyMax;

		private static bool s_sfxSearched;

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

		internal static AudioSource PlayGlide(Player player)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s_glide == (Object)null)
			{
				s_glide = LoadWav("ghost_glide.wav");
			}
			if ((Object)(object)s_glide == (Object)null)
			{
				return null;
			}
			if (!s_sfxSearched)
			{
				s_sfxGroup = FindSfxGroup();
			}
			GameObject val = new GameObject("EnhancedVanillaWeapons_GlideSound");
			val.transform.SetParent(((Component)player).transform, false);
			val.transform.localPosition = Vector3.up * 1f;
			AudioSource obj = val.AddComponent<AudioSource>();
			obj.playOnAwake = false;
			obj.spatialBlend = 1f;
			obj.minDistance = 3f;
			obj.maxDistance = 30f;
			obj.outputAudioMixerGroup = s_sfxGroup;
			obj.clip = s_glide;
			obj.volume = 0.24f;
			obj.Play();
			Object.Destroy((Object)(object)val, s_glide.length + 0.5f);
			return obj;
		}

		internal static void PlayPop(Vector3 position, int stacks)
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			if (stacks <= 0)
			{
				return;
			}
			int num = Mathf.Clamp(stacks, 1, PopVolumes.Length) - 1;
			bool num2 = num == PopVolumes.Length - 1;
			if (num2 && (Object)(object)s_popFull == (Object)null)
			{
				s_popFull = LoadWav("rot_pop_full.wav");
			}
			if (!num2 && (Object)(object)s_pop == (Object)null)
			{
				s_pop = LoadWav("rot_pop.wav");
			}
			if (!num2)
			{
				PlayAt(s_pop, position, PopVolumes[num], PopPitches[num]);
				return;
			}
			float num3 = Mathf.InverseLerp(3f, 15f, (float)stacks);
			float num4 = Mathf.Lerp(PopPitches[num], 0.8f, num3);
			PlayAt(s_popFull, position, PopVolumes[num], num4);
			if (!(num3 <= 0f))
			{
				PlayAt(s_popFull, position, 0.8f * num3, num4 * 1.04f);
				if ((Object)(object)s_popHeavy == (Object)null)
				{
					s_popHeavy = LoadWav("rot_pop_heavy.wav");
				}
				PlayAt(s_popHeavy, position, 0.75f * num3, num4 * 0.94f / 0.8f);
				if ((Object)(object)s_popBoom == (Object)null)
				{
					s_popBoom = LoadWav("rot_pop_boom.wav");
				}
				PlayAt(s_popBoom, position, 0.5f * num3, 1f);
			}
		}

		internal static void PlayReady(Vector3 position, int stacks)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s_ready == (Object)null)
			{
				s_ready = LoadWav("rot_ready.wav");
			}
			if ((Object)(object)s_readyMax == (Object)null)
			{
				s_readyMax = LoadWav("rot_ready_max.wav");
			}
			float num = Mathf.InverseLerp(3f, 15f, (float)stacks);
			if (num < 1f)
			{
				PlayAt(s_ready, position, 0.5f * (1f - num), 1f);
			}
			if (num > 0f)
			{
				PlayAt(s_readyMax, position, 0.7f * num, 1f);
			}
		}

		private static void PlayAt(AudioClip clip, Vector3 position, float volume, float pitch)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			if (!((Object)(object)clip == (Object)null))
			{
				if (!s_sfxSearched)
				{
					s_sfxGroup = FindSfxGroup();
				}
				GameObject val = new GameObject("EnhancedVanillaWeapons_Sound");
				val.transform.position = position;
				AudioSource val2 = val.AddComponent<AudioSource>();
				val2.playOnAwake = false;
				val2.spatialBlend = 1f;
				val2.minDistance = 3f;
				val2.maxDistance = 30f;
				val2.outputAudioMixerGroup = s_sfxGroup;
				val2.clip = clip;
				val2.volume = volume;
				val2.pitch = pitch;
				val2.Play();
				Object.Destroy((Object)val, clip.length / val2.pitch + 0.5f);
			}
		}

		internal static void FadeOut(AudioSource source, float seconds)
		{
			if (!((Object)(object)source == (Object)null))
			{
				s_fades.Add(new Fade
				{
					Source = source,
					StartVolume = source.volume,
					Seconds = Mathf.Max(0.01f, seconds)
				});
			}
		}

		internal static void Update()
		{
			for (int num = s_fades.Count - 1; num >= 0; num--)
			{
				Fade fade = s_fades[num];
				if ((Object)(object)fade.Source == (Object)null)
				{
					s_fades.RemoveAt(num);
				}
				else
				{
					fade.Progress += Time.deltaTime / fade.Seconds;
					if (fade.Progress >= 1f)
					{
						Object.Destroy((Object)(object)((Component)fade.Source).gameObject);
						s_fades.RemoveAt(num);
					}
					else
					{
						float num2 = 1f - fade.Progress;
						fade.Source.volume = fade.StartVolume * num2 * num2;
					}
				}
			}
		}

		private static AudioMixerGroup FindSfxGroup()
		{
			s_sfxSearched = true;
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.GetPrefab("sfx_perfect_dodge") : null);
			AudioSource val2 = (((Object)(object)val != (Object)null) ? val.GetComponentInChildren<AudioSource>(true) : null);
			if ((Object)(object)val2 == (Object)null)
			{
				Plugin.Log.LogWarning((object)"No mixer group from sfx_perfect_dodge; mod sounds ignore the SFX volume.");
			}
			if (!((Object)(object)val2 != (Object)null))
			{
				return null;
			}
			return val2.outputAudioMixerGroup;
		}

		private static AudioClip LoadWav(string name)
		{
			if (s_failedWavs.Contains(name))
			{
				return null;
			}
			try
			{
				using Stream stream = typeof(ModSounds).Assembly.GetManifestResourceStream("EnhancedVanillaWeapons.Sounds." + name);
				if (stream == null)
				{
					throw new FileNotFoundException("embedded resource missing", name);
				}
				using BinaryReader reader = new BinaryReader(stream);
				return ParseWav(reader, name);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Couldn't load sound " + name + ": " + ex.Message));
				s_failedWavs.Add(name);
				return null;
			}
		}

		private static AudioClip ParseWav(BinaryReader reader, string name)
		{
			if (new string(reader.ReadChars(4)) != "RIFF")
			{
				throw new InvalidDataException("not RIFF");
			}
			reader.ReadInt32();
			if (new string(reader.ReadChars(4)) != "WAVE")
			{
				throw new InvalidDataException("not WAVE");
			}
			int num = 0;
			int num2 = 0;
			while (reader.BaseStream.Position < reader.BaseStream.Length)
			{
				string text = new string(reader.ReadChars(4));
				int num3 = reader.ReadInt32();
				if (text == "fmt ")
				{
					short num4 = reader.ReadInt16();
					num = reader.ReadInt16();
					num2 = reader.ReadInt32();
					reader.ReadInt32();
					reader.ReadInt16();
					short num5 = reader.ReadInt16();
					if (num4 != 1 || num5 != 16)
					{
						throw new InvalidDataException($"need 16-bit PCM, got format {num4}, {num5} bit");
					}
					reader.BaseStream.Seek(num3 - 16, SeekOrigin.Current);
					continue;
				}
				if (text == "data")
				{
					int num6 = num3 / 2;
					float[] array = new float[num6];
					for (int i = 0; i < num6; i++)
					{
						array[i] = (float)reader.ReadInt16() / 32768f;
					}
					AudioClip val = AudioClip.Create(name, num6 / num, num, num2, false);
					SetData.Invoke(val, new object[2] { array, 0 });
					return val;
				}
				reader.BaseStream.Seek(num3 + (num3 & 1), SeekOrigin.Current);
			}
			throw new InvalidDataException("no data chunk");
		}
	}
	[BepInPlugin("Iteravio.EnhancedVanillaWeapons", "EnhancedVanillaWeapons", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "Iteravio.EnhancedVanillaWeapons";

		public const string PluginName = "EnhancedVanillaWeapons";

		public const string PluginVersion = "1.1.0";

		private const string SkollAndHatiSection = "Skoll and Hati";

		private const string JotunBaneSection = "Jotun Bane";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> StrikeEnabled;

		internal static ConfigEntry<int> StrikeEitrCost;

		internal static ConfigEntry<int> StrikeStaminaCost;

		internal static ConfigEntry<float> StrikeBackstabMultiplier;

		internal static ConfigEntry<float> StrikeCooldownSeconds;

		internal static ConfigEntry<int> StrikeRangeMeters;

		internal static ConfigEntry<bool> BaneEnabled;

		internal static ConfigEntry<int> BaneBluntPerStack;

		internal static ConfigEntry<float> BanePoisonMultiplier;

		internal static ConfigEntry<float> BaneCloudRadius;

		internal static ConfigEntry<float> BaneCloudRadiusPerExtra;

		internal static ConfigEntry<int> BaneExtraPoison;

		internal static ConfigEntry<int> BaneExtraDotPercent;

		internal static ConfigEntry<int> BaneRuptureGrowthPercent;

		internal static ConfigEntry<bool> LogStrikes;

		internal static ConfigEntry<bool> LogBane;

		private const string SyncedTag = "[Synced with Server]";

		private const string NotSyncedTag = "[Not synced with Server]";

		private void Awake()
		{
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			StrikeEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Skoll and Hati", "ShadowStrikeEnabled", true, Synced("The secondary attack turns you to smoke that quickly glides behind the enemy and stabs its back.", null, 6));
			StrikeEitrCost = ((BaseUnityPlugin)this).Config.Bind<int>("Skoll and Hati", "ShadowStrikeEitrCost", 25, Synced("Shadow Strike eitr cost. If you have less eitr than this, the secondary attack stays as the vanilla leap.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), 5));
			StrikeStaminaCost = ((BaseUnityPlugin)this).Config.Bind<int>("Skoll and Hati", "ShadowStrikeStaminaCost", 20, Synced("Shadow Strike stamina cost (lowered by knife skill like any attack).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), 4));
			StrikeBackstabMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Skoll and Hati", "ShadowStrikeBackstabMultiplier", 3f, Synced("Damage multiplier when a Shadow Strike lands as a sneak attack.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), 3));
			StrikeCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Skoll and Hati", "ShadowStrikeCooldownSeconds", 3f, Synced("Shadow Strike cooldown (seconds).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 15f), 2));
			StrikeRangeMeters = ((BaseUnityPlugin)this).Config.Bind<int>("Skoll and Hati", "ShadowStrikeRangeMeters", 20, Synced("Shadow Strike range (meters).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(4, 30), 1));
			BaneEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Jotun Bane", "PoisonStacksEnabled", true, Synced("Every hit adds a rot stack (up to 15), making the poison stronger, and keeps the stacks going for 8 more seconds.\n\nThe secondary attack ruptures the stacks, dealing all remaining poison at once plus extra poison & blunt damage per stack. A rupture of 3 or more releases a rot cloud that spreads stacks to nearby enemies.", null, 8));
			BanePoisonMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Jotun Bane", "RupturePoisonMultiplier", 1.5f, Synced("How much harder the remaining poison hits when ruptured.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f), 7));
			BaneBluntPerStack = ((BaseUnityPlugin)this).Config.Bind<int>("Jotun Bane", "RuptureBluntPerStack", 20, Synced("Blunt damage a rupture deals per stack. Lands even on poison-immune enemies.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), 6));
			BaneExtraPoison = ((BaseUnityPlugin)this).Config.Bind<int>("Jotun Bane", "RupturePoisonPerStack", 20, Synced("Extra poison damage a rupture deals per stack, on top of the stacked poison.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), 5));
			BaneRuptureGrowthPercent = ((BaseUnityPlugin)this).Config.Bind<int>("Jotun Bane", "PercentRuptureDamageIncreasePerExtraStack", 2, Synced("How much bigger each stack past 3 makes the rupture's per-stack blunt and poison.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), 4));
			BaneExtraDotPercent = ((BaseUnityPlugin)this).Config.Bind<int>("Jotun Bane", "PercentPoisonPerSecondIncreasePerExtraStack", 5, Synced("How much stronger the poison gets with each stack past 3.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), 2));
			BaneCloudRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Jotun Bane", "RotCloudRadiusMeters", 7.5f, Synced("Rot cloud radius at 3 stacks (meters).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f), 1));
			BaneCloudRadiusPerExtra = ((BaseUnityPlugin)this).Config.Bind<float>("Jotun Bane", "RotCloudRadiusMetersPerExtraStack", 1.5f, Synced("How much the rot cloud's radius grows per stack past 3 (meters).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), 0));
			LogStrikes = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogStrikes", false, "Log each Shadow Strike. Should be disabled, unless you are testing something? : D [Not synced with Server]");
			LogBane = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogJotunBane", false, "Log Jotun Bane stacks and ruptures (on the machine that controls the enemy). Should be disabled, unless you are testing something? : D [Not synced with Server]");
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new StatusCommand());
			new Harmony("Iteravio.EnhancedVanillaWeapons").PatchAll();
			Log.LogInfo((object)("Ready: " + GetSettingsSummary()));
		}

		private void Update()
		{
			Glide.Update();
			Ghosts.Update();
			TunnelVision.Update();
			ModSounds.Update();
			JotunBane.Update();
		}

		private static ConfigDescription Synced(string description, AcceptableValueBase range, int order)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			return new ConfigDescription(description + " [Synced with Server]", range, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				Order = order,
				ShowRangeAsPercent = false
			} });
		}

		internal static string GetSettingsSummary()
		{
			return (StrikeEnabled.Value ? ($"Shadow Strike on, {StrikeEitrCost.Value} eitr, {StrikeStaminaCost.Value} stamina, {StrikeBackstabMultiplier.Value:0.#}x backstab, " + $"{StrikeCooldownSeconds.Value:0.#} s cooldown, {StrikeRangeMeters.Value} m range") : "Shadow Strike off (vanilla leap)") + "; " + (BaneEnabled.Value ? ($"Jotun Bane stacks on, {BanePoisonMultiplier.Value:0.##}x rupture poison, {BaneBluntPerStack.Value} blunt and {BaneExtraPoison.Value} poison per stack, " + $"+{BaneRuptureGrowthPercent.Value}% rupture and +{BaneExtraDotPercent.Value}% poison per second per extra stack, {BaneCloudRadius.Value:0.#} m rot cloud (+{BaneCloudRadiusPerExtra.Value:0.#} m per extra stack)") : "Jotun Bane stacks off");
		}

		internal static string GetSettingsSource()
		{
			ZNet instance = ZNet.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return "local config";
			}
			if (!instance.IsServer())
			{
				return "synced from host";
			}
			return "this machine (host/solo)";
		}
	}
	internal class StatusCommand : ConsoleCommand
	{
		public override string Name => "enhancedvanillaweapons";

		public override string Help => "Show EnhancedVanillaWeapons settings in effect and this session's Shadow Strike and Jotun Bane counts";

		public override void Run(string[] args, Terminal context)
		{
			if (!((Object)(object)context == (Object)null))
			{
				context.AddString("EnhancedVanillaWeapons 1.1.0");
				context.AddString("Settings (" + Plugin.GetSettingsSource() + "): " + Plugin.GetSettingsSummary());
				context.AddString($"This session: {ShadowStrike.Strikes} Shadow Strikes ({ShadowStrike.Hits} hit, {ShadowStrike.Misses} missed), {ShadowStrike.Fizzles} fizzles");
				context.AddString($"This session: {JotunBane.Ruptures} Jotun Bane ruptures ({JotunBane.FullRuptures} at 3+ stacks, biggest {JotunBane.BiggestRupture})");
			}
		}
	}
	internal static class ShadowStrike
	{
		private class HitDistanceComparer : IComparer<RaycastHit>
		{
			internal static readonly HitDistanceComparer Instance = new HitDistanceComparer();

			public int Compare(RaycastHit a, RaycastHit b)
			{
				return ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance);
			}
		}

		private const string KnifeName = "$item_knife_skollandhati";

		private const string SmokePrefab = "vfx_odin_despawn";

		private const string ArrivalSound = "sfx_perfect_dodge";

		private const float AimAssistRadius = 0.5f;

		private const float AimConeDegrees = 6f;

		private const float WindupHoldSpeed = 0.25f;

		private const float WindupArrivalSpeed = 10f;

		private const float FizzleInterval = 0.6f;

		private const float BehindGap = 0.5f;

		private const float MaxHeightDifference = 1.5f;

		private const float PreferredMaxUphill = 0.4f;

		private const float MaxGroundSlope = 50f;

		private const float SwingReachMargin = 0.6f;

		private const float MaxSwingReach = 5f;

		private const float CatchUpGap = 1.8f;

		private static readonly float[] SpotAngles = new float[5] { 0f, 35f, -35f, 70f, -70f };

		internal static int Strikes;

		internal static int Fizzles;

		internal static int Hits;

		internal static int Misses;

		private static Attack s_activeAttack;

		private static Attack s_pendingAttack;

		private static Character s_pendingTarget;

		private static float s_pressTime;

		private static Vector3 s_armedSpot;

		private static float s_readyTime;

		private static float s_nextFizzleTime;

		private static Character s_strikeTarget;

		private static bool s_strikeLanded;

		private static string s_otherVictims = "";

		private static int s_solidMask;

		private static int s_characterMask;

		private static readonly RaycastHit[] s_hits = (RaycastHit[])(object)new RaycastHit[32];

		private static readonly Collider[] s_overlaps = (Collider[])(object)new Collider[32];

		private static readonly FieldRef<Character, float> MaxAirAltitude = AccessTools.FieldRefAccess<Character, float>("m_maxAirAltitude");

		private const float LocalEffectLifetime = 8f;

		private static void InitMasks()
		{
			if (s_solidMask == 0)
			{
				s_solidMask = LayerMask.GetMask(new string[7] { "Default", "static_solid", "Default_small", "piece", "terrain", "blocker", "vehicle" });
				s_characterMask = LayerMask.GetMask(new string[5] { "character", "character_net", "character_ghost", "hitbox", "character_noenv" });
			}
		}

		internal static bool IsStrikeWeapon(ItemData weapon)
		{
			return weapon?.m_shared.m_name == "$item_knife_skollandhati";
		}

		internal static bool HasEitrForStrike(Player player)
		{
			int value = Plugin.StrikeEitrCost.Value;
			if (value > 0)
			{
				if (((Character)player).GetMaxEitr() > 0f)
				{
					return ((Character)player).HaveEitr((float)value + 0.1f);
				}
				return false;
			}
			return true;
		}

		internal static Character TryArm(Player player)
		{
			if (Time.time < s_readyTime)
			{
				return Fizzle(player, "on cooldown");
			}
			Character val = FindTarget(player);
			if ((Object)(object)val == (Object)null)
			{
				return Fizzle(player, "no target");
			}
			if (!TryFindSpotBehind(player, val, out s_armedSpot, out var _))
			{
				return Fizzle(player, "no safe spot behind " + val.m_name);
			}
			return val;
		}

		internal static void OnAttackStarted(Player player, Attack attack, Character target)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			s_activeAttack = attack;
			s_pendingAttack = attack;
			s_pendingTarget = target;
			s_pressTime = Time.time;
			s_readyTime = Time.time + Plugin.StrikeCooldownSeconds.Value;
			((Character)player).UseEitr((float)Plugin.StrikeEitrCost.Value);
			s_otherVictims = "";
			Strikes++;
			Glide.Begin(player, target, s_armedSpot);
			if (Plugin.LogStrikes.Value)
			{
				Plugin.Log.LogInfo((object)$"Shadow Strike behind {target.m_name}, height difference {((Component)target).transform.position.y - s_armedSpot.y:0.0} m");
			}
		}

		internal static void OnAttackUpdate(Attack attack, ZSyncAnimation zanim)
		{
			if (attack == s_pendingAttack && (Object)(object)zanim != (Object)null)
			{
				zanim.SetSpeed(Glide.Active ? 0.25f : 10f);
			}
		}

		internal static void BeforeAttackTrigger(Attack attack, ZSyncAnimation zanim)
		{
			if (attack != s_pendingAttack)
			{
				return;
			}
			Character val = s_pendingTarget;
			s_pendingAttack = null;
			s_pendingTarget = null;
			if (zanim != null)
			{
				zanim.SetSpeed(1f);
			}
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				Glide.Finish(localPlayer);
				if (!((Object)(object)val == (Object)null) && !val.IsDead())
				{
					CatchUp(localPlayer, val);
					FaceTarget(localPlayer, val);
					ShapeSwing(attack, localPlayer, val);
					s_strikeTarget = val;
					s_strikeLanded = false;
				}
			}
		}

		private static void CatchUp(Player player, Character target)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			CapsuleCollider collider = target.GetCollider();
			Vector3 centerPoint = ((Character)player).GetCenterPoint();
			Vector3 val = (((Object)(object)collider != (Object)null) ? ((Collider)collider).ClosestPoint(centerPoint) : target.GetCenterPoint());
			if (!(Vector3.Distance(centerPoint, val) <= 1.8f) && TryFindSpotBehind(player, target, out var spot, out var _))
			{
				Teleport(player, spot, target);
				if (Plugin.LogStrikes.Value)
				{
					Plugin.Log.LogInfo((object)("Caught up with " + target.m_name + " before the stab"));
				}
			}
		}

		private static void ShapeSwing(Attack attack, Player player, Character target)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			attack.m_hitTerrain = false;
			attack.m_maxYAngle = 90f;
			CapsuleCollider collider = target.GetCollider();
			Vector3 centerPoint = ((Character)player).GetCenterPoint();
			Vector3 val = (((Object)(object)collider != (Object)null) ? ((Collider)collider).ClosestPoint(centerPoint) : target.GetCenterPoint());
			float num = Vector3.Distance(centerPoint, val) + 0.6f;
			attack.m_attackRange = Mathf.Clamp(num, attack.m_attackRange, 5f);
		}

		internal static void AfterAttackTrigger()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			Character val = s_strikeTarget;
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			s_strikeTarget = null;
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				if (s_strikeLanded)
				{
					Hits++;
				}
				else
				{
					Misses++;
				}
				if (Plugin.LogStrikes.Value)
				{
					float num = Vector3.Distance(((Component)localPlayer).transform.position, ((Component)val).transform.position) - val.GetRadius();
					string arg = (s_strikeLanded ? "" : ((s_otherVictims.Length > 0) ? (", struck " + s_otherVictims + " instead") : ", struck no creature"));
					Plugin.Log.LogInfo((object)(string.Format("{0} {1} {2:0.00} s after the press, ", s_strikeLanded ? "Hit" : "MISSED", val.m_name, Time.time - s_pressTime) + $"{num:0.0} m from its edge, height difference {((Component)val).transform.position.y - ((Component)localPlayer).transform.position.y:0.0} m{arg}"));
				}
			}
		}

		internal static void OnDamage(Character victim, HitData hit)
		{
			if (!((Object)(object)s_strikeTarget == (Object)null) && !((Object)(object)hit.GetAttacker() != (Object)(object)Player.m_localPlayer))
			{
				if (hit.m_backstabBonus > 1f)
				{
					hit.m_backstabBonus = Plugin.StrikeBackstabMultiplier.Value;
				}
				if ((Object)(object)victim == (Object)(object)s_strikeTarget)
				{
					s_strikeLanded = true;
				}
				else
				{
					s_otherVictims = s_otherVictims + ((s_otherVictims.Length > 0) ? ", " : "") + victim.m_name;
				}
			}
		}

		internal static void OnAttackStop(Attack attack)
		{
			if (attack == s_activeAttack)
			{
				s_activeAttack = null;
				s_pendingAttack = null;
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null)
				{
					Glide.Finish(localPlayer);
				}
			}
		}

		internal static bool SuppressesMovement(Character character)
		{
			if (s_activeAttack != null && (Object)(object)character == (Object)(object)Player.m_localPlayer)
			{
				return !s_activeAttack.IsDone();
			}
			return false;
		}

		private static Character Fizzle(Player player, string reason)
		{
			if (Time.time < s_nextFizzleTime)
			{
				return null;
			}
			s_nextFizzleTime = Time.time + 0.6f;
			Fizzles++;
			if (Plugin.LogStrikes.Value)
			{
				Plugin.Log.LogInfo((object)("Fizzle: " + reason));
			}
			return null;
		}

		internal static void FaceTarget(Player player, Character target)
		{
			//IL_0001: 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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0046: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = target.GetCenterPoint() - ((Character)player).GetCenterPoint();
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(val.x, 0f, val.z);
			if (!(((Vector3)(ref val2)).sqrMagnitude < 0.0001f))
			{
				Quaternion rotation = Quaternion.LookRotation(val2);
				((Component)player).transform.rotation = rotation;
				Rigidbody component = ((Component)player).GetComponent<Rigidbody>();
				if ((Object)(object)component != (Object)null)
				{
					component.rotation = rotation;
				}
				((Character)player).SetLookDir(val, 0f);
			}
		}

		private static Character FindTarget(Player player)
		{
			//IL_0028: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: 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_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			GameCamera instance = GameCamera.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			InitMasks();
			float num = Plugin.StrikeRangeMeters.Value;
			Vector3 position = ((Component)instance).transform.position;
			Vector3 forward = ((Component)instance).transform.forward;
			float num2 = Vector3.Distance(position, ((Character)player).GetEyePoint()) + num + 2f;
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(position, forward, ref val, num2, s_solidMask, (QueryTriggerInteraction)1))
			{
				num2 = ((RaycastHit)(ref val)).distance;
			}
			int num3 = Physics.SphereCastNonAlloc(position, 0.5f, forward, s_hits, num2, s_characterMask, (QueryTriggerInteraction)1);
			Array.Sort(s_hits, 0, num3, HitDistanceComparer.Instance);
			for (int i = 0; i < num3; i++)
			{
				Character componentInParent = ((Component)((RaycastHit)(ref s_hits[i])).collider).GetComponentInParent<Character>();
				if (IsValidTarget(player, componentInParent, num))
				{
					return componentInParent;
				}
			}
			Character val2 = null;
			float num4 = 6f;
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (IsValidTarget(player, allCharacter, num))
				{
					Vector3 centerPoint = allCharacter.GetCenterPoint();
					float num5 = Vector3.Angle(forward, centerPoint - position);
					if (!(num5 >= num4) && !Physics.Linecast(position, centerPoint, s_solidMask, (QueryTriggerInteraction)1))
					{
						val2 = allCharacter;
						num4 = num5;
					}
				}
			}
			if ((Object)(object)val2 == (Object)null && Plugin.LogStrikes.Value)
			{
				LogNearestMiss(player, position, forward);
			}
			return val2;
		}

		private static void LogNearestMiss(Player player, Vector3 origin, Vector3 direction)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_0044: 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)
			Character val = null;
			float num = 30f;
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (!((Object)(object)allCharacter == (Object)(object)player) && !allCharacter.IsDead() && BaseAI.IsEnemy((Character)(object)player, allCharacter))
				{
					float num2 = Vector3.Angle(direction, allCharacter.GetCenterPoint() - origin);
					if (!(num2 >= num))
					{
						val = allCharacter;
						num = num2;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogInfo((object)"No target: no enemy within 30° of the crosshair");
				return;
			}
			float num3 = Vector3.Distance(((Component)player).transform.position, ((Component)val).transform.position) - val.GetRadius();
			bool flag = Physics.Linecast(origin, val.GetCenterPoint(), s_solidMask, (QueryTriggerInteraction)1);
			Plugin.Log.LogInfo((object)string.Format("No target: nearest enemy {0} {1:0.0}° off the crosshair, {2:0.0} m away{3}", val.m_name, num, num3, flag ? ", behind cover" : ""));
		}

		private static bool IsValidTarget(Player player, Character character, float range)
		{
			//IL_0029: 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 ((Object)(object)character != (Object)null && (Object)(object)character != (Object)(object)player && !character.IsDead() && BaseAI.IsEnemy((Character)(object)player, character))
			{
				return Vector3.Distance(((Component)player).transform.position, ((Component)character).transform.position) <= range + character.GetRadius();
			}
			return false;
		}

		internal static bool TryFindSpotBehind(Player player, Character target, out Vector3 spot, out Vector3 facing)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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_0014: 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)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: 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_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing referenc