Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of WeaverCrest v0.1.4
BepInEx/plugins/WeaverCrest/WeaverCrest.dll
Decompiled 4 days ago
The result has been truncated due to the large size, download it to view full contents!
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