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 GojoBracken v0.2.1
BepInEx/plugins/GojoBracken/GojoBracken.dll
Decompiled 40 minutes ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Logging; using HarmonyLib; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("GojoBracken.Authoring")] [assembly: InternalsVisibleTo("Assembly-CSharp-Editor")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("GojoBracken")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Cosmetic Gojo Satoru replacement for Lethal Company's Bracken.")] [assembly: AssemblyFileVersion("0.2.0.0")] [assembly: AssemblyInformationalVersion("0.2.0+ac50210044d845f670b79eb5add9dee669831732")] [assembly: AssemblyProduct("GojoBracken")] [assembly: AssemblyTitle("GojoBracken")] [assembly: AssemblyVersion("0.2.0.0")] namespace GojoBracken; internal sealed class BrackenCosmeticController : MonoBehaviour { private BrackenV81Presentation presentation; private GameObject effects; private ParticleSystem[] particles; private float[] timeRates; private float[] distanceRates; private Burst[][] bursts; private Burst[][] scaledBursts; private Renderer[] renderers; private Vector3[] rendererScales; private bool[] visible; private MaterialPropertyBlock[] properties; private const float BalancedVoiceVolume = 0.95493f; private const float BalancedMusicVolume = 0.32137f; private float musicMaxVolume = 1f; private AudioSource voice; private AudioSource music; private float strength; private bool stopped; private bool visibleByGame = true; private int gameLayer; internal int VoiceRequests { get; private set; } internal BrackenCosmeticFrame LastFrame { get; private set; } internal Vector3 WorldPosition => effects.transform.position; internal static bool TryCreate(Transform host, Guid gameMvid, GameObject auraPrefab, AudioClip clip, float saturationAnger, float auraStrength, out BrackenCosmeticController controller, out string error, AudioClip musicClip = null, bool boostVoice = false) { //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Expected O, but got Unknown //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_021b: 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) //IL_0232: Unknown result type (might be due to invalid IL or missing references) controller = null; error = null; BrackenCosmeticController brackenCosmeticController = null; try { if ((Object)(object)host == (Object)null || !((Component)host).gameObject.activeInHierarchy) { throw new ArgumentException("A live, active visual anchor is required."); } if ((Object)(object)((Component)host).GetComponent<BrackenCosmeticController>() != (Object)null) { throw new InvalidOperationException("This anchor already has a cosmetic controller."); } BrackenV81Presentation brackenV81Presentation = new BrackenV81Presentation(gameMvid, saturationAnger); if (float.IsNaN(auraStrength) || float.IsInfinity(auraStrength) || auraStrength < 0f || auraStrength > 3f) { throw new ArgumentOutOfRangeException("auraStrength", "Aura strength must be between 0 and 3."); } if ((Object)(object)auraPrefab == (Object)null || auraPrefab.GetComponentsInChildren<ParticleSystem>(true).Length == 0) { throw new ArgumentException("An aura prefab with particles is required."); } if ((Object)(object)clip == (Object)null || clip.samples <= 0) { throw new ArgumentException("A nonempty voice clip is required."); } Transform[] componentsInChildren = auraPrefab.GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { Component[] components = ((Component)val).GetComponents<Component>(); foreach (Component val2 in components) { if (!(val2 is Transform) && !(val2 is ParticleSystem) && !(val2 is ParticleSystemRenderer) && !(val2 is MeshRenderer) && !(val2 is MeshFilter)) { throw new ArgumentException("Aura contains an unsupported or missing component on " + ((Object)val).name); } } } brackenCosmeticController = ((Component)host).gameObject.AddComponent<BrackenCosmeticController>(); brackenCosmeticController.presentation = brackenV81Presentation; brackenCosmeticController.strength = auraStrength; brackenCosmeticController.effects = new GameObject("GojoBracken cosmetics"); brackenCosmeticController.effects.transform.SetParent(host, false); brackenCosmeticController.effects.SetActive(false); GameObject val3 = Object.Instantiate<GameObject>(auraPrefab, brackenCosmeticController.effects.transform, false); val3.SetActive(true); brackenCosmeticController.particles = val3.GetComponentsInChildren<ParticleSystem>(true); brackenCosmeticController.timeRates = new float[brackenCosmeticController.particles.Length]; brackenCosmeticController.distanceRates = new float[brackenCosmeticController.particles.Length]; brackenCosmeticController.bursts = new Burst[brackenCosmeticController.particles.Length][]; brackenCosmeticController.scaledBursts = new Burst[brackenCosmeticController.particles.Length][]; for (int k = 0; k < brackenCosmeticController.particles.Length; k++) { ParticleSystem obj = brackenCosmeticController.particles[k]; MainModule main = obj.main; ((MainModule)(ref main)).playOnAwake = false; obj.Stop(false, (ParticleSystemStopBehavior)0); EmissionModule emission = obj.emission; brackenCosmeticController.timeRates[k] = ((EmissionModule)(ref emission)).rateOverTimeMultiplier; brackenCosmeticController.distanceRates[k] = ((EmissionModule)(ref emission)).rateOverDistanceMultiplier; Burst[] array = (Burst[])(object)new Burst[((EmissionModule)(ref emission)).burstCount]; ((EmissionModule)(ref emission)).GetBursts(array); brackenCosmeticController.bursts[k] = array; brackenCosmeticController.scaledBursts[k] = (Burst[])array.Clone(); } brackenCosmeticController.renderers = val3.GetComponentsInChildren<Renderer>(true); brackenCosmeticController.rendererScales = Array.ConvertAll(brackenCosmeticController.renderers, (Renderer renderer) => ((Component)renderer).transform.localScale); brackenCosmeticController.visible = Array.ConvertAll(brackenCosmeticController.renderers, (Renderer renderer) => renderer.enabled); brackenCosmeticController.properties = Array.ConvertAll(brackenCosmeticController.renderers, (Converter<Renderer, MaterialPropertyBlock>)((Renderer renderer) => new MaterialPropertyBlock())); Renderer[] array2 = brackenCosmeticController.renderers; for (int i = 0; i < array2.Length; i++) { array2[i].enabled = false; } brackenCosmeticController.voice = brackenCosmeticController.CreateAudioSource(clip, loop: false); if (boostVoice) { ((Component)brackenCosmeticController.voice).gameObject.AddComponent<GojoVoiceGain>(); brackenCosmeticController.voice.volume = 0.95493f; brackenCosmeticController.musicMaxVolume = 0.32137f; } if ((Object)(object)musicClip != (Object)null && musicClip.samples > 0) { brackenCosmeticController.music = brackenCosmeticController.CreateAudioSource(musicClip, loop: true); } brackenCosmeticController.effects.SetActive(true); controller = brackenCosmeticController; return true; } catch (Exception ex) { if ((Object)(object)brackenCosmeticController != (Object)null) { brackenCosmeticController.Shutdown(); Object.Destroy((Object)(object)brackenCosmeticController); } error = "Cosmetic attachment failed; keep vanilla Bracken visible. " + ex.Message; return false; } } private AudioSource CreateAudioSource(AudioClip clip, bool loop) { //IL_000f: 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) GameObject val = new GameObject(loop ? "Gojo aggro music" : "Gojo aggro voice"); val.transform.SetParent(effects.transform, false); AudioSource obj = val.AddComponent<AudioSource>(); obj.playOnAwake = false; obj.loop = loop; obj.clip = clip; obj.spatialBlend = 1f; obj.dopplerLevel = 0f; obj.rolloffMode = (AudioRolloffMode)0; obj.minDistance = 2f; obj.maxDistance = 25f; return obj; } internal void Apply(BrackenObservation observation, bool useDetailedAnger, float deltaTime) { //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) if (stopped || presentation == null) { return; } LastFrame = presentation.Evaluate(observation, useDetailedAnger, deltaTime); if (LastFrame.StopEffects || (Object)(object)effects == (Object)null) { Shutdown(); return; } float num = LastFrame.AuraLevel * strength; float num2 = Mathf.Clamp01((LastFrame.AuraLevel - 0.15f) / 0.85f); for (int i = 0; i < particles.Length; i++) { ParticleSystem val = particles[i]; if ((Object)(object)val == (Object)null) { Shutdown(); return; } EmissionModule emission = val.emission; ((EmissionModule)(ref emission)).rateOverTimeMultiplier = timeRates[i] * num; ((EmissionModule)(ref emission)).rateOverDistanceMultiplier = distanceRates[i] * num; Burst[] array = scaledBursts[i]; for (int j = 0; j < array.Length; j++) { ((Burst)(ref array[j])).probability = ((Burst)(ref bursts[i][j])).probability * Mathf.Clamp01(num); } ((EmissionModule)(ref emission)).SetBursts(array); if (num == 0f) { val.Stop(false, (ParticleSystemStopBehavior)0); } else if (((Component)val).gameObject.activeInHierarchy && !val.isPlaying) { val.Play(false); } } for (int k = 0; k < renderers.Length; k++) { Renderer val2 = renderers[k]; if ((Object)(object)val2 == (Object)null) { Shutdown(); return; } val2.enabled = visible[k] && num > 0f && visibleByGame; ((Component)val2).gameObject.layer = gameLayer; val2.GetPropertyBlock(properties[k]); properties[k].SetFloat("_Strength", num2); properties[k].SetFloat("_Intensity", strength); val2.SetPropertyBlock(properties[k]); } if ((Object)(object)music != (Object)null) { music.volume = num2 * musicMaxVolume; if (observation.StateIndex != 2 && music.isPlaying) { music.Stop(); } } if (LastFrame.PlayAggroVoice) { VoiceRequests++; voice.Stop(); voice.Play(); if ((Object)(object)music != (Object)null) { music.Play(); } } } internal void Shutdown() { if (stopped) { return; } stopped = true; presentation?.Reset(); if ((Object)(object)voice != (Object)null) { voice.Stop(); } if ((Object)(object)music != (Object)null) { music.Stop(); } if (particles != null) { ParticleSystem[] array = particles; foreach (ParticleSystem val in array) { if ((Object)(object)val != (Object)null) { val.Stop(false, (ParticleSystemStopBehavior)0); } } } if ((Object)(object)effects != (Object)null) { effects.SetActive(false); Object.Destroy((Object)(object)effects); } } internal void SetEffectScale(float wispScale, float flameHeightScale) { //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_004c: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) if (stopped || (Object)(object)effects == (Object)null) { return; } effects.transform.localScale = Vector3.one * wispScale; for (int i = 0; i < renderers.Length; i++) { if (renderers[i] is MeshRenderer) { Vector3 localScale = rendererScales[i]; localScale.y *= flameHeightScale / wispScale; ((Component)renderers[i]).transform.localScale = localScale; } } ParticleSystem[] array = particles; foreach (ParticleSystem obj in array) { MainModule main = obj.main; ((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)0; obj.Clear(false); } } internal void SetVisibility(BrackenVisibility visibility) { if (visibility.Layer < 0 || visibility.Layer > 31) { throw new ArgumentOutOfRangeException("visibility"); } visibleByGame = visibility.Visible; gameLayer = visibility.Layer; } private void OnDisable() { Shutdown(); } private void OnDestroy() { Shutdown(); } } internal sealed class GojoVoiceGain : MonoBehaviour { internal void OnAudioFilterRead(float[] samples, int channels) { for (int i = 0; i < samples.Length; i++) { samples[i] *= 2f; } } } internal sealed class BrackenGameBinding : MonoBehaviour { private Component enemy; private BrackenStateReader reader; private BrackenVisibilityReader visibilityReader; private PropertyInfo owner; private BrackenCosmeticController controller; private Action<string> warning; private bool ownerWarning; private bool stopped; private BrackenModelAttachment replacement; private Func<Renderer, bool> forceHidden; private Action<string> traceVisibleLayers; private bool motionLogged; private Vector3? previousVisiblePosition; private float sampledTravel; internal string ModelPoseStatus { get { if (replacement == null) { return "model disabled"; } return "fixed standing pose"; } } internal static BrackenGameBinding Attach(Component enemy, Guid gameMvid, GameObject aura, AudioClip voice, float saturation, float strength, Action<string> warning, GameObject modelPrefab = null, float modelScale = 1f, float wispScale = 1f, float flameHeightScale = 1f, Action<string> traceVisibleLayers = null, bool useV81BodyLayout = false, AudioClip music = null, bool boostVoice = false) { BrackenStateReader brackenStateReader = new BrackenStateReader(((object)enemy).GetType()); if (!brackenStateReader.TryRead(enemy, out var observation, out var error)) { throw new InvalidOperationException(error); } if (observation.Dead) { return null; } BrackenVisibilityReader brackenVisibilityReader = new BrackenVisibilityReader(((object)enemy).GetType()); if (useV81BodyLayout) { brackenVisibilityReader.SelectV81Body(enemy); } if (!brackenVisibilityReader.TryRead(enemy, out var visibility, out error, null, traceVisibleLayers)) { throw new InvalidOperationException(error); } if (!BrackenCosmeticController.TryCreate(enemy.transform, gameMvid, aura, voice, saturation, strength, out var brackenCosmeticController, out error, music, boostVoice)) { throw new InvalidOperationException(error); } BrackenGameBinding brackenGameBinding = null; BrackenModelAttachment brackenModelAttachment = null; try { if ((Object)(object)modelPrefab != (Object)null) { brackenModelAttachment = BrackenModelAttachment.Create(enemy.transform, brackenVisibilityReader.SnapshotRenderers(enemy), modelPrefab, visibility, modelScale); } if (wispScale != 1f || flameHeightScale != 1f) { brackenCosmeticController.SetEffectScale(wispScale, flameHeightScale); } brackenGameBinding = enemy.gameObject.AddComponent<BrackenGameBinding>(); brackenGameBinding.enemy = enemy; brackenGameBinding.reader = brackenStateReader; brackenGameBinding.visibilityReader = brackenVisibilityReader; brackenGameBinding.controller = brackenCosmeticController; brackenGameBinding.warning = warning; brackenGameBinding.traceVisibleLayers = traceVisibleLayers; brackenGameBinding.replacement = brackenModelAttachment; if (brackenModelAttachment != null) { brackenGameBinding.forceHidden = brackenModelAttachment.IsHiddenByGame; } PropertyInfo property = ((object)enemy).GetType().GetProperty("IsOwner", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); brackenGameBinding.owner = ((property != null && property.PropertyType == typeof(bool) && property.CanRead && property.GetIndexParameters().Length == 0) ? property : null); brackenGameBinding.Sample(0f); if (brackenGameBinding.stopped) { throw new InvalidOperationException("Initial cosmetic sample failed; vanilla visuals restored."); } return brackenGameBinding; } catch { brackenModelAttachment?.Dispose(); brackenCosmeticController.Shutdown(); Object.Destroy((Object)(object)brackenCosmeticController); if ((Object)(object)brackenGameBinding != (Object)null) { Object.Destroy((Object)(object)brackenGameBinding); } throw; } } private void LateUpdate() { Sample(Time.deltaTime); } internal void Sample(float deltaTime) { if (stopped) { return; } try { if (!((Object)(object)enemy == (Object)null) && enemy.gameObject.activeInHierarchy && !((Object)(object)controller == (Object)null)) { Component obj = enemy; Behaviour val = (Behaviour)(object)((obj is Behaviour) ? obj : null); if (val == null || val.isActiveAndEnabled) { if (!reader.TryRead(enemy, out var observation, out var error)) { throw new InvalidOperationException(error); } if (observation.Dead) { controller.Apply(observation, useDetailedAnger: false, deltaTime); Stop(); return; } if (!visibilityReader.TryRead(enemy, out var visibility, out error, forceHidden, traceVisibleLayers)) { throw new InvalidOperationException(error); } replacement?.Sync(visibility); controller.SetVisibility(visibility); bool useDetailedAnger = false; try { if (owner != null) { useDetailedAnger = (bool)owner.GetValue(enemy, null); } else { WarnOwnership(); } } catch { WarnOwnership(); } controller.Apply(observation, useDetailedAnger, deltaTime); TraceMotion(visibility.Visible, deltaTime); return; } } Stop(); } catch (Exception ex) { Stop(); warning?.Invoke("[Effects] Binding stopped; vanilla visuals restored. " + ex.Message); } } private void TraceMotion(bool visible, float deltaTime) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //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_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_0081: 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_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) if (traceVisibleLayers == null || motionLogged || replacement == null) { return; } if (!visible || deltaTime <= 0f) { previousVisiblePosition = null; sampledTravel = 0f; return; } Vector3 position = enemy.transform.position; Vector3? val = previousVisiblePosition; previousVisiblePosition = position; if (!val.HasValue) { return; } Vector3 val2 = Vector3.ProjectOnPlane(position - val.Value, Vector3.up); float magnitude = ((Vector3)(ref val2)).magnitude; if (magnitude > 0.75f) { sampledTravel = 0f; return; } sampledTravel += magnitude; if (!(sampledTravel < 0.25f)) { motionLogged = true; traceVisibleLayers(FormattableString.Invariant($"[Effects] Motion sample: Bracken id={((Object)enemy).GetInstanceID()}, horizontal travel={sampledTravel:F3} m, model anchor offset={Vector3.Distance(position, replacement.WorldPosition):F3} m, aura anchor offset={Vector3.Distance(position, controller.WorldPosition):F3} m.")); } } private void WarnOwnership() { if (!ownerWarning) { ownerWarning = true; warning?.Invoke("[Effects] Ownership unavailable; using phase approximation for this Bracken."); } } internal void Stop() { if (!stopped) { stopped = true; replacement?.Dispose(); if ((Object)(object)controller != (Object)null) { controller.Shutdown(); Object.Destroy((Object)(object)controller); } } } private void OnDisable() { Stop(); } private void OnDestroy() { Stop(); } } internal sealed class BrackenModelAttachment : IDisposable { private readonly Dictionary<Renderer, bool> originalMasks = new Dictionary<Renderer, bool>(); private GameObject root; private Renderer[] renderers; private bool[] authoredVisible; private bool disposed; private bool committed; internal Vector3 WorldPosition => root.transform.position; internal static BrackenModelAttachment Create(Transform host, Renderer[] originals, GameObject prefab, BrackenVisibility visibility, float modelScale = 1f) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)host == (Object)null || originals == null || originals.Length == 0) { throw new ArgumentException("A live anchor and explicit vanilla body renderers are required."); } Validate(prefab); BrackenModelAttachment brackenModelAttachment = new BrackenModelAttachment(); try { foreach (Renderer val in originals) { if ((Object)(object)val == (Object)null || !((Component)val).transform.IsChildOf(host)) { throw new ArgumentException("A vanilla body renderer is missing or outside the enemy hierarchy."); } brackenModelAttachment.originalMasks.Add(val, val.forceRenderingOff); } brackenModelAttachment.root = new GameObject("GojoBracken model"); brackenModelAttachment.root.SetActive(false); brackenModelAttachment.root.transform.SetParent(host, false); brackenModelAttachment.root.transform.localScale = Vector3.one * modelScale; GameObject val2 = Object.Instantiate<GameObject>(prefab, brackenModelAttachment.root.transform, false); val2.SetActive(true); UseStandingPose(brackenModelAttachment.root.transform); brackenModelAttachment.renderers = val2.GetComponentsInChildren<Renderer>(true); brackenModelAttachment.authoredVisible = Array.ConvertAll(brackenModelAttachment.renderers, (Renderer renderer) => renderer.enabled); brackenModelAttachment.Sync(visibility); brackenModelAttachment.root.SetActive(true); brackenModelAttachment.committed = true; return brackenModelAttachment; } catch { brackenModelAttachment.Dispose(); throw; } } internal static void Validate(GameObject prefab) { if ((Object)(object)prefab == (Object)null || !prefab.activeSelf) { throw new ArgumentException("The Gojo model prefab is missing or inactive."); } Transform[] componentsInChildren = prefab.GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { Component[] components = ((Component)val).GetComponents<Component>(); foreach (Component val2 in components) { if (!(val2 is Transform) && !(val2 is Animator) && !(val2 is SkinnedMeshRenderer) && !(val2 is MeshRenderer) && !(val2 is MeshFilter)) { throw new ArgumentException("Gojo model contains a missing or unsupported component: " + ((Object)val).name); } } } SkinnedMeshRenderer[] componentsInChildren2 = prefab.GetComponentsInChildren<SkinnedMeshRenderer>(true); if (componentsInChildren2.Length == 0) { throw new ArgumentException("Gojo model requires a skinned mesh."); } SkinnedMeshRenderer[] array = componentsInChildren2; foreach (SkinnedMeshRenderer val3 in array) { if ((Object)(object)val3.sharedMesh == (Object)null || val3.sharedMesh.vertexCount == 0 || val3.bones.Length == 0 || val3.bones.Length != val3.sharedMesh.bindposes.Length) { throw new ArgumentException("Gojo skin mesh/bind poses are incomplete."); } componentsInChildren = val3.bones; foreach (Transform val4 in componentsInChildren) { if ((Object)(object)val4 == (Object)null || !val4.IsChildOf(prefab.transform)) { throw new ArgumentException("Gojo skin has a missing or external bone."); } } } Animator[] componentsInChildren3 = prefab.GetComponentsInChildren<Animator>(true); if (componentsInChildren3.Length == 0) { throw new ArgumentException("Gojo model requires an Animator."); } Animator[] array2 = componentsInChildren3; foreach (Animator obj in array2) { if ((Object)(object)obj.runtimeAnimatorController == (Object)null) { throw new ArgumentException("Gojo Animator has no controller."); } if (obj.runtimeAnimatorController.animationClips.Length == 0) { throw new ArgumentException("Gojo Animator has no clips."); } AnimationClip[] animationClips = obj.runtimeAnimatorController.animationClips; foreach (AnimationClip val5 in animationClips) { if ((Object)(object)val5 == (Object)null || val5.events.Length != 0) { throw new ArgumentException("Cosmetic model clips must exist and contain no animation events."); } } } MeshFilter[] componentsInChildren4 = prefab.GetComponentsInChildren<MeshFilter>(true); foreach (MeshFilter val6 in componentsInChildren4) { if ((Object)(object)val6.sharedMesh == (Object)null || val6.sharedMesh.vertexCount == 0) { throw new ArgumentException("Gojo model has an empty static mesh."); } } bool flag = false; Renderer[] componentsInChildren5 = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val7 in componentsInChildren5) { if (val7.sharedMaterials.Length == 0) { throw new ArgumentException("Gojo renderer has no materials."); } Material[] sharedMaterials = val7.sharedMaterials; foreach (Material val8 in sharedMaterials) { if ((Object)(object)val8 == (Object)null || (Object)(object)val8.shader == (Object)null || !val8.shader.isSupported || ((Object)val8.shader).name == "Hidden/InternalErrorShader") { throw new ArgumentException("Gojo model has a missing or unsupported material/shader."); } } bool flag2 = true; Transform val9 = ((Component)val7).transform; while ((Object)(object)val9 != (Object)null && (Object)(object)val9 != (Object)(object)prefab.transform.parent) { flag2 &= ((Component)val9).gameObject.activeSelf; val9 = val9.parent; } flag |= flag2 && val7.enabled && !val7.forceRenderingOff; } if (!flag) { throw new ArgumentException("Gojo model has no drawable renderer."); } } internal bool IsHiddenByGame(Renderer renderer) { if (disposed || !originalMasks.TryGetValue(renderer, out var value)) { throw new InvalidOperationException("The vanilla body renderer set changed during model attachment."); } return value; } internal void Sync(BrackenVisibility visibility) { if (disposed || (Object)(object)root == (Object)null || (committed && !root.activeSelf)) { throw new InvalidOperationException("The Gojo visual was removed or disabled."); } Renderer[] array = renderers; for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] == (Object)null) { throw new InvalidOperationException("A Gojo renderer was removed."); } } for (int j = 0; j < renderers.Length; j++) { renderers[j].enabled = authoredVisible[j] && visibility.Visible; ((Component)renderers[j]).gameObject.layer = visibility.Layer; } foreach (Renderer key in originalMasks.Keys) { if ((Object)(object)key == (Object)null) { throw new InvalidOperationException("A vanilla body renderer was removed."); } key.forceRenderingOff = true; } } internal static void UseStandingPose(Transform visual) { //IL_00eb: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: 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_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_014c: 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_0150: 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) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) Animator[] componentsInChildren = ((Component)visual).GetComponentsInChildren<Animator>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = false; } Transform[] componentsInChildren2 = ((Component)visual).GetComponentsInChildren<Transform>(true); Transform val = Array.Find(componentsInChildren2, (Transform bone) => ((Object)bone).name == "leftFoot"); Transform val2 = Array.Find(componentsInChildren2, (Transform bone) => ((Object)bone).name == "rightFoot"); Transform val3 = Array.Find(componentsInChildren2, (Transform bone) => ((Object)bone).name == "leftFootToe"); Transform val4 = Array.Find(componentsInChildren2, (Transform bone) => ((Object)bone).name == "rightFootToe"); if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null) && !((Object)(object)val3 == (Object)null) && !((Object)(object)val4 == (Object)null)) { Vector3 val5 = Vector3.ProjectOnPlane(val3.position - val.position + val4.position - val2.position, Vector3.up); Vector3 val6 = Vector3.ProjectOnPlane(visual.forward, Vector3.up); if (((Vector3)(ref val5)).sqrMagnitude > 0.0001f && ((Vector3)(ref val6)).sqrMagnitude > 0.0001f) { visual.rotation = Quaternion.AngleAxis(Vector3.SignedAngle(val5, val6, Vector3.up), Vector3.up) * visual.rotation; } } } public void Dispose() { if (disposed) { return; } disposed = true; if ((Object)(object)root != (Object)null) { root.SetActive(false); Object.Destroy((Object)(object)root); } foreach (KeyValuePair<Renderer, bool> originalMask in originalMasks) { if ((Object)(object)originalMask.Key != (Object)null) { originalMask.Key.forceRenderingOff = originalMask.Value; } } originalMasks.Clear(); } } internal sealed class BrackenRigReport { private readonly Type enemyType; private readonly string directory; private readonly string pluginVersion; private readonly Action<string> info; private readonly Action<string> warning; private float nextAttempt; private int attempts; private bool finished; internal BrackenRigReport(Type enemyType, string directory, string pluginVersion, Action<string> info, Action<string> warning) { this.enemyType = enemyType; this.directory = directory; this.pluginVersion = pluginVersion; this.info = info; this.warning = warning; if (enemyType == null || !typeof(Component).IsAssignableFrom(enemyType)) { finished = true; warning("[RigReport] Bracken component type unavailable; no report was exported."); } else { info("[RigReport] Looking for an already-loaded Bracken prefab for up to two minutes. No enemy will be spawned."); } } internal void Update(float now) { //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) if (finished || now < nextAttempt) { return; } nextAttempt = now + 5f; attempts++; try { Object[] array = Resources.FindObjectsOfTypeAll(enemyType); foreach (Object obj in array) { Component val = (Component)(object)((obj is Component) ? obj : null); if (!((Object)(object)val == (Object)null)) { Scene scene = val.gameObject.scene; if (!((Scene)(ref scene)).IsValid()) { string contents = Describe(val, pluginVersion); Directory.CreateDirectory(directory); string path = "bracken-rig-" + DateTime.UtcNow.ToString("yyyyMMdd-HHmmss", CultureInfo.InvariantCulture) + "-" + Guid.NewGuid().ToString("N").Substring(0, 8) + ".txt"; string text = Path.Combine(directory, path); File.WriteAllText(text, contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); finished = true; info("[RigReport] Exported loaded prefab report: " + text); return; } } } if (attempts == 1 || attempts % 5 == 0) { info("[RigReport] Scan " + attempts + "/24 complete; no loaded prefab asset found."); } if (attempts >= 24) { finished = true; warning("[RigReport] No loaded Bracken prefab was found. No report was exported; do not search for an enemy. Return this message for the next inspection approach."); } } catch (Exception ex) { finished = true; warning("[RigReport] Export stopped after " + ex.GetType().Name + ": " + ex.Message); } } internal void Cancel(string reason) { if (!finished) { finished = true; warning("[RigReport] Search cancelled after " + attempts + "/24 scans: " + reason + ". No report was exported."); } } internal static string Describe(Component enemy, string version) { //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_0764: Unknown result type (might be due to invalid IL or missing references) //IL_0769: Unknown result type (might be due to invalid IL or missing references) Transform transform = enemy.transform; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("GojoBracken loaded-prefab rig report; schema=1"); stringBuilder.AppendLine("plugin=" + Clean(version) + "; unity=" + Application.unityVersion + "; application=" + Clean(Application.version)); stringBuilder.AppendLine("utc=" + DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture)); stringBuilder.AppendLine("source=loaded prefab asset; not a spawned enemy or an observed animation pose"); stringBuilder.AppendLine("component=" + ((object)enemy).GetType().FullName + "; gameAssemblyMvid=" + ((object)enemy).GetType().Module.ModuleVersionId); RenderPipelineAsset currentRenderPipeline = GraphicsSettings.currentRenderPipeline; stringBuilder.AppendLine("pipeline=" + (((Object)(object)currentRenderPipeline == (Object)null) ? "<null: built-in or not initialized>" : (((object)currentRenderPipeline).GetType().FullName + "; assemblyVersion=" + ((object)currentRenderPipeline).GetType().Assembly.GetName().Version))); FieldInfo fieldInfo = FindField(((object)enemy).GetType(), "angerMeter"); stringBuilder.AppendLine("angerFieldType=" + ((fieldInfo == null) ? "<unavailable>" : fieldInfo.FieldType.FullName) + "; replication and authoritative range are NOT established by this report"); stringBuilder.AppendLine(); stringBuilder.AppendLine("AUTHORED STATE LABELS (not verified phase meanings)"); IEnumerable enumerable = ReadField(enemy, "enemyBehaviourStates") as IEnumerable; int num = 0; if (enumerable != null) { foreach (object item in enumerable) { stringBuilder.AppendLine(num++ + ": " + Clean(ReadField(item, "name"))); } } if (num == 0) { stringBuilder.AppendLine("<unavailable>"); } stringBuilder.AppendLine(); stringBuilder.AppendLine("TRANSFORMS (prefab-local TRS, sibling-indexed paths)"); Transform[] componentsInChildren = ((Component)transform).GetComponentsInChildren<Transform>(true); for (int i = 0; i < Math.Min(componentsInChildren.Length, 512); i++) { Transform val = componentsInChildren[i]; Quaternion localRotation = val.localRotation; stringBuilder.AppendLine(PathOf(transform, val) + "; position=" + V(val.localPosition) + "; rotation=(" + F(localRotation.x) + "," + F(localRotation.y) + "," + F(localRotation.z) + "," + F(localRotation.w) + "); scale=" + V(val.localScale) + "; activeSelf=" + ((Component)val).gameObject.activeSelf); } if (componentsInChildren.Length > 512) { stringBuilder.AppendLine("<hierarchy truncated at 512 transforms>"); } stringBuilder.AppendLine(); stringBuilder.AppendLine("RENDERERS AND BONE REFERENCES (no mesh/texture data exported)"); Renderer[] componentsInChildren2 = ((Component)transform).GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren2) { stringBuilder.AppendLine(PathOf(transform, ((Component)val2).transform) + "; type=" + ((object)val2).GetType().Name); Material[] sharedMaterials = val2.sharedMaterials; foreach (Material val3 in sharedMaterials) { stringBuilder.AppendLine(" material=" + (((Object)(object)val3 == (Object)null) ? "<missing>" : Clean(((Object)val3).name)) + "; shader=" + (((Object)(object)val3 == (Object)null || (Object)(object)val3.shader == (Object)null) ? "<missing>" : Clean(((Object)val3.shader).name))); } SkinnedMeshRenderer val4 = (SkinnedMeshRenderer)(object)((val2 is SkinnedMeshRenderer) ? val2 : null); if (!((Object)(object)val4 == (Object)null)) { stringBuilder.AppendLine(" rootBone=" + PathOf(transform, val4.rootBone) + "; vertexCount=" + (((Object)(object)val4.sharedMesh == (Object)null) ? "<missing>" : val4.sharedMesh.vertexCount.ToString(CultureInfo.InvariantCulture))); Transform[] bones = val4.bones; for (int l = 0; l < bones.Length; l++) { stringBuilder.AppendLine(" bone[" + l + "]=" + PathOf(transform, bones[l])); } } } stringBuilder.AppendLine(); stringBuilder.AppendLine("ANIMATORS (controller metadata only; no animation is played)"); Animator[] componentsInChildren3 = ((Component)transform).GetComponentsInChildren<Animator>(true); foreach (Animator val5 in componentsInChildren3) { stringBuilder.AppendLine(PathOf(transform, ((Component)val5).transform) + "; enabled=" + ((Behaviour)val5).enabled + "; applyRootMotion=" + val5.applyRootMotion + "; isInitialized=" + val5.isInitialized); Avatar avatar = val5.avatar; stringBuilder.AppendLine(" avatar=" + (((Object)(object)avatar == (Object)null) ? "<none>" : (Clean(((Object)avatar).name) + "; valid=" + avatar.isValid + "; human=" + avatar.isHuman))); RuntimeAnimatorController runtimeAnimatorController = val5.runtimeAnimatorController; stringBuilder.AppendLine(" controller=" + (((Object)(object)runtimeAnimatorController == (Object)null) ? "<none>" : Clean(((Object)runtimeAnimatorController).name))); if ((Object)(object)runtimeAnimatorController == (Object)null) { continue; } AnimationClip[] animationClips = runtimeAnimatorController.animationClips; foreach (AnimationClip val6 in animationClips) { stringBuilder.AppendLine(" clip=" + (((Object)(object)val6 == (Object)null) ? "<missing>" : (Clean(((Object)val6).name) + "; seconds=" + F(val6.length) + "; humanMotion=" + val6.humanMotion + "; loop=" + ((Motion)val6).isLooping))); } if (!val5.isInitialized) { stringBuilder.AppendLine(" parameters=<unavailable: prefab Animator not initialized; no rebind or playback attempted>"); continue; } try { AnimatorControllerParameter[] parameters = val5.parameters; stringBuilder.AppendLine(" parameterCount=" + parameters.Length + "; prefab metadata may be unavailable before initialization"); AnimatorControllerParameter[] array = parameters; foreach (AnimatorControllerParameter val7 in array) { stringBuilder.AppendLine(" parameter=" + Clean(val7.name) + "; type=" + ((object)val7.type/*cast due to .constrained prefix*/).ToString()); } } catch (Exception ex) { stringBuilder.AppendLine(" parameters=<unavailable:" + ex.GetType().Name + ">"); } } return stringBuilder.ToString(); } private static FieldInfo FindField(Type type, string name) { while (type != null) { FieldInfo field = type.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field; } type = type.BaseType; } return null; } private static object ReadField(object target, string name) { if (target != null) { return FindField(target.GetType(), name)?.GetValue(target); } return null; } private static string PathOf(Transform root, Transform node) { if ((Object)(object)node == (Object)null) { return "<missing>"; } if ((Object)(object)node == (Object)(object)root) { return "."; } if (!node.IsChildOf(root)) { return "<outside-prefab>/" + Clean(((Object)node).name); } string text = ""; while ((Object)(object)node != (Object)(object)root) { text = "/" + Clean(((Object)node).name) + "[" + node.GetSiblingIndex() + "]" + text; node = node.parent; } return "." + text; } private static string Clean(object value) { if (value != null) { return Convert.ToString(value, CultureInfo.InvariantCulture).Replace("\\", "\\\\").Replace("\r", "\\r") .Replace("\n", "\\n"); } return "<unavailable>"; } private static string F(float value) { return value.ToString("R", CultureInfo.InvariantCulture); } private static string V(Vector3 value) { //IL_0010: 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_003c: Unknown result type (might be due to invalid IL or missing references) return "(" + F(value.x) + "," + F(value.y) + "," + F(value.z) + ")"; } } internal readonly struct BrackenVisibility { internal readonly bool Visible; internal readonly int Layer; internal BrackenVisibility(bool visible, int layer) { Visible = visible; Layer = layer; } } internal sealed class BrackenVisibilityReader { private readonly FieldInfo skins; private readonly FieldInfo meshes; private Renderer[] originalLayout; private Renderer[] selectedBody; private Transform modelRoot; private Renderer particleCollision; internal BrackenVisibilityReader(Type type) { skins = Bind(type, "skinnedMeshRenderers", typeof(SkinnedMeshRenderer[])); meshes = Bind(type, "meshRenderers", typeof(MeshRenderer[])); } internal bool IsReady(Component enemy) { if (skins == null || meshes == null) { return true; } if (skins.GetValue(enemy) != null) { return meshes.GetValue(enemy) != null; } return false; } internal void SelectV81Body(Component enemy) { if (!IsReady(enemy) || skins == null || meshes == null) { throw new InvalidOperationException("Bracken renderer arrays are unavailable."); } Renderer[] array = SnapshotRenderers(enemy); List<Renderer> list = new List<Renderer>(); HashSet<Renderer> hashSet = new HashSet<Renderer>(); Transform val = null; bool flag = false; Renderer val2 = null; Renderer[] array2 = array; foreach (Renderer val3 in array2) { if ((Object)(object)val3 == (Object)null || !((Component)val3).transform.IsChildOf(enemy.transform) || !hashSet.Add(val3)) { throw new InvalidOperationException("Unexpected cached renderer reference in the v81 Bracken layout."); } int layer = ((Component)val3).gameObject.layer; if ((layer == 22 && ((Object)val3).name == "ScanNode") || (layer == 14 && ((Object)val3).name == "MapDot (2)")) { continue; } if (IsParticleCollision(val3)) { if ((Object)(object)val2 != (Object)null) { throw new InvalidOperationException("Multiple ParticleCollision renderers in the v81 Bracken layout."); } val2 = val3; continue; } Transform parent = ((Component)val3).transform.parent; while ((Object)(object)parent != (Object)null && (Object)(object)parent != (Object)(object)enemy.transform && ((Object)parent).name != "FlowermanModel") { parent = parent.parent; } if (layer != 19 || (Object)(object)parent == (Object)null || (Object)(object)parent == (Object)(object)enemy.transform || ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)parent)) { throw new InvalidOperationException("Unexpected v81 Bracken renderer: " + DescribeRenderer(val3)); } val = parent; flag |= ((Object)val3).name == "LOD1"; list.Add(val3); } if (!flag || list.Count == 0) { throw new InvalidOperationException("No v81 Bracken body with LOD1 under FlowermanModel on layer 19."); } if ((Object)(object)val2 != (Object)null && (Object)(object)((Component)val2).transform.parent.parent != (Object)(object)val) { throw new InvalidOperationException("ParticleCollision belongs to a different model: " + DescribeRenderer(val2)); } particleCollision = val2; originalLayout = array; selectedBody = list.ToArray(); modelRoot = val; } private static bool IsParticleCollision(Renderer renderer) { if (!(renderer is MeshRenderer) || renderer.enabled || ((Component)renderer).gameObject.layer != 15 || ((Object)renderer).name != "ParticleCollision") { return false; } Transform parent = ((Component)renderer).transform.parent; if ((Object)(object)parent != (Object)null && ((Object)parent).name == "AnimContainer" && (Object)(object)parent.parent != (Object)null) { return ((Object)parent.parent).name == "FlowermanModel"; } return false; } internal Renderer[] SnapshotRenderers(Component enemy) { if (selectedBody != null) { return selectedBody; } SkinnedMeshRenderer[] array = (SkinnedMeshRenderer[])skins.GetValue(enemy); MeshRenderer[] array2 = (MeshRenderer[])meshes.GetValue(enemy); Renderer[] array3 = (Renderer[])(object)new Renderer[array.Length + array2.Length]; Array.Copy(array, 0, array3, 0, array.Length); Array.Copy(array2, 0, array3, array.Length, array2.Length); return array3; } internal bool TryRead(Component enemy, out BrackenVisibility visibility, out string error, Func<Renderer, bool> forceHidden = null, Action<string> traceVisibleLayers = null) { visibility = default(BrackenVisibility); error = null; try { if ((Object)(object)enemy == (Object)null || skins == null || meshes == null) { throw new InvalidOperationException("Bracken renderer fields are missing or have unexpected types."); } SkinnedMeshRenderer[] array = skins.GetValue(enemy) as SkinnedMeshRenderer[]; MeshRenderer[] array2 = meshes.GetValue(enemy) as MeshRenderer[]; if (array == null || array2 == null || array.Length + array2.Length == 0) { throw new InvalidOperationException("Bracken body renderer arrays are not initialized or empty."); } bool visible = false; bool mixed = false; int layer = -1; int fallbackLayer = -1; if (selectedBody != null) { CheckLayout(array, array2, enemy.transform); Accumulate(selectedBody, enemy.transform, forceHidden, ref visible, ref layer, ref fallbackLayer, ref mixed); } else { Renderer[] array3 = (Renderer[])(object)array; Accumulate(array3, enemy.transform, forceHidden, ref visible, ref layer, ref fallbackLayer, ref mixed); array3 = (Renderer[])(object)array2; Accumulate(array3, enemy.transform, forceHidden, ref visible, ref layer, ref fallbackLayer, ref mixed); } if (mixed) { if (traceVisibleLayers != null) { if (selectedBody != null) { TraceVisibleLayers(selectedBody, enemy, forceHidden, traceVisibleLayers); } else { Renderer[] array3 = (Renderer[])(object)array; TraceVisibleLayers(array3, enemy, forceHidden, traceVisibleLayers); array3 = (Renderer[])(object)array2; TraceVisibleLayers(array3, enemy, forceHidden, traceVisibleLayers); } } throw new InvalidOperationException("Visible Bracken body renderers use mixed layers; no safe single aura layer."); } visibility = new BrackenVisibility(visible, visible ? layer : fallbackLayer); return true; } catch (Exception ex) { error = "Bracken visibility unavailable: " + ex.Message; return false; } } private void CheckLayout(SkinnedMeshRenderer[] skinArray, MeshRenderer[] meshArray, Transform enemy) { if (skinArray.Length + meshArray.Length != originalLayout.Length || (Object)(object)modelRoot == (Object)null || !modelRoot.IsChildOf(enemy) || ((Object)modelRoot).name != "FlowermanModel") { throw new InvalidOperationException("The v81 Bracken renderer layout changed after attachment."); } for (int i = 0; i < skinArray.Length; i++) { if ((object)skinArray[i] != originalLayout[i]) { throw new InvalidOperationException("The v81 Bracken skinned renderer list changed after attachment."); } } for (int j = 0; j < meshArray.Length; j++) { if ((object)meshArray[j] != originalLayout[skinArray.Length + j]) { throw new InvalidOperationException("The v81 Bracken mesh renderer list changed after attachment."); } } if ((Object)(object)particleCollision != (Object)null && (!IsParticleCollision(particleCollision) || (Object)(object)((Component)particleCollision).transform.parent.parent != (Object)(object)modelRoot)) { throw new InvalidOperationException("The exempt ParticleCollision renderer changed: " + DescribeRenderer(particleCollision)); } Renderer[] array = selectedBody; foreach (Renderer val in array) { if ((Object)(object)val == (Object)null || !((Component)val).transform.IsChildOf(modelRoot) || (((Component)val).gameObject.layer != 19 && ((Component)val).gameObject.layer != 23)) { throw new InvalidOperationException("A selected Bracken renderer changed hierarchy or moved to an unexpected layer."); } } } private static void Accumulate(Renderer[] group, Transform enemy, Func<Renderer, bool> forceHidden, ref bool visible, ref int layer, ref int fallbackLayer, ref bool mixed) { foreach (Renderer val in group) { if ((Object)(object)val == (Object)null || !((Component)val).transform.IsChildOf(enemy)) { throw new InvalidOperationException("Bracken body renderer is missing or outside its hierarchy."); } if (fallbackLayer < 0) { fallbackLayer = ((Component)val).gameObject.layer; } if (IsVisible(val, forceHidden)) { int layer2 = ((Component)val).gameObject.layer; mixed |= layer >= 0 && layer != layer2; layer = layer2; visible = true; } } } private static bool IsVisible(Renderer renderer, Func<Renderer, bool> forceHidden) { bool flag = forceHidden?.Invoke(renderer) ?? renderer.forceRenderingOff; if (renderer.enabled && ((Component)renderer).gameObject.activeInHierarchy) { return !flag; } return false; } private static void TraceVisibleLayers(Renderer[] group, Component enemy, Func<Renderer, bool> forceHidden, Action<string> trace) { foreach (Renderer renderer in group) { if (IsVisible(renderer, forceHidden)) { trace($"[Effects] Visible body renderer: Bracken id={((Object)enemy).GetInstanceID()}, {DescribeRenderer(renderer)}"); } } } private static string DescribeRenderer(Renderer renderer) { Stack<string> stack = new Stack<string>(); Transform val = ((Component)renderer).transform; while ((Object)(object)val != (Object)null) { stack.Push($"{((Object)val).name}[{val.GetSiblingIndex()}]"); val = val.parent; } int layer = ((Component)renderer).gameObject.layer; string text = LayerMask.LayerToName(layer); return string.Format("type={0}, layer={1} ({2}), ", ((object)renderer).GetType().Name, layer, string.IsNullOrEmpty(text) ? "unnamed" : text) + string.Format("path={0}, enabled={1}, active={2}.", string.Join("/", stack), renderer.enabled, ((Component)renderer).gameObject.activeInHierarchy); } private static FieldInfo Bind(Type type, string name, Type expected) { while (type != null) { FieldInfo field = type.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { if (!(field.FieldType == expected)) { return null; } return field; } type = type.BaseType; } return null; } } internal sealed class DevelopmentEffects : IDisposable { private readonly Type enemyType; private readonly GojoAssetBundle assets; private readonly float saturation; private readonly float strength; private readonly Action<string> info; private readonly Action<string> warning; private readonly BrackenVisibilityReader visibilityReader; private readonly Dictionary<Component, BrackenGameBinding> attempted = new Dictionary<Component, BrackenGameBinding>(); private readonly Dictionary<Component, int> discovered = new Dictionary<Component, int>(); private readonly Dictionary<Component, string> candidateStatus = new Dictionary<Component, string>(); private float nextScanLog; private int lastScanScene = int.MinValue; private int lastFoundCount = -1; private bool stopped; private readonly bool standingModelPreview; private readonly bool soloLiveTest; private DevelopmentEffects(Type enemyType, GojoAssetBundle assets, float saturation, float strength, Action<string> info, Action<string> warning, bool standingModelPreview, bool soloLiveTest) { this.enemyType = enemyType; this.assets = assets; this.saturation = saturation; this.strength = strength; this.info = info; this.warning = warning; this.standingModelPreview = standingModelPreview; this.soloLiveTest = soloLiveTest; visibilityReader = new BrackenVisibilityReader(enemyType); } internal static DevelopmentEffects Start(Type enemyType, string directory, float saturation, float strength, Action<string> info, Action<string> warning, bool standingModelPreview = false, bool soloLiveTest = false) { if (enemyType == null || !typeof(Component).IsAssignableFrom(enemyType) || enemyType.Module.ModuleVersionId != BrackenV81Presentation.SupportedMvid) { warning("[Effects] Disabled: FlowermanAI does not match the inspected v81 assembly. Vanilla visuals retained."); return null; } new BrackenV81Presentation(enemyType.Module.ModuleVersionId, saturation); if (float.IsNaN(strength) || float.IsInfinity(strength) || strength < 0f || strength > 3f) { throw new ArgumentOutOfRangeException("strength"); } if (!GojoAssetBundle.TryLoad(directory, out var gojoAssetBundle, out var error)) { warning("[Effects] Disabled: " + error); return null; } info("[Effects] Development cosmetics enabled; standingModelPreview=" + standingModelPreview + ". Non-owner/unknown anger uses phase approximation. Animation adaptation is incomplete."); return new DevelopmentEffects(enemyType, gojoAssetBundle, saturation, strength, info, warning, standingModelPreview, soloLiveTest); } internal void Scan() { //IL_011a: 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 (stopped) { return; } List<Component> list = new List<Component>(); foreach (KeyValuePair<Component, BrackenGameBinding> item in attempted) { if ((Object)(object)item.Key == (Object)null) { list.Add(item.Key); } } foreach (KeyValuePair<Component, int> item2 in discovered) { if ((Object)(object)item2.Key == (Object)null) { list.Add(item2.Key); } } foreach (Component item3 in list) { attempted.Remove(item3); discovered.Remove(item3); candidateStatus.Remove(item3); } Object[] array = Object.FindObjectsOfType(enemyType, soloLiveTest); if (soloLiveTest) { Scene activeScene = SceneManager.GetActiveScene(); float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup >= nextScanLog || ((Scene)(ref activeScene)).handle != lastScanScene || array.Length != lastFoundCount) { info($"[Effects] Live scan: activeScene={((Scene)(ref activeScene)).name}, loadedScenes={SceneManager.sceneCount}, " + $"FlowermanAI found={array.Length}, tracked={attempted.Count}."); nextScanLog = realtimeSinceStartup + 5f; lastScanScene = ((Scene)(ref activeScene)).handle; lastFoundCount = array.Length; } } Object[] array2 = array; foreach (Object obj in array2) { Component val = (Component)(object)((obj is Component) ? obj : null); if ((Object)(object)val == (Object)null || attempted.ContainsKey(val)) { continue; } if (val.gameObject.activeInHierarchy) { Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null); if (val2 == null || val2.isActiveAndEnabled) { if (!discovered.TryGetValue(val, out var value)) { TraceCandidate(val, "discovered; waiting one frame for EnemyAI.Start"); discovered.Add(val, Time.frameCount); } else { if (Time.frameCount <= value) { continue; } if (!visibilityReader.IsReady(val)) { TraceCandidate(val, "skipped for now: vanilla renderer arrays are not initialized"); continue; } TraceCandidate(val, "renderer arrays ready; attempting attachment"); attempted.Add(val, null); discovered.Remove(val); try { BrackenGameBinding brackenGameBinding = BrackenGameBinding.Attach(val, enemyType.Module.ModuleVersionId, assets.Aura, assets.Voice, saturation, strength, warning, standingModelPreview ? assets.Model : null, standingModelPreview ? 1.4285715f : 1f, standingModelPreview ? 1.25f : 1f, standingModelPreview ? 1.75f : 1f, soloLiveTest ? info : null, useV81BodyLayout: true, assets.Music, assets.BoostVoice); attempted[val] = brackenGameBinding; if ((Object)(object)brackenGameBinding != (Object)null) { info("[Effects] Attached cosmetics to Bracken " + ((Object)val).GetInstanceID() + "; standingModelPreview=" + standingModelPreview + "; " + brackenGameBinding.ModelPoseStatus + (standingModelPreview ? "; trial height=3.000 m; wisps=1.250; flame width/depth=1.250; flame height=1.750" : "")); } else { TraceCandidate(val, "skipped: Bracken was already dead"); } } catch (Exception ex) { warning("[Effects] Attachment skipped; vanilla visuals retained. " + ex.Message + (soloLiveTest ? $" Candidate id={((Object)val).GetInstanceID()}." : "")); } } continue; } } TraceCandidate(val, "skipped for now: GameObject inactive or component disabled"); if (soloLiveTest) { discovered[val] = Time.frameCount; } else { discovered.Remove(val); } } } private void TraceCandidate(Component enemy, string status) { //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) if (soloLiveTest && (!candidateStatus.TryGetValue(enemy, out var value) || !(value == status))) { candidateStatus[enemy] = status; Action<string> action = info; object[] obj = new object[4] { ((Object)enemy).GetInstanceID(), ((Object)enemy).name, null, null }; Scene scene = enemy.gameObject.scene; obj[2] = ((Scene)(ref scene)).name; obj[3] = status; action(string.Format("[Effects] FlowermanAI id={0}, name={1}, scene={2}: {3}.", obj)); } } public void Dispose() { if (stopped) { return; } stopped = true; foreach (BrackenGameBinding value in attempted.Values) { if ((Object)(object)value != (Object)null) { value.Stop(); Object.Destroy((Object)(object)value); } } attempted.Clear(); discovered.Clear(); candidateStatus.Clear(); assets.Dispose(); } } internal sealed class GojoAssetBundle : IDisposable { private AssetBundle bundle; internal GameObject Model { get; private set; } internal GameObject Aura { get; private set; } internal AudioClip Voice { get; private set; } internal AudioClip Music { get; private set; } internal bool BoostVoice { get; private set; } internal string Credits { get; private set; } private GojoAssetBundle(AssetBundle bundle, GameObject model, GameObject aura, AudioClip voice, AudioClip music, bool boostVoice, string credits) { this.bundle = bundle; Model = model; Aura = aura; Voice = voice; Music = music; BoostVoice = boostVoice; Credits = credits; } internal static bool TryLoad(string directory, out GojoAssetBundle assets, out string error) { assets = null; error = null; AssetBundle val = null; try { if (string.IsNullOrWhiteSpace(directory)) { throw new InvalidDataException("A plugin asset directory is required."); } string text = Path.Combine(directory, "gojobracken"); if (!File.Exists(text)) { throw new FileNotFoundException("Missing gojobracken bundle beside the plugin DLL."); } val = AssetBundle.LoadFromFile(text); if ((Object)(object)val == (Object)null) { throw new InvalidDataException("Unity could not open gojobracken. Check the bundle platform, Unity version, or corruption."); } GameObject model = val.LoadAsset<GameObject>("gojo"); GameObject aura = val.LoadAsset<GameObject>("aura"); AudioClip voice = val.LoadAsset<AudioClip>("domain_expansion"); TextAsset val2 = val.LoadAsset<TextAsset>("asset_credits"); Validate(model, aura, voice, val2); AudioClip val3 = val.LoadAsset<AudioClip>("aggro_music"); assets = new GojoAssetBundle(val, model, aura, voice, ((Object)(object)val3 != (Object)null && val3.samples > 0) ? val3 : null, val.Contains("uniform_voice_boost"), val2.text); val = null; return true; } catch (Exception ex) { error = "Gojo assets unavailable; keep vanilla Bracken visible. " + ex.GetType().Name + ": " + ex.Message; return false; } finally { if ((Object)(object)val != (Object)null) { val.Unload(true); } } } internal static void Validate(GameObject model, GameObject aura, AudioClip voice, TextAsset credits) { if ((Object)(object)model == (Object)null) { throw new InvalidDataException("Missing GameObject asset 'gojo'."); } if ((Object)(object)aura == (Object)null) { throw new InvalidDataException("Missing GameObject asset 'aura'."); } if ((Object)(object)voice == (Object)null || voice.samples <= 0 || voice.length <= 0f) { throw new InvalidDataException("Missing or empty AudioClip 'domain_expansion'."); } if ((Object)(object)credits == (Object)null || string.IsNullOrWhiteSpace(credits.text)) { throw new InvalidDataException("Missing or empty TextAsset 'asset_credits'; rebuild with the current exporter."); } SkinnedMeshRenderer[] componentsInChildren = model.GetComponentsInChildren<SkinnedMeshRenderer>(true); if (componentsInChildren.Length == 0) { throw new InvalidDataException("Gojo requires a skinned mesh."); } SkinnedMeshRenderer[] array = componentsInChildren; foreach (SkinnedMeshRenderer val in array) { if ((Object)(object)val.sharedMesh == (Object)null || val.sharedMesh.vertexCount == 0 || val.bones.Length == 0 || val.sharedMesh.bindposes.Length != val.bones.Length) { throw new InvalidDataException("Gojo has an empty mesh or inconsistent skin bones/bind poses."); } Transform[] bones = val.bones; for (int j = 0; j < bones.Length; j++) { if ((Object)(object)bones[j] == (Object)null) { throw new InvalidDataException("Gojo has a missing skin bone."); } } } Animator[] componentsInChildren2 = model.GetComponentsInChildren<Animator>(true); if (componentsInChildren2.Length == 0) { throw new InvalidDataException("Gojo requires an Animator with an animation controller."); } Animator[] array2 = componentsInChildren2; for (int i = 0; i < array2.Length; i++) { if ((Object)(object)array2[i].runtimeAnimatorController == (Object)null) { throw new InvalidDataException("Gojo Animator is missing its animation controller."); } } if (aura.GetComponentsInChildren<ParticleSystem>(true).Length == 0) { throw new InvalidDataException("Aura requires a ParticleSystem."); } ValidatePrefab(model, "gojo"); ValidatePrefab(aura, "aura"); } private static void ValidatePrefab(GameObject prefab, string name) { Transform[] componentsInChildren = prefab.GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { Component[] components = ((Component)val).GetComponents<Component>(); foreach (Component val2 in components) { if ((Object)(object)val2 == (Object)null || val2 is MonoBehaviour) { throw new InvalidDataException(name + " contains a missing or custom script: " + ((Object)val).name); } } } Renderer[] componentsInChildren2 = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val3 in componentsInChildren2) { if (val3.sharedMaterials.Length == 0) { throw new InvalidDataException(name + " has a renderer without materials: " + ((Object)val3).name); } Material[] sharedMaterials = val3.sharedMaterials; foreach (Material val4 in sharedMaterials) { if ((Object)(object)val4 == (Object)null || (Object)(object)val4.shader == (Object)null || !val4.shader.isSupported || ((Object)val4.shader).name == "Hidden/InternalErrorShader") { throw new InvalidDataException(name + " has a missing or unsupported material/shader: " + ((Object)val3).name); } } } } public void Dispose() { if (!((Object)(object)bundle == (Object)null)) { bundle.Unload(true); bundle = null; GameObject model = (Aura = null); Model = model; AudioClip voice = (Music = null); Voice = voice; Credits = null; } } } internal sealed class InGameRenderPreview : IDisposable { internal const string BundleName = "gojobracken-hdrp-material-check"; private const float AuraReferenceHeight = 2.1f; private const string RequestName = "gojobracken-preview.request"; private static readonly (int state, float anger, bool carrying)[] CyclePhases = new(int, float, bool)[7] { (0, 0f, false), (1, 4f, false), (2, 12f, false), (2, 6f, true), (1, 2f, false), (2, 12f, false), (0, 0f, false) }; private readonly string directory; private readonly Func<Camera> soloCamera; private readonly Action<string> info; private readonly Action<string> warning; private AssetBundle bundle; private GameObject anchor; private GameObject visual; private RaycastHit deck; private AudioClip previewClip; private Camera camera; private int sceneHandle; private bool waitingLogged; private BrackenCosmeticController controller; private bool walking; private float walkTime; private float maxAuraOffset; private Vector3 walkStart; private Vector3 walkEnd; private int cycleIndex = -1; private int cycleVoiceAtStart; private float cycleTime; private float cycleAggroHold; private string cycleAudio; internal string RequestPath => Path.Combine(directory, "gojobracken-preview.request"); internal InGameRenderPreview(string directory, Func<Camera> soloCamera, Action<string> info, Action<string> warning) { this.directory = directory; this.soloCamera = soloCamera; this.info = info; this.warning = warning; info("[RenderPreview] Ready for calm, full, walk, cycle, height, or clear requests beside the plugin DLL."); } internal static Func<Camera> BindSoloCamera(Assembly game) { Type type = game.GetType("StartOfRound", throwOnError: true); Type type2 = game.GetType("GameNetcodeStuff.PlayerControllerB", throwOnError: true); PropertyInfo instance = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public); FieldInfo connected = type.GetField("connectedPlayersAmount", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo local = type.GetField("localPlayerController", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo gameplay = type2.GetField("gameplayCamera", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (instance?.PropertyType != type || connected?.FieldType != typeof(int) || local?.FieldType != type2 || gameplay?.FieldType != typeof(Camera)) { throw new InvalidOperationException("The v81 solo camera members are unavailable."); } return delegate { object? value = instance.GetValue(null); Component val = (Component)((value is Component) ? value : null); if ((Object)(object)val == (Object)null || (int)connected.GetValue(val) != 0) { return (Camera)null; } object? value2 = local.GetValue(val); Component val2 = (Component)((value2 is Component) ? value2 : null); if (!((Object)(object)val2 == (Object)null)) { object? value3 = gameplay.GetValue(val2); return (Camera)((value3 is Camera) ? value3 : null); } return (Camera)null; }; } internal void Poll() { string requestPath = RequestPath; try { if ((Object)(object)anchor != (Object)null && !IsCurrentSession()) { Clear(); } if (!File.Exists(requestPath)) { waitingLogged = false; return; } string text = File.ReadAllText(requestPath).Trim().ToLowerInvariant(); if (!waitingLogged) { info("[RenderPreview] Found request file."); } switch (text) { case "calm": case "full": case "walk": case "cycle": { Camera val = soloCamera(); if ((Object)(object)val == (Object)null || !((Behaviour)val).isActiveAndEnabled) { if (!waitingLogged) { info("[RenderPreview] Request queued. Waiting for a solo gameplay camera."); } waitingLogged = true; return; } break; } } waitingLogged = false; File.Delete(requestPath); switch (text) { case "calm": Show(0f); return; case "full": Show(12f); return; case "walk": StartWalk(); return; case "cycle": StartCycle(); return; case "clear": Clear(); info("[RenderPreview] Cleared."); return; } if (text.StartsWith("height ", StringComparison.Ordinal)) { ChangeHeight(text.Substring(7)); } else { warning("[RenderPreview] Expected calm, full, walk, cycle, height <metres>, or clear."); } } catch (IOException ex) { warning("[RenderPreview] File operation failed: " + ex.Message); } catch (Exception ex2) { Clear(); warning("[RenderPreview] Preview failed: " + ex2.Message); } } private void Show(float anger, bool testTone = false) { //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_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) walking = false; cycleIndex = -1; RenderPipelineAsset currentRenderPipeline = GraphicsSettings.currentRenderPipeline; if ((Object)(object)currentRenderPipeline == (Object)null || ((object)currentRenderPipeline).GetType().FullName != "UnityEngine.Rendering.HighDefinition.HDRenderPipelineAsset") { throw new InvalidOperationException("An active HDRP camera is required."); } if ((Object)(object)anchor == (Object)null) { Create(testTone); } controller.Apply(new BrackenObservation(0, anger, angerMode: false, carryingBody: false, inKillAnimation: false, dead: false), useDetailedAnger: true, 10f); Action<string> action = info; string text = $"[RenderPreview] Applied anger {anger:0}/12, aura {controller.LastFrame.AuraLevel:0.00}, "; Scene activeScene = SceneManager.GetActiveScene(); action(text + $"scene={((Scene)(ref activeScene)).name}, HDRP, {QualitySettings.activeColorSpace}, {SystemInfo.graphicsDeviceType}."); } private void Create(bool testTone) { //IL_0042: 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_004c: 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_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_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0119: 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_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Expected O, but got Unknown //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Expected O, but got Unknown camera = soloCamera(); if ((Object)(object)camera == (Object)null || !((Behaviour)camera).isActiveAndEnabled) { throw new InvalidOperationException("No active solo gameplay camera. Enter a solo ship and retry."); } Vector3 val = Vector3.ProjectOnPlane(((Component)camera).transform.forward, Vector3.up); if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { throw new InvalidOperationException("Look horizontally before placing the preview."); } ((Vector3)(ref val)).Normalize(); if ((Object)(object)bundle == (Object)null) { bundle = AssetBundle.LoadFromFile(Path.Combine(directory, "gojobracken-hdrp-material-check")); } if ((Object)(object)bundle == (Object)null) { throw new InvalidOperationException("Could not open gojobracken-hdrp-material-check."); } GameObject obj = bundle.LoadAsset<GameObject>("gojo"); GameObject val2 = bundle.LoadAsset<GameObject>("aura"); BrackenModelAttachment.Validate(obj); if ((Object)(object)val2 == (Object)null) { throw new InvalidOperationException("The preview bundle is missing the aura."); } Vector3 val3 = ((Component)camera).transform.position + val * 3.5f - Vector3.up * 1.55f; deck = FindDeck(val3); Scene activeScene = SceneManager.GetActiveScene(); sceneHandle = ((Scene)(ref activeScene)).handle; anchor = new GameObject("GojoBracken local HDRP preview"); anchor.transform.SetPositionAndRotation(val3, Quaternion.LookRotation(-val, Vector3.up)); visual = new GameObject("Owned preview model"); visual.transform.SetParent(anchor.transform, false); Object.Instantiate<GameObject>(obj, visual.transform, false); BrackenModelAttachment.UseStandingPose(visual.transform); float height = AlignHeight(3f); AudioClip val4 = ((testTone && bundle.Contains("voice_source")) ? bundle.LoadAsset<AudioClip>("domain_expansion") : null); if (testTone && bundle.Contains("voice_source") && ((Object)(object)val4 == (Object)null || val4.samples <= 0)) { throw new InvalidOperationException("The preview bundle declares a voice source but has no valid domain_expansion clip."); } if ((Object)(object)val4 == (Object)null) { previewClip = CreatePreviewClip(testTone); } AudioClip val5 = (((Object)(object)val4 != (Object)null) ? bundle.LoadAsset<AudioClip>("aggro_music") : null); if ((Object)(object)val5 != (Object)null) { info("[RenderPreview] Loaded aggro music for the phase cycle."); } cycleAudio = (((Object)(object)val4 == (Object)null) ? "synthetic tone" : "imported voice clip"); cycleAggroHold = (((Object)(object)val4 == (Object)null) ? 2.5f : Mathf.Max(2.5f, val4.length + 0.25f)); if (!BrackenCosmeticController.TryCreate(anchor.transform, BrackenV81Presentation.SupportedMvid, val2, val4 ?? previewClip, 12f, 1f, out controller, out var error, val5, (Object)(object)val4 != (Object)null && bundle.Contains("uniform_voice_boost"))) { throw new InvalidOperationException(error); } ScaleAura(height); info("[RenderPreview] Placed local model: fixed standing pose."); } private static AudioClip CreatePreviewClip(bool testTone) { if (!testTone) { return AudioClip.Create("Silent render fixture", 480, 1, 48000, false); } float[] array = new float[24000]; for (int i = 0; i < array.Length; i++) { array[i] = Mathf.Sin(MathF.PI * 880f * (float)i / 48000f) * 0.08f * Mathf.Sin(MathF.PI * (float)i / (float)array.Length); } AudioClip val = AudioClip.Create("Synthetic aggro test tone", array.Length, 1, 48000, false); if (val.SetData(array, 0)) { return val; } Object.Destroy((Object)(object)val); throw new InvalidOperationException("Could not initialize the preview test tone."); } private void StartCycle() { Clear(); Show(0f, testTone: true); cycleIndex = 0; cycleTime = -4f; cycleVoiceAtStart = 0; info("[RenderPreview] Phase cycle queued. Audio source: " + cycleAudio + ". Listen on each aggro entry."); } internal void TickCycle(float deltaTime) { if (cycleIndex < 0 || deltaTime <= 0f) { return; } try { if (!IsCurrentSession()) { Clear(); return; } float num = Mathf.Min(deltaTime, 0.1f); cycleTime += num; if (cycleTime <= 0f) { return; } (int, float, bool) tuple = CyclePhases[cycleIndex]; controller.Apply(new BrackenObservation(tuple.Item1, tuple.Item2, tuple.Item1 == 2, tuple.Item3, inKillAnimation: false, dead: false), useDetailedAnger: true, num); if (!(cycleTime < ((tuple.Item1 == 2 && !tuple.Item3) ? cycleAggroHold : 2.5f))) { int voiceRequests = controller.VoiceRequests; info(FormattableString.Invariant($"[RenderPreview] Phase sample: {controller.LastFrame.Phase}, anger={tuple.Item2:0}/12, aura={controller.LastFrame.AuraLevel:F2}, new voice requests={voiceRequests - cycleVoiceAtStart}.")); cycleVoiceAtStart = voiceRequests; cycleTime = 0f; if (++cycleIndex >= CyclePhases.Length) { cycleIndex = -1; info($"[RenderPreview] Phase cycle complete: {voiceRequests} voice requests ({cycleAudio})."); } } } catch (Exception ex) { Clear(); warning("[RenderPreview] Phase cycle failed: " + ex.Message); } } private bool IsCurrentSession() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)anchor != (Object)null && (Object)(object)camera != (Object)null && ((Behaviour)camera).isActiveAndEnabled && (Object)(object)camera == (Object)(object)soloCamera()) { Scene activeScene = SceneManager.GetActiveScene(); return ((Scene)(ref activeScene)).handle == sceneHandle; } return false; } private void StartWalk() { //IL_001e: 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_002a: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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_00ec: Unknown result type (might be due to invalid IL or missing references) Clear(); Show(12f); walkStart = anchor.transform.position; walkEnd = walkStart + anchor.transform.forward * 1.2f; RaycastHit val2 = default(RaycastHit); for (int i = 1; i <= 2; i++) { Vector3 val = ((RaycastHit)(ref deck)).point + (walkEnd - walkStart) * ((float)i / 2f); if (!Physics.Raycast(val + Vector3.up * 0.15f, Vector3.down, ref val2, 0.25f, -5, (QueryTriggerInteraction)1) || (Object)(object)((RaycastHit)(ref val2)).collider != (Object)(object)((RaycastHit)(ref deck)).collider || ((RaycastHit)(ref val2)).normal.y < 0.8f || Mathf.Abs(((RaycastHit)(ref val2)).point.y - val.y) > 0.05f) { throw new InvalidOperationException("The walk needs a clear, level deck. Face down the ship aisle."); } } walkTime = -4f; maxAuraOffset = 0f; walking = true; info("[RenderPreview] Walk queued: return to the game for a 1.2 m pass with full aura."); } internal void TickWalk(float deltaTime) { //IL_005d: 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_0074: 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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) if (!walking || deltaTime <= 0f) { return; } try { if (!IsCurrentSession()) { Clear(); return; } float num = Mathf.Min(deltaTime, 0.1f); walkTime += num; if (!(walkTime <= 0f)) { anchor.transform.position = Vector3.Lerp(walkStart, walkEnd, walkTime / 2f); maxAuraOffset = Mathf.Max(maxAuraOffset, Vector3.Distance(anchor.transform.position, controller.WorldPosition)); if (!(walkTime < 2f)) { walking = false; info(FormattableString.Invariant($"[RenderPreview] Walk complete: travel={Vector3.Distance(walkStart, anchor.transform.position):F3} m, max aura anchor offset={maxAuraOffset:F3} m.")); } } } catch (Exception ex) { Clear(); warning("[RenderPreview] Walk failed: " + ex.Message); } } private void ChangeHeight(string value) { if (!float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || float.IsNaN(result) || result < 1f || result > 3f) { warning("[RenderPreview] Height must be between 1.000 and 3.000 m."); return; } if ((Object)(object)anchor == (Object)null || (Object)(object)visual == (Object)null || (Object)(object)((RaycastHit)(ref deck)).collider == (Object)null) { warning("[RenderPreview] Place Gojo with calm before changing height."); return; } walking = false; ScaleAura(AlignHeight(result)); } private float AlignHeight(float targetHeight) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_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_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0129: 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_0054: Unknown result type (might be due to invalid IL or missing references) float y = anchor.transform.position.y; (float, float) tuple = MeasureStandingMesh(visual); float item = tuple.Item2; float num = 1f; if (Mathf.Abs(item - targetHeight) > 0.005f) { num = targetHeight / item; Transform transform = visual.transform; transform.localScale *= num; tuple = MeasureStandingMesh(visual); } info(FormattableString.Invariant($"[RenderPreview] Standing height: original={item:F3}, target={targetHeight:F3}, final={tuple.Item2:F3} m, scale={num:F3}.")); float item2 = tuple.Item1; float num2 = ((RaycastHit)(ref deck)).point.y - item2 + 0.005f; Transform transform2 = anchor.transform; transform2.position += Vector3.up * num2; info(FormattableString.Invariant($"[RenderPreview] Floor alignment: collider={((Object)((RaycastHit)(ref deck)).collider).name}, deckY={((RaycastHit)(ref deck)).point.y:F3}, anchorYBefore={y:F3}, meshBottomOffset={item2 - y:F3}, correction={num2:F3} m.")); return tuple.Item2; } private void ScaleAura(float height) { float num = height / 2.1f; float num2 = Mathf.Min(num, 1.25f); float num3 = ((num <= 1f) ? num : Mathf.Lerp(1f, 1.75f, Mathf.InverseLerp(2.1f, 3f, height))); controller.SetEffectScale(num2, num3); info(FormattableString.Invariant($"[RenderPreview] Aura geometry scale: wisps={num2:F3}, flame width/depth={num2:F3}, flame height={num3:F3} at {height:F3} m.")); } private RaycastHit FindDeck(Vector3 estimatedFeet) { //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_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0059: 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_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0178: 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_016a: 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_0201: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) Vector3 val = estimatedFeet + Vector3.up * 0.65f; RaycastHit[] array = Physics.RaycastAll(val, Vector3.down, 1.6999999f, -5, (QueryTriggerInteraction)1); info(FormattableString.Invariant($"[RenderPreview] Floor probe: origin=({val.x:F3}, {val.y:F3}, {val.z:F3}), down={1.6999999f:F3} m, estimatedFeetY={estimatedFeet.y:F3}, mask=0x{-5:X8}, triggers=ignored, minimumNormalY={0.8f:F2}, hits={array.Length}.")); float num = float.PositiveInfinity; RaycastHit result = default(RaycastHit); RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit val2 = array2[i]; float num2 = Mathf.Abs(((RaycastHit)(ref val2)).point.y - estimatedFeet.y); if (!(((RaycastHit)(ref val2)).normal.y < 0.8f) && !(num2 >= num)) { num = num2; result = val2; } } Array.Sort(array, (RaycastHit left, RaycastHit right) => ((RaycastHit)(ref left)).distance.CompareTo(((RaycastHit)(ref right)).distance)); for (int num3 = 0; num3 < Math.Min(array.Length, 12); num3++) { RaycastHit hit = array[num3]; string result2 = (((Object)(object)((RaycastHit)(ref hit)).collider == (Object)(object)((RaycastHit)(ref result)).collider && ((RaycastHit)(ref hit)).point == ((RaycastHit)(ref result)).point) ? "selected" : ((((RaycastHit)(ref hit)).normal.y < 0.8f) ? "surface too steep" : "farther from estimated feet")); LogFloorHit("primary", hit, estimatedFeet.y, result2); } if (array.Length > 12) { info($"[RenderPreview] Floor probe: {array.Length - 12} additional primary hits omitted."); } if ((Object)(object)((RaycastHit)(ref result)).collider == (Object)null) { LogNearbySurfaces(estimatedFeet, 0.65f, 1.05f, 0.8f, -5); throw new InvalidOperationException("No walkable surface near the preview's estimated foot height."); } return result; } private void LogNearbySurfaces(Vector3 estimatedFeet, float aboveFeet, float belowFeet, float minimumUpNormal, int layerMask) { //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_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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_015d: 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) Vector3 val = estimatedFeet + Vector3.up * 1.5f; RaycastHit[] array = Physics.RaycastAll(val, Vector3.down, 4.5f, -1, (QueryTriggerInteraction)2); info(FormattableString.Invariant($"[RenderPreview] Floor diagnostic: origin=({val.x:F3}, {val.y:F3}, {val.z:F3}), down={4.5f:F3} m, all layers and triggers, hits={array.Length}.")); Array.Sort(array, (RaycastHit left, RaycastHit right) => ((RaycastHit)(ref left)).distance.CompareTo(((RaycastHit)(ref right)).distance)); for (int num = 0; num < Math.Min(array.Length, 12); num++) { RaycastHit hit = array[num]; string text = ""; float num2 = ((RaycastHit)(ref hit)).point.y - estimatedFeet.y; if (num2 > aboveFeet || num2 < 0f - belowFeet) { text += "outside primary height range, "; } if ((layerMask & (1 << ((Component)((RaycastHit)(ref hit)).collider).gameObject.layer)) == 0) { text += "layer excluded by primary mask, "; } if (((RaycastHit)(ref hit)).collider.isTrigger) { text += "trigger, "; } if (((RaycastHit)(ref hit)).normal.y < minimumUpNormal) { text += "surface too steep, "; } LogFloorHit("diagnostic", hit, estimatedFeet.y, (text.Length == 0) ? "eligible by filters but absent from primary results" : text.TrimEnd(',', ' ')); } if (array.Length > 12) { info($"[RenderPreview] Floor diagnostic: {array.Length - 12} additional hits omitted."); } } private void LogFloorHit(string probe, RaycastHit hit, float estimatedY, string result) { //IL_004d: 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_0077: Unknown result type (might be due to invalid IL or missing references) int layer = ((Component)((RaycastHit)(ref hit)).collider).gameObject.layer; info(FormattableString.Invariant($"[RenderPreview] Floor {probe} hit: collider={((Object)((RaycastHit)(ref hit)).collider).name}, layer={layer} ({LayerMask.LayerToName(layer)}), y={((RaycastHit)(ref hit)).point.y:F3}, offset={((RaycastHit)(ref hit)).point.y - estimatedY:F3} m, normalY={((RaycastHit)(ref hit)).normal.y:F3}, trigger={((RaycastHit)(ref hit)).collider.isTrigger}, result={result}.")); } private static (float bottom, float height) MeasureStandingMesh(GameObject visual) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0061: Unknown result type (might be due to invalid IL or missing references) float num = float.PositiveInfinity; float num2 = float.NegativeInfinity; Mesh val = new Mesh(); List<Vector3> list = new List<Vector3>(); try { SkinnedMeshRenderer[] componentsInChildren = visual.GetComponentsInChildren<SkinnedMeshRenderer>(); foreach (SkinnedMeshRenderer val2 in componentsInChildren) { if (!((Renderer)val2).enabled) { continue; } val2.BakeMesh(val, true); val.GetVertices(list); foreach (Vector3 item in list) { float y = ((Component)val2).transform.TransformPoint(item).y; num = Mathf.Min(num, y); num2 = Mathf.Max(num2, y); } } } finally { Object.Destroy((Object)(object)val); } float num3 = num2 - num; if (float.IsNaN(num3) || float.IsInfinity(num3) || num3 <= 0.01f) { throw new InvalidOperationException("Could not measure the Gojo mesh for deck alignment."); } return (bottom: num, height: num3); } private void Clear() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) walking = false; cycleIndex = -1; if ((Object)(object)anchor != (Object)null) { anchor.SetActive(false); Object.Destroy((Object)(object)anchor); } if ((Object)(object)previewClip != (Object)null) { Object.Destroy((Object)(object)previewClip); } anchor = null; visual = null; deck = default(RaycastHit); previewClip = null; camera = null; controller = null; } public void Dispose() { Clear(); if ((Object)(object)bundle != (Object)null) { bundle.Unload(true); } bundle = null; } } internal sealed class InGameRenderPreviewRunner : MonoBehaviour { private static InGameRenderPreviewRunner instance; private InGameRenderPreview preview; private Func<DevelopmentEffects> openLive; private Action<string> liveWarning; private Func<Camera> soloCamera; private DevelopmentEffects live; private bool attemptedLive; private bool liveWasReady; private string logTag; private Action<string> info; private float nextPoll; private float nextHeartbeat; private int pollCount; private static Action<ScriptableRenderContext, Camera> cameraRendered; internal static void StartPreview(string directory, Func<Camera> soloCamera, Action<string> info, Action<string> warning) { Arm("[RenderPreview]", soloCamera, info, warning, delegate(InGameRenderPreviewRunner runner) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) runner.preview = new InGameRenderPreview(directory, soloCamera, info, warning); Action<string> action = info; Scene activeScene = SceneManager.GetActiveScene(); action("[RenderPreview] Solo gameplay camera rendered in " + ((Scene)(ref activeScene)).name + ". " + $"Runner {((Object)runner).GetInstanceID()} watching: {runner.preview.RequestPath}"); }); } internal static void StartLiveTest(Func<Camera> soloCamera, Func<DevelopmentEffects> openLive, Action<string> info, Action<string> warning) { Arm("[LiveTest]", soloCamera, info, warning, delegate(InGameRenderPreviewRunner runner) { runner.soloCamera = soloCamera; runner.openLive = openLive; runner.liveWarning = warning; info("[LiveTest] Solo camera rendered. Waiting for live Bracken attachment."); }); } private static void Arm(string tag, Func<Camera> soloCamera, Action<string> info, Action<string> warning, Action<InGameRenderPreviewRunner> configure) { if (cameraRendered != null) { return; } float nextAttempt = 0f; cameraRendered = delegate(ScriptableRenderContext _, Camera renderedCamera) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown if (!((Object)(object)instance != (Object)null) || !((Behaviour)instance).isActiveAndEnabled) { float realtimeSinceStartup = Time.realtimeSinceStartup; if (!(realtimeSinceStartup < nextAttempt) && !((Object)(object)renderedCamera == (Object)null) && (int)renderedCamera.cameraType == 1) { try { if (!((Object)(object)renderedCamera != (Object)(object)soloCamera())) { nextAttempt = realtimeSinceStartup + 1f; if ((Object)(object)instance != (Object)null) { Object.Destroy((Object)(object)((Component)instance).gameObject); } else {