Decompiled source of WeaverCrest v0.1.4

BepInEx/plugins/WeaverCrest/WeaverCrest.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GlobalEnums;
using GlobalSettings;
using HarmonyLib;
using HutongGames.PlayMaker;
using HutongGames.PlayMaker.Actions;
using InControl;
using Silksong.AssetHelper.ManagedAssets;
using TeamCherry.Localization;
using TeamCherry.NestedFadeGroup;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.AddressableAssets.ResourceLocators;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceLocations;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.SceneManagement;
using UnityEngine.U2D;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyFileVersion("0.1.4")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.1.4.0")]
namespace WeaverCrestMod;

internal static class WeaverAlphaHitboxBuilder
{
	private struct IntPoint : IEquatable<IntPoint>
	{
		internal int X;

		internal int Y;

		internal IntPoint(int x, int y)
		{
			X = x;
			Y = y;
		}

		public bool Equals(IntPoint other)
		{
			if (X == other.X)
			{
				return Y == other.Y;
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is IntPoint)
			{
				return Equals((IntPoint)obj);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return (X * 397) ^ Y;
		}
	}

	private struct Edge : IEquatable<Edge>
	{
		internal IntPoint Start;

		internal IntPoint End;

		internal Edge(IntPoint start, IntPoint end)
		{
			Start = start;
			End = end;
		}

		public bool Equals(Edge other)
		{
			if (Start.Equals(other.Start))
			{
				return End.Equals(other.End);
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is Edge)
			{
				return Equals((Edge)obj);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return (Start.GetHashCode() * 397) ^ End.GetHashCode();
		}
	}

	internal static Vector2[] Build(Texture2D texture, Vector2 pivot, float pixelsPerUnit, byte alphaThreshold, int blockSize, float simplifyTolerance)
	{
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)texture == (Object)null || pixelsPerUnit <= 0f)
		{
			return null;
		}
		blockSize = Mathf.Clamp(blockSize, 2, 32);
		int num = (((Texture)texture).width + blockSize - 1) / blockSize;
		int num2 = (((Texture)texture).height + blockSize - 1) / blockSize;
		bool[,] array = new bool[num, num2];
		Color32[] pixels = texture.GetPixels32();
		for (int i = 0; i < ((Texture)texture).height; i++)
		{
			int num3 = i * ((Texture)texture).width;
			for (int j = 0; j < ((Texture)texture).width; j++)
			{
				if (pixels[num3 + j].a >= alphaThreshold)
				{
					array[j / blockSize, i / blockSize] = true;
				}
			}
		}
		List<Edge> edges = new List<Edge>();
		Dictionary<IntPoint, List<Edge>> outgoing = new Dictionary<IntPoint, List<Edge>>();
		for (int k = 0; k < num2; k++)
		{
			for (int l = 0; l < num; l++)
			{
				if (array[l, k])
				{
					int x = l * blockSize;
					int x2 = Mathf.Min(((Texture)texture).width, (l + 1) * blockSize);
					int y = k * blockSize;
					int y2 = Mathf.Min(((Texture)texture).height, (k + 1) * blockSize);
					if (k == 0 || !array[l, k - 1])
					{
						AddEdge(edges, outgoing, new IntPoint(x, y), new IntPoint(x2, y));
					}
					if (l == num - 1 || !array[l + 1, k])
					{
						AddEdge(edges, outgoing, new IntPoint(x2, y), new IntPoint(x2, y2));
					}
					if (k == num2 - 1 || !array[l, k + 1])
					{
						AddEdge(edges, outgoing, new IntPoint(x2, y2), new IntPoint(x, y2));
					}
					if (l == 0 || !array[l - 1, k])
					{
						AddEdge(edges, outgoing, new IntPoint(x, y2), new IntPoint(x, y));
					}
				}
			}
		}
		List<IntPoint> list = FindLargestLoop(edges, outgoing);
		if (list == null || list.Count < 3)
		{
			return null;
		}
		List<Vector2> list2 = new List<Vector2>(list.Count);
		float num4 = pivot.x * (float)((Texture)texture).width;
		float num5 = pivot.y * (float)((Texture)texture).height;
		for (int m = 0; m < list.Count; m++)
		{
			list2.Add(new Vector2(((float)list[m].X - num4) / pixelsPerUnit, ((float)list[m].Y - num5) / pixelsPerUnit));
		}
		List<Vector2> list3 = SimplifyClosed(list2, Mathf.Max(0.005f, simplifyTolerance));
		float num6 = Mathf.Max(0.005f, simplifyTolerance);
		while (list3.Count > 128 && num6 < 0.5f)
		{
			num6 *= 1.5f;
			list3 = SimplifyClosed(list2, num6);
		}
		if (list3.Count > 128)
		{
			List<Vector2> list4 = new List<Vector2>(128);
			for (int n = 0; n < 128; n++)
			{
				list4.Add(list3[n * list3.Count / 128]);
			}
			list3 = list4;
		}
		if (list3.Count < 3)
		{
			return null;
		}
		return list3.ToArray();
	}

	private static void AddEdge(List<Edge> edges, Dictionary<IntPoint, List<Edge>> outgoing, IntPoint start, IntPoint end)
	{
		Edge item = new Edge(start, end);
		edges.Add(item);
		if (!outgoing.TryGetValue(start, out var value))
		{
			value = (outgoing[start] = new List<Edge>());
		}
		value.Add(item);
	}

	private static List<IntPoint> FindLargestLoop(List<Edge> edges, Dictionary<IntPoint, List<Edge>> outgoing)
	{
		HashSet<Edge> hashSet = new HashSet<Edge>();
		List<IntPoint> result = null;
		float num = 0f;
		for (int i = 0; i < edges.Count; i++)
		{
			if (hashSet.Contains(edges[i]))
			{
				continue;
			}
			Edge item = edges[i];
			IntPoint start = item.Start;
			List<IntPoint> list = new List<IntPoint>();
			int num2 = edges.Count + 1;
			while (num2-- > 0 && !hashSet.Contains(item))
			{
				hashSet.Add(item);
				list.Add(item.Start);
				if (item.End.Equals(start))
				{
					break;
				}
				if (!outgoing.TryGetValue(item.End, out var value))
				{
					list.Clear();
					break;
				}
				bool flag = false;
				for (int j = 0; j < value.Count; j++)
				{
					if (!hashSet.Contains(value[j]))
					{
						item = value[j];
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					list.Clear();
					break;
				}
			}
			if (list.Count >= 3)
			{
				float num3 = Mathf.Abs(SignedArea(list));
				if (num3 > num)
				{
					num = num3;
					result = list;
				}
			}
		}
		return result;
	}

	private static float SignedArea(List<IntPoint> points)
	{
		long num = 0L;
		for (int i = 0; i < points.Count; i++)
		{
			IntPoint intPoint = points[i];
			IntPoint intPoint2 = points[(i + 1) % points.Count];
			num += (long)intPoint.X * (long)intPoint2.Y - (long)intPoint2.X * (long)intPoint.Y;
		}
		return (float)num * 0.5f;
	}

	private static List<Vector2> SimplifyClosed(List<Vector2> points, float tolerance)
	{
		//IL_0026: 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_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		if (points == null || points.Count < 4)
		{
			if (points != null)
			{
				return new List<Vector2>(points);
			}
			return new List<Vector2>();
		}
		int num = 0;
		int num2 = 0;
		for (int i = 1; i < points.Count; i++)
		{
			if (points[i].x < points[num].x)
			{
				num = i;
			}
			if (points[i].x > points[num2].x)
			{
				num2 = i;
			}
		}
		if (num == num2)
		{
			return new List<Vector2>(points);
		}
		List<Vector2> points2 = ExtractArc(points, num, num2);
		List<Vector2> points3 = ExtractArc(points, num2, num);
		points2 = SimplifyOpen(points2, tolerance);
		points3 = SimplifyOpen(points3, tolerance);
		List<Vector2> list = new List<Vector2>(points2.Count + points3.Count - 2);
		list.AddRange(points2);
		for (int j = 1; j < points3.Count - 1; j++)
		{
			list.Add(points3[j]);
		}
		return list;
	}

	private static List<Vector2> ExtractArc(List<Vector2> points, int start, int end)
	{
		//IL_000b: 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)
		List<Vector2> list = new List<Vector2>();
		int num = start;
		list.Add(points[num]);
		while (num != end)
		{
			num = (num + 1) % points.Count;
			list.Add(points[num]);
		}
		return list;
	}

	private static List<Vector2> SimplifyOpen(List<Vector2> points, float tolerance)
	{
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		if (points.Count <= 2)
		{
			return new List<Vector2>(points);
		}
		bool[] array = new bool[points.Count];
		array[0] = true;
		array[points.Count - 1] = true;
		SimplifySection(points, 0, points.Count - 1, tolerance * tolerance, array);
		List<Vector2> list = new List<Vector2>();
		for (int i = 0; i < points.Count; i++)
		{
			if (array[i])
			{
				list.Add(points[i]);
			}
		}
		return list;
	}

	private static void SimplifySection(List<Vector2> points, int first, int last, float toleranceSquared, bool[] keep)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		if (last <= first + 1)
		{
			return;
		}
		float num = 0f;
		int num2 = -1;
		Vector2 a = points[first];
		Vector2 b = points[last];
		for (int i = first + 1; i < last; i++)
		{
			float num3 = DistanceToSegmentSquared(points[i], a, b);
			if (num3 > num)
			{
				num = num3;
				num2 = i;
			}
		}
		if (num2 >= 0 && !(num <= toleranceSquared))
		{
			keep[num2] = true;
			SimplifySection(points, first, num2, toleranceSquared, keep);
			SimplifySection(points, num2, last, toleranceSquared, keep);
		}
	}

	private static float DistanceToSegmentSquared(Vector2 point, Vector2 a, Vector2 b)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: 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)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: 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_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: 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_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: 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)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		Vector2 val = b - a;
		float sqrMagnitude = ((Vector2)(ref val)).sqrMagnitude;
		if (sqrMagnitude <= 1E-06f)
		{
			Vector2 val2 = point - a;
			return ((Vector2)(ref val2)).sqrMagnitude;
		}
		float num = Mathf.Clamp01(Vector2.Dot(point - a, val) / sqrMagnitude);
		Vector2 val3 = a + val * num;
		Vector2 val4 = point - val3;
		return ((Vector2)(ref val4)).sqrMagnitude;
	}
}
internal static class WeaverAnimationCatalog
{
	private sealed class AnimationSettings
	{
		internal float Fps;

		internal float PixelsPerUnit;

		internal float PivotX;

		internal float PivotY;
	}

	private const int NormalThreeChargedSlashReleaseStartFrame = 3;

	private const float NormalThreeChargedSlashReleaseDuration = 0.25f;

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

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

	private static tk2dSpriteAnimationClip normalThreeChargedSlashRelease;

	private static readonly string AnimationRoot = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Assets", "Animations");

	internal static bool TryPlayBody(HeroController hero, WeaverMoveDefinition move)
	{
		if ((Object)(object)hero == (Object)null || move == null || string.IsNullOrEmpty(move.BodyAnimationName))
		{
			return false;
		}
		HeroAnimationController animCtrl = hero.AnimCtrl;
		if ((Object)(object)animCtrl != (Object)null && string.Equals(move.Id, "normal_3", StringComparison.Ordinal))
		{
			tk2dSpriteAnimationClip val = GetNormalThreeChargedSlashRelease();
			tk2dSpriteAnimator component = ((Component)animCtrl).GetComponent<tk2dSpriteAnimator>();
			if ((Object)(object)component != (Object)null && val != null)
			{
				component.Play(val);
				ReportBodyOverride(move, val.name);
				return true;
			}
		}
		tk2dSpriteAnimationClip val2 = (((Object)(object)animCtrl != (Object)null) ? animCtrl.GetClip(move.BodyAnimationName) : null);
		if (val2 == null)
		{
			val2 = CreateFallbackAlias(animCtrl, move);
		}
		if (val2 == null)
		{
			ReportFallback(move, "could not create its fallback alias");
			return false;
		}
		animCtrl.PlayClipForced(move.BodyAnimationName);
		ReportBodyOverride(move, move.BodyAnimationName);
		return true;
	}

	internal static float GetBodyAnimationDuration(HeroController hero, WeaverMoveDefinition move)
	{
		if ((Object)(object)hero == (Object)null || move == null || string.IsNullOrEmpty(move.BodyAnimationName))
		{
			return 0f;
		}
		tk2dSpriteAnimationClip val = (string.Equals(move.Id, "normal_3", StringComparison.Ordinal) ? GetNormalThreeChargedSlashRelease() : (((Object)(object)hero.AnimCtrl != (Object)null) ? hero.AnimCtrl.GetClip(move.BodyAnimationName) : null));
		if (val == null || !(val.fps > 0f) || val.frames == null)
		{
			return 0f;
		}
		return (float)val.frames.Length / val.fps;
	}

