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 Phainon v1.0.4
PhainonMod.dll
Decompiled 6 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.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using AncientScepter; using BaseVoiceoverLib; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using EntityStates.Commando; using EntityStates.CursedBook.RitualCircle; using EntityStates.CursedBook.Spells; using EntityStates.DroneScrapper; using EntityStates.Merc.Weapon; using EntityStates.Missions.ChampRush; using EntityStates.Reaper; using HG; using HG.BlendableTypes; using HG.Reflection; using IL.EntityStates.ChampRushReaper; using IL.RoR2; using IL.RoR2.CharacterAI; using IL.RoR2.Items; using KinematicCharacterController; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; using MonoMod.Cil; using MonoMod.RuntimeDetour; using On.EntityStates; using On.EntityStates.CursedBook.RitualCircle; using On.EntityStates.Missions.ChampRush; using On.EntityStates.Reaper; using On.RoR2; using On.RoR2.CharacterAI; using On.RoR2.Items; using On.RoR2.UI; using PhainonMod.Components; using PhainonMod.Content; using PhainonMod.Core; using PhainonMod.Hooks; using PhainonMod.Modules; using PhainonMod.Net; using PhainonMod.SkillDefs; using PhainonMod.SkillStates.Base; using PhainonMod.SkillStates.Khaslana; using PhainonMod.SkillStates.Phainon; using PhainonMod.Survivors; using PhainonMod.Visuals; using R2API; using R2API.Networking; using R2API.Networking.Interfaces; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using RoR2.Audio; using RoR2.CameraModes; using RoR2.CharacterAI; using RoR2.ContentManagement; using RoR2.EntityLogic; using RoR2.HudOverlay; using RoR2.Items; using RoR2.Navigation; using RoR2.Networking; using RoR2.Projectile; using RoR2.Skills; using RoR2.Stats; using RoR2.UI; using TMPro; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Animations; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.Rendering; using UnityEngine.Rendering.PostProcessing; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: OptIn] [assembly: IgnoresAccessChecksTo("RoR2")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Joaqi")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.4.0")] [assembly: AssemblyInformationalVersion("1.0.4+c908ced2b682b0a7e57ceed4ac9adb88b1bb5ca2")] [assembly: AssemblyProduct("PhainonMod")] [assembly: AssemblyTitle("PhainonMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.4.0")] [module: UnverifiableCode] namespace PhainonMod { internal static class Log { private static ManualLogSource _log; internal static void Init(ManualLogSource log) { _log = log; } internal static void Debug(object data) { _log.LogDebug(data); } internal static void Info(object data) { _log.LogInfo(data); } internal static void Trace(object data) { _log.LogDebug(data); } internal static void Message(object data) { _log.LogMessage(data); } internal static void Warning(object data) { _log.LogWarning(data); } internal static void Error(object data) { _log.LogError(data); } internal static void Fatal(object data) { _log.LogFatal(data); } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.Joaqi.PhainonMod", "PhainonMod", "1.0.4")] public sealed class PhainonPlugin : BaseUnityPlugin { public static PhainonPlugin Instance { get; private set; } private void Awake() { Instance = this; Log.Init(((BaseUnityPlugin)this).Logger); try { Config.ReadConfig(((BaseUnityPlugin)this).Config); if (Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions")) { try { RiskOfOptionsCompat.Init(); } catch (Exception ex) { Log.Warning("RiskOfOptions entries skipped: " + ex.Message); } } Asset.Initialize(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location)); if (Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions")) { try { RiskOfOptionsCompat.SetIcon(); } catch (Exception ex2) { Log.Warning("RiskOfOptions icon skipped: " + ex2.Message); } } PhainonSounds.Init(); bool num = Chainloader.PluginInfos.ContainsKey("com.Moffein.BaseVoiceoverLib"); PhainonVoice.Init(num); if (num) { try { VoiceoverCompat.Init(); } catch (Exception ex3) { Log.Warning("Voice lines skipped: " + ex3.Message); } } PhainonEffects.Create(); PhainonItems.Create(); PhainonHudGauge.Init(); KhaslanaHealthCard.Init(); ConversionTable.Init(); PhainonBuffs.Create(); States.RegisterStates(); Tokens.AddTokens(); AncientScepterCompat.Init(); PhainonSurvivor.Create(); if (AncientScepterCompat.Installed) { try { AncientScepterCompat.Register(); } catch (Exception ex4) { Log.Warning("AncientScepter: Beginning of the End not registered: " + ex4.Message); } } if (Chainloader.PluginInfos.ContainsKey("Def.BazaarIsMyHaven")) { try { BazaarCompat.Init(); } catch (Exception ex5) { Log.Warning("BazaarIsMyHaven: Donation Altar reward skipped: " + ex5.Message); } } PhainonEntrance.Create(); PhainonDeath.Wire(); PhainonUmbra.CreateMaster(); PhainonHooks.Init(); FormStateNet.Register(); ScourgeNet.Register(); new ContentPacks().Initialize(); } catch (Exception arg) { Log.Error(string.Format("{0} failed to load: {1}", "PhainonMod", arg)); return; } Log.Info(string.Format("{0} {1} loaded: {2} entity states, ", "PhainonMod", "1.0.4", States.entityStates.Count) + $"{Skills.skillDefs.Count} skill defs, {PhainonItems.All.Count} items, {PhainonBuffs.All.Count} buffs, " + $"{Prefabs.bodyPrefabs.Count} bodies, {Prefabs.masterPrefabs.Count} masters."); } } internal static class PluginInfo { public const string Guid = "com.Joaqi.PhainonMod"; public const string Name = "PhainonMod"; public const string Version = "1.0.4"; public const string Author = "Joaqi"; } } namespace PhainonMod.Visuals { internal sealed class BladeRibbon : MonoBehaviour { private struct Sample { internal Vector3 grip; internal Vector3 direction; internal float length; internal float time; internal float strength; } internal const string GripEntry = "SwordBase"; internal const string TipEntry = "SwordTip"; internal static float Lifetime = 0.1f; internal static float Lead = 0.15f; internal static float Trail = 0.15f; internal static float InnerFraction = 0.3f; internal static float InnerAlpha = 0.35f; internal static float SpeedLow = 6f; internal static float SpeedHigh = 20f; internal static float FadePower = 1.5f; internal static bool FlipU = false; internal static float UStart = 0.5f; internal static float VMargin = 0f; private const float StepDegrees = 4f; private const int MaxSteps = 16; private readonly List<Sample> samples = new List<Sample>(); private readonly List<Vector3> vertices = new List<Vector3>(); private readonly List<Color> colors = new List<Color>(); private readonly List<Vector2> uvs = new List<Vector2>(); private readonly List<int> triangles = new List<int>(); private Transform grip; private Transform tip; private Mesh mesh; private bool doubleSided; private bool emitting = true; private bool frozen; private float clock; internal static int Live { get; private set; } internal static BladeRibbon Spawn(Transform model, Transform gripEntry, Transform tipEntry, Material material) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown Transform val = ShownSource(gripEntry); Transform val2 = ShownSource(tipEntry); if (!Object.op_Implicit((Object)(object)model) || !Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)material)) { return null; } GameObject val3 = new GameObject("PhainonBladeRibbon") { layer = ((Component)model).gameObject.layer }; val3.transform.SetParent(model, false); MeshRenderer obj = val3.AddComponent<MeshRenderer>(); ((Renderer)obj).sharedMaterial = material; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)obj).receiveShadows = false; ((Renderer)obj).lightProbeUsage = (LightProbeUsage)0; ((Renderer)obj).reflectionProbeUsage = (ReflectionProbeUsage)0; BladeRibbon bladeRibbon = val3.AddComponent<BladeRibbon>(); bladeRibbon.grip = val; bladeRibbon.tip = val2; bladeRibbon.doubleSided = !material.HasProperty("_Cull"); bladeRibbon.mesh = new Mesh { name = "PhainonBladeRibbon" }; bladeRibbon.mesh.MarkDynamic(); val3.AddComponent<MeshFilter>().sharedMesh = bladeRibbon.mesh; return bladeRibbon; } internal static void ShownBlade(ChildLocator locator, out Transform grip, out Transform tip) { grip = ShownSource(Object.op_Implicit((Object)(object)locator) ? locator.FindChild("SwordBase") : null); tip = ShownSource(Object.op_Implicit((Object)(object)locator) ? locator.FindChild("SwordTip") : null); } private static Transform ShownSource(Transform entry) { //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) ParentConstraint val = (Object.op_Implicit((Object)(object)entry) ? ((Component)entry).GetComponent<ParentConstraint>() : null); if (!Object.op_Implicit((Object)(object)val)) { return entry; } Transform val2 = null; float num = 0f; for (int i = 0; i < val.sourceCount; i++) { ConstraintSource source = val.GetSource(i); if (Object.op_Implicit((Object)(object)((ConstraintSource)(ref source)).sourceTransform) && ((Component)((ConstraintSource)(ref source)).sourceTransform).gameObject.activeInHierarchy && ((ConstraintSource)(ref source)).weight > num) { val2 = ((ConstraintSource)(ref source)).sourceTransform; num = ((ConstraintSource)(ref source)).weight; } } if (!Object.op_Implicit((Object)(object)val2)) { return entry; } return val2; } internal void Stop() { emitting = false; } internal void SetFrozen(bool value) { frozen = value; } private void OnEnable() { Live++; } private void OnDisable() { Live--; } private void OnDestroy() { if (Object.op_Implicit((Object)(object)mesh)) { Object.Destroy((Object)(object)mesh); } } private void LateUpdate() { if (!Object.op_Implicit((Object)(object)grip) || !Object.op_Implicit((Object)(object)tip)) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } if (!frozen) { clock += Time.deltaTime; if (emitting) { AddSample(); } } while (samples.Count > 1 && clock - samples[1].time > Lifetime) { samples.RemoveAt(0); } if (!emitting && (samples.Count == 0 || clock - samples[samples.Count - 1].time > Lifetime)) { Object.Destroy((Object)(object)((Component)this).gameObject); } else { Rebuild(); } } private void AddSample() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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) Vector3 val = ((Component)this).transform.InverseTransformPoint(grip.position); Vector3 val2 = ((Component)this).transform.InverseTransformPoint(tip.position); Vector3 val3 = val2 - val; float magnitude = ((Vector3)(ref val3)).magnitude; if (!(magnitude < 0.0001f)) { float strength = 0f; if (samples.Count > 0 && Time.deltaTime > 0f) { Sample sample = samples[samples.Count - 1]; Vector3 val4 = val2 - (sample.grip + sample.direction * sample.length); float num = ((Vector3)(ref val4)).magnitude / Time.deltaTime; strength = Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(SpeedLow, SpeedHigh, num)); } samples.Add(new Sample { grip = val, direction = val3 / magnitude, length = magnitude, time = clock, strength = strength }); } } private void Rebuild() { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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_00ea: 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_00f8: Unknown result type (might be due to invalid IL or missing references) vertices.Clear(); colors.Clear(); uvs.Clear(); triangles.Clear(); int count = samples.Count; if (count >= 2) { for (int i = 0; i < count - 1; i++) { Sample sample = samples[i]; Sample sample2 = samples[i + 1]; Vector3 p = samples[Mathf.Max(i - 1, 0)].grip; Vector3 p2 = samples[Mathf.Min(i + 2, count - 1)].grip; int num = Mathf.Clamp(Mathf.CeilToInt(Vector3.Angle(sample.direction, sample2.direction) / 4f), 1, 16); for (int j = 0; j < num; j++) { float num2 = (float)j / (float)num; AddPoint(CatmullRom(p, sample.grip, sample2.grip, p2, num2), Vector3.Slerp(sample.direction, sample2.direction, num2), Mathf.Lerp(sample.length, sample2.length, num2), Mathf.Lerp(sample.time, sample2.time, num2), Mathf.Lerp(sample.strength, sample2.strength, num2)); } } Sample sample3 = samples[count - 1]; AddPoint(sample3.grip, sample3.direction, sample3.length, sample3.time, sample3.strength); for (int k = 0; k + 3 < vertices.Count; k += 2) { triangles.Add(k); triangles.Add(k + 1); triangles.Add(k + 2); triangles.Add(k + 1); triangles.Add(k + 3); triangles.Add(k + 2); if (doubleSided) { triangles.Add(k); triangles.Add(k + 2); triangles.Add(k + 1); triangles.Add(k + 1); triangles.Add(k + 2); triangles.Add(k + 3); } } } mesh.Clear(); mesh.SetVertices(vertices); mesh.SetColors(colors); mesh.SetUVs(0, uvs); mesh.SetTriangles(triangles, 0); mesh.RecalculateBounds(); } private void AddPoint(Vector3 gripPoint, Vector3 direction, float length, float time, float strength) { //IL_0053: 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_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_0087: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: 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) float num = Mathf.Clamp01((clock - time) / Lifetime); float num2 = strength * Mathf.Pow(1f - num, FadePower); float num3 = Mathf.Lerp(UStart, 1f, num); num3 = (FlipU ? (1f - num3) : num3); vertices.Add(gripPoint + direction * (length * InnerFraction)); colors.Add(new Color(1f, 1f, 1f, num2 * InnerAlpha)); uvs.Add(new Vector2(num3, VMargin)); vertices.Add(gripPoint + direction * length); colors.Add(new Color(1f, 1f, 1f, num2)); uvs.Add(new Vector2(num3, 1f - VMargin)); } private static Vector3 CatmullRom(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t) { //IL_0015: 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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_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_005a: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) float num = t * t; float num2 = num * t; return 0.5f * (2f * p1 + (p2 - p0) * t + (2f * p0 - 5f * p1 + 4f * p2 - p3) * num + (3f * p1 - p0 - 3f * p2 + p3) * num2); } } internal sealed class FxSprite { internal string name; internal Material material; internal float aspect = 1f; } internal static class BloodthornFx { private struct Tint { internal Material material; internal int property; internal Color recoloured; internal bool fades; } internal const string ChargeName = "PhainonBloodthornCharge"; internal const int AdditiveQueue = 3010; internal static float CoreScale = 1f; internal static float CoreBrightness = 0.3f; internal static float CoreOpacity = 0.4f; internal static readonly Dictionary<string, bool> CoreParts = DefaultCoreParts(); internal static float ChargeScale = 1f; internal static float ChargeIntensity = 1f; internal static float DevTimeScale = 1f; internal static float AdditiveBoost = 1f; internal static float AdditiveAlphaBoost = 0.5f; internal static float RampHotStart = 0.86f; internal static Color RampDeep = new Color(0.42f, 0.3f, 0.04f); internal static Color RampGold = new Color(1f, 0.82f, 0.32f); internal static Color RampHot = new Color(1f, 0.94f, 0.72f); internal static float ChargeLife = 0.3f; internal static int ArcCount = 4; internal static float ArcLength = 0.9f; internal static float ArcWidth = 0.2f; internal static int ArcSegments = 10; internal static float ArcJitter = 0.12f; internal static float ArcReroll = 0.035f; internal static float ArcCrawl = 0.6f; internal static float ArcTilt = 18f; internal static Color ArcTint = new Color(1f, 1f, 1f, 1f); internal static float ChargeCoreFrom = 0.3f; internal static float ChargeCoreTo = 1.3f; internal static Color ChargeCoreTint = new Color(1f, 0.97f, 0.85f, 1f); internal static Color ChargeLightColor = new Color(1f, 0.82f, 0.32f); internal static float ChargeLightIntensity = 3f; internal static float ChargeLightRange = 0.8f; internal static float BlastSwordPoint = 0.5f; internal static bool CasterFlashOn = true; internal static Color CasterFlashColor = new Color(1f, 0.92f, 0.65f); internal static float CasterFlashPeak = 0.2f; internal static float CasterFlashRampIn = 0.02f; internal static float CasterFlashHold = 0.03f; internal static float CasterFlashFade = 0.14f; internal static float CasterFlashHdr = 1f; internal static GameObject charge; internal static string summary = "not built"; internal static FxSprite core; internal static Material arcMaterial; private static readonly List<Material> windUpMaterials = new List<Material>(); private static string basisGains = "?"; private static readonly List<Tint> coreTints = new List<Tint>(); private static string coreNote = "not converted"; private static string coreDetail = "not converted"; private static string partsNote = "not set"; private static GameObject holder; private static Mesh centredQuad; private static readonly List<string> failed = new List<string>(); private static readonly string[] CoreSeeThroughMaterials = new string[1] { "matVoidCrabAntiMatterParticleDonut" }; private const string CoreShaderSource = "matVoidCrabAntiMatterParticleSphere"; private const string CoreRampName = "texRampMatterAntimatter"; private const string CoreRampAlpha = "alpha 0 below index ~0.36, 1 above (bundle dump)"; private static readonly Dictionary<string, string> CloudRemapToggles = new Dictionary<string, string>(StringComparer.Ordinal) { { "_DisableRemapOn", "DISABLEREMAP" }, { "_UseUV1On", "USE_UV1" }, { "_FadeCloseOn", "FADECLOSE" }, { "_CloudsOn", "USE_CLOUDS" }, { "_CloudOffsetOn", "CLOUDOFFSET" }, { "_VertexColorOn", "VERTEXCOLOR" }, { "_VertexAlphaOn", "VERTEXALPHA" }, { "_CalcTextureAlphaOn", "CALCTEXTUREALPHA" }, { "_VertexOffsetOn", "VERTEXOFFSET" }, { "_FresnelOn", "FRESNEL" }, { "_SkyboxOnly", "SKYBOX_ONLY" } }; private static Texture2D goldRamp; private static readonly HashSet<string> warned = new HashSet<string>(); internal const float StrokeBody = 0.3f; internal const float StrokeCore = 0.12f; internal static Mesh CentredQuad { get { if (!Object.op_Implicit((Object)(object)centredQuad)) { return centredQuad = BuildQuad("PhainonFxQuadCentred"); } return centredQuad; } } internal static Texture2D GoldRamp { get { //IL_0014: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)goldRamp)) { goldRamp = new Texture2D(256, 1, (TextureFormat)4, false) { name = "texPhainonRampBloodthornGold", wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1, hideFlags = (HideFlags)61 }; FillGoldRamp(); } return goldRamp; } } private static Dictionary<string, bool> DefaultCoreParts() { Dictionary<string, bool> dictionary = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase); string[] bloodthornCoreOff = PhainonEffects.BloodthornCoreOff; foreach (string key in bloodthornCoreOff) { dictionary[key] = false; } return dictionary; } internal static void ResetCoreParts() { CoreParts.Clear(); foreach (KeyValuePair<string, bool> item in DefaultCoreParts()) { CoreParts[item.Key] = item.Value; } } internal static bool CorePartDrawn(string childName) { bool result = true; int num = -1; foreach (KeyValuePair<string, bool> corePart in CoreParts) { if (corePart.Key.Length > num && (childName ?? "").StartsWith(corePart.Key, StringComparison.OrdinalIgnoreCase)) { num = corePart.Key.Length; result = corePart.Value; } } return result; } internal static void ApplyCoreParts(ParticleSystemRenderer[] renderers, Transform root) { foreach (ParticleSystemRenderer val in renderers) { if (Object.op_Implicit((Object)(object)val) && (Object)(object)((Component)val).transform != (Object)(object)root) { ((Renderer)val).enabled = CorePartDrawn(((Object)((Component)val).gameObject).name); } } } internal static string CorePartRules() { if (CoreParts.Count != 0) { return string.Join(", ", CoreParts.Select((KeyValuePair<string, bool> p) => "'" + p.Key + "' " + (p.Value ? "on" : "off"))); } return "none"; } internal static string CorePartsNote(GameObject clone) { if (!Object.op_Implicit((Object)(object)clone)) { return "no core clone"; } List<string> list = new List<string>(); List<string> list2 = new List<string>(); ParticleSystemRenderer[] componentsInChildren = clone.GetComponentsInChildren<ParticleSystemRenderer>(true); foreach (ParticleSystemRenderer val in componentsInChildren) { if (Object.op_Implicit((Object)(object)val) && !((Object)(object)((Component)val).transform == (Object)(object)clone.transform)) { string name = ((Object)((Component)val).gameObject).name; if (!((Component)val).gameObject.activeSelf) { list2.Add("'" + name + "'"); } else { list.Add("'" + name + "' " + (CorePartDrawn(name) ? "on" : "off")); } } } return "parts " + string.Join(", ", list) + " (rules " + CorePartRules() + ", per spawn)" + ((list2.Count > 0) ? ("; inactive in the prefab: " + string.Join(", ", list2)) : ""); } private static Mesh BuildQuad(string name) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //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_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) //IL_0063: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0112: 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_011e: 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_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) Mesh val = new Mesh(); ((Object)val).name = name; ((Object)val).hideFlags = (HideFlags)61; val.vertices = (Vector3[])(object)new Vector3[4] { new Vector3(-0.5f, -0.5f, 0f), new Vector3(0.5f, -0.5f, 0f), new Vector3(0.5f, 0.5f, 0f), new Vector3(-0.5f, 0.5f, 0f) }; val.uv = (Vector2[])(object)new Vector2[4] { new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(0f, 1f) }; val.colors = (Color[])(object)new Color[4] { Color.white, Color.white, Color.white, Color.white }; val.normals = (Vector3[])(object)new Vector3[4] { Vector3.back, Vector3.back, Vector3.back, Vector3.back }; val.triangles = new int[6] { 0, 3, 2, 0, 2, 1 }; return val; } internal static void Build() { failed.Clear(); core = Layer("charge core", () => AdditiveFrom("texPhainonFxCore", CinematicFx.FlareTexture)); arcMaterial = Layer("charge arcs", () => AdditiveFrom("texPhainonFxLine", LineTexture(64, 16)))?.material; charge = Guard("charge EffectDef", () => BuildTemplate("PhainonBloodthornCharge", ChargeLife, typeof(BloodthornChargeFx))); Guard("core parts", delegate { partsNote = InstallCoreParts(); return ""; }); Guard("core see-through", delegate { SeeThroughCore(); return ""; }); Guard("blast tints", delegate { CollectTints(coreTints, "bloodthornCore"); return ""; }); Guard("tuning", delegate { ApplyTuning(); return ""; }); if (Object.op_Implicit((Object)(object)PhainonEffects.bloodthornCore)) { Log.Info($"Effects: {((Object)PhainonEffects.bloodthornCore).name} see-through (CoreOpacity {CoreOpacity:0.##}): {coreDetail}; " + "alpha x CoreOpacity on " + FadingNames(coreTints)); } summary = "blast at the blade [core " + BlastLayer(PhainonEffects.bloodthornCore, "bloodthornCore", CoreScale) + "; " + partsNote + "]; " + string.Format("charge {0} [{1} arcs {2}, core {3}; gold ramp ", Describe(charge), ArcCount, Object.op_Implicit((Object)(object)arcMaterial) ? "on" : "off", On(core)) + $"(hot from {RampHotStart:0.##}), _Boost {AdditiveBoost:0.##}, _AlphaBoost {AdditiveAlphaBoost:0.##} (basis {basisGains})]" + ((failed.Count > 0) ? ("; failed: " + string.Join(", ", failed)) : ""); Log.Info("Effects: Bloodthorn Ferry built (" + summary + ")"); } private static T Guard<T>(string what, Func<T> build) where T : class { try { return build(); } catch (Exception ex) { failed.Add(what); Log.Warning("Effects: Bloodthorn Ferry: " + what + " threw " + ex.GetType().Name + ": " + ex.Message + "; skipped, the rest still builds"); return null; } } private static FxSprite Layer(string what, Func<FxSprite> build) { FxSprite fxSprite = Guard(what, build); if (fxSprite == null || !Object.op_Implicit((Object)(object)fxSprite.material)) { return null; } return fxSprite; } private static string On(FxSprite sprite) { if (sprite == null || !Object.op_Implicit((Object)(object)sprite.material)) { return "off"; } return "on"; } private static string Describe(GameObject prefab) { if (!Object.op_Implicit((Object)(object)prefab)) { return "none"; } return "EffectDef " + ((Object)prefab).name; } private static string BlastLayer(GameObject clone, string field, float factor) { if (!Object.op_Implicit((Object)(object)clone)) { return "off (no clone)"; } TintReport tintReport = PhainonEffects.Find(field)?.tint; int num = (from t in coreTints where t.fades select t.material).Distinct().Count(); return ((Object)clone).name + " (" + ((tintReport != null) ? (tintReport.blendedRampsKept + " own ramps kept, ") : "") + "see-through: " + coreNote + "; " + $"opacity {CoreOpacity:0.##} on {num} alpha-blended material(s); scale = radius x {factor:0.##})"; } private static void CollectTints(List<Tint> into, string field) { into.Clear(); PhainonEffects.Entry entry = PhainonEffects.Find(field); if (entry != null && Object.op_Implicit((Object)(object)entry.prefab) && entry.tint != null) { AddTints(into, entry.tint); } } private static void AddTints(List<Tint> into, TintReport report) { //IL_0064: 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) foreach (Material item in report.created) { if (!Object.op_Implicit((Object)(object)item)) { continue; } bool fades = AlphaBlended(item); string[] tintProperties = PhainonEffects.TintProperties; foreach (string text in tintProperties) { if (item.HasProperty(text)) { into.Add(new Tint { material = item, property = Shader.PropertyToID(text), recoloured = item.GetColor(text), fades = fades }); } } } } private static void ApplyTints(List<Tint> tints, float brightness, float opacity) { //IL_0032: 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_0045: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_007a: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(0f, brightness); float num2 = Mathf.Clamp01(opacity); foreach (Tint tint in tints) { if (Object.op_Implicit((Object)(object)tint.material)) { Color recoloured = tint.recoloured; tint.material.SetColor(tint.property, new Color(recoloured.r * num, recoloured.g * num, recoloured.b * num, tint.fades ? (recoloured.a * num2) : recoloured.a)); } } } private static bool AlphaBlended(Material m) { if (!BlendPair(m, "_SrcBlend", "_DstBlend")) { return BlendPair(m, "_SrcBlendFloat", "_DstBlendFloat"); } return true; } private static bool BlendPair(Material m, string src, string dst) { if (m.HasProperty(src) && m.HasProperty(dst) && Mathf.RoundToInt(m.GetFloat(src)) == 5) { return Mathf.RoundToInt(m.GetFloat(dst)) == 10; } return false; } private static string FadingNames(List<Tint> tints) { List<string> list = (from t in tints where t.fades && Object.op_Implicit((Object)(object)t.material) select ((Object)t.material).name).Distinct().ToList(); if (list.Count != 0) { return string.Format("{0} material(s): {1}", list.Count, string.Join(", ", list)); } return "none"; } private static string InstallCoreParts() { GameObject bloodthornCore = PhainonEffects.bloodthornCore; if (!Object.op_Implicit((Object)(object)bloodthornCore)) { return "no core clone"; } if (!Object.op_Implicit((Object)(object)bloodthornCore.GetComponent<BloodthornCoreParts>())) { bloodthornCore.AddComponent<BloodthornCoreParts>(); } ApplyCoreParts(bloodthornCore.GetComponentsInChildren<ParticleSystemRenderer>(true), bloodthornCore.transform); return CorePartsNote(bloodthornCore); } internal static void SeeThroughCore() { coreNote = "not converted"; coreDetail = "not converted"; PhainonEffects.Entry entry = PhainonEffects.Find("bloodthornCore"); if (entry == null || !Object.op_Implicit((Object)(object)entry.prefab) || entry.tint == null) { coreNote = (coreDetail = "no core clone"); return; } List<Material> list = entry.tint.created.Where((Material val3) => Object.op_Implicit((Object)(object)val3)).ToList(); Material val = ((IEnumerable<Material>)list).FirstOrDefault((Func<Material, bool>)((Material val3) => IsCloudRemap(val3) && ((Object)val3).name.StartsWith("matVoidCrabAntiMatterParticleSphere", StringComparison.Ordinal))) ?? ((IEnumerable<Material>)list).FirstOrDefault((Func<Material, bool>)IsCloudRemap); Shader val2; string shaderFrom; if ((Object)(object)val != (Object)null) { val2 = val.shader; shaderFrom = ((Object)val).name; } else { val2 = PhainonEffects.PlainCloudRemapShader(out var from); shaderFrom = "the plain shell basis " + from; } if (!Object.op_Implicit((Object)(object)val2)) { coreNote = (coreDetail = "no Cloud Remap shader, the donut stays opaque"); WarnOnce("no Hopoo Games/FX/Cloud Remap shader on the core or the plain shell basis; the core's donut ring stays opaque (the blast still spawns; CoreOpacity still thins its other alpha-blended materials)"); return; } List<string> list2 = new List<string>(); List<string> list3 = new List<string>(); foreach (Material m in list) { if (CoreSeeThroughMaterials.Any((string prefix) => ((Object)m).name.StartsWith(prefix, StringComparison.Ordinal))) { if ((Object)(object)m.shader == (Object)(object)val2) { list3.Add(((Object)m).name + ": already " + ((Object)val2).name); continue; } list3.Add(ToAlphaBlended(m, val2, shaderFrom, out var brief)); list2.Add(brief); } } if (list3.Count == 0) { coreNote = (coreDetail = "no donut material on the core, nothing converted"); WarnOnce("the core has no " + string.Join("/", CoreSeeThroughMaterials) + " instance; nothing converted (the blast still spawns)"); } else { coreNote = ((list2.Count > 0) ? string.Join(", ", list2) : "donut already alpha-blended"); coreDetail = string.Join("; ", list3); } } private static bool IsCloudRemap(Material m) { if (Object.op_Implicit((Object)(object)m) && Object.op_Implicit((Object)(object)m.shader)) { return ((Object)m.shader).name == "Hopoo Games/FX/Cloud Remap"; } return false; } private static string ToAlphaBlended(Material m, Shader shader, string shaderFrom, out string brief) { //IL_01e6: Unknown result type (might be due to invalid IL or missing references) string text = (Object.op_Implicit((Object)(object)m.shader) ? ((Object)m.shader).name : "no shader"); int renderQueue = m.renderQueue; string text2 = string.Join(" ", m.shaderKeywords.OrderBy<string, string>((string k) => k, StringComparer.Ordinal)); m.shader = shader; string text3 = Float(m, "_AlphaBias"); SetIfPresent(m, "_AlphaBias", 0f); SetIfPresent(m, "_SrcBlend", 5f); SetIfPresent(m, "_DstBlend", 10f); bool flag = m.HasProperty("_ZWrite"); SetIfPresent(m, "_ZWrite", 0f); m.renderQueue = 3000; foreach (KeyValuePair<string, string> cloudRemapToggle in CloudRemapToggles) { if (m.HasProperty(cloudRemapToggle.Key)) { if (m.GetFloat(cloudRemapToggle.Key) != 0f) { m.EnableKeyword(cloudRemapToggle.Value); } else { m.DisableKeyword(cloudRemapToggle.Value); } } } m.DisableKeyword("CLOUDNORMAL"); string text4 = string.Join(" ", m.shaderKeywords.OrderBy<string, string>((string k) => k, StringComparer.Ordinal)); Texture val = (m.HasProperty("_RemapTex") ? m.GetTexture("_RemapTex") : null); object obj2; if (Object.op_Implicit((Object)(object)val)) { string[] obj = new string[6] { ((Object)val).name, " (", null, null, null, null }; Texture2D val2 = (Texture2D)(object)((val is Texture2D) ? val : null); obj[2] = ((val2 != null) ? $"{val2.format}, readable {((Texture)val2).isReadable}" : ((object)val).GetType().Name); obj[3] = "; "; obj[4] = ((((Object)val).name == "texRampMatterAntimatter") ? "alpha 0 below index ~0.36, 1 above (bundle dump)" : "alpha not known for this ramp"); obj[5] = ")"; obj2 = string.Concat(obj); } else { obj2 = "no ramp"; } string text5 = (string)obj2; brief = "donut " + Short(text) + " -> " + Short(((Object)m.shader).name) + " " + Float(m, "_SrcBlend") + "/" + Float(m, "_DstBlend") + ", " + string.Format("queue {0} -> {1}, ramp {2} ", renderQueue, m.renderQueue, Object.op_Implicit((Object)(object)val) ? ((Object)val).name : "none") + ((Object.op_Implicit((Object)(object)val) && ((Object)val).name == "texRampMatterAntimatter") ? "alpha 0 below ~0.36, 1 above" : "alpha unknown"); return ((Object)m).name + ": " + text + " -> " + ((Object)m.shader).name + " (from " + shaderFrom + "), _SrcBlend " + Float(m, "_SrcBlend") + ", _DstBlend " + Float(m, "_DstBlend") + ", zWrite " + (flag ? ("_ZWrite " + Float(m, "_ZWrite")) : "0 (fixed by the shader)") + ", " + $"queue {renderQueue} -> {m.renderQueue}, keywords [{text2}] -> [{text4}], _AlphaBias {text3} -> " + Float(m, "_AlphaBias") + ", _AlphaBoost " + Float(m, "_AlphaBoost") + ", _InvFade " + Float(m, "_InvFade") + ", _Cull " + Float(m, "_Cull") + ", ramp " + text5; } private static string Short(string shaderName) { int num = shaderName.LastIndexOf('/'); if (num < 0) { return shaderName; } return shaderName.Substring(num + 1); } private static FxSprite AdditiveFrom(string name, Texture2D texture) { if (!Object.op_Implicit((Object)(object)texture)) { return null; } Material val = PhainonEffects.BuildFlareMaterial("mat" + name.Substring(3), (Texture)(object)texture, PhainonEffects.PhainonPalette); if (!Object.op_Implicit((Object)(object)val)) { WarnOnce("no plain Cloud Remap material: the wind-up's core and arcs are off"); return null; } val.renderQueue = Mathf.Max(val.renderQueue, 3010); if (windUpMaterials.Count == 0) { basisGains = "_Boost " + Float(val, "_Boost") + ", _AlphaBoost " + Float(val, "_AlphaBoost"); } if (val.HasProperty("_RemapTex")) { val.SetTexture("_RemapTex", (Texture)(object)GoldRamp); } windUpMaterials.Add(val); return new FxSprite { name = name, material = val, aspect = Aspect((Texture)(object)texture) }; } private static string Float(Material m, string property) { if (!m.HasProperty(property)) { return "none"; } return m.GetFloat(property).ToString("0.##", CultureInfo.InvariantCulture); } internal static void ApplyTuning() { FillGoldRamp(); foreach (Material windUpMaterial in windUpMaterials) { SetIfPresent(windUpMaterial, "_Boost", AdditiveBoost); SetIfPresent(windUpMaterial, "_AlphaBoost", AdditiveAlphaBoost); SetIfPresent(windUpMaterial, "_AlphaBias", 0f); } ApplyTints(coreTints, CoreBrightness, CoreOpacity); } private static void SetIfPresent(Material m, string property, float value) { if (Object.op_Implicit((Object)(object)m) && m.HasProperty(property)) { m.SetFloat(property, value); } } private static void FillGoldRamp() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00df: 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_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_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_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)goldRamp)) { float num = Mathf.Clamp(RampHotStart, 0.35f, 0.98f); float num2 = Mathf.Lerp(num, 1f, 0.55f); Color[] array = (Color[])(object)new Color[256]; for (int i = 0; i < 256; i++) { float num3 = (float)i / 255f; Color val = ((!(num3 < 0.12f)) ? ((!(num3 < 0.3f)) ? ((!(num3 < num)) ? ((!(num3 < num2)) ? Color.Lerp(RampHot, Color.white, (num3 - num2) / (1f - num2)) : Color.Lerp(RampGold, RampHot, (num3 - num) / (num2 - num))) : RampGold) : Color.Lerp(RampDeep, RampGold, (num3 - 0.12f) / 0.18f)) : Color.Lerp(new Color(0f, 0f, 0f, 0f), RampDeep, num3 / 0.12f)); val.a = ((num3 < 0.12f) ? (num3 / 0.12f) : 1f); array[i] = val; } goldRamp.SetPixels(array); goldRamp.Apply(false, false); } } private static float Aspect(Texture texture) { if (!Object.op_Implicit((Object)(object)texture) || texture.height <= 0) { return 1f; } return (float)texture.width / (float)texture.height; } private static void WarnOnce(string what) { if (warned.Add(what)) { Log.Warning("Effects: Bloodthorn Ferry: " + what); } } private static Texture2D NewTexture(string name, int width, int height) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown return new Texture2D(width, height, (TextureFormat)4, true, true) { name = name, wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)2, hideFlags = (HideFlags)61 }; } private static Texture2D Finish(Texture2D texture, float[] values) { //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) Color32[] array = (Color32[])(object)new Color32[values.Length]; for (int i = 0; i < values.Length; i++) { byte b = (byte)Mathf.RoundToInt(Mathf.Clamp01(values[i]) * 255f); array[i] = new Color32(b, b, b, b); } texture.SetPixels32(array); texture.Apply(true, true); return texture; } private static Texture2D LineTexture(int width, int height) { float[] array = new float[width * height]; for (int i = 0; i < height; i++) { float num = ((float)i + 0.5f) / (float)height; float num2 = Profile(Mathf.Abs(2f * num - 1f), 0.3f, 0.12f); for (int j = 0; j < width; j++) { array[i * width + j] = num2; } } return Finish(NewTexture("texPhainonFxLine", width, height), array); } private static float Profile(float q, float body, float core) { q = Mathf.Clamp01(q); return body * (1f - Mathf.SmoothStep(0.35f, 1f, q)) + (1f - body) * (1f - Mathf.SmoothStep(0f, core, q)); } private static GameObject BuildTemplate(string name, float life, Type driver) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_005b: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)holder)) { holder = new GameObject("PhainonBloodthornFxTemplates"); holder.SetActive(false); Object.DontDestroyOnLoad((Object)(object)holder); } GameObject val = new GameObject(name); val.transform.SetParent(holder.transform, false); EffectComponent obj = val.AddComponent<EffectComponent>(); obj.applyScale = false; obj.effectIndex = (EffectIndex)(-1); VFXAttributes obj2 = val.AddComponent<VFXAttributes>(); obj2.vfxPriority = (VFXPriority)2; obj2.vfxIntensity = (VFXIntensity)1; obj2.DoNotPool = true; val.AddComponent<DestroyOnTimer>().duration = life + 0.25f; val.AddComponent(driver); Asset.effectDefs.Add(new EffectDef(val)); PhainonEffects.AddEntry(name, name, "built in code", val, effectDef: true, $"Bloodthorn Ferry, {life:0.##} s, never pooled"); return val; } internal static void SpawnBlast(Vector3 centre, Quaternion facing, float radius, bool transmit = true) { //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) SpawnScaled(PhainonEffects.bloodthornCore, "Bloodthorn blast core", centre, facing, radius * CoreScale, transmit); } internal static void SpawnCharge(Vector3 centre, Quaternion facing, float radius, bool transmit = true) { //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) SpawnScaled(charge, "Bloodthorn charge", centre, facing, Mathf.Max(0.5f, radius), transmit); } internal static void SpawnScaled(GameObject prefab, string what, Vector3 centre, Quaternion facing, float scale, bool transmit) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown if (Object.op_Implicit((Object)(object)prefab) && !(scale <= 0f) && EffectCheck.IsRegistered(prefab, what)) { EffectManager.SpawnEffect(prefab, new EffectData { origin = centre, rotation = facing, scale = scale }, transmit); } } internal static void CasterFlash(CharacterBody body) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (!CasterFlashOn || !Object.op_Implicit((Object)(object)body)) { return; } foreach (CameraRigController readOnlyInstances in CameraRigController.readOnlyInstancesList) { if (Object.op_Implicit((Object)(object)readOnlyInstances) && (Object)(object)readOnlyInstances.targetBody == (Object)(object)body) { ScreenFlash.PlayOn(readOnlyInstances, CasterFlashColor, CasterFlashPeak, CasterFlashRampIn, CasterFlashHold, CasterFlashFade, CasterFlashHdr); } } } } internal static class BundleVisuals { internal const string SlashMuzzle = "MuzzleSlash"; internal const string FullBody = "FullBody, Override"; internal const string Gesture = "Gesture, Override"; internal const string EmptyState = "Empty"; internal const string BufferEmptyState = "BufferEmpty"; private static readonly string[] GestureLayers = new string[1] { "Gesture, Override" }; private static readonly (string state, string clip, bool gesture, bool holds)[] SkillStates = new(string, string, bool, bool)[10] { ("Slash1", "PhainonSlash1", true, false), ("Slash2", "PhainonSlash2", true, false), ("SlashBack", "PhainonSlashBack", true, false), ("Slash1Chain", "PhainonSlash1Chain", true, false), ("Sweep", "PhainonSweep", true, false), ("Dash", "PhainonDash", false, false), ("Execute", "PhainonExecute", false, false), ("TransformStart", "PhainonTransformStart", false, true), ("FormEnd", "PhainonFormEnd", false, true), ("StageEntrance", "PhainonStageEntrance", false, true) }; private static readonly (string state, string clip, bool holds)[] KhaslanaSkillStates = new(string, string, bool)[8] { ("TransformReveal", "KhaslanaTransformReveal", true), ("Bloodthorn1", "KhaslanaBloodthorn1", false), ("Bloodthorn2", "KhaslanaBloodthorn2", false), ("Soulscorch", "KhaslanaSoulscorch", false), ("FlaresArrive", "KhaslanaFlaresArrive", false), ("VerdictReady", "KhaslanaVerdictReady", true), ("VerdictLoop", "KhaslanaVerdictLoop", true), ("FinalHit", "KhaslanaFinalHit", true) }; private static readonly string[] KhaslanaBodyStates = new string[9] { "Idle", "IdleCombat", "Run", "Sprint", "Jump", "BonusJump", "AscendDescend", "Hurt1", "Hurt2" }; private static FormVisuals table; private static FormVisuals khaslanaTable; internal static IEnumerable<(string layer, string state)> ProbeStates => SkillStates.Select(((string state, string clip, bool gesture, bool holds) s) => (FullBody: "FullBody, Override", state: s.state)).Concat<(string, string)>(from s in SkillStates where s.gesture select (Gesture: "Gesture, Override", state: s.state)).Concat(new(string, string)[5] { ("FullBody, Override", "Empty"), ("Gesture, Override", "Empty"), ("FullBody, Override", "BufferEmpty"), ("Gesture, Override", "BufferEmpty"), ("Body", "IdleCombat") }); internal static IEnumerable<string> ProbeParameters => SkillStates.Select(((string state, string clip, bool gesture, bool holds) s) => RateParam(s.state)); internal static IEnumerable<(string layer, string state)> KhaslanaProbeStates => KhaslanaSkillStates.Select(((string state, string clip, bool holds) s) => (FullBody: "FullBody, Override", state: s.state)).Concat(new(string, string)[6] { ("FullBody, Override", "Empty"), ("FullBody, Override", "BufferEmpty"), ("Gesture, Override", "Empty"), ("Gesture, Override", "BufferEmpty"), ("AimPitch", "PitchControl"), ("AimYaw", "YawControl") }).Concat<(string, string)>(KhaslanaBodyStates.Select((string s) => ("Body", s: s))); internal static IEnumerable<string> KhaslanaProbeParameters => KhaslanaSkillStates.Select(((string state, string clip, bool holds) s) => RateParam(s.state)); internal static FormVisuals Table { get { if (table == null) { table = Build(); } CopyPlaceholderSounds(table); return table; } } internal static FormVisuals KhaslanaTable { get { if (khaslanaTable == null) { khaslanaTable = BuildKhaslana(); } CopyPlaceholderSounds(khaslanaTable); return khaslanaTable; } } internal static string RateParam(string state) { return state + ".playbackRate"; } private static void CopyPlaceholderSounds(FormVisuals visuals) { FormVisuals formVisuals = PlaceholderVisuals.Table; visuals.slashSwingSound = formVisuals.slashSwingSound; visuals.slashHitSound = formVisuals.slashHitSound; } private static string SoundNote() { if (!PhainonSounds.BankLoaded) { return "Merc sounds (no PhainonBank)"; } return "PhainonBank cues (Merc sounds unused)"; } private static GameObject EffectOr(GameObject clone, GameObject placeholder) { if (!Object.op_Implicit((Object)(object)clone)) { return placeholder; } return clone; } private static FormVisuals Build() { List<string> resolved = new List<string>(); List<string> missing = new List<string>(); AnimRef animRef = Skill("SlashBack"); FormVisuals formVisuals = new FormVisuals { slashHitbox = "PhSlash", sweepHitbox = "PhSweep", bloodthornHitbox = "PhSlash", soulscorchHitbox = "PhSweep", slash1 = Skill("Slash1"), slash2 = (animRef.IsValid ? animRef : Skill("Slash2")), slash1Chain = (animRef.IsValid ? Skill("Slash1Chain") : default(AnimRef)), sweep = Skill("Sweep"), dash = Skill("Dash"), execute = Skill("Execute"), transformStart = Skill("TransformStart"), formEnd = Skill("FormEnd"), stageEntrance = Skill("StageEntrance"), transformReveal = default(AnimRef), slash1Muzzle = "MuzzleSlash", slash2Muzzle = "MuzzleSlash", slashSwingEffect = EffectOr(PhainonEffects.slashSwing, PlaceholderVisuals.Table.slashSwingEffect), slashHitEffect = EffectOr(PhainonEffects.slashHit, PlaceholderVisuals.Table.slashHitEffect), slashRibbon = ((Object)(object)PhainonEffects.slashRibbon != (Object)null) }; Log.Info("Visuals: bundle rig table, skill states [" + string.Join(", ", resolved) + "]" + ((missing.Count > 0) ? (", not in animPhainon [" + string.Join(", ", missing) + "] (off)") : "") + "; release states [" + string.Join(", ", ReleaseStates(Has)) + "]; clip data " + (ClipData.Loaded ? (ClipData.Count + " clips") : "missing (fallback timings)") + "; " + (PhainonModel.HasKhaslanaRig ? "Khaslana refs on animKhaslana (KhaslanaTable)" : "Khaslana refs off (no KhaslanaRig)") + "; effects " + (formVisuals.slashRibbon ? ("blade ribbon (" + PhainonEffects.slashRibbonKind + ")") : NameOf(formVisuals.slashSwingEffect)) + "/" + NameOf(formVisuals.slashHitEffect) + ", " + SoundNote() + ", muzzle MuzzleSlash"); return formVisuals; AnimRef Skill(string state) { var (text, clip, flag, holds) = SkillStates.First(((string state, string clip, bool gesture, bool holds) s) => s.state == state); if (!Has("FullBody, Override", text)) { missing.Add(text); return default(AnimRef); } string text2 = RateParam(text); if (PhainonModel.ProbeHasParameter(text2) == false) { Log.Warning("Visuals: animPhainon has state " + text + " but no float '" + text2 + "'; playing it unscaled"); text2 = null; } string[] array = ((flag && Has("Gesture, Override", text)) ? GestureLayers : null); resolved.Add((array != null) ? (text + "(+Gesture)") : text); return new AnimRef("FullBody, Override", text, text2, array, clip, holds); } } private static string NameOf(GameObject prefab) { if (!Object.op_Implicit((Object)(object)prefab)) { return "<none>"; } return ((Object)prefab).name; } private static FormVisuals BuildKhaslana() { List<string> resolved = new List<string>(); List<string> missing = new List<string>(); AnimRef animRef = Skill("Bloodthorn1"); AnimRef animRef2 = Skill("Bloodthorn2"); FormVisuals formVisuals = new FormVisuals { slashHitbox = "PhSlash", sweepHitbox = "PhSweep", bloodthornHitbox = "PhSlash", soulscorchHitbox = "PhSweep", slash1 = animRef, slash2 = animRef2, transformReveal = Skill("TransformReveal"), bloodthorn1 = animRef, bloodthorn2 = animRef2, soulscorch = Skill("Soulscorch"), flares = Skill("FlaresArrive"), stardeath = Skill("VerdictReady"), stardeathLoop = Skill("VerdictLoop"), finalHit = Skill("FinalHit"), slash1Muzzle = "MuzzleSlash", slash2Muzzle = "MuzzleSlash", slashSwingEffect = EffectOr(PhainonEffects.khaslanaSwing, PlaceholderVisuals.Table.slashSwingEffect), slashHitEffect = EffectOr(PhainonEffects.khaslanaHit, PlaceholderVisuals.Table.slashHitEffect), slashRibbon = ((Object)(object)PhainonEffects.slashRibbon != (Object)null) }; Log.Info("Visuals: Khaslana table (animKhaslana), skill states [" + string.Join(", ", resolved) + "]" + ((missing.Count > 0) ? (", not in animKhaslana [" + string.Join(", ", missing) + "] (off)") : "") + "; release states [" + string.Join(", ", ReleaseStates(HasKhaslana)) + "]; slash1/slash2 = Bloodthorn1/Bloodthorn2; effects " + (formVisuals.slashRibbon ? ("blade ribbon (" + PhainonEffects.slashRibbonKind + ")") : NameOf(formVisuals.slashSwingEffect)) + "/" + NameOf(formVisuals.slashHitEffect) + ", " + SoundNote() + ", muzzle MuzzleSlash"); return formVisuals; AnimRef Skill(string state) { var (text, clip, flag) = KhaslanaSkillStates.First(((string state, string clip, bool holds) s) => s.state == state); if (!HasKhaslana("FullBody, Override", text)) { missing.Add(text); return default(AnimRef); } string text2 = RateParam(text); if (PhainonModel.ProbeHasKhaslanaParameter(text2) == false) { Log.Warning("Visuals: animKhaslana has state " + text + " but no float '" + text2 + "'; playing it unscaled"); text2 = null; } ClipInfo info; ClipInfo clipInfo = (ClipData.TryGet(clip, out info) ? info : null); resolved.Add(text + (flag ? "(holds)" : "") + ((clipInfo == null) ? "(no clip data)" : (clipInfo.hideWeapon ? "(weapon hide)" : ""))); return new AnimRef("FullBody, Override", text, text2, null, clip, flag); } } private static bool Has(string layer, string state) { return PhainonModel.ProbeHasState(layer, state) == true; } private static bool HasKhaslana(string layer, string state) { return PhainonModel.ProbeHasKhaslanaState(layer, state) == true; } internal static string ReleaseState(string layer) { return ReleaseState(layer, Has); } private static string ReleaseState(string layer, Func<string, string, bool> has) { if (!has(layer, "BufferEmpty")) { if (!has(layer, "Empty")) { return null; } return "Empty"; } return "BufferEmpty"; } internal static string ReleaseStateOn(Animator animator, string layerName) { int layer = (Object.op_Implicit((Object)(object)animator) ? animator.GetLayerIndex(layerName) : (-1)); if (layer < 0) { return null; } if (!HasLive("BufferEmpty")) { if (!HasLive("Empty")) { return null; } return "Empty"; } return "BufferEmpty"; bool HasLive(string state) { if (!animator.HasState(layer, Animator.StringToHash(state))) { return animator.HasState(layer, Animator.StringToHash(layerName + "." + state)); } return true; } } private static IEnumerable<string> ReleaseStates(Func<string, string, bool> has) { return new string[2] { "FullBody, Override", "Gesture, Override" }.Select((string layer) => layer + "/" + (ReleaseState(layer, has) ?? "<none>")); } } internal enum CameraAnchor { Rig, Ground } internal sealed class CameraTrack { internal string name; internal float start; internal float dt; internal CameraAnchor anchor; internal Vector3[] positions; internal Quaternion[] rotations; internal float[] fovs; internal float End => start + dt * (float)(positions.Length - 1); internal void Sample(float clipTime, out Vector3 position, out Quaternion rotation, out float fov) { //IL_004d: 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_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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) int num = positions.Length - 1; float num2 = Mathf.Clamp((clipTime - start) / dt, 0f, (float)num); int num3 = Mathf.Min((int)num2, Mathf.Max(0, num - 1)); int num4 = Mathf.Min(num3 + 1, num); float num5 = num2 - (float)num3; position = Vector3.LerpUnclamped(positions[num3], positions[num4], num5); rotation = Quaternion.SlerpUnclamped(rotations[num3], rotations[num4], num5); fov = Mathf.LerpUnclamped(fovs[num3], fovs[num4], num5); } } internal static class CameraTracks { internal const string FileName = "phainon_cameras.json"; internal const string TransformClose = "TransformClose"; internal const string TransformOrbit = "TransformOrbit"; internal const string TransformHero = "TransformHero"; internal const string FinalHitGround = "FinalHitGround"; internal const string FinalHitClose = "FinalHitClose"; internal const string FormEndFront = "FormEndFront"; private const float AuthoredStep = 1f / 30f; private static readonly Dictionary<string, CameraTrack> tracks = new Dictionary<string, CameraTrack>(StringComparer.Ordinal); internal static bool Loaded => tracks.Count > 0; internal static IEnumerable<CameraTrack> All => tracks.Values; internal static bool TryGet(string name, out CameraTrack track) { track = null; if (name != null) { return tracks.TryGetValue(name, out track); } return false; } internal static void Load() { tracks.Clear(); string path = Path.Combine(Asset.pluginDirectory ?? "", "phainon_cameras.json"); if (!File.Exists(path)) { Log.Info("Asset: no phainon_cameras.json; the transform and Final Hit keep the normal camera (run tools/anim/camtrack.py)"); return; } try { Parse(File.ReadAllText(path)); BuildFormEndFront(); List<string> list = new List<string>(); foreach (CameraTrack value in tracks.Values) { list.Add($"{value.name} {value.start:0.###}-{value.End:0.###} s ({value.positions.Length}, {value.anchor})"); } Log.Info("Asset: camera tracks " + string.Join(", ", list)); } catch (Exception ex) { tracks.Clear(); Log.Error("Asset: phainon_cameras.json could not be parsed (" + ex.GetType().Name + ": " + ex.Message + "); the cinematics keep the normal camera"); } } internal static void BuildFormEndFront() { //IL_0157: 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_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) if (!Loaded) { return; } float num = Mathf.Max(1f / 30f, CinematicFx.FormEndShotSettleAt); float num2 = Mathf.Max(num + 1f / 30f, CinematicFx.FormEndShotEndAt); float num3 = (CinematicFx.FormEndShotEndDistance - CinematicFx.FormEndShotDistance) / (num2 - num); int num4 = Mathf.CeilToInt(num2 / (1f / 30f) - 0.001f) + 1; CameraTrack cameraTrack = new CameraTrack { name = "FormEndFront", start = 0f, dt = 1f / 30f, anchor = CameraAnchor.Rig, positions = (Vector3[])(object)new Vector3[num4], rotations = (Quaternion[])(object)new Quaternion[num4], fovs = new float[num4] }; Vector3 val = default(Vector3); for (int i = 0; i < num4; i++) { float num5 = (float)i * (1f / 30f); float num6; float num7; float num8; if (num5 < num) { float u = num5 / num; num6 = Hermite(CinematicFx.FormEndShotStartDistance, CinematicFx.FormEndShotDistance, 1.5f, num3 * num, u); num7 = Hermite(CinematicFx.FormEndShotStartHeight, CinematicFx.FormEndShotHeight, 0f, 0f, u); num8 = Hermite(CinematicFx.FormEndShotStartAim, CinematicFx.FormEndShotAim, 0f, 0f, u); } else { num6 = CinematicFx.FormEndShotDistance + num3 * Mathf.Min(num5 - num, num2 - num); num7 = CinematicFx.FormEndShotHeight; num8 = CinematicFx.FormEndShotAim; } ((Vector3)(ref val))..ctor(CinematicFx.FormEndShotSide, num7, num6); Vector3 val2 = new Vector3(0f, num8, 0f) - val; cameraTrack.positions[i] = val; cameraTrack.rotations[i] = ((((Vector3)(ref val2)).sqrMagnitude > 0.0001f) ? Quaternion.LookRotation(val2, Vector3.up) : Quaternion.identity); cameraTrack.fovs[i] = CinematicFx.FormEndShotFov; } tracks["FormEndFront"] = cameraTrack; } private static float Hermite(float from, float to, float startSpeed, float endSlope, float u) { float num = u * u; float num2 = num * u; return (2f * num2 - 3f * num + 1f) * from + (num2 - 2f * num + u) * startSpeed * (to - from) + (-2f * num2 + 3f * num) * to + (num2 - num) * endSlope; } private static void Parse(string json) { //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: 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_0228: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) if (!(ClipData.MiniJson.Parse(json) is Dictionary<string, object> dictionary) || !dictionary.TryGetValue("tracks", out var value) || !(value is Dictionary<string, object> dictionary2)) { throw new FormatException("expected {\"tracks\": {...}}"); } foreach (KeyValuePair<string, object> item in dictionary2) { if (!(item.Value is Dictionary<string, object> dictionary3) || !dictionary3.TryGetValue("frames", out var value2) || !(value2 is List<object> { Count: not 0 } list)) { throw new FormatException("track " + item.Key + ": no frames"); } object value3; CameraTrack cameraTrack = new CameraTrack { name = item.Key, start = Number(dictionary3, "start"), dt = Number(dictionary3, "dt"), anchor = ((dictionary3.TryGetValue("anchor", out value3) && value3 as string == "ground") ? CameraAnchor.Ground : CameraAnchor.Rig), positions = (Vector3[])(object)new Vector3[list.Count], rotations = (Quaternion[])(object)new Quaternion[list.Count], fovs = new float[list.Count] }; if (!(cameraTrack.dt > 0f)) { throw new FormatException($"track {item.Key}: dt {cameraTrack.dt}"); } for (int i = 0; i < list.Count; i++) { if (!(list[i] is List<object> { Count: >=8 } list2)) { throw new FormatException($"track {item.Key}: frame {i} is not [x, y, z, qx, qy, qz, qw, fov]"); } cameraTrack.positions[i] = new Vector3(F(list2[0]), F(list2[1]), F(list2[2])); cameraTrack.rotations[i] = Quaternion.Normalize(new Quaternion(F(list2[3]), F(list2[4]), F(list2[5]), F(list2[6]))); cameraTrack.fovs[i] = F(list2[7]); } tracks[item.Key] = cameraTrack; } } private static float Number(Dictionary<string, object> entry, string key) { if (!entry.TryGetValue(key, out var value) || !(value is double num)) { throw new FormatException("no number '" + key + "'"); } return (float)num; } private static float F(object value) { if (!(value is double num)) { throw new FormatException($"not a number: {value}"); } return (float)num; } } internal struct ClipMark { public float time; public string tag; public ClipMark(float time, string tag) { this.time = time; this.tag = tag; } } internal struct MotionSample { public float dx; public float dz; public float yaw; public Vector3 Planar => new Vector3(dx, 0f, dz); public MotionSample(float dx, float dz, float yaw) { this.dx = dx; this.dz = dz; this.yaw = yaw; } } internal sealed class ClipMotion { public string source; public float length; public readonly List<float> times = new List<float>(); public readonly List<MotionSample> samples = new List<MotionSample>(); public Vector2 Net { get; internal set; } public MotionSample DisplacementAt(float t) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) int count = times.Count; if (count == 0) { float num = ((length > 0f) ? Mathf.Clamp01(t / length) : 1f); return new MotionSample(Net.x * num, Net.y * num, 0f); } if (t <= times[0]) { return samples[0]; } if (t >= times[count - 1]) { return samples[count - 1]; } int num2 = 0; int num3 = count - 1; while (num3 - num2 > 1) { int num4 = (num2 + num3) / 2; if (times[num4] <= t) { num2 = num4; } else { num3 = num4; } } float num5 = times[num3] - times[num2]; float num6 = ((num5 > 0f) ? ((t - times[num2]) / num5) : 0f); MotionSample motionSample = samples[num2]; MotionSample motionSample2 = samples[num3]; float yaw = ((Mathf.Abs(motionSample2.yaw - motionSample.yaw) > 180f) ? Mathf.LerpAngle(motionSample.yaw, motionSample2.yaw, num6) : Mathf.Lerp(motionSample.yaw, motionSample2.yaw, num6)); return new MotionSample(Mathf.Lerp(motionSample.dx, motionSample2.dx, num6), Mathf.Lerp(motionSample.dz, motionSample2.dz, num6), yaw); } public MotionSample Delta(float from, float to) { MotionSample motionSample = DisplacementAt(from); MotionSample motionSample2 = DisplacementAt(to); return new MotionSample(motionSample2.dx - motionSample.dx, motionSample2.dz - motionSample.dz, motionSample2.yaw - motionSample.yaw); } } internal sealed class ClipInfo { public string name; public float length; public float frameRate = 60f; public bool loop; public string source; public Vector2? trim; public readonly List<ClipMark> hits = new List<ClipMark>(); public readonly List<ClipMark> events = new List<ClipMark>(); public ClipMotion motion; public string weapon = "clip"; public bool hideWeapon => string.Equals(weapon, "hide", StringComparison.OrdinalIgnoreCase); public float HitTime(string tag, float fallback) { foreach (ClipMark hit in hits) { if (hit.tag == tag) { return hit.time; } } return fallback; } public List<float> HitTimes(string tag) { List<float> list = new List<float>(); foreach (ClipMark hit in hits) { if (hit.tag == tag) { list.Add(hit.time); } } list.Sort(); return list; } public float HitFraction(string tag, float fallbackFraction) { if (length <= 0f) { return fallbackFraction; } float num = HitTime(tag, float.NaN); if (!float.IsNaN(num)) { return Mathf.Clamp01(num / length); } return fallbackFraction; } public override string ToString() { //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(string.Format("{0}: {1:0.####} s @ {2:0} fps{3}", name, length, frameRate, loop ? ", loop" : "")); if (hits.Count > 0) { stringBuilder.Append(", hits ["); for (int i = 0; i < hits.Count; i++) { stringBuilder.Append((i > 0) ? ", " : "").Append($"{hits[i].tag} {hits[i].time:0.####}"); } stringBuilder.Append("]"); } if (events.Count > 0) { stringBuilder.Append($", {events.Count} event(s)"); } if (hideWeapon) { stringBuilder.Append(", weapon hide"); } if (motion != null) { stringBuilder.Append($", motion net ({motion.Net.x:0.###}, {motion.Net.y:0.###}) m over {motion.times.Count} frames"); } return stringBuilder.ToString(); } } internal static class ClipData { internal sealed class MiniJson { private readonly string text; private int pos; private MiniJson(string text) { this.text = text ?? ""; } internal static object Parse(string text) { MiniJson miniJson = new MiniJson(text); if (miniJson.text.Length > 0 && miniJson.text[0] == '\ufeff') { miniJson.pos = 1; } object result = miniJson.ReadValue(); miniJson.SkipWhitespace(); if (miniJson.pos != miniJson.text.Length) { throw miniJson.Error("trailing characters"); } return result; } private FormatException Error(string message) { return new FormatException($"JSON: {message} at offset {pos}"); } private void SkipWhitespace() { while (pos < text.Length && (text[pos] == ' ' || text[pos] == '\t' || text[pos] == '\n' || text[pos] == '\r')) { pos++; } } private object ReadValue() { SkipWhitespace(); if (pos >= text.Length) { throw Error("unexpected end"); } char c = text[pos]; switch (c) { case '{': return ReadObject(); case '[': return ReadArray(); case '"': return ReadString(); case 't': Expect("true"); return true; case 'f': Expect("false"); return false; case 'n': Expect("null"); return null; default: switch (c) { case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return ReadNumber(); default: switch (c) { case 'N': Expect("NaN"); return double.NaN; case 'I': Expect("Infinity"); return double.PositiveInfinity; default: throw Error($"unexpected '{c}'"); } } } } private void Expect(string word) { if (string.CompareOrdinal(text, pos, word, 0, word.Length) != 0) { throw Error("expected '" + word + "'"); } pos += word.Length; } private Dictionary<string, object> ReadObject() { Dictionary<string, object> dictionary = new Dictionary<string, object>(StringComparer.Ordinal); pos++; SkipWhitespace(); if (pos < text.Length && text[pos] == '}') { pos++; return dictionary; } while (true) { SkipWhitespace(); if (pos >= text.Length || text[pos] != '"') { throw Error("expected a key"); } string key = ReadString(); SkipWhitespace(); if (pos >= text.Length || text[pos] != ':') { throw Error("expected ':'"); } pos++; dictionary[key] = ReadValue(); SkipWhitespace(); if (pos >= text.Length) { throw Error("unterminated object"); } if (text[pos] != ',') { break; } pos++; } if (text[pos] == '}') { pos++; return dictionary; } throw Error("expected ',' or '}'"); } private List<object> ReadArray() { List<object> list = new List<object>(); pos++; SkipWhitespace(); if (pos < text.Length && text[pos] == ']') { pos++; return list; } while (true) { list.Add(ReadValue()); SkipWhitespace(); if (pos >= text.Length) { throw Error("unterminated array"); } if (text[pos] != ',') { break; } pos++; } if (text[pos] == ']') { pos++; return list; } throw Error("expected ',' or ']'"); } private string ReadString() { pos++; StringBuilder stringBuilder = new StringBuilder(); while (pos < text.Length) { char c = text[pos++]; switch (c) { case '"': return stringBuilder.ToString(); default: stringBuilder.Append(c); continue; case '\\': break; } if (pos >= text.Length) { break; } char c2 = text[pos++]; switch (c2) { case '"': stringBuilder.Append('"'); break; case '\\': stringBuilder.Append('\\'); break; case '/': stringBuilder.Append('/'); break; case 'b': stringBuilder.Append('\b'); break; case 'f': stringBuilder.Append('\f'); break; case 'n': stringBuilder.Append('\n'); break; case 'r': stringBuilder.Append('\r'); break; case 't': stringBuilder.Append('\t'); break; case 'u': { if (pos + 4 > text.Length || !int.TryParse(text.Substring(pos, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result)) { throw Error("bad \\u escape"); } stringBuilder.Append((char)result); pos += 4; break; } default: throw Error($"bad escape '\\{c2}'"); } } throw Error("unterminated string"); } private double ReadNumber() { int num = pos; if (this.text[pos] == '-') { pos++; } while (pos < this.text.Length) { char c = this.text[pos]; if ((c < '0' || c > '9') && c != '.' && c != 'e' && c != 'E' && c != '+' && c != '-') { break; } pos++; } string text = this.text.Substring(num, pos - num); if (text == "-" && string.CompareOrdinal(this.text, pos, "Infinity", 0, 8) == 0) { pos += 8; return double.NegativeInfinity; } if (!double.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { throw Error("bad number '" + text + "'"); } return result; } } internal const string AssetName = "PhainonClipData"; private static readonly Dictionary<string, ClipInfo> clips = new Dictionary<string, ClipInfo>(StringComparer.Ordinal); internal static bool Loaded { get; private set; } internal static int Count => clips.Count; internal static IEnumerable<ClipInfo> All => clips.Values; internal static bool TryGet(string clip, out ClipInfo info) { info = null; if (!string.IsNullOrEmpty(clip)) { return clips.TryGetValue(clip, out info); } return false; } internal static void Load() { clips.Clear(); Loaded = false; if (!Object.op_Implicit((Object)(object)Asset.Bundle)) { Log.Info("Asset: no phainon.bundle; no clip data (states use their fallback timings)"); return; } if (!Asset.HasBundleAsset("PhainonClipData")) { Log.Warning("Asset: no PhainonClipData in phainon.bundle (bundle older than M4); states use their fallback timings"); return; } TextAsset val = Asset.LoadBundleAsset<TextAsset>("PhainonClipData"); if (!Object.op_Implicit((Object)(object)val)) { return; } try { Parse(val.text); Loaded = true; Log.Info(string.Format("Asset: clip data {0} clips ({1})", clips.Count, string.Join(", ", clips.Keys))); } catch (Exception ex) { clips.Clear(); Log.Error("Asset: PhainonClipData could not be parsed (" + ex.GetType().Name + ": " + ex.Message + "); states use their fallback timings"); } } internal static void Parse(string json) { if (!(MiniJson.Parse(json) is Dictionary<string, object> dictionary) || !dictionary.TryGetValue("clips", out var value) || !(value is Dictionary<string, object> dictionary2)) { throw new FormatException("expected {\"clips\": {...}}"); } foreach (KeyValuePair<string, object> item in dictionary2) { if (!(item.Value is Dictionary<string, object> entry)) { throw new FormatException("clip '" + item.Key + "' is not an object"); } clips[item.Key] = ReadClip(item.Key, entry); } } private static ClipInfo ReadClip(string name, Dictionary<string, object> entry) { //IL_011b: Unknown result type (might be due to invalid IL or missing references) ClipInfo obj = new ClipInfo { name = name, length = Number(entry, "length", 0f), frameRate = Number(entry, "frameRate", 60f) }; bool flag = default(bool); int num; if (entry.TryGetValue("loop", out var value)) { if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } obj.loop = (byte)((uint)num & (flag ? 1u : 0u)) != 0; obj.source = (entry.TryGetValue("source", out var value2) ? (value2 as string) : null); obj.weapon = ((entry.TryGetValue("weapon", out var value3) && value3 is string { Length: >0 } text) ? text : "clip"); ClipInfo clipInfo = obj; if (clipInfo.length <= 0f) { throw new FormatException("clip '" + name + "' has no positive length"); } if (entry.TryGetValue("trim", out var value4) && value4 is Dictionary<string, object> obj2) { clipInfo.trim = new Vector2(Number(obj2, "start", 0f), Number(obj2, "end", 0f)); } ReadMarks(entry, "hits", clipInfo.hits, name); ReadMarks(entry, "events", clipInfo.events, name); if (entry.TryGetValue("motion", out var value5) && value5 is Dictionary<string, object> obj3) { clipInfo.motion = ReadMotion(obj3, clipInfo.length); } return clipInfo; } private static void ReadMarks(Dictionary<string, object> entry, string key, List<ClipMark> into, string clip) { if (!entry.TryGetValue(key, out var value) || !(value is List<object> list)) { return; } foreach (object item in list) { if (item is List<object> { Count: >=2 } list2 && list2[0] is double num && list2[1] is string tag) { into.Add(new ClipMark((float)num, tag)); continue; } if (item is Dictionary<string, object> dictionary && dictionary.TryGetValue("tag", out var value2) && value2 is string tag2) { into.Add(new ClipMark(Number(dictionary, "t", Number(dictionary, "time", 0f)), tag2)); continue; } throw new FormatException("clip '" + clip + "': bad " + key + " item"); } into.Sort((ClipMark a, ClipMark b) => a.time.CompareTo(b.time)); } private static ClipMotion ReadMotion(Dictionary<string, object> obj, float clipLength) { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) object value; ClipMotion clipMotion = new ClipMotion { source = (obj.TryGetValue("source", out value) ? (value as string) : null), length = Number(obj, "length", clipLength) }; if (obj.TryGetValue("net", out var value2) && value2 is List<object> { Count: >=2 } list && list[0] is double num && list[1] is double num2) { clipMotion.Net = new Vector2((float)num, (float)num2); } if (obj.TryGetValue("frames", out var value3) && value3 is List<object> list2) { List<KeyValuePair<float, MotionSample>> list3 = new List<KeyValuePair<float, MotionSample>>(list2.Count); foreach (object item in list2) { if (item is Dictionary<string, object> obj2) { list3.Add(new KeyValuePair<float, MotionSample>(Number(obj2, "t", 0f), new MotionSample(Number(obj2, "dx", 0f), Number(obj2, "dz", 0f), Number(obj2, "yaw", 0f)))); } } list3.Sort((KeyValuePair<float, MotionSample> a, KeyValuePair<float, MotionSample> b) => a.Key.CompareTo(b.Key)); foreach (KeyValuePair<float, MotionSample> item2 in list3) { clipMotion.times.Add(item2.Key); clipMotion.samples.Add(item2.Value); } if (value2 == null && clipMotion.samples.Count > 0) { MotionSample motionSample = clipMotion.samples[clipMotion.samples.Count - 1]; clipMotion.Net = new Vector2(motionSample.dx, motionSample.dz); } } return clipMotion; } private static float Number(Dictionary<string, object> obj, string key, float fallback) { if (!obj.TryGetValue(key, out var value) || !(value is double num)) { return fallback; } return (float)num; } } internal static class ClothShared { internal class Tuning { internal float damping; internal float elasticity; internal float stiffness; internal float inert; internal float endLength; internal float radius; public override string ToString() { return $"damping {damping:0.###} elasticity {elasticity:0.###} stiffness {stiffness:0.###} inert {inert:0.###} " + $"endLength {endLength:0.##} radius {radius:0.###}"; } } internal static void Write(DynamicBone bone, Tuning t, float radius) { bone.m_Damping = Mathf.Clamp01(t.damping); bone.m_Elasticity = Mathf.Clamp01(t.elasticity); bone.m_Stiffness = Mathf.Clamp01(t.stiffness); bone.m_Inert = Mathf.Clamp01(t.inert); bone.m_EndLength = Mathf.Max(0f, t.endLength); bone.m_Radius = Mathf.Max(0f, radius); } internal static DynamicBone AddChain(GameObject host, Transform chainRoot, List<DynamicBoneCollider> capsules) { DynamicBone obj = host.AddComponent<DynamicBone>(); obj.m_Root = chainRoot; obj.m_Colliders = ((capsules != null) ? new List<DynamicBoneCollider>(capsules) : new List<DynamicBoneCollider>()); obj.m_Exclusions = new List<Transform>(); return obj; } internal static List<DynamicBoneCollider> AddLegCapsules(Transform rig, Transform rootBone, (string bone, string child, float radius)[] segments, List<string> missing) { //IL_0072: 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) List<DynamicBoneCollider> list = new List<DynamicBoneCollider>(); for (int i = 0; i < segments.Length; i++) { (string bone, string child, float radius) tuple = segments[i]; string item = tuple.bone; string item2 = tuple.child; float item3 = tuple.radius; Transform val = Prefabs.FindDeep(rootBone, item); Transform val2 = (Object.op_Implicit((Object)(object)val) ? val.Find(item2) : null); if (!Object.op_Implicit((Object)(object)val2)) { missing.Add(item + "->" + item2); } else { list.Add(AddCapsule(val, val2, item3 * rig.lossyScale.x / val.lossyScale.x)); } } return list; } private static DynamicBoneCollider AddCapsule(Transform bone, Transform child, float localRadius) { //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_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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_0051: 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_0043: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) Vector3 localPosition = child.localPosition; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(Mathf.Abs(localPosition.x), Mathf.Abs(localPosition.y), Mathf.Abs(localPosition.z)); int num = ((!(val.x >= val.y) || !(val.x >= val.z)) ? ((val.y >= val.z) ? 1 : 2) : 0); DynamicBoneCollider obj = ((Component)bone).gameObject.AddComponent<DynamicBoneCollider>(); obj.m_Direction = (Direction)num; obj.m_Center = localPosition * 0.5f; obj.m_Radius = localRadius; obj.m_Height = ((Vector3)(ref val))[num] + 2f * localRadius; return obj; } internal static float Gap(Vector3 point, float particleRadius, List<DynamicBoneCollider> capsules, out string capsuleName) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) float num = float.PositiveInfinity; capsuleName = "none"; foreach (DynamicBoneCollider capsule in capsules) { CapsuleWorld(capsule, out var a, out var b, out var radius); float num2 = DistanceToSegment(point, a, b) - radius - particleRadius; if (num2 < num) { num = num2; capsuleName = ((Object)capsule).name; } } return num; } private static void CapsuleWorld(DynamicBoneCollider capsule, out Vector3 a, out Vector3 b, out float radius) { //IL_000f: 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) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected I4, but got Unknown //IL_0055: 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_005b: 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_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) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)capsule).transform; radius = capsule.m_Radius * Mathf.Abs(transform.lossyScale.x); float num = Mathf.Max(0f, capsule.m_Height * 0.5f - capsule.m_Radius); Vector3 zero = Vector3.zero; ((Vector3)(ref zero))[(int)capsule.m_Direction] = num; a = transform.TransformPoint(capsule.m_Center - zero); b = transform.TransformPoint(capsule.m_Center + zero); } private static float DistanceToSegment(Vector3 p, Vector3 a, Vector3 b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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_0038: 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) Vector3 val = b - a; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; float num = ((sqrMagnitude >