Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of AbsoluteVirtueSurvivor v1.0.1
plugins\AbsoluteVirtueSurvivor\AbsoluteVirtueSurvivor.dll
Decompiled 9 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.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
The result has been truncated due to the large size, download it to view full contents!
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