	internal static void PrewarmBody(HeroController hero, WeaverMoveDefinition move)
	{
		if ((Object)(object)hero == (Object)null || move == null || string.IsNullOrEmpty(move.BodyAnimationName))
		{
			return;
		}
		if (string.Equals(move.Id, "normal_3", StringComparison.Ordinal))
		{
			GetNormalThreeChargedSlashRelease();
			return;
		}
		HeroAnimationController animCtrl = hero.AnimCtrl;
		if (!((Object)(object)animCtrl == (Object)null) && animCtrl.GetClip(move.BodyAnimationName) == null)
		{
			CreateFallbackAlias(animCtrl, move);
		}
	}

	private static void ReportBodyOverride(WeaverMoveDefinition move, string clipName)
	{
		if (move != null && ReportedBodyOverrides.Add(move.Id))
		{
			WeaverCrestPlugin.ModLog.LogInfo((object)("Normal combo body animation: " + move.Id + " -> '" + clipName + "'."));
		}
	}

	private static tk2dSpriteAnimationClip GetBeastChargedSlash()
	{
		try
		{
			ToolCrest warriorCrest = Gameplay.WarriorCrest;
			HeroControllerConfig val = (((Object)(object)warriorCrest != (Object)null) ? warriorCrest.HeroConfig : null);
			return ((Object)(object)val != (Object)null) ? val.GetAnimationClip("Slash_Charged") : null;
		}
		catch (Exception ex)
		{
			WeaverCrestPlugin.ModLog.LogInfo((object)("Normal combo: Beast charged-slash lookup failed: " + ex.Message));
			return null;
		}
	}

	private static tk2dSpriteAnimationClip GetNormalThreeChargedSlashRelease()
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Expected O, but got Unknown
		if (normalThreeChargedSlashRelease != null)
		{
			return normalThreeChargedSlashRelease;
		}
		tk2dSpriteAnimationClip beastChargedSlash = GetBeastChargedSlash();
		if (beastChargedSlash == null || beastChargedSlash.frames == null || beastChargedSlash.frames.Length <= 3)
		{
			return beastChargedSlash;
		}
		int num = beastChargedSlash.frames.Length - 3;
		tk2dSpriteAnimationClip val = new tk2dSpriteAnimationClip(beastChargedSlash);
		val.name = "Weaver Normal 3 Warrior Release";
		val.frames = (tk2dSpriteAnimationFrame[])(object)new tk2dSpriteAnimationFrame[num];
		Array.Copy(beastChargedSlash.frames, 3, val.frames, 0, num);
		val.fps = (float)num / 0.25f;
		normalThreeChargedSlashRelease = val;
		WeaverCrestPlugin.ModLog.LogInfo((object)("Normal combo body animation: normal_3 uses frames " + 3 + "-" + (beastChargedSlash.frames.Length - 1) + " of '" + beastChargedSlash.name + "' at " + val.fps.ToString("0.##") + " FPS to match the 0.25s blade arc."));
		return normalThreeChargedSlashRelease;
	}

	private static tk2dSpriteAnimationClip CreateFallbackAlias(HeroAnimationController animation, WeaverMoveDefinition move)
	{
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Expected O, but got Unknown
		if ((Object)(object)animation == (Object)null || string.IsNullOrEmpty(move.FallbackBodyAnimationName))
		{
			return null;
		}
		tk2dSpriteAnimationClip clip = animation.GetClip(move.FallbackBodyAnimationName);
		tk2dSpriteAnimator component = ((Component)animation).GetComponent<tk2dSpriteAnimator>();
		tk2dSpriteAnimation val = (((Object)(object)component != (Object)null) ? component.Library : null);
		if (clip == null || (Object)(object)val == (Object)null)
		{
			return null;
		}
		tk2dSpriteAnimationClip val2 = new tk2dSpriteAnimationClip(clip);
		val2.name = move.BodyAnimationName;
		bool flag = TryInstallExternalFrames(val2, clip, move);
		tk2dSpriteAnimationClip[] array = (tk2dSpriteAnimationClip[])(((object)val.clips) ?? ((object)new tk2dSpriteAnimationClip[0]));
		tk2dSpriteAnimationClip[] array2 = (tk2dSpriteAnimationClip[])(object)new tk2dSpriteAnimationClip[array.Length + 1];
		Array.Copy(array, array2, array.Length);
		array2[array.Length] = val2;
		val.clips = array2;
		val.ValidateLookup();
		if (!flag)
		{
			ReportFallback(move, "is using a cloned fallback");
		}
		return val2;
	}

	private static bool TryInstallExternalFrames(tk2dSpriteAnimationClip target, tk2dSpriteAnimationClip fallback, WeaverMoveDefinition move)
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		//IL_0101: 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_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Expected O, but got Unknown
		string text = Path.Combine(AnimationRoot, move.Id);
		string[] array = WeaverPackagedAssets.Frames(text);
		if (array.Length == 0)
		{
			return false;
		}
		try
		{
			AnimationSettings animationSettings = ReadSettings(Path.Combine(text, "animation.cfg"), fallback.fps);
			tk2dSpriteAnimationFrame[] array2 = (tk2dSpriteAnimationFrame[])(object)new tk2dSpriteAnimationFrame[array.Length];
			for (int i = 0; i < array.Length; i++)
			{
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
				((Object)val).name = move.Id + "_" + i.ToString("D3", CultureInfo.InvariantCulture);
				if (!ImageConversion.LoadImage(val, WeaverPackagedAssets.ReadBytes(array[i]), false))
				{
					throw new InvalidDataException("Unity could not decode " + array[i]);
				}
				((Texture)val).filterMode = (FilterMode)0;
				((Texture)val).wrapMode = (TextureWrapMode)1;
				string name = ((Object)val).name;
				tk2dSpriteCollectionData val2 = tk2dSpriteCollectionData.CreateFromTexture((Texture)(object)val, tk2dSpriteCollectionSize.PixelsPerMeter(animationSettings.PixelsPerUnit), new string[1] { name }, (Rect[])(object)new Rect[1]
				{
					new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height)
				}, (Vector2[])(object)new Vector2[1]
				{
					new Vector2(animationSettings.PivotX, animationSettings.PivotY)
				});
				((Object)val2).name = "WeaverCrest_" + name;
				val2.Transient = true;
				tk2dSpriteAnimationFrame val3 = new tk2dSpriteAnimationFrame();
				val3.spriteCollection = val2;
				val3.spriteId = val2.GetSpriteIdByName(name);
				array2[i] = val3;
			}
			CopyAnimationEvents(fallback.frames, array2);
			target.frames = array2;
			target.fps = animationSettings.Fps;
			WeaverCrestPlugin.ModLog.LogInfo((object)("Loaded " + array2.Length + " external frames for " + move.Id + " at " + animationSettings.Fps.ToString("0.##", CultureInfo.InvariantCulture) + " FPS."));
			return true;
		}
		catch (Exception ex)
		{
			WeaverCrestPlugin.ModLog.LogError((object)("Could not load external frames for " + move.Id + "; keeping fallback: " + ex));
			return false;
		}
	}

	private static void CopyAnimationEvents(tk2dSpriteAnimationFrame[] source, tk2dSpriteAnimationFrame[] destination)
	{
		if (source == null || source.Length == 0 || destination == null || destination.Length == 0)
		{
			return;
		}
		for (int i = 0; i < source.Length; i++)
		{
			if (source[i].triggerEvent)
			{
				int num = ((source.Length != 1) ? Mathf.RoundToInt((float)i / (float)(source.Length - 1) * (float)(destination.Length - 1)) : 0);
				destination[num].CopyTriggerFrom(source[i]);
			}
		}
	}

	private static AnimationSettings ReadSettings(string path, float fallbackFps)
	{
		AnimationSettings animationSettings = new AnimationSettings();
		animationSettings.Fps = fallbackFps;
		animationSettings.PixelsPerUnit = 64f;
		animationSettings.PivotX = 0.5f;
		animationSettings.PivotY = 0.5f;
		string[] array = WeaverPackagedAssets.ReadLines(path);
		for (int i = 0; i < array.Length; i++)
		{
			string text = array[i].Trim();
			if (text.Length == 0 || text.StartsWith("#", StringComparison.Ordinal))
			{
				continue;
			}
			int num = text.IndexOf('=');
			if (num <= 0)
			{
				continue;
			}
			string text2 = text.Substring(0, num).Trim().ToLowerInvariant();
			if (float.TryParse(text.Substring(num + 1).Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				if (text2 == "fps" && result > 0f)
				{
					animationSettings.Fps = result;
				}
				else if (text2 == "pixels_per_unit" && result > 0f)
				{
					animationSettings.PixelsPerUnit = result;
				}
				else if (text2 == "pivot_x")
				{
					animationSettings.PivotX = result;
				}
				else if (text2 == "pivot_y")
				{
					animationSettings.PivotY = result;
				}
			}
		}
		return animationSettings;
	}

	private static void ReportFallback(WeaverMoveDefinition move, string reason)
	{
		if (ReportedFallbacks.Add(move.BodyAnimationName))
		{
			WeaverCrestPlugin.ModLog.LogInfo((object)("Weaver animation '" + move.BodyAnimationName + "' " + reason + " from '" + move.FallbackBodyAnimationName + "' for " + move.Id + "."));
		}
	}
}
internal static class WeaverCounterThrustSlashVisual
{
	internal const float Duration = 0.29f;

	private const float PixelsPerUnit = 200f;

	private static readonly Vector2 Pivot = new Vector2(0.35f, 0.56f);

	private static readonly string FrameRoot = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Assets", "Slashes", "counter_thrust");

	private static bool loadAttempted;

	private static Sprite[] frames;

	internal static bool IsAvailable()
	{
		EnsureLoaded();
		if (frames != null)
		{
			return frames.Length > 0;
		}
		return false;
	}

	internal static GameObject Spawn(Vector2 position, float facing, float angleDegrees, bool mirrorVertically, float scale, int sortingLayerId, int sortingOrder, float alpha)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: 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)
		EnsureLoaded();
		if (frames == null || frames.Length == 0)
		{
			return null;
		}
		GameObject val = new GameObject("Weaver Counter Thrust Slash");
		val.transform.position = new Vector3(position.x, position.y, 0f);
		val.transform.rotation = Quaternion.Euler(0f, 0f, angleDegrees * ((facing >= 0f) ? 1f : (-1f)));
		val.transform.localScale = new Vector3(((facing >= 0f) ? 1f : (-1f)) * scale, (mirrorVertically ? (-1f) : 1f) * scale, scale);
		SpriteRenderer val2 = val.AddComponent<SpriteRenderer>();
		val2.sprite = frames[0];
		val2.color = new Color(1f, 1f, 1f, Mathf.Clamp01(alpha));
		((Renderer)val2).sortingLayerID = sortingLayerId;
		((Renderer)val2).sortingOrder = sortingOrder;
		WeaverCounterThrustSlashPlayer weaverCounterThrustSlashPlayer = val.AddComponent<WeaverCounterThrustSlashPlayer>();
		weaverCounterThrustSlashPlayer.Frames = frames;
		weaverCounterThrustSlashPlayer.Duration = 0.29f;
		return val;
	}

	private static void EnsureLoaded()
	{
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Expected O, but got Unknown
		//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Expected O, but got Unknown
		//IL_0140: 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)
		if (loadAttempted)
		{
			return;
		}
		loadAttempted = true;
		try
		{
			if (!Directory.Exists(FrameRoot))
			{
				WeaverCrestPlugin.ModLog.LogWarning((object)("Counter thrust frames unavailable: missing " + FrameRoot));
				return;
			}
			string[] files = Directory.GetFiles(FrameRoot, "frame_*.png");
			Array.Sort(files, (IComparer<string>?)StringComparer.OrdinalIgnoreCase);
			if (files.Length == 0)
			{
				WeaverCrestPlugin.ModLog.LogWarning((object)("Counter thrust frames unavailable: no frame_*.png in " + FrameRoot));
				return;
			}
			Sprite[] array = (Sprite[])(object)new Sprite[files.Length];
			for (int i = 0; i < files.Length; i++)
			{
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
				if (!ImageConversion.LoadImage(val, File.ReadAllBytes(files[i]), false))
				{
					Object.Destroy((Object)(object)val);
					throw new InvalidDataException("Unity could not decode " + files[i]);
				}
				Texture2D val2 = new Texture2D(((Texture)val).width, ((Texture)val).height, (TextureFormat)4, true);
				((Object)val2).name = "WeaverCounterThrustTex_" + i.ToString("D3");
				val2.SetPixels32(val.GetPixels32());
				Object.Destroy((Object)(object)val);
				((Texture)val2).filterMode = (FilterMode)2;
				((Texture)val2).wrapMode = (TextureWrapMode)1;
				((Texture)val2).mipMapBias = 0.2f;
				val2.Apply(true, true);
				Sprite val3 = Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), Pivot, 200f);
				((Object)val3).name = "WeaverCounterThrustSprite_" + i.ToString("D3");
				array[i] = val3;
			}
			frames = array;
			WeaverCrestPlugin.ModLog.LogInfo((object)string.Concat("Loaded Weaver counter thrust visual (", frames.Length, " frames, pivot=", Pivot, ")."));
		}
		catch (Exception ex)
		{
			frames = null;
			WeaverCrestPlugin.ModLog.LogWarning((object)("Counter thrust frames could not be loaded: " + ex.Message));
		}
	}
}
internal sealed class WeaverCounterThrustSlashPlayer : MonoBehaviour
{
	internal Sprite[] Frames;

