Decompiled source of AbsoluteVirtueSurvivor v1.0.1

plugins\AbsoluteVirtueSurvivor\AbsoluteVirtueSurvivor.dll

Decompiled 9 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using AbsoluteVirtueSurvivor.Buffs;
using AbsoluteVirtueSurvivor.Character;
using AbsoluteVirtueSurvivor.Character.Master;
using AbsoluteVirtueSurvivor.Character.States;
using AbsoluteVirtueSurvivor.Character.Survivor;
using AbsoluteVirtueSurvivor.Core;
using AbsoluteVirtueSurvivor.Skills;
using AbsoluteVirtueSurvivor.Skills.Abilities;
using AbsoluteVirtueSurvivor.Skills.Magic;
using AbsoluteVirtueSurvivor.Skills.Polearm;
using AbsoluteVirtueSurvivor.Sound;
using AbsoluteVirtueSurvivor.Vfx;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates;
using HG.BlendableTypes;
using Microsoft.CodeAnalysis;
using On.RoR2;
using R2API;
using Rewired;
using RoR2;
using RoR2.ContentManagement;
using RoR2.Skills;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using XiVfx.Format;
using XiVfx.Unity;
using XiVfx.Unity.Practical;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AbsoluteVirtueSurvivor")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("AbsoluteVirtueSurvivor")]
[assembly: AssemblyTitle("AbsoluteVirtueSurvivor")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace AbsoluteVirtueSurvivor
{
	[BepInPlugin("com.abyssano78.absolutevirtuesurvivor", "AbsoluteVirtueSurvivor", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static Action<DamageReport> <0>__OnTakeDamage;

			public static hook_TakeDamageProcess <1>__HalveDamageOverTime;
		}

		public const string PluginGuid = "com.abyssano78.absolutevirtuesurvivor";

		public const string PluginName = "AbsoluteVirtueSurvivor";

		public const string PluginVersion = "1.0.1";

		private AssetBundle _assetBundle;

		private AssetBundle _vfxBundle;

		private void Awake()
		{
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Expected O, but got Unknown
			Log.Init(((BaseUnityPlugin)this).Logger);
			AVConfig.Init(((BaseUnityPlugin)this).Config);
			string text = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? string.Empty;
			_assetBundle = LoadBundle(text, "absolutevirtueassets");
			if ((Object)(object)_assetBundle == (Object)null)
			{
				return;
			}
			GameObject val = _assetBundle.LoadAsset<GameObject>("AbsoluteVirtue");
			if ((Object)(object)val == (Object)null)
			{
				Log.Error("Could not find a GameObject named AbsoluteVirtue in the AssetBundle.");
				return;
			}
			AVIcons.Init(_assetBundle);
			try
			{
				Log.Info("XiVFX runtime: " + typeof(XiEffectAsset).Assembly.GetName().Version);
				_vfxBundle = LoadBundle(text, "avvfx");
				if ((Object)(object)_vfxBundle != (Object)null)
				{
					AVVfx.Init(_vfxBundle);
				}
			}
			catch (Exception ex)
			{
				Log.Error("FFXI effects unavailable: " + ex);
			}
			AVSound.Init(text);
			AVBuffs.Init();
			GlobalEventManager.onServerDamageDealt += AVLifecycle.OnTakeDamage;
			object obj = <>O.<1>__HalveDamageOverTime;
			if (obj == null)
			{
				hook_TakeDamageProcess val2 = AVLifecycle.HalveDamageOverTime;
				<>O.<1>__HalveDamageOverTime = val2;
				obj = (object)val2;
			}
			HealthComponent.TakeDamageProcess += (hook_TakeDamageProcess)obj;
			try
			{
				if (AVBody.Initialize(val) && AVPolearmSkills.Initialize(AVBody.BodyPrefab) && AVSkills.Initialize(AVBody.BodyPrefab) && AVMaster.Initialize() && AVSurvivor.Initialize())
				{
					AVContentPackProvider.Register();
					Log.Info("Absolute Virtue survivor content prepared.");
				}
				else
				{
					Log.Error("Absolute Virtue survivor setup did not complete.");
				}
			}
			catch (Exception ex2)
			{
				Log.Error("Absolute Virtue survivor initialization failed: " + ex2);
			}
		}

		private static AssetBundle LoadBundle(string directory, string name)
		{
			string text = Path.Combine(directory, name);
			if (!File.Exists(text))
			{
				Log.Error("AssetBundle " + name + " was not found beside the plugin DLL.");
				return null;
			}
			AssetBundle obj = AssetBundle.LoadFromFile(text);
			if ((Object)(object)obj == (Object)null)
			{
				Log.Error("AssetBundle.LoadFromFile(" + name + ") returned null.");
			}
			return obj;
		}

		private void OnDestroy()
		{
			if ((Object)(object)_assetBundle != (Object)null)
			{
				_assetBundle.Unload(false);
			}
			if ((Object)(object)_vfxBundle != (Object)null)
			{
				_vfxBundle.Unload(false);
			}
		}
	}
	internal static class Log
	{
		private static ManualLogSource source;

		internal static void Init(ManualLogSource logSource)
		{
			source = logSource;
		}

		internal static void Info(object data)
		{
			ManualLogSource obj = source;
			if (obj != null)
			{
				obj.LogInfo(data);
			}
		}

		internal static void Warning(object data)
		{
			ManualLogSource obj = source;
			if (obj != null)
			{
				obj.LogWarning(data);
			}
		}

		internal static void Error(object data)
		{
			ManualLogSource obj = source;
			if (obj != null)
			{
				obj.LogError(data);
			}
		}

		internal static void Debug(object data)
		{
			ManualLogSource obj = source;
			if (obj != null)
			{
				obj.LogDebug(data);
			}
		}
	}
}
namespace AbsoluteVirtueSurvivor.Vfx
{
	internal sealed class AVActorLook : IDisposable
	{
		private sealed class ColorLerp
		{
			public Color32 From;

			public Color32 To;

			public int Duration;

			public int Elapsed;
		}

		private sealed class UvLerp
		{
			public float From;

			public float To;

			public int Axis;

			public int Duration;

			public int Elapsed;
		}

		private sealed class Lifetime
		{
			public int Duration;

			public int Elapsed;
		}

		private static readonly Color32 NeutralFade = new Color32((byte)128, (byte)128, (byte)128, (byte)128);

		private Color32 wrapColor;

		private Vector2 wrapUv;

		private Texture2D wrapTexture;

		private Color32 fadeColor = NeutralFade;

		private readonly List<ColorLerp> wrapColors = new List<ColorLerp>();

		private readonly List<UvLerp> wrapUvs = new List<UvLerp>();

		private readonly List<Lifetime> textures = new List<Lifetime>();

		private readonly List<ColorLerp> fades = new List<ColorLerp>();

		private readonly List<SkinnedMeshRenderer> wrapRenderers = new List<SkinnedMeshRenderer>();

		private readonly List<SkinnedMeshRenderer> fadeRenderers = new List<SkinnedMeshRenderer>();

		private Material wrapMaterial;

		private Material fadeMaterial;

		internal void Attach(Transform visual)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)AVVfx.WrapOverlayMaterial))
			{
				wrapMaterial = new Material(AVVfx.WrapOverlayMaterial);
			}
			if (Object.op_Implicit((Object)(object)AVVfx.FadeOverlayMaterial))
			{
				fadeMaterial = new Material(AVVfx.FadeOverlayMaterial);
			}
			SkinnedMeshRenderer[] componentsInChildren = ((Component)visual).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val in componentsInChildren)
			{
				if (!((Object)(object)val.sharedMesh == (Object)null))
				{
					if (Object.op_Implicit((Object)(object)wrapMaterial))
					{
						wrapRenderers.Add(Clone(val, "FFXI wrap", wrapMaterial));
					}
					if (Object.op_Implicit((Object)(object)fadeMaterial))
					{
						fadeRenderers.Add(Clone(val, "FFXI fade", fadeMaterial));
					}
				}
			}
		}

		private static SkinnedMeshRenderer Clone(SkinnedMeshRenderer source, string suffix, Material material)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(((Object)source).name + " " + suffix);
			val.transform.SetParent(((Component)source).transform.parent, false);
			val.transform.localPosition = ((Component)source).transform.localPosition;
			val.transform.localRotation = ((Component)source).transform.localRotation;
			val.transform.localScale = ((Component)source).transform.localScale;
			SkinnedMeshRenderer val2 = val.AddComponent<SkinnedMeshRenderer>();
			val2.sharedMesh = source.sharedMesh;
			val2.bones = source.bones;
			val2.rootBone = source.rootBone;
			val2.updateWhenOffscreen = true;
			((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)val2).receiveShadows = false;
			Material[] array = (Material[])(object)new Material[((Renderer)source).sharedMaterials.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = material;
			}
			((Renderer)val2).sharedMaterials = array;
			((Renderer)val2).enabled = false;
			return val2;
		}

		internal void Apply(XiFfxiActorCommand command)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected I4, but got Unknown
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			XiFfxiActorCommandKind kind = command.Kind;
			switch (kind - 5)
			{
			case 3:
				wrapColors.Add(new ColorLerp
				{
					From = wrapColor,
					To = Argb(command.PackedColorRgba),
					Duration = command.DurationTicks
				});
				break;
			case 2:
				wrapUvs.Add(new UvLerp
				{
					From = ((command.WrapUvAxis == 0) ? wrapUv.x : wrapUv.y),
					To = command.WrapUvEndpoint,
					Axis = command.WrapUvAxis,
					Duration = command.DurationTicks
				});
				break;
			case 1:
				wrapTexture = FindTexture(command.ResourceId, command.DirectoryPath);
				textures.Add(new Lifetime
				{
					Duration = command.DurationTicks
				});
				break;
			case 0:
				fades.Add(new ColorLerp
				{
					From = fadeColor,
					To = Rgba(command.PackedColorRgba),
					Duration = command.DurationTicks
				});
				break;
			}
		}

		private static Color32 Rgba(uint packed)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			return new Color32((byte)(packed & 0xFF), (byte)((packed >> 8) & 0xFF), (byte)((packed >> 16) & 0xFF), (byte)((packed >> 24) & 0xFF));
		}

		private static Color32 Argb(uint packed)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			return new Color32((byte)((packed >> 16) & 0xFF), (byte)((packed >> 8) & 0xFF), (byte)(packed & 0xFF), (byte)((packed >> 24) & 0xFF));
		}

		private static Texture2D FindTexture(string id, string directory)
		{
			id = (id ?? string.Empty).TrimEnd('\0', ' ');
			if (id.Length == 0 || (Object)(object)AVVfx.Asset == (Object)null)
			{
				return null;
			}
			Texture2D val = null;
			XiTextureBinding[] array = AVVfx.Asset.Textures;
			foreach (XiTextureBinding val2 in array)
			{
				if (!((Object)(object)val2?.texture == (Object)null) && !(val2.sectionId.TrimEnd('\0', ' ') != id))
				{
					if (!string.IsNullOrEmpty(directory) && directory.StartsWith(val2.directoryPath ?? "", StringComparison.OrdinalIgnoreCase))
					{
						return val2.texture;
					}
					val = val ?? val2.texture;
				}
			}
			return val;
		}

		internal void StepFfxiFrame()
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			foreach (Lifetime texture in textures)
			{
				texture.Elapsed++;
			}
			textures.RemoveAll((Lifetime item) => item.Elapsed >= item.Duration);
			if (textures.Count == 0)
			{
				wrapTexture = null;
			}
			wrapColor = Advance(wrapColors, wrapColor);
			fadeColor = Advance(fades, fadeColor);
			foreach (UvLerp wrapUv in wrapUvs)
			{
				wrapUv.Elapsed = Mathf.Min(wrapUv.Elapsed + 1, wrapUv.Duration);
				float num = ((wrapUv.Duration == 0) ? 1f : ((float)wrapUv.Elapsed / (float)wrapUv.Duration));
				float num2 = Mathf.Lerp(wrapUv.From, wrapUv.To, num);
				this.wrapUv = ((wrapUv.Axis == 0) ? new Vector2(num2, this.wrapUv.y) : new Vector2(this.wrapUv.x, num2));
			}
			wrapUvs.RemoveAll((UvLerp item) => item.Elapsed >= item.Duration);
		}

		private static Color32 Advance(List<ColorLerp> items, Color32 current)
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			foreach (ColorLerp item in items)
			{
				item.Elapsed = Mathf.Min(item.Elapsed + 1, item.Duration);
				float t = ((item.Duration == 0) ? 1f : ((float)item.Elapsed / (float)item.Duration));
				current = new Color32(Lerp(item.From.r, item.To.r, t), Lerp(item.From.g, item.To.g, t), Lerp(item.From.b, item.To.b, t), Lerp(item.From.a, item.To.a, t));
			}
			items.RemoveAll((ColorLerp item) => item.Elapsed >= item.Duration);
			return current;
		}

		private static byte Lerp(byte a, byte b, float t)
		{
			return (byte)Mathf.FloorToInt((1f - t) * (float)(int)a + t * (float)(int)b);
		}

		internal void Render()
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			bool flag = Object.op_Implicit((Object)(object)wrapMaterial) && wrapColor.a > 0 && (wrapColor.r | wrapColor.g | wrapColor.b) != 0;
			if (flag)
			{
				wrapMaterial.SetColor("_XiFfxiWrapColor", Color32.op_Implicit(wrapColor));
				wrapMaterial.SetVector("_XiFfxiWrapOffset", new Vector4(wrapUv.x, wrapUv.y, 0f, 0f));
				wrapMaterial.SetFloat("_UseTexture", Object.op_Implicit((Object)(object)wrapTexture) ? 1f : 0f);
				if (Object.op_Implicit((Object)(object)wrapTexture))
				{
					wrapMaterial.SetTexture("_XiFfxiWrapTexture", (Texture)(object)wrapTexture);
				}
			}
			foreach (SkinnedMeshRenderer wrapRenderer in wrapRenderers)
			{
				if (Object.op_Implicit((Object)(object)wrapRenderer))
				{
					((Renderer)wrapRenderer).enabled = flag;
				}
			}
			bool flag2 = Object.op_Implicit((Object)(object)fadeMaterial) && (fadeColor.r != 128 || fadeColor.g != 128 || fadeColor.b != 128);
			if (flag2)
			{
				fadeMaterial.SetColor("_FadeColor", Color32.op_Implicit(fadeColor));
			}
			foreach (SkinnedMeshRenderer fadeRenderer in fadeRenderers)
			{
				if (Object.op_Implicit((Object)(object)fadeRenderer))
				{
					((Renderer)fadeRenderer).enabled = flag2;
				}
			}
		}

		public void Dispose()
		{
			foreach (SkinnedMeshRenderer wrapRenderer in wrapRenderers)
			{
				if (Object.op_Implicit((Object)(object)wrapRenderer))
				{
					Object.Destroy((Object)(object)((Component)wrapRenderer).gameObject);
				}
			}
			foreach (SkinnedMeshRenderer fadeRenderer in fadeRenderers)
			{
				if (Object.op_Implicit((Object)(object)fadeRenderer))
				{
					Object.Destroy((Object)(object)((Component)fadeRenderer).gameObject);
				}
			}
			if (Object.op_Implicit((Object)(object)wrapMaterial))
			{
				Object.Destroy((Object)(object)wrapMaterial);
			}
			if (Object.op_Implicit((Object)(object)fadeMaterial))
			{
				Object.Destroy((Object)(object)fadeMaterial);
			}
		}
	}
	internal sealed class AVTargetProxy : MonoBehaviour
	{
		internal Object Owner;

		private CharacterBody body;

		private bool ownerAssigned;

		internal XiPracticalActor Actor { get; private set; }

		internal static AVTargetProxy Create(AVTarget target)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			GameObject val = new GameObject("AV FFXI target");
			AVTargetProxy aVTargetProxy = val.AddComponent<AVTargetProxy>();
			aVTargetProxy.body = target.Body;
			float num = 2f;
			if (Object.op_Implicit((Object)(object)target.Body))
			{
				num = Mathf.Max(1f, (target.Body.corePosition.y - target.Body.footPosition.y) * 2f);
				val.transform.position = target.Body.footPosition;
				val.transform.rotation = Facing(target.Body);
			}
			else
			{
				val.transform.position = target.Point;
			}
			aVTargetProxy.Actor = new XiPracticalActor
			{
				Root = val.transform,
				Joints = XiPracticalSkeleton.BuildGenericAnchors(val.transform, num)
			};
			return aVTargetProxy;
		}

		private static Quaternion Facing(CharacterBody body)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			Transform val = (Object.op_Implicit((Object)(object)body.modelLocator) ? body.modelLocator.modelBaseTransform : null);
			Vector3 val2 = (Object.op_Implicit((Object)(object)val) ? val.forward : body.transform.forward);
			val2.y = 0f;
			if (!(((Vector3)(ref val2)).sqrMagnitude > 0f))
			{
				return Quaternion.identity;
			}
			return Quaternion.LookRotation(val2);
		}

		private void Update()
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			if (Owner != (Object)null)
			{
				ownerAssigned = true;
			}
			else if (ownerAssigned)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.healthComponent) && body.healthComponent.alive)
			{
				((Component)this).transform.position = body.footPosition;
				((Component)this).transform.rotation = Facing(body);
			}
		}
	}
	internal struct AVTarget
	{
		public CharacterBody Body;

		public Vector3 Point;

		public Vector3 CorePosition
		{
			get
			{
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				if (!Object.op_Implicit((Object)(object)Body))
				{
					return Point + Vector3.up;
				}
				return Body.corePosition;
			}
		}

		public static AVTarget Of(CharacterBody body)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			return new AVTarget
			{
				Body = body,
				Point = (Object.op_Implicit((Object)(object)body) ? body.footPosition : Vector3.zero)
			};
		}

		public static AVTarget At(Vector3 point)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return new AVTarget
			{
				Point = point
			};
		}
	}
	internal static class AVVfx
	{
		internal const string AV = "tens/tens";

		internal const string AVMotion = "tens/mot_";

		internal const string Aeroga = "airo";

		internal const string Tornado = "toln";

		internal const string Comet = "mete";

		internal const string Benediction = "kami";

		internal const string BloodWeapon = "blad";

		internal const string Chainspell = "renz";

		internal const string HundredFists = "hyak";

		internal const string MightyStrikes = "mats";

		internal const string PerfectDodge = "touz";

		internal const int TornadoExtraFrames = 120;

		private static float lastShake;

		internal static XiEffectAsset Asset { get; private set; }

		internal static XiSkeletonData Skeleton { get; private set; }

		internal static Material WrapOverlayMaterial { get; private set; }

		internal static Material FadeOverlayMaterial { get; private set; }

		internal static bool Ready => (Object)(object)Asset != (Object)null;

		internal static void Init(AssetBundle bundle)
		{
			Asset = bundle.LoadAllAssets<XiEffectAsset>().FirstOrDefault();
			Shader[] array = bundle.LoadAllAssets<Shader>();
			Shader[] array2 = array;
			foreach (Shader val in array2)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					XiParticleRenderer.RegisteredShaders[((Object)val).name] = val;
				}
			}
			WrapOverlayMaterial = MakeMaterial(array, "AV/FFXI Wrap Overlay");
			FadeOverlayMaterial = MakeMaterial(array, "AV/FFXI Fade Overlay");
			if ((Object)(object)Asset == (Object)null)
			{
				Log.Error("avvfx bundle does not contain the AVEffects XiEffectAsset.");
				return;
			}
			Skeleton = ((IEnumerable<XiSkeletonBinding>)Asset.Skeletons).FirstOrDefault((Func<XiSkeletonBinding, bool>)((XiSkeletonBinding s) => s.sectionId.TrimEnd('\0', ' ') == "ange"))?.skeleton;
			StretchTornado();
			XiPracticalEffect.CameraProvider = SceneCameras;
			Log.Info($"FFXI effects ready: {Asset.EffectRoutines.Length} routines, {Asset.ParticleGenerators.Length} generators, " + string.Format("{0} shaders, skeleton {1}", array.Length, (Skeleton != null) ? "ange" : "missing"));
		}

		private static void StretchTornado()
		{
			HashSet<string> hashSet = new HashSet<string> { "tb00", "tb01", "vib0", "wne0", "wne1", "ras0", "ras1" };
			int num = 0;
			XiParticleGeneratorBinding[] particleGenerators = Asset.ParticleGenerators;
			foreach (XiParticleGeneratorBinding val in particleGenerators)
			{
				if (!(val.directoryPath != "toln") && hashSet.Contains(val.sectionId.TrimEnd('\0', ' ')))
				{
					XiParticleGeneratorProgram program = val.program;
					XiParticleInstruction val2 = ((program != null && program.Sections?.Length > 1) ? ((IEnumerable<XiParticleInstruction>)val.program.Sections[1].Instructions).FirstOrDefault((Func<XiParticleInstruction, bool>)((XiParticleInstruction val5) => val5.OpCode == 1)) : null);
					if (val2?.RawOperands != null && val2.RawOperands.Length >= 8)
					{
						uint num2 = val2.RawOperands[7] >> 16;
						val2.RawOperands[7] = (num2 + 120 << 16) | (val2.RawOperands[7] & 0xFFFF);
						num++;
					}
				}
			}
			bool flag = false;
			XiEffectRoutineBinding val3 = ((IEnumerable<XiEffectRoutineBinding>)Asset.EffectRoutines).FirstOrDefault((Func<XiEffectRoutineBinding, bool>)((XiEffectRoutineBinding r) => r.directoryPath == "toln" && r.sectionId.TrimEnd('\0', ' ') == "main"));
			if (val3?.program?.Sections != null)
			{
				int num3 = 0;
				XiRoutineProgramSection[] sections = val3.program.Sections;
				for (int i = 0; i < sections.Length; i++)
				{
					XiRoutineInstruction[] instructions = sections[i].Instructions;
					foreach (XiRoutineInstruction val4 in instructions)
					{
						if (!flag && num3 >= 60 && val4.Delay > 0)
						{
							val4.Delay += 120;
							flag = true;
						}
						num3 += val4.Delay;
					}
				}
			}
			Log.Info($"Tornado II lengthened: {num} funnel particles +{120} frames, closing shifted: {flag}");
		}

		private static Material MakeMaterial(Shader[] shaders, string name)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			Shader val = ((IEnumerable<Shader>)shaders).FirstOrDefault((Func<Shader, bool>)((Shader s) => ((Object)s).name == name)) ?? Shader.Find(name);
			if ((Object)(object)val == (Object)null)
			{
				Log.Error("Missing shader " + name);
				return null;
			}
			return new Material(val)
			{
				name = name
			};
		}

		private static IEnumerable<Camera> SceneCameras()
		{
			foreach (CameraRigController readOnlyInstances in CameraRigController.readOnlyInstancesList)
			{
				if ((Object)(object)readOnlyInstances != (Object)null && (Object)(object)readOnlyInstances.sceneCam != (Object)null && ((Behaviour)readOnlyInstances.sceneCam).isActiveAndEnabled)
				{
					yield return readOnlyInstances.sceneCam;
				}
			}
		}

		internal static XiPracticalEffect Play(CharacterBody source, string routine, string directory, IList<AVTarget> targets = null, Action<int> onHit = null, float scaleMultiplier = 1f, float timeScale = 1f, bool detachedSounds = false)
		{
			if (!Ready || (Object)(object)source == (Object)null)
			{
				return null;
			}
			AVVfxActor aVVfxActor = AVVfxActor.Get(source);
			if ((Object)(object)aVVfxActor == (Object)null || !aVVfxActor.EnsureActor())
			{
				return null;
			}
			List<XiPracticalActor> list = new List<XiPracticalActor>();
			List<AVTargetProxy> list2 = new List<AVTargetProxy>();
			if (targets != null)
			{
				foreach (AVTarget target in targets)
				{
					AVTargetProxy aVTargetProxy = AVTargetProxy.Create(target);
					list2.Add(aVTargetProxy);
					list.Add(aVTargetProxy.Actor);
				}
			}
			if (list.Count == 0)
			{
				list.Add(aVVfxActor.Actor);
			}
			XiPracticalEffect val;
			try
			{
				val = XiPracticalEffect.Play(Asset, routine, directory, AVConfig.EffectScale.Value * scaleMultiplier, aVVfxActor.Actor, (IList<XiPracticalActor>)list, (IXiFfxiActorCommandContext)(object)aVVfxActor, 0u);
			}
			catch (Exception arg)
			{
				Log.Error($"FFXI routine {routine}@{directory} failed: {arg}");
				val = null;
			}
			if ((Object)(object)val == (Object)null)
			{
				foreach (AVTargetProxy item in list2)
				{
					Object.Destroy((Object)(object)((Component)item).gameObject);
				}
				return null;
			}
			foreach (AVTargetProxy item2 in list2)
			{
				item2.Owner = (Object)(object)val;
			}
			GameObject soundEmitter = ((Component)source).gameObject;
			List<uint> playing = new List<uint>();
			val.SoundEmitted = delegate(int id, Vector3 position)
			{
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				if (detachedSounds)
				{
					uint num = AVSound.PlayAt(id, position, null);
					Log.Info($"{routine}: sound {id} -> playing id {num}");
				}
				else
				{
					uint num2 = AVSound.PlayAt(id, position, Object.op_Implicit((Object)(object)soundEmitter) ? soundEmitter.transform : null);
					if (num2 != 0)
					{
						playing.Add(num2);
					}
				}
			};
			val.CameraShake = delegate(Vector3 position, float near, float far, float amount)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				Shake(position, far, amount);
			};
			if (onHit != null)
			{
				val.Hit = onHit;
			}
			val.TimeScale = timeScale;
			aVVfxActor.Track(val, playing);
			return val;
		}

		private static void Shake(Vector3 position, float radius, float amount)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			if (AVConfig.CameraShake.Value && !(Time.time - lastShake < 0.1f))
			{
				lastShake = Time.time;
				ShakeEmitter.CreateSimpleShakeEmitter(position, new Wave
				{
					amplitude = Mathf.Clamp(amount, 0f, 0.33f) * 6f,
					frequency = 30f,
					cycleOffset = 0f
				}, 0.15f, Mathf.Max(radius, 30f), true);
			}
		}
	}
	internal sealed class AVVfxActor : MonoBehaviour, IXiFfxiActorCommandContext, IXiFfxiActorCommandBackend
	{
		private CharacterBody body;

		private Animator animator;

		private AVAnimationDriver driver;

		private Transform visual;

		private string pendingFollowUp;

		private float followUpAt;

		private bool? pendingWeaponVisibility;

		private readonly List<(XiPracticalEffect effect, List<uint> sounds)> effects = new List<(XiPracticalEffect, List<uint>)>();

		private readonly AVActorLook look = new AVActorLook();

		private float lookClock;

		private float weaponDeadline;

		private CharacterModel characterModel;

		internal XiPracticalActor Actor { get; private set; }

		internal Renderer Spear { get; private set; }

		internal static AVVfxActor Get(CharacterBody body)
		{
			if (!Object.op_Implicit((Object)(object)body))
			{
				return null;
			}
			AVVfxActor component = ((Component)body).GetComponent<AVVfxActor>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return ((Component)body).gameObject.AddComponent<AVVfxActor>();
			}
			return component;
		}

		internal bool EnsureActor()
		{
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected O, but got Unknown
			if (Actor != null && Object.op_Implicit((Object)(object)Actor.Root))
			{
				return true;
			}
			body = ((Component)this).GetComponent<CharacterBody>();
			ModelLocator val = (Object.op_Implicit((Object)(object)body) ? body.modelLocator : null);
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.modelBaseTransform) || !Object.op_Implicit((Object)(object)val.modelTransform) || AVVfx.Skeleton == null)
			{
				return false;
			}
			visual = val.modelTransform.Find("AbsoluteVirtueVisual");
			if (!Object.op_Implicit((Object)(object)visual))
			{
				return false;
			}
			animator = ((Component)visual).GetComponentInChildren<Animator>(true);
			driver = ((Component)this).GetComponent<AVAnimationDriver>();
			Renderer[] componentsInChildren = ((Component)visual).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if (((Object)val2).name.EndsWith("wep3"))
				{
					Spear = val2;
				}
			}
			Actor = new XiPracticalActor
			{
				Root = val.modelBaseTransform,
				Joints = XiPracticalSkeleton.BuildAnchors(visual, AVVfx.Skeleton, new Vector3(1f, -1f, 1f), "bone")
			};
			look.Attach(visual);
			return true;
		}

		internal void Track(XiPracticalEffect effect, List<uint> sounds)
		{
			effects.Add((effect, sounds));
		}

		internal static void Stop(XiPracticalEffect effect)
		{
			if (!Object.op_Implicit((Object)(object)effect))
			{
				return;
			}
			AVVfxActor aVVfxActor = ((Object.op_Implicit((Object)(object)effect.Context) && Object.op_Implicit((Object)(object)effect.Context.SourceActorRoot)) ? ((Component)effect.Context.SourceActorRoot).GetComponentInParent<AVVfxActor>() : null);
			if (Object.op_Implicit((Object)(object)aVVfxActor))
			{
				foreach (var effect2 in aVVfxActor.effects)
				{
					if (!((Object)(object)effect2.effect == (Object)(object)effect))
					{
						continue;
					}
					foreach (uint item in effect2.sounds)
					{
						AVSound.Stop(item);
					}
				}
			}
			effect.Finish();
		}

		internal void SetWeaponVisibleOnNextCommand(bool visible)
		{
			pendingWeaponVisibility = visible;
			weaponDeadline = Time.time + 1.2f;
		}

		internal void SetWeaponVisible(bool visible)
		{
			EnsureActor();
			if (Object.op_Implicit((Object)(object)Spear))
			{
				Spear.enabled = visible;
			}
		}

		private void HideSpearWithBody()
		{
			if (Object.op_Implicit((Object)(object)Spear) && Object.op_Implicit((Object)(object)body))
			{
				if (!Object.op_Implicit((Object)(object)characterModel) && Object.op_Implicit((Object)(object)body.modelLocator) && Object.op_Implicit((Object)(object)body.modelLocator.modelTransform))
				{
					characterModel = ((Component)body.modelLocator.modelTransform).GetComponent<CharacterModel>();
				}
				Spear.forceRenderingOff = (Object)(object)body.currentVehicle != (Object)null || (Object.op_Implicit((Object)(object)characterModel) && characterModel.invisibilityCount > 0);
			}
		}

		private void Update()
		{
			effects.RemoveAll(((XiPracticalEffect effect, List<uint> sounds) item) => !Object.op_Implicit((Object)(object)item.effect));
			if (Object.op_Implicit((Object)(object)Spear) || EnsureActor())
			{
				HideSpearWithBody();
			}
			if (pendingWeaponVisibility.HasValue && Time.time >= weaponDeadline)
			{
				SetWeaponVisible(pendingWeaponVisibility.Value);
				pendingWeaponVisibility = null;
			}
			if (pendingFollowUp != null && Time.time >= followUpAt)
			{
				PlayState(pendingFollowUp, 0.4f);
				pendingFollowUp = null;
			}
			lookClock += Time.deltaTime;
			while (lookClock >= 1f / 60f)
			{
				lookClock -= 1f / 60f;
				look.StepFfxiFrame();
			}
			look.Render();
		}

		private void OnDestroy()
		{
			look.Dispose();
			foreach (var effect in effects)
			{
				if (Object.op_Implicit((Object)(object)effect.effect))
				{
					effect.effect.Finish();
				}
			}
		}

		public bool TryValidate(XiFfxiActorCommand command, out string reason)
		{
			reason = null;
			return true;
		}

		public bool TryExecute(XiFfxiActorCommand command, out string reason)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected I4, but got Unknown
			reason = null;
			if (command == null || command.UseTargetActor)
			{
				return true;
			}
			XiFfxiActorCommandKind kind = command.Kind;
			switch (kind - 1)
			{
			case 0:
				PlayMotion(command.ResourceId, command.DurationTicks);
				break;
			case 10:
				if (Object.op_Implicit((Object)(object)driver))
				{
					driver.ReleaseMotionLock();
				}
				break;
			case 4:
			case 5:
			case 6:
			case 7:
				look.Apply(command);
				break;
			case 11:
			case 12:
			case 13:
			case 15:
				if (pendingWeaponVisibility.HasValue)
				{
					SetWeaponVisible(pendingWeaponVisibility.Value);
					pendingWeaponVisibility = null;
				}
				break;
			}
			return true;
		}

		private void PlayMotion(string resourceId, int durationTicks)
		{
			string text = (resourceId ?? string.Empty).TrimEnd('\0', ' ').Replace('?', '0');
			if (!text.StartsWith("at"))
			{
				switch (text)
				{
				case "mw10":
				case "cm00":
					text = "wz60";
					break;
				case "mw20":
				case "cm10":
					text = "ta00";
					pendingFollowUp = "ta10";
					followUpAt = Time.time + Mathf.Max(0.3f, (float)durationTicks / 60f * 0.6f);
					break;
				}
				PlayState(text, Mathf.Max((float)durationTicks / 60f, 0.3f));
			}
		}

		internal void HoldState(string state)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (EnsureActor() && Object.op_Implicit((Object)(object)animator))
			{
				if (Object.op_Implicit((Object)(object)driver))
				{
					driver.LockFor(0.25f);
				}
				int num = Animator.StringToHash("Base Layer." + state);
				AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(0);
				if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash != num && !animator.IsInTransition(0) && animator.HasState(0, num))
				{
					animator.CrossFadeInFixedTime(num, 0.15f, 0);
				}
			}
		}

		internal void PlayState(string state, float lockSeconds)
		{
			if (!EnsureActor() || !Object.op_Implicit((Object)(object)animator))
			{
				return;
			}
			int num = Animator.StringToHash("Base Layer." + state);
			if (animator.HasState(0, num))
			{
				if (Object.op_Implicit((Object)(object)driver))
				{
					driver.LockFor(lockSeconds);
				}
				animator.CrossFadeInFixedTime(num, 0.12f, 0);
			}
		}
	}
}
namespace AbsoluteVirtueSurvivor.Sound
{
	internal static class AVSound
	{
		private static readonly HashSet<int> available = new HashSet<int>();

