Decompiled source of LobbyReactions v1.0.1

LobbyReactions.dll

Decompiled 3 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using LobbyReactions.Core;
using LobbyReactions.Net;
using LobbyReactions.Net.Commands;
using LobbyReactions.Players;
using LobbyReactions.UI;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.TextCore;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("RED")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+46a9ecc61c0cc989f2f8eb583872cc48ef802219")]
[assembly: AssemblyProduct("LobbyReactions")]
[assembly: AssemblyTitle("LobbyReactions")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace LobbyReactions.UI
{
	internal static class FallbackFontRules
	{
		internal const string SharedName = "SP-CyrillicFallback";

		internal static bool ShouldRegister(bool triedThisProcess, IEnumerable<string?>? globalFallbackNames)
		{
			if (triedThisProcess)
			{
				return false;
			}
			if (globalFallbackNames == null)
			{
				return true;
			}
			foreach (string globalFallbackName in globalFallbackNames)
			{
				if (string.Equals(globalFallbackName, "SP-CyrillicFallback", StringComparison.Ordinal))
				{
					return false;
				}
			}
			return true;
		}

		internal static bool PumpsBeforeLobby(BridgeVerdict bridge)
		{
			return bridge == BridgeVerdict.Absent;
		}
	}
	internal enum WheelKeyVerdict
	{
		Usable,
		Off,
		NotKeyboard,
		GameKey,
		SharePermissionsKey
	}
	internal static class HotkeyRules
	{
		internal const int None = 0;

		internal const int Escape = 27;

		internal const int Mouse0 = 323;

		internal const int Mouse6 = 329;

		internal const int JoystickButton0 = 330;

		internal static bool IsKeyboardKey(int key)
		{
			if (key > 0)
			{
				switch (key)
				{
				default:
					return key < 330;
				case 27:
				case 323:
				case 324:
				case 325:
				case 326:
				case 327:
				case 328:
				case 329:
					break;
				}
			}
			return false;
		}

		internal static WheelKeyVerdict JudgeWheelKey(int wheel, bool gameUsesKey, bool takenBySharePermissions = false)
		{
			if (wheel == 0)
			{
				return WheelKeyVerdict.Off;
			}
			if (!IsKeyboardKey(wheel))
			{
				return WheelKeyVerdict.NotKeyboard;
			}
			if (takenBySharePermissions)
			{
				return WheelKeyVerdict.SharePermissionsKey;
			}
			if (!gameUsesKey)
			{
				return WheelKeyVerdict.Usable;
			}
			return WheelKeyVerdict.GameKey;
		}

		internal static int EffectiveWheelKey(int configured, bool takenBySharePermissions)
		{
			if (!takenBySharePermissions)
			{
				return configured;
			}
			return 0;
		}

		internal static string Why(WheelKeyVerdict verdict)
		{
			return verdict switch
			{
				WheelKeyVerdict.Off => "is None (the wheel is off)", 
				WheelKeyVerdict.NotKeyboard => "is not a key the wheel takes (Esc, a mouse or joystick button, F16 and up)", 
				WheelKeyVerdict.GameKey => "is bound by R.E.P.O.", 
				WheelKeyVerdict.SharePermissionsKey => "is a key SharePermissions uses", 
				_ => "is usable", 
			};
		}
	}
	internal sealed class WheelKeyWarnings
	{
		private int refusedKey;

		private WheelKeyVerdict refusedWhy;

		internal bool ShouldWarn(int key, WheelKeyVerdict verdict)
		{
			if (verdict == WheelKeyVerdict.Usable)
			{
				refusedKey = 0;
				refusedWhy = WheelKeyVerdict.Usable;
				return false;
			}
			if (key == refusedKey && verdict == refusedWhy)
			{
				return false;
			}
			refusedKey = key;
			refusedWhy = verdict;
			return true;
		}
	}
	internal static class KeyText
	{
		private const string AlphaPrefix = "Alpha";

		private const string KeypadPrefix = "Keypad";

		private const string KeyboardDevice = "<Keyboard>";

		internal static bool IsKeyboardBindingFor(string? bindingPath, string keyCodeName)
		{
			if (bindingPath == null)
			{
				return false;
			}
			int num = bindingPath.IndexOf('/');
			if (num <= 0 || num == bindingPath.Length - 1)
			{
				return false;
			}
			if (!string.Equals(bindingPath.Substring(0, num), "<Keyboard>", StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			string a = bindingPath.Substring(num + 1);
			string[] array = ControlNames(keyCodeName);
			foreach (string b in array)
			{
				if (string.Equals(a, b, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		internal static string[] ControlNames(string keyCodeName)
		{
			string text = DigitAfter("Alpha", keyCodeName);
			if (text != null)
			{
				return new string[1] { text };
			}
			if (keyCodeName.Length > "Keypad".Length && keyCodeName.StartsWith("Keypad", StringComparison.Ordinal))
			{
				return new string[1] { "numpad" + keyCodeName.Substring("Keypad".Length) };
			}
			switch (keyCodeName)
			{
			case "Return":
				return new string[1] { "enter" };
			case "LeftShift":
				return new string[2] { "leftShift", "shift" };
			case "RightShift":
				return new string[2] { "rightShift", "shift" };
			case "LeftControl":
				return new string[2] { "leftCtrl", "ctrl" };
			case "RightControl":
				return new string[2] { "rightCtrl", "ctrl" };
			case "LeftAlt":
				return new string[2] { "leftAlt", "alt" };
			case "RightAlt":
			case "AltGr":
				return new string[3] { "rightAlt", "altGr", "alt" };
			case "LeftApple":
			case "LeftWindows":
			case "LeftCommand":
			case "LeftMeta":
				return new string[4] { "leftMeta", "leftWindows", "leftCommand", "leftApple" };
			case "RightMeta":
			case "RightApple":
			case "RightWindows":
			case "RightCommand":
				return new string[4] { "rightMeta", "rightWindows", "rightCommand", "rightApple" };
			case "Print":
				return new string[1] { "printScreen" };
			case "Menu":
				return new string[1] { "contextMenu" };
			default:
				return new string[1] { keyCodeName };
			}
		}

		private static string? DigitAfter(string prefix, string keyCodeName)
		{
			if (keyCodeName.Length != prefix.Length + 1 || !keyCodeName.StartsWith(prefix, StringComparison.Ordinal) || keyCodeName[prefix.Length] < '0' || keyCodeName[prefix.Length] > '9')
			{
				return null;
			}
			return keyCodeName.Substring(prefix.Length);
		}
	}
	internal static class KeyUse
	{
		private static bool gameKeysUnreadableLogged;

		private static bool menuLibLooked;

		private static Func<bool>? menuLibFocus;

		private static bool menuLibFocusFailedLogged;

		private const string MenuLibAssembly = "MenuLib";

		private const string MenuLibInputType = "MenuLib.MonoBehaviors.REPOInputStringSystem";

		internal unsafe static bool GameUsesKey(KeyCode key)
		{
			try
			{
				return GameUsesKeyRaw(((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString());
			}
			catch (Exception ex)
			{
				if (!gameKeysUnreadableLogged)
				{
					gameKeysUnreadableLogged = true;
					Plugin.Logger.LogWarning((object)("Game key bindings unreadable, the wheel key's check against them is skipped (logged once): " + ex.GetType().Name + ": " + ex.Message));
				}
				return false;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool GameUsesKeyRaw(string keyCodeName)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Invalid comparison between Unknown and I4
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			InputManager instance = InputManager.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			foreach (InputKey value in Enum.GetValues(typeof(InputKey)))
			{
				if ((int)value != 22 && KeyText.IsKeyboardBindingFor(instance.GetKeyString(value), keyCodeName))
				{
					return true;
				}
			}
			foreach (MovementDirection value2 in Enum.GetValues(typeof(MovementDirection)))
			{
				if (instance.GetMovementBindingIndex(value2) >= 0 && KeyText.IsKeyboardBindingFor(instance.GetMovementKeyString(value2), keyCodeName))
				{
					return true;
				}
			}
			return false;
		}

		internal static bool IsTyping()
		{
			if (MenuLibFieldFocused())
			{
				return true;
			}
			MenuManager instance = MenuManager.instance;
			if ((Object)(object)instance != (Object)null && instance.textInputActive)
			{
				return true;
			}
			ChatManager instance2 = ChatManager.instance;
			if ((Object)(object)instance2 != (Object)null)
			{
				return instance2.chatActive;
			}
			return false;
		}

		private static bool MenuLibFieldFocused()
		{
			if (!menuLibLooked)
			{
				menuLibLooked = true;
				menuLibFocus = FindMenuLibFocus();
			}
			if (menuLibFocus == null)
			{
				return false;
			}
			try
			{
				return menuLibFocus();
			}
			catch (Exception ex)
			{
				menuLibFocus = null;
				if (!menuLibFocusFailedLogged)
				{
					menuLibFocusFailedLogged = true;
					Plugin.Logger.LogWarning((object)("MenuLib's text-field focus unreadable, the wheel no longer checks it (logged once): " + ex.GetType().Name + ": " + ex.Message));
				}
				return false;
			}
		}

		private static Func<bool>? FindMenuLibFocus()
		{
			FieldInfo field = FindMenuLibFocusField();
			if (field == null)
			{
				return null;
			}
			try
			{
				Func<bool> func = Expression.Lambda<Func<bool>>(Expression.Field(null, field), Array.Empty<ParameterExpression>()).Compile();
				func();
				return func;
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogInfo((object)("MenuLib's text-field focus is read by reflection (" + ex.GetType().Name + ": " + ex.Message + ")"));
				return delegate
				{
					object value = field.GetValue(null);
					return value is bool && (bool)value;
				};
			}
		}

		private static FieldInfo? FindMenuLibFocusField()
		{
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					string name;
					try
					{
						name = assembly.GetName().Name;
					}
					catch (Exception)
					{
						continue;
					}
					if (!(name != "MenuLib"))
					{
						FieldInfo fieldInfo = assembly.GetType("MenuLib.MonoBehaviors.REPOInputStringSystem", throwOnError: false)?.GetField("hasAnyFocus", BindingFlags.Static | BindingFlags.Public);
						if (fieldInfo != null && fieldInfo.FieldType == typeof(bool))
						{
							return fieldInfo;
						}
						Plugin.Logger.LogWarning((object)"MenuLib is loaded but has no static bool MenuLib.MonoBehaviors.REPOInputStringSystem.hasAnyFocus - the wheel cannot tell when a MenuLib text field has focus");
						return null;
					}
				}
			}
			catch (Exception ex2)
			{
				Plugin.Logger.LogWarning((object)("Looking for MenuLib's text-field focus failed: " + ex2.GetType().Name + ": " + ex2.Message));
			}
			return null;
		}
	}
	internal static class ModStyle
	{
		internal const int ReactionWheelSortingOrder = 110;

		internal const int ReactionStageSortingOrder = 105;

		internal const float ReactionWheelBackdropAlpha = 0.2f;

		internal static Color ReactionWheelColor(int rgb)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			return new Color((float)((rgb >> 16) & 0xFF) / 255f, (float)((rgb >> 8) & 0xFF) / 255f, (float)(rgb & 0xFF) / 255f);
		}

		internal static void ConfigureSingleLineEllipsis(TextMeshProUGUI label)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			((TMP_Text)label).enableWordWrapping = false;
			((TMP_Text)label).overflowMode = (TextOverflowModes)1;
			((TMP_Text)label).margin = new Vector4(0f, 0f - ((TMP_Text)label).fontSize, 0f, 0f - ((TMP_Text)label).fontSize);
		}
	}
	internal static class OverlayFont
	{
		private static TMP_FontAsset? nativeFont;

		private static Material? nativeFontMaterial;

		private static bool fallbackTried;

		private static float nextProbeAt;

		private static readonly string[] FallbackOsFonts = new string[3] { "Segoe UI", "Arial", "Tahoma" };

		private static readonly string CyrillicAlphabet = BuildCyrillicAlphabet();

		private static readonly List<Transform> ownRoots = new List<Transform>();

		internal static TMP_FontAsset? Font => nativeFont;

		internal static int Generation { get; private set; }

		private static string BuildCyrillicAlphabet()
		{
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 1040; i <= 1103; i++)
			{
				stringBuilder.Append((char)i);
			}
			stringBuilder.Append('Ё').Append('ё');
			return stringBuilder.ToString();
		}

		internal static void RegisterOwnRoot(Transform root)
		{
			if ((Object)(object)root != (Object)null && !ownRoots.Contains(root))
			{
				ownRoots.Add(root);
			}
		}

		internal static void Pump()
		{
			if ((Object)(object)nativeFont != (Object)null || Time.unscaledTime < nextProbeAt)
			{
				return;
			}
			nextProbeAt = Time.unscaledTime + 0.5f;
			try
			{
				ResolveRaw();
			}
			catch
			{
			}
			if (!((Object)(object)nativeFont == (Object)null))
			{
				try
				{
					RegisterGlobalFallbackRaw();
				}
				catch (Exception ex)
				{
					Plugin.Logger.LogInfo((object)("Cyrillic fallback font not registered (" + ex.GetType().Name + ": " + ex.Message + ") - the wheel's text uses the game font only"));
				}
				Generation++;
				Plugin.Logger.LogInfo((object)("Overlay font resolved: " + ((Object)nativeFont).name));
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void ResolveRaw()
		{
			TMP_FontAsset val = null;
			TextMeshProUGUI[] array = Object.FindObjectsOfType<TextMeshProUGUI>();
			foreach (TextMeshProUGUI val2 in array)
			{
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((TMP_Text)val2).font == (Object)null) && !((Object)(object)((TMP_Asset)((TMP_Text)val2).font).material == (Object)null) && !IsOwnLabel(((TMP_Text)val2).transform))
				{
					if (val == null)
					{
						val = ((TMP_Text)val2).font;
					}
					if ((Object)(object)((TMP_Text)val2).fontSharedMaterial != (Object)null && ((Object)((TMP_Text)val2).fontSharedMaterial).GetInstanceID() == ((Object)((TMP_Asset)((TMP_Text)val2).font).material).GetInstanceID())
					{
						nativeFont = ((TMP_Text)val2).font;
						nativeFontMaterial = ((TMP_Asset)((TMP_Text)val2).font).material;
						return;
					}
				}
			}
			if (!((Object)(object)val == (Object)null))
			{
				nativeFont = val;
				nativeFontMaterial = ((TMP_Asset)val).material;
			}
		}

		private static bool IsOwnLabel(Transform t)
		{
			foreach (Transform ownRoot in ownRoots)
			{
				if ((Object)(object)ownRoot != (Object)null && t.IsChildOf(ownRoot))
				{
					return true;
				}
			}
			return false;
		}

		private static List<string?>? GlobalFallbackNames()
		{
			List<TMP_FontAsset> fallbackFontAssets = TMP_Settings.fallbackFontAssets;
			if (fallbackFontAssets == null)
			{
				return null;
			}
			List<string> list = new List<string>(fallbackFontAssets.Count);
			foreach (TMP_FontAsset item in fallbackFontAssets)
			{
				list.Add(((Object)(object)item == (Object)null) ? null : ((Object)item).name);
			}
			return list;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void RegisterGlobalFallbackRaw()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)nativeFont == (Object)null)
			{
				return;
			}
			bool flag = fallbackTried;
			fallbackTried = true;
			if (!FallbackFontRules.ShouldRegister(flag, GlobalFallbackNames()))
			{
				if (!flag)
				{
					Plugin.Logger.LogInfo((object)"Cyrillic fallback font already in TMP's global list (SP-CyrillicFallback, registered by SharePermissions) - using that one");
				}
				return;
			}
			string[] pathsToOSFonts = Font.GetPathsToOSFonts();
			string[] fallbackOsFonts = FallbackOsFonts;
			string text2 = default(string);
			foreach (string wanted in fallbackOsFonts)
			{
				string text = ResolveInstalledPath(pathsToOSFonts, wanted);
				if (text == null)
				{
					continue;
				}
				Font val = new Font();
				try
				{
					Font.Internal_CreateFontFromPath(val, text);
				}
				catch (Exception ex)
				{
					Plugin.Logger.LogInfo((object)("Internal_CreateFontFromPath threw for " + text + ": " + ex.Message));
					Object.Destroy((Object)(object)val);
					continue;
				}
				TMP_FontAsset val2 = TMP_FontAsset.CreateFontAsset(val);
				if ((Object)(object)val2 == (Object)null)
				{
					Plugin.Logger.LogInfo((object)("CreateFontAsset returned null: " + text));
					Object.Destroy((Object)(object)val);
					continue;
				}
				((Object)val2).hideFlags = (HideFlags)61;
				((Object)val2).name = "SP-CyrillicFallback";
				if ((Object)(object)nativeFontMaterial != (Object)null && (Object)(object)((TMP_Asset)val2).material != (Object)null)
				{
					((TMP_Asset)val2).material.shader = nativeFontMaterial.shader;
				}
				if (!val2.TryAddCharacters(CyrillicAlphabet, ref text2, false))
				{
					Plugin.Logger.LogInfo((object)("OS font missing Cyrillic characters [" + text2 + "]: " + text));
					Object.Destroy((Object)(object)val2);
					Object.Destroy((Object)(object)val);
					continue;
				}
				ClampFace(val2);
				if (!AddToGlobalFallbacks(val2))
				{
					Plugin.Logger.LogInfo((object)("Could not reach TMP_Settings.fallbackFontAssets - Cyrillic stays unavailable: " + text));
					Object.Destroy((Object)(object)val2);
					Object.Destroy((Object)(object)val);
					continue;
				}
				ManualLogSource logger = Plugin.Logger;
				string text3 = $"Cyrillic fallback font registered globally: {text} (chars={val2.characterTable.Count} ";
				FaceInfo faceInfo = val2.faceInfo;
				logger.LogInfo((object)(text3 + $"pointSize={((FaceInfo)(ref faceInfo)).pointSize} globalList=[{DescribeGlobalFallbacks()}])"));
				return;
			}
			Plugin.Logger.LogInfo((object)"No OS fallback font found - the wheel's text uses the game font only");
		}

		private static void ClampFace(TMP_FontAsset fallback)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				FaceInfo faceInfo = nativeFont.faceInfo;
				FaceInfo faceInfo2 = fallback.faceInfo;
				if (((FaceInfo)(ref faceInfo)).pointSize > 0 && ((FaceInfo)(ref faceInfo2)).pointSize > 0)
				{
					float num = ((FaceInfo)(ref faceInfo)).ascentLine / (float)((FaceInfo)(ref faceInfo)).pointSize;
					float num2 = ((FaceInfo)(ref faceInfo)).descentLine / (float)((FaceInfo)(ref faceInfo)).pointSize;
					bool flag = false;
					if (((FaceInfo)(ref faceInfo2)).ascentLine / (float)((FaceInfo)(ref faceInfo2)).pointSize > num)
					{
						((FaceInfo)(ref faceInfo2)).ascentLine = num * (float)((FaceInfo)(ref faceInfo2)).pointSize;
						flag = true;
					}
					if (((FaceInfo)(ref faceInfo2)).descentLine / (float)((FaceInfo)(ref faceInfo2)).pointSize < num2)
					{
						((FaceInfo)(ref faceInfo2)).descentLine = num2 * (float)((FaceInfo)(ref faceInfo2)).pointSize;
						flag = true;
					}
					if (flag)
					{
						fallback.faceInfo = faceInfo2;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogInfo((object)("Fallback face clamp skipped: " + ex.Message));
			}
		}

		private static bool AddToGlobalFallbacks(TMP_FontAsset fallback)
		{
			List<TMP_FontAsset> list = TMP_Settings.fallbackFontAssets;
			if (list == null)
			{
				TMP_Settings instance = TMP_Settings.instance;
				if ((Object)(object)instance == (Object)null)
				{
					return false;
				}
				FieldInfo field = typeof(TMP_Settings).GetField("m_fallbackFontAssets", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field == null)
				{
					return false;
				}
				list = new List<TMP_FontAsset>();
				field.SetValue(instance, list);
			}
			if (!list.Contains(fallback))
			{
				list.Insert(0, fallback);
			}
			return true;
		}

		private static string DescribeGlobalFallbacks()
		{
			List<TMP_FontAsset> fallbackFontAssets = TMP_Settings.fallbackFontAssets;
			if (fallbackFontAssets == null)
			{
				return "<null>";
			}
			StringBuilder stringBuilder = new StringBuilder(fallbackFontAssets.Count * 32);
			stringBuilder.Append("n=").Append(fallbackFontAssets.Count);
			for (int i = 0; i < fallbackFontAssets.Count; i++)
			{
				stringBuilder.Append((i == 0) ? ": " : ", ");
				TMP_FontAsset val = fallbackFontAssets[i];
				stringBuilder.Append(((Object)(object)val == (Object)null) ? "<null>" : (string.IsNullOrEmpty(((Object)val).name) ? "<unnamed>" : ((Object)val).name));
			}
			return stringBuilder.ToString();
		}

		private static string? ResolveInstalledPath(string[] paths, string wanted)
		{
			string text = wanted.Replace(" ", "");
			string text2 = null;
			foreach (string text3 in paths)
			{
				string text4 = Path.GetFileNameWithoutExtension(text3).Replace(" ", "");
				if (string.Equals(text4, text, StringComparison.OrdinalIgnoreCase))
				{
					return text3;
				}
				if (text2 == null && text4.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					text2 = text3;
				}
			}
			return text2;
		}
	}
	internal static class PngHeader
	{
		internal const int MaxBytes = 1048576;

		internal const int Length = 24;

		private static readonly byte[] Signature = new byte[8] { 137, 80, 78, 71, 13, 10, 26, 10 };

		internal static bool TryReadSize(byte[]? png, out int width, out int height)
		{
			width = (height = 0);
			if (png == null || png.Length < 24)
			{
				return false;
			}
			for (int i = 0; i < Signature.Length; i++)
			{
				if (png[i] != Signature[i])
				{
					return false;
				}
			}
			if (BigEndian(png, 8) != 13 || png[12] != 73 || png[13] != 72 || png[14] != 68 || png[15] != 82)
			{
				return false;
			}
			int num = BigEndian(png, 16);
			int num2 = BigEndian(png, 20);
			if (num <= 0 || num2 <= 0)
			{
				return false;
			}
			width = num;
			height = num2;
			return true;
		}

		internal static string? Refusal(byte[]? png, int size)
		{
			if (!TryReadSize(png, out var width, out var height))
			{
				return "does not start with a PNG signature and an IHDR chunk";
			}
			if (width != size || height != size)
			{
				return $"is {width}x{height} px, not {size}x{size}";
			}
			return null;
		}

		private static int BigEndian(byte[] b, int at)
		{
			return (b[at] << 24) | (b[at + 1] << 16) | (b[at + 2] << 8) | b[at + 3];
		}
	}
	internal static class ReactionAnimCore
	{
		internal enum Sprite
		{
			Coin,
			Sparkle,
			Shard,
			Droplet,
			Dust,
			Wisp,
			Star,
			Steam,
			Z,
			Question,
			Ember,
			Confetti,
			Mote
		}

		internal enum Channel
		{
			X,
			Y,
			ScaleX,
			ScaleY,
			Rotation,
			Red
		}

		internal enum Shape
		{
			Bump,
			Hop,
			Shake,
			Wave,
			Pulse,
			Rise,
			Spring,
			UiSpring,
			Keys
		}

		internal readonly struct Move
		{
			internal readonly Channel Channel;

			internal readonly float Start;

			internal readonly float Length;

			internal readonly float Amount;

			internal readonly float Hz;

			internal readonly Shape Shape;

			internal readonly float Damping;

			internal readonly float Hold;

			internal readonly Track? Track;

			internal Move(Channel channel, float start, float length, float amount, Shape shape, float hz, float damping = 0f, float hold = 0f, Track? track = null)
			{
				Channel = channel;
				Start = start;
				Length = length;
				Amount = amount;
				Shape = shape;
				Hz = hz;
				Damping = damping;
				Hold = hold;
				Track = track;
			}
		}

		internal sealed class Track
		{
			private readonly float[] times;

			private readonly float[] values;

			private readonly float offset;

			internal readonly bool Loop;

			internal readonly bool IsValid;

			internal Track(bool loop, params float[] pairs)
				: this(loop, Half(pairs, 0), Half(pairs, 1), 0f, pairs != null && pairs.Length % 2 == 0)
			{
			}

			private Track(bool loop, float[] times, float[] values, float offset, bool even)
			{
				Loop = loop;
				this.times = times;
				this.values = values;
				this.offset = offset;
				bool flag = even && times.Length >= 2 && times[0] == 0f;
				int num = 0;
				while (flag && num < times.Length)
				{
					flag = !float.IsNaN(values[num]) && !float.IsInfinity(values[num]) && !float.IsInfinity(times[num]) && (num == 0 || times[num] > times[num - 1]);
					num++;
				}
				IsValid = flag;
			}

			private static float[] Half(float[] pairs, int which)
			{
				if (pairs == null)
				{
					return new float[0];
				}
				float[] array = new float[pairs.Length / 2];
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = pairs[2 * i + which];
				}
				return array;
			}

			internal float At(float time)
			{
				if (!IsValid)
				{
					return 0f;
				}
				float num = times[times.Length - 1];
				double num2 = (double)time + (double)offset;
				if (Loop)
				{
					num2 %= (double)num;
					if (num2 < 0.0)
					{
						num2 += (double)num;
					}
				}
				else
				{
					if (num2 <= 0.0)
					{
						return values[0];
					}
					if (num2 >= (double)num)
					{
						return values[values.Length - 1];
					}
				}
				for (int i = 1; i < times.Length; i++)
				{
					if (!(num2 > (double)times[i]))
					{
						double num3 = times[i - 1];
						double num4 = (num2 - num3) / ((double)times[i] - num3);
						return (float)((double)values[i - 1] + (double)(values[i] - values[i - 1]) * num4);
					}
				}
				return values[values.Length - 1];
			}

			internal Track From(float seconds)
			{
				return new Track(Loop, times, values, offset + seconds, IsValid);
			}
		}

		internal sealed class Emitter
		{
			internal Sprite Sprite;

			internal int Count = 6;

			internal float SpawnStart = 0.55f;

			internal float SpawnLength = 0.2f;

			internal float OriginX;

			internal float OriginY;

			internal float Angle;

			internal float Spread = 60f;

			internal bool Radial;

			internal float SpeedMin = 200f;

			internal float SpeedMax = 360f;

			internal float Gravity = 800f;

			internal float Spin = 180f;

			internal float LifeMin = 0.7f;

			internal float LifeMax = 1f;

			internal float Size = 48f;

			internal float ScaleStart = 1f;

			internal float ScaleEnd = 0.6f;

			internal float SwayAmp;

			internal float SwayHz;

			internal uint Tint = 16777215u;

			internal bool Palette;

			internal bool Sphere;

			internal Track? SizeOverLife;
		}

		internal sealed class Script
		{
			internal readonly string Code;

			internal readonly Move[] Moves;

			internal readonly Emitter[] Emitters;

			internal readonly Extent Reach;

			internal Script(string code, Move[] moves, Emitter[] emitters)
			{
				Code = code;
				Moves = moves;
				Emitters = emitters;
				Reach = MeasureReach(this);
			}
		}

		internal readonly struct Extent
		{
			internal readonly float Left;

			internal readonly float Right;

			internal readonly float Up;

			internal readonly float Down;

			internal Extent(float left, float right, float up, float down)
			{
				Left = left;
				Right = right;
				Up = up;
				Down = down;
			}
		}

		internal struct Particle
		{
			internal Sprite Sprite;

			internal float X;

			internal float Y;

			internal float Rotation;

			internal float Size;

			internal float Alpha;

			internal uint Tint;
		}

		internal sealed class Frame
		{
			internal int Phase;

			internal int FrameIndex;

			internal float Flight;

			internal float FlightScale;

			internal float X;

			internal float Y;

			internal float ScaleX;

			internal float ScaleY;

			internal float Rotation;

			internal float Alpha;

			internal float Red;

			internal readonly Particle[] Particles = new Particle[24];

			internal int ParticleCount;
		}

		internal static class ClipTracks
		{
			internal static readonly Track SprintBounce = new Track(true, 0f, 1f, 0.017f, 0.89f, 0.033f, 0.6f, 0.083f, -0.6f, 0.1f, -0.89f, 0.117f, -1f, 0.133f, -0.85f, 0.15f, -0.48f, 0.183f, 0.48f, 0.2f, 0.85f, 0.217f, 1f, 0.233f, 0.85f, 0.25f, 0.48f, 0.283f, -0.48f, 0.3f, -0.85f, 0.317f, -1f, 0.333f, -0.85f, 0.35f, -0.48f, 0.383f, 0.48f, 0.4f, 0.85f, 0.417f, 1f);

			internal static readonly Track SprintRoll = new Track(true, 0f, 0f, 0.017f, -0.35f, 0.033f, -0.6f, 0.05f, -0.76f, 0.083f, -0.93f, 0.133f, -0.95f, 0.15f, -0.88f, 0.183f, -0.56f, 0.25f, 0.42f, 0.283f, 0.8f, 0.317f, 0.98f, 0.333f, 1f, 0.367f, 0.84f, 0.383f, 0.65f, 0.4f, 0.39f, 0.417f, 0f);

			internal static readonly Track LandSquash = new Track(false, 0f, -1f, 0.05f, 0f, 0.067f, 0.17f, 0.1f, 0.2f, 0.167f, 0.01f, 0.3f, 0f);

			internal static readonly Track StandBreath = new Track(true, 0f, 0.38f, 0.083f, 0.73f, 0.167f, 0.93f, 0.267f, 1f, 0.367f, 0.95f, 0.567f, 0.61f, 1.1f, -0.67f, 1.25f, -0.91f, 1.4f, -1f, 1.617f, -0.9f, 1.767f, -0.67f, 1.883f, -0.26f, 2f, 0.38f);

			internal static readonly Track CrouchBreath = new Track(true, 0f, 1f, 0.167f, 0.92f, 0.3f, 0.73f, 0.417f, 0.41f, 0.617f, -0.42f, 0.7f, -0.69f, 0.817f, -0.92f, 0.967f, -1f, 1.133f, -0.93f, 1.267f, -0.75f, 1.383f, -0.43f, 1.583f, 0.35f, 1.683f, 0.65f, 1.833f, 0.9f, 2f, 1f);

			internal static readonly Track CrouchMoveSway = new Track(true, 0f, 0f, 0.117f, -0.6f, 0.2f, -0.86f, 0.3f, -0.97f, 0.45f, -0.93f, 0.517f, -0.83f, 0.567f, -0.65f, 0.617f, -0.37f, 0.717f, 0.36f, 0.8f, 0.75f, 0.883f, 0.93f, 1f, 1f, 1.1f, 0.95f, 1.167f, 0.83f, 1.233f, 0.57f, 1.333f, 0f);

			internal static readonly Track DuckWaddleBob = new Track(true, 0f, 0.89f, 0.033f, 0.57f, 0.083f, -1f, 0.183f, -0.94f, 0.217f, -0.57f, 0.3f, 0.79f, 0.317f, 0.94f, 0.35f, 1f, 0.433f, 0.89f, 0.45f, 0.66f, 0.467f, 0.21f, 0.5f, -1f, 0.583f, -1f, 0.617f, -0.69f, 0.683f, 0.69f, 0.7f, 0.91f, 0.733f, 1f, 0.833f, 0.89f);

			internal static readonly Track DuckAttackThrash = new Track(true, 0f, 1f, 0.033f, 0.96f, 0.067f, 0.76f, 0.083f, 0.53f, 0.117f, -0.13f, 0.133f, -0.38f, 0.167f, -0.68f, 0.217f, -0.88f, 0.267f, -0.93f, 0.3f, -0.9f, 0.317f, -0.8f, 0.333f, -0.55f, 0.367f, 0.44f, 0.383f, 0.69f, 0.417f, 0.91f, 0.483f, 1f);

			internal static readonly Track DuckBiteSquash = new Track(true, 0f, 0f, 0.117f, 0f, 0.133f, -0.1f, 0.183f, -0.9f, 0.2f, -1f, 0.233f, 0f, 0.383f, 0f, 0.4f, -0.26f, 0.417f, -0.74f, 0.433f, -1f, 0.45f, -0.74f, 0.467f, -0.26f, 0.483f, 0f);

			internal static readonly Track DuckDetransSquash = new Track(true, 0f, 0f, 0.167f, -0.14f, 0.55f, -0.88f, 0.7f, -1f, 0.733f, -1f, 0.75f, -0.93f, 0.767f, -0.76f, 0.817f, -0.03f, 0.833f, 0.14f, 0.85f, 0.21f, 0.9f, 0f, 1.05f, 0f);

			internal static readonly Track BowtieNoticeRoll = new Track(true, 0f, 0f, 0.05f, 0.02f, 0.083f, 0.3f, 0.133f, 0.83f, 0.167f, 1f, 0.217f, 0.93f, 0.25f, 0.74f, 0.283f, 0.32f, 0.317f, -0.29f, 0.333f, -0.46f, 0.35f, -0.5f, 0.383f, -0.37f, 0.45f, 0.24f, 0.5f, 0.42f, 0.533f, 0.39f, 0.6f, 0.03f, 0.617f, 0f, 0.783f, 0f);

			internal static readonly Track BowtieScreamThrob = new Track(true, 0f, 0f, 0.05f, -0.02f, 0.1f, -0.13f, 0.133f, -0.36f, 0.15f, -0.67f, 0.167f, -0.87f, 0.217f, -1f, 0.267f, -0.95f, 0.3f, -0.05f, 0.367f, 0.05f, 0.4f, 0.04f, 0.433f, -0.07f, 0.45f, -0.22f, 0.467f, -0.56f, 0.483f, -0.82f, 0.5f, -0.93f, 0.567f, -0.99f, 0.583f, -0.95f, 0.617f, -0.03f, 0.633f, 0f);

			internal static readonly Track RobeShiver = new Track(true, 0f, 0f, 0.033f, 0.59f, 0.083f, 0.64f, 0.117f, -0.32f, 0.15f, -0.33f, 0.167f, -0.24f, 0.183f, 0.3f, 0.2f, 0.67f, 0.217f, 0.04f, 0.233f, -0.9f, 0.25f, -0.71f, 0.267f, 0f, 0.3f, 0.57f, 0.35f, 0.67f, 0.383f, -0.33f, 0.433f, -0.33f, 0.467f, 0.67f, 0.5f, -1f, 0.517f, 0f, 0.55f, 0.59f, 0.6f, 0.67f, 0.633f, -0.33f, 0.683f, 0f);

			internal static readonly Track MachineShake = new Track(true, 0f, 0.01f, 0.033f, -1f, 0.05f, -0.49f, 0.067f, 0.47f, 0.083f, 0.98f, 0.1f, 0.84f, 0.15f, -0.25f, 0.167f, -0.39f, 0.183f, -0.33f, 0.25f, 0.43f, 0.267f, 0.5f, 0.283f, 0.31f, 0.317f, -0.55f, 0.333f, -0.74f, 0.35f, -0.47f, 0.383f, 0.71f, 0.4f, 0.98f, 0.417f, 0.86f, 0.483f, -0.55f, 0.5f, -0.67f, 0.533f, -0.06f, 0.567f, 0.01f, 0.6f, -1f, 0.617f, -0.49f, 0.633f, 0.47f, 0.65f, 0.98f, 0.667f, 0.84f, 0.717f, -0.25f, 0.733f, -0.39f, 0.75f, -0.26f, 0.783f, 0.32f, 0.8f, 0.48f, 0.883f, 0.12f, 0.933f, 0.87f, 0.95f, 0.77f, 1f, 0.01f);

			internal static readonly Track CrouchDrop = new Track(false, 0f, 0f, 0.033f, -0.04f, 0.067f, -0.21f, 0.117f, -0.81f, 0.15f, -0.99f, 0.183f, -1f, 0.2f, -0.89f, 0.233f, -0.82f, 0.333f, -1f);

			internal static readonly Track CrouchRise = new Track(false, 0f, -1f, 0.017f, -0.94f, 0.033f, -0.77f, 0.083f, -0.1f, 0.1f, 0.03f, 0.117f, 0.08f, 0.15f, 0.09f, 0.25f, -0.03f, 0.333f, 0f);

			internal static readonly Track HunterAimBody = new Track(false, 0f, -0.5f, 0.1f, -0.58f, 0.133f, -0.52f, 0.3f, 0.68f, 0.333f, 0.85f, 0.383f, 0.98f, 0.433f, 0.99f, 0.483f, 0.85f, 0.5f, 0.71f, 0.533f, 0.31f, 0.55f, 0.26f, 0.7f, 0.33f, 0.833f, 0.31f);

			internal static readonly Track ThrowerThrow = new Track(false, 0f, 0f, 0.033f, -0.03f, 0.067f, -0.15f, 0.133f, -0.77f, 0.167f, -0.91f, 0.333f, -0.72f, 0.35f, -0.64f, 0.367f, -0.46f, 0.4f, 0.77f, 0.417f, 0.97f, 0.433f, 1f, 0.533f, 0.81f, 0.683f, 0.73f, 0.7f, 0.65f, 0.733f, 0.15f, 0.75f, 0.01f, 0.767f, -0.05f, 0.933f, 0f);

			internal static readonly Track UpscreamShudder = new Track(false, 0f, 0f, 0.017f, -0.33f, 0.05f, -0.47f, 0.067f, 0.22f, 0.083f, 0.51f, 0.117f, -0.72f, 0.133f, -1f, 0.15f, -0.96f, 0.183f, -0.44f, 0.2f, 0.12f, 0.217f, 0.14f, 0.25f, -0.32f, 0.267f, -0.74f, 0.283f, -0.76f, 0.317f, -0.41f, 0.333f, -0.07f, 0.383f, -0.22f, 0.433f, -0.19f, 0.467f, 0.11f, 0.517f, -0.18f, 0.617f, -0.07f, 0.667f, -0.39f, 0.75f, 0.29f, 0.817f, -0.28f, 0.883f, -0.06f, 0.917f, -0.1f, 0.967f, -0.38f, 0.983f, -0.21f);

			internal static readonly Track HeadBiteRear = new Track(false, 0f, 0f, 0.033f, -0.03f, 0.067f, -0.17f, 0.083f, -0.36f, 0.1f, -0.75f, 0.117f, -0.91f, 0.183f, -1f, 0.2f, -0.85f, 0.233f, -0.13f, 0.25f, 0.13f, 0.267f, 0.15f, 0.3f, 0f, 0.333f, -0.03f, 0.9f, 0f);

			internal static readonly Track TumbleMoveRoll = new Track(true, 0f, -1f, 0.017f, -0.91f, 0.033f, -0.67f, 0.05f, -0.23f, 0.067f, 0.28f, 0.083f, 0.69f, 0.1f, 0.92f, 0.117f, 1f, 0.133f, 0.96f, 0.15f, 0.77f, 0.167f, 0.43f, 0.2f, -0.53f, 0.217f, -0.89f, 0.233f, -1f);
		}

		internal static class ParticleCurves
		{
			internal static readonly Track LoveMoteSize = new Track(false, 0f, 0f, 0.017f, 0.1f, 0.05f, 0.66f, 0.067f, 0.83f, 0.1f, 0.97f, 0.133f, 1f, 0.2f, 0.91f, 0.3f, 0.56f, 0.35f, 0.45f, 0.533f, 0.57f, 0.683f, 0.2f, 0.817f, 0.28f, 1f, 0f);
		}

		internal const float Duration = 3f;

		internal const float LaunchEnd = 0.35f;

		internal const float WindUpEnd = 0.55f;

		internal const float MomentEnd = 1.9f;

		internal const float SettleEnd = 2.6f;

		internal const float StartScale = 0.15f;

		internal const int MaxParticles = 24;

		internal const float StickerPx = 280f;

		internal const float AnchorDx = 190f;

		internal const float AnchorDy = 70f;

		internal const float ArcHeight = 40f;

		private const float Hit = 0.55f;

		internal const float EdgeFade = 0.06f;

		internal const int ReachSamplesPerSecond = 600;

		internal const float ReachPad = 1f;

		private static readonly float[] ConfettiTimes = new float[3] { 0.02f, 0.16f, 0.49f };

		private static readonly uint[] ConfettiColors = new uint[3] { 16777215u, 14942089u, 5766912u };

		internal static readonly IReadOnlyDictionary<string, Script> Scripts = BuildScripts();

		private static readonly int[] FallbackPhases = new int[3] { 1, 0, 2 };

		private const float TwoPi = MathF.PI * 2f;

		private const float LookHz = 2.387324f;

		private const float LookDamping = 0.3f;

		private const float TiltHz = 2.387324f;

		private const float TiltDamping = 0.5f;

		private const float SideHz = 2.387324f;

		private const float SideDamping = 0.6f;

		private const float TiltHold = 0.25f;

		internal static uint Seed(int actor, float start)
		{
			return (uint)(actor * -1640531535) ^ (uint)(start * 1000f);
		}

		internal static void Anchor(Script s, float headX, float headY, float screenW, float screenH, out float ax, out float ay)
		{
			Anchor(s.Reach, 190f, headX, headY, screenW, screenH, out ax, out ay);
		}

		internal static void Anchor(Extent reach, float dx, float headX, float headY, float screenW, float screenH, out float ax, out float ay)
		{
			ax = Clamp(headX + dx, reach.Left, Math.Max(reach.Left, screenW - reach.Right));
			ay = Clamp(headY + 70f, reach.Down, Math.Max(reach.Down, screenH - reach.Up));
		}

		internal static int FrameToDraw(int phase, int index, Func<int, int, bool> gone, int[] phaseCounts, out int drawPhase)
		{
			drawPhase = -1;
			if (phase < 0 || phase > 2 || phaseCounts == null || phaseCounts.Length != 3)
			{
				return -1;
			}
			int num = phaseCounts[phase];
			if (num > 0)
			{
				int num2 = Math.Max(0, Math.Min(index, num - 1));
				for (int i = 0; i < num; i++)
				{
					int num3 = (num2 - i + num) % num;
					if (!gone(phase, num3))
					{
						drawPhase = phase;
						return num3;
					}
				}
			}
			int[] fallbackPhases = FallbackPhases;
			foreach (int num4 in fallbackPhases)
			{
				if (num4 == phase)
				{
					continue;
				}
				for (int k = 0; k < phaseCounts[num4]; k++)
				{
					if (!gone(num4, k))
					{
						drawPhase = num4;
						return k;
					}
				}
			}
			return -1;
		}

		internal static int FrameIndex(float elapsed, int count, float rate)
		{
			if (count <= 1 || !(rate > 0f) || !(elapsed > 0f))
			{
				return 0;
			}
			double num = (double)elapsed * (double)rate + 0.001;
			if (num >= 2147483647.0)
			{
				return 0;
			}
			return (int)num % count;
		}

		internal static int HeldIndex(float elapsed, int count, float rate)
		{
			if (count <= 1 || !(rate > 0f) || !(elapsed > 0f))
			{
				return 0;
			}
			double num = (double)elapsed * (double)rate + 0.001;
			if (!(num >= (double)(count - 1)))
			{
				return (int)num;
			}
			return count - 1;
		}

		internal static float MomentRate(int count, float rate, bool momentOnce)
		{
			if (!momentOnce)
			{
				return rate;
			}
			return (float)count / 1.3499999f;
		}

		internal static Dictionary<string, Script> Playable(IEnumerable<Script> scripts, List<string> refused)
		{
			Dictionary<string, Script> dictionary = new Dictionary<string, Script>(StringComparer.Ordinal);
			foreach (Script script in scripts)
			{
				if (Validate(script, out string error))
				{
					dictionary[script.Code] = script;
				}
				else
				{
					refused.Add(script.Code + ": " + error);
				}
			}
			return dictionary;
		}

		internal static void StickerPosition(Frame f, float headX, float headY, float anchorX, float anchorY, out float x, out float y)
		{
			FlightPosition(f, headX, headY, anchorX, anchorY, out x, out y);
			x += f.X;
			y += f.Y;
		}

		internal static void FlightPosition(Frame f, float headX, float headY, float anchorX, float anchorY, out float x, out float y)
		{
			float flight = f.Flight;
			x = headX + (anchorX - headX) * flight;
			y = headY + (anchorY - headY) * flight + 40f * (float)Math.Sin(Math.PI * (double)flight);
		}

		internal static void Evaluate(Script s, float t, uint seed, Frame f, int[] phaseCounts, float rate, bool momentOnce = false)
		{
			t = Clamp(t, 0f, 3f);
			EvaluateSticker(s, t, f);
			int count = ((phaseCounts == null || phaseCounts.Length != 3) ? 1 : phaseCounts[f.Phase]);
			if (f.Phase == 0)
			{
				f.FrameIndex = HeldIndex(t, count, rate);
			}
			else if (f.Phase == 2)
			{
				f.FrameIndex = HeldIndex(t - 1.9f, count, rate);
			}
			else if (momentOnce)
			{
				f.FrameIndex = HeldIndex(t - 0.55f, count, MomentRate(count, rate, momentOnce: true));
			}
			else
			{
				f.FrameIndex = FrameIndex(t - 0.55f, count, rate);
			}
			f.ParticleCount = 0;
			for (int i = 0; i < s.Emitters.Length; i++)
			{
				Emit(s.Emitters[i], i, t, seed, f);
			}
		}

		internal static void EvaluateMotion(Script s, float t, Frame f)
		{
			EvaluateSticker(s, Clamp(t, 0f, 3f), f);
		}

		private static void EvaluateSticker(Script s, float t, Frame f)
		{
			f.Phase = ((!(t < 0.55f)) ? ((t < 1.9f) ? 1 : 2) : 0);
			float flight;
			float num2;
			float alpha;
			if (t < 0.35f)
			{
				float num = t / 0.35f;
				flight = OutQuad(num);
				num2 = Lerp(0.15f, 1f, OutBack(num));
				alpha = Clamp01(num / 0.35f);
			}
			else if (t < 2.6f)
			{
				flight = 1f;
				num2 = 1f;
				alpha = 1f;
			}
			else
			{
				float num3 = (t - 2.6f) / 0.4000001f;
				flight = 1f - InQuad(num3);
				num2 = Lerp(1f, 0.15f, InQuad(num3));
				alpha = 1f - Clamp01((num3 - 0.4f) / 0.6f);
			}
			float num4 = num2;
			float num5 = num2;
			float num6 = 0f;
			float num7 = 0f;
			float num8 = 0f;
			float num9 = 0f;
			Move[] moves = s.Moves;
			for (int i = 0; i < moves.Length; i++)
			{
				Move m = moves[i];
				if (!(t < m.Start) && !(t > m.Start + m.Length))
				{
					float u = ((m.Length > 0f) ? ((t - m.Start) / m.Length) : 1f);
					float num10 = m.Amount * ShapeAt(in m, u, t - m.Start);
					switch (m.Channel)
					{
					case Channel.X:
						num6 += num10;
						break;
					case Channel.Y:
						num7 += num10;
						break;
					case Channel.ScaleX:
						num4 *= 1f + num10;
						break;
					case Channel.ScaleY:
						num5 *= 1f + num10;
						break;
					case Channel.Rotation:
						num8 += num10;
						break;
					case Channel.Red:
						num9 += num10;
						break;
					}
				}
			}
			f.Flight = flight;
			f.FlightScale = num2;
			f.X = num6;
			f.Y = num7;
			f.ScaleX = num4;
			f.ScaleY = num5;
			f.Rotation = num8;
			f.Alpha = alpha;
			f.Red = Clamp01(num9);
		}

		private static Extent MeasureReach(Script s)
		{
			Frame frame = new Frame();
			double num = 140.0;
			float num2 = 0f;
			float num3 = 0f;
			float num4 = 0f;
			float num5 = 0f;
			int num6 = (int)Math.Round(210.0);
			int num7 = (int)Math.Round(1560.0);
			for (int i = num6; i <= num7; i++)
			{
				EvaluateSticker(s, (float)i / 600f, frame);
				double num8 = (double)frame.Rotation * Math.PI / 180.0;
				double num9 = Math.Abs(Math.Cos(num8));
				double num10 = Math.Abs(Math.Sin(num8));
				double num11 = num * (double)Math.Abs(frame.ScaleX);
				double num12 = num * (double)Math.Abs(frame.ScaleY);
				float num13 = (float)(num11 * num9 + num12 * num10);
				float num14 = (float)(num11 * num10 + num12 * num9);
				num2 = Math.Max(num2, num13 - frame.X);
				num3 = Math.Max(num3, num13 + frame.X);
				num5 = Math.Max(num5, num14 - frame.Y);
				num4 = Math.Max(num4, num14 + frame.Y);
			}
			return new Extent(num2 + 1f, num3 + 1f, num4 + 1f, num5 + 1f);
		}

		internal static bool Validate(Script s, out string error)
		{
			Move[] moves = s.Moves;
			for (int i = 0; i < moves.Length; i++)
			{
				Move move = moves[i];
				if (move.Start < 0f || move.Length < 0f || move.Start + move.Length > 3.0001f)
				{
					error = "a move outside the 3 s";
					return false;
				}
				if (!Enum.IsDefined(typeof(Shape), move.Shape))
				{
					error = "an unknown shape";
					return false;
				}
				if (move.Shape == Shape.Rise && move.Start != 0f)
				{
					error = "a Rise that does not start at 0 s";
					return false;
				}
				if (move.Shape == Shape.Spring && (!(move.Hz > 0f) || !(move.Damping >= 0f) || move.Damping >= 1f || !(move.Hold >= 0f)))
				{
					error = "a spring without a frequency, with a damping outside 0 to 1, or a negative hold";
					return false;
				}
				if (move.Shape == Shape.Keys && (move.Track == null || !move.Track.IsValid))
				{
					error = "a keyed move without a valid track";
					return false;
				}
			}
			Emitter[] emitters = s.Emitters;
			foreach (Emitter emitter in emitters)
			{
				if (!Enum.IsDefined(typeof(Sprite), emitter.Sprite))
				{
					error = "an unknown sprite";
					return false;
				}
				if (emitter.Count <= 0 || emitter.LifeMin <= 0f || emitter.LifeMax < emitter.LifeMin)
				{
					error = "an emitter without particles or life";
					return false;
				}
				if (emitter.SizeOverLife != null && !emitter.SizeOverLife.IsValid)
				{
					error = "an emitter with a size curve that is not valid";
					return false;
				}
				if (emitter.SpawnStart + emitter.SpawnLength + 0.02f + emitter.LifeMax > 3.0001f)
				{
					error = "particles outliving the reaction";
					return false;
				}
			}
			for (int k = 0; k <= 180; k++)
			{
				if (LiveCount(s, (float)k / 60f, 1u) > 24)
				{
					error = "more than " + 24 + " particles at once";
					return false;
				}
			}
			error = "";
			return true;
		}

		private static int LiveCount(Script s, float t, uint seed)
		{
			int num = 0;
			for (int i = 0; i < s.Emitters.Length; i++)
			{
				Emitter emitter = s.Emitters[i];
				for (int j = 0; j < emitter.Count; j++)
				{
					Spawn(emitter, i, j, seed, out var spawn, out var life, out var _);
					float num2 = t - spawn;
					if (num2 >= 0f && num2 <= life)
					{
						num++;
					}
				}
			}
			return num;
		}

		private static void Spawn(Emitter em, int emitter, int i, uint seed, out float spawn, out float life, out uint h)
		{
			h = Hash(seed, (uint)emitter, (uint)i);
			float num = ((em.Count == 1) ? 0f : ((float)i / (float)(em.Count - 1)));
			spawn = em.SpawnStart + em.SpawnLength * num + 0.04f * (Rand(h, 1u) - 0.5f);
			life = Lerp(em.LifeMin, em.LifeMax, Rand(h, 2u));
		}

		private static void Emit(Emitter em, int emitter, float t, uint seed, Frame f)
		{
			for (int i = 0; i < em.Count; i++)
			{
				if (f.ParticleCount >= 24)
				{
					break;
				}
				Spawn(em, emitter, i, seed, out var spawn, out var life, out var h);
				float num = t - spawn;
				if (!(num < 0f) && !(num > life))
				{
					float num2 = (em.Radial ? (em.Angle + 360f * (float)i / (float)em.Count) : (em.Angle + em.Spread * (Rand(h, 3u) - 0.5f)));
					float num3 = Lerp(em.SpeedMin, em.SpeedMax, Rand(h, 4u));
					if (em.Sphere)
					{
						float num4 = 2f * Rand(h, 8u) - 1f;
						num3 *= (float)Math.Sqrt(1f - num4 * num4);
					}
					double num5 = (double)num2 * Math.PI / 180.0;
					float num6 = (float)Math.Sin(num5) * num3;
					float num7 = (float)Math.Cos(num5) * num3;
					float num8 = num / life;
					ref Particle reference = ref f.Particles[f.ParticleCount++];
					reference.Sprite = em.Sprite;
					reference.X = em.OriginX + num6 * num + em.SwayAmp * (float)Math.Sin(Math.PI * 2.0 * (double)em.SwayHz * (double)num + 6.2832 * (double)Rand(h, 5u));
					reference.Y = em.OriginY + num7 * num - 0.5f * em.Gravity * num * num;
					reference.Rotation = em.Spin * (Rand(h, 6u) * 2f - 1f) * num;
					float num9 = ((em.SizeOverLife != null) ? em.SizeOverLife.At(num8) : Lerp(em.ScaleStart, em.ScaleEnd, num8));
					reference.Size = em.Size * num9 * Lerp(0.8f, 1.2f, Rand(h, 7u));
					reference.Alpha = Clamp01(Math.Min(1f, num / 0.08f) * ((num8 < 0.7f) ? 1f : (1f - (num8 - 0.7f) / 0.3f)));
					reference.Tint = (em.Palette ? ConfettiAt(num8) : em.Tint);
				}
			}
		}

		private static uint ConfettiAt(float u)
		{
			int num = ConfettiTimes.Length - 1;
			if (!(u > ConfettiTimes[0]))
			{
				return ConfettiColors[0];
			}
			if (u >= ConfettiTimes[num])
			{
				return ConfettiColors[num];
			}
			int i;
			for (i = 1; u > ConfettiTimes[i]; i++)
			{
			}
			float num2 = (u - ConfettiTimes[i - 1]) / (ConfettiTimes[i] - ConfettiTimes[i - 1]);
			uint num3 = ConfettiColors[i - 1];
			uint num4 = ConfettiColors[i];
			uint num5 = 0u;
			for (int num6 = 16; num6 >= 0; num6 -= 8)
			{
				float num7 = (num3 >> num6) & 0xFF;
				float num8 = (num4 >> num6) & 0xFF;
				num5 |= (uint)Math.Round(num7 + (num8 - num7) * num2) << num6;
			}
			return num5;
		}

		private static float ShapeAt(in Move m, float u, float dt)
		{
			float hz = m.Hz;
			switch (m.Shape)
			{
			case Shape.Bump:
				return (float)Math.Sin(Math.PI * (double)u);
			case Shape.Hop:
				return (float)Math.Abs(Math.Sin(Math.PI * (double)hz * (double)dt)) * (1f - u);
			case Shape.Shake:
				return (float)Math.Sin(Math.PI * 2.0 * (double)hz * (double)dt) * (1f - u);
			case Shape.Wave:
				return (float)(Math.Sin(Math.PI * 2.0 * (double)hz * (double)dt) * Math.Sin(Math.PI * (double)u));
			case Shape.Pulse:
				return (float)Math.Pow(Math.Max(0.0, Math.Sin(Math.PI * 2.0 * (double)hz * (double)dt)), 3.0) * (1f - u);
			case Shape.Spring:
				return SpringAt(dt, hz, m.Damping, m.Hold) * EaseOut(m.Length - dt);
			case Shape.UiSpring:
				return (float)(Math.Sin((double)hz * (1.0 - (double)u) * (double)u * Math.PI * 2.0) * (1.0 - (double)u));
			case Shape.Keys:
				if (m.Track == null)
				{
					return 0f;
				}
				return m.Track.At(dt * ((hz > 0f) ? hz : 1f)) * EaseOut(dt) * EaseOut(m.Length - dt);
			default:
				return 1f - OutCubic(u);
			}
		}

		private static float EaseOut(float left)
		{
			float num = Clamp01(left / 0.06f);
			return num * num * (3f - 2f * num);
		}

		private static float SpringAt(float dt, float hz, float damping, float hold)
		{
			if (!(dt > 0f) || !(hz > 0f) || damping < 0f || damping >= 1f)
			{
				return 0f;
			}
			double num = Math.PI * 2.0 * (double)hz;
			double wd = num * Math.Sqrt(1.0 - (double)(damping * damping));
			double a = (double)damping * num;
			if (hold <= 0f)
			{
				double num2 = Math.Atan2(wd, a) / wd;
				return (float)(Math.Exp((0.0 - a) * (double)dt) * Math.Sin(wd * (double)dt) / (Math.Exp((0.0 - a) * num2) * Math.Sin(wd * num2)));
			}
			return (float)(Step(dt) - Step(dt - hold));
			double Step(double x)
			{
				if (!(x <= 0.0))
				{
					return 1.0 - Math.Exp((0.0 - a) * x) * (Math.Cos(wd * x) + a / wd * Math.Sin(wd * x));
				}
				return 0.0;
			}
		}

		private static uint Hash(uint seed, uint a, uint b)
		{
			uint num = (uint)(((int)seed * -1640531535) ^ ((int)(a + 2135587861) * -2048144777) ^ ((int)(b + 374761393) * -1028477379));
			num ^= num >> 15;
			num *= 739982445;
			num ^= num >> 12;
			num *= 695872825;
			return num ^ (num >> 15);
		}

		private static float Rand(uint h, uint salt)
		{
			uint num = h ^ (salt * 668265263);
			num ^= num >> 16;
			num *= 2146121005;
			num ^= num >> 15;
			num *= 2221713035u;
			num ^= num >> 16;
			return (float)(num & 0xFFFFFF) / 16777216f;
		}

		private static float Lerp(float a, float b, float u)
		{
			return a + (b - a) * u;
		}

		private static float Clamp(float v, float lo, float hi)
		{
			if (!(v < lo))
			{
				if (!(v > hi))
				{
					return v;
				}
				return hi;
			}
			return lo;
		}

		private static float Clamp01(float v)
		{
			return Clamp(v, 0f, 1f);
		}

		private static float OutQuad(float u)
		{
			return 1f - (1f - u) * (1f - u);
		}

		private static float InQuad(float u)
		{
			return u * u;
		}

		private static float OutCubic(float u)
		{
			return 1f - (1f - u) * (1f - u) * (1f - u);
		}

		private static float OutBack(float u)
		{
			float num = u - 1f;
			return 1f + 2.70158f * num * num * num + 1.70158f * num * num;
		}

		private static Move M(Channel channel, float start, float length, float amount, Shape shape, float hz = 0f)
		{
			return new Move(channel, start, length, amount, shape, hz);
		}

		private static Move K(Channel channel, float start, float length, float amount, Track track, float speed = 0f)
		{
			return new Move(channel, start, length, amount, Shape.Keys, speed, 0f, 0f, track);
		}

		private static Move S(Channel channel, float start, float length, float amount, float hz, float damping, float hold = 0f)
		{
			return new Move(channel, start, length, amount, Shape.Spring, hz, damping, hold);
		}

		private static Move[] Cat(params Move[][] parts)
		{
			int num = 0;
			foreach (Move[] array in parts)
			{
				num += array.Length;
			}
			Move[] array2 = new Move[num];
			int num2 = 0;
			foreach (Move[] array3 in parts)
			{
				array3.CopyTo(array2, num2);
				num2 += array3.Length;
			}
			return array2;
		}

		private static Move[] Quake(float at, float shake, float shakeHold, float impact, float impactHold)
		{
			float length = shakeHold + shake / 10f;
			float length2 = impactHold + impact / 30f;
			return new Move[4]
			{
				M(Channel.Rotation, at, length, 0.5f * shake, Shape.Shake, 6f),
				M(Channel.X, at, length, 2f * shake, Shape.Shake, 5.3f),
				M(Channel.Y, at, length, 1.5f * shake, Shape.Shake, 6.7f),
				M(Channel.X, at, length2, 1.5f * impact, Shape.Shake, 20f)
			};
		}

		private static Move Jolt(float at, float impact, float impactHold)
		{
			return M(Channel.X, at, impactHold + impact / 30f, 1.5f * impact, Shape.Shake, 20f);
		}

		private static Dictionary<string, Script> BuildScripts()
		{
			Dictionary<string, Script> d = new Dictionary<string, Script>(StringComparer.Ordinal);
			Add("loot", new Move[4]
			{
				K(Channel.Y, 0.55f, 1.3499999f, 4f, ClipTracks.SprintBounce),
				K(Channel.Rotation, 0.55f, 1.3499999f, 1.5f, ClipTracks.SprintRoll),
				S(Channel.Rotation, 0.55f, 0.7f, -5f, 2.387324f, 0.5f, 0.25f),
				S(Channel.Rotation, 1.9f, 0.7f, -3.5f, 2.387324f, 0.5f, 0.25f)
			}, new Emitter[5]
			{
				CoinHop(0.6541667f),
				CoinHop(0.8625f),
				CoinHop(1.0708333f),
				CoinHop(1.2791667f),
				new Emitter
				{
					Sprite = Sprite.Sparkle,
					Count = 4,
					SpawnStart = 0.6f,
					SpawnLength = 1f,
					OriginX = -45f,
					OriginY = 0f,
					Spread = 360f,
					SpeedMin = 40f,
					SpeedMax = 100f,
					Gravity = 0f,
					Spin = 90f,
					LifeMin = 0.5f,
					LifeMax = 0.7f,
					Size = 36f,
					ScaleStart = 0.4f,
					ScaleEnd = 1.1f
				}
			});
			Add("oops", new Move[4]
			{
				M(Channel.X, 0.55f, 0.2f, 3f, Shape.Shake, 20f),
				M(Channel.Y, 0.55f, 0.2f, 2f, Shape.Shake, 17f),
				S(Channel.Y, 0.55f, 1f, -4f, 2.387324f, 0.3f),
				S(Channel.Y, 1.9f, 1f, -3f, 2.387324f, 0.3f)
			}, new Emitter[1]
			{
				new Emitter
				{
					Sprite = Sprite.Shard,
					Count = 8,
					SpawnLength = 0.08f,
					OriginX = -85f,
					OriginY = -80f,
					Spread = 150f,
					SpeedMin = 260f,
					SpeedMax = 440f,
					Gravity = 1300f,
					Spin = 720f,
					LifeMin = 0.7f,
					LifeMax = 1f,
					Size = 42f,
					ScaleEnd = 0.9f
				}
			});
			Add("fire", new Move[5]
			{
				K(Channel.Y, 0.55f, 1.3499999f, 5f, ClipTracks.SprintBounce),
				K(Channel.Rotation, 0.55f, 1.3499999f, 1.5f, ClipTracks.SprintRoll),
				S(Channel.Rotation, 0.55f, 0.7f, -5f, 2.387324f, 0.5f, 0.25f),
				K(Channel.ScaleY, 1.9f, 0.3f, 0.073f, ClipTracks.LandSquash),
				K(Channel.ScaleX, 1.9f, 0.3f, -0.068f, ClipTracks.LandSquash)
			}, new Emitter[2]
			{
				new Emitter
				{
					Sprite = Sprite.Ember,
					Count = 16,
					SpawnLength = 1.3f,
					OriginX = -50f,
					OriginY = 100f,
					Spread = 50f,
					SpeedMin = 90f,
					SpeedMax = 170f,
					Gravity = -120f,
					Spin = 0f,
					LifeMin = 0.7f,
					LifeMax = 1f,
					Size = 30f,
					ScaleEnd = 0.3f,
					SwayAmp = 12f,
					SwayHz = 2f
				},
				new Emitter
				{
					Sprite = Sprite.Sparkle,
					Count = 4,
					SpawnLength = 0.1f,
					OriginX = -50f,
					OriginY = 95f,
					Spread = 360f,
					SpeedMin = 80f,
					SpeedMax = 160f,
					Gravity = 0f,
					LifeMin = 0.5f,
					LifeMax = 0.7f,
					Size = 34f,
					ScaleStart = 0.5f,
					ScaleEnd = 1f
				}
			});
			Add("run", new Move[3]
			{
				K(Channel.Y, 0.35f, 2.25f, 5f, ClipTracks.SprintBounce.From(0.2167f)),
				K(Channel.Rotation, 0.35f, 2.25f, 1.5f, ClipTracks.SprintRoll.From(0.2167f)),
				S(Channel.Rotation, 0.55f, 0.7f, -5f, 2.387324f, 0.5f, 0.25f)
			}, new Emitter[2]
			{
				new Emitter
				{
					Sprite = Sprite.Droplet,
					Count = 4,
					SpawnLength = 0.15f,
					OriginX = -90f,
					OriginY = 55f,
					Angle = 50f,
					Spread = 50f,
					SpeedMin = 180f,
					SpeedMax = 260f,
					Gravity = 900f,
					LifeMin = 0.5f,
					LifeMax = 0.7f,
					Size = 30f,
					Tint = 10475775u
				},
				new Emitter
				{
					Sprite = Sprite.Dust,
					Count = 9,
					SpawnStart = 0.65000004f,
					SpawnLength = 1.6664f,
					OriginX = -90f,
					OriginY = -95f,
					Angle = 60f,
					Spread = 70f,
					SpeedMin = 40f,
					SpeedMax = 90f,
					Gravity = -30f,
					Spin = 60f,
					LifeMin = 0.45f,
					LifeMax = 0.6f,
					Size = 56f,
					ScaleStart = 0.5f,
					ScaleEnd = 1.3f
				}
			});
			Add("help", new Move[2]
			{
				S(Channel.Y, 0.55f, 0.9f, -3f, 2.387324f, 0.3f),
				S(Channel.Y, 1.9f, 0.9f, -3f, 2.387324f, 0.3f)
			}, new Emitter[2]
			{
				new Emitter
				{
					Sprite = Sprite.Dust,
					Count = 5,
					SpawnStart = 1f,
					SpawnLength = 0.06f,
					OriginX = -30f,
					OriginY = -92f,
					Spread = 170f,
					SpeedMin = 80f,
					SpeedMax = 170f,
					Gravity = -30f,
					Spin = 60f,
					LifeMin = 0.5f,
					LifeMax = 0.7f,
					Size = 56f,
					ScaleStart = 0.5f,
					ScaleEnd = 1.3f
				},
				new Emitter
				{
					Sprite = Sprite.Droplet,
					Count = 3,
					SpawnStart = 1.9f,
					SpawnLength = 0.15f,
					OriginX = 55f,
					OriginY = -35f,
					Spread = 140f,
					SpeedMin = 160f,
					SpeedMax = 240f,
					Gravity = 900f,
					LifeMin = 0.5f,
					LifeMax = 0.7f,
					Size = 28f,
					Tint = 10475775u
				}
			});
			Add("rip", new Move[0], new Emitter[3]
			{
				new Emitter
				{
					Sprite = Sprite.Wisp,
					Count = 6,
					SpawnStart = 0.6f,
					SpawnLength = 1.3f,
					OriginX = -28f,
					OriginY = 30f,
					Spread = 40f,
					SpeedMin = 40f,
					SpeedMax = 80f,
					Gravity = -20f,
					Spin = 30f,
					LifeMin = 0.9f,
					LifeMax = 1f,
					Size = 56f,
					ScaleStart = 0.7f,
					ScaleEnd = 1.2f,
					SwayAmp = 18f,
					SwayHz = 1.2f
				},
				new Emitter
				{
					Sprite = Sprite.Dust,
					Count = 2,
					SpawnStart = 91f / 120f,
					SpawnLength = 0f,
					OriginX = -20f,
					OriginY = -100f,
					Spread = 140f,
					SpeedMin = 80f,
					SpeedMax = 160f,
					Gravity = 600f,
					LifeMin = 0.45f,
					LifeMax = 0.6f,
					Size = 40f,
					ScaleEnd = 0.7f,
					Tint = 9071178u
				},
				new Emitter
				{
					Sprite = Sprite.Dust,
					Count = 2,
					SpawnStart = 1.3833333f,
					SpawnLength = 0f,
					OriginX = -20f,
					OriginY = -100f,
					Spread = 140f,
					SpeedMin = 80f,
					SpeedMax = 160f,
					Gravity = 600f,
					LifeMin = 0.45f,
					LifeMax = 0.6f,
					Size = 40f,
					ScaleEnd = 0.7f,
					Tint = 9071178u
				}
			});
			Add("scared", new Move[1] { K(Channel.ScaleX, 0.55f, 2.05f, 0.02f, ClipTracks.RobeShiver) }, new Emitter[1]
			{
				new Emitter
				{
					Sprite = Sprite.Droplet,
					Count = 6,
					SpawnLength = 0.3f,
					OriginX = 75f,
					OriginY = -15f,
					Spread = 150f,
					SpeedMin = 200f,
					SpeedMax = 300f,
					Gravity = 1000f,
					LifeMin = 0.5f,
					LifeMax = 0.8f,
					Size = 28f,
					Tint = 10475775u
				}
			});
			Add("gg", new Move[0], new Emitter[3]
			{
				new Emitter
				{
					Sprite = Sprite.Confetti,
					Count = 12,
					SpawnLength = 0.15f,
					OriginY = 40f,
					Spread = 120f,
					SpeedMin = 340f,
					SpeedMax = 540f,
					Gravity = 650f,
					Spin = 720f,
					LifeMin = 1.1f,
					LifeMax = 1.3f,
					Size = 30f,
					ScaleEnd = 0.9f,
					Palette = true
				},
				new Emitter
				{
					Sprite = Sprite.Confetti,
					Count = 6,
					SpawnStart = 1.4495502f,
					SpawnLength = 0.1f,
					OriginY = 40f,
					Spread = 100f,
					SpeedMin = 300f,
					SpeedMax = 480f,
					Gravity = 650f,
					Spin = 720f,
					LifeMin = 1f,
					LifeMax = 1.2f,
					Size = 28f,
					ScaleEnd = 0.9f,
					Palette = true
				},
				new Emitter
				{
					Sprite = Sprite.Sparkle,
					Count = 5,
					SpawnStart = 0.75f,
					SpawnLength = 1f,
					OriginX = 28f,
					OriginY = 10f,
					Spread = 360f,
					SpeedMin = 50f,
					SpeedMax = 120f,
					Gravity = 0f,
					LifeMin = 0.5f,
					LifeMax = 0.7f,
					Size = 36f,
					ScaleStart = 0.5f,
					ScaleEnd = 1f
				}
			});
			float num = 1.037125f;
			float num2 = 1.4499999f;
			Add("clap", Cat(Quake(num, 2f, 0.1f, 2f, 0.05f), Quake(num2, 2f, 0.1f, 2f, 0.05f), new Move[2]
			{
				K(Channel.Rotation, num, 0.5f, 1.5f, ClipTracks.MachineShake),
				K(Channel.Rotation, num2, 0.5f, 1.5f, ClipTracks.MachineShake)
			}), new Emitter[5]
			{
				new Emitter
				{
					Sprite = Sprite.Sparkle,
					Count = 3,
					SpawnStart = 0.55f,
					SpawnLength = 0.3f,
					OriginX = -10f,
					OriginY = 30f,
					Spread = 360f,
					SpeedMin = 30f,
					SpeedMax = 70f,
					Gravity = 0f,
					Spin = 90f,
					LifeMin = 0.3f,
					LifeMax = 0.4f,
					Size = 30f,
					ScaleStart = 0.4f,
					ScaleEnd = 1f
				},
				new Emitter
				{
					Sprite = Sprite.Sparkle,
					Count = 3,
					SpawnStart = 1f,
					SpawnLength = 0.3f,
					OriginX = -75f,
					OriginY = -85f,
					Spread = 360f,
					SpeedMin = 30f,
					SpeedMax = 70f,
					Gravity = 0f,
					Spin = 90f,
					LifeMin = 0.3f,
					LifeMax = 0.4f,
					Size = 30f,
					ScaleStart = 0.4f,
					ScaleEnd = 1f
				},
				new Emitter
				{
					Sprite = Sprite.Confetti,
					Count = 7,
					SpawnStart = num2,
					SpawnLength = 0.08f,
					OriginX = 40f,
					OriginY = 120f,
					Angle = -30f,
					Spread = 50f,
					SpeedMin = 380f,
					SpeedMax = 560f,
					Gravity = 650f,
					Spin = 720f,
					LifeMin = 1.1f,
					LifeMax = 1.3f,
					Size = 30f,
					ScaleEnd = 0.9f,
					Palette = true
				},
				new Emitter
				{
					Sprite = Sprite.Confetti,
					Count = 7,
					SpawnStart = num2,
					SpawnLength = 0.08f,
					OriginX = 85f,
					OriginY = 120f,
					Angle = 30f,
					Spread = 50f,
					SpeedMin = 380f,
					SpeedMax = 560f,
					Gravity = 650f,
					Spin = 720f,
					LifeMin = 1.1f,
					LifeMax = 1.3f,
					Size = 30f,
					ScaleEnd = 0.9f,
					Palette = true
				},
				new Emitter
				{
					Sprite = Sprite.Sparkle,
					Count = 3,
					SpawnStart = num2,
					SpawnLength = 0.2f,
					OriginX = 60f,
					OriginY = 110f,
					Spread = 360f,
					SpeedMin = 80f,
					SpeedMax = 160f,
					Gravity = 0f,
					LifeMin = 0.6f,
					LifeMax = 0.8f,
					Size = 34f,
					ScaleStart = 0.5f,
					ScaleEnd = 1f,
					Palette = true
				}
			});
			Add("laugh", new Move[12]
			{
				S(Channel.Y, 0.55f, 0.9f, -3f, 2.387324f, 0.3f),
				K(Channel.ScaleY, Ha(0), 0.3f, 0.05f, ClipTracks.LandSquash),
				K(Channel.ScaleX, Ha(0), 0.3f, -0.045f, ClipTracks.LandSquash),
				K(Channel.ScaleY, Ha(2), 0.3f, 0.05f, ClipTracks.LandSquash),
				K(Channel.ScaleX, Ha(2), 0.3f, -0.045f, ClipTracks.LandSquash),
				K(Channel.ScaleY, Ha(3), 0.3f, 0.05f, ClipTracks.LandSquash),
				K(Channel.ScaleX, Ha(3), 0.3f, -0.045f, ClipTracks.LandSquash),
				K(Channel.ScaleY, Ha(5), 0.3f, 0.05f, ClipTracks.LandSquash),
				K(Channel.ScaleX, Ha(5), 0.3f, -0.045f, ClipTracks.LandSquash),
				K(Channel.ScaleY, Ha(6), 0.3f, 0.05f, ClipTracks.LandSquash),
				K(Channel.ScaleX, Ha(6), 0.3f, -0.045f, ClipTracks.LandSquash),
				S(Channel.Y, 1.9f, 0.7f, -2f, 2.387324f, 0.3f)
			}, new Emitter[4]
			{
				Tears(Ha(0)),
				Tears(Ha(2)),
				Tears(Ha(3)),
				Tears(Ha(5))
			});
			float num3 = 0.67f;
			Add("angry", Cat(Quake(0.383f, 3f, 0.42f, 3f, 0.1f), Quake(0.55f, 3f, 0.6f, 2f, 0.1f), Quake(1.2f, 3f, 0.5f, 2f, 0.1f), new Move[11]
			{
				K(Channel.Rotation, 0f, 0.65f, 8f, ClipTracks.BowtieNoticeRoll),
				Jolt(0.5f, 3f, 0.1f),
				K(Channel.ScaleY, num3, 1.9f - num3, 0.08f, ClipTracks.BowtieScreamThrob),
				K(Channel.ScaleX, num3, 1.9f - num3, -0.04f, ClipTracks.BowtieScreamThrob),
				Jolt(num3 + 0.167f, 2f, 0.1f),
				Jolt(num3 + 0.3f, 2f, 0.1f),
				Jolt(num3 + 0.483f, 2f, 0.1f),
				Jolt(num3 + 0.617f, 2f, 0.1f),
				Jolt(num3 + 0.8f, 2f, 0.1f),
				Jolt(num3 + 0.933f, 2f, 0.1f),
				Jolt(num3 + 1.117f, 2f, 0.1f)
			}), new Emitter[2]
			{
				new Emitter
				{
					Sprite = Sprite.Steam,
					Count = 4,
					SpawnLength = 0.4f,
					OriginX = -80f,
					OriginY = 20f,
					Angle = -55f,
					Spread = 30f,
					SpeedMin = 140f,
					SpeedMax = 220f,
					Gravity = -60f,
					Spin = 60f,
					LifeMin = 0.6f,
					LifeMax = 0.9f,
					Size = 64f,
					ScaleStart = 0.6f,
					ScaleEnd = 1.6f
				},
				new Emitter
				{
					Sprite = Sprite.Steam,
					Count = 4,
					SpawnLength = 0.4f,
					OriginX = 80f,
					OriginY = 20f,
					Angle = 55f,
					Spread = 30f,
					SpeedMin = 140f,
					SpeedMax = 220f,
					Gravity = -60f,
					Spin = 60f,
					LifeMin = 0.6f,
					LifeMax = 0.9f,
					Size = 64f,
					ScaleStart = 0.6f,
					ScaleEnd = 1.6f
				}
			});
			Add("love", new Move[6]
			{
				K(Channel.Y, 0.35f, 2.65f, 3f, ClipTracks.StandBreath.From(0.2f)),
				S(Channel.Y, 0.55f, 2.45f, 3f, 2.387324f, 0.3f, 2.05f),
				M(Channel.Y, Word(0), 0.2f, 6f, Shape.UiSpring, 5f),
				M(Channel.Y, Word(1), 0.2f, 6f, Shape.UiSpring, 5f),
				M(Channel.Y, Word(2), 0.2f, 6f, Shape.UiSpring, 5f),
				M(Channel.Y, Word(3), 0.2f, 6f, Shape.UiSpring, 5f)
			}, new Emitter[1]
			{
				new Emitter
				{
					Sprite = Sprite.Mote,
					Count = 8,
					SpawnStart = 0.4f,
					SpawnLength = 1.35f,
					OriginX = -18f,
					OriginY = -14f,
					Spread = 360f,
					Sphere = true,
					SpeedMin = 45f,
					SpeedMax = 70f,
					Gravity = 0f,
					Spin = 0f,
					LifeMin = 0.9f,
					LifeMax = 1.2f,
					Size = 30f,
					SizeOverLife = ParticleCurves.LoveMoteSize,
					SwayAmp = 6f,
					SwayHz = 1f
				}
			});
			Add("sleepy", new Move[1] { K(Channel.Y, 0.35f, 2.65f, 3f, ClipTracks.CrouchBreath.From(1.8f)) }, new Emitter[1]
			{
				new Emitter
				{
					Sprite = Sprite.Z,
					Count = 4,
					SpawnStart = 0.6f,
					SpawnLength = 1.35f,
					OriginX = 40f,
					OriginY = 90f,
					Angle = 20f,
					Spread = 10f,
					SpeedMin = 60f,
					SpeedMax = 80f,
					Gravity = 0f,
					Spin = 20f,
					LifeMin = 0.9f,
					LifeMax = 1f,
					Size = 44f,
					ScaleStart = 0.6f,
					ScaleEnd = 1.3f,
					SwayAmp = 14f,
					SwayHz = 1.2f
				}
			});
			Add("question", new Move[2]
			{
				S(Channel.Rotation, 0.55f, 1.95f, -4f, 2.387324f, 0.6f, 1.3499999f),
				S(Channel.Y, 1.9f, 0.9f, -3f, 2.387324f, 0.3f)
			}, new Emitter[1]
			{
				new Emitter
				{
					Sprite = Sprite.Question,
					Count = 3,
					SpawnLength = 0.35f,
					OriginX = 47f,
					OriginY = 99f,
					Spread = 80f,
					SpeedMin = 160f,
					SpeedMax = 220f,
					Gravity = 300f,
					Spin = 60f,
					LifeMin = 0.7f,
					LifeMax = 0.9f,
					Size = 46f,
					ScaleStart = 0.4f,
					ScaleEnd = 1f
				}
			});
			float num4 = 0.9f;
			Add("duck", Cat(Quake(num4 + 0.1f, 2f, 0.5f, 2f, 0.1f), new Move[9]
			{
				K(Channel.Y, 0f, 0.6f, 5f, ClipTracks.DuckWaddleBob),
				K(Channel.Rotation, num4 + 0.11f, 0.966f, 6f, ClipTracks.DuckAttackThrash.From(0.11f)),
				K(Channel.ScaleY, num4, 1.076f, 0.04f, ClipTracks.DuckBiteSquash),
				K(Channel.ScaleX, num4, 1.076f, -0.02f, ClipTracks.DuckBiteSquash),
				Jolt(num4 + 0.333f, 2f, 0.1f),
				Jolt(num4 + 0.583f, 2f, 0.1f),
				Jolt(num4 + 0.817f, 2f, 0.1f),
				K(Channel.ScaleY, 1.9f, 0.5f, 0.1f, ClipTracks.DuckDetransSquash.From(0.5f)),
				K(Channel.ScaleX, 1.9f, 0.5f, -0.05f, ClipTracks.DuckDetransSquash.From(0.5f))
			}), new Emitter[2]
			{
				new Emitter
				{
					Sprite = Sprite.Dust,
					Count = 5,
					SpawnStart = 0.667f,
					SpawnLength = 0.08f,
					OriginY = 50f,
					Spread = 160f,
					SpeedMin = 120f,
					SpeedMax = 220f,
					Gravity = -30f,
					Spin = 90f,
					LifeMin = 0.5f,
					LifeMax = 0.7f,
					Size = 54f,
					ScaleStart = 0.5f,
					ScaleEnd = 1.3f
				},
				new Emitter
				{
					Sprite = Sprite.Droplet,
					Count = 5,
					SpawnStart = num4 + 0.1f,
					SpawnLength = 0.4f,
					OriginY = 40f,
					Spread = 120f,
					SpeedMin = 160f,
					SpeedMax = 260f,
					Gravity = 900f,
					LifeMin = 0.5f,
					LifeMax = 0.7f,
					Size = 26f,
					Tint = 10475775u
				}
			});
			Add("bonk", Cat(Quake(0.55f, 5f, 0.5f, 5f, 0.2f), Quake(1.9f, 3f, 0.5f, 5f, 0.1f)), new Emitter[3]
			{
				new Emitter
				{
					Sprite = Sprite.Steam,
					Count = 5,
					SpawnStart = 0.70000005f,
					SpawnLength = 0.3f,
					OriginX = -40f,
					OriginY = 45f,
					Spread = 90f,
					SpeedMin = 50f,
					SpeedMax = 110f,
					Gravity = -60f,
					Spin = 60f,
					LifeMin = 0.9f,
					LifeMax = 1.2f,
					Size = 52f,
					ScaleStart = 0.5f,
					ScaleEnd = 1.4f
				},
				new Emitter
				{
					Sprite = Sprite.Star,
					Count = 5,
					SpawnStart = 1.2249999f,
					SpawnLength = 0f,
					Radial = true,
					OriginX = -80f,
					OriginY = -50f,
					SpeedMin = 160f,
					SpeedMax = 160f,
					Gravity = 0f,
					LifeMin = 0.45f,
					LifeMax = 0.5f,
					Size = 32f,
					ScaleEnd = 0.3f
				},
				new Emitter
				{
					Sprite = Sprite.Star,
					Count = 4,
					SpawnStart = 1.9f,
					SpawnLength = 0.4f,
					OriginX = -100f,
					OriginY = -80f,
					Spread = 360f,
					SpeedMin = 40f,
					SpeedMax = 70f,
					Gravity = 0f,
					Spin = 240f,
					LifeMin = 0.5f,
					LifeMax = 0.55f,
					Size = 30f,
					ScaleStart = 0.6f,
					ScaleEnd = 1f,
					SwayAmp = 20f,
					SwayHz = 1.5f
				}
			});
			Add("taxed", Cat(Drop(0.55f), Drop(1f), Drop(1.4499999f)), new Emitter[3]
			{
				Drain(0.55f),
				Drain(1f),
				Drain(1.4499999f)
			});
			Add("tiny", new Move[1] { K(Channel.Rotation, 0.22f, 2f, 2.5f, ClipTracks.CrouchMoveSway) }, new Emitter[2]
			{
				new Emitter
				{
					Sprite = Sprite.Sparkle,
					Count = 3,
					SpawnStart = 0.85300004f,
					SpawnLength = 0f,
					OriginX = -84f,
					OriginY = -60f,
					Spread = 180f,
					SpeedMin = 40f,
					SpeedMax = 100f,
					Gravity = 0f,
					LifeMin = 0.5f,
					LifeMax = 0.7f,
					Size = 32f,
					ScaleStart = 0.5f,
					ScaleEnd = 1f
				},
				new Emitter
				{
					Sprite = Sprite.Sparkle,
					Count = 3,
					SpawnStart = 1.52f,
					SpawnLength = 0f,
					OriginX = -84f,
					OriginY = -60f,
					Spread = 180f,
					SpeedMin = 40f,
					SpeedMax = 100f,
					Gravity = 0f,
					LifeMin = 0.5f,
					LifeMax = 0.7f,
					Size = 32f,
					ScaleStart = 0.5f,
					ScaleEnd = 1f
				}
			});
			float[] array = new float[5]
			{
				Stomp(0),
				Stomp(2),
				Stomp(3),
				Stomp(5),
				Stomp(6)
			};
			List<Move> list = new List<Move>();
			List<Emitter> list2 = new List<Emitter>();
			float[] array2 = array;
			foreach (float num5 in array2)
			{
				list.AddRange(Quake(num5, 2f, 0.1f, 1f, 0.05f));
				list.Add(K(Channel.ScaleY, num5, 0.3f, 0.05f, ClipTracks.LandSquash));
				list.Add(K(Channel.ScaleX, num5, 0.3f, -0.045f, ClipTracks.LandSquash));
				list2.Add(new Emitter
				{
					Sprite = Sprite.Dust,
					Count = 3,
					SpawnStart = num5,
					SpawnLength = 0.04f,
					OriginX = -10f,
					OriginY = -112f,
					Spread = 160f,
					SpeedMin = 70f,
					SpeedMax = 140f,
					Gravity = -30f,
					Spin = 60f,
					LifeMin = 0.35f,
					LifeMax = 0.45f,
					Size = 44f,
					ScaleStart = 0.5f,
					ScaleEnd = 1.2f
				});
			}
			Add("mad", list.ToArray(), list2.ToArray());
			Add("shh", new Move[2]
			{
				K(Channel.Rotation, 0.55f, 1.3499999f, 2f, ClipTracks.HunterAimBody.From(0.05f), 0.833f),
				S(Channel.Y, 1.9f, 0.9f, -3f, 2.387324f, 0.3f)
			}, Array.Empty<Emitter>());
			float num6 = 1.5625f;
			float num7 = 88f / 135f;
			float start = 1.2249999f - 0.43f / num7;
			Add("yoink", new Move[5]
			{
				S(Channel.Y, 0.55f, 0.9f, -3f, 2.387324f, 0.3f),
				K(Channel.Rotation, start, 0.933f / num7, 3f, ClipTracks.ThrowerThrow, num7),
				Jolt(num6, 10f, 0.1f),
				S(Channel.Y, 1.9f, 0.9f, -3f, 2.387324f, 0.3f),
				K(Channel.Rotation, 1.9f, 0.6999999f, 2f, ClipTracks.TumbleMoveRoll.From(0.1f))
			}, new Emitter[1]
			{
				new Emitter
				{
					Sprite = Sprite.Shard,
					Count = 8,
					SpawnStart = num6,
					SpawnLength = 0f,
					Radial = true,
					Angle = 20f,
					OriginX = 33f,
					OriginY = 41f,
					SpeedMin = 260f,
					SpeedMax = 420f,
					Gravity = 1300f,
					Spin = 720f,
					LifeMin = 0.7f,
					LifeMax = 0.95f,
					Size = 40f,
					ScaleEnd = 0.85f
				}
			});
			List<Move> list3 = new List<Move>();
			for (int j = 0; j < 3; j++)
			{
				float num8 = 0.55f + 2f * (float)j * (25f / 111f);
				list3.Add(K(Channel.ScaleY, num8 - 25f / 111f, 0.2852252f, 0.04f, ClipTracks.CrouchDrop, 1.479852f));
				list3.Add(K(Channel.ScaleY, num8, 0.2852252f, 0.04f, ClipTracks.CrouchRise, 0.888f));
			}
			Add("teabag", list3.ToArray(), Array.Empty<Emitter>());
			Add("yeeted", Quake(0.55f, 6f, 0.1f, 5f, 0.1f), new Emitter[1]
			{
				new Emitter
				{
					Sprite = Sprite.Dust,
					Count = 6,
					SpawnStart = 0.55f,
					SpawnLength = 0.06f,
					OriginX = 65f,
					OriginY = -115f,
					Spread = 170f,
					SpeedMin = 120f,
					SpeedMax = 220f,
					Gravity = -30f,
					Spin = 90f,
					LifeMin = 0.45f,
					LifeMax = 0.6f,
					Size = 42f,
					ScaleStart = 0.5f,
					ScaleEnd = 1.2f
				}
			});
			Add("boo", Cat(Quake(1.4499999f, 2f, 0.5f, 1f, 0.1f), new Move[3]
			{
				S(Channel.Y, 0.55f, 0.9f, -3f, 2.387324f, 0.3f),
				K(Channel.Rotation, 0.55f, 0.8f, 2.5f, ClipTracks.UpscreamShudder.From(0.15f)),
				S(Channel.Y, 1.9f, 0.9f, -3f, 2.387324f, 0.3f)
			}), Array.Empty<Emitter>());
			Add("heavy", new Move[4]
			{
				K(Channel.Rotation, 0.55f, 1f, 2f, ClipTracks.CrouchMoveSway.From(0.867f)),
				K(Channel.Rotation, 1.55f, 0.3499999f, 2f, ClipTracks.CrouchMoveSway.From(0.867f)),
				S(Channel.Y, 0.55f, 0.9f, -2.5f, 2.387324f, 0.3f),
				S(Channel.Y, 1.9f, 0.9f, -3f, 2.387324f, 0.3f)
			}, new Emitter[5]
			{
				Strain(0.55f, 95f, -5f, 2),
				Strain(0.65000004f, -105f, 0f, 2),
				Strain(1.2166667f, 95f, -5f, 3),
				Strain(1.9f, 95f, -5f, 2),
				Strain(1.9499999f, -105f, 0f, 2)
			});
			List<Move> list4 = new List<Move>();
			for (int k = 0; k < 6; k++)
			{
				list4.Add(S(Channel.Rotation, 0.45000002f + (float)k * 0.24213074f, 0.6f, (k % 2 == 0) ? 1.5f : (-1.5f), 2.387324f, 0.5f, 0.24213074f));
			}
			Add("aaaaa", list4.ToArray(), Array.Empty<Emitter>());
			List<Move> list5 = new List<Move>();
			for (int l = 0; l < 3; l++)
			{
				list5.Add(K(Channel.X, 0.55f + 0.5f * (float)l, Math.Min(0.5f, 1.3499999f - 0.5f * (float)l), 6f, ClipTracks.HeadBiteRear.From(0.05f), 0.4f));
			}
			list5.Add(S(Channel.Y, 1.9f, 0.9f, -3f, 2.387324f, 0.3f));
			Add("mybad", list5.ToArray(), new Emitter[1]
			{
				new Emitter
				{
					Sprite = Sprite.Droplet,
					Count = 3,
					SpawnStart = 1.9f,
					SpawnLength = 0.1f,
					OriginX = 85f,
					OriginY = 25f,
					Spread = 140f,
					SpeedMin = 180f,
					SpeedMax = 260f,
					Gravity = 900f,
					LifeMin = 0.5f,
					LifeMax = 0.7f,
					Size = 28f,
					Tint = 10475775u
				}
			});
			Add("holdthis", Cat(Quake(0.55f, 5f, 0.5f, 8f, 0.2f), new Move[2]
			{
				S(Channel.Y, 0.32154343f, 0.9f, -3f, 2.387324f, 0.3f),
				S(Channel.Y, 1.9f, 0.9f, -3f, 2.387324f, 0.3f)
			}), new Emitter[2]
			{
				new Emitter
				{
					Sprite = Sprite.Steam,
					Count = 6,
					SpawnStart = 1.2249999f,
					SpawnLength = 0.35f,
					OriginX = 14f,
					OriginY = 50f,
					Spread = 120f,
					SpeedMin = 50f,
					SpeedMax = 110f,
					Gravity = -60f,
					Spin = 60f,
					LifeMin = 0.9f,
					LifeMax = 1.2f,
					Size = 60f,
					ScaleStart = 0.6f,
					ScaleEnd = 1.5f
				},
				new Emitter
				{
					Sprite = Sprite.Star,
					Count = 4,
					SpawnStart = 1.9f,
					SpawnLength = 0.4f,
					OriginX = 96f,
					OriginY = 2f,
					Spread = 360f,
					SpeedMin = 40f,
					SpeedMax = 70f,
					Gravity = 0f,
					Spin = 240f,
					LifeMin = 0.5f,
					LifeMax = 0.55f,
					Size = 30f,
					ScaleStart = 0.6f,
					ScaleEnd = 1f,
					SwayAmp = 20f,
					SwayHz = 1.5f
				}
			});
			List<Move> list6 = new List<Move> { K(Channel.Y, 0.35f, 2.65f, 2f, ClipTracks.StandBreath.From(0.2f)) };
			for (int m = 0; m < 5; m++)
			{
				list6.Add(S(Channel.Y, 0.55f + (float)m * (20f / 69f), 0.9f, -2f, 2.387324f, 0.3f));
			}
			list6.Add(S(Channel.Y, 1.9f, 0.9f, -2f, 2.387324f, 0.3f));
			list6.Add(S(Channel.Rotation, 1.9f, 1.1f, 2f, 2.387324f, 0.5f, 0.6999999f));
			Add("bruh", list6.ToArray(), Array.Empty<Emitter>());
			Add("sus", new Move[4]
			{
				K(Channel.Y, 0.35f, 2.65f, 2f, ClipTracks.StandBreath.From(0.2f)),
				S(Channel.Y, 0.55f, 0.9f, -2.5f, 2.387324f, 0.3f),
				S(Channel.Y, 1.2249999f, 0.9f, -2.5f, 2.387324f, 0.3f),
				S(Channel.Rotation, 1.9f, 1.1f, -1.5f, 2.387324f, 0.5f, 0.6999999f)
			}, Array.Empty<Emitter>());
			return d;
			void Add(string code, Move[] moves, params Emitter[] emitters)
			{
				d[code] = new Script(code, moves, emitters);
			}
			static Emitter CoinHop(float at)
			{
				return new Emitter
				{
					Sprite = Sprite.Coin,
					Count = 2,
					SpawnStart = at,
					SpawnLength = 0f,
					OriginX = -45f,
					OriginY = 5f,
					Spread = 70f,
					SpeedMin = 240f,
					SpeedMax = 340f,
					Gravity = 1100f,
					Spin = 540f,
					LifeMin = 0.6f,
					LifeMax = 0.75f,
					Size = 36f,
					ScaleEnd = 0.8f
				};
			}
			static Emitter Drain(float at)
			{
				return new Emitter
				{
					Sprite = Sprite.Coin,
					Count = 4,
					SpawnStart = at,
					SpawnLength = 0.15f,
					OriginX = -90f,
					OriginY = -84f,
					Angle = 180f,
					Spread = 50f,
					SpeedMin = 60f,
					SpeedMax = 140f,
					Gravity = 700f,
					Spin = 360f,
					LifeMin = 0.6f,
					LifeMax = 0.8f,
					Size = 40f,
					ScaleEnd = 0.7f
				};
			}
			static Move[] Drop(float at)
			{
				return new Move[4]
				{
					M(Channel.Y, at, 0.3f, 6f, Shape.UiSpring, 10f),
					M(Channel.ScaleX, at, 0.2f, 0.04f, Shape.UiSpring, 5f),
					M(Channel.ScaleY, at, 0.2f, 0.04f, Shape.UiSpring, 5f),
					M(Channel.Red, at, 0.25f, 0.5f, Shape.Bump)
				};
			}
			static float Ha(int num9)
			{
				return 0.55f + (float)num9 / 4.55f;
			}
			static float Stomp(int num9)
			{
				return 0.55f + (float)num9 / 4.55f;
			}
			static Emitter Strain(float at, float x, float y, int n)
			{
				return new Emitter
				{
					Sprite = Sprite.Droplet,
					Count = n,
					SpawnStart = at,
					SpawnLength = 0.1f,
					OriginX = x,
					OriginY = y,
					Spread = 140f,
					SpeedMin = 140f,
					SpeedMax = 220f,
					Gravity = 900f,
					LifeMin = 0.45f,
					LifeMax = 0.6f,
					Size = 24f,
					Tint = 10475775u
				};
			}
			static Emitter Tears(float at)
			{
				return new Emitter
				{
					Sprite = Sprite.Droplet,
					Count = 2,
					SpawnStart = at,
					SpawnLength = 0f,
					OriginX = 70f,
					OriginY = 100f,
					Spread = 140f,
					SpeedMin = 200f,
					SpeedMax = 280f,
					Gravity = 900f,
					LifeMin = 0.5f,
					LifeMax = 0.7f,
					Size = 26f,
					Tint = 12577279u
				};
			}
			static float Word(int num9)
			{
				return 0.55f + (float)num9 / 2.5f;
			}
		}
	}
	internal static class ReactionArt
	{
		internal const string StickerPrefix = "LobbyReactions.ReactionStickers.";

		internal const string ParticlePrefix = "LobbyReactions.ReactionParticles.";

		internal const string SoundPrefix = "LobbyReactions.ReactionSounds.";

		internal const int StickerSize = 320;

		internal const int ParticleSize = 96;

		internal static readonly IReadOnlyDictionary<string, string[][]> Frames = new Dictionary<string, string[][]>(StringComparer.Ordinal)
		{
			["loot"] = new string[3][]
			{
				new string[2] { "loot_a_1.png", "loot_a_2.png" },
				new string[4] { "loot_b_1.png", "loot_b_2.png", "loot_b_3.png", "loot_b_4.png" },
				new string[2] { "loot_c_1.png", "loot_c_2.png" }
			},
			["fire"] = new string[3][]
			{
				new string[2] { "fire_a_1.png", "fire_a_2.png" },
				new string[4] { "fire_b_1.png", "fire_b_2.png", "fire_b_3.png", "fire_b_4.png" },
				new string[1] { "fire_c_1.png" }
			},
			["oops"] = new string[3][]
			{
				new string[2] { "oops_a_1.png", "oops_a_2.png" },
				new string[3] { "oops_b_1.png", "oops_b_2.png", "oops_b_3.png" },
				new string[2] { "oops_c_1.png", "oops_c_2.png" }
			},
			["help"] = new string[3][]
			{
				new string[1] { "help_a_1.png" },
				new string[3] { "help_b_1.png", "help_b_2.png", "help_b_3.png" },
				new string[1] { "help_c_1.png" }
			},
			["scared"] = new string[3][]
			{
				new string[2] { "scared_a_1.png", "scared_a_2.png" },
				new string[3] { "scared_b_1.png", "scared_b_2.png", "scared_b_3.png" },
				new string[1] { "scared_c_1.png" }
			},
			["run"] = new string[3][]
			{
				new string[1] { "run_a_1.png" },
				new string[4] { "run_b_1.png", "run_b_2.png", "run_b_3.png", "run_b_4.png" },
				new string[1] { "run_c_1.png" }
			},
			["rip"] = new string[3][]
			{
				new string[1] { "rip_a_1.png" },
				new string[3] { "rip_b_1.png", "rip_b_2.png", "rip_b_3.png" },
				new string[2] { "rip_c_1.png", "rip_c_2.png" }
			},
			["gg"] = new string[3][]
			{
				new string[1] { "gg_a_1.png" },
				new string[3] { "gg_b_1.png", "gg_b_2.png", "gg_b_3.png" },
				new string[2] { "gg_c_1.png", "gg_c_2.png" }
			},
			["clap"] = new string[3][]
			{
				new string[1] { "clap_a_1.png" },
				new string[3] { "clap_b_1.png", "clap_b_2.png", "clap_b_3.png" },
				new string[2] { "clap_c_1.png", "clap_c_2.png" }
			},
			["laugh"] = new string[3][]
			{
				new string[1] { "laugh_a_1.png" },
				new string[3] { "laugh_b_1.png", "laugh_b_2.png", "laugh_b_3.png" },
				new string[1] { "laugh_c_1.png" }
			},
			["love"] = new string[3][]
			{
				new string[1] { "love_a_1.png" },
				new string[3] { "love_b_1.png", "love_b_2.png", "love_b_3.png" },
				new string[1] { "love_c_1.png" }
			},
			["sleepy"] = new string[3][]
			{
				new string[1] { "sleepy_a_1.png" },
				new string[2] { "sleepy_b_1.png", "sleepy_b_2.png" },
				new string[1] { "sleepy_c_1.png" }
			},
			["question"] = new string[3][]
			{
				new string[1] { "question_a_1.png" },
				new string[2] { "question_b_1.png", "question_b_2.png" },
				new string[2] { "question_c_1.png", "question_c_2.png" }
			},
			["mad"] = new string[3][]
			{
				new string[1] { "mad_a_1.png" },
				new string[3] { "mad_b_1.png", "mad_b_2.png", "mad_b_3.png" },
				new string[1] { "mad_c_1.png" }
			},
			["angry"] = new string[3][]
			{
				new string[1] { "angry_a_1.png" },
				new string[3] { "angry_b_1.png", "angry_b_2.png", "angry_b_3.png" },
				new string[1] { "angry_c_1.png" }
			},
			["duck"] = new string[3][]
			{
				new string[2] { "duck_a_1.png", "duck_a_2.png" },
				new string[3] { "duck_b_1.png", "duck_b_2.png", "duck_b_3.png" },
				new string[2] { "duck_c_1.png", "duck_c_2.png" }
			},
			["boo"] = new string[3][]
			{
				new string[1] { "boo_a_1.png" },
				new string[3] { "boo_b_1.png", "boo_b_2.png", "boo_b_3.png" },
				new string[1] { "boo_c_1.png" }
			},
			["aaaaa"] = new string[3][]
			{
				new string[1] { "aaaaa_a_1.png" },
				new string[2] { "aaaaa_b_1.png", "aaaaa_b_2.png" },
				new string[1] { "aaaaa_c_1.png" }
			},
			["yeeted"] = new string[3][]
			{
				new string[3] { "yeeted_a_1.png", "yeeted_a_2.png", "yeeted_a_3.png" },
				new string[1] { "yeeted_b_1.png" },
				new string[1] { "yeeted_c_1.png" }
			},
			["mybad"] = new string[3][]
			{
				new string[1] { "mybad_a_1.png" },
				new string[2] { "mybad_b_1.png", "mybad_b_2.png" },
				new string[1] { "mybad_c_1.png" }
			},
			["holdthis"] = new string[3][]
			{
				new string[2] { "holdthis_a_1.png", "holdthis_a_2.png" },
				new string[2] { "holdthis_b_1.png", "holdthis_b_2.png" },
				new string[1] { "holdthis_c_1.png" }
			},
			["bonk"] = new string[3][]
			{
				new string[2] { "bonk_a_1.png", "bonk_a_2.png" },
				new string[2] { "bonk_b_1.png", "bonk_b_2.png" },
				new string[1] { "bonk_c_1.png" }
			},
			["teabag"] = new string[3][]
			{
				new string[1] { "teabag_a_1.png" },
				new string[2] { "teabag_b_1.png", "teabag_b_2.png" },
				new string[1] { "teabag_c_1.png" }
			},
			["sus"] = new string[3][]
			{
				new string[1] { "sus_a_1.png" },
				new string[2] { "sus_b_1.png", "sus_b_2.png" },
				new string[1] { "sus_c_1.png" }
			},
			["bruh"] = new string[3][]
			{
				new string[1] { "bruh_a_1.png" },
				new string[2] { "bruh_b_1.png", "bruh_b_2.png" },
				new string[1] { "bruh_c_1.png" }
			},
			["taxed"] = new string[3][]
			{
				new string[2] { "taxed_a_1.png", "taxed_a_2.png" },
				new string[3] { "taxed_b_1.png", "taxed_b_2.png", "taxed_b_3.png" },
				new string[1] { "taxed_c_1.png" }
			},
			["yoink"] = new string[3][]
			{
				new string[1] { "yoink_a_1.png" },
				new string[4] { "yoink_b_1.png", "yoink_b_2.png", "yoink_b_3.png", "yoink_b_4.png" },
				new string[1] { "yoink_c_1.png" }
			},
			["heavy"] = new string[3][]
			{
				new string[1] { "heavy_a_1.png" },
				new string[3] { "heavy_b_1.png", "heavy_b_2.png", "heavy_b_3.png" },
				new string[1] { "heavy_c_1.png" }
			},
			["tiny"] = new string[3][]
			{
				new string[1] { "tiny_a_1.png" },
				new string[3] { "tiny_b_1.png", "tiny_b_2.png", "tiny_b_3.png" },
				new string[1] { "tiny_c_1.png" }
			},
			["shh"] = new string[3][]
			{
				new string[1] { "shh_a_1.png" },
				new string[3] { "shh_b_1.png", "shh_b_2.png", "shh_b_3.png" },
				new string[1] { "shh_c_1.png" }
			}
		};

		internal static readonly IReadOnlyDictionary<string, float> FrameRate = new Dictionary<string, float>(StringComparer.Ordinal)
		{
			["loot"] = 9.6f,
			["fire"] = 9.6f,
			["oops"] = 5f,
			["help"] = 3.33f,
			["scared"] = 4.39f,
			["run"] = 9.6f,
			["rip"] = 4.8f,
			["gg"] = 6.67f,
			["clap"] = 1.67f,
			["laugh"] = 4.55f,
			["love"] = 2.5f,
			["sleepy"] = 1f,
			["question"] = 5f,
			["mad"] = 4.55f,
			["angry"] = 4f,
			["duck"] = 10f,
			["boo"] = 5f,
			["aaaaa"] = 4.13f,
			["yeeted"] = 5.45f,
			["mybad"] = 4f,
			["holdthis"] = 3.11f,
			["bonk"] = 2.86f,
			["teabag"] = 4.44f,
			["sus"] = 2f,
			["bruh"] = 3.45f,
			["taxed"] = 12.5f,
			["yoink"] = 4f,
			["heavy"] = 3f,
			["tiny"] = 3f,
			["shh"] = 3f
		};

		internal static readonly IReadOnlyList<string> MomentOnce = new string[12]
		{
			"oops", "help", "clap", "duck", "boo", "yeeted", "holdthis", "bonk", "sus", "taxed",
			"yoink", "shh"
		};

		internal static readonly IReadOnlyDictionary<string, (int Phase, int Index)> Icon = new Dictionary<string, (int, int)>(StringComparer.Ordinal)
		{
			["loot"] = (1, 2),
			["fire"] = (1, 2),
			["oops"] = (1, 1),
			["help"] = (1, 1),
			["scared"] = (1, 1),
			["run"] = (1, 2),
			["rip"] = (1, 1),
			["gg"] = (1, 1),
			["clap"] = (1, 1),
			["laugh"] = (1, 1),
			["love"] = (1, 1),
			["sleepy"] = (1, 1),
			["question"] = (1, 1),
			["mad"] = (1, 1),
			["angry"] = (1, 1),
			["duck"] = (1, 1),
			["boo"] = (1, 1),
			["aaaaa"] = (1, 1),
			["yeeted"] = (0, 2),
			["mybad"] = (1, 1),
			["holdthis"] = (1, 0),
			["bonk"] = (1, 0),
			["teabag"] = (1, 1),
			["sus"] = (1, 1),
			["bruh"] = (1, 1),
			["taxed"] = (1, 1),
			["yoink"] = (1, 2),
			["heavy"] = (1, 1),
			["tiny"] = (1, 1),
			["shh"] = (1, 1)
		};

		internal static readonly IReadOnlyDictionary<string, (int X0, int Y0, int X1, int Y1)> ArtBounds = new Dictionary<string, (int, int, int, int)>(StringComparer.Ordinal)
		{
			["loot"] = (2, 5, 318, 315),
			["fire"] = (59, 2, 260, 318),
			["oops"] = (2, 36, 318, 284),
			["help"] = (30, 2, 291, 318),
			["scared"] = (7, 2, 313, 318),
			["run"] = (2, 28, 318, 292),
			["rip"] = (2, 16, 318, 304),
			["gg"] = (62, 2, 258, 318),
			["clap"] = (53, 2, 267, 318),
			["laugh"] = (39, 2, 281, 318),
			["love"] = (2, 7, 318, 313),
			["sleepy"] = (45, 2, 275, 318),
			["question"] = (66, 2, 253, 318),
			["mad"] = (76, 2, 244, 318),
			["angry"] = (78, 2, 242, 318),
			["duck"] = (14, 2, 306, 318),
			["boo"] = (2, 49, 318, 271),
			["aaaaa"] = (60, 2, 260, 318),
			["yeeted"] = (31, 2, 289, 318),
			["mybad"] = (2, 53, 318, 267),
			["holdthis"] = (2, 12, 318, 308),
			["bonk"] = (2, 5, 318, 315),
			["teabag"] = (78, 2, 242, 318),
			["sus"] = (32, 2, 288, 318),
			["bruh"] = (13, 2, 308, 318),
			["taxed"] = (16, 2, 304, 318),
			["yoink"] = (2, 32, 318, 287),
			["heavy"] = (2, 59, 318, 261),
			["tiny"] = (17, 2, 303, 318),
			["shh"] = (2, 31, 318, 289)
		};

		internal static readonly IReadOnlyList<string> Particles = new string[13]
		{
			"coin.png", "sparkle.png", "shard.png", "droplet.png", "dust.png", "wisp.png", "star.png", "steam.png", "z.png", "question.png",
			"ember.png", "confetti.png", "mote.png"
		};
	}
	internal sealed class ReactionBubbleGraphic : MaskableGraphic
	{
		private readonly BubbleMesh mesh = new BubbleMesh();

		private readonly BubbleTail tail = new BubbleTail();

		private ReactionAnimCore.Extent body;

		private bool hasBody;

		private float aimX = float.NaN;

		private float aimY = float.NaN;

		private float aimScale = float.NaN;

		internal void Show(in ReactionAnimCore.Extent box, float headX, float headY, float scale, float alpha)
		{
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			if (!hasBody || !Same(in body, in box))
			{
				body = box;
				hasBody = true;
				aimX = (aimY = float.NaN);
			}
			if (ReactionBubbleLayout.NeedsAim(aimX, aimY, aimScale, headX, headY, scale))
			{
				aimX = headX;
				aimY = headY;
				aimScale = scale;
				ReactionBubbleLayout.AimTail(body, headX, headY, scale, tail);
				flag = true;
			}
			if (flag)
			{
				ReactionBubbleLayout.Build(body, tail, mesh);
				((Graphic)this).SetVerticesDirty();
			}
			((Graphic)this).color = new Color(1f, 1f, 1f, alpha);
			if (!((Behaviour)this).enabled)
			{
				((Behaviour)this).enabled = true;
			}
		}

		internal void Hide()
		{
			if (((Behaviour)this).enabled)
			{
				((Behaviour)this).enabled = false;
			}
		}

		private static bool Same(in ReactionAnimCore.Extent a, in ReactionAnimCore.Extent b)
		{
			if (a.Left == b.Left && a.Right == b.Right && a.Up == b.Up)
			{
				return a.Down == b.Down;
			}
			return false;
		}

		protected override void OnPopulateMesh(VertexHelper vh)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			vh.Clear();
			Color color = ((Graphic)this).color;
			Color32 val = default(Color32);
			for (int i = 0; i < mesh.VertexCount; i++)
			{
				int num = mesh.Rgb[i];
				((Color32)(ref val))..ctor((byte)((float)((num >> 16) & 0xFF) * color.r + 0.5f), (byte)((float)((num >> 8) & 0xFF) * color.g + 0.5f), (byte)((float)(num & 0xFF) * color.b + 0.5f), (byte)(Mathf.Clamp01(mesh.Alpha[i] * color.a) * 255f + 0.5f));
				vh.AddVert(new Vector3(mesh.X[i], mesh.Y[i], 0f), val, Vector4.zero);
			}
			for (int j = 0; j + 2 < mesh.IndexCount; j += 3)
			{
				vh.AddTriangle(mesh.Indices[j], mesh.Indices[j + 1], mesh.Indices[j + 2]);
			}
		}
	}
	internal static class ReactionBubbleLayout
	{
		internal readonly struct Bubble
		{
			internal readonly ReactionAnimCore.Extent Body;

			internal readonly ReactionAnimCore.Extent Reach;

			internal readonly float AnchorDx;

			internal Bubble(ReactionAnimCore.Extent body, ReactionAnimCore.Extent reach, float anchorDx)
			{
				Body = body;
				Reach = reach;
				AnchorDx = anchorDx;
			}
		}

		internal const float Pad = 12f;

		internal const float Radius = 36f;

		internal const float Keyline = 5f;

		internal const float ShadowDx = 5f;

		internal const float ShadowDy = -8f;

		internal const float ShadowSoftness = 12f;

		internal const float ShadowAlpha = 22f / 51f;

		internal const float EdgeFeather = 0.85f;

		internal const int FillRgb = 16777215;

		internal const float FillAlpha = 0.7f;

		internal const int InkRgb = 1972262;

		internal const int CornerSegments = 8;

		internal const int TipSegments = 8;

		private const float MitreSharp = 2f;

		private const float MitreDeep = 4f;

		internal const float HeadClear = 60f;

		internal const float HeadRadius = 33.625f;

		internal const float TailHalfBase = 17f;

		internal const float TailInset = 14f;

		internal const float TailGap = 6f;

		internal const float TailMax = 90f;

		internal const float TailBow = 6f;

		internal const float TailBowInner = 3f;

		internal const float TailBowMost = 6f;

		internal const int TailSteps = 12;

		internal const float AimTolerance = 0.5f;

		private const float MinScale = 0.01f;

		internal const int RimPoints = 36;

		private static readonly float[] CornerCos;

		private static readonly float[] CornerSin;

		private static readonly float[] BowAt;

		static ReactionBubbleLayout()
		{
			CornerCos = new float[36];
			CornerSin = new float[36];
			BowAt = new float[13];
			float[] array = new float[4] { 180f, 270f, 0f, 90f };
			int i = 0;
			int num = 0;
			for (; i < 4; i++)
			{
				int num2 = 0;
				while (num2 <= 8)
				{
					double num3 = ((double)array[i] + 90.0 * (double)num2 / 8.0) * Math.PI / 180.0;
					CornerCos[num] = (float)Math.Cos(num3);
					CornerSin[num] = (float)Math.Sin(num3);
					num2++;
					num++;
				}
			}
			for (int j = 1; j < 12; j++)
			{
				BowAt[j] = (float)Math.Sin(Math.PI * (double)j / 12.0);
			}
		}

		internal static bool TryArtExtent(string code, out ReactionAnimCore.Extent art)
		{
			art = default(ReactionAnimCore.Extent);
			if (code == null || !ReactionArt.ArtBounds.TryGetValue(code, out (int, int, int, int) value))
			{
				return false;
			}
			float num = 0.875f;
			float num2 = 160f;
			art = new ReactionAnimCore.Extent((num2 - (float)value.Item1) * num, ((float)value.Item3 - num2) * num, (num2 - (float)value.Item2) * num, ((float)value.Item4 - num2) * num);
			return true;
		}

		internal static ReactionAnimCore.Extent ArtExtent(string code)
		{
			if (TryArtExtent(code, out var art))
			{
				return art;
			}
			float num = 140f;
			return new ReactionAnimCore.Extent(num, num, num, num);
		}

		internal static ReactionAnimCore.Extent BodyOf(ReactionAnimCore.Script s, ReactionAnimCore.Extent art)
		{
			ReactionAnimCore.Frame frame = new ReactionAnimCore.Frame();
			float num = 600f;
			float num2 = float.MinValue;
			float num3 = float.MinValue;
			float num4 = float.MinValue;
			float num5 = float.MinValue;
			int num6 = (int)Math.Round(0.35f * num);
			int num7 = (int)Math.Round(2.6f * num);
			for (int i = num6; i <= num7; i++)
			{
				ReactionAnimCore.EvaluateMotion(s, (float)i / num, frame);
				if (frame.Flight == 1f)
				{
					double num8 = (double)frame.Rotation * Math.PI / 180.0;
					double num9 = Math.Cos(num8);
					double num10 = Math.Sin(num8);
					for (int j = 0; j < 4; j++)
					{
						double num11 = (double)((j == 0 || j == 3) ? (0f - art.Left) : art.Right) * (double)frame.ScaleX;
						double num12 = (double)((j < 2) ? art.Up : (0f - art.Down)) * (double)frame.ScaleY;
						float num13 = (float)(num11 * num9 + num12 * num10) + frame.X;
						float num14 = (float)((0.0 - num11) * num10 + num12 * num9) + frame.Y;
						num2 = Math.Max(num2, 0f - num13);
						num3 = Math.Max(num3, num13);
						num4 = Math.Max(num4, num14);
						num5 = Math.Max(num5, 0f - num14);
					}
				}
			}
			if (num2 == float.MinValue)
			{
				num2 = art.Left;
				num3 = art.Right;
				num4 = art.Up;
				num5 = art.Down;
			}
			return new ReactionAnimCore.Extent(num2 + 12f, num3 + 12f, num4 + 12f, num5 + 12f);
		}

		internal static Bubble For(ReactionAnimCore.Script s)
		{
			return For(s, ArtExtent(s.Code));
		}

		internal static Bubble For(ReactionAnimCore.Script s, ReactionAnimCore.Extent art)
		{
			ReactionAnimCore.Extent body = BodyOf(s, art);
			ReactionAnimCore.Extent extent = Drawn(body);
			ReactionAnimCore.Extent reach = s.Reach;
			return new Bubble(reach: new ReactionAnimCore.Extent(Math.Max(reach.Left, extent.Left), Math.Max(reach.Right, extent.Right), Math.Max(reach.Up, extent.Up), Math.Max(reach.Down, extent.Down)), body: body, anchorDx: Math.Max(190f, 60f + body.Left));
		}

		internal static ReactionAnimCore.Extent Drawn(ReactionAnimCore.Extent body)
		{
			float num = 6f;
			return new ReactionAnimCore.Extent(body.Left + Math.Max(5f, 5f + num - 5f), body.Right + Math.Max(5f, 5f + num + 5f), body.Up + Math.Max(5f, 5f + num + -8f), body.Down + Math.Max(5f, 5f + num - -8f));
		}

		internal static void Anchor(in Bubble b, float headX, float headY, float screenW, float screenH, out float ax, out float ay)
		{
			ReactionAnimCore.Anchor(b.Reach, b.AnchorDx, headX, headY, screenW, screenH, out ax, out ay);
		}

		internal static void Place(ReactionAnimCore.Frame f, float headX, float headY, float ax, float ay, out float x, out float y, out float scale)
		{
			ReactionAnimCore.FlightPosition(f, headX, headY, ax, ay, out x, out y);
			scale = f.FlightScale;
		}

		internal static void HeadInBubble(float headX, float headY, float x, float y, float scale, out float localX, out float localY)
		{
			float num = ((scale > 0.01f) ? scale : 0.01f);
			localX = (headX - x) / num;
			localY = (headY - y) / num;
		}

		internal static float TipToHead(float scale)
		{
			return 39.625f / ((scale > 0.01f) ? scale : 0.01f);
		}

		internal static bool NeedsAim(float lastX, float lastY, float lastScale, float x, float y, float scale)
		{
			float num = x - lastX;
			float num2 = y - lastY;
			float value = TipToHead(scale) - TipToHead(lastScale);
			if (num * num + num2 * num2 <= 0.25f && Math.Abs(value) <= 0.5f)
			{
				return float.IsNaN(lastScale);
			}
			return true;
		}

		internal static void AimTail(ReactionAnimCore.Extent body, float headX, float headY, float scale, BubbleTail tail)
		{
			tail.Visible = false;
			float num = 0f - body.Left;
			float right = body.Right;
			float num2 = 0f - body.Down;
			float up = body.Up;
			if (!(right > num) || !(up > num2) || float.IsNaN(headX) || float.IsNaN(headY) || float.IsInfinity(headX) || float.IsInfinity(headY))
			{
				return;
			}
			float num3 = CornerRadius(body);
			float num4 = ((headX < num) ? (num - headX) : ((headX > right) ? (headX - right) : 0f));
			float num5 = ((headY < num2) ? (num2 - headY) : ((headY > up) ? (headY - up) : 0f));
			if (num4 <= 0f && num5 <= 0f)
			{
				return;
			}
			float num6 = 0f;
			float num7 = 0f;
			float num8;
			float num9;
			if (num4 >= num5)
			{
				num6 = ((headX < num) ? (-1f) : 1f);
				num8 = ((num6 < 0f) ? num : right) - num6 * 14f;
				num9 = Along(headY, num2 + num3 + 17f, up - num3 - 17f);
			}
			else
			{
				num7 = ((headY < num2) ? (-1f) : 1f);
				num9 = ((num7 < 0f) ? num2 : up) - num7 * 14f;
				num8 = Along(headX, num + num3 + 17f, right - num3 - 17f);
			}
			float num10 = headX - num8;
			float num11 = headY - num9;
			float num12 = (float)Math.Sqrt(num10 * num10 + num11 * num11);
			if (!(num12 > 0f))
			{
				return;
			}
			float num13 = num10 / num12;
			float num14 = num11 / num12;
			float num15 = Math.Min(num12 - TipToHead(scale), 104f);
			if (num15 * (num13 * num6 + num14 * num7) - 14f > 1f)
			{
				float num16 = num8 + num13 * num15;
				float num17 = num9 + num14 * num15;
				float num18 = 0f - num14;
				float num19 = num13;
				if (num19 < 0f || (num19 == 0f && num18 > 0f))
				{
					num18 = 0f - num18;
					num19 = 0f - num19;
				}
				float num20 = (0f - num7) * 17f;
				float num21 = num6 * 17f;
				if (num20 * num18 + num21 * num19 < 0f)
				{
					num20 = 0f - num20;
					num21 = 0f - num21;
				}
				float num22 = num8 + num20;
				float num23 = num9 + num21;
				float num24 = num8 - num20;
				float num25 = num9 - num21;
				for (int i = 0; i <= 12; i++)
				{
					float num26 = (float)i / 12f;
					float num27 = BowAt[i];
					tail.UpperX[i] = num22 + (num16 - num22) * num26 + num18 * 6f * num27;
					tail.UpperY[i] = num23 + (num17 - num23) * num26 + num19 * 6f * num27;
					tail.LowerX[i] = num24 + (num16 - num24) * num26 + num18 * 3f * num27;