	internal float Duration = 0.29f;

	private SpriteRenderer spriteRenderer;

	private float elapsed;

	private int lastFrame = -1;

	private void Awake()
	{
		spriteRenderer = ((Component)this).GetComponent<SpriteRenderer>();
	}

	private void Update()
	{
		if ((Object)(object)spriteRenderer == (Object)null || Frames == null || Frames.Length == 0)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		elapsed += Time.unscaledDeltaTime;
		float num = ((Duration > 0f) ? Mathf.Clamp01(elapsed / Duration) : 1f);
		int num2 = Mathf.Clamp(Mathf.FloorToInt(num * (float)Frames.Length), 0, Frames.Length - 1);
		if (num2 != lastFrame)
		{
			spriteRenderer.sprite = Frames[num2];
			lastFrame = num2;
		}
		if (elapsed >= Duration)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}
	}
}
internal static class WeaverNativeUpSlashVisual
{
	private const float InnerScale = 0.82f;

	private static readonly Dictionary<NailSlash, GameObject> Active = new Dictionary<NailSlash, GameObject>();

	private static bool warnedMissingNativeClip;

	internal static void Apply(NailSlash slash)
	{
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Expected O, but got Unknown
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: 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)
		if ((Object)(object)slash == (Object)null)
		{
			return;
		}
		Remove(slash);
		tk2dSpriteAnimator component = ((Component)slash).GetComponent<tk2dSpriteAnimator>();
		tk2dSprite component2 = ((Component)slash).GetComponent<tk2dSprite>();
		tk2dSpriteAnimationClip val = (((Object)(object)component != (Object)null) ? component.CurrentClip : null);
		if (val == null && (Object)(object)component != (Object)null)
		{
			val = component.GetClipByName(slash.animName);
		}
		if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || val == null || val.frames == null || val.frames.Length == 0)
		{
			if (!warnedMissingNativeClip)
			{
				warnedMissingNativeClip = true;
				WeaverCrestPlugin.ModLog.LogWarning((object)"Up slash visual: the active native UpSlash clip could not be copied; leaving the stock arc unchanged.");
			}
			return;
		}
		GameObject val2 = new GameObject("Weaver Native Up Slash Inner Arc");
		val2.layer = ((Component)slash).gameObject.layer;
		val2.transform.SetParent(((Component)slash).transform, false);
		val2.transform.localPosition = new Vector3(0f, -0.04f, -0.001f);
		val2.transform.localRotation = Quaternion.identity;
		val2.transform.localScale = Vector3.one * 0.82f;
		tk2dSprite val3 = val2.AddComponent<tk2dSprite>();
		tk2dSpriteAnimator val4 = val2.AddComponent<tk2dSpriteAnimator>();
		val4.Library = component.Library;
		val4.playAutomatically = false;
		((tk2dBaseSprite)val3).SetSprite(val.frames[0].spriteCollection, val.frames[0].spriteId);
		((tk2dBaseSprite)val3).color = Color.black;
		Renderer component3 = ((Component)slash).GetComponent<Renderer>();
		Renderer component4 = val2.GetComponent<Renderer>();
		if ((Object)(object)component3 != (Object)null && (Object)(object)component4 != (Object)null)
		{
			WeaverCombat.ApplyHeroEffectSorting(component4, component3, 1);
			if ((Object)(object)component3.sharedMaterial != (Object)null)
			{
				component4.sharedMaterial = component3.sharedMaterial;
			}
		}
		val4.Play(val);
		val4.ClipFps = component.ClipFps;
		Active[slash] = val2;
	}

	internal static void Restore(NailSlash slash)
	{
		Remove(slash);
	}

	internal static void RestoreAll()
	{
		NailSlash[] array = (NailSlash[])(object)new NailSlash[Active.Count];
		Active.Keys.CopyTo(array, 0);
		for (int i = 0; i < array.Length; i++)
		{
			Remove(array[i]);
		}
	}

	private static void Remove(NailSlash slash)
	{
		if (!((Object)(object)slash == (Object)null) && Active.TryGetValue(slash, out var value))
		{
			if ((Object)(object)value != (Object)null)
			{
				Object.Destroy((Object)(object)value);
			}
			Active.Remove(slash);
		}
	}
}
internal static class WeaverPackagedAssets
{
	private static readonly Assembly Owner = typeof(WeaverPackagedAssets).Assembly;

	private static readonly string Root = Path.GetDirectoryName(Owner.Location) + Path.DirectorySeparatorChar;

	private static string Resource(string path)
	{
		string fullPath = Path.GetFullPath(path);
		if (!fullPath.StartsWith(Root, StringComparison.OrdinalIgnoreCase))
		{
			throw new InvalidDataException("Asset path is outside the plugin directory.");
		}
		return "WeaverCrest.Packaged." + fullPath.Substring(Root.Length).Replace('\\', '.').Replace('/', '.');
	}

	internal static string[] Frames(string folder)
	{
		string[] array;
		if (WeaverFeatures.IsRelease)
		{
			string prefix = Resource(Path.Combine(folder, "frame_"));
			array = (from name in Owner.GetManifestResourceNames()
				where name.StartsWith(prefix, StringComparison.Ordinal) && name.EndsWith(".png", StringComparison.Ordinal)
				select Path.Combine(folder, "frame_" + name.Substring(prefix.Length))).ToArray();
		}
		else
		{
			array = (Directory.Exists(folder) ? Directory.GetFiles(folder, "frame_*.png") : new string[0]);
		}
		Array.Sort(array, (IComparer<string>?)StringComparer.OrdinalIgnoreCase);
		return array;
	}

	internal static byte[] ReadBytes(string path)
	{
		if (!WeaverFeatures.IsRelease)
		{
			return File.ReadAllBytes(path);
		}
		using Stream stream = Owner.GetManifestResourceStream(Resource(path));
		using MemoryStream memoryStream = new MemoryStream();
		if (stream == null)
		{
			throw new FileNotFoundException("Missing packaged combat asset.", path);
		}
		stream.CopyTo(memoryStream);
		return memoryStream.ToArray();
	}

	internal static string[] ReadLines(string path)
	{
		if (!WeaverFeatures.IsRelease)
		{
			if (!File.Exists(path))
			{
				return new string[0];
			}
			return File.ReadAllLines(path);
		}
		using Stream stream = Owner.GetManifestResourceStream(Resource(path));
		if (stream == null)
		{
			return new string[0];
		}
		using StreamReader streamReader = new StreamReader(stream);
		return streamReader.ReadToEnd().Split(new char[2] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
	}
}
internal static class WeaverSlashSkin
{
	private sealed class Tuning
	{
		internal float OffsetX;

		internal float OffsetY;

		internal float OverallScale = 1f;

		internal float HorizontalScale = 1f;

		internal float VerticalScale = 1f;

		internal float Rotation;

		internal bool FlipHorizontal = true;
	}

	private sealed class ArtSet
	{
		internal Sprite[] Frames;

		internal Vector2[][] HitboxFrames;

		internal Material Material;

		internal Color Tint;

		internal float Duration;
	}

	private sealed class Overlay
	{
		internal GameObject Go;

		internal string MoveId;

		internal tk2dSprite StockSprite;

		internal Color StockColor;

		internal bool HidStock;
	}

	private sealed class SlashSettings
	{
		internal float PixelsPerUnit;

		internal float PivotX;

		internal float PivotY;

		internal bool FlipX;

		internal float Duration;

		internal byte HitboxAlphaThreshold;

		internal int HitboxBlockSize;

		internal float HitboxSimplify;

		internal Color Tint;
	}

	internal static bool Enabled = true;

	private static readonly Dictionary<string, Tuning> TuningByMove = new Dictionary<string, Tuning>();

	private static readonly Tuning DefaultTuning = new Tuning();

	private static readonly string SlashRoot = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Assets", "Slashes");

	private static readonly Dictionary<string, ArtSet> ArtByMove = new Dictionary<string, ArtSet>();

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

	private static readonly Dictionary<NailSlash, Overlay> Active = new Dictionary<NailSlash, Overlay>();

	internal static int TuningVersion { get; private set; }