		private static string bankPath;

		internal static void Init(string pluginDirectory)
		{
			bankPath = Path.Combine(pluginDirectory, "AbsoluteVirtueBank.bnk");
			string path = Path.Combine(pluginDirectory, "bank-ids.txt");
			if (File.Exists(path))
			{
				string[] array = File.ReadAllLines(path);
				for (int i = 0; i < array.Length; i++)
				{
					if (int.TryParse(array[i].Trim(), out var result))
					{
						available.Add(result);
					}
				}
			}
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(LoadBank));
		}

		private static void LoadBank()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			uint num = default(uint);
			AKRESULT val = AkSoundEngine.LoadBank(bankPath, ref num);
			if ((int)val == 1 || (int)val == 69)
			{
				Log.Info($"Loaded AbsoluteVirtueBank ({num}), {available.Count} FFXI sounds");
			}
			else
			{
				Log.Error($"Could not load {bankPath}: {val}");
			}
		}

		internal static bool Has(int soundId)
		{
			return available.Contains(soundId);
		}

		internal static uint Play(int soundId, GameObject emitter)
		{
			if ((Object)(object)emitter == (Object)null || !available.Contains(soundId))
			{
				return 0u;
			}
			return Util.PlaySound("Play_AV_" + soundId, emitter);
		}

		internal static uint PlayAt(int soundId, Vector3 position, Transform follow)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (!available.Contains(soundId))
			{
				return 0u;
			}
			GameObject val = new GameObject("AV FFXI sound " + soundId);
			val.transform.position = position;
			if (Object.op_Implicit((Object)(object)follow))
			{
				val.transform.SetParent(follow, true);
			}
			AkGameObj obj = val.AddComponent<AkGameObj>();
			obj.isStaticObject = false;
			obj.isStaticAfterDelay = false;
			uint result = AkSoundEngine.PostEvent("Play_AV_" + soundId, val);
			Object.Destroy((Object)(object)val, 30f);
			return result;
		}

		internal static void Stop(uint playingId)
		{
			if (playingId != 0)
			{
				AkSoundEngine.StopPlayingID(playingId);
			}
		}
	}
}
namespace AbsoluteVirtueSurvivor.Skills
{
	internal static class AVSkills
	{
		internal static SkillDef Aeroga;

		internal static SkillDef Tornado;

		internal static SkillDef Comet;

		internal static SkillDef Benediction;

		internal static SkillDef BloodWeapon;

		internal static SkillDef PerfectDodge;

		internal static SkillDef Fervor;

		internal static bool Initialize(GameObject bodyPrefab)
		{
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			SkillLocator component = bodyPrefab.GetComponent<SkillLocator>();
			if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.secondary) || !Object.op_Implicit((Object)(object)component.utility) || !Object.op_Implicit((Object)(object)component.special))
			{
				return false;
			}
			Aeroga = Make("AerogaIV", typeof(AerogaIVState), AVConfig.AerogaCooldown.Value, 1, "Aeroga IV", "Channel for <style=cIsUtility>10s</style>, then strike every enemy around the target with <style=cIsDamage>4 waves of wind</style> for <style=cIsDamage>1400%</style> damage in total.");
			Tornado = Make("TornadoII", typeof(TornadoIIState), AVConfig.TornadoCooldown.Value, 1, "Tornado II", "Channel for <style=cIsUtility>10s</style>, then trap one enemy in a tornado that hits it <style=cIsDamage>12 times for 2400%</style> damage in total and <style=cIsUtility>lowers its armor by 25</style>.");
			Comet = Make("Comet", typeof(CometState), AVConfig.CometCooldown.Value, 1, "Comet", "Channel for <style=cIsUtility>10s</style>, then drop a comet for <style=cIsDamage>3500%</style> dark damage around the target. <style=cIsDamage>Each cast makes the next one 5% stronger</style> (up to +50%).");
			Benediction = Make("Benediction", typeof(BenedictionState), AVConfig.BenedictionCooldown.Value, 2, "Benediction", "<style=cIsHealing>Fully heal</style> and <style=cIsUtility>cleanse</style> yourself and every ally nearby. <style=cIsUtility>Instant, 2 charges.</style>");
			BloodWeapon = Make("BloodWeapon", typeof(BloodWeaponState), AVConfig.BloodWeaponCooldown.Value, 1, "Blood Weapon", "For <style=cIsUtility>30s</style>, polearm attacks <style=cIsHealing>heal you for the damage dealt</style>.");
			PerfectDodge = Make("PerfectDodge", typeof(PerfectDodgeState), AVConfig.PerfectDodgeCooldown.Value, 1, "Perfect Dodge", "For <style=cIsUtility>10s</style>, <style=cIsUtility>no attack can hit you</style>.");
			Fervor = Make("Fervor", typeof(FervorState), AVConfig.FervorCooldown.Value, 1, "Apotheosis", "<style=cIsUtility>(Chainspell + Hundred Fists + Mighty Strikes)</style> For <style=cIsUtility>45s</style>: <style=cIsUtility>spells are instant</style> and their <style=cIsUtility>recast is divided by 3</style>, <style=cIsDamage>+100% attack speed</style>, and <style=cIsDamage>every hit is critical</style>.");
			Assign(component.secondary, Aeroga, "Secondary");
			Assign(component.utility, Tornado, "Utility");
			Assign(component.special, Comet, "Special");
			Type[] array = new Type[7]
			{
				typeof(AerogaIVState),
				typeof(TornadoIIState),
				typeof(CometState),
				typeof(BenedictionState),
				typeof(BloodWeaponState),
				typeof(PerfectDodgeState),
				typeof(FervorState)
			};
			for (int i = 0; i < array.Length; i++)
			{
				AVContent.AddEntityState(array[i]);
			}
			component.passiveSkill = new PassiveSkill
			{
				enabled = true,
				skillNameToken = "ABSOLUTE_VIRTUE_PASSIVE_NAME",
				skillDescriptionToken = "ABSOLUTE_VIRTUE_PASSIVE_DESCRIPTION",
				icon = AVIcons.Get("Passive")
			};
			LanguageAPI.Add("ABSOLUTE_VIRTUE_PASSIVE_NAME", "Absolute Virtue");
			LanguageAPI.Add("ABSOLUTE_VIRTUE_PASSIVE_DESCRIPTION", "<style=cIsHealing>Auto Regen</style>: high natural regeneration. <style=cIsUtility>Magic Defense Bonus</style>: damage over time is halved. Press <style=cIsUtility>D-pad left</style> (or <style=cIsUtility>" + ((object)AVConfig.StanceKey.Value/*cast due to .constrained prefix*/).ToString() + "</style>) to switch between the <style=cIsDamage>Magic</style> and <style=cIsUtility>Ability</style> stances.");
			bodyPrefab.AddComponent<AVStanceController>();
			return true;
		}

		private static SkillDef Make(string id, Type state, float cooldown, int stock, string name, string description)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			SkillDef obj = ScriptableObject.CreateInstance<SkillDef>();
			((Object)obj).name = "AV" + id;
			obj.skillName = "AV" + id;
			obj.skillNameToken = "ABSOLUTE_VIRTUE_" + id.ToUpperInvariant() + "_NAME";
			obj.skillDescriptionToken = "ABSOLUTE_VIRTUE_" + id.ToUpperInvariant() + "_DESCRIPTION";
			obj.icon = AVIcons.Get(id);
			obj.activationState = new SerializableEntityStateType(state);
			obj.activationStateMachineName = "Weapon";
			obj.interruptPriority = (InterruptPriority)1;
			obj.baseRechargeInterval = cooldown;
			obj.baseMaxStock = stock;
			obj.rechargeStock = 1;
			obj.requiredStock = 1;
			obj.stockToConsume = 1;
			obj.fullRestockOnAssign = false;
			obj.beginSkillCooldownOnSkillEnd = false;
			obj.isCombatSkill = true;
			obj.mustKeyPress = true;
			obj.cancelSprintingOnActivation = true;
			obj.canceledFromSprinting = false;
			LanguageAPI.Add(obj.skillNameToken, name);
			LanguageAPI.Add(obj.skillDescriptionToken, description);
			AVContent.AddSkillDef(obj);
			return obj;
		}

		private static void Assign(GenericSkill slot, SkillDef skill, string slotName)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			SkillFamily val = ScriptableObject.CreateInstance<SkillFamily>();
			((Object)val).name = "AbsoluteVirtue" + slotName + "Family";
			Variant[] array = new Variant[1];
			Variant val2 = new Variant
			{
				skillDef = skill
			};
			((Variant)(ref val2)).viewableNode = new Node(skill.skillNameToken, false, (Node)null);
			array[0] = val2;
			val.variants = (Variant[])(object)array;
			slot._skillFamily = val;
			AVContent.AddSkillFamily(val);
		}
	}
	internal sealed class AVStanceController : MonoBehaviour
	{
		private struct SlotState
		{
			public int stock;

			public float stopwatch;

			public float savedAt;

			public bool initialized;
		}

		private CharacterBody body;

		private GenericSkill[] slots;

		private SkillDef[] magic;

		private SkillDef[] ability;

		private SlotState[] magicStates;

		private SlotState[] abilityStates;

		private bool abilityStance;

		private bool initialized;

		internal bool AbilityStance => abilityStance;

		private void Start()
		{
			body = ((Component)this).GetComponent<CharacterBody>();
			SkillLocator component = ((Component)this).GetComponent<SkillLocator>();
			if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)component))
			{
				((Behaviour)this).enabled = false;
				return;
			}
			slots = (GenericSkill[])(object)new GenericSkill[4] { component.primary, component.secondary, component.utility, component.special };
			magic = (SkillDef[])(object)new SkillDef[4]
			{
				(SkillDef)AVPolearmSkills.PrimarySkillDef,
				AVSkills.Aeroga,
				AVSkills.Tornado,
				AVSkills.Comet
			};
			ability = (SkillDef[])(object)new SkillDef[4]
			{
				AVSkills.Benediction,
				AVSkills.BloodWeapon,
				AVSkills.PerfectDodge,
				AVSkills.Fervor
			};
			magicStates = new SlotState[4];
			abilityStates = new SlotState[4];
			initialized = true;
		}

		private void Update()
		{
			if (initialized && Object.op_Implicit((Object)(object)body) && body.hasEffectiveAuthority && StancePressed())
			{
				Toggle();
			}
		}

		private static bool StancePressed()
		{
			//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)
			KeyboardShortcut value = AVConfig.StanceKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				return true;
			}
			if (!ReInput.isReady)
			{
				return false;
			}
			Player player = ReInput.players.GetPlayer(0);
			if (player == null)
			{
				return false;
			}
			foreach (Joystick joystick in player.controllers.Joysticks)
			{
				IGamepadTemplate template = ((Controller)joystick).GetTemplate<IGamepadTemplate>();
				if (template != null && template.dPad.left.justPressed)
				{
					return true;
				}
			}
			return false;
		}

		internal void Toggle()
		{
			Save(abilityStance ? abilityStates : magicStates, abilityStance ? ability : magic);
			abilityStance = !abilityStance;
			SkillDef[] array = (abilityStance ? ability : magic);
			for (int i = 0; i < 4; i++)
			{
				slots[i].UnsetSkillOverride((object)this, magic[i], (SkillOverridePriority)4);
				slots[i].UnsetSkillOverride((object)this, ability[i], (SkillOverridePriority)4);
				if (abilityStance)
				{
					slots[i].SetSkillOverride((object)this, array[i], (SkillOverridePriority)4);
				}
			}
			Restore(abilityStance ? abilityStates : magicStates);
			AVVfxActor aVVfxActor = AVVfxActor.Get(body);
			if (Object.op_Implicit((Object)(object)aVVfxActor))
			{
				aVVfxActor.SetWeaponVisibleOnNextCommand(!abilityStance);
				if ((Object)(object)AVVfx.Play(body, abilityStance ? "bton" : "ntob", "tens/mot_") == (Object)null)
				{
					aVVfxActor.SetWeaponVisible(!abilityStance);
				}
			}
			Log.Info("Absolute Virtue stance: " + (abilityStance ? "Ability" : "Magic"));
		}

		private void Save(SlotState[] states, SkillDef[] defs)
		{
			for (int i = 0; i < 4; i++)
			{
				states[i].stock = slots[i].stock;
				states[i].stopwatch = slots[i].rechargeStopwatch;
				states[i].savedAt = Time.time;
				states[i].initialized = true;
			}
		}

		private void Restore(SlotState[] states)
		{
			for (int i = 0; i < 4; i++)
			{
				GenericSkill val = slots[i];
				if (!states[i].initialized)
				{
					states[i] = new SlotState
					{
						stock = val.maxStock,
						stopwatch = 0f,
						savedAt = Time.time,
						initialized = true
					};
				}
				val.stock = Mathf.Clamp(states[i].stock, 0, val.maxStock);
				val.rechargeStopwatch = Mathf.Max(0f, states[i].stopwatch + (Time.time - states[i].savedAt));
			}
		}

		private void OnDestroy()
		{
			if (!initialized)
			{
				return;
			}
			for (int i = 0; i < 4; i++)
			{
				if (Object.op_Implicit((Object)(object)slots[i]))
				{
					slots[i].UnsetSkillOverride((object)this, ability[i], (SkillOverridePriority)4);
				}
			}
		}
	}
}
namespace AbsoluteVirtueSurvivor.Skills.Polearm
{
	internal static class AVPolearmSkills
	{
		internal static SteppedSkillDef PrimarySkillDef { get; private set; }

