Decompiled source of GojoBracken v0.2.1

BepInEx/plugins/GojoBracken/GojoBracken.dll

Decompiled 40 minutes ago
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
							{