	internal static void MaintainStockHidden(NailSlash slash)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)slash == (Object)null) && Active.TryGetValue(slash, out var value) && value.HidStock && !((Object)(object)value.StockSprite == (Object)null))
		{
			Color color = ((tk2dBaseSprite)value.StockSprite).color;
			color.a = 0f;
			((tk2dBaseSprite)value.StockSprite).color = color;
		}
	}

	private static Tuning GetTuning(string moveId)
	{
		if (moveId != null && TuningByMove.TryGetValue(moveId, out var value))
		{
			return value;
		}
		return DefaultTuning;
	}

	internal static void SetRuntimeTuning(string moveId, float offsetX, float offsetY, float overallScale, float horizontalScale, float verticalScale, float rotation, bool flipHorizontal)
	{
		if (string.IsNullOrEmpty(moveId))
		{
			return;
		}
		if (!TuningByMove.TryGetValue(moveId, out var value))
		{
			value = new Tuning();
			TuningByMove[moveId] = value;
		}
		value.OffsetX = offsetX;
		value.OffsetY = offsetY;
		value.OverallScale = Mathf.Max(0.01f, overallScale);
		value.HorizontalScale = Mathf.Max(0.01f, horizontalScale);
		value.VerticalScale = Mathf.Max(0.01f, verticalScale);
		value.Rotation = rotation;
		value.FlipHorizontal = flipHorizontal;
		TuningVersion++;
		foreach (KeyValuePair<NailSlash, Overlay> item in Active)
		{
			if (item.Value != null && (Object)(object)item.Value.Go != (Object)null)
			{
				ApplyRuntimeTransform(item.Value.Go.transform, item.Value.MoveId);
			}
		}
	}

	internal static void ApplyRuntimeTransform(Transform target, string moveId)
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)target == (Object)null))
		{
			Tuning tuning = GetTuning(moveId);
			float num = tuning.OverallScale * tuning.HorizontalScale;
			if (tuning.FlipHorizontal)
			{
				num = 0f - num;
			}
			target.localPosition = new Vector3(tuning.OffsetX, tuning.OffsetY, 0f);
			target.localRotation = Quaternion.Euler(0f, 0f, tuning.Rotation);
			target.localScale = new Vector3(num, tuning.OverallScale * tuning.VerticalScale, 1f);
		}
	}

	internal static Vector2[] TransformHitboxPath(string moveId, Vector2[] source)
	{
		//IL_00fe: 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_0104: 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_0113: 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_0118: Unknown result type (might be due to invalid IL or missing references)
		if (source == null)
		{
			return null;
		}
		Tuning tuning = GetTuning(moveId);
		Vector2[] array = (Vector2[])(object)new Vector2[source.Length];
		float num = tuning.OverallScale * tuning.HorizontalScale;
		if (tuning.FlipHorizontal)
		{
			num = 0f - num;
		}
		float num2 = tuning.OverallScale * tuning.VerticalScale;
		float num3 = tuning.Rotation * ((float)Math.PI / 180f);
		float num4 = Mathf.Cos(num3);
		float num5 = Mathf.Sin(num3);
		bool flag = moveId == "normal_1" || moveId == "normal_2" || moveId == "normal_3";
		Vector2 val = default(Vector2);
		((Vector2)(ref val))..ctor(tuning.OffsetX, tuning.OffsetY);
		Vector2 val2 = default(Vector2);
		for (int i = 0; i < source.Length; i++)
		{
			float num6 = source[i].x * num;
			float num7 = source[i].y * num2;
			((Vector2)(ref val2))..ctor(num6 * num4 - num7 * num5 + tuning.OffsetX, num6 * num5 + num7 * num4 + tuning.OffsetY);
			ref Vector2 reference = ref array[i];
			reference = (flag ? (val + (val2 - val) * 1.1f) : val2);
		}
		return array;
	}

	internal static void Apply(NailSlash slash, string moveId)
	{
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Expected O, but got Unknown
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: 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)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		if (!Enabled || (Object)(object)slash == (Object)null || string.IsNullOrEmpty(moveId) || NoFrames.Contains(moveId))
		{
			return;
		}
		Material slashMaterial = GetSlashMaterial(slash);
		ArtSet art = GetArt(moveId, slashMaterial);
		if (art != null && art.Frames != null && art.Frames.Length != 0)
		{
			Remove(slash);
			Overlay overlay = new Overlay();
			tk2dSprite component = ((Component)slash).GetComponent<tk2dSprite>();
			if ((Object)(object)component != (Object)null)
			{
				overlay.StockSprite = component;
				overlay.StockColor = ((tk2dBaseSprite)component).color;
				overlay.HidStock = true;
				Color color = ((tk2dBaseSprite)component).color;
				color.a = 0f;
				((tk2dBaseSprite)component).color = color;
			}
			GameObject val = new GameObject("WeaverSlashOverlay");
			val.transform.SetParent(((Component)slash).transform, false);
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = Quaternion.identity;
			val.transform.localScale = Vector3.one;
			ApplyRuntimeTransform(val.transform, moveId);
			SpriteRenderer val2 = val.AddComponent<SpriteRenderer>();
			val2.sprite = art.Frames[0];
			val2.color = art.Tint;
			if ((Object)(object)art.Material != (Object)null)
			{
				((Renderer)val2).sharedMaterial = art.Material;
			}
			Renderer component2 = ((Component)slash).GetComponent<Renderer>();
			if ((Object)(object)component2 != (Object)null)
			{
				((Renderer)val2).sortingLayerID = component2.sortingLayerID;
				((Renderer)val2).sortingOrder = component2.sortingOrder;
				((Renderer)val2).sharedMaterial.renderQueue = (((Object)(object)component2.sharedMaterial != (Object)null) ? component2.sharedMaterial.renderQueue : ((Renderer)val2).sharedMaterial.renderQueue);
			}
			WeaverSlashOverlayPlayer weaverSlashOverlayPlayer = val.AddComponent<WeaverSlashOverlayPlayer>();
			weaverSlashOverlayPlayer.Frames = art.Frames;
			weaverSlashOverlayPlayer.Duration = art.Duration;
			weaverSlashOverlayPlayer.Slash = slash;
			weaverSlashOverlayPlayer.MoveId = moveId;
			if (art.HitboxFrames != null)
			{
				WeaverHitboxStore.ApplyAnimated(slash, moveId, art.HitboxFrames);
			}
			overlay.Go = val;
			overlay.MoveId = moveId;
			Active[slash] = overlay;
		}
	}

	internal static void Prewarm(NailSlash slash, string moveId)
	{
		if (Enabled && !((Object)(object)slash == (Object)null) && !string.IsNullOrEmpty(moveId) && !NoFrames.Contains(moveId) && !ArtByMove.ContainsKey(moveId))
		{
			Material slashMaterial = GetSlashMaterial(slash);
			if (!((Object)(object)slashMaterial == (Object)null))
			{
				GetArt(moveId, slashMaterial);
			}
		}
	}

	internal static void Restore(NailSlash slash)
	{
		Remove(slash);
	}

	internal static void RestoreAll()
	{
		NailSlash[] array = (NailSlash[])(object)new NailSlash[Active.Count];
		Active.Keys.CopyTo(array, 0);
		for (int i = 0; i < array.Length; i++)
		{
			Remove(array[i]);
		}
	}

	private static void Remove(NailSlash slash)
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)slash == (Object)null) && Active.TryGetValue(slash, out var value))
		{
			if ((Object)(object)value.Go != (Object)null)
			{
				Object.Destroy((Object)(object)value.Go);
			}
			if (value.HidStock && (Object)(object)value.StockSprite != (Object)null)
			{
				((tk2dBaseSprite)value.StockSprite).color = value.StockColor;
			}
			Active.Remove(slash);
		}
	}

	private static Material GetSlashMaterial(NailSlash slash)
	{
		Renderer component = ((Component)slash).GetComponent<Renderer>();
		if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMaterial != (Object)null && (Object)(object)component.sharedMaterial.shader != (Object)null)
		{
			return component.sharedMaterial;
		}
		tk2dSpriteAnimator component2 = ((Component)slash).GetComponent<tk2dSpriteAnimator>();
		if ((Object)(object)component2 != (Object)null)
		{
			tk2dSpriteAnimationClip clipByName = component2.GetClipByName(slash.animName);
			if (clipByName != null && clipByName.frames != null && clipByName.frames.Length > 0)
			{
				tk2dSpriteCollectionData spriteCollection = clipByName.frames[0].spriteCollection;
				int spriteId = clipByName.frames[0].spriteId;
				if ((Object)(object)spriteCollection != (Object)null && spriteCollection.spriteDefinitions != null && spriteId >= 0 && spriteId < spriteCollection.spriteDefinitions.Length)
				{
					tk2dSpriteDefinition val = spriteCollection.spriteDefinitions[spriteId];
					if (val != null)
					{
						if (!((Object)(object)val.materialInst != (Object)null))
						{
							return val.material;
						}
						return val.materialInst;
					}
				}
			}
		}
		return null;
	}

	private static ArtSet GetArt(string moveId, Material stockMaterial)
	{
		if (ArtByMove.TryGetValue(moveId, out var value))
		{
			return value;
		}
		if ((Object)(object)stockMaterial == (Object)null)
		{
			return null;
		}
		value = BuildArt(moveId, stockMaterial);
		if (value != null)
		{
			ArtByMove[moveId] = value;
		}
		else
		{
			NoFrames.Add(moveId);
		}
		return value;
	}

	private static ArtSet BuildArt(string moveId, Material stockMaterial)
	{
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Expected O, but got Unknown
		//IL_0278: Unknown result type (might be due to invalid IL or missing references)
		//IL_027f: Expected O, but got Unknown
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Expected O, but got Unknown
		//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_021f: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		string text = Path.Combine(SlashRoot, moveId);
		string[] array = WeaverPackagedAssets.Frames(text);
		if (array.Length == 0)
		{
			return null;
		}
		try
		{
			SlashSettings slashSettings = ReadSettings(Path.Combine(text, "animation.cfg"));
			Sprite[] array2 = (Sprite[])(object)new Sprite[array.Length];
			Vector2[][] array3 = new Vector2[array.Length][];
			bool flag = false;
			Texture2D val = null;
			for (int i = 0; i < array.Length; i++)
			{
				Texture2D val2 = new Texture2D(2, 2, (TextureFormat)4, false);
				if (!ImageConversion.LoadImage(val2, WeaverPackagedAssets.ReadBytes(array[i]), false))
				{
					Object.Destroy((Object)(object)val2);
					throw new InvalidDataException("Unity could not decode " + array[i]);
				}
				Texture2D val3 = new Texture2D(((Texture)val2).width, ((Texture)val2).height, (TextureFormat)4, true);
				((Object)val3).name = "WeaverSlashTex_" + moveId + "_" + i.ToString("D3", CultureInfo.InvariantCulture);
				val3.SetPixels32(val2.GetPixels32());
				Object.Destroy((Object)(object)val2);
				float num = slashSettings.PivotX;
				if (slashSettings.FlipX)
				{
					FlipTextureHorizontally(val3);
					num = 1f - slashSettings.PivotX;
				}
				Color32[] pixels = val3.GetPixels32();
				if (string.Equals(moveId, "normal_1", StringComparison.Ordinal) || string.Equals(moveId, "normal_2", StringComparison.Ordinal) || string.Equals(moveId, "normal_3", StringComparison.Ordinal))
				{
					NormalizeSlashTone(pixels);
				}
				int darkCoreExpansionRadius = GetDarkCoreExpansionRadius(moveId, ((Texture)val3).width);
				if (darkCoreExpansionRadius > 0)
				{
					ExpandDarkCore(pixels, ((Texture)val3).width, ((Texture)val3).height, darkCoreExpansionRadius, moveId);
				}
				SmoothAlphaEdges(pixels, ((Texture)val3).width, ((Texture)val3).height);
				val3.SetPixels32(pixels);
				val3.Apply(false, false);
				array3[i] = WeaverAlphaHitboxBuilder.Build(val3, new Vector2(num, slashSettings.PivotY), slashSettings.PixelsPerUnit, slashSettings.HitboxAlphaThreshold, slashSettings.HitboxBlockSize, slashSettings.HitboxSimplify);
				if (array3[i] != null && array3[i].Length >= 3)
				{
					flag = true;
				}
				((Texture)val3).filterMode = (FilterMode)2;
				((Texture)val3).wrapMode = (TextureWrapMode)1;
				((Texture)val3).mipMapBias = 0.35f;
				val3.Apply(true, true);
				if ((Object)(object)val == (Object)null)
				{
					val = val3;
				}
				Sprite val4 = Sprite.Create(val3, new Rect(0f, 0f, (float)((Texture)val3).width, (float)((Texture)val3).height), new Vector2(num, slashSettings.PivotY), slashSettings.PixelsPerUnit);
				((Object)val4).name = "WeaverSlashSprite_" + moveId + "_" + i.ToString(CultureInfo.InvariantCulture);
				array2[i] = val4;
			}
			Material val5 = new Material(stockMaterial);
			((Object)val5).name = "WeaverSlashMat_" + moveId;
			if ((Object)(object)val != (Object)null)
			{
				val5.mainTexture = (Texture)(object)val;
			}
			ArtSet artSet = new ArtSet();
			artSet.Frames = array2;
			artSet.HitboxFrames = (flag ? array3 : null);
			artSet.Material = val5;
			artSet.Tint = slashSettings.Tint;
			artSet.Duration = slashSettings.Duration;
			WeaverCrestPlugin.ModLog.LogInfo((object)("Built Weaver slash overlay (" + array2.Length + " frames) for " + moveId + "."));
			if (artSet.HitboxFrames != null)
			{
				string text2 = string.Empty;
				for (int j = 0; j < artSet.HitboxFrames.Length; j++)
				{
					text2 = text2 + ((j == 0) ? string.Empty : ",") + ((artSet.HitboxFrames[j] != null) ? artSet.HitboxFrames[j].Length.ToString(CultureInfo.InvariantCulture) : "0");
				}
				WeaverCrestPlugin.ModLog.LogInfo((object)("Built alpha hitboxes for " + moveId + " (vertices per frame: " + text2 + ")."));
			}
			else
			{
				WeaverCrestPlugin.ModLog.LogWarning((object)("Could not build every alpha hitbox for " + moveId + "; keeping the configured fallback collider."));
			}
			return artSet;
		}
		catch (Exception ex)
		{
			WeaverCrestPlugin.ModLog.LogError((object)("Could not build Weaver slash overlay for " + moveId + "; keeping stock slash: " + ex));
			return null;
		}
	}

	private static void FlipTextureHorizontally(Texture2D texture)
	{
		//IL_0048: 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)
		int width = ((Texture)texture).width;
		int height = ((Texture)texture).height;
		Color32[] pixels = texture.GetPixels32();
		Color32[] array = (Color32[])(object)new Color32[pixels.Length];
		for (int i = 0; i < height; i++)
		{
			int num = i * width;
			for (int j = 0; j < width; j++)
			{
				ref Color32 reference = ref array[num + j];
				reference = pixels[num + (width - 1 - j)];
			}
		}
		texture.SetPixels32(array);
	}

	private static int GetDarkCoreExpansionRadius(string moveId, int textureWidth)
	{
		if (string.Equals(moveId, "normal_1", StringComparison.Ordinal))
		{
			return Mathf.Max(1, Mathf.RoundToInt((float)textureWidth * 0.012f));
		}
		if (string.Equals(moveId, "normal_2", StringComparison.Ordinal))
		{
			return Mathf.Max(1, Mathf.RoundToInt((float)textureWidth * 0.014f));
		}
		return 0;
	}

	private static void NormalizeSlashTone(Color32[] pixels)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < pixels.Length; i++)
		{
			Color32 val = pixels[i];
			if (val.a > 0 && val.r > 170 && val.g > 115 && val.r - val.b > 25 && val.g - val.b > 10)
			{
				ref Color32 reference = ref pixels[i];
				reference = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, val.a);
			}
		}
	}

	private static void ExpandDarkCore(Color32[] pixels, int width, int height, int radius, string moveId)
	{
		//IL_0033: 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)
		if (pixels == null || pixels.Length == 0 || radius <= 0)
		{
			return;
		}
		if (string.Equals(moveId, "normal_1", StringComparison.Ordinal))
		{
			for (int i = 0; i < height; i++)
			{
				int num = i * width;
				int num2 = width;
				for (int j = 0; j < width; j++)
				{
					if (IsDarkCorePixel(pixels[num + j]))
					{
						num2 = j;
						break;
					}
				}
				if (num2 < width)
				{
					for (int k = 1; k <= radius && num2 - k >= 0; k++)
					{
						BlendDarkCorePixel(ref pixels[num + num2 - k], GetCoreExpansionAlpha(k, radius));
					}
				}
			}
		}
		else
		{
			if (!string.Equals(moveId, "normal_2", StringComparison.Ordinal))
			{
				return;
			}
			for (int l = 0; l < width; l++)
			{
				int num3 = -1;
				for (int num4 = height - 1; num4 >= 0; num4--)
				{
					if (IsDarkCorePixel(pixels[num4 * width + l]))
					{
						num3 = num4;
						break;
					}
				}
				if (num3 >= 0)
				{
					for (int m = 1; m <= radius && num3 + m < height; m++)
					{
						BlendDarkCorePixel(ref pixels[(num3 + m) * width + l], GetCoreExpansionAlpha(m, radius));
					}
				}
			}
		}
	}

	private static bool IsDarkCorePixel(Color32 pixel)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		if (pixel.a >= 64)
		{
			return GetLuminance(pixel) <= 72;
		}
		return false;
	}

	private static byte GetCoreExpansionAlpha(int distance, int radius)
	{
		float num = Mathf.Clamp01(1f - (float)distance / (float)(radius + 1));
		return (byte)Mathf.Clamp(Mathf.RoundToInt(150f + 80f * num), 0, 255);
	}

	private static void BlendDarkCorePixel(ref Color32 target, byte alpha)
	{
		//IL_000b: 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_002d: Unknown result type (might be due to invalid IL or missing references)
		if ((target.a < 40 || GetLuminance(target) <= 96) && alpha > target.a)
		{
			target = new Color32((byte)2, (byte)4, (byte)6, alpha);
		}
	}

	private static int GetLuminance(Color32 pixel)
	{
		return pixel.r * 54 + pixel.g * 183 + pixel.b * 19 >> 8;
	}

	private static void SmoothAlphaEdges(Color32[] pixels, int width, int height)
	{
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0266: 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)
		if (pixels == null || pixels.Length == 0 || width < 3 || height < 3)
		{
			return;
		}
		int num = width;
		int num2 = height;
		int num3 = -1;
		int num4 = -1;
		for (int i = 0; i < height; i++)
		{
			int num5 = i * width;
			for (int j = 0; j < width; j++)
			{
				if (pixels[num5 + j].a > 4)
				{
					num = Math.Min(num, j);
					num2 = Math.Min(num2, i);
					num3 = Math.Max(num3, j);
					num4 = Math.Max(num4, i);
				}
			}
		}
		if (num3 < num || num4 < num2)
		{
			return;
		}
		Color32[] array = (Color32[])pixels.Clone();
		num = Math.Max(1, num - 1);
		num2 = Math.Max(1, num2 - 1);
		num3 = Math.Min(width - 2, num3 + 1);
		num4 = Math.Min(height - 2, num4 + 1);
		int[] array2 = new int[3] { 1, 2, 1 };
		for (int k = num2; k <= num4; k++)
		{
			for (int l = num; l <= num3; l++)
			{
				int num6 = k * width + l;
				bool flag = false;
				bool flag2 = false;
				int num7 = 0;
				int num8 = 0;
				int num9 = 0;
				int num10 = 0;
				int num11 = 0;
				for (int m = -1; m <= 1; m++)
				{
					int num12 = (k + m) * width;
					int num13 = array2[m + 1];
					for (int n = -1; n <= 1; n++)
					{
						Color32 val = array[num12 + l + n];
						int num14 = num13 * array2[n + 1];
						num7 += val.a * num14;
						if (val.a >= 16)
						{
							flag = true;
						}
						if (val.a <= 239)
						{
							flag2 = true;
						}
						int num15 = val.a * num14;
						num8 += val.r * num15;
						num9 += val.g * num15;
						num10 += val.b * num15;
						num11 += num15;
					}
				}
				if (flag && flag2)
				{
					Color32 val2 = array[num6];
					val2.a = (byte)Mathf.Clamp((num7 + 8) / 16, 0, 255);
					if (array[num6].a < 32 && num11 > 0)
					{
						val2.r = (byte)Mathf.Clamp(num8 / num11, 0, 255);
						val2.g = (byte)Mathf.Clamp(num9 / num11, 0, 255);
						val2.b = (byte)Mathf.Clamp(num10 / num11, 0, 255);
					}
					pixels[num6] = val2;
				}
			}
		}
	}

	private static SlashSettings ReadSettings(string path)
	{
		//IL_0054: 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_0277: Unknown result type (might be due to invalid IL or missing references)
		//IL_027c: Unknown result type (might be due to invalid IL or missing references)
		SlashSettings slashSettings = new SlashSettings();
		slashSettings.PixelsPerUnit = 200f;
		slashSettings.PivotX = 0.853f;
		slashSettings.PivotY = 0.511f;
		slashSettings.FlipX = false;
		slashSettings.Duration = 0.24f;
		slashSettings.HitboxAlphaThreshold = 64;
		slashSettings.HitboxBlockSize = 8;
		slashSettings.HitboxSimplify = 0.045f;
		slashSettings.Tint = Color.white;
		float num = 1f;
		float num2 = 1f;
		float num3 = 1f;
		float num4 = 1f;
		string[] array = WeaverPackagedAssets.ReadLines(path);
		for (int i = 0; i < array.Length; i++)
		{
			string text = array[i].Trim();
			if (text.Length == 0 || text.StartsWith("#", StringComparison.Ordinal))
			{
				continue;
			}
			int num5 = text.IndexOf('=');
			if (num5 <= 0)
			{
				continue;
			}
			string text2 = text.Substring(0, num5).Trim().ToLowerInvariant();
			if (!float.TryParse(text.Substring(num5 + 1).Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				continue;
			}
			if (text2 == "pixels_per_unit" && result > 0f)
			{
				slashSettings.PixelsPerUnit = result;
				continue;
			}
			switch (text2)
			{
			case "pivot_x":
				slashSettings.PivotX = result;
				continue;
			case "pivot_y":
				slashSettings.PivotY = result;
				continue;
			case "flip_x":
				slashSettings.FlipX = result != 0f;
				continue;
			case "duration":
				if (result > 0f)
				{
					slashSettings.Duration = result;
					continue;
				}
				break;
			}
			switch (text2)
			{
			case "hitbox_alpha_threshold":
				slashSettings.HitboxAlphaThreshold = (byte)Mathf.Clamp(Mathf.RoundToInt(result), 1, 255);
				continue;
			case "hitbox_block_size":
				slashSettings.HitboxBlockSize = Mathf.Clamp(Mathf.RoundToInt(result), 2, 32);
				continue;
			case "hitbox_simplify":
				if (result > 0f)
				{
					slashSettings.HitboxSimplify = result;
					continue;
				}
				break;
			}
			switch (text2)
			{
			case "tint_r":
				num = result;
				break;
			case "tint_g":
				num2 = result;
				break;
			case "tint_b":
				num3 = result;
				break;
			case "tint_a":
				num4 = result;
				break;
			}
		}
		slashSettings.Tint = new Color(num, num2, num3, num4);
		return slashSettings;
	}
}
internal sealed class WeaverSlashOverlayPlayer : MonoBehaviour
{
	internal Sprite[] Frames;

	internal float Duration = 0.24f;

	internal NailSlash Slash;

	internal string MoveId;

	private SpriteRenderer spriteRenderer;

	private float elapsed;

	private int lastIndex = -1;

	private int lastTuningVersion = -1;

	private bool sawActiveDamageWindow;

	private void Awake()
	{
		spriteRenderer = ((Component)this).GetComponent<SpriteRenderer>();
	}

	private void OnEnable()
	{
		elapsed = 0f;
		lastIndex = -1;
		lastTuningVersion = -1;
		sawActiveDamageWindow = false;
	}

	private void Update()
	{
		if (Frames == null || Frames.Length == 0 || (Object)(object)spriteRenderer == (Object)null)
		{
			return;
		}
		elapsed += Time.deltaTime;
		float num = ((Duration > 0f) ? (elapsed / Duration) : 1f);
		if (num > 1f)
		{
			num = 1f;
		}
		int num2 = ResolveFrameIndex(num);
		if ((Object)(object)Slash != (Object)null && Slash.IsSlashOut)
		{
			sawActiveDamageWindow = true;
		}
		else if (sawActiveDamageWindow && Frames.Length >= 3 && num2 < 2)
		{
			num2 = 2;
		}
		int tuningVersion = WeaverSlashSkin.TuningVersion;
		if (num2 != lastIndex || tuningVersion != lastTuningVersion)
		{
			if (num2 != lastIndex)
			{
				spriteRenderer.sprite = Frames[num2];
			}
			WeaverSlashSkin.ApplyRuntimeTransform(((Component)this).transform, MoveId);
			WeaverHitboxStore.SetFrame(Slash, num2);
			lastIndex = num2;
			lastTuningVersion = tuningVersion;
		}
	}

	private void LateUpdate()
	{
		WeaverSlashSkin.MaintainStockHidden(Slash);
	}

	private int ResolveFrameIndex(float progress)
	{
		return Mathf.Clamp(Mathf.FloorToInt(progress * (float)Frames.Length), 0, Frames.Length - 1);
	}
}
internal sealed class DamageProfileSnapshot
{
	internal float DamageMultiplier;

	internal bool MultiHitter;

	internal int StepsPerHit;

	internal float[] DamagePerHit;

	internal FreezeMomentTypes FirstHitFreeze;
}
internal static class DamageProfileStore
{
	private static readonly FieldInfo DamagePerHitField = AccessTools.Field(typeof(DamageEnemies), "damageMultPerHit");

	private static readonly FieldInfo FirstHitFreezeField = AccessTools.Field(typeof(DamageEnemies), "firstHitFreeze");

	private static readonly Dictionary<DamageEnemies, DamageProfileSnapshot> Snapshots = new Dictionary<DamageEnemies, DamageProfileSnapshot>();

	internal static void Apply(NailSlash slash, WeaverAttackProfile profile, float normalDamageMultiplier)
	{
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)slash == (Object)null || profile == WeaverAttackProfile.None || profile == WeaverAttackProfile.Up || profile == WeaverAttackProfile.DownFirst || profile == WeaverAttackProfile.DashFlurry)
		{
			return;
		}
		DamageEnemies[] componentsInChildren = ((Component)slash).GetComponentsInChildren<DamageEnemies>(true);
		foreach (DamageEnemies val in componentsInChildren)
		{
			Restore(val);
			DamageProfileSnapshot damageProfileSnapshot = new DamageProfileSnapshot();
			damageProfileSnapshot.DamageMultiplier = val.DamageMultiplier;
			damageProfileSnapshot.MultiHitter = val.multiHitter;
			damageProfileSnapshot.StepsPerHit = val.stepsPerHit;
			damageProfileSnapshot.DamagePerHit = DamagePerHitField.GetValue(val) as float[];
			damageProfileSnapshot.FirstHitFreeze = (FreezeMomentTypes)FirstHitFreezeField.GetValue(val);
			Snapshots[val] = damageProfileSnapshot;
			switch (profile)
			{
			case WeaverAttackProfile.Light:
				val.DamageMultiplier = damageProfileSnapshot.DamageMultiplier * normalDamageMultiplier;
				break;
			case WeaverAttackProfile.Heavy:
				val.DamageMultiplier = damageProfileSnapshot.DamageMultiplier;
				val.multiHitter = true;
				val.stepsPerHit = 1;
				DamagePerHitField.SetValue(val, new float[4] { 0.5f, 0.6f, 0.6f, 0.8f });
				FirstHitFreezeField.SetValue(val, (object)(FreezeMomentTypes)(-1));
				break;
			case WeaverAttackProfile.Dash:
				val.DamageMultiplier = damageProfileSnapshot.DamageMultiplier * 0.33f;
				val.multiHitter = false;
				DamagePerHitField.SetValue(val, null);
				FirstHitFreezeField.SetValue(val, (object)(FreezeMomentTypes)6);
				break;
			}
		}
	}

	internal static void RestoreSlash(NailSlash slash)
	{
		if (!((Object)(object)slash == (Object)null))
		{
			DamageEnemies[] componentsInChildren = ((Component)slash).GetComponentsInChildren<DamageEnemies>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Restore(componentsInChildren[i]);
			}
		}
	}

	internal static void Restore(DamageEnemies damager)
	{
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)damager == (Object)null) && Snapshots.TryGetValue(damager, out var value))
		{
			damager.DamageMultiplier = value.DamageMultiplier;
			damager.multiHitter = value.MultiHitter;
			damager.stepsPerHit = value.StepsPerHit;
			DamagePerHitField.SetValue(damager, value.DamagePerHit);
			FirstHitFreezeField.SetValue(damager, value.FirstHitFreeze);
			Snapshots.Remove(damager);
		}
	}

	internal static void RestoreAll()
	{
		DamageEnemies[] array = (DamageEnemies[])(object)new DamageEnemies[Snapshots.Count];
		Snapshots.Keys.CopyTo(array, 0);
		for (int i = 0; i < array.Length; i++)
		{
			Restore(array[i]);
		}
	}
}
internal static class SlashVisualProfileStore
{
	private static readonly Dictionary<NailSlash, Quaternion> Rotations = new Dictionary<NailSlash, Quaternion>();

	internal static void Apply(NailSlash slash, WeaverAttackProfile profile, HeroController hero)
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)slash == (Object)null) && !((Object)(object)hero == (Object)null))
		{
			Restore(slash);
			if (profile == WeaverAttackProfile.Dash || profile == WeaverAttackProfile.DashFlurry)
			{
				Rotations[slash] = ((Component)slash).transform.localRotation;
				float num = 0f;
				num = ((hero.cState.attackCount % 2 == 0) ? 16f : (-16f));
				((Component)slash).transform.localRotation = Rotations[slash] * Quaternion.Euler(0f, 0f, num);
			}
		}
	}

	internal static void Restore(NailSlash slash)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)slash == (Object)null) && Rotations.TryGetValue(slash, out var value))
		{
			((Component)slash).transform.localRotation = value;
			Rotations.Remove(slash);
		}
	}
}
internal enum WeaverAttackProfile
{
	None,
	Light,
	Heavy,
	Up,
	DownFirst,
	Dash,
	DashFlurry
}
internal sealed class DamageHeroState
{
	internal DamageHero Component;

	internal bool WasEnabled;

	internal int OriginalDamage;
}
internal sealed class CollisionIgnoreState
{
	internal Collider2D HeroCollider;

	internal Collider2D EnemyCollider;

	internal bool WasIgnored;
}
internal sealed class WeaverCombat : MonoBehaviour
{
	private enum AirSpinDamageOutcome
	{
		None,
		Blocked,
		Damaged
	}

	private sealed class AirSpinDamagerSnapshot
	{
		internal DamageEnemies Damager;

		internal AttackTypes AttackType;

		internal bool UseNailDamage;

		internal float NailDamageMultiplier;

		internal int DamageDealt;

		internal float DamageMultiplier;

		internal bool MultiHitter;

		internal int StepsPerHit;

		internal float MagnitudeMultiplier;

		internal bool IgnoreInvulnerable;

		internal bool ManualTrigger;

		internal bool HitOnceUntilEnd;

		internal bool CanWeakHit;

		internal float StunDamage;
	}

	private enum AirSpinLungePhase
	{
		Windup,
		Burst,
		Straight,
		Arc,
		Grind
	}

	private sealed class AssetWarmupStep
	{
		internal string Name;

		internal Action Run;

		internal Func<IEnumerator> Routine;
	}

	private sealed class BlinkDecoyHold
	{
		internal HealthManager Target;

		internal Transform Root;

		internal float Sign;
	}

	private sealed class ChargedWhipSatellite
	{
		internal GameObject Visual;

		internal LineRenderer TrailGlow;

		internal LineRenderer TrailCore;

		internal HealthManager Anchor;

		internal Vector2 Offset;

		internal Vector2 Position;

		internal Vector2 PreviousPosition;

		internal Vector2 Direction;

		internal float SpawnedAt;

		internal float AimDuration;

		internal float PauseDuration;

		internal float LaunchDelay;

		internal float InitialAngle;

		internal bool Fired;

		internal readonly HashSet<int> HitTargets = new HashSet<int>();

		internal readonly List<Vector3> Trail = new List<Vector3>();
	}

	private sealed class CocoonLoop
	{
		internal LineRenderer Core;

		internal LineRenderer Glow;

		internal float Tilt;

		internal float TiltSpeed;

		internal float Phase;

		internal float FlattenY;

		internal float RadiusScale;

		internal float AlphaScale;

		internal float SpawnAngle;

		internal float SpawnDelay;
	}

	private sealed class CocoonStrand
	{
		internal readonly List<CocoonLoop> Loops = new List<CocoonLoop>();

		internal float SnapStartedAt;

		internal float BreakAngle;
	}

	private struct CocoonImpulse
	{
		internal float AngleRadians;

		internal float Strength;

		internal float Spread;

		internal float StartedAt;
	}

	private sealed class CounterGuardVictim
	{
		internal WeaverEnemyControlLease Control;

		internal HealthManager Target;

		internal Rigidbody2D Body;

		internal GameObject Root;

		internal Vector3 RootOffset;

		internal float Gravity;

		internal float NextAttackCancelAt;

		internal readonly List<DamageHeroState> ContactDamage = new List<DamageHeroState>();

		internal readonly List<CollisionIgnoreState> IgnoredCollisions = new List<CollisionIgnoreState>();
	}

	private sealed class CounterRiposteCatch
	{
		internal HealthManager Target;

		internal CounterGuardVictim Victim;

		internal int JoinedBeat;

		internal float Side;

		internal int FanIndex;

		internal Vector2 CaughtAt;

		internal float CaughtTime;

		internal float BottomExtent;

		internal CounterStunPose Pose;
	}

	private sealed class CounterStunPose
	{
		internal tk2dSpriteAnimator Animator;

		internal tk2dSprite Sprite;

		internal tk2dSpriteAnimationClip Clip;

		internal tk2dSpriteAnimationClip OriginalClip;

		internal bool WasPlaying;

		internal float StartedAt;
	}

	private sealed class CrossSlashVictim
	{
		internal WeaverEnemyControlLease Control;

		internal HealthManager Target;

		internal Rigidbody2D Body;

		internal GameObject Root;

		internal Vector3 RootOffset;

		internal float Gravity;

		internal float BottomExtent;

		internal float TopExtent;

		internal float SlamDropHeight;

		internal bool Blacklisted;

		internal bool LoggedResponse;

		internal readonly List<CrossSlashAnimatorState> Animators = new List<CrossSlashAnimatorState>();

		internal readonly List<DamageHeroState> ContactDamage = new List<DamageHeroState>();

		internal readonly List<CollisionIgnoreState> IgnoredCollisions = new List<CollisionIgnoreState>();
	}

	private sealed class CrossSlashAnimatorState
	{
		internal tk2dSpriteAnimator Animator;

		internal tk2dSpriteAnimationClip OriginalClip;

		internal tk2dSpriteAnimationClip DeathClip;

		internal bool WasPlaying;

		internal bool WasPaused;

		internal int OriginalFrame;

		internal float PoseStartedAt;

		internal float OriginalFps;
	}

	private sealed class CrossSlashPendingFinisher
	{
		internal HealthManager Target;

		internal int Damage;
	}

	private struct CrossSlashSlamSurface
	{
		internal bool Found;

		internal bool Hazard;

		internal float Y;

		internal HazardType HazardType;
	}

	private struct SprintExitDanger
	{
		public Vector2 Position;

		public Vector2 Velocity;
	}

	private enum DownDiveContactType
	{
		None,
		BouncePod,
		Surface
	}

	private sealed class FinalAssistSilhouette
	{
		internal string Name;

		internal GameObject Root;

		internal float Scale;

		internal AudioClip[] Voices;

		internal bool VisibleBody;

		internal string[] PreferredClips;

		internal bool RequireActiveClip;

		internal tk2dSpriteAnimationClip SelectedClip;

		internal tk2dSpriteAnimationClip IdleClip;

		internal tk2dSpriteAnimationClip JumpClip;

		internal bool InvertFacing;
	}

	private sealed class AllOutAssistSpec
	{
		internal string Name;

		internal float Scale;

		internal int Archetype;

		internal string[] Aliases;

		internal string[] VoiceAliases;

		internal string[] VoiceNames;

		internal string[] BundleFiles;

		internal string[] AssetPaths;

		internal string[] PreferredClips;

		internal bool RequireActiveClip;

		internal string[] VoiceBundleFiles;

		internal bool InvertFacing;
	}

	private sealed class AllOutAttacker
	{
		internal string Name;

		internal FinalAssistSilhouette Assist;

		internal bool IsHero;
	}

	private struct AllOutPassTrajectory
	{
		internal Vector2 From;

		internal Vector2 To;

		internal bool FaceRight;

		internal float AngleDegrees;

		internal float Duration;
	}

	private sealed class FinalDialogueRenderer
	{
		internal Renderer Renderer;

		internal int Layer;

		internal int Order;
	}

	private sealed class FinalDialogueGroup
	{
		internal SortingGroup Group;

		internal int Layer;

		internal int Order;
	}

	private sealed class FinalRendererState
	{
		internal Renderer Renderer;

		internal int SortingLayerId;

		internal int SortingOrder;

		internal bool WasEnabled;

		internal MaterialPropertyBlock Properties;

		internal SpriteRenderer SpriteRenderer;

		internal Color SpriteColor;
	}

	private sealed class FinalParticleState
	{
		internal ParticleSystem System;

		internal bool UsedUnscaledTime;

		internal MinMaxGradient StartColor;
	}

	private sealed class FinalAnimatorState
	{
		internal Animator Animator;

		internal AnimatorUpdateMode UpdateMode;
	}

	private sealed class FinalEffectSprite
	{
		internal SpriteRenderer Renderer;

		internal Color BaseColor;

		internal Vector3 BaseScale;

		internal Vector3 BasePosition;

		internal Vector3 Drift;
	}

	private sealed class FinalExecutionCameraShake : ICameraShake
	{
		private readonly float magnitude;

		private readonly float duration;

		private readonly float phase;

		public bool CanFinish => true;

		public bool PersistThroughScenes => false;

		public int FreezeFrames => 0;

		public ICameraShakeVibration CameraShakeVibration => null;

		public CameraShakeWorldForceIntensities WorldForceOnStart => (CameraShakeWorldForceIntensities)0;

		public float Magnitude => magnitude;

		internal FinalExecutionCameraShake(float magnitude, float duration)
		{
			this.magnitude = magnitude;
			this.duration = duration;
			phase = Random.value * 10f;
		}

		public Vector2 GetOffset(float elapsedTime)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp01(elapsedTime / duration);
			float num2 = (1f - num) * (1f - num);
			float num3 = Mathf.Sin((elapsedTime + phase) * 91f);
			float num4 = Mathf.Cos((elapsedTime + phase * 0.73f) * 127f);
			return new Vector2(num3, num4 * 0.72f) * (magnitude * num2);
		}

		public bool IsDone(float elapsedTime)
		{
			return elapsedTime >= duration;
		}
	}

	private sealed class HeartGrabTravelResult
	{
		internal HealthManager Target;
	}

	private sealed class SilkStreamEmitter
	{
		internal string Name;

		internal bool Wispy;

		internal bool Looping;

		internal float Duration;

		internal float LifeMin;

		internal float LifeMax;

		internal float SpeedMin;

		internal float SpeedMax;

		internal float SizeMin;

		internal float SizeMax;

		internal float Gravity;

		internal int MaxParticles;

		internal float Rate;

		internal float ArcStart;

		internal float Arc;

		internal float ShapeRadius;

		internal bool Stretch;

		internal float SpinRadians;

		internal float[] SizeCurve;

		internal bool FullAlphaHold;

		internal bool RandomRow;

		internal bool SideJitter;
	}

	private sealed class PhantomDiveDragVictim
	{
		internal HealthManager Target;

		internal Rigidbody2D Body;

		internal Vector2 StartPosition;

		internal float LandingY;

		internal float DropHeight;
	}

	private const float AirSpinBladeInnerRadius = 0.16f;

	private const float AirSpinBladeArcDegrees = 132f;

	private const float AirSpinTargetPointLeeway = 0.85f;

	private const float AirSpinLargeColliderLimit = 8.5f;

	private const float AirSpinCooldown = 0.62f;

	private const float AirSpinSweepStartDegrees = 60f;

	private const float AirSpinSweepDegrees = 360f;

	private const float AirSpinWedgeSampleStepDegrees = 11f;

	private const float AirSpinWedgeSampleStepRadius = 0.5f;

	private const float AirSpinHitFreezeHold = 0.022f;

	private const float AirSpinHitFreezeMinGap = 0.06f;

	private const float AirSpinSceneFxMinGap = 0.11f;

	private const float AirSpinAdhesionDistance = 1.35f;

	private const float AirSpinAdhesionMinimumDistance = 0.75f;

	private const float AirSpinAdhesionMaxApproachSpeed = 4.5f;

	private const float AirSpinAdhesionMaxSpeed = 9.5f;

	private const float AirSpinAdhesionVelocityStep = 1.6f;

	private const string AirSpinProjectileBreakEvent = "PROJECTILE BREAK";

	private const float AirSpinFreezePauseThreshold = 0.1f;

	private const float AirSpinStunPerHit = 0.15f;

	private const string AirSpinRecoveryClip = "DownSpikeBounce 1";

	private const int AirSpinRecoveryFrame = 34;

	private const int AirSpinBodyFrameCount = 12;

	private const float AssetWarmupCheckInterval = 0.5f;

	private const int AssetWarmupSettleFrames = 2;

	private const double AssetWarmupSlowStepMs = 8.0;

	private const float WeaverBackstepDownInputBuffer = 0.12f;

	private const float WeaverBackstepAnticTravelFraction = 0.22f;

	private const float WeaverBackstepPeakSpeedProgress = 0.2f;

	private const float WeaverBackstepHopPeakProgress = 0.42f;

	private const float WeaverBackstepHopHeight = 0.32f;

	private const float WeaverBackstepBurstFrontOffset = 1.4f;

	private const float WeaverBackstepBurstVerticalOffset = -0.42f;

	private const float WeaverBackstepReentryBuffer = 0.35f;

	private const float WeaverBackstepRecoveryFps = 20f;

	private const float WeaverBackstepCompletionHoldDuration = 1f / 60f;

	private const int WeaverBackstepTravelFrameCount = 6;

	private const int WeaverBackstepRecoveryFirstFrame = 6;

	private const string WeaverBackstepFrameResourcePrefix = "WeaverCrest.Assets.Imported.HK1HornetEvade.";

	private const float WeaverBackstepForwardDashGrace = 0.18f;

	private const float WeaverBackstepBaseDistance = 3.2f;

	private const float WeaverBackstepHoldExtensionSpeedFactor = 1.2f;

	private const string BlinkFlashPrefix = "WeaverCrest.Assets.Imported.FirstWeaverBlink.";

	internal const string BlinkTelePrefix = "WeaverCrest.Assets.Imported.FirstWeaverTele.";

	private const int BlinkTwirlFirstFrame = 1;

	private const int BlinkTwirlLastFrame = 6;

	private const float BlinkTwirlOutSeconds = 0.12f;

	private const float BlinkTwirlInSeconds = 0.12f;

	private const float BlinkTeleFrameSeconds = 1f / 45f;

	private const int BlinkTeleOutFirst = 5;

	private const int BlinkTeleOutLast = 9;

	private const int BlinkTeleInFrames = 3;

	private const float BlinkDecoyRadius = 12f;

	private const float BlinkLineHalfHeight = 2.5f;

	private const float BlinkExitMargin = 1.5f;

	private const float BrutalSmashAimMarkerRadius = 2.4f;

	private const float BrutalSmashEvaHealScale = 0.7898965f;

	private const float BrutalSmashAimHalfAngle = 70f;

	private const float BrutalSmashAimStartAngle = -35f;

	private const float BrutalSmashAimSweepDegreesPerSecond = 210f;

	private const float BrutalSmashAimHoldThreshold = 0.12f;

	private const float BrutalSmashProjectileSpeed = 60f;

	private const float BrutalSmashProjectileRange = 32f;

	private const float BrutalSmashProjectileRadius = 1.45f;

	private const float BrutalSmashExplosionRadius = 5f;

	private const float BrutalSmashExplosionDamageDuration = 0.5f;

	private const float BrutalSmashHomingRange = 10f;

	private const float BrutalSmashHomingTurnRate = 75f;

	private const float BrutalSmashDamageMultiplier = 3f;

	private const float BrutalSmashFallDamagePerUnit = 0.2f;

	private const float BrutalSmashMinimumFallHeight = 0.8f;

	private const float BrutalSmashReleaseSpeedMultiplier = 1.65f;

	private const float BrutalSmashReleaseAnticHoldDuration = 0.055f;

	private const float BrutalSmashProjectilePixelsPerUnit = 256f;

	private const float BrutalSmashProjectileVisualScaleX = 1.38f;

	private const float BrutalSmashProjectileVisualScaleY = 1.22f;

	private const float BrutalSmashAfterimageDefaultDensity = 0.75f;

	private const int BrutalSmashAfterimageDefaultMaxVisibleCount = 4;

	private const float BrutalSmashAfterimageLifetime = 0.14f;

	private const float BrutalSmashRepeatCooldown = 0.65f;

	private const float BrutalSmashLockMaxFlightSeconds = 3f;

	private const float ChargedWhipSwingDuration = 0.27f;

	private const float ChargedWhipInputOpen = 0.1f;

	private const float ChargedWhipInputClose = 0.38f;

	private const float ChargedWhipReverseArcDuration = 0.105f;

	private const float ChargedWhipThrustDuration = 0.09f;

	private const float ChargedWhipReturnArcDuration = 0.125f;

	private const float ChargedWhipFadeDuration = 0.075f;

	private const float ChargedWhipEllipseRadiusX = 3.6f;

	private const float ChargedWhipEllipseRadiusY = 2.2f;

	private const float ChargedWhipThrustDistance = 8f;

	private const float ChargedWhipSweepRadius = 0.48f;

	private const float ChargedWhipThreadSweepRadius = 0.24f;

	private const float ChargedWhipSatelliteSpeed = 28f;

	private const float ChargedWhipSatelliteFlightDuration = 0.64f;

	private const int CocoonDefaultStrandCount = 6;

	private const float CocoonDefaultDuration = 20f;

	private const float CocoonDefaultRadius = 1.25f;

	private const float CocoonDefaultVerticalOffset = 0.25f;

	private const float CocoonDefaultShotDurationCost = 0.8f;

	private const float CocoonDefaultContactDamage = 0.25f;

	private const float CocoonDefaultContactInterval = 0.45f;

	private const float CocoonDefaultContactDurationCost = 0.6f;

	private const int CocoonDefaultVisualLoopCount = 12;

	private const int CocoonStrandSegments = 96;

	private const float CocoonCoreWidth = 0.1f;

	private const float CocoonGlowWidth = 0.42f;

	private const float CocoonCoreAlpha = 1f;

	private const float CocoonGlowAlpha = 0.24f;

	private const float CocoonBubbleAlpha = 1f;

	private const float CocoonWobbleSpeed = 2.4f;

	private const float CocoonDefaultCastWindup = 0.6f;

	private const float CocoonDefaultCastAnimSpeed = 1.35f;

	private const float CocoonExpiryFadeWindow = 1.5f;

	private const float CocoonAbsorbGraceDuration = 0.4f;

	private const float CocoonWeaveStartFraction = 0.3f;

	private const float CocoonWeaveEndFraction = 0.82f;

	private const float CocoonBubbleStartFraction = 0.78f;

	private const float CocoonRuneFadeInDuration = 0.35f;

	private const float CocoonStrandSnapDuration = 0.34f;

	private const float CocoonSnapWhipFrequency = 34f;

	private const float CocoonSnapRecoil = 0.3f;

	private const float CocoonSnapPreFlareWindow = 0.25f;

	private const float CocoonSnapPreFlareBoost = 2.4f;

	private const float CocoonSnapFlashDuration = 0.34f;

	private const float CocoonSnapFlashStartScale = 0.9f;

	private const float CocoonImpulseDuration = 0.55f;

	private const float CocoonImpulseFrequency = 9f;

	private const float CocoonImpulseDecay = 5.5f;

	private const float CocoonBreakPitchMin = 1.4f;

	private const float CocoonBreakPitchMax = 1.65f;

	private const float CocoonStrainVolume = 0.4f;

	private const float CocoonCastVolume = 0.7f;

	private const string CocoonProjectileTinkEvent = "DAMAGER TINKED";

	private const int CocoonSoftEdgeTextureHeight = 64;

	private const int CocoonBubbleTextureSize = 192;

	private const string CocoonRuneRingResource = "WeaverCrest.Assets.Effects.CocoonRune.rune_ring.png";

	private const string CocoonRuneGlyphResource = "WeaverCrest.Assets.Effects.CocoonRune.rune_glyph.png";

	private const float NormalOneAttackDuration = 0.24f;

	private const float NormalOneToTwoCooldown = 0.24f;

	private const float ScriptedMoveWatchdogTimeout = 8f;

	private const float CounterGuardWindow = 0.72f;

	private const float CounterGuardRecoverTime = 0.18f;

	private const float CounterRushSpeed = 48f;

	private const float CounterRushThreshold = 4.4f;

	private const float CounterTargetDistance = 4.05f;

	private const float CounterRecoveryInvulnerability = 0.42f;

	private const float CounterThrustForwardOffset = 0.55f;

	private const float CounterThrustVerticalOffset = 1.15f;

	private const float CounterThrustScale = 1.02f;

	private const int CounterThrustVisualCount = 34;

	private const float CounterThrustVisualInterval = 0.034f;

	private const int CounterHitCount = 10;

	private const float CounterHitDamage = 0.15f;

	private const float CounterHitInterval = 0.12f;

	private const float CounterRiposteReach = 7f;

	private const float CounterRiposteSampleStep = 0.2f;

	private const byte CounterRiposteAlphaThreshold = 48;

	private const float CounterRiposteGatherSeconds = 0.08f;

	private const float CounterRiposteFanDegrees = 9f;

	private const float CounterRiposteAnticFrameSeconds = 0.025f;

	private const float CounterGuardContactMargin = 0.15f;

	private const float CounterParryStanceWindow = 0.4f;

	private const float CounterParryAnticDuration = 0.09f;

	private const float CounterThrowAnticDuration = 0.13f;

	private const float CounterThrowArcDuration = 0.34f;

	private const float CounterThrowSlamDuration = 0.11f;

	private const float CounterThrowRecoverDuration = 0.16f;

	private const float CounterThrowRadius = 2.65f;

	private const float CounterThrowArcDegrees = 180f;

	private const float CounterThrowSlamProbe = 12f;

	private const int CounterThrowStunPoseFps = 12;

	internal const float CounterParrySuccessFreeze = 0.07f;

	private const float CounterThrowStartFreeze = 0.045f;

	private const float CounterThrowLiftFreeze = 0.06f;

	private const float CounterThrowSlamFreeze = 0.16f;

	private const float CounterThrowStartShare = 0.25f;

	private const float CounterThrowLiftShare = 0.25f;

	private const float CounterThrowSlamShare = 0.5f;

	private const float CounterThrowMinBehindDistance = 0.9f;

	private const int CrossSlashSkillPassCount = 6;

	private const float CrossSlashSkillRadius = 5.6f;

	private const float CrossSlashNativeAttackGlowStartTime = 1.0333333f;

	private const float CrossSlashNativeAttackGlowDuration = 0.7f;

	private const float CrossSlashOriginalPassDuration = 0.11f;

	private const float CrossSlashOriginalPassPause = 0.045f;

	private const float CrossSlashOriginalPassSequenceDuration = 0.885f;

	private const float CrossSlashPassTimingScale = 140f / 177f;

	private const float CrossSlashSkillEntryDuration = 0.1f;

	private const float CrossSlashSkillPassDuration = 0.087005645f;

	private const float CrossSlashSkillPassPause = 0.035593223f;

	private const float CrossSlashSkillPostPassPause = 0.045f;

	private const float CrossSlashSkillPreSlamPause = 0.13f;

	private const float CrossSlashSkillSlamSpeed = 78f;

	private const float CrossSlashSkillSlamMaxSpeed = 110f;

	private const float CrossSlashSkillSlamAcceleration = 260f;

	private const float CrossSlashSkillMaxSlamDrop = 24f;

	private const float CrossSlashSkillSlamApexHeight = 1.6f;

	private const float CrossSlashSkillSlamRiseDuration = 0.12f;

	private const float CrossSlashSkillSlamProbeRange = 200f;

	private const float CrossSlashSkillSlamMaxCarrySeconds = 1.4f;

	private const float CrossSlashSkillHazardReleaseHeight = 3f;

	private const float CrossSlashSkillHazardHurlDuration = 0.14f;

	private const float CrossSlashSkillDustSpacing = 1.5f;

	private const float CrossSlashSkillDustWaveSpeed = 45f;

	private const float CrossSlashSkillSlamHeroHeadroom = 0.15f;

	private const float CrossSlashSkillExitInvulnerabilitySeconds = 0.8f;

	private const float CrossSlashSkillTravelRadiusScale = 0.74f;

	private const float CrossSlashSkillRushCaptureRadius = 0.9f;

	private const float CrossSlashSkillRushCaptureSpacing = 0.5f;

	private const float CrossSlashSkillWatchdogSeconds = 5.5f;

	private const float CrossSlashSkillHitDamage = 0.3f;

	private const float CrossSlashSkillSlamDamage = 1.2f;

	private const float CrossSlashSkillHeightDamagePerUnit = 0.08f;

	private const float CrossSlashSkillCaptureRadiusScale = 0.9f;

	private const float CrossSlashSkillCaptureScanInterval = 0.05f;

	private const int SprintExecHitCount = 3;

	private const float SprintExecPassDuration = 0.055f;

	private const float SprintExecEntryDuration = 0.075f;

	private const float SprintExecExitDuration = 0.13f;

	private const float SprintBodyVisualStretch = 0.95f;

	private const float SprintBodyVisualSquash = 0.52f;

	private const float SprintBodyBlurAlpha = 0.34f;

	private const float SprintBodyBlurLife = 0.055f;

	private const float SprintBodyBlurSpacing = 0.45f;

	private const int SprintBodyBlurMaxSamples = 12;

	private const float SprintSafeExitEnemyRadius = 4.2f;

	private const float SprintSafeExitDangerRadius = 2.4f;

	private const int SprintSafeExitPathSamples = 6;

	private const float SprintSafeExitDangerLookahead = 0.9f;

	private const float SprintSafeExitDangerScanRadius = 26f;

	private const float DashChargeVoiceVolume = 0.7f;

	private const float DashChargeVoiceFade = 0.1f;

	private const float DashChargeVoiceLeadIn = 0.15f;

	private const float DashCollisionFallbackAttackDuration = 0.17f;

	private const float DashCollisionInvulnerability = 0.135f;

	private const float DashCollisionHitstop = 0.06f;

	private const float DashChargeVoiceHoldThreshold = 0.08f;

	private const string DashCollisionBonkClipName = "Sprint Bonk";

	private const float DownDiveInitialFallSpeed = 44f;

	private const float DownDiveAcceleration = 220f;

	private const float DownDiveMaxFallSpeed = 62f;

	private const float DownDiveVoiceInterval = 0.34f;

	private const float DownDiveMaxDuration = 1.5f;

	private const float DownDiveCooldown = 0.16f;

	private const float DownDiveBladeWidth = 3.5f;

	private const float DownDiveBladeHeight = 2.3f;

	private const float DownDiveBladeOffsetY = -1.5f;

	private const float DownDiveHitstopHold = 0.065f;

	private const float DownDiveStunPerHit = 0.18f;

	private const float DownDiveSwingDuration = 0.27f;

	private const float DownDiveEnemyExitDuration = 0.28f;

	private const float DownDiveMissExitSpeedX = 9f;

	private const float DownDiveMissExitSpeedY = 2.5f;

	private const string DownDiveNativeAnimationAsset = "Assets/Animations/Knight.prefab";

	private const string DownDiveNativeBodyAnimationAsset = "Assets/Animations/Cutscene/Crest Get Anim.prefab";

	private const string DownDiveNativeBladeClipName = "DownSlashEffect";

	private const string DownDiveNativeAudioAsset = "";

	private const string DownDiveNativeSwingClipName = "";

	private const float ExecutionRecoveryDelay = 10f;

	private const float ExecutionRecoveryDistance = 24f;

	private const int AllOutRushPassCount = 18;

	private const int DeltaruneBulletWaveCount = 4;

	private const int DeltaruneFrenzySlashCount = 10;

	private const float DeltaruneHeartHopInterval = 0.12f;

	private const int FinalExecutionHealthThreshold = 35;

	private const int FinalExecutionOverlayOrder = 30000;

	private const float HeartGrabLungeMaxDistance = 16.5f;

	private const float HeartGrabLeapMaxDistance = 14.3f;

	private const float HeartGrabCarryMaxSeconds = 1.5f;

	private const float HeartGrabSlideSeconds = 0.4f;

	private const float HeartGrabReach = 1.35f;

	private const float HeartGrabSearchRadius = 15f;

	private const float HeartGrabCooldown = 0.35f;

	private const float HeartGrabAttachSeconds = 0.3f;

	private const float HeartGrabStruggleSeconds = 0.3f;

	private const float HeartGrabSettleDelay = 0.16f;

	private const float HeartGrabLandSeconds = 0.32f;

	private const float HeartGrabAnticFrameSeconds = 0.07f;

	private const float HeartGrabLeapAnticFrameSeconds = 0.04f;

	private const float HeartGrabRipFrameSeconds = 0.09f;

	private const float HeartGrabTumbleFrameSeconds = 0.035f;

	private const int HeartGrabBossHits = 8;

	private const float HeartGrabBossHitDamage = 0.55f;

	private const float HeartGrabBossHitInterval = 0.07f;

	private const int HeartGrabSilkReward = 6;

	private const string SilkStreamPrefix = "WeaverCrest.Assets.Imported.PhantomSilkStream.";

	private const float SilkStreamGushSeconds = 0.75f;

	private const string Hk1HornetVoiceResourcePrefix = "WeaverCrest.Assets.Imported.HK1HornetVoice.";

	private const float BackstepVoiceChance = 0.4f;

	private const float WeaverTimeCastPhysicsMaxStep = 0.0016f;

	private const int WeaverTimeCastPhysicsMaxStepsPerFrame = 8;

	private const float NormalAttackAdvanceDuration = 0.18f;

	private const float OneHitCounterDamageMultiplier = 0.3f;

	private const int OneHitCounterHitCount = 6;

	private const float OneHitCounterPostInvulnerability = 1f;

	private const float OneHitCounterSlashLifetime = 0.21f;

	private const float OneHitCounterFacingRecoveryLock = 0.12f;

	private const int OneHitBodyLoopFirstFrame = 3;

	private const float OneHitBodyLoopFps = 12f;

	private const float OneHitBodyOpeningFrameTravelFraction = 0.18f;

	private const string OneHitSlashPrefabAsset = "Assets/Prefabs/Enemies/Hit Effects/Thread Sphere Slash.prefab";

	private const string OneHitBodyBundle = "atlases_assets_assets/sprites/_atlases/heart_deaths.spriteatlas.bundle";

	private const string OneHitBodyAtlasAsset = "Assets/Sprites/_Atlases/Heart_Deaths.spriteatlas";

	private const string OneHitBodyEmbeddedResourcePrefix = "WeaverCrest.Assets.Effects.OneHitBody.";

	private const string OneHitSlashPrefabBundle = "sharedeffects_assets_all.bundle";

	private const string OneHitSlashAnimationBundle = "animations_assets_shared.bundle";

	private const string OneHitSlashAtlasBundle = "atlases_assets_assets/sprites/_atlases/hornet.spriteatlas.bundle";

	private const float PhantomDiveMaxDescentSeconds = 4f;

	private const float PhantomDiveRiseDuration = 0.18f;

	private const float PhantomDiveTelegraphDuration = 0.58f;

	private const float PhantomDiveNativeFocusClipDuration = 1.2f;

	private const float PhantomDiveFallDuration = 0.12f;

	private const float PhantomDiveNoTargetHoverDuration = 0.24f;

	private const float PhantomDiveNoTargetReturnDuration = 0.24f;

	private const float PhantomDiveSkyHeight = 12f;

	private const float PhantomDiveImpactWidth = 10.291615f;

	private const float PhantomDiveTargetRange = 11.5f;

	private const float PhantomDiveImpactHeight = 12f;

	private const float PhantomDiveLaunchDuration = 0.42f;

	private const float PhantomDiveBaseDamage = 2f;

	private const float PhantomDiveHeightDamagePerUnit = 0.22f;

	private const float PhantomDiveMinDragHeight = 0.75f;

	private const float PhantomDiveWallDamage = 1.25f;

	private const float PhantomDivePostImpactInvulnSeconds = 1.2f;

	private const float EffectDepthStep = 0.001f;

	private const float SilkBulletDefaultSpeed = 32f;

	private const float SilkBulletDefaultLaunchAngle = 10f;

	private const float SilkBulletDefaultGravity = 24f;

	private const float SilkBulletDefaultLifetime = 1.2f;

	private const float SilkBulletDefaultDamageMultiplier = 0.2f;

	private const float SilkBulletDefaultHitRadius = 0.35f;

	private const int SilkBulletDefaultVolleyCount = 4;

	private const float SilkBulletDefaultVolleySpread = 14f;

	private const float SilkBulletDefaultVolleyRange = 18f;

	private const float SilkBulletPixelsPerUnit = 64f;

	private const float SilkBulletSpawnForwardOffset = 0.9f;

	private const float SilkBulletSpawnVerticalOffset = 1f;

	private const float SilkBulletShotVolume = 0.55f;

	private const float SilkBulletImpactVolume = 0.7f;

	private const string SilkBulletTerrainEffectName = "Nail Terrain Hit Effect";

	internal const string WeaverDashEntryState = "Weaver Dash Start";

	internal const string WeaverDashAnticState = "Weaver Dash Antic";

	internal const string WeaverDashAttackState = "Weaver Dash Attack";

	internal const string WeaverDashSkidState = "Weaver Dash Skid";

	private const float SustainedSprintStrikeInterval = 0.16f;

	private const float SustainedSprintComboGrace = 0.42f;

	private const float SustainedSprintMinimumComboGrace = 0.18f;

	private const float SustainedSprintStandOff = 2.7f;

	private const float SustainedSprintHitRange = 5.4f;

	private const float SustainedSprintHitHeight = 3.2f;

	private const float SustainedSprintDamage = 0.35f;

	private const float SustainedSprintEnemySlow = 0.55f;

	private const float SustainedSprintEnemySlowDuration = 0.24f;

	private const float SustainedSprintSliceInnerScale = 0.88f;

	private const int SustainedSprintMaxBufferedStrikes = 3;

	private const float SustainedSprintClashCooldown = 0.18f;

	private const float SustainedSprintClashFreezeCooldown = 0.65f;

	private const float SustainedSprintVoiceInterval = 0.34f;

	private const float SustainedSprintPostRetreatInvulnerabilityDuration = 0.55f;

	private const string FirstWeaverCollectionAsset = "Assets/Collections/First Weaver Cln Data/First Weaver Cln.prefab";

	private const string FirstWeaverAnimationAsset = "Assets/Animations/Hornet Enemies/First Weaver Anim.prefab";

	private const string FirstWeaverAttackAudioAsset = "Assets/Audio/SFX/HornetEnemy/Spinner/widow_run_n_slash.wav";

	private const float SustainedSprintResumeBridgeMaxSeconds = 0.3f;

	private const float TargetedDiveSpeed = 52f;

	private const float TargetedDiveWindUpDistanceSpeed = 46f;

	private const float TargetedDiveRange = 16f;

	private const float TargetedDiveBladeReach = 0.85f;

	private const int TargetedDiveInvulnerabilitySteps = 6;

	private const float TargetedDiveLineOfSightSkip = 0.35f;

	private const float PerfectDodgeConfirmWindow = 0.2f;

	private const float PerfectDodgeVacateWindow = 0.3f;

	private const int PerfectDodgeAttackLayerMask = 12587008;

	private const float LinkTimeScale = 0.08f;

	private const float HeroTimeScale = 0.35f;

	private const float PostLandingWindow = 0.75f;

	private const float WeaverTimeCooldownDuration = 1f;

	private const float MusicDuckMultiplier = 0.25f;

	private static readonly float[] AirSpinDamageSequence = new float[4] { 0.3f, 0.3f, 0.2f, 0.2f };

	private static readonly float[] AirSpinSilkSequence = new float[6] { 0.6f, 0.3f, 0.5f, 0.2f, 0.2f, 0.6f };

	private static bool airSpinClipLogged;

	private static Texture2D airSpinFanTexture;

	private static Sprite airSpinFanSprite;

	private static GameObject airSpinTerrainFxPrefab;

	private static GameObject airSpinClashFxPrefab;

	private static GameObject airSpinParryFxPrefab;

	private static bool airSpinFeedbackResolved;

	private bool airSpinSfxResolved;

	private RandomAudioClipTable airSpinSfxTable;

	private AudioClip airSpinSfxClip;

	private bool airSpinActive;

	private Coroutine airSpinRoutine;

	private GameObject airSpinVisualRoot;

	private WeaverImportedHornetBody airSpinBody;

	private NailSlash airSpinDamageSlash;

	private DamageEnemies airSpinDamageBackend;

	private Collider2D airSpinDamageCollider;

	private DamageEnemies airSpinPreviousCurrentDamager;

	private AirSpinDamagerSnapshot airSpinDamagerSnapshot;

	private int airSpinAnimationControlVersion = -1;

	private bool airSpinAnimationControlStopped;

	private float airSpinBladeAngle;

	private float airSpinCooldownUntil;

	private float airSpinAirborneSince = -1f;

	private bool airSpinWasGrounded = true;

	private bool airSpinHasBeenGrounded;

	private float airSpinNextHitFreezeTime;

	private float airSpinNextSceneFxTime;

	private HealthManager airSpinAdhesionTarget;

	private bool airSpinLoggedFirstHit;

	private bool airSpinQueuedBounce;

	private bool airSpinLoggedFirstSceneHit;

	private readonly Dictionary<int, float> airSpinNextTargetHitTimes = new Dictionary<int, float>();

	private int airSpinChargeTicks;

	private readonly HashSet<int> airSpinChargeHitIndices = new HashSet<int>();

	private readonly Dictionary<int, int> airSpinTargetHitCounts = new Dictionary<int, int>();

	private readonly HashSet<int> airSpinSceneInteractions = new HashSet<int>();

	private GameObject airSpinSweepObject;

	private Rigidbody2D airSpinSweepBody;

	private CircleCollider2D airSpinSweepCollider;

	private Coroutine airSpinSilkSweepRoutine;

	private static Camera airSpinCachedCamera;

	private GameObject airSpinBounceObject;

	private readonly HashSet<int> airSpinBounceResponders = new HashSet<int>();

	private PolygonCollider2D airSpinBounceCollider;

	private float airSpinBounceRadius;

	priv