		internal static bool Initialize(GameObject bodyPrefab)
		{
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Expected O, but got Unknown
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)bodyPrefab == (Object)null)
			{
				Debug.LogError((object)"[AbsoluteVirtue] Cannot create polearm skill: body prefab is null.");
				return false;
			}
			SkillLocator component = bodyPrefab.GetComponent<SkillLocator>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.primary == (Object)null)
			{
				Debug.LogError((object)"[AbsoluteVirtue] Body has no primary GenericSkill.");
				return false;
			}
			SkillFamily val = ScriptableObject.CreateInstance<SkillFamily>();
			((Object)val).name = "AbsoluteVirtuePrimaryFamily";
			val.variants = Array.Empty<Variant>();
			Sprite val2 = null;
			SkillFamily skillFamily = component.primary.skillFamily;
			if ((Object)(object)skillFamily != (Object)null && skillFamily.variants != null && skillFamily.variants.Length != 0)
			{
				val2 = skillFamily.variants[0].skillDef?.icon;
			}
			PrimarySkillDef = ScriptableObject.CreateInstance<SteppedSkillDef>();
			((Object)PrimarySkillDef).name = "AbsoluteVirtuePolearmCombo";
			((SkillDef)PrimarySkillDef).skillName = "AbsoluteVirtuePolearmCombo";
			((SkillDef)PrimarySkillDef).skillNameToken = "ABSOLUTE_VIRTUE_PRIMARY_POLEARM_NAME";
			((SkillDef)PrimarySkillDef).skillDescriptionToken = "ABSOLUTE_VIRTUE_PRIMARY_POLEARM_DESCRIPTION";
			((SkillDef)PrimarySkillDef).icon = AVIcons.Get("Polearm") ?? val2;
			((SkillDef)PrimarySkillDef).activationState = new SerializableEntityStateType(typeof(AVPolearmComboState));
			((SkillDef)PrimarySkillDef).activationStateMachineName = "Weapon";
			((SkillDef)PrimarySkillDef).interruptPriority = (InterruptPriority)1;
			((SkillDef)PrimarySkillDef).baseMaxStock = 1;
			((SkillDef)PrimarySkillDef).baseRechargeInterval = 0f;
			((SkillDef)PrimarySkillDef).rechargeStock = 1;
			((SkillDef)PrimarySkillDef).requiredStock = 1;
			((SkillDef)PrimarySkillDef).stockToConsume = 1;
			((SkillDef)PrimarySkillDef).fullRestockOnAssign = true;
			((SkillDef)PrimarySkillDef).dontAllowPastMaxStocks = false;
			((SkillDef)PrimarySkillDef).beginSkillCooldownOnSkillEnd = false;
			((SkillDef)PrimarySkillDef).resetCooldownTimerOnUse = false;
			((SkillDef)PrimarySkillDef).isCombatSkill = true;
			((SkillDef)PrimarySkillDef).mustKeyPress = false;
			((SkillDef)PrimarySkillDef).cancelSprintingOnActivation = true;
			((SkillDef)PrimarySkillDef).canceledFromSprinting = false;
			((SkillDef)PrimarySkillDef).forceSprintDuringState = false;
			PrimarySkillDef.stepCount = 3;
			PrimarySkillDef.stepGraceDuration = 0.8f;
			Variant[] array = new Variant[1];
			Variant val3 = new Variant
			{
				skillDef = (SkillDef)(object)PrimarySkillDef,
				unlockableDef = null
			};
			((Variant)(ref val3)).viewableNode = new Node(((SkillDef)PrimarySkillDef).skillNameToken, false, (Node)null);
			array[0] = val3;
			val.variants = (Variant[])(object)array;
			component.primary._skillFamily = val;
			AVContent.AddSkillDef((SkillDef)(object)PrimarySkillDef);
			AVContent.AddSkillFamily(val);
			AVContent.AddEntityState(typeof(AVPolearmComboState));
			LanguageAPI.Add("ABSOLUTE_VIRTUE_PRIMARY_POLEARM_NAME", "Polearm Combo");
			LanguageAPI.Add("ABSOLUTE_VIRTUE_PRIMARY_POLEARM_DESCRIPTION", "Strike for <style=cIsDamage>400%</style>, then <style=cIsDamage>450%</style>, then <style=cIsDamage>500%</style> damage. A critical strike becomes a sweeping blow for <style=cIsDamage>700%</style>. <style=cIsUtility>Hold to keep the combo going.</style>");
			Debug.Log((object)"[AbsoluteVirtue] Polearm Combo primary registered.");
			return true;
		}
	}
}
namespace AbsoluteVirtueSurvivor.Skills.Magic
{
	public abstract class AVSpellState : BaseSkillState
	{
		private GameObject targetObject;

		private Vector3 targetPoint;

		private float castTime;

		private bool released;

		private XiPracticalEffect castEffect;

		private float releaseAge;

		private int hitsApplied;

		private bool damageDone;

		private float damagePerHit;

		private bool crit;

		protected abstract string Directory { get; }

		protected abstract float DamageCoefficient { get; }

		protected abstract float BlastRadius { get; }

		protected virtual int DamageHits => 1;

		protected virtual float ProcCoefficient => 1f;

		protected virtual float AfterReleaseDuration => 1.2f;

		protected virtual bool AreaTargets => false;

		protected virtual DamageSource Source => (DamageSource)2;

		protected virtual int[] PulseFrames => null;

		protected virtual bool UsesHitMarkers => true;

		protected virtual float EffectScaleMultiplier => 1f;

		protected virtual float EffectTimeScale => 1f;

		protected virtual void OnSpellHit(CharacterBody target)
		{
		}

		public override void OnEnter()
		{
			((BaseState)this).OnEnter();
			bool flag = Object.op_Implicit((Object)(object)((EntityState)this).characterBody) && ((EntityState)this).characterBody.HasBuff(AVBuffs.Fervor);
			castTime = (flag ? 0f : AVConfig.CastTime);
			if (((EntityState)this).isAuthority)
			{
				PickTarget();
			}
			((BaseState)this).StartAimMode(castTime + 1f, false);
			if (castTime > 0f)
			{
				castEffect = AVVfx.Play(((EntityState)this).characterBody, "cabk", "tens/tens");
			}
		}

		private void PickTarget()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			Ray aimRay = ((BaseState)this).GetAimRay();
			BullseyeSearch val = new BullseyeSearch
			{
				viewer = ((EntityState)this).characterBody,
				searchOrigin = ((Ray)(ref aimRay)).origin,
				searchDirection = ((Ray)(ref aimRay)).direction,
				maxAngleFilter = 25f,
				maxDistanceFilter = 150f,
				teamMaskFilter = TeamMask.GetUnprotectedTeams(((BaseState)this).GetTeam()),
				filterByLoS = true,
				sortMode = (SortMode)2
			};
			val.RefreshCandidates();
			val.FilterOutGameObject(((EntityState)this).gameObject);
			HurtBox val2 = val.GetResults().FirstOrDefault();
			CharacterBody val3 = ((Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.healthComponent)) ? val2.healthComponent.body : null);
			if (Object.op_Implicit((Object)(object)val3))
			{
				targetObject = ((Component)val3).gameObject;
				targetPoint = val3.footPosition;
			}
			else
			{
				RaycastHit val4 = default(RaycastHit);
				targetPoint = (Physics.Raycast(aimRay, ref val4, 150f, LayerMask.op_Implicit(((LayerIndex)(ref LayerIndex.world)).mask), (QueryTriggerInteraction)1) ? ((RaycastHit)(ref val4)).point : ((Ray)(ref aimRay)).GetPoint(40f));
			}
		}

		public override void FixedUpdate()
		{
			((EntityState)this).FixedUpdate();
			if (!released && ((EntityState)this).fixedAge >= castTime)
			{
				Release();
			}
			if (!released)
			{
				if (((EntityState)this).fixedAge > 0.3f)
				{
					AVVfxActor.Get(((EntityState)this).characterBody)?.HoldState("ma00");
				}
				return;
			}
			releaseAge += Time.fixedDeltaTime;
			if (((EntityState)this).isAuthority && releaseAge >= AfterReleaseDuration)
			{
				((EntityState)this).outer.SetNextStateToMain();
			}
		}

		private void Release()
		{
			released = true;
			AVVfxActor.Stop(castEffect);
			castEffect = null;
			crit = ((BaseState)this).RollCrit();
			damagePerHit = ((BaseState)this).damageStat * DamageCoefficient * AVBuffs.CometMultiplier((Directory == "mete") ? ((EntityState)this).characterBody : null) / (float)Mathf.Max(1, DamageHits);
			List<AVTarget> targets = BuildTargets();
			AVVfx.Play(((EntityState)this).characterBody, "shbk", "tens/tens");
			XiPracticalEffect val = AVVfx.Play(((EntityState)this).characterBody, "main", Directory, targets, OnHitMarker, EffectScaleMultiplier, EffectTimeScale);
			int[] pulses = PulseFrames;
			if ((Object)(object)val != (Object)null && pulses != null && ((EntityState)this).isAuthority)
			{
				int nextPulse = 0;
				val.Stepped = delegate(long frame)
				{
					while (nextPulse < pulses.Length && frame >= pulses[nextPulse])
					{
						nextPulse++;
						RegisterHit();
					}
				};
			}
			if (((EntityState)this).isAuthority)
			{
				if ((Object)(object)val == (Object)null)
				{
					ApplyRemainingDamage();
				}
				else
				{
					val.Ended = (Action)Delegate.Combine(val.Ended, (Action)delegate
					{
						if (!damageDone)
						{
							ApplyRemainingDamage();
						}
					});
				}
			}
			OnReleased();
			if (((EntityState)this).isAuthority && ((EntityState)this).characterBody.HasBuff(AVBuffs.Fervor) && Object.op_Implicit((Object)(object)((BaseSkillState)this).activatorSkillSlot))
			{
				float num = Mathf.Max(1f, AVConfig.ApotheosisCooldownDivisor.Value);
				((BaseSkillState)this).activatorSkillSlot.rechargeStopwatch = Mathf.Max(((BaseSkillState)this).activatorSkillSlot.rechargeStopwatch, ((BaseSkillState)this).activatorSkillSlot.finalRechargeInterval * (1f - 1f / num));
			}
		}

		protected virtual void OnReleased()
		{
		}

		private List<AVTarget> BuildTargets()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			CharacterBody val = (Object.op_Implicit((Object)(object)targetObject) ? targetObject.GetComponent<CharacterBody>() : null);
			List<AVTarget> list = new List<AVTarget> { Object.op_Implicit((Object)(object)val) ? AVTarget.Of(val) : AVTarget.At(targetPoint) };
			if (!AreaTargets)
			{
				return list;
			}
			Vector3 corePosition = list[0].CorePosition;
			TeamIndex team = ((BaseState)this).GetTeam();
			foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList)
			{
				if (list.Count >= 8)
				{
					break;
				}
				if (Object.op_Implicit((Object)(object)readOnlyInstances) && !((Object)(object)readOnlyInstances == (Object)(object)val) && !((Object)(object)readOnlyInstances == (Object)(object)((EntityState)this).characterBody) && Object.op_Implicit((Object)(object)readOnlyInstances.healthComponent) && readOnlyInstances.healthComponent.alive && Object.op_Implicit((Object)(object)readOnlyInstances.teamComponent) && readOnlyInstances.teamComponent.teamIndex != team)
				{
					Vector3 val2 = readOnlyInstances.corePosition - corePosition;
					if (!(((Vector3)(ref val2)).sqrMagnitude > BlastRadius * BlastRadius))
					{
						list.Add(AVTarget.Of(readOnlyInstances));
					}
				}
			}
			return list;
		}

		private void OnHitMarker(int targetIndex)
		{
			if (((EntityState)this).isAuthority && !damageDone && UsesHitMarkers && targetIndex <= 0)
			{
				RegisterHit();
			}
		}

		private void RegisterHit()
		{
			if (!damageDone)
			{
				hitsApplied++;
				Blast(damagePerHit);
				if (hitsApplied >= Mathf.Max(1, DamageHits))
				{
					damageDone = true;
				}
			}
		}

		private void ApplyRemainingDamage()
		{
			int num = Mathf.Max(1, DamageHits) - hitsApplied;
			if (num > 0)
			{
				Blast(damagePerHit * (float)num);
			}
			hitsApplied = Mathf.Max(1, DamageHits);
			damageDone = true;
		}

		private void Blast(float damage)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			CharacterBody val = (Object.op_Implicit((Object)(object)targetObject) ? targetObject.GetComponent<CharacterBody>() : null);
			Vector3 position = (Object.op_Implicit((Object)(object)val) ? val.corePosition : (targetPoint + Vector3.up));
			HitPoint[] array = (HitPoint[])(((object)new BlastAttack
			{
				attacker = ((EntityState)this).gameObject,
				inflictor = ((EntityState)this).gameObject,
				teamIndex = ((BaseState)this).GetTeam(),
				position = position,
				radius = BlastRadius,
				falloffModel = (FalloffModel)0,
				baseDamage = damage,
				baseForce = 0f,
				crit = crit,
				damageType = new DamageTypeCombo(DamageTypeCombo.op_Implicit((DamageType)0), (DamageTypeExtended)0, Source),
				procCoefficient = ProcCoefficient,
				attackerFiltering = (AttackerFiltering)2
			}.Fire().hitPoints) ?? ((object)new HitPoint[0]));
			foreach (HitPoint val2 in array)
			{
				CharacterBody val3 = ((Object.op_Implicit((Object)(object)val2.hurtBox) && Object.op_Implicit((Object)(object)val2.hurtBox.healthComponent)) ? val2.hurtBox.healthComponent.body : null);
				if (Object.op_Implicit((Object)(object)val3))
				{
					OnSpellHit(val3);
				}
			}
		}

		public override void OnExit()
		{
			if (!released)
			{
				AVVfxActor.Stop(castEffect);
			}
			((EntityState)this).OnExit();
		}

		public override InterruptPriority GetMinimumInterruptPriority()
		{
			if (released)
			{
				return (InterruptPriority)0;
			}
			return (InterruptPriority)2;
		}

		public override void OnSerialize(NetworkWriter writer)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			((BaseSkillState)this).OnSerialize(writer);
			writer.Write(targetObject);
			writer.Write(targetPoint);
		}

		public override void OnDeserialize(NetworkReader reader)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			((BaseSkillState)this).OnDeserialize(reader);
			targetObject = reader.ReadGameObject();
			targetPoint = reader.ReadVector3();
		}
	}
	public sealed class AerogaIVState : AVSpellState
	{
		protected override string Directory => "airo";

		protected override float DamageCoefficient => 14f;

		protected override float BlastRadius => 16f;

		protected override bool AreaTargets => true;

		protected override int[] PulseFrames => new int[2] { 30, 90 };

		protected override int DamageHits => 4;

		protected override float ProcCoefficient => 0.6f;

		protected override DamageSource Source => (DamageSource)2;
	}
	public sealed class TornadoIIState : AVSpellState
	{
		private static readonly int[] Ticks = new int[12]
		{
			70, 90, 110, 130, 150, 170, 190, 210, 230, 250,
			270, 290
		};

		protected override string Directory => "toln";

		protected override float DamageCoefficient => 24f;

		protected override float BlastRadius => 4f;

		protected override int DamageHits => Ticks.Length;

		protected override int[] PulseFrames => Ticks;

		protected override bool UsesHitMarkers => false;

		protected override float ProcCoefficient => 0.25f;

		protected override DamageSource Source => (DamageSource)4;

		protected override void OnSpellHit(CharacterBody target)
		{
			if (NetworkServer.active)
			{
				target.AddTimedBuff(AVBuffs.WindTorn, 8f);
			}
		}
	}
	public sealed class CometState : AVSpellState
	{
		protected override string Directory => "mete";

		protected override float DamageCoefficient => 35f;

		protected override float BlastRadius => 13f;

		protected override float EffectScaleMultiplier => 1.5f;

		protected override DamageSource Source => (DamageSource)8;

		protected override void OnReleased()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (((EntityState)this).isAuthority && ((EntityState)this).characterBody.GetBuffCount(AVBuffs.CometFocus) < 10)
			{
				((EntityState)this).characterBody.AddTimedBuffAuthority(AVBuffs.CometFocus.buffIndex, 20f);
			}
		}
	}
}
namespace AbsoluteVirtueSurvivor.Skills.Abilities
{
	public abstract class AVAbilityState : BaseSkillState
	{
		protected abstract string[] Directories { get; }

		protected virtual float Duration => 1.6f;

		public override void OnEnter()
		{
			((BaseState)this).OnEnter();
			string[] directories = Directories;
			foreach (string directory in directories)
			{
				AVVfx.Play(((EntityState)this).characterBody, "main", directory, Targets());
			}
			if (((EntityState)this).isAuthority)
			{
				Activate();
			}
		}

		private protected virtual IList<AVTarget> Targets()
		{
			return null;
		}

		protected abstract void Activate();

		public override void FixedUpdate()
		{
			((EntityState)this).FixedUpdate();
			if (((EntityState)this).isAuthority && ((EntityState)this).fixedAge >= Duration)
			{
				((EntityState)this).outer.SetNextStateToMain();
			}
		}

		public override InterruptPriority GetMinimumInterruptPriority()
		{
			return (InterruptPriority)2;
		}
	}
	public sealed class BenedictionState : AVAbilityState
	{
		private const float Radius = 40f;

		private bool healed;

		protected override string[] Directories => new string[1] { "kami" };

		private protected override IList<AVTarget> Targets()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			List<AVTarget> list = new List<AVTarget>();
			foreach (TeamComponent teamMember in TeamComponent.GetTeamMembers(((BaseState)this).GetTeam()))
			{
				CharacterBody val = (Object.op_Implicit((Object)(object)teamMember) ? teamMember.body : null);
				if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.healthComponent) || !val.healthComponent.alive)
				{
					continue;
				}
				Vector3 val2 = val.corePosition - ((EntityState)this).characterBody.corePosition;
				if (!(((Vector3)(ref val2)).sqrMagnitude > 1600f))
				{
					list.Add(AVTarget.Of(val));
					if (list.Count >= 8)
					{
						break;
					}
				}
			}
			return list;
		}

		protected override void Activate()
		{
		}

		public override void FixedUpdate()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			base.FixedUpdate();
			if (healed || ((EntityState)this).fixedAge < 1.2f)
			{
				return;
			}
			healed = true;
			if (!NetworkServer.active)
			{
				return;
			}
			foreach (AVTarget item in Targets())
			{
				item.Body.healthComponent.HealFraction(1f, default(ProcChainMask));
				Util.CleanseBody(item.Body, true, false, false, true, true, false);
			}
		}
	}
	public sealed class BloodWeaponState : AVAbilityState
	{
		protected override string[] Directories => new string[1] { "blad" };

		protected override void Activate()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			((EntityState)this).characterBody.AddTimedBuffAuthority(AVBuffs.BloodWeapon.buffIndex, 30f);
		}
	}
	public sealed class FervorState : AVAbilityState
	{
		protected override string[] Directories => new string[2] { "renz", "hyak" };

		protected override void Activate()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			((EntityState)this).characterBody.AddTimedBuffAuthority(AVBuffs.Fervor.buffIndex, 45f);
		}
	}
	public sealed class PerfectDodgeState : AVAbilityState
	{
		protected override string[] Directories => new string[1] { "touz" };

		protected override float Duration => 0.8f;

		protected override void Activate()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			((EntityState)this).characterBody.AddTimedBuffAuthority(AVBuffs.PerfectDodge.buffIndex, 10f);
			((EntityState)this).characterBody.AddTimedBuffAuthority(Buffs.HiddenInvincibility.buffIndex, 10f);
		}
	}
}
namespace AbsoluteVirtueSurvivor.Core
{
	internal static class AVConfig
	{
		internal static ConfigEntry<float> EffectScale;

		internal static ConfigEntry<float> PolearmHitboxScale;

		internal static ConfigEntry<float> ApotheosisCooldownDivisor;

		internal static ConfigEntry<bool> FfxiCastTimes;

		internal static ConfigEntry<float> FastCastTime;

		internal static ConfigEntry<KeyboardShortcut> StanceKey;

		internal static ConfigEntry<bool> CameraShake;

		internal static ConfigEntry<bool> Voice;

		internal static ConfigEntry<float> AerogaCooldown;

		internal static ConfigEntry<float> TornadoCooldown;

		internal static ConfigEntry<float> CometCooldown;

		internal static ConfigEntry<float> BenedictionCooldown;

		internal static ConfigEntry<float> BloodWeaponCooldown;

		internal static ConfigEntry<float> FervorCooldown;

		internal static ConfigEntry<float> PerfectDodgeCooldown;

		internal static float CastTime
		{
			get
			{
				if (!FfxiCastTimes.Value)
				{
					return Mathf.Max(0f, FastCastTime.Value);
				}
				return 10f;
			}
		}

		internal static void Init(ConfigFile config)
		{
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			EffectScale = config.Bind<float>("Visuals", "FFXI effect scale", 3.5f, "World size of one FFXI unit for the original effects. 3.5 matches AV's model scale.");
			PolearmHitboxScale = config.Bind<float>("Gameplay", "Polearm hitbox scale", 2.5f, "Multiplier on the polearm attack volumes (1 = exactly the weapon).");
			ApotheosisCooldownDivisor = config.Bind<float>("Gameplay", "Apotheosis spell cooldown divisor", 3f, "While Apotheosis (Chainspell) lasts, spells are instant and their cooldown is divided by this.");
			CameraShake = config.Bind<bool>("Visuals", "Camera shake", true, "Play the camera shakes authored in the FFXI effects (Comet, Aeroga IV...).");
			Voice = config.Bind<bool>("Audio", "Absolute Virtue voice", true, "Play AV's FFXI attack / hurt voice lines.");
			FfxiCastTimes = config.Bind<bool>("Gameplay", "FFXI cast times", true, "Use FFXI's 10 second cast times for Aeroga IV, Tornado II and Comet (AV can move while casting).");
			FastCastTime = config.Bind<float>("Gameplay", "Cast time", 1.5f, "Cast time in seconds when FFXI cast times are disabled.");
			StanceKey = config.Bind<KeyboardShortcut>("Controls", "Stance key", new KeyboardShortcut((KeyCode)102, Array.Empty<KeyCode>()), "Keyboard key that switches between the Magic and Ability stances (gamepad: D-pad left).");
			AerogaCooldown = config.Bind<float>("Cooldowns", "Aeroga IV", 50f, "FFXI recast: 50s");
			TornadoCooldown = config.Bind<float>("Cooldowns", "Tornado II", 60f, "FFXI recast: 60s");
			CometCooldown = config.Bind<float>("Cooldowns", "Comet", 45f, "FFXI recast: 45s");
			BenedictionCooldown = config.Bind<float>("Cooldowns", "Benediction", 60f, "Seconds per charge (2 charges: 120s to refill both)");
			BloodWeaponCooldown = config.Bind<float>("Cooldowns", "Blood Weapon", 90f, "FFXI recast: 120s");
			FervorCooldown = config.Bind<float>("Cooldowns", "Apotheosis", 60f, "Chainspell + Hundred Fists + Mighty Strikes");
			PerfectDodgeCooldown = config.Bind<float>("Cooldowns", "Perfect Dodge", 60f, "FFXI recast: 60s");
		}
	}
	internal static class AVContent
	{
		internal static void AddBody(GameObject bodyPrefab)
		{
			AVContentPackProvider.BodyPrefabs.Add(bodyPrefab);
		}

		internal static void AddMaster(GameObject masterPrefab)
		{
			AVContentPackProvider.MasterPrefabs.Add(masterPrefab);
		}

		internal static void AddSurvivor(SurvivorDef survivorDef)
		{
			AVContentPackProvider.SurvivorDefs.Add(survivorDef);
		}

		internal static void AddSkillDef(SkillDef skillDef)
		{
			AVContentPackProvider.SkillDefs.Add(skillDef);
		}

		internal static void AddSkillFamily(SkillFamily skillFamily)
		{
			AVContentPackProvider.SkillFamilies.Add(skillFamily);
		}

		internal static void AddEntityState(Type entityStateType)
		{
			AVContentPackProvider.EntityStateTypes.Add(entityStateType);
		}
	}
	internal sealed class AVContentPackProvider : IContentPackProvider
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static CollectContentPackProvidersDelegate <0>__AddProvider;
		}

		private readonly ContentPack _contentPack = new ContentPack();

		internal static readonly List<GameObject> BodyPrefabs = new List<GameObject>();

		internal static readonly List<GameObject> MasterPrefabs = new List<GameObject>();

		internal static readonly List<SurvivorDef> SurvivorDefs = new List<SurvivorDef>();

		internal static readonly List<SkillDef> SkillDefs = new List<SkillDef>();

		internal static readonly List<SkillFamily> SkillFamilies = new List<SkillFamily>();

		internal static readonly List<Type> EntityStateTypes = new List<Type>();

		public string identifier => "com.abyssano78.absolutevirtuesurvivor";

		internal static void Register()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			object obj = <>O.<0>__AddProvider;
			if (obj == null)
			{
				CollectContentPackProvidersDelegate val = AddProvider;
				<>O.<0>__AddProvider = val;
				obj = (object)val;
			}
			ContentManager.collectContentPackProviders += (CollectContentPackProvidersDelegate)obj;
		}

		private static void AddProvider(AddContentPackProviderDelegate addContentPackProvider)
		{
			addContentPackProvider.Invoke((IContentPackProvider)(object)new AVContentPackProvider());
		}

		public IEnumerator LoadStaticContentAsync(LoadStaticContentAsyncArgs args)
		{
			_contentPack.identifier = identifier;
			_contentPack.bodyPrefabs.Add(BodyPrefabs.ToArray());
			_contentPack.masterPrefabs.Add(MasterPrefabs.ToArray());
			_contentPack.survivorDefs.Add(SurvivorDefs.ToArray());
			_contentPack.skillDefs.Add(SkillDefs.ToArray());
			_contentPack.skillFamilies.Add(SkillFamilies.ToArray());
			_contentPack.entityStateTypes.Add(EntityStateTypes.ToArray());
			args.ReportProgress(1f);
			yield break;
		}

		public IEnumerator GenerateContentPackAsync(GetContentPackAsyncArgs args)
		{
			ContentPack.Copy(_contentPack, args.output);
			args.ReportProgress(1f);
			yield break;
		}

		public IEnumerator FinalizeAsync(FinalizeAsyncArgs args)
		{
			args.ReportProgress(1f);
			yield break;
		}
	}
	internal static class AVIcons
	{
		private static readonly Dictionary<string, Sprite> sprites = new Dictionary<string, Sprite>();

		internal static void Init(AssetBundle bundle)
		{
			if (!Object.op_Implicit((Object)(object)bundle))
			{
				return;
			}
			Sprite[] array = bundle.LoadAllAssets<Sprite>();
			foreach (Sprite val in array)
			{
				if (((Object)val).name.StartsWith("AVIcon_"))
				{
					sprites[((Object)val).name.Substring(7)] = val;
				}
			}
			Log.Info($"{sprites.Count} skill icons");
		}

		internal static Sprite Get(string id)
		{
			if (!sprites.TryGetValue(id, out var value))
			{
				return null;
			}
			return value;
		}
	}
}
namespace AbsoluteVirtueSurvivor.Character
{
	public class AVDeathState : GenericCharacterDeath
	{
		private const float BodyLifetime = 5f;

		public override bool shouldAutoDestroy => false;

		public override void OnEnter()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			((GenericCharacterDeath)this).OnEnter();
			if (Object.op_Implicit((Object)(object)((EntityState)this).characterMotor))
			{
				((EntityState)this).characterMotor.velocity = Vector3.zero;
			}
			AVAnimationDriver component = ((EntityState)this).GetComponent<AVAnimationDriver>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.SetLocomotionLocked(locked: true);
			}
			if ((Object)(object)AVVfx.Play(((EntityState)this).characterBody, "dead", "tens/tens", null, null, 1f, 1f, detachedSounds: true) == (Object)null)
			{
				AVVfxActor.Get(((EntityState)this).characterBody)?.PlayState("ded0", 5f);
			}
		}

		public override void PlayDeathAnimation(float crossfadeDuration = 0.1f)
		{
		}

		public override void FixedUpdate()
		{
			((GenericCharacterDeath)this).FixedUpdate();
			if (NetworkServer.active && ((EntityState)this).fixedAge > 5f)
			{
				EntityState.Destroy((Object)(object)((EntityState)this).gameObject);
			}
		}

		public override InterruptPriority GetMinimumInterruptPriority()
		{
			return (InterruptPriority)9;
		}
	}
	internal sealed class AVLifecycle : MonoBehaviour
	{
		private CharacterBody body;

		private bool introPlayed;

		private float lastHurtVoice;

		private float startTime;

		private void Start()
		{
			body = ((Component)this).GetComponent<CharacterBody>();
			startTime = Time.time;
			AVVfxActor.Get(body);
		}

		private void Update()
		{
			if (!introPlayed && Object.op_Implicit((Object)(object)body) && AVVfx.Ready && !((Object)(object)body.currentVehicle != (Object)null) && !(Time.time - startTime < 0.5f))
			{
				introPlayed = true;
				AVVfx.Play(body, "app3", "tens/tens");
			}
		}

		internal static void HalveDamageOverTime(orig_TakeDamageProcess orig, HealthComponent self, DamageInfo damageInfo)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Invalid comparison between Unknown and I4
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)self) && damageInfo != null && Object.op_Implicit((Object)(object)self.body) && Object.op_Implicit((Object)(object)((Component)self.body).GetComponent<AVLifecycle>()) && ((int)damageInfo.dotIndex != -1 || (damageInfo.damageType.damageType & 0x4000000) != 0))
			{
				damageInfo.damage *= 0.5f;
			}
			orig.Invoke(self, damageInfo);
		}

		internal static void OnTakeDamage(DamageReport report)
		{
			CharacterBody val = report?.victimBody;
			if (Object.op_Implicit((Object)(object)val) && AVConfig.Voice.Value)
			{
				AVLifecycle component = ((Component)val).GetComponent<AVLifecycle>();
				if (Object.op_Implicit((Object)(object)component) && !(Time.time - component.lastHurtVoice < 4f) && !(report.damageDealt < val.healthComponent.fullCombinedHealth * 0.08f))
				{
					component.lastHurtVoice = Time.time;
					AVVfx.Play(val, "vdam", "tens/tens");
				}
			}
		}
	}
	public sealed class AVAnimationDriver : MonoBehaviour
	{
		private static readonly int IdleState = Animator.StringToHash("Base Layer.btl0");

		private static readonly int WalkState = Animator.StringToHash("Base Layer.1lk0");

		private static readonly int RunState = Animator.StringToHash("Base Layer.1un0");

		private CharacterBody _body;

		private CharacterMotor _motor;

		private ModelLocator _modelLocator;

		private Animator _animator;

		private int _requestedState;

		private bool _locomotionLocked;

		private const float MoveThresholdSquared = 0.04f;

		private const float CrossFadeDuration = 0.12f;

		private float _motionLockUntil;

		private void Awake()
		{
			ResolveReferences();
		}

		private void Start()
		{
			ResolveReferences();
			PlayState(IdleState, immediate: true);
		}

		private void ResolveReferences()
		{
			_body = ((Component)this).GetComponent<CharacterBody>();
			_motor = ((Component)this).GetComponent<CharacterMotor>();
			_modelLocator = ((Component)this).GetComponent<ModelLocator>();
			if ((Object)(object)_modelLocator != (Object)null && (Object)(object)_modelLocator.modelTransform != (Object)null)
			{
				Animator[] componentsInChildren = ((Component)_modelLocator.modelTransform).GetComponentsInChildren<Animator>(true);
				foreach (Animator val in componentsInChildren)
				{
					if ((Object)(object)val != (Object)null && val.layerCount > 0 && val.HasState(0, IdleState))
					{
						_animator = val;
						break;
					}
				}
			}
			if ((Object)(object)_animator == (Object)null)
			{
				Animator[] componentsInChildren = ((Component)this).GetComponentsInChildren<Animator>(true);
				foreach (Animator val2 in componentsInChildren)
				{
					if ((Object)(object)val2 != (Object)null && val2.layerCount > 0 && val2.HasState(0, IdleState))
					{
						_animator = val2;
						break;
					}
				}
			}
			if ((Object)(object)_animator != (Object)null)
			{
				((Behaviour)_animator).enabled = true;
				_animator.speed = 1f;
				_animator.applyRootMotion = false;
				_animator.cullingMode = (AnimatorCullingMode)0;
				_animator.updateMode = (AnimatorUpdateMode)0;
			}
		}

		public void SetLocomotionLocked(bool locked)
		{
			_locomotionLocked = locked;
		}

		public void LockFor(float seconds)
		{
			_motionLockUntil = Mathf.Max(_motionLockUntil, Time.time + seconds);
			_requestedState = 0;
		}

		public void ReleaseMotionLock()
		{
			_motionLockUntil = 0f;
			_requestedState = 0;
		}

		public void ForceRefresh()
		{
			_requestedState = 0;
		}

		private void Update()
		{
			if (!_locomotionLocked && !(Time.time < _motionLockUntil))
			{
				if ((Object)(object)_animator == (Object)null || (Object)(object)_body == (Object)null)
				{
					ResolveReferences();
				}
				else
				{
					UpdateLocomotionAnimation();
				}
			}
		}

		private void UpdateLocomotionAnimation()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			if ((Object)(object)_motor != (Object)null)
			{
				Vector3 velocity = _motor.velocity;
				velocity.y = 0f;
				flag = ((Vector3)(ref velocity)).sqrMagnitude > 0.04f;
			}
			int stateHash = ((!flag) ? IdleState : ((!_body.isSprinting) ? WalkState : RunState));
			PlayState(stateHash, immediate: false);
		}

		private void PlayState(int stateHash, bool immediate)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_animator == (Object)null)
			{
				return;
			}
			if (!_animator.HasState(0, stateHash))
			{
				Debug.LogError((object)$"[AbsoluteVirtue] Animator state missing: {stateHash}");
				return;
			}
			AnimatorStateInfo currentAnimatorStateInfo = _animator.GetCurrentAnimatorStateInfo(0);
			AnimatorStateInfo nextAnimatorStateInfo = _animator.GetNextAnimatorStateInfo(0);
			bool num = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash == stateHash;
			bool flag = _animator.IsInTransition(0) && ((AnimatorStateInfo)(ref nextAnimatorStateInfo)).fullPathHash == stateHash;
			if (num || flag)
			{
				_requestedState = stateHash;
				return;
			}
			if (immediate)
			{
				_animator.Play(stateHash, 0, 0f);
			}
			else
			{
				_animator.CrossFade(stateHash, 0.12f, 0, 0f);
			}
			_requestedState = stateHash;
		}
	}
	public static class AVBody
	{
		private static readonly Quaternion VisualAxisCorrection = Quaternion.Euler(0f, -90f, 0f);

		public static GameObject BodyPrefab { get; private set; }

		public static GameObject DisplayPrefab { get; private set; }

		public static bool Initialize(GameObject visualPrefab)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)visualPrefab == (Object)null)
			{
				Debug.LogError((object)"[AbsoluteVirtue] Visual prefab is null.");
				return false;
			}
			GameObject val = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Commando/CommandoBody.prefab").WaitForCompletion();
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogError((object)"[AbsoluteVirtue] Could not load CommandoBody.");
				return false;
			}
			BodyPrefab = PrefabAPI.InstantiateClone(val, "AbsoluteVirtueBody", true);
			CharacterBody component = BodyPrefab.GetComponent<CharacterBody>();
			ModelLocator component2 = BodyPrefab.GetComponent<ModelLocator>();
			CharacterDirection component3 = BodyPrefab.GetComponent<CharacterDirection>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)component2.modelBaseTransform == (Object)null)
			{
				Debug.LogError((object)"[AbsoluteVirtue] Cloned body lacks required components.");
				BodyPrefab = null;
				return false;
			}
			Transform modelTransform = component2.modelTransform;
			if ((Object)(object)modelTransform != (Object)null)
			{
				Renderer[] componentsInChildren = ((Component)modelTransform).GetComponentsInChildren<Renderer>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].enabled = false;
				}
				((Component)modelTransform).gameObject.SetActive(false);
			}
			GameObject val2 = new GameObject("AbsoluteVirtueModelRoot");
			Transform transform = val2.transform;
			transform.SetParent(component2.modelBaseTransform, false);
			transform.localPosition = Vector3.zero;
			transform.localRotation = Quaternion.identity;
			transform.localScale = Vector3.one;
			GameObject val3 = Object.Instantiate<GameObject>(visualPrefab, transform);
			((Object)val3).name = "AbsoluteVirtueVisual";
			val3.transform.localPosition = Vector3.zero;
			val3.transform.localRotation = VisualAxisCorrection;
			val3.transform.localScale = Vector3.one * 3.5f;
			val3.SetActive(true);
			component2.modelTransform = transform;
			ConfigureHurtBox(transform, modelTransform, component);
			Animator componentInChildren = val3.GetComponentInChildren<Animator>(true);
			if ((Object)(object)componentInChildren == (Object)null)
			{
				Debug.LogError((object)"[AbsoluteVirtue] No Animator found on the AV model.");
				return false;
			}
			((Behaviour)componentInChildren).enabled = true;
			componentInChildren.speed = 1f;
			componentInChildren.applyRootMotion = false;
			componentInChildren.cullingMode = (AnimatorCullingMode)0;
			componentInChildren.updateMode = (AnimatorUpdateMode)0;
			if ((Object)(object)component3 != (Object)null)
			{
				component3.targetTransform = component2.modelBaseTransform;
				component3.overrideAnimatorForwardTransform = null;
				component3.rootMotionAccumulator = null;
				component3.modelAnimator = componentInChildren;
				component3.driveFromRootRotation = false;
				component3.turnSpeed = 720f;
			}
			ConfigureCameraAndAim(BodyPrefab, component);
			ConfigureCameraDistance(BodyPrefab);
			ConfigureCharacterModel(val2, component);
			ConfigurePolearmHitBoxes(val3);
			BodyPrefab.AddComponent<AVAnimationDriver>();
			BodyPrefab.AddComponent<AVLifecycle>();
			CharacterDeathBehavior component4 = BodyPrefab.GetComponent<CharacterDeathBehavior>();
			if ((Object)(object)component4 != (Object)null)
			{
				component4.deathState = new SerializableEntityStateType(typeof(AVDeathState));
				AVContent.AddEntityState(typeof(AVDeathState));
			}
			Sprite val4 = AVIcons.Get("Portrait");
			if ((Object)(object)val4 != (Object)null)
			{
				component.portraitIcon = (Texture)(object)val4.texture;
			}
			component.baseNameToken = "ABSOLUTE_VIRTUE_NAME";
			component.subtitleNameToken = "ABSOLUTE_VIRTUE_SUBTITLE";
			component.baseMaxHealth = 500f;
			component.levelMaxHealth = 210f;
			component.baseRegen = 5f;
			component.levelRegen = 0.5f;
			component.baseDamage = 16f;
			component.levelDamage = 2.5f;
			component.baseMoveSpeed = 10.5f;
			component.baseAttackSpeed = 1.5f;
			component.baseAcceleration = 80f;
			component.baseJumpPower = 15f;
			component.baseArmor = 20f;
			component.baseCrit = 5f;
			if (!CreateDisplayPrefab(visualPrefab))
			{
				return false;
			}
			Transform obj = DisplayPrefab.transform.Find("AbsoluteVirtueDisplayRoot");
			ConfigureSkins(val2, (obj != null) ? ((Component)obj).gameObject : null);
			AVContent.AddBody(BodyPrefab);
			Debug.Log((object)"[AbsoluteVirtue] Body created with explicit locomotion animation, Henry-style CharacterDirection, and farther camera.");
			return true;
		}

		private static void ConfigureHurtBox(Transform modelRoot, Transform vanillaModel, CharacterBody body)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)vanillaModel != (Object)null)
			{
				HurtBox[] componentsInChildren = ((Component)vanillaModel).GetComponentsInChildren<HurtBox>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					((Component)componentsInChildren[i]).gameObject.SetActive(false);
				}
				HurtBoxGroup[] componentsInChildren2 = ((Component)vanillaModel).GetComponentsInChildren<HurtBoxGroup>(

plugins\AbsoluteVirtueSurvivor\XiVfx.Bridge.Runtime.dll

Decompiled 9 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;
using XiVfx.Format;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("XiVfx.Bridge.Runtime")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("XiVfx.Bridge.Runtime")]
[assembly: AssemblyTitle("XiVfx.Bridge.Runtime")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace XiVfx.Unity
{
	[Serializable]
	public sealed class XiVfxManifest
	{
		public int schemaVersion;

		public string exporter;

		public string exportedAtUtc;

		public string sourceFileName;

		public long sourceLength;

		public string sourceSha256;

		public int effectScore;

		public bool containsVfx;

		public bool containsSfx;

		public bool containsZone;

		public string zoneDecodeTablesSha256;

		public XiDatSection[] sections;

		public XiAudioDependency[] audioDependencies;

		public XiDatDependency[] datDependencies;

		public XiSpellEffectDependency[] spellEffectDependencies;

		public XiZoneSubAreaDependency[] zoneSubAreaDependencies;
	}
	[Serializable]
	public sealed class XiSpellEffectDependency
	{
		public int spellIndex;

		public int fileTableId;

		public int sourceDatIndex;

		public string sourceRelativePath;

		public string routineId;

		public string routineDirectoryPath;
	}
	[Serializable]
	public sealed class XiZoneSubAreaDependency
	{
		public uint subAreaId;

		public int fileTableId;

		public int sourceDatIndex;

		public string sourceRelativePath;
	}
	[Serializable]
	public sealed class XiDatDependency
	{
		public string sourceRelativePath;

		public long sourceLength;

		public string sourceSha256;

		public XiDatSection[] sections;

		public int effectScore;

		public bool containsVfx;

		public bool containsSfx;
	}
	[Serializable]
	public sealed class XiDatDependencyBinding
	{
		public int dependencyIndex;

		public string sourceRelativePath;

		public long sourceLength;

		public string sourceSha256;

		[HideInInspector]
		public byte[] rawDat;
	}
	[Serializable]
	public sealed class XiAudioDependency
	{
		public string pointerSectionId;

		public string directoryPath;

		public long pointerSectionOffset;

		public int soundId;

		public string sourceRelativePath;

		public bool embedded;

		public bool decoded;

		public string blockReason;

		public long rawLength;

		public string rawSha256;

		public int codec;

		public int sampleRate;

		public int channels;

		public int sampleFrames;

		public int loopStartSample;

		public int loopEndSample;

		public string pcm16Sha256;

		public int sourceDatIndex;

		public int sepTagByte;
	}
	[Serializable]
	public sealed class XiDatSection
	{
		public string id;

		public string idHex;

		public byte typeCode;

		public string typeName;

		public long offset;

		public int size;

		public uint rawMetadata;

		public string directoryPath;
	}
	[Serializable]
	public sealed class XiTextureBinding
	{
		public int sourceDatIndex;

		public string sectionId;

		public string directoryPath;

		public long sectionOffset;

		public string sourceName;

		public XiTextureEncoding sourceEncoding;

		public Texture2D texture;
	}
	[Serializable]
	public sealed class XiKeyFrameBinding
	{
		public int sourceDatIndex;

		public string sectionId;

		public string directoryPath;

		public long sectionOffset;

		public XiKeyFrameEntry[] entries;
	}
	[Serializable]
	public sealed class XiEnvironmentBinding
	{
		public int sourceDatIndex;

		public string sectionId;

		public string directoryPath;

		public long sectionOffset;

		public bool activationTimeValid;

		public int activationHour;

		public int activationMinute;

		public int activationNativeTicks;

		public XiWeatherConditionData condition;
	}
	[Serializable]
	public sealed class XiPointListBinding
	{
		public int sourceDatIndex;

		public string sectionId;

		public string directoryPath;

		public long sectionOffset;

		public XiPointListData pointList;
	}
	[Serializable]
	public sealed class XiRouteBinding
	{
		public int sourceDatIndex;

		public string sectionId;

		public string directoryPath;

		public long sectionOffset;

		public XiRouteData route;
	}
	[Serializable]
	public sealed class XiSkeletonAnimationBinding
	{
		public int sourceDatIndex;

		public string sectionId;

		public string directoryPath;

		public long sectionOffset;

		public XiSkeletonAnimationData animation;
	}
	[Serializable]
	public sealed class XiSkeletonBinding
	{
		public int sourceDatIndex;

		public string sectionId;

		public string directoryPath;

		public long sectionOffset;

		public XiSkeletonData skeleton;
	}
	[Serializable]
	public sealed class XiSkeletonMeshBinding
	{
		public int sourceDatIndex;

		public string sectionId;

		public string directoryPath;

		public long sectionOffset;

		public XiSkeletonMeshData mesh;
	}
	[Serializable]
	public sealed class XiParticleSubMeshBinding
	{
		public string textureName;

		public Mesh mesh;
	}
	[Serializable]
	public sealed class XiParticleMeshBinding
	{
		public string sectionId;

		public string directoryPath;

		public long sectionOffset;

		public int sourceVersion;

		public int declaredTriangleCount;

		public int nativeDrawRadius;

		public XiParticleSubMeshBinding[] subMeshes;
	}
	[Serializable]
	public sealed class XiSpriteSheetFrameBinding
	{
		public ushort unknownValue;

		public byte quadCount;

		public byte unknownByte;

		public uint[] rawLensFlareWords;

		public Mesh mesh;
	}
	[Serializable]
	public sealed class XiSpriteSheetBinding
	{
		public string sectionId;

		public string directoryPath;

		public long sectionOffset;

		public ushort unknownFlags;

		public byte lensFlareFlag;

		public byte unknownByte0;

		public byte unknownByte1;

		public byte normalizationFlag;

		public bool usesUnnormalizedTextureCoordinates;

		public string textureName;

		public byte[] trailingPadding;

		public XiSpriteSheetFrameBinding[] frames;
	}
	[Serializable]
	public sealed class XiWeightedMeshChunkBinding
	{
		public float[] positions;

		public float[] normals;

		public uint[] rawPackedNormals;
	}
	[Serializable]
	public sealed class XiWeightedMeshBinding
	{
		public string sectionId;

		public string directoryPath;

		public long sectionOffset;

		public ushort unknownValue;

		public byte meshConfiguration;

		public byte offsetExtension;

		public ushort positionCount;

		public ushort normalCount;

		public ushort rawIndexOffset;

		public ushort primitiveCount;

		public ushort rawColorOffset;

		public ushort rawUvOffset;

		public bool alphaDiscardEnabled;

		public int weightCount;

		public int colorScale;

		public string textureName;

		public XiWeightedMeshChunkBinding[] chunks;

		public byte[] rawBgraColors;

		public byte[] rgbaColors;

		public float[] textureCoordinates;

		public ushort[] positionIndices;

		public ushort[] normalIndices;
	}
	[Serializable]
	public sealed class XiParticleGeneratorBinding
	{
		public int sourceDatIndex;

		public string sectionId;

		public string directoryPath;

		public long sectionOffset;

		public XiParticleGeneratorProgram program;
	}
	[Serializable]
	public sealed class XiEffectRoutineBinding
	{
		public int sourceDatIndex;

		public string sectionId;

		public string directoryPath;

		public long sectionOffset;

		public XiEffectRoutineProgram program;
	}
	[Serializable]
	public sealed class XiSoundBinding
	{
		public string pointerSectionId;

		public string directoryPath;

		public long pointerSectionOffset;

		public int sepTagByte;

		public bool scheduleActivationTimeValid;

		public int scheduleActivationHour;

		public int scheduleActivationMinute;

		public int scheduleActivationNativeTicks;

		public int soundId;

		public string sourceRelativePath;

		public string rawSha256;

		public string pcm16Sha256;

		public int codec;

		public int sampleRate;

		public int channels;

		public int sampleFrames;

		public int loopStartSample;

		public int loopEndSample;

		public int sourceDatIndex;

		[HideInInspector]
		public byte[] rawSpw;

		[NonSerialized]
		public AudioClip clip;

		public AudioClip GetOrCreateClip()
		{
			if (!TryGetOrCreateClip(out var resolved, out var _))
			{
				return null;
			}
			return resolved;
		}

		public bool TryGetOrCreateClip(out AudioClip resolved, out string reason)
		{
			if ((Object)(object)clip != (Object)null)
			{
				resolved = clip;
				reason = string.Empty;
				return true;
			}
			if (rawSpw == null || rawSpw.Length == 0)
			{
				resolved = null;
				reason = "The embedded SPW payload is absent.";
				return false;
			}
			try
			{
				XiSpwData xiSpwData = XiSpwDecoder.Decode(rawSpw);
				if (xiSpwData.SoundId != soundId || xiSpwData.Codec != codec || xiSpwData.SampleRate != sampleRate || xiSpwData.Channels != channels || xiSpwData.SampleFrames != sampleFrames || xiSpwData.LoopStartSample != loopStartSample || xiSpwData.LoopEndSample != loopEndSample)
				{
					resolved = null;
					reason = "The persisted SPW metadata no longer matches its verified import record.";
					return false;
				}
				AudioClip val = AudioClip.Create($"se{xiSpwData.SoundId:000000}", xiSpwData.SampleFrames, xiSpwData.Channels, xiSpwData.SampleRate, false);
				((Object)val).hideFlags = (HideFlags)61;
				float[] array = new float[xiSpwData.Samples.Length];
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (float)xiSpwData.Samples[i] / 32768f;
				}
				if (!val.SetData(array, 0))
				{
					Object.DestroyImmediate((Object)(object)val);
					resolved = null;
					reason = "Unity rejected the exact decoded PCM samples.";
					return false;
				}
				clip = val;
				resolved = val;
				reason = string.Empty;
				return true;
			}
			catch (Exception ex)
			{
				resolved = null;
				reason = ex.Message;
				return false;
			}
		}
	}
	public sealed class XiEffectAsset : ScriptableObject
	{
		[SerializeField]
		private XiVfxManifest manifest;

		[SerializeField]
		[HideInInspector]
		private byte[] sourceDat;

		[SerializeField]
		[TextArea(4, 12)]
		private string manifestJson;

		[SerializeField]
		private XiTextureBinding[] textures;

		[SerializeField]
		private XiKeyFrameBinding[] keyFrames;

		[SerializeField]
		private XiPointListBinding[] pointLists;

		[SerializeField]
		private XiRouteBinding[] routes;

		[SerializeField]
		private XiSkeletonAnimationBinding[] skeletonAnimations;

		[SerializeField]
		private XiSkeletonBinding[] skeletons;

		[SerializeField]
		private XiSkeletonMeshBinding[] skeletonMeshes;

		[SerializeField]
		private XiParticleMeshBinding[] particleMeshes;

		[SerializeField]
		private XiSpriteSheetBinding[] spriteSheets;

		[SerializeField]
		private XiWeightedMeshBinding[] weightedMeshes;

		[SerializeField]
		private XiParticleGeneratorBinding[] particleGenerators;

		[SerializeField]
		private XiEffectRoutineBinding[] effectRoutines;

		[SerializeField]
		private XiSoundBinding[] sounds;

		[SerializeField]
		private XiEnvironmentBinding[] environments;

		[SerializeField]
		private XiZoneReceiverAsset[] zoneReceivers;

		[SerializeField]
		private XiDatDependencyBinding[] datDependencies;

		[SerializeField]
		[HideInInspector]
		private byte[] zoneFirstDecodeTable;

		[SerializeField]
		[HideInInspector]
		private byte[] zoneSecondDecodeTable;

		public XiVfxManifest Manifest => manifest;

		public byte[] SourceDat => sourceDat;

		public string ManifestJson => manifestJson;

		public XiTextureBinding[] Textures => textures;

		public XiKeyFrameBinding[] KeyFrames => keyFrames;

		public XiPointListBinding[] PointLists => pointLists;

		public XiRouteBinding[] Routes => routes;

		public XiSkeletonAnimationBinding[] SkeletonAnimations => skeletonAnimations;

		public XiSkeletonBinding[] Skeletons => skeletons;

		public XiSkeletonMeshBinding[] SkeletonMeshes => skeletonMeshes;

		public XiParticleMeshBinding[] ParticleMeshes => particleMeshes;

		public XiSpriteSheetBinding[] SpriteSheets => spriteSheets;

		public XiWeightedMeshBinding[] WeightedMeshes => weightedMeshes;

		public XiParticleGeneratorBinding[] ParticleGenerators => particleGenerators;

		public XiEffectRoutineBinding[] EffectRoutines => effectRoutines;

		public XiSoundBinding[] Sounds => sounds;

		public XiEnvironmentBinding[] Environments => environments;

		public XiZoneReceiverAsset[] ZoneReceivers => zoneReceivers;

		public XiDatDependencyBinding[] DatDependencies => datDependencies;

		public byte[] ZoneFirstDecodeTable => zoneFirstDecodeTable;

		public byte[] ZoneSecondDecodeTable => zoneSecondDecodeTable;

		public bool TrySampleEnvironmentSchedule(int sourceDatIndex, string directoryPath, int currentNativeTicks, out XiWeatherScheduleSampleData sample, out string reason)
		{
			sample = null;
			if (string.IsNullOrEmpty(directoryPath))
			{
				reason = "The environment schedule directory is absent.";
				return false;
			}
			List<XiWeatherConditionData> list = new List<XiWeatherConditionData>();
			List<int> list2 = new List<int>();
			XiEnvironmentBinding[] array = environments ?? Array.Empty<XiEnvironmentBinding>();
			foreach (XiEnvironmentBinding xiEnvironmentBinding in array)
			{
				if (xiEnvironmentBinding != null && xiEnvironmentBinding.sourceDatIndex == sourceDatIndex && string.Equals(xiEnvironmentBinding.directoryPath, directoryPath, StringComparison.Ordinal))
				{
					if (!xiEnvironmentBinding.activationTimeValid)
					{
						reason = "Environment resource " + xiEnvironmentBinding.sectionId + " has no confirmed native HHMM activation time.";
						return false;
					}
					if (xiEnvironmentBinding.condition == null || xiEnvironmentBinding.condition.SourceSectionSize != 192 || !xiEnvironmentBinding.condition.HasExtendedWorldParameters)
					{
						reason = "Environment resource " + xiEnvironmentBinding.sectionId + " uses a layout whose interpolation is not confirmed.";
						return false;
					}
					list.Add(xiEnvironmentBinding.condition);
					list2.Add(xiEnvironmentBinding.activationNativeTicks);
				}
			}
			if (list.Count == 0)
			{
				reason = $"No environment schedule exists in source DAT {sourceDatIndex} at {directoryPath}.";
				return false;
			}
			try
			{
				sample = XiWeatherScheduleEvaluator.Evaluate(list.ToArray(), list2.ToArray(), currentNativeTicks);
				reason = string.Empty;
				return true;
			}
			catch (Exception ex)
			{
				sample = null;
				reason = ex.Message;
				return false;
			}
		}

		public bool TryResolveAndSampleWeatherSchedule(int sourceDatIndex, string areaDirectoryPath, uint weatherFourCC, int currentNativeTicks, out XiWeatherContainerResolutionData resolution, out XiWeatherScheduleSampleData sample, out string reason)
		{
			resolution = null;
			sample = null;
			if (!TryResolveWeatherContainer(sourceDatIndex, areaDirectoryPath, weatherFourCC, out resolution, out reason))
			{
				return false;
			}
			if (TrySampleEnvironmentSchedule(sourceDatIndex, resolution.ScheduleDirectoryPath, currentNativeTicks, out sample, out reason))
			{
				return true;
			}
			resolution = null;
			sample = null;
			return false;
		}

		public bool TryResolveAndBuildWeatherSceneState(int sourceDatIndex, string areaDirectoryPath, uint weatherFourCC, XiWeatherSceneInputData input, out XiWeatherContainerResolutionData resolution, out XiWeatherScheduleSampleData sample, out XiWeatherSceneStateData state, out string reason)
		{
			state = null;
			if (!TryResolveAndSampleWeatherSchedule(sourceDatIndex, areaDirectoryPath, weatherFourCC, input?.NativeTimeTicks ?? (-1), out resolution, out sample, out reason))
			{
				return false;
			}
			XiWeatherSceneStateEvaluator xiWeatherSceneStateEvaluator = new XiWeatherSceneStateEvaluator();
			if (!xiWeatherSceneStateEvaluator.TryApplyWeatherCondition(sample.Condition, preserveEnvironment1Primary: false, out reason) || !xiWeatherSceneStateEvaluator.TryMoveLightState(input, out reason) || !xiWeatherSceneStateEvaluator.TrySnapshot(input, out state, out reason))
			{
				resolution = null;
				sample = null;
				state = null;
				return false;
			}
			reason = string.Empty;
			return true;
		}

		public bool TryResolveWeatherContainer(int sourceDatIndex, string areaDirectoryPath, uint weatherFourCC, out XiWeatherContainerResolutionData resolution, out string reason)
		{
			resolution = null;
			if (!TryGetSourceSections(sourceDatIndex, out var sections, out reason))
			{
				return false;
			}
			List<XiWeatherContainerDirectoryData> list = new List<XiWeatherContainerDirectoryData>();
			XiDatSection[] array = sections;
			foreach (XiDatSection xiDatSection in array)
			{
				if (xiDatSection != null && xiDatSection.typeCode == 1)
				{
					list.Add(new XiWeatherContainerDirectoryData
					{
						SourceDatIndex = sourceDatIndex,
						Id = (xiDatSection.id ?? string.Empty),
						ParentDirectoryPath = (xiDatSection.directoryPath ?? string.Empty),
						SectionOffset = xiDatSection.offset
					});
				}
			}
			return XiWeatherContainerResolver.TryResolve(list.ToArray(), sourceDatIndex, areaDirectoryPath, weatherFourCC, out resolution, out reason);
		}

		public bool TryBuildWeatherLifecyclePlan(int sourceDatIndex, string areaDirectoryPath, uint weatherFourCC, int placeCode, out XiWeatherContainerResolutionData resolution, out XiWeatherLifecyclePlanData plan, out string reason)
		{
			plan = null;
			if (!TryResolveWeatherContainer(sourceDatIndex, areaDirectoryPath, weatherFourCC, out resolution, out reason))
			{
				return false;
			}
			List<XiWeatherGeneratorResourceData> list = new List<XiWeatherGeneratorResourceData>();
			XiParticleGeneratorBinding[] array = particleGenerators ?? Array.Empty<XiParticleGeneratorBinding>();
			foreach (XiParticleGeneratorBinding xiParticleGeneratorBinding in array)
			{
				if (xiParticleGeneratorBinding != null)
				{
					list.Add(new XiWeatherGeneratorResourceData
					{
						SourceDatIndex = xiParticleGeneratorBinding.sourceDatIndex,
						SectionId = (xiParticleGeneratorBinding.sectionId ?? string.Empty),
						DirectoryPath = (xiParticleGeneratorBinding.directoryPath ?? string.Empty),
						SectionOffset = xiParticleGeneratorBinding.sectionOffset,
						Program = xiParticleGeneratorBinding.program
					});
				}
			}
			List<XiWeatherSchedulerResourceData> list2 = new List<XiWeatherSchedulerResourceData>();
			XiEffectRoutineBinding[] array2 = effectRoutines ?? Array.Empty<XiEffectRoutineBinding>();
			foreach (XiEffectRoutineBinding xiEffectRoutineBinding in array2)
			{
				if (xiEffectRoutineBinding != null)
				{
					list2.Add(new XiWeatherSchedulerResourceData
					{
						SourceDatIndex = xiEffectRoutineBinding.sourceDatIndex,
						SectionId = (xiEffectRoutineBinding.sectionId ?? string.Empty),
						DirectoryPath = (xiEffectRoutineBinding.directoryPath ?? string.Empty),
						SectionOffset = xiEffectRoutineBinding.sectionOffset,
						Program = xiEffectRoutineBinding.program
					});
				}
			}
			if (XiWeatherLifecyclePlanner.TryBuild(resolution, placeCode, list.ToArray(), list2.ToArray(), out plan, out reason))
			{
				return true;
			}
			resolution = null;
			plan = null;
			return false;
		}

		public bool TrySelectWeatherSoundSchedule(int sourceDatIndex, string areaDirectoryPath, uint weatherFourCC, int placeCode, int currentNativeTicks, out XiWeatherContainerResolutionData resolution, out XiWeatherSoundSelectionData selection, out string reason)
		{
			selection = null;
			if (!TryResolveWeatherContainer(sourceDatIndex, areaDirectoryPath, weatherFourCC, out resolution, out reason))
			{
				return false;
			}
			if (!TryGetSourceSections(sourceDatIndex, out var sections, out reason))
			{
				resolution = null;
				return false;
			}
			List<XiWeatherContainerDirectoryData> list = new List<XiWeatherContainerDirectoryData>();
			HashSet<long> hashSet = new HashSet<long>();
			XiDatSection[] array = sections;
			foreach (XiDatSection xiDatSection in array)
			{
				if (xiDatSection != null)
				{
					if (xiDatSection.typeCode == 1)
					{
						list.Add(new XiWeatherContainerDirectoryData
						{
							SourceDatIndex = sourceDatIndex,
							Id = (xiDatSection.id ?? string.Empty),
							ParentDirectoryPath = (xiDatSection.directoryPath ?? string.Empty),
							SectionOffset = xiDatSection.offset
						});
					}
					else if (xiDatSection.typeCode == 61 && IsWithinDirectory(xiDatSection.directoryPath, resolution.ScheduleDirectoryPath))
					{
						hashSet.Add(xiDatSection.offset);
					}
				}
			}
			List<XiWeatherSoundResourceData> list2 = new List<XiWeatherSoundResourceData>();
			XiSoundBinding[] array2 = sounds ?? Array.Empty<XiSoundBinding>();
			foreach (XiSoundBinding xiSoundBinding in array2)
			{
				if (xiSoundBinding != null && xiSoundBinding.sourceDatIndex == sourceDatIndex && IsWithinDirectory(xiSoundBinding.directoryPath, resolution.ScheduleDirectoryPath))
				{
					hashSet.Remove(xiSoundBinding.pointerSectionOffset);
					list2.Add(new XiWeatherSoundResourceData
					{
						SourceDatIndex = xiSoundBinding.sourceDatIndex,
						SectionId = (xiSoundBinding.pointerSectionId ?? string.Empty),
						DirectoryPath = (xiSoundBinding.directoryPath ?? string.Empty),
						SectionOffset = xiSoundBinding.pointerSectionOffset,
						SoundId = xiSoundBinding.soundId
					});
				}
			}
			if (hashSet.Count != 0)
			{
				reason = "Weather container " + resolution.ScheduleDirectoryPath + " contains " + $"{hashSet.Count} sound pointer(s) whose native payload is not decoded.";
				resolution = null;
				return false;
			}
			if (XiWeatherSoundScheduleEvaluator.TrySelect(resolution, placeCode, currentNativeTicks, list.ToArray(), list2.ToArray(), out selection, out reason))
			{
				return true;
			}
			resolution = null;
			selection = null;
			return false;
		}

		public bool TryBuildWeatherTransitionDefinition(int sourceDatIndex, string areaDirectoryPath, uint weatherFourCC, int placeCode, out XiWeatherTransitionDefinitionData definition, out string reason)
		{
			definition = null;
			if (!TryBuildWeatherLifecyclePlan(sourceDatIndex, areaDirectoryPath, weatherFourCC, placeCode, out var resolution, out var plan, out reason))
			{
				return false;
			}
			if (!TryGetSourceSections(sourceDatIndex, out var sections, out reason))
			{
				return false;
			}
			List<XiWeatherConditionData> list = new List<XiWeatherConditionData>();
			List<int> list2 = new List<int>();
			XiEnvironmentBinding[] array = environments ?? Array.Empty<XiEnvironmentBinding>();
			foreach (XiEnvironmentBinding xiEnvironmentBinding in array)
			{
				if (xiEnvironmentBinding != null && xiEnvironmentBinding.sourceDatIndex == sourceDatIndex && string.Equals(xiEnvironmentBinding.directoryPath, resolution.ScheduleDirectoryPath, StringComparison.Ordinal))
				{
					if (!xiEnvironmentBinding.activationTimeValid)
					{
						reason = "Environment resource " + xiEnvironmentBinding.sectionId + " has no confirmed native HHMM activation time.";
						return false;
					}
					if (xiEnvironmentBinding.condition == null || xiEnvironmentBinding.condition.SourceSectionSize != 192 || !xiEnvironmentBinding.condition.HasExtendedWorldParameters)
					{
						reason = "Environment resource " + xiEnvironmentBinding.sectionId + " uses a layout whose transition interpolation is not confirmed.";
						return false;
					}
					list.Add(xiEnvironmentBinding.condition);
					list2.Add(xiEnvironmentBinding.activationNativeTicks);
				}
			}
			if (list.Count == 0)
			{
				reason = "No confirmed current-layout environment schedule exists at " + resolution.ScheduleDirectoryPath + ".";
				return false;
			}
			List<XiWeatherContainerDirectoryData> list3 = new List<XiWeatherContainerDirectoryData>();
			HashSet<long> hashSet = new HashSet<long>();
			XiDatSection[] array2 = sections;
			foreach (XiDatSection xiDatSection in array2)
			{
				if (xiDatSection != null)
				{
					if (xiDatSection.typeCode == 1)
					{
						list3.Add(new XiWeatherContainerDirectoryData
						{
							SourceDatIndex = sourceDatIndex,
							Id = (xiDatSection.id ?? string.Empty),
							ParentDirectoryPath = (xiDatSection.directoryPath ?? string.Empty),
							SectionOffset = xiDatSection.offset
						});
					}
					else if (xiDatSection.typeCode == 61 && IsWithinDirectory(xiDatSection.directoryPath, resolution.ScheduleDirectoryPath))
					{
						hashSet.Add(xiDatSection.offset);
					}
				}
			}
			List<XiWeatherSoundResourceData> list4 = new List<XiWeatherSoundResourceData>();
			XiSoundBinding[] array3 = sounds ?? Array.Empty<XiSoundBinding>();
			foreach (XiSoundBinding xiSoundBinding in array3)
			{
				if (xiSoundBinding != null && xiSoundBinding.sourceDatIndex == sourceDatIndex && IsWithinDirectory(xiSoundBinding.directoryPath, resolution.ScheduleDirectoryPath))
				{
					hashSet.Remove(xiSoundBinding.pointerSectionOffset);
					list4.Add(new XiWeatherSoundResourceData
					{
						SourceDatIndex = xiSoundBinding.sourceDatIndex,
						SectionId = (xiSoundBinding.pointerSectionId ?? string.Empty),
						DirectoryPath = (xiSoundBinding.directoryPath ?? string.Empty),
						SectionOffset = xiSoundBinding.pointerSectionOffset,
						SoundId = xiSoundBinding.soundId
					});
				}
			}
			if (hashSet.Count != 0)
			{
				reason = "Weather container " + resolution.ScheduleDirectoryPath + " contains " + $"{hashSet.Count} sound pointer(s) whose native payload is not decoded.";
				return false;
			}
			XiWeatherTransitionDefinitionData xiWeatherTransitionDefinitionData = new XiWeatherTransitionDefinitionData
			{
				Resolution = resolution,
				LifecyclePlan = plan,
				ScheduleConditions = list.ToArray(),
				ScheduleActivationNativeTicks = list2.ToArray(),
				Directories = list3.ToArray(),
				Sounds = list4.ToArray()
			};
			if (!XiWeatherTransitionController.TryValidateDefinition(xiWeatherTransitionDefinitionData, out reason))
			{
				return false;
			}
			definition = xiWeatherTransitionDefinitionData;
			reason = string.Empty;
			return true;
		}

		private static bool IsWithinDirectory(string path, string container)
		{
			path = (path ?? string.Empty).Replace('\\', '/').Trim('/');
			container = (container ?? string.Empty).Replace('\\', '/').Trim('/');
			if (!string.Equals(path, container, StringComparison.Ordinal))
			{
				return path.StartsWith(container + "/", StringComparison.Ordinal);
			}
			return true;
		}

		private bool TryGetSourceSections(int sourceDatIndex, out XiDatSection[] sections, out string reason)
		{
			sections = null;
			if (manifest == null)
			{
				reason = "The XiVFX manifest is absent.";
				return false;
			}
			if (sourceDatIndex == 0)
			{
				sections = manifest.sections ?? Array.Empty<XiDatSection>();
				reason = string.Empty;
				return true;
			}
			XiDatDependency[] array = manifest.datDependencies ?? Array.Empty<XiDatDependency>();
			if (sourceDatIndex < 1 || sourceDatIndex > array.Length || array[sourceDatIndex - 1] == null)
			{
				reason = $"Source DAT index {sourceDatIndex} is not present in this XiVFX package.";
				return false;
			}
			sections = array[sourceDatIndex - 1].sections ?? Array.Empty<XiDatSection>();
			reason = string.Empty;
			return true;
		}
	}
	[DisallowMultipleComponent]
	[RequireComponent(typeof(XiParticleRenderer))]
	public sealed class XiEffectPlayer : MonoBehaviour
	{
		[SerializeField]
		private XiEffectAsset effect;

		[SerializeField]
		private bool playOnEnable = true;

		[SerializeField]
		private string entryId = "main";

		[SerializeField]
		private string entryDirectory;

		[SerializeField]
		private bool entryIsGenerator;

		[SerializeField]
		[Min(0f)]
		private int directGeneratorDurationFrames;

		[SerializeField]
		private uint deterministicRandomSeed;

		[SerializeField]
		[Range(0f, 24f)]
		private float ffxiTimeOfDayHours;

		[SerializeField]
		[Tooltip("Confirms the Vana'diel calendar day used by weekday and moon-phase particle colors.")]
		private bool vanaDateConfirmed;

		[SerializeField]
		[Range(0f, 359f)]
		[Tooltip("Zero-based day in FFXI's 360-day Vana'diel year.")]
		private int vanaDayOfYear;

		[SerializeField]
		[Range(0f, 1f)]
		private float associatedVisibility = 1f;

		[SerializeField]
		[Tooltip("Enable only when this player is launched with FFXI's native zone association. A zone receiver parent is also required.")]
		private bool zoneAssociatedPlayback;

		[SerializeField]
		[Tooltip("FFXI player position used by generator emission-distance gates. Defaults to Main Camera for standalone preview.")]
		private Transform ffxiPlayerRoot;

		[SerializeField]
		[Tooltip("FFXI camera used by particle draw-distance behavior. Defaults to the renderer Target Camera, then Main Camera.")]
		private Transform ffxiDrawObserverRoot;

		[SerializeField]
		[Tooltip("Confirms the external FFXI zone draw distance used when generator opcode s1:0x0A authors maximum distance zero.")]
		private bool ffxiZoneDrawDistanceConfirmed;

		[SerializeField]
		[Min(0f)]
		[Tooltip("Current native zone draw distance. A confirmed parent zone receiver overrides this value.")]
		private float ffxiZoneDrawDistance;

		[SerializeField]
		[Tooltip("FFXI camera orientation used by explicit stereo sound panning. Defaults to the Main Camera.")]
		private Transform ffxiAudioCameraRoot;

		private XiSemanticRuntime runtime;

		private float accumulatedSeconds;

		private int consumedSoundEvents;

		private int consumedRuntimeWarnings;

		private readonly List<GameObject> activeSoundObjects = new List<GameObject>();

		private readonly Dictionary<XiSoundEvent, GameObject> particleSoundObjects = new Dictionary<XiSoundEvent, GameObject>();

		private readonly Dictionary<XiSoundEvent, GameObject> routineSoundObjects = new Dictionary<XiSoundEvent, GameObject>();

		public XiEffectAsset Effect
		{
			get
			{
				return effect;
			}
			set
			{
				effect = value;
			}
		}

		public XiSemanticRuntime Runtime => runtime;

		public string EntryId
		{
			get
			{
				return entryId;
			}
			set
			{
				entryId = value;
			}
		}

		public string EntryDirectory
		{
			get
			{
				return entryDirectory;
			}
			set
			{
				entryDirectory = value;
			}
		}

		public bool EntryIsGenerator
		{
			get
			{
				return entryIsGenerator;
			}
			set
			{
				entryIsGenerator = value;
			}
		}

		public int DirectGeneratorDurationFrames
		{
			get
			{
				return directGeneratorDurationFrames;
			}
			set
			{
				directGeneratorDurationFrames = Mathf.Max(0, value);
			}
		}

		public uint DeterministicRandomSeed
		{
			get
			{
				return deterministicRandomSeed;
			}
			set
			{
				deterministicRandomSeed = value;
			}
		}

		public float FfxiTimeOfDayHours
		{
			get
			{
				return ffxiTimeOfDayHours;
			}
			set
			{
				ffxiTimeOfDayHours = Mathf.Clamp(value, 0f, 24f);
			}
		}

		public bool VanaDateConfirmed
		{
			get
			{
				return vanaDateConfirmed;
			}
			set
			{
				vanaDateConfirmed = value;
			}
		}

		public int VanaDayOfYear
		{
			get
			{
				return vanaDayOfYear;
			}
			set
			{
				vanaDayOfYear = Mathf.Clamp(value, 0, 359);
			}
		}

		public float AssociatedVisibility
		{
			get
			{
				return associatedVisibility;
			}
			set
			{
				associatedVisibility = Mathf.Clamp01(value);
			}
		}

		public bool ZoneAssociatedPlayback
		{
			get
			{
				return zoneAssociatedPlayback;
			}
			set
			{
				zoneAssociatedPlayback = value;
			}
		}

		public Transform FfxiPlayerRoot
		{
			get
			{
				return ffxiPlayerRoot;
			}
			set
			{
				ffxiPlayerRoot = value;
			}
		}

		public Transform FfxiDrawObserverRoot
		{
			get
			{
				return ffxiDrawObserverRoot;
			}
			set
			{
				ffxiDrawObserverRoot = value;
			}
		}

		public bool FfxiZoneDrawDistanceConfirmed
		{
			get
			{
				return ffxiZoneDrawDistanceConfirmed;
			}
			set
			{
				ffxiZoneDrawDistanceConfirmed = value;
			}
		}

		public float FfxiZoneDrawDistance
		{
			get
			{
				return ffxiZoneDrawDistance;
			}
			set
			{
				ffxiZoneDrawDistance = value;
			}
		}

		public Transform FfxiAudioCameraRoot
		{
			get
			{
				return ffxiAudioCameraRoot;
			}
			set
			{
				ffxiAudioCameraRoot = value;
			}
		}

		private void OnEnable()
		{
			if (playOnEnable && (Object)(object)effect != (Object)null)
			{
				Play();
			}
		}

		private void Update()
		{
			if (runtime != null && !runtime.HasBlockingIssues)
			{
				accumulatedSeconds += Time.deltaTime;
				UpdateFfxiGeneratorCullContext();
				while (accumulatedSeconds >= 1f / 60f)
				{
					runtime.StepFrame();
					ConsumeSoundEvents();
					SynchronizeParticleSounds();
					SynchronizeRoutineSounds();
					ConsumeRuntimeWarnings();
					accumulatedSeconds -= 1f / 60f;
				}
				CleanupFinishedSounds();
			}
		}

		public void Play()
		{
			if ((Object)(object)effect == (Object)null)
			{
				Debug.LogWarning((object)"XiEffectPlayer has no XiEffectAsset assigned.", (Object)(object)this);
				return;
			}
			accumulatedSeconds = 0f;
			consumedSoundEvents = 0;
			consumedRuntimeWarnings = 0;
			DestroyActiveSounds();
			XiFfxiZoneReceiverRuntime componentInParent = ((Component)this).GetComponentInParent<XiFfxiZoneReceiverRuntime>();
			XiFfxiActorContext component = ((Component)this).GetComponent<XiFfxiActorContext>();
			if ((Object)(object)component != (Object)null)
			{
				component.ZoneReceiverRuntime = componentInParent;
			}
			runtime = new XiSemanticRuntime(effect, deterministicRandomSeed, ffxiTimeOfDayHours / 24f, associatedVisibility, component, requireAttachmentContext: true, ((Component)this).GetComponent<XiFfxiRoutineConditionContext>(), requireConditionContext: true, ((Component)this).GetComponent<XiFfxiActorCommandContext>(), requireActorCommandContext: true, componentInParent, requireZoneModelTransformContext: true, ((Object)(object)componentInParent != (Object)null) ? componentInParent.CreateFloorProjectionContext(((Component)this).transform) : null, ((Component)this).GetComponentInParent<XiFfxiEnvironmentLightingState>(), requireEnvironmentLightingContext: true, zoneAssociatedPlayback && (Object)(object)componentInParent != (Object)null, FindWeatherTransitionContext(), requireWeatherTransitionContext: true, vanaDayOfYear, vanaDateConfirmed);
			UpdateFfxiGeneratorCullContext();
			if (entryIsGenerator ? runtime.PlayGenerator(entryId, directGeneratorDurationFrames, entryDirectory) : runtime.PlayRoutine(entryId, entryDirectory))
			{
				return;
			}
			foreach (XiRuntimeIssue issue in runtime.Issues)
			{
				Debug.LogError((object)$"XiVFX fidelity block: {issue}", (Object)(object)this);
			}
		}

		public void Stop()
		{
			runtime = null;
			accumulatedSeconds = 0f;
			consumedSoundEvents = 0;
			consumedRuntimeWarnings = 0;
			DestroyActiveSounds();
		}

		private IXiFfxiWeatherTransitionContext FindWeatherTransitionContext()
		{
			MonoBehaviour[] componentsInParent = ((Component)this).GetComponentsInParent<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInParent)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)this && val is IXiFfxiWeatherTransitionContext result)
				{
					return result;
				}
			}
			return null;
		}

		public void StepOneFfxiFrame()
		{
			UpdateFfxiGeneratorCullContext();
			runtime?.StepFrame();
			ConsumeSoundEvents();
			SynchronizeParticleSounds();
			SynchronizeRoutineSounds();
			ConsumeRuntimeWarnings();
		}

		private void UpdateFfxiGeneratorCullContext()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			if (runtime == null)
			{
				return;
			}
			Transform transform = ffxiPlayerRoot;
			if ((Object)(object)transform == (Object)null && (Object)(object)Camera.main != (Object)null)
			{
				transform = ((Component)Camera.main).transform;
			}
			if ((Object)(object)transform == (Object)null)
			{
				runtime.FfxiPlayerSourcePosition = Vector3.zero;
			}
			else
			{
				Matrix4x4 worldToLocalMatrix = ((Component)this).transform.worldToLocalMatrix;
				Vector3 val = ((Matrix4x4)(ref worldToLocalMatrix)).MultiplyPoint3x4(transform.position);
				runtime.FfxiPlayerSourcePosition = new Vector3(val.z, val.y, val.x);
			}
			Transform transform2 = ffxiDrawObserverRoot;
			if ((Object)(object)transform2 == (Object)null)
			{
				XiParticleRenderer component = ((Component)this).GetComponent<XiParticleRenderer>();
				if ((Object)(object)component != (Object)null && (Object)(object)component.TargetCamera != (Object)null)
				{
					transform2 = ((Component)component.TargetCamera).transform;
				}
			}
			if ((Object)(object)transform2 == (Object)null && (Object)(object)Camera.main != (Object)null)
			{
				transform2 = ((Component)Camera.main).transform;
			}
			if ((Object)(object)transform2 == (Object)null)
			{
				runtime.FfxiEffectLocalToObserver = Matrix4x4.identity;
				runtime.FfxiDrawObserverConfirmed = false;
			}
			else
			{
				runtime.FfxiEffectLocalToObserver = transform2.worldToLocalMatrix * ((Component)this).transform.localToWorldMatrix;
				runtime.FfxiDrawObserverConfirmed = true;
			}
			XiFfxiZoneReceiverRuntime componentInParent = ((Component)this).GetComponentInParent<XiFfxiZoneReceiverRuntime>();
			if ((Object)(object)componentInParent != (Object)null && componentInParent.SourceStateConfirmed)
			{
				runtime.FfxiZoneDrawDistance = componentInParent.EnvironmentDrawDistance;
				runtime.FfxiZoneDrawDistanceConfirmed = true;
			}
			else
			{
				runtime.FfxiZoneDrawDistance = ffxiZoneDrawDistance;
				runtime.FfxiZoneDrawDistanceConfirmed = ffxiZoneDrawDistanceConfirmed && !float.IsNaN(ffxiZoneDrawDistance) && !float.IsInfinity(ffxiZoneDrawDistance) && ffxiZoneDrawDistance >= 0f;
			}
		}

		private void ConsumeSoundEvents()
		{
			if (runtime != null)
			{
				while (consumedSoundEvents < runtime.SoundEvents.Count)
				{
					PlaySound(runtime.SoundEvents[consumedSoundEvents++]);
				}
			}
		}

		private void ConsumeRuntimeWarnings()
		{
			if (runtime != null)
			{
				while (consumedRuntimeWarnings < runtime.Warnings.Count)
				{
					Debug.LogWarning((object)$"XiVFX runtime warning: {runtime.Warnings[consumedRuntimeWarnings++]}", (Object)(object)this);
				}
			}
		}

		private void PlaySound(XiSoundEvent soundEvent)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Expected O, but got Unknown
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Expected O, but got Unknown
			if (soundEvent == null || (Object)(object)soundEvent.Clip == (Object)null)
			{
				return;
			}
			GameObject val = new GameObject($"FFXI Sound {soundEvent.SoundId}");
			XiFfxiActorContext component = ((Component)this).GetComponent<XiFfxiActorContext>();
			Transform val2 = soundEvent.FollowRoot;
			if ((Object)(object)val2 == (Object)null && !soundEvent.IsParticleAudio && soundEvent.Target == XiSoundTarget.Target)
			{
				val2 = (((Object)(object)component != (Object)null) ? component.TargetActorRoot : null);
			}
			else if ((Object)(object)val2 == (Object)null && !soundEvent.IsParticleAudio && soundEvent.Target == XiSoundTarget.Source)
			{
				val2 = (((Object)(object)component != (Object)null) ? component.SourceActorRoot : null);
			}
			if ((Object)(object)val2 != (Object)null)
			{
				val.transform.SetParent(val2, false);
			}
			else
			{
				val.transform.SetParent(((Component)this).transform, false);
				val.transform.localPosition = soundEvent.LocalPosition;
			}
			AudioSource val3 = val.AddComponent<AudioSource>();
			val3.playOnAwake = false;
			val3.clip = soundEvent.Clip;
			val3.loop = false;
			val3.spatialBlend = 0f;
			val3.dopplerLevel = 0f;
			val3.rolloffMode = (AudioRolloffMode)2;
			if (soundEvent.IsParticleAudio || soundEvent.UseFlatRolloff)
			{
				val3.minDistance = 0.0001f;
				val3.maxDistance = 1000000f;
				val3.volume = soundEvent.VolumeMultiplier * soundEvent.FadeMultiplier;
				val3.SetCustomCurve((AudioSourceCurveType)0, new AnimationCurve((Keyframe[])(object)new Keyframe[2]
				{
					new Keyframe(0f, 1f),
					new Keyframe(1f, 1f)
				}));
			}
			else
			{
				val3.minDistance = Mathf.Max(0.0001f, soundEvent.NearDistance);
				val3.maxDistance = Mathf.Max(val3.minDistance, soundEvent.FarDistance);
				float num = Mathf.Clamp01(soundEvent.NearDistance / val3.maxDistance);
				if (num >= 1f)
				{
					num = 0.999999f;
				}
				val3.SetCustomCurve((AudioSourceCurveType)0, new AnimationCurve((Keyframe[])(object)new Keyframe[3]
				{
					new Keyframe(0f, 1f),
					new Keyframe(num, 1f),
					new Keyframe(1f, 0f)
				}));
			}
			val3.Play();
			activeSoundObjects.Add(val);
			if (soundEvent.IsParticleAudio)
			{
				particleSoundObjects[soundEvent] = val;
			}
			else
			{
				routineSoundObjects[soundEvent] = val;
			}
		}

		private void SynchronizeParticleSounds()
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			if (particleSoundObjects.Count == 0)
			{
				return;
			}
			foreach (KeyValuePair<XiSoundEvent, GameObject> item in new List<KeyValuePair<XiSoundEvent, GameObject>>(particleSoundObjects))
			{
				XiSoundEvent key = item.Key;
				GameObject value = item.Value;
				AudioSource val = (((Object)(object)value != (Object)null) ? value.GetComponent<AudioSource>() : null);
				if (key == null || (Object)(object)value == (Object)null || (Object)(object)val == (Object)null || key.IsComplete || key.StopRequested)
				{
					if ((Object)(object)val != (Object)null)
					{
						val.Stop();
					}
					DestroySoundObject(value);
					activeSoundObjects.Remove(value);
					particleSoundObjects.Remove(item.Key);
				}
				else
				{
					value.transform.localPosition = key.LocalPosition;
					val.volume = Mathf.Clamp01(key.VolumeMultiplier * key.FadeMultiplier);
					val.panStereo = ComputeFfxiPan(key, value);
					if (key.Looping && !key.StopLoopingRequested && key.LoopStartSample >= 0 && key.LoopEndSample > key.LoopStartSample && val.timeSamples >= key.LoopEndSample)
					{
						val.timeSamples = key.LoopStartSample;
					}
				}
			}
		}

		private void SynchronizeRoutineSounds()
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			if (routineSoundObjects.Count == 0)
			{
				return;
			}
			foreach (KeyValuePair<XiSoundEvent, GameObject> routineSoundObject in routineSoundObjects)
			{
				XiSoundEvent key = routineSoundObject.Key;
				GameObject value = routineSoundObject.Value;
				AudioSource val = (((Object)(object)value != (Object)null) ? value.GetComponent<AudioSource>() : null);
				if (key == null || (Object)(object)value == (Object)null || (Object)(object)val == (Object)null)
				{
					continue;
				}
				if ((Object)(object)value.transform.parent == (Object)(object)((Component)this).transform)
				{
					value.transform.localPosition = key.LocalPosition;
				}
				if (key.Target == XiSoundTarget.Global || key.Target == XiSoundTarget.PlayerOnly || !key.Spatialized)
				{
					val.volume = 1f;
				}
				else
				{
					Transform val2 = ResolveFfxiListenerTransform();
					float num;
					if (!((Object)(object)val2 == (Object)null))
					{
						num = Vector3.Distance(value.transform.position, val2.position);
					}
					else
					{
						Vector3 localPosition = value.transform.localPosition;
						num = ((Vector3)(ref localPosition)).magnitude;
					}
					float distance = num;
					val.volume = FfxiFalloff(distance, key.NearDistance, key.FarDistance);
				}
				val.panStereo = ComputeFfxiPan(key, value);
			}
		}

		private float ComputeFfxiPan(XiSoundEvent soundEvent, GameObject soundObject)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			if (soundEvent == null || (Object)(object)soundObject == (Object)null || !soundEvent.Spatialized)
			{
				return 0f;
			}
			Transform val = ResolveFfxiCameraTransform();
			if ((Object)(object)val == (Object)null)
			{
				return 0f;
			}
			return Mathf.Clamp(val.InverseTransformPoint(soundObject.transform.position).x / 5f, -1f, 1f);
		}

		private Transform ResolveFfxiListenerTransform()
		{
			if ((Object)(object)ffxiPlayerRoot != (Object)null)
			{
				return ffxiPlayerRoot;
			}
			if (!((Object)(object)Camera.main != (Object)null))
			{
				return ((Component)this).transform;
			}
			return ((Component)Camera.main).transform;
		}

		private Transform ResolveFfxiCameraTransform()
		{
			if ((Object)(object)ffxiAudioCameraRoot != (Object)null)
			{
				return ffxiAudioCameraRoot;
			}
			if (!((Object)(object)Camera.main != (Object)null))
			{
				return ((Component)this).transform;
			}
			return ((Component)Camera.main).transform;
		}

		private static float FfxiFalloff(float distance, float near, float far)
		{
			if (distance < near)
			{
				return 1f;
			}
			if (distance < far)
			{
				return 1f - (distance - near) / (far - near);
			}
			return 0f;
		}

		private void CleanupFinishedSounds()
		{
			for (int num = activeSoundObjects.Count - 1; num >= 0; num--)
			{
				GameObject val = activeSoundObjects[num];
				if (!particleSoundObjects.ContainsValue(val))
				{
					AudioSource val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<AudioSource>() : null);
					if (!((Object)(object)val2 != (Object)null) || !val2.isPlaying)
					{
						RemoveRoutineSoundObject(val);
						DestroySoundObject(val);
						activeSoundObjects.RemoveAt(num);
					}
				}
			}
		}

		private void DestroyActiveSounds()
		{
			foreach (GameObject activeSoundObject in activeSoundObjects)
			{
				DestroySoundObject(activeSoundObject);
			}
			activeSoundObjects.Clear();
			particleSoundObjects.Clear();
			routineSoundObjects.Clear();
		}

		private void RemoveRoutineSoundObject(GameObject soundObject)
		{
			XiSoundEvent xiSoundEvent = null;
			foreach (KeyValuePair<XiSoundEvent, GameObject> routineSoundObject in routineSoundObjects)
			{
				if (!((Object)(object)routineSoundObject.Value != (Object)(object)soundObject))
				{
					xiSoundEvent = routineSoundObject.Key;
					break;
				}
			}
			if (xiSoundEvent != null)
			{
				routineSoundObjects.Remove(xiSoundEvent);
			}
		}

		private static void DestroySoundObject(GameObject soundObject)
		{
			if (!((Object)(object)soundObject == (Object)null))
			{
				if (Application.isPlaying)
				{
					Object.Destroy((Object)(object)soundObject);
				}
				else
				{
					Object.DestroyImmediate((Object)(object)soundObject);
				}
			}
		}
	}
	[Serializable]
	public sealed class XiFfxiBroadcastActorColor
	{
		public bool confirmed;

		public Color32 initialColor = new Color32((byte)128, (byte)128, (byte)128, (byte)128);
	}
	[DisallowMultipleComponent]
	public sealed class XiFfxiActorColorBackend : MonoBehaviour, IXiFfxiActorCommandBackend, IXiFfxiActorCommandFrameBackend, IXiFfxiActorCommandEndFrameBackend
	{
		private sealed class ActorFade
		{
			public Color32 Initial;

			public Color32 Final;

			public int DurationFrames;

			public int ElapsedFrames;
		}

		[SerializeField]
		private bool sourceColorConfirmed;

		[SerializeField]
		private Color32 sourceInitialColor = new Color32((byte)128, (byte)128, (byte)128, (byte)128);

		[SerializeField]
		private bool targetColorConfirmed;

		[SerializeField]
		private Color32 targetInitialColor = new Color32((byte)128, (byte)128, (byte)128, (byte)128);

		[SerializeField]
		[Tooltip("Confirmed initial effect colors aligned by FFXI all-target index. Primary-target entries are ignored because they use Target Initial Color.")]
		private XiFfxiBroadcastActorColor[] broadcastTargetInitialColors = Array.Empty<XiFfxiBroadcastActorColor>();

		private readonly List<ActorFade> sourceFades = new List<ActorFade>();

		private readonly List<ActorFade> targetFades = new List<ActorFade>();

		private readonly Dictionary<int, List<ActorFade>> broadcastTargetFades = new Dictionary<int, List<ActorFade>>();

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

		private Color32 sourceColor;

		private Color32 targetColor;

		public bool SourceColorConfirmed
		{
			get
			{
				return sourceColorConfirmed;
			}
			set
			{
				sourceColorConfirmed = value;
			}
		}

		public Color32 SourceInitialColor
		{
			get
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				return sourceInitialColor;
			}
			set
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				sourceInitialColor = value;
			}
		}

		public bool TargetColorConfirmed
		{
			get
			{
				return targetColorConfirmed;
			}
			set
			{
				targetColorConfirmed = value;
			}
		}

		public Color32 TargetInitialColor
		{
			get
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				return targetInitialColor;
			}
			set
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				targetInitialColor = value;
			}
		}

		public XiFfxiBroadcastActorColor[] BroadcastTargetInitialColors
		{
			get
			{
				return broadcastTargetInitialColors;
			}
			set
			{
				broadcastTargetInitialColors = value ?? Array.Empty<XiFfxiBroadcastActorColor>();
			}
		}

		public Color32 SourceColor => sourceColor;

		public Color32 TargetColor => targetColor;

		public int SourceActiveFadeCount => sourceFades.Count;

		public int TargetActiveFadeCount => targetFades.Count;

		public bool TryGetBroadcastTargetColor(int targetIndex, out Color32 color)
		{
			return broadcastTargetColors.TryGetValue(targetIndex, out color);
		}

		public int GetBroadcastTargetActiveFadeCount(int targetIndex)
		{
			if (!broadcastTargetFades.TryGetValue(targetIndex, out var value))
			{
				return 0;
			}
			return value.Count;
		}

		private void Awake()
		{
			RestoreInitialColors();
		}

		public bool TryValidate(XiFfxiActorCommand command, out string reason)
		{
			if (command == null || command.Kind != XiFfxiActorCommandKind.ActorFade)
			{
				reason = "The actor-color backend received a non-fade FFXI command.";
				return false;
			}
			if (command.DurationTicks < 0)
			{
				reason = "The FFXI actor fade duration is negative.";
				return false;
			}
			if (command.BroadcastTargetIndex >= 0)
			{
				if (!command.UseTargetActor)
				{
					reason = "An indexed broadcast color fade does not select the FFXI association target.";
					return false;
				}
				XiFfxiBroadcastActorColor[] array = broadcastTargetInitialColors ?? Array.Empty<XiFfxiBroadcastActorColor>();
				if (command.BroadcastTargetIndex >= array.Length)
				{
					reason = $"The FFXI broadcast target color array has no entry at index {command.BroadcastTargetIndex}.";
					return false;
				}
				XiFfxiBroadcastActorColor xiFfxiBroadcastActorColor = array[command.BroadcastTargetIndex];
				if (xiFfxiBroadcastActorColor == null || !xiFfxiBroadcastActorColor.confirmed)
				{
					reason = $"The FFXI broadcast target {command.BroadcastTargetIndex} current effect color has not been confirmed.";
					return false;
				}
				reason = string.Empty;
				return true;
			}
			if (command.UseTargetActor ? (!targetColorConfirmed) : (!sourceColorConfirmed))
			{
				reason = "The FFXI " + (command.UseTargetActor ? "target" : "source") + " actor's current effect color has not been confirmed.";
				return false;
			}
			reason = string.Empty;
			return true;
		}

		public bool TryExecute(XiFfxiActorCommand command, out string reason)
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			if (!TryValidate(command, out reason))
			{
				return false;
			}
			if (command.BroadcastTargetIndex >= 0)
			{
				if (!broadcastTargetFades.TryGetValue(command.BroadcastTargetIndex, out var value))
				{
					value = new List<ActorFade>();
					broadcastTargetFades.Add(command.BroadcastTargetIndex, value);
				}
				if (!broadcastTargetColors.TryGetValue(command.BroadcastTargetIndex, out var value2))
				{
					value2 = broadcastTargetInitialColors[command.BroadcastTargetIndex].initialColor;
					broadcastTargetColors[command.BroadcastTargetIndex] = value2;
				}
				value.Add(new ActorFade
				{
					Initial = value2,
					Final = UnpackRgba(command.PackedColorRgba),
					DurationFrames = command.DurationTicks
				});
				reason = string.Empty;
				return true;
			}
			List<ActorFade> obj = (command.UseTargetActor ? targetFades : sourceFades);
			Color32 initial = (command.UseTargetActor ? targetColor : sourceColor);
			obj.Add(new ActorFade
			{
				Initial = initial,
				Final = UnpackRgba(command.PackedColorRgba),
				DurationFrames = command.DurationTicks
			});
			reason = string.Empty;
			return true;
		}

		public void ResetActorCommands()
		{
			sourceFades.Clear();
			targetFades.Clear();
			broadcastTargetFades.Clear();
			RestoreInitialColors();
		}

		public bool TryBeginFfxiFrame(out string reason)
		{
			reason = string.Empty;
			return true;
		}

		public bool TryEndFfxiFrame(out string reason)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			Advance(sourceFades, ref sourceColor);
			Advance(targetFades, ref targetColor);
			foreach (int item in new List<int>(broadcastTargetFades.Keys))
			{
				Color32 current2 = broadcastTargetColors[item];
				Advance(broadcastTargetFades[item], ref current2);
				broadcastTargetColors[item] = current2;
			}
			reason = string.Empty;
			return true;
		}

		private void RestoreInitialColors()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			sourceColor = sourceInitialColor;
			targetColor = targetInitialColor;
			broadcastTargetColors.Clear();
			XiFfxiBroadcastActorColor[] array = broadcastTargetInitialColors ?? Array.Empty<XiFfxiBroadcastActorColor>();
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] != null && array[i].confirmed)
				{
					broadcastTargetColors[i] = array[i].initialColor;
				}
			}
		}

		private static void Advance(List<ActorFade> fades, ref Color32 current)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < fades.Count; i++)
			{
				ActorFade actorFade = fades[i];
				actorFade.ElapsedFrames = Mathf.Min(actorFade.ElapsedFrames + 1, actorFade.DurationFrames);
				float progress = ((actorFade.DurationFrames == 0) ? 1f : ((float)actorFade.ElapsedFrames / (float)actorFade.DurationFrames));
				current = InterpolateBytes(actorFade.Initial, actorFade.Final, progress);
			}
			fades.RemoveAll((ActorFade item) => item.ElapsedFrames >= item.DurationFrames);
		}

		private static Color32 InterpolateBytes(Color32 initial, Color32 final, float progress)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			return new Color32(InterpolateByte(initial.r, final.r, progress), InterpolateByte(initial.g, final.g, progress), InterpolateByte(initial.b, final.b, progress), InterpolateByte(initial.a, final.a, progress));
		}

		private static byte InterpolateByte(byte initial, byte final, float progress)
		{
			return (byte)Mathf.FloorToInt((1f - progress) * (float)(int)initial + progress * (float)(int)final);
		}

		private static Color32 UnpackRgba(uint packed)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			return new Color32((byte)(packed & 0xFF), (byte)((packed >> 8) & 0xFF), (byte)((packed >> 16) & 0xFF), (byte)((packed >> 24) & 0xFF));
		}
	}
	public enum XiFfxiActorCommandKind
	{
		RouteMotion,
		SkeletonAnimation,
		AnimationLock,
		MovementLock,
		FacingLock,
		ActorFade,
		ActorWrapTexture,
		ActorWrapUv,
		ActorWrapColor,
		ForwardDisplacement,
		ActorJump,
		TransitionToIdle,
		ModelVisibility,
		AnimationMode,
		DisplayRangedModel,
		DisplayDead,
		DefaultModelVisibility
	}
	public sealed class XiFfxiActorCommand
	{
		public XiFfxiActorCommandKind Kind { get; internal set; }

		public string ResourceId { get; internal set; }

		public string DirectoryPath { get; internal set; }

		public int CommandSourceDatIndex { get; internal set; }

		public bool UseTargetActor { get; internal set; }

		public int BroadcastTargetIndex { get; internal set; } = -1;

		public int DurationTicks { get; internal set; }

		public int TransitionInTicks { get; internal set; }

		public int TransitionOutTicks { get; internal set; }

		public int MaximumLoops { get; internal set; }

		public float TransitionInFrames { get; internal set; }

		public bool IndefiniteLoop { get; internal set; }

		public bool LowPriority { get; internal set; }

		public bool OnlyIfIdle { get; internal set; }

		public uint PackedColorRgba { get; internal set; }

		public float WrapUvEndpoint { get; internal set; }

		public int WrapUvAxis { get; internal set; }

		public float ForwardDisplacement { get; internal set; }

		public int TargetJoint { get; internal set; }

		public int ModelSlot { get; internal set; }

		public bool ModelHidden { get; internal set; }

		public bool ModelIfEngaged { get; internal set; }

		public XiFfxiModelVisibilityState ModelVisibilityState { get; internal set; }

		public int AnimationMode { get; internal set; }

		public int AnimationModeValue { get; internal set; }

		public long EmittedFrame { get; internal set; }

		internal Func<bool> OriginRoutineIsActive { get; set; }
	}
	public interface IXiFfxiActorCommandBackend
	{
		bool TryValidate(XiFfxiActorCommand command, out string reason);

		bool TryExecute(XiFfxiActorCommand command, out string reason);
	}
	public interface IXiFfxiActorCommandContext : IXiFfxiActorCommandBackend
	{
	}
	public interface IXiFfxiActorCommandFrameBackend
	{
		void ResetActorCommands();

		bool TryBeginFfxiFrame(out string reason);
	}
	public interface IXiFfxiActorCommandFrameContext
	{
		void ResetActorCommands();

		bool TryBeginFfxiFrame(out string reason);
	}
	public interface IXiFfxiActorCommandValidationBackend
	{
		void BeginActorCommandValidation();

		void EndActorCommandValidation();
	}
	public interface IXiFfxiActorCommandValidationContext
	{
		void BeginActorCommandValidation();

		void EndActorCommandValidation();
	}
	public interface IXiFfxiActorCommandEndFrameBackend
	{
		bool TryEndFfxiFrame(out string reason);
	}
	public interface IXiFfxiActorCommandEndFrameContext
	{
		bool TryEndFfxiFrame(out string reason);
	}
	[DisallowMultipleComponent]
	public sealed class XiFfxiActorCommandContext : MonoBehaviour, IXiFfxiActorCommandContext, IXiFfxiActorCommandBackend, IXiFfxiActorCommandFrameContext, IXiFfxiActorCommandValidationContext, IXiFfxiActorCommandEndFrameContext
	{
		[SerializeField]
		[Tooltip("Component that reproduces FFXI route and skeleton-animation commands exactly.")]
		private MonoBehaviour backend;

		[SerializeField]
		[Tooltip("Component that retains exact FFXI animation, movement, and facing locks.")]
		private MonoBehaviour lockBackend;

		[SerializeField]
		[Tooltip("Component that retains exact FFXI actor color-fade state.")]
		private MonoBehaviour actorStateBackend;

		[SerializeField]
		[Tooltip("Component that retains exact FFXI actor-wrap texture, color, and UV state.")]
		private MonoBehaviour actorWrapBackend;

		[SerializeField]
		[Tooltip("Component that applies exact temporary FFXI actor display displacement.")]
		private MonoBehaviour displacementBackend;

		[SerializeField]
		[Tooltip("Component that retains exact FFXI actor model visibility and animation-mode state.")]
		private MonoBehaviour modelStateBackend;

		public MonoBehaviour Backend
		{
			get
			{
				return backend;
			}
			set
			{
				backend = value;
			}
		}

		public MonoBehaviour LockBackend
		{
			get
			{
				return lockBackend;
			}
			set
			{
				lockBackend = value;
			}
		}

		public MonoBehaviour ActorStateBackend
		{
			get
			{
				return actorStateBackend;
			}
			set
			{
				actorStateBackend = value;
			}
		}

		public MonoBehaviour ActorWrapBackend
		{
			get
			{
				return actorWrapBackend;
			}
			set
			{
				actorWrapBackend = value;
			}
		}

		public MonoBehaviour DisplacementBackend
		{
			get
			{
				return displacementBackend;
			}
			set
			{
				displacementBackend = value;
			}
		}

		public MonoBehaviour ModelStateBackend
		{
			get
			{
				return modelStateBackend;
			}
			set
			{
				modelStateBackend = value;
			}
		}

		public bool TryValidate(XiFfxiActorCommand command, out string reason)
		{
			IXiFfxiActorCommandBackend xiFfxiActorCommandBackend = ResolveBackend(command);
			if (xiFfxiActorCommandBackend == null)
			{
				reason = "XiFfxiActorCommandContext needs a confirmed FFXI actor-command backend; no command was approximated.";
				return false;
			}
			return xiFfxiActorCommandBackend.TryValidate(command, out reason);
		}

		public bool TryExecute(XiFfxiActorCommand command, out string reason)
		{
			IXiFfxiActorCommandBackend xiFfxiActorCommandBackend = ResolveBackend(command);
			if (xiFfxiActorCommandBackend == null)
			{
				reason = "The confirmed FFXI actor-command backend is missing at execution time.";
				return false;
			}
			return xiFfxiActorCommandBackend.TryExecute(command, out reason);
		}

		public void ResetActorCommands()
		{
			(backend as IXiFfxiActorCommandFrameBackend)?.ResetActorCommands();
			if (lockBackend != backend)
			{
				(lockBackend as IXiFfxiActorCommandFrameBackend)?.ResetActorCommands();
			}
			if (actorStateBackend != backend && actorStateBackend != lockBackend)
			{
				(actorStateBackend as IXiFfxiActorCommandFrameBackend)?.ResetActorCommands();
			}
			if (modelStateBackend != backend && modelStateBackend != lockBackend && modelStateBackend != actorStateBackend)
			{
				(modelStateBackend as IXiFfxiActorCommandFrameBackend)?.ResetActorCommands();
			}
			if (actorWrapBackend != backend && actorWrapBackend != lockBackend && actorWrapBackend != actorStateBackend && actorWrapBackend != modelStateBackend)
			{
				(actorWrapBackend as IXiFfxiActorCommandFrameBackend)?.ResetActorCommands();
			}
			if (displacementBackend != backend && displacementBackend != lockBackend && displacementBackend != actorStateBackend && displacementBackend != modelStateBackend && displacementBackend != actorWrapBackend)
			{
				(displacementBackend as IXiFfxiActorCommandFrameBackend)?.ResetActorCommands();
			}
		}

		public bool TryBeginFfxiFrame(out string reason)
		{
			if (backend is IXiFfxiActorCommandFrameBackend xiFfxiActorCommandFrameBackend && !xiFfxiActorCommandFrameBackend.TryBeginFfxiFrame(out reason))
			{
				return false;
			}
			if (lockBackend != backend && lockBackend is IXiFfxiActorCommandFrameBackend xiFfxiActorCommandFrameBackend2 && !xiFfxiActorCommandFrameBackend2.TryBeginFfxiFrame(out reason))
			{
				return false;
			}
			if (actorStateBackend != backend && actorStateBackend != lockBackend && actorStateBackend is IXiFfxiActorCommandFrameBackend xiFfxiActorCommandFrameBackend3 && !xiFfxiActorCommandFrameBackend3.TryBeginFfxiFrame(out reason))
			{
				return false;
			}
			if (modelStateBackend != backend && modelStateBackend != lockBackend && modelStateBackend != actorStateBackend && modelStateBackend is IXiFfxiActorCommandFrameBackend xiFfxiActorCommandFrameBackend4 && !xiFfxiActorCommandFrameBackend4.TryBeginFfxiFrame(out reason))
			{
				return false;
			}
			if (actorWrapBackend != backend && actorWrapBackend != lockBackend && actorWrapBackend != actorStateBackend && actorWrapBackend != modelStateBackend && actorWrapBackend is IXiFfxiActorCommandFrameBackend xiFfxiActorCommandFrameBackend5 && !xiFfxiActorCommandFrameBackend5.TryBeginFfxiFrame(out reason))
			{
				return false;
			}
			if (displacementBackend != backend && displacementBackend != lockBackend && displacementBackend != actorStateBackend && displacementBackend != modelStateBackend && displacementBackend != actorWrapBackend && displacementBackend is IXiFfxiActorCommandFrameBackend xiFfxiActorCommandFrameBackend6 && !xiFfxiActorCommandFrameBackend6.TryBeginFfxiFrame(out reason))
			{
				return false;
			}
			reason = string.Empty;
			return true;
		}

		public bool TryEndFfxiFrame(out string reason)
		{
			if (backend is IXiFfxiActorCommandEndFrameBackend xiFfxiActorCommandEndFrameBackend && !xiFfxiActorCommandEndFrameBackend.TryEndFfxiFrame(out reason))
			{
				return false;
			}
			if (lockBackend != backend && lockBackend is IXiFfxiActorCommandEndFrameBackend xiFfxiActorCommandEndFrameBackend2 && !xiFfxiActorCommandEndFrameBackend2.TryEndFfxiFrame(out reason))
			{
				return false;
			}
			if (actorStateBackend != backend && actorStateBackend != lockBackend && actorStateBackend is IXiFfxiActorCommandEndFrameBackend xiFfxiActorCommandEndFrameBackend3 && !xiFfxiActorCommandEndFrameBackend3.TryEndFfxiFrame(out reason))
			{
				return false;
			}
			if (modelStateBackend != backend && modelStateBackend != lockBackend && modelStateBackend != actorStateBackend && modelStateBackend is IXiFfxiActorCommandEndFrameBackend xiFfxiActorCommandEndFrameBackend4 && !xiFfxiActorCommandEndFrameBackend4.TryEndFfxiFrame(out reason))
			{
				return false;
			}
			if (actorWrapBackend != backend && actorWrapBackend != lockBackend && actorWrapBackend != actorStateBackend && actorWrapBackend != modelStateBackend && actorWrapBackend is IXiFfxiActorCommandEndFrameBackend xiFfxiActorCommandEndFrameBackend5 && !xiFfxiActorCommandEndFrameBackend5.TryEndFfxiFrame(out reason))
			{
				return false;
			}
			if (displacementBackend != backend && displacementBackend != lockBackend && displacementBackend != actorStateBackend && displacementBackend != modelStateBackend && displacementBackend != actorWrapBackend && displacementBackend is IXiFfxiActorCommandEndFrameBackend xiFfxiActorCommandEndFrameBackend6 && !xiFfxiActorCommandEndFrameBackend6.TryEndFfxiFrame(out reason))
			{
				return false;
			}
			reason = string.Empty;
			return true;
		}

		public void BeginActorCommandValidation()
		{
			(backend as IXiFfxiActorCommandValidationBackend)?.BeginActorCommandValidation();
			if (lockBackend != backend)
			{
				(lockBackend as IXiFfxiActorCommandValidationBackend)?.BeginActorCommandValidation();
			}
			if (actorStateBackend != backend && actorStateBackend != lockBackend)
			{
				(actorStateBackend as IXiFfxiActorCommandValidationBackend)?.BeginActorCommandValidation();
			}
			if (modelStateBackend != backend && modelStateBackend != lockBackend && modelStateBackend != actorStateBackend)
			{
				(modelStateBackend as IXiFfxiActorCommandValidationBackend)?.BeginActorCommandValidation();
			}
			if (actorWrapBackend != backend && actorWrapBackend != lockBackend && actorWrapBackend != actorStateBackend && actorWrapBackend != modelStateBackend)
			{
				(actorWrapBackend as IXiFfxiActorCommandValidationBackend)?.BeginActorCommandValidation();
			}
			if (displacementBackend != backend && displacementBackend != lockBackend && displacementBackend != actorStateBackend && displacementBackend != modelStateBackend && displacementBackend != actorWrapBackend)
			{
				(displacementBackend as IXiFfxiActorCommandValidationBackend)?.BeginActorCommandValidation();
			}
		}

		public void EndActorCommandValidation()
		{
			(backend as IXiFfxiActorCommandValidationBackend)?.EndActorCommandValidation();
			if (lockBackend != backend)
			{
				(lockBackend as IXiFfxiActorCommandValidationBackend)?.EndActorCommandValidation();
			}
			if (actorStateBackend != backend && actorStateBackend != lockBackend)
			{
				(actorStateBackend as IXiFfxiActorCommandValidationBackend)?.EndActorCommandValidation();
			}
			if (modelStateBackend != backend && modelStateBackend != lockBackend && modelStateBackend != actorStateBackend)
			{
				(modelStateBackend as IXiFfxiActorCommandValidationBackend)?.EndActorCommandValidation();
			}
			if (actorWrapBackend != backend && actorWrapBackend != lockBackend && actorWrapBackend != actorStateBackend && actorWrapBackend != modelStateBackend)
			{
				(actorWrapBackend as IXiFfxiActorCommandValidationBackend)?.EndActorCommandValidation();
			}
			if (displacementBackend != backend && displacementBackend != lockBackend && displacementBackend != actorStateBackend && displacementBackend != modelStateBackend && displacementBackend != actorWrapBackend)
			{
				(displacementBackend as IXiFfxiActorCommandValidationBackend)?.EndActorCommandValidation();
			}
		}

		private IXiFfxiActorCommandBackend ResolveBackend(XiFfxiActorCommand command)
		{
			bool flag = command != null;
			if (flag)
			{
				XiFfxiActorCommandKind kind = command.Kind;
				bool flag2 = (uint)(kind - 2) <= 2u;
				flag = flag2;
			}
			if (flag)
			{
				return (lockBackend as IXiFfxiActorCommandBackend) ?? (backend as IXiFfxiActorCommandBackend);
			}
			if (command != null && command.Kind == XiFfxiActorCommandKind.ActorFade)
			{
				return actorStateBackend as IXiFfxiActorCommandBackend;
			}
			flag = command != null;
			if (flag)
			{
				XiFfxiActorCommandKind kind = command.Kind;
				bool flag2 = (uint)(kind - 6) <= 2u;
				flag = flag2;
			}
			if (flag)
			{
				return actorWrapBackend as IXiFfxiActorCommandBackend;
			}
			flag = command != null;
			if (flag)
			{
				XiFfxiActorCommandKind kind = command.Kind;
				bool flag2 = (uint)(kind - 9) <= 1u;
				flag = flag2;
			}
			if (flag)
			{
				return displacementBackend as IXiFfxiActorCommandBackend;
			}
			flag = command != null;
			if (flag)
			{
				XiFfxiActorCommandKind kind = command.Kind;
				bool flag2 = (uint)(kind - 12) <= 4u;
				flag = flag2;
			}
			if (flag)
			{
				return modelStateBackend as IXiFfxiActorCommandBackend;
			}
			return backend as IXiFfxiActorCommandBackend;
		}
	}
	public struct XiFfxiAttachmentState
	{
		public Vector3 LocalPosition;

		public Quaternion LocalRotation;

		public float PositionScale;

		public float SizeScale;

		public float ActorToActorDistanceScale;

		public static XiFfxiAttachmentState Identity => new XiFfxiAttachmentState
		{
			LocalPosition = Vector3.zero,
			LocalRotation = Quaternion.identity,
			PositionScale = 1f,
			SizeScale = 1f,
			ActorToActorDistanceScale = 1f
		};
	}
	public interface IXiFfxiAttachmentContext
	{
		bool TryResolve(XiParticleGeneratorProgram program, out XiFfxiAttachmentState state, out string reason);

		bool TryResolveActor(bool useTarget, out XiFfxiAttachmentState state, out string reason);
	}
	public interface IXiFfxiAssociationAttachmentContext
	{
		bool TryResolve(XiParticleGeneratorProgram program, bool swapSourceAndTarget, out XiFfxiAttachmentState state, out string reason);
	}
	public interface IXiFfxiNearestJointContext
	{
		bool TrySnapshotNearestJoints(XiParticleGeneratorProgram program, bool swapSourceAndTarget, int broadcastTargetIndex, out XiParticleGeneratorProgram resolvedProgram, out string reason);
	}
	public interface IXiFfxiBroadcastTargetContext
	{
		bool TryGetBroadcastTargetCount(out int count, out string reason);

		bool IsBroadcastTargetPrimary(int targetIndex);

		bool TryResolveBroadcast(XiParticleGeneratorProgram program, bool swapSourceAndTarget, int targetIndex, out XiFfxiAttachmentState state, out string reason);

		bool TryResolveBroadcastActor(bool useAssociationTarget, int targetIndex, out XiFfxiAttachmentState state, out string reason);
	}
	public struct XiFfxiSoundTargetState
	{
		public bool ShouldEmit;

		public bool HasPosition;

		public XiFfxiAttachmentState Attachment;

		public Transform FollowRoot;
	}
	public interface IXiFfxiSoundTargetContext
	{
		bool TryResolveSoundTarget(XiSoundTarget target, bool associationFlipped, Vector3 listenerLocalPosition, out XiFfxiSoundTargetState state, out string reason);

		bool TryResolveBroadcastSoundTarget(XiSoundTarget target, bool associationFlipped, int targetIndex, Vector3 listenerLocalPosition, out XiFfxiSoundTargetState state, out string reason);
	}
	public interface IXiFfxiActorSnapshotContext
	{
		bool TryValidateActorSnapshotCommands(out string reason);

		bool TryApplyPositionAndJointSnapshot(out string reason);

		bool TrySetJointSnapshot(bool enabled, out string reason);

		void ResetActorSnapshots();
	}
	public interface IXiFfxiRangedAnimationContext
	{
		bool TryResolveRangedAnimationProfile(bool useTargetActor, out bool isPlayerCharacter, out bool hasRangedWeaponInfo, out int rangedWeaponType, out string reason);
	}
	public interface IXiFfxiEffectColorContext
	{
		bool TryConfirmNoEffectColorOverride(bool useTargetActor, out string reason);
	}
	public enum XiFfxiRangedWeaponType
	{
		None = 0,
		WindInstrument = 1,
		StringInstrument = 2,
		Marksmanship = 3,
		ThrowingWeapon = 4,
		ThrowingAmmo = 5,
		Archery = 6,
		HandbellIndi = 10,
		HandbellGeo = 11,
		Unset = 255
	}
	public enum XiFfxiWeaponAttachmentModel
	{
		Unconfirmed,
		NonPlayerCharacterSkeleton,
		PlayerCharacterSkeleton,
		ActorModelWithoutSkeleton
	}
	[Serializable]
	public sealed class XiFfxiJointAnchor
	{
		[Range(0f, 127f)]
		public int standardJoint;

		public Transform anchor;
	}
	[Serializable]
	public sealed class XiFfxiBroadcastActorPose
	{
		public bool confirmed;

		public XiFfxiJointAnchor[] joints = Array.Empty<XiFfxiJointAnchor>();

		[Min(0f)]
		public float positionScale = 1f;

		[Min(0f)]
		public float sizeScale = 1f;
	}
	[Serializable]
	public sealed class XiFfxiJointOverride
	{
		[Range(0f, 255f)]
		public int sourceJoint;

		[Range(0f, 127f)]
		public int resolvedStandardJoint;
	}
	[Serializable]
	public sealed class XiFfxiZoneActorProfile
	{
		public bool confirmed;

		public bool hasNpcEffectLink;

		public string npcEffectLinkId;

		public bool isDoor;
	}
	[DisallowMultipleComponent]
	public sealed class XiFfxiActorContext : MonoBehaviour, IXiFfxiAttachmentContext, IXiFfxiAssociationAttachmentContext, IXiFfxiSoundTargetContext, IXiFfxiActorSnapshotContext, IXiFfxiBroadcastTargetContext, IXiFfxiRangedAnimationContext, IXiFfxiEffectColorContext, IXiFfxiNearestJointContext
	{
		private struct ActorPoseSnapshot
		{
			public Vector3 WorldPosition;

			public float WorldYaw;
		}

		[SerializeField]
		private bool sourceValuesConfirmed;

		[SerializeField]
		private Transform sourceActorRoot;

		[SerializeField]
		private XiFfxiJointAnchor[] sourceJoints = Array.Empty<XiFfxiJointAnchor>();

		[SerializeField]
		[Min(0f)]
		private float sourcePositionScale = 1f;

		[SerializeField]
		[Min(0f)]
		private float sourceSizeScale = 1f;

		[SerializeField]
		private bool targetValuesConfirmed;

		[SerializeField]
		private Transform targetActorRoot;

		[SerializeField]
		private XiFfxiJointAnchor[] targetJoints = Array.Empty<XiFfxiJointAnchor>();

		[SerializeField]
		[Min(0f)]
		private float targetPositionScale = 1f;

		[SerializeField]
		[Min(0f)]
		private float targetSizeScale = 1f;

		[Header("Weapon attachment (type 0x9)")]
		[SerializeField]
		private XiFfxiWeaponAttachmentModel sourceWeaponAttachmentModel;

		[SerializeField]
		private XiFfxiWeaponAttachmentModel targetWeaponAttachmentModel;

		[SerializeField]
		private bool sourceWeaponJointOverridesConfirmed;

		[SerializeField]
		private XiFfxiJointOverride[] sourceWeaponJointOverrides = Array.Empty<XiFfxiJointOverride>();

		[SerializeField]
		private bool targetWeaponJointOverridesConfirmed;

		[SerializeField]
		private XiFfxiJointOverride[] targetWeaponJointOverrides = Array.Empty<XiFfxiJointOverride>();

		[Header("Zone actor attachment (type 0xA)")]
		[SerializeField]
		private XiFfxiZoneActorProfile sourceZoneActorProfile = new XiFfxiZoneActorProfile();

		[SerializeField]
		private XiFfxiZoneActorProfile targetZoneActorProfile = new XiFfxiZoneActorProfile();

		[NonSerialized]
		private XiFfxiZoneReceiverRuntime zoneReceiverRuntime;

		[Header("Actor effect color")]
		[SerializeField]
		[Tooltip("Confirms that the source actor has no external FFXI effect-color override. Required when parent-color inheritance reads a source-associated particle.")]
		private bool sourceEffectColorOverrideAbsentConfirmed;

		[SerializeField]
		[Tooltip("Confirms that the target actor has no external FFXI effect-color override. Required when parent-color inheritance reads a target-associated particle.")]
		private bool targetEffectColorOverrideAbsentConfirmed;

		[Header("Sound target set")]
		[SerializeField]
		private bool soundTargetsConfirmed;

		[SerializeField]
		private Transform[] allTargetActorRoots = Array.Empty<Transform>();

		[SerializeField]
		[Tooltip("Posed joints and evaluated actor scales aligned one-for-one with All Target Actor Roots. The primary target continues to use the normal Target fields.")]
		private XiFfxiBroadcastActorPose[] broadcastTargetPoses = Array.Empty<XiFfxiBroadcastActorPose>();

		[SerializeField]
		private Transform targetAoeCenter;

		[SerializeField]
		private Transform playerActorRoot;

		[Header("Actor jump")]
		[SerializeField]
		[Tooltip("Confirms the FFXI player identity and whether Target AOE Center is intentionally present or absent for actor-jump opcode 0x7A.")]
		private bool actorJumpContextConfirmed;

		[Header("Ranged animation dispatch")]
		[SerializeField]
		private bool sourceRangedAnimationConfirmed;

		[SerializeField]
		private bool sourceIsPlayerCharacter;

		[SerializeField]
		private bool sourceHasRangedWeaponInfo;

		[SerializeField]
		private XiFfxiRangedWeaponType sourceRangedWeaponType = XiFfxiRangedWeaponType.Unset;

		[SerializeField]
		private bool targetRangedAnimationConfirmed;

		[SerializeField]
		private bool targetIsPlayerCharacter;

		[SerializeField]
		private bool targetHasRangedWeaponInfo;

		[SerializeField]
		private XiFfxiRangedWeaponType targetRangedWeaponType = XiFfxiRangedWeaponType.Unset;

		private bool snapshotPositions;

		private bool snapshotJoints;

		private readonly Dictionary<Transform, ActorPoseSnapshot> actorPoseSnapshots = new Dictionary<Transform, ActorPoseSnapshot>();

		private readonly Dictionary<Transform, Dictionary<int, Vector3>> jointSnapshots = new Dictionary<Transform, Dictionary<int, Vector3>>();

		public bool SourceValuesConfirmed
		{
			get
			{
				return sourceValuesConfirmed;
			}
			set
			{
				sourceValuesConfirmed = value;
			}
		}

		public Transform SourceActorRoot
		{
			get
			{
				return sourceActorRoot;
			}
			set
			{
				sourceActorRoot = value;
			}
		}

		public XiFfxiJointAnchor[] SourceJoints
		{
			get
			{
				return sourceJoints;
			}
			set
			{
				sourceJoints = value ?? Array.Empty<XiFfxiJointAnchor>();
			}
		}

		public float SourcePositionScale
		{
			get
			{
				return sourcePositionScale;
			}
			set
			{
				sourcePositionScale = Mathf.Max(0f, value);
			}
		}

		public float SourceSizeScale
		{
			get
			{
				return sourceSizeScale;
			}
			set
			{
				sourceSizeScale = Mathf.Max(0f, value);
			}
		}

		public bool TargetValuesConfirmed
		{
			get
			{
				return targetValuesConfirmed;
			}
			set
			{
				targetValuesConfirmed = value;
			}
		}

		public Transform TargetActorRoot
		{
			get
			{
				return targetActorRoot;
			}
			set
			{
				targetActorRoot = value;
			}
		}

		public XiFfxiJointAnchor[] TargetJoints
		{
			get
			{
				return targetJoints;
			}
			set
			{
				targetJoints = value ?? Array.Empty<XiFfxiJointAnchor>();
			}
		}

		public float TargetPositionScale
		{
			get
			{
				return targetPositionScale;
			}
			set
			{
				targetPositionScale = Mathf.Max(0f, value);
			}
		}

		public float TargetSizeScale
		{
			get
			{
				return targetSizeScale;
			}
			set
			{
				targetSizeScale = Mathf.Max(0f, value);
			}
		}

		public XiFfxiWeaponAttachmentModel SourceWeaponAttachmentModel
		{
			get
			{
				return sourceWeaponAttachmentModel;
			}
			set
			{
				sourceWeaponAttachmentModel = value;
			}
		}

		public XiFfxiWeaponAttachmentModel TargetWeaponAttachmentModel
		{
			get
			{
				return targetWeaponAttachmentModel;
			}
			set
			{
				targetWeaponAttachmentModel = value;
			}
		}

		public bool SourceWeaponJointOverridesConfirmed
		{
			get
			{
				return sourceWeaponJointOverridesConfirmed;
			}
			set
			{
				sourceWeaponJointOverridesConfirmed = value;
			}
		}

		public XiFfxiJointOverride[] SourceWeaponJointOverrides
		{
			get
			{
				return sourceWeaponJointOverrides;
			}
			set
			{
				sourceWeaponJointOverrides = value ?? Array.Empty<XiFfxiJointOverride>();
			}
		}

		public bool TargetWeaponJointOverridesConfirmed
		{
			get
			{
				return targetWeaponJointOverridesConfirmed;
			}
			set
			{
				targetWeaponJointOverridesConfirmed = value;
			}
		}

		public XiFfxiJointOverride[] TargetWeaponJointOverrides
		{
			get
			{
				return targetWeaponJointOverrides;
			}
			set
			{
				targetWeaponJointOverrides = value ?? Array.Empty<XiFfxiJointOverride>();
			}
		}

		public XiFfxiZoneActorProfile SourceZoneActorProfile
		{
			get
			{
				return sourceZoneActorProfile;
			}
			set
			{
				sourceZoneActorProfile = value ?? new XiFfxiZoneActorProfile();
			}
		}

		public XiFfxiZoneActorProfile TargetZoneActorProfile
		{
			get
			{
				return targetZoneActorProfile;
			}
			set
			{
				targetZoneActorProfile = value ?? new XiFfxiZoneActorProfile();
			}
		}

		public XiFfxiZoneReceiverRuntime ZoneReceiverRuntime
		{
			get
			{
				return zoneReceiverRuntime;
			}
			set
			{
				zoneReceiverRuntime = value;
			}
		}

		public bool SourceEffectColorOverrideAbsentConfirmed
		{
			get
			{
				return sourceEffectColorOverrideAbsentConfirmed;
			}
			set
			{
				sourceEffectColorOverrideAbsentConfirmed = value;
			}
		}

		public bool TargetEffectColorOverrideAbsentConfirmed
		{
			get
			{
				return targetEffectColorOverrideAbsentConfirmed;
			}
			set
			{
				targetEffectColorOverrideAbsentConfirmed = value;
			}
		}

		public bool SoundTargetsConfirmed
		{
			get
			{
				return soundTargetsConfirmed;
			}
			set
			{
				soundTargetsConfirmed = value;
			}
		}

		public Transform[] AllTargetActorRoots
		{
			get
			{
				return allTargetActorRoots;
			}
			set
			{
				allTargetActorRoots = value ?? Array.Empty<Transform>();
			}
		}

		public XiFfxiBroadcastActorPose[] BroadcastTargetPoses
		{
			get
			{
				return broadcastTargetPoses;
			}
			set
			{
				broadcastTargetPoses = value ?? Array.Empty<XiFfxiBroadcastActorPose>();
			}
		}

		public Transform TargetAoeCenter
		{
			get
			{
				return targetAoeCenter;
			}
			set
			{
				targetAoeCenter = value;
			}
		}

		public Transform PlayerActorRoot
		{
			get
			{
				return playerActorRoot;
			}
			set
			{
				playerActorRoot = value;
			}
		}

		public bool ActorJumpContextConfirmed
		{
			get
			{
				return actorJumpContextConfirmed;
			}
			set
			{
				actorJumpContextConfirmed = value;
			}
		}

		public bool SourceRangedAnimationConfirmed
		{
			get
			{
				return sourceRangedAnimationConfirmed;
			}
			set
			{
				sourceRangedAnimationConfirmed = value;
			}
		}

		public bool SourceIsPlayerCharacter
		{
			get
			{
				return sourceIsPlayerCharacter;
			}
			set
			{
				sourceIsPlayerCharacter = value;
			}
		}

		public bool SourceHasRangedWeaponInfo
		{
			get
			{
				return sourceHasRangedWeaponInfo;
			}
			set
			{
				sourceHasRangedWeaponInfo = value;
			}
		}

		public XiFfxiRangedWeaponType SourceRangedWeaponType
		{
			get
			{
				return sourceRangedWeaponType;
			}
			set
			{
				sourceRangedWeaponType = value;
			}
		}

		public bool TargetRangedAnimationConfirmed
		{
			get
			{
				return targetRangedAnimationConfirmed;
			}
			set
			{
				targetRangedAnimationConfirmed = value;
			}
		}

		public bool TargetIsPlayerCharacter
		{
			get
			{
				return targetIsPlayerCharacter;
			}
			set
			{
				targetIsPlayerCharacter = value;
			}
		}

		public bool TargetHasRangedWeaponInfo
		{
			get
			{
				return targetHasRangedWeaponInfo;
			}
			set
			{
				targetHasRangedWeaponInfo = value;
			}
		}

		public XiFfxiRangedWeaponType TargetRangedWeaponType
		{
			get
			{
				return targetRangedWeaponType;
			}
			set
			{
				targetRangedWeaponType = value;
			}
		}

		public bool PositionSnapshotEnabled => snapshotPositions;

		public bool JointSnapshotEnabled => snapshotJoints;

		public int RetainedActorSnapshotCount => actorPoseSnapshots.Count;

		public bool TryConfirmNoEffectColorOverride(bool useTargetActor, out string reason)
		{
			if (useTargetActor ? targetEffectColorOverrideAbsentConfirmed : sourceEffectColorOverrideAbsentConfirmed)
			{
				reason = string.Empty;
				return true;
			}
			reason = "The FFXI " + (useTargetActor ? "target" : "source") + " actor's external effect-color override has not been confirmed absent in XiFfxiActorContext.";
			return false;
		}

		public bool TryResolve(XiParticleGeneratorProgram program, out XiFfxiAttachmentState state, out string reason)
		{
			return TryResolve(program, swapSourceAndTarget: false, out state, out reason);
		}

		public bool TryResolve(XiParticleGeneratorProgram program, bool swapSourceAndTarget, out XiFfxiAttachmentState state, out string reason)
		{
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_0356: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_036a: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			state = XiFfxiAttachmentState.Identity;
			reason = string.Empty;
			if (program == null)
			{
				reason = "The particle generator has no decoded attachment header.";
				return false;
			}
			if (program.AttachType == 0)
			{
				return true;
			}
			if (program.AttachType == 9)
			{
				return TryResolveSourceWeapon(program, swapSourceAndTarget, out state, out reason);
			}
			if (program.AttachType == 10)
			{
				return TryResolveZoneActor(program, swapSourceAndTarget, out state, out reason);
			}
			int attachType = program.AttachType;
			if ((uint)(attachType - 7) <= 1u)
			{
				reason = $"FFXI attachment type 0x{program.AttachType:X} remains blocked because its native association kind, position and rotation basis, and update/follow behavior are not confirmed.";
				return false;
			}
			if (program.AttachType == 13)
			{
				reason = "FFXI attachment type 0xD remains blocked because its actor association, joint roles, native position and rotation basis, and actor-scale semantics are not confirmed.";
				return false;
			}
			attachType = program.AttachType;
			if ((uint)(attachType - 11) <= 1u)
			{
				reason = $"FFXI zone-actor attachment type 0x{program.AttachType:X} remains blocked because its native compound rotation correction is not confirmed.";
				return false;
			}
			attachType = program.AttachType;
			if ((uint)(attachType - 14) <= 1u)
			{
				reason = $"FFXI celestial attachment type 0x{program.AttachType:X} remains blocked because its native trajectory, radius, camera/area conversion, follow override, and fog behavior are not confirmed.";
				return false;
			}
			if (!TrySnapshotNearestJoints(program, swapSourceAndTarget, -1, out program, out reason))
			{
				return false;
			}
			attachType = program.AttachType;
			if ((attachType == 3 || attachType == 6) ? true : false)
			{
				return TryResolveActorBasis(program, swapSourceAndTarget, out state, out reason);
			}
			attachType = program.AttachType;
			bool flag = (uint)(attachType - 4) <= 1u;
			if (flag || (program.AttachType == 2 && (program.AdditionalAttachFlags & 1) != 0))
			{
				return TryResolveActorFacing(program, swapSourceAndTarget, out state, out reason);
			}
			if (program.AttachType != 1 && program.AttachType != 2)
			{
				reason = $"FFXI attachment type 0x{program.AttachType:X} is not yet confirmed in Unity.";
				return false;
			}
			bool flag2 = program.AttachType == 1;
			bool num = (swapSourceAndTarget ? (!flag2) : flag2);
			bool flag3 = (num ? sourceValuesConfirmed : targetValuesConfirmed);
			Transform val = (num ? sourceActorRoot : targetActorRoot);
			int num2 = (flag2 ? program.AttachedJoint0 : program.AttachedJoint1);
			XiFfxiJointAnchor[] joints = (num ? sourceJoints : targetJoints);
			string text = (num ? "source" : "target");
			if (!flag3)
			{
				reason = "The FFXI " + text + " actor values have not been confirmed in XiFfxiActorContext.";
				return false;
			}
			if ((Object)(object)val == (Object)null)
			{
				reason = "The FFXI " + text + " actor root is missing in XiFfxiActorContext.";
				return false;
			}
			Transform val2 = ((num2 == 48) ? val : FindJoint(joints, num2));
			if ((Object)(object)val2 == (Object)null)
			{
				reason = $"FFXI {text} standard joint {num2} has no posed anchor in XiFfxiActorContext.";
				return false;
			}
			float sourceValue = (swapSourceAndTarget ? targetPositionScale : sourcePositionScale);
			float targetValue = (swapSourceAndTarget ? sourcePositionScale : targetPositionScale);
			float sourceValue2 = (swapSourceAndTarget ? targetSizeScale : sourceSizeScale);
			float targetValue2 = (swapSourceAndTarget ? sourceSizeScale : targetSizeScale);
			float num3 = ResolveScale(program.AdditionalAttachFlags, 64, 128, sourceValue, targetValue);
			float num4 = ResolveScale(program.AdditionalAttachFlags, 1024, 2048, sourceValue2, targetValue2);
			if (!IsFinitePositive(num3) || !IsFinitePositive(num4))
			{
				reason = "The evaluated FFXI actor position/size scale must be finite and greater than zero.";
				return false;
			}
			ActorPoseSnapshot actorPoseSnapshot = ResolveActorPose(val);
			Vector3 val3 = ((num2 == 48) ? Vector3.zero : ResolveJointOffset(val, num2, val2));
			Matrix4x4 worldToLocalMatrix = ((Component)this).transform.worldToLocalMatrix;
			Vector3 localPosition = ((Matrix4x4)(ref worldToLocalMatrix)).MultiplyPoint3x4(actorPoseSnapshot.WorldPosition + val3);
			Quaternion localRotation = Quaternion.Inverse(((Component)this).transform.rotation) * Quaternion.Euler(0f, actorPoseSnapshot.WorldYaw, 0f);
			state = new XiFfxiAttachmentState
			{
				LocalPosition = localPosition,
				LocalRotation = localRotation,
				PositionScale = num3,
				SizeScale = num4,
				ActorToActorDistanceScale = 1f
			};
			return true;
		}

		public bool TrySnapshotNearestJoints(XiParticleGeneratorProgram program, bool swapSourceAndTarget, int broadcastTargetIndex, out XiParticleGeneratorProgram resolvedProgram, out string reason)
		{
			resolvedProgram = program;
			reason = string.Empty;
			if (program == null)
			{
				reason = "The particle generator has no decoded attachment header.";
				return false;
			}
			bool flag = program.AttachType == 9;
			int attachType;
			if (!flag)
			{
				attachType = program.AttachType;
				bool flag2 = ((attachType == 0 || (uint)(attachType - 7) <= 1u || (uint)(attachType - 11) <= 4u) ? true : false);
				flag = flag2;
			}
			if (flag)
			{
				return true;
			}
			switch (program.AttachType)
			{
			case 1:
			case 3:
			case 5:
			case 6:
			case 10:
				flag = true;
				break;
			default:
				flag = false;
				break;
			}
			bool flag3 = flag || (program.AttachType == 2 && (program.AdditionalAttachFlags & 1) != 0);
			attachType = program.AttachType;
			flag = (((uint)(attachType - 2) <= 2u || attachType == 6) ? true : false);
			bool num = flag;
			int attachedJoint = program.AttachedJoint0;
			int attachedJoint2 = program.AttachedJoint1;
			bool flag4 = flag3 && attachedJoint >= 49 && attachedJoint <= 51 && !program.AttachedJoint0NearestSnapshot;
			bool flag5 = num && attachedJoint2 >= 49 && attachedJoint2 <= 51 && !program.AttachedJoint1NearestSnapshot;
			if (!flag4 && !flag5)
			{
				return true;
			}
			if ((flag4 && attachedJoint != 49) || (flag5 && attachedJoint2 != 49))
			{
				reason = "FFXI nearest-joint pseudo references 50 and 51 remain blocked: the retained implementation confirms the joint-49 search over standard joints 13-20 but explicitly leaves the distinction for 50/51 unknown.";
				return false;
			}
			bool flag6 = targetValuesConfirmed;
			Transform actorRoot = targetActorRoot;
			XiFfxiJointAnchor[] joints = targetJoints;
			if (broadcastTargetIndex >= 0 && !IsBroadcastTargetPrimary(broadcastTargetIndex))
			{
				if (!TryGetBroadcastTargetPose(broadcastTargetIndex, out actorRoot, out var pose, out reason))
				{
					return false;
				}
				flag6 = true;
				joints = pose.joints;
			}
			bool num2 = (swapSourceAndTarget ? flag6 : sourceValuesConfirmed);
			bool flag7 = (swapSourceAndTarget ? sourceValuesConfirmed : flag6);
			Transform val = (swapSourceAndTarget ? actorRoot : sourceActorRoot);
			Transform val2 = (swapSourceAndTarget ? sourceActorRoot : actorRoot);
			XiFfxiJointAnchor[] joints2 = (swapSourceAndTarget ? joints : sourceJoints);
			XiFfxiJointAnchor[] joints3 = (swapSourceAndTarget ? sourceJoints : joints);
			if (!num2 || !flag7)
			{
				reason = "Both FFXI association actors must be confirmed to resolve nearest-joint pseudo reference 49.";
				return false;
			}
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				reason = "Both FFXI association actor roots are required to resolve nearest-joint pseudo reference 49.";
				return false;
			}
			int selectedJoint = attachedJoint;
			int selectedJoint2 = attachedJoint2;
			if (flag4 && !TrySelectNearestStandardJoint(val, joints2, val2, "association source", out selectedJoint, out reason))
			{
				return false;
			}
			if (flag5 && !TrySelectNearestStandardJoint(val2, joints3, val, "association target", out selectedJoint2, out reason))
			{
				return false;
			}
			resolvedProgram = CloneWithResolvedNearestJoints(program, selectedJoint, selectedJoint2, flag4, flag5);
			return true;
		}

		private bool TrySelectNearestStandardJoint(Transform candidateActorRoot, XiFfxiJointAnchor[] joints, Transform referenceActorRoot, string actorName, out int selectedJoint, out string reason)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			selectedJoint = 13;
			reason = string.Empty;
			float num = float.PositiveInfinity;
			Vector3 worldPosition = ResolveActorPose(referenceActorRoot).WorldPosition;
			Vector3 worldPosition2 = ResolveActorPose(candidateActorRoot).WorldPosition;
			for (int i = 13; i <= 20; i++)
			{
				Transform val = FindJoint(joints, i);
				if ((Object)(object)val == (Object)null)
				{
					reason = $"FFXI {actorName} nearest-joint candidate {i} has no posed anchor in XiFfxiActorContext; all standard joints 13-2