Decompiled source of DrifterBracken v2.1.0

DrifterBracken.dll

Decompiled 4 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Animations;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Playables;
using UnityEngine.Rendering.HighDefinition;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DrifterBracken
{
	public class BrackenAnimTester : MonoBehaviour
	{
		private static BrackenAnimTester _primary;

		private Animator _animator;

		private AnimationClip[] _clips = (AnimationClip[])(object)new AnimationClip[0];

		private RuntimeAnimatorController _originalController;

		private readonly List<Behaviour> _suspended = new List<Behaviour>();

		private PlayableGraph _graph;

		private AnimationClipPlayable _playable;

		private bool _graphLive;

		private Transform[] _recBones = (Transform[])(object)new Transform[0];

		private readonly List<PoseClip> _recClips = new List<PoseClip>();

		private readonly List<PoseFrame> _recFrames = new List<PoseFrame>();

		private float _recAccum;

		private const float RecFps = 20f;

		private int _index;

		private float _timer;

		private bool _running;

		private bool _paused;

		private bool _held;

		private float _heldSpeed = 1f;

		private void Awake()
		{
			_animator = ((Component)this).GetComponentInChildren<Animator>(true);
			if ((Object)(object)_animator == (Object)null)
			{
				((Behaviour)this).enabled = false;
				return;
			}
			_clips = (AnimationClip[])(((Object)(object)_animator.runtimeAnimatorController == (Object)null) ? ((Array)new AnimationClip[0]) : ((Array)(from c in _animator.runtimeAnimatorController.animationClips
				where (Object)(object)c != (Object)null
				group c by ((Object)c).name into grp
				select grp.First() into c
				orderby ((Object)c).name
				select c).ToArray()));
			SkinnedMeshRenderer val = ((IEnumerable<SkinnedMeshRenderer>)((Component)this).GetComponentsInChildren<SkinnedMeshRenderer>(true)).FirstOrDefault((Func<SkinnedMeshRenderer, bool>)((SkinnedMeshRenderer r) => r.bones != null && r.bones.Length > 60));
			if ((Object)(object)val != (Object)null)
			{
				_recBones = val.bones.Where((Transform b) => (Object)(object)b != (Object)null).ToArray();
			}
			if ((Object)(object)_primary == (Object)null)
			{
				_primary = this;
			}
			Plugin.Log.LogInfo((object)("Test mode: " + _clips.Length + " clips on '" + ((Object)this).name + "' -> " + string.Join(", ", _clips.Select((AnimationClip c) => ((Object)c).name).ToArray())));
		}

		private void OnDestroy()
		{
			Stop();
			Release();
			if ((Object)(object)_primary == (Object)(object)this)
			{
				_primary = null;
			}
		}

		private void Update()
		{
			bool flag = Plugin.HoldActive && !Plugin.TestActive;
			if (flag && !_held)
			{
				HoldStill();
			}
			else if (!flag && _held)
			{
				Release();
			}
			if (Plugin.TestActive && !_running)
			{
				Begin();
			}
			else if (!Plugin.TestActive && _running)
			{
				Stop();
			}
			if (!_running || _clips.Length == 0)
			{
				return;
			}
			if (Plugin.ConsumeStep(out var step))
			{
				Show(_index + step);
				return;
			}
			if (Plugin.ConsumePause())
			{
				_paused = !_paused;
			}
			if (!_paused)
			{
				if (Plugin.RecordPoses.Value && (Object)(object)_primary == (Object)(object)this)
				{
					Sample();
				}
				_timer += Time.deltaTime;
				float num = _clips[_index].length;
				if (num <= 0.01f)
				{
					num = 2f;
				}
				if (_timer >= num + Plugin.TestHold.Value)
				{
					Show(_index + 1);
				}
			}
		}

		private void Begin()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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_0071: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			_running = true;
			Suspend();
			_originalController = _animator.runtimeAnimatorController;
			_animator.runtimeAnimatorController = null;
			_graph = PlayableGraph.Create("DrifterBrackenTest:" + ((Object)this).GetInstanceID());
			((PlayableGraph)(ref _graph)).SetTimeUpdateMode((DirectorUpdateMode)1);
			AnimationPlayableOutput val = AnimationPlayableOutput.Create(_graph, "anim", _animator);
			_playable = AnimationClipPlayable.Create(_graph, (_clips.Length != 0) ? _clips[0] : null);
			PlayableOutputExtensions.SetSourcePlayable<AnimationPlayableOutput, AnimationClipPlayable>(val, _playable);
			_graphLive = true;
			((PlayableGraph)(ref _graph)).Play();
			_index = -1;
			Show(0);
			Plugin.Log.LogInfo((object)("Test mode ON - frozen, cycling " + _clips.Length + " clips."));
		}

		private void Stop()
		{
			if (_running)
			{
				_running = false;
				_paused = false;
				if (_graphLive && ((PlayableGraph)(ref _graph)).IsValid())
				{
					((PlayableGraph)(ref _graph)).Destroy();
				}
				_graphLive = false;
				if ((Object)(object)_animator != (Object)null)
				{
					_animator.runtimeAnimatorController = _originalController;
				}
				Resume();
				Plugin.Log.LogInfo((object)"Test mode OFF - Bracken released.");
			}
		}

		private void Suspend()
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			_suspended.Clear();
			MonoBehaviour[] components = ((Component)this).GetComponents<MonoBehaviour>();
			foreach (MonoBehaviour val in components)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)this) && ((Behaviour)val).enabled && val is EnemyAI)
				{
					((Behaviour)val).enabled = false;
					_suspended.Add((Behaviour)(object)val);
				}
			}
			NavMeshAgent component = ((Component)this).GetComponent<NavMeshAgent>();
			if ((Object)(object)component != (Object)null && ((Behaviour)component).enabled)
			{
				if (component.isOnNavMesh)
				{
					component.isStopped = true;
				}
				component.velocity = Vector3.zero;
				((Behaviour)component).enabled = false;
				_suspended.Add((Behaviour)(object)component);
			}
			components = ((Component)this).GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val2 in components)
			{
				if (!((Object)(object)val2 == (Object)null) && ((Behaviour)val2).enabled && !(((object)val2).GetType().Name != "RigBuilder"))
				{
					((Behaviour)val2).enabled = false;
					_suspended.Add((Behaviour)(object)val2);
				}
			}
		}

		private void Resume()
		{
			foreach (Behaviour item in _suspended)
			{
				if ((Object)(object)item != (Object)null)
				{
					item.enabled = true;
				}
			}
			_suspended.Clear();
		}

		private void HoldStill()
		{
			_held = true;
			Suspend();
			if ((Object)(object)_animator != (Object)null)
			{
				_heldSpeed = ((_animator.speed <= 0f) ? 1f : _animator.speed);
				_animator.speed = 0f;
			}
			Plugin.Log.LogInfo((object)("Hold still ON - '" + ((Object)this).name + "' frozen on its current pose."));
		}

		private void Release()
		{
			if (_held)
			{
				_held = false;
				if ((Object)(object)_animator != (Object)null)
				{
					_animator.speed = _heldSpeed;
				}
				Resume();
				Plugin.Log.LogInfo((object)("Hold still OFF - '" + ((Object)this).name + "' released."));
			}
		}

		private void Sample()
		{
			//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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			if (_recBones.Length == 0)
			{
				return;
			}
			_recAccum += Time.deltaTime;
			if (!(_recAccum < 0.05f))
			{
				_recAccum = 0f;
				float[] array = new float[_recBones.Length * 4];
				for (int i = 0; i < _recBones.Length; i++)
				{
					Quaternion localRotation = _recBones[i].localRotation;
					array[i * 4] = localRotation.x;
					array[i * 4 + 1] = localRotation.y;
					array[i * 4 + 2] = localRotation.z;
					array[i * 4 + 3] = localRotation.w;
				}
				Vector3 localPosition = _recBones[0].localPosition;
				_recFrames.Add(new PoseFrame
				{
					r = array,
					p = new float[3] { localPosition.x, localPosition.y, localPosition.z }
				});
			}
		}

		private void FlushClip()
		{
			if (!Plugin.RecordPoses.Value || (Object)(object)_primary != (Object)(object)this)
			{
				return;
			}
			if (_index < 0 || _index >= _clips.Length || _recFrames.Count == 0)
			{
				_recFrames.Clear();
				return;
			}
			string name = ((Object)_clips[_index]).name;
			if (_recClips.Any((PoseClip c) => c.name == name))
			{
				_recFrames.Clear();
				return;
			}
			_recClips.Add(new PoseClip
			{
				name = name,
				fps = 20f,
				frames = _recFrames.ToArray()
			});
			_recFrames.Clear();
			if (_recClips.Count >= _clips.Length)
			{
				WriteRecording();
			}
		}

		private void WriteRecording()
		{
			try
			{
				PoseRecording poseRecording = new PoseRecording
				{
					bones = _recBones.Select((Transform b) => ((Object)b).name).ToArray(),
					clips = _recClips.ToArray()
				};
				string text = Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location), "bracken_anim.json");
				File.WriteAllText(text, JsonUtility.ToJson((object)poseRecording));
				Plugin.Log.LogInfo((object)($"Recorded {_recClips.Count} clips, " + $"{_recClips.Sum((PoseClip c) => c.frames.Length)} frames -> {text}"));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Could not write recording: " + ex.Message));
			}
		}

		private void Show(int i)
		{
			//IL_005a: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			FlushClip();
			if (_clips.Length == 0)
			{
				return;
			}
			_index = (i % _clips.Length + _clips.Length) % _clips.Length;
			_timer = 0f;
			if (_graphLive && ((PlayableGraph)(ref _graph)).IsValid())
			{
				AnimationPlayableOutput val = (AnimationPlayableOutput)((PlayableGraph)(ref _graph)).GetOutput(0);
				if (PlayableExtensions.IsValid<AnimationClipPlayable>(_playable))
				{
					((PlayableGraph)(ref _graph)).DestroyPlayable<AnimationClipPlayable>(_playable);
				}
				_playable = AnimationClipPlayable.Create(_graph, _clips[_index]);
				((AnimationClipPlayable)(ref _playable)).SetApplyFootIK(false);
				PlayableOutputExtensions.SetSourcePlayable<AnimationPlayableOutput, AnimationClipPlayable>(val, _playable);
				PlayableExtensions.SetTime<AnimationClipPlayable>(_playable, 0.0);
				PlayableExtensions.SetSpeed<AnimationClipPlayable>(_playable, 1.0);
				Plugin.Log.LogInfo((object)($"Test clip {_index + 1}/{_clips.Length}: '{((Object)_clips[_index]).name}' " + $"({_clips[_index].length:F2}s, loop={((Motion)_clips[_index]).isLooping})"));
			}
		}

		private void OnGUI()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			if (_running && !((Object)(object)_primary != (Object)(object)this) && _clips.Length != 0)
			{
				GUIStyle val = new GUIStyle(GUI.skin.label)
				{
					fontSize = 18
				};
				val.normal.textColor = Color.white;
				GUIStyle val2 = val;
				GUIStyle val3 = new GUIStyle(GUI.skin.box);
				GUI.Box(new Rect(10f, 10f, 430f, 104f), GUIContent.none, val3);
				GUI.Label(new Rect(20f, 16f, 420f, 26f), "DRIFTER BRACKEN - TEST MODE" + (_paused ? "  [PAUSED]" : ""), val2);
				GUI.Label(new Rect(20f, 42f, 420f, 26f), $"{_index + 1}/{_clips.Length}  {((Object)_clips[_index]).name}  ({_clips[_index].length:F2}s)", val2);
				GUI.Label(new Rect(20f, 68f, 420f, 26f), $"{Plugin.TestToggle.Value} exit   {Plugin.TestNext.Value}/{Plugin.TestPrev.Value} step" + $"   {Plugin.TestPause.Value} pause", val2);
			}
		}
	}
	[HarmonyPatch(typeof(FlowermanAI), "OnCollideWithPlayer")]
	internal static class HeldBrackenCannotGrabPatch
	{
		private static bool Prefix()
		{
			if (!Plugin.HoldActive)
			{
				return !Plugin.TestActive;
			}
			return false;
		}
	}
	public class DrifterBrackenSkin : MonoBehaviour
	{
		private readonly List<Material> _owned = new List<Material>();

		private SkinnedMeshRenderer _lod1;

		private SkinnedMeshRenderer[] _mine = (SkinnedMeshRenderer[])(object)new SkinnedMeshRenderer[0];

		private Renderer[] _hidden = (Renderer[])(object)new Renderer[0];

		private bool _ready;

		private EnemyAI _ai;

		private float _voiceTimer;

		private static readonly string[] StripSlots = new string[19]
		{
			"_MaskMap", "_NormalMap", "_NormalMapOS", "_BentNormalMap", "_BentNormalMapOS", "_DetailMap", "_HeightMap", "_EmissiveColorMap", "_SpecularColorMap", "_AnisotropyMap",
			"_CoatMaskMap", "_SubsurfaceMaskMap", "_ThicknessMap", "_TangentMap", "_TangentMapOS", "_IridescenceMaskMap", "_IridescenceThicknessMap", "_TransmissionMaskMap", "_TransmittanceColorMap"
		};

		private static readonly string[] StripKeywords = new string[14]
		{
			"_NORMALMAP", "_NORMALMAP_TANGENT_SPACE", "_MASKMAP", "_DETAIL_MAP", "_HEIGHTMAP", "_EMISSIVE_COLOR_MAP", "_EMISSION", "_BENTNORMALMAP", "_MATERIAL_FEATURE_SUBSURFACE_SCATTERING", "_MATERIAL_FEATURE_TRANSMISSION",
			"_MATERIAL_FEATURE_ANISOTROPY", "_MATERIAL_FEATURE_IRIDESCENCE", "_MATERIAL_FEATURE_CLEAR_COAT", "_MATERIAL_FEATURE_SPECULAR_COLOR"
		};

		private static bool _loggedShader;

		private static bool _loggedValidate;

		private static bool _loggedEyes;

		private void Start()
		{
			try
			{
				Setup();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Setup failed on '" + ((Object)this).name + "': " + ex));
			}
		}

		private void Setup()
		{
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: 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_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.Meshes.Count == 0)
			{
				return;
			}
			SkinnedMeshRenderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			_lod1 = ((IEnumerable<SkinnedMeshRenderer>)componentsInChildren).FirstOrDefault((Func<SkinnedMeshRenderer, bool>)((SkinnedMeshRenderer r) => ((Object)r).name == "LOD1")) ?? componentsInChildren.FirstOrDefault();
			if ((Object)(object)_lod1 == (Object)null)
			{
				Plugin.Log.LogError((object)"No Bracken renderer found.");
				return;
			}
			Transform[] bones = _lod1.bones;
			Transform rootBone = _lod1.rootBone;
			Material template = ((IEnumerable<Material>)((Renderer)_lod1).sharedMaterials).FirstOrDefault((Func<Material, bool>)((Material m) => (Object)(object)m != (Object)null));
			List<SkinnedMeshRenderer> list = new List<SkinnedMeshRenderer>();
			foreach (KeyValuePair<string, Mesh> mesh in Plugin.Meshes)
			{
				Mesh value = mesh.Value;
				if (value.bindposes.Length != bones.Length)
				{
					Plugin.Log.LogError((object)($"'{mesh.Key}' has {value.bindposes.Length} bindposes but the Bracken " + $"has {bones.Length} bones - skipping."));
					continue;
				}
				GameObject val = new GameObject("Drifter_" + mesh.Key);
				val.transform.SetParent(((Component)_lod1).transform.parent, false);
				val.transform.localPosition = Vector3.zero;
				val.transform.localRotation = Quaternion.identity;
				val.transform.localScale = Vector3.one;
				SkinnedMeshRenderer val2 = val.AddComponent<SkinnedMeshRenderer>();
				val2.sharedMesh = value;
				val2.bones = bones;
				val2.rootBone = rootBone;
				((Renderer)val2).localBounds = ((Renderer)_lod1).localBounds;
				val2.quality = (SkinQuality)4;
				val2.updateWhenOffscreen = false;
				((Renderer)val2).shadowCastingMode = ((Renderer)_lod1).shadowCastingMode;
				((Renderer)val2).receiveShadows = ((Renderer)_lod1).receiveShadows;
				string[] value2;
				string[] array = (Plugin.MaterialNames.TryGetValue(mesh.Key, out value2) ? value2 : new string[0]);
				Material[] array2 = (Material[])(object)new Material[value.subMeshCount];
				for (int num = 0; num < array2.Length; num++)
				{
					array2[num] = BuildMaterial(template, (num < array.Length) ? array[num] : "");
				}
				((Renderer)val2).sharedMaterials = array2;
				list.Add(val2);
				Plugin.Log.LogInfo((object)($"Attached '{mesh.Key}': {value.vertexCount} verts, " + $"{value.subMeshCount} submeshes, {bones.Length} bones."));
			}
			_mine = list.ToArray();
			if (_mine.Length == 0)
			{
				Plugin.Log.LogError((object)"Nothing attached.");
				return;
			}
			List<Renderer> list2 = new List<Renderer> { (Renderer)(object)_lod1 };
			Transform[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<Transform>(true);
			foreach (Transform val3 in componentsInChildren2)
			{
				if (((Object)val3).name == "LeftEye" || ((Object)val3).name == "RightEye")
				{
					list2.AddRange(((Component)val3).GetComponents<Renderer>());
				}
			}
			_hidden = list2.Where((Renderer r) => (Object)(object)r != (Object)null).ToArray();
			_ready = true;
		}

		private void LateUpdate()
		{
			Plugin.PollHotkeys();
			_voiceTimer += Time.deltaTime;
			if (_voiceTimer >= 1f)
			{
				_voiceTimer = 0f;
				if (DrifterVoice.Enabled)
				{
					if ((Object)(object)_ai == (Object)null)
					{
						_ai = ((Component)this).GetComponent<EnemyAI>();
					}
					DrifterVoice.FillState(_ai);
				}
			}
			if (!_ready)
			{
				return;
			}
			bool enabled = (Object)(object)_lod1 != (Object)null && ((Renderer)_lod1).enabled;
			for (int i = 0; i < _mine.Length; i++)
			{
				if ((Object)(object)_mine[i] != (Object)null)
				{
					((Renderer)_mine[i]).enabled = enabled;
				}
			}
			bool value = Plugin.HideOriginal.Value;
			for (int j = 0; j < _hidden.Length; j++)
			{
				if ((Object)(object)_hidden[j] != (Object)null)
				{
					_hidden[j].forceRenderingOff = value;
				}
			}
		}

		private void OnDestroy()
		{
			SkinnedMeshRenderer[] mine = _mine;
			foreach (SkinnedMeshRenderer val in mine)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
			foreach (Material item in _owned)
			{
				if ((Object)(object)item != (Object)null)
				{
					Object.Destroy((Object)(object)item);
				}
			}
			_owned.Clear();
		}

		private Material BuildMaterial(Material template, string slotName)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0530: Unknown result type (might be due to invalid IL or missing references)
			//IL_0535: 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_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
			Shader val = (((Object)(object)template != (Object)null) ? template.shader : Shader.Find("HDRP/Lit"));
			Material val2 = (((Object)(object)val != (Object)null) ? new Material(val) : new Material(template));
			((Object)val2).name = "Drifter_" + slotName;
			_owned.Add(val2);
			if (!_loggedShader)
			{
				_loggedShader = true;
				Plugin.Log.LogInfo((object)("Materials built on shader '" + (((Object)(object)val != (Object)null) ? ((Object)val).name : "<none>") + "' (template '" + (((Object)(object)template != (Object)null) ? ((Object)template).name : "<none>") + "')"));
			}
			string[] stripSlots = StripSlots;
			foreach (string text in stripSlots)
			{
				if (val2.HasProperty(text))
				{
					val2.SetTexture(text, (Texture)null);
				}
			}
			stripSlots = StripKeywords;
			foreach (string text2 in stripSlots)
			{
				val2.DisableKeyword(text2);
			}
			SetColor(val2, Color.black, "_EmissiveColor", "_EmissionColor");
			if (val2.HasProperty("_NormalMapSpace"))
			{
				val2.SetFloat("_NormalMapSpace", 0f);
			}
			val2.renderQueue = (((Object)(object)val != (Object)null) ? val.renderQueue : (-1));
			string text3 = slotName.ToLowerInvariant();
			string text4 = (text3.Contains("teeth") ? "drifter_teeth" : (text3.Contains("eye") ? "drifter_eyes" : (text3.Contains("hair") ? "drifter_hair" : (text3.Contains("lower") ? "drifter_lower_body" : (text3.Contains("head") ? "drifter_head" : "drifter_upper_body")))));
			Texture2D val3 = Tex(text4);
			bool flag = SetTex(val2, val3, "_BaseColorMap", "_MainTex", "_BaseMap");
			SetColor(val2, Color.white, "_BaseColor", "_Color");
			Plugin.Log.LogInfo((object)("  slot '" + slotName + "' -> " + text4 + (((Object)(object)val3 == (Object)null) ? " [TEXTURE MISSING FROM BUNDLE]" : (flag ? $" ({((Texture)val3).width}x{((Texture)val3).height})" : " [NO BASE COLOUR PROPERTY ON SHADER]"))));
			if (text4 == "drifter_head")
			{
				Texture2D val4 = Tex("drifter_head_normal");
				if ((Object)(object)val4 != (Object)null && SetTex(val2, val4, "_NormalMap", "_BumpMap"))
				{
					val2.EnableKeyword("_NORMALMAP");
				}
			}
			if (val2.HasProperty("_Smoothness"))
			{
				val2.SetFloat("_Smoothness", Plugin.Smoothness.Value);
			}
			if (val2.HasProperty("_Metallic"))
			{
				val2.SetFloat("_Metallic", 0f);
			}
			if (text4 == "drifter_eyes")
			{
				SetColor(val2, Color.black, "_BaseColor", "_Color");
				if (val2.HasProperty("_Smoothness"))
				{
					val2.SetFloat("_Smoothness", 0f);
				}
				if (val2.HasProperty("_Metallic"))
				{
					val2.SetFloat("_Metallic", 0f);
				}
				float value = Plugin.EyeBrightness.Value;
				Texture2D val5 = Tex("drifter_eyes");
				if (value > 0f && (Object)(object)val5 != (Object)null)
				{
					SetTex(val2, val5, "_EmissiveColorMap", "_EmissionMap");
					SetColor(val2, Color.white * value, "_EmissiveColor", "_EmissionColor");
					if (val2.HasProperty("_UseEmissiveIntensity"))
					{
						val2.SetFloat("_UseEmissiveIntensity", 0f);
					}
					if (val2.HasProperty("_EmissiveExposureWeight"))
					{
						val2.SetFloat("_EmissiveExposureWeight", 0f);
					}
					val2.EnableKeyword("_EMISSIVE_COLOR_MAP");
					val2.EnableKeyword("_EMISSION");
				}
			}
			try
			{
				HDMaterial.ValidateMaterial(val2);
			}
			catch (Exception ex)
			{
				if (!_loggedValidate)
				{
					_loggedValidate = true;
					Plugin.Log.LogWarning((object)("HDMaterial.ValidateMaterial unavailable: " + ex.Message));
				}
			}
			if (text4 == "drifter_eyes" && !_loggedEyes)
			{
				_loggedEyes = true;
				Texture val6 = (val2.HasProperty("_EmissiveColorMap") ? val2.GetTexture("_EmissiveColorMap") : null);
				Plugin.Log.LogInfo((object)("  eyes: emissive map = " + (((Object)(object)val6 == (Object)null) ? "NONE" : ((Object)val6).name) + ", _EMISSIVE_COLOR_MAP keyword = " + val2.IsKeywordEnabled("_EMISSIVE_COLOR_MAP") + ", emissive colour = " + ((object)val2.GetColor("_EmissiveColor")/*cast due to .constrained prefix*/).ToString()));
			}
			return val2;
		}

		private static Texture2D Tex(string key)
		{
			if (!Plugin.Textures.TryGetValue(key, out var value))
			{
				return null;
			}
			return value;
		}

		private static bool SetTex(Material m, Texture2D t, params string[] props)
		{
			if ((Object)(object)t == (Object)null)
			{
				return false;
			}
			bool result = false;
			foreach (string text in props)
			{
				if (m.HasProperty(text))
				{
					m.SetTexture(text, (Texture)(object)t);
					result = true;
				}
			}
			return result;
		}

		private static void SetColor(Material m, Color c, params string[] props)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			foreach (string text in props)
			{
				if (m.HasProperty(text))
				{
					m.SetColor(text, c);
				}
			}
		}
	}
	internal static class DrifterVoice
	{
		private static readonly FieldInfo FAngerVoice = AccessTools.Field(typeof(FlowermanAI), "creatureAngerVoice");

		private static readonly FieldInfo FCrackNeck = AccessTools.Field(typeof(FlowermanAI), "crackNeckSFX");

		private static readonly FieldInfo FStunSFX = AccessTools.Field(typeof(EnemyType), "stunSFX");

		private static readonly FieldInfo FClips = AccessTools.Field(typeof(EnemyType), "audioClips");

		private static readonly FieldInfo FAngerMode = AccessTools.Field(typeof(FlowermanAI), "isInAngerMode");

		private static bool _stunDone;

		private static bool _loggedClips;

		internal static bool Enabled
		{
			get
			{
				if (Plugin.ReplaceVoice != null && Plugin.ReplaceVoice.Value)
				{
					return Plugin.Voice.Count > 0;
				}
				return false;
			}
		}

		internal static AudioClip Pick(string category)
		{
			if (!Plugin.Voice.TryGetValue(category, out var value) || value.Count == 0)
			{
				return null;
			}
			return value[Random.Range(0, value.Count)];
		}

		internal static void FillState(EnemyAI ai)
		{
			if ((Object)(object)ai == (Object)null || (Object)(object)ai.enemyType == (Object)null || FClips == null || !(FClips.GetValue(ai.enemyType) is AudioClip[] array))
			{
				return;
			}
			bool flag = FAngerMode != null && ai is FlowermanAI && (bool)FAngerMode.GetValue(ai);
			string category = (flag ? "enraged" : "spotted");
			for (int i = 0; i < array.Length; i++)
			{
				AudioClip val = Pick(category) ?? Pick("spotted") ?? Pick("enraged");
				if ((Object)(object)val != (Object)null)
				{
					array[i] = val;
				}
			}
			if (!_loggedClips)
			{
				_loggedClips = true;
				Plugin.Log.LogInfo((object)("Voice: enemyType.audioClips has " + array.Length + " slot(s), all filled from state (angry=" + flag + ")"));
			}
			if (!_stunDone && FStunSFX != null)
			{
				AudioClip val2 = Pick("stunned");
				if ((Object)(object)val2 != (Object)null)
				{
					FStunSFX.SetValue(ai.enemyType, val2);
					_stunDone = true;
				}
			}
		}

		internal static void SetAngerVoice(FlowermanAI f)
		{
			if (!((Object)(object)f == (Object)null) && !(FAngerVoice == null))
			{
				object? value = FAngerVoice.GetValue(f);
				AudioSource val = (AudioSource)((value is AudioSource) ? value : null);
				AudioClip val2 = Pick("enraged");
				if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
				{
					val.clip = val2;
				}
			}
		}

		internal static void SetKillVoice(FlowermanAI f)
		{
			if (!((Object)(object)f == (Object)null) && !(FCrackNeck == null))
			{
				AudioClip val = Pick("kill");
				if ((Object)(object)val != (Object)null)
				{
					FCrackNeck.SetValue(f, val);
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemyAI), "PlayAudioOfCurrentState")]
	internal static class VoiceStatePatch
	{
		private static void Prefix(EnemyAI __instance)
		{
			if (DrifterVoice.Enabled && __instance is FlowermanAI)
			{
				DrifterVoice.FillState(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(FlowermanAI), "EnterAngerModeClientRpc")]
	internal static class VoiceAngerPatch
	{
		private static void Prefix(FlowermanAI __instance)
		{
			if (DrifterVoice.Enabled)
			{
				DrifterVoice.FillState((EnemyAI)(object)__instance);
				DrifterVoice.SetAngerVoice(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(FlowermanAI), "KillPlayerAnimationClientRpc")]
	internal static class VoiceKillPatch
	{
		private static void Prefix(FlowermanAI __instance)
		{
			if (DrifterVoice.Enabled)
			{
				DrifterVoice.SetKillVoice(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(EnemyAI), "SetEnemyStunned")]
	internal static class VoiceStunPatch
	{
		private static void Prefix(EnemyAI __instance)
		{
			if (DrifterVoice.Enabled && __instance is FlowermanAI)
			{
				DrifterVoice.FillState(__instance);
			}
		}
	}
	[BepInPlugin("drifterbracken", "Drifter Bracken", "1.18.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "drifterbracken";

		internal static ManualLogSource Log;

		internal static readonly Dictionary<string, Mesh> Meshes = new Dictionary<string, Mesh>();

		internal static readonly Dictionary<string, string[]> MaterialNames = new Dictionary<string, string[]>();

		internal static readonly Dictionary<string, Texture2D> Textures = new Dictionary<string, Texture2D>();

		internal static readonly Dictionary<string, List<AudioClip>> Voice = new Dictionary<string, List<AudioClip>>();

		internal static ConfigEntry<float> EyeBrightness;

		internal static ConfigEntry<float> Smoothness;

		internal static ConfigEntry<bool> HideOriginal;

		internal static ConfigEntry<bool> ReplaceVoice;

		internal static ConfigEntry<bool> TestAutoStart;

		internal static ConfigEntry<bool> RecordPoses;

		internal static ConfigEntry<float> TestHold;

		internal static ConfigEntry<KeyboardShortcut> TestToggle;

		internal static ConfigEntry<KeyboardShortcut> TestNext;

		internal static ConfigEntry<KeyboardShortcut> TestPrev;

		internal static ConfigEntry<KeyboardShortcut> TestPause;

		internal static ConfigEntry<KeyboardShortcut> HoldKey;

		internal static bool TestActive;

		internal static bool HoldActive;

		private static int _step;

		private static int _stepFrame = -1;

		private static int _pauseFrame = -1;

		private static readonly Dictionary<KeyCode, Key> KeyFixups = new Dictionary<KeyCode, Key>
		{
			{
				(KeyCode)13,
				(Key)2
			},
			{
				(KeyCode)271,
				(Key)77
			},
			{
				(KeyCode)306,
				(Key)55
			},
			{
				(KeyCode)305,
				(Key)56
			},
			{
				(KeyCode)96,
				(Key)4
			},
			{
				(KeyCode)316,
				(Key)74
			}
		};

		private static readonly Dictionary<string, bool> _held = new Dictionary<string, bool>();

		private static bool _kbLogged;

		private static float _kbNag;

		private static int _polledFrame = -1;

		private static int _tick;

		internal static bool ConsumeStep(out int step)
		{
			step = _step;
			if (_stepFrame == Time.frameCount)
			{
				return _step != 0;
			}
			return false;
		}

		internal static bool ConsumePause()
		{
			return _pauseFrame == Time.frameCount;
		}

		private unsafe static Key ToKey(KeyCode c)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			if (KeyFixups.TryGetValue(c, out var value))
			{
				return value;
			}
			string text = ((object)(*(KeyCode*)(&c))/*cast due to .constrained prefix*/).ToString();
			if (text.StartsWith("Alpha"))
			{
				text = "Digit" + text.Substring(5);
			}
			else if (text.StartsWith("Keypad"))
			{
				text = "Numpad" + text.Substring(6);
			}
			if (!Enum.TryParse<Key>(text, out value))
			{
				return (Key)0;
			}
			return value;
		}

		private static Keyboard Kb()
		{
			return Keyboard.current ?? InputSystem.GetDevice<Keyboard>();
		}

		internal static bool Pressed(ConfigEntry<KeyboardShortcut> e)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			Keyboard val = Kb();
			if (val == null)
			{
				return false;
			}
			KeyboardShortcut value = e.Value;
			Key val2 = ToKey(((KeyboardShortcut)(ref value)).MainKey);
			if ((int)val2 == 0)
			{
				return false;
			}
			bool flag = ((ButtonControl)val[val2]).isPressed;
			if (flag)
			{
				value = e.Value;
				foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
				{
					Key val3 = ToKey(modifier);
					if ((int)val3 != 0 && !((ButtonControl)val[val3]).isPressed)
					{
						flag = false;
						break;
					}
				}
			}
			string key = ((ConfigEntryBase)e).Definition.Section + "/" + ((ConfigEntryBase)e).Definition.Key;
			_held.TryGetValue(key, out var value2);
			_held[key] = flag;
			if (flag)
			{
				return !value2;
			}
			return false;
		}

		private static void KeyboardDiagnostics()
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			Keyboard val = Kb();
			if (val != null)
			{
				if (!_kbLogged)
				{
					_kbLogged = true;
					Log.LogInfo((object)("Keyboard found: '" + ((InputControl)val).name + "', Input System updateMode=" + ((object)InputSystem.settings.updateMode/*cast due to .constrained prefix*/).ToString() + ". Hotkeys are live."));
				}
				return;
			}
			_kbNag += Time.unscaledDeltaTime;
			if (!(_kbNag < 15f))
			{
				_kbNag = 0f;
				Log.LogWarning((object)("Input System has no keyboard device yet, so hotkeys cannot fire. Devices: " + string.Join(", ", ((IEnumerable<InputDevice>)(object)InputSystem.devices).Select((InputDevice d) => ((InputControl)d).name).ToArray())));
			}
		}

		private void Awake()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Expected O, but got Unknown
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: 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)
			Log = ((BaseUnityPlugin)this).Logger;
			Smoothness = ((BaseUnityPlugin)this).Config.Bind<float>("Look", "Smoothness", 0.35f, new ConfigDescription("Surface smoothness. The Drifter's roughness maps aren't shipped, so this is a flat value.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			EyeBrightness = ((BaseUnityPlugin)this).Config.Bind<float>("Look", "EyeBrightness", 2f, new ConfigDescription("How bright the eyes render. They are unlit, so this is their brightness in any light. 1 is the texture as authored, higher blooms, 0 goes black.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 8f), Array.Empty<object>()));
			ReplaceVoice = ((BaseUnityPlugin)this).Config.Bind<bool>("Look", "ReplaceVoice", true, "Give the Bracken the Drifter's voice - stalking, anger, the neck snap and being stunned. Turn off to keep the vanilla sounds.");
			HideOriginal = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "HideOriginalBracken", true, "Hide the vanilla Bracken mesh. Turn off to see both models overlaid while tuning.");
			TestAutoStart = ((BaseUnityPlugin)this).Config.Bind<bool>("TestMode", "AutoStart", false, "Start every Bracken frozen and cycling its animations, without pressing the toggle key.");
			RecordPoses = ((BaseUnityPlugin)this).Config.Bind<bool>("TestMode", "RecordPoses", true, "While cycling, sample the Bracken's skeleton and write bracken_anim.json next to the plugin. The standalone retarget test scene replays that file, so the animations can be inspected without launching the game.");
			TestHold = ((BaseUnityPlugin)this).Config.Bind<float>("TestMode", "HoldSeconds", 1f, new ConfigDescription("Extra pause after each clip finishes before the next one starts.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
			HoldKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("TestMode", "HoldStillKey", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Freeze every Bracken where it stands, on its pose, without cycling animations. Its AI is off while held, so it will not chase or kill - walk up and look at it.");
			TestToggle = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("TestMode", "ToggleKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Freeze every Bracken in place and cycle through all of its animations.");
			TestNext = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("TestMode", "NextKey", new KeyboardShortcut((KeyCode)290, Array.Empty<KeyCode>()), "Step to the next animation.");
			TestPrev = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("TestMode", "PrevKey", new KeyboardShortcut((KeyCode)291, Array.Empty<KeyCode>()), "Step to the previous animation.");
			TestPause = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("TestMode", "PauseKey", new KeyboardShortcut((KeyCode)292, Array.Empty<KeyCode>()), "Hold the current animation instead of advancing.");
			if (LoadBundle())
			{
				TestActive = TestAutoStart.Value;
				new Harmony("drifterbracken").PatchAll(Assembly.GetExecutingAssembly());
				Log.LogInfo((object)("Drifter Bracken ready. Hold still: " + ((object)HoldKey.Value/*cast due to .constrained prefix*/).ToString() + ", test mode: " + ((object)TestToggle.Value/*cast due to .constrained prefix*/).ToString() + ". Waiting for the Input System to report a keyboard."));
			}
		}

		private void Update()
		{
			PollHotkeys();
		}

		internal static void PollHotkeys()
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			if (_polledFrame == Time.frameCount)
			{
				return;
			}
			_polledFrame = Time.frameCount;
			if (_tick < 3)
			{
				_tick++;
				Keyboard val = Kb();
				Log.LogInfo((object)("Hotkey poll " + _tick + ": keyboard=" + ((val == null) ? "null" : ((InputControl)val).name) + ", devices=" + InputSystem.devices.Count));
			}
			KeyboardDiagnostics();
			if (Pressed(HoldKey))
			{
				HoldActive = !HoldActive;
				Log.LogInfo((object)("Hold still " + (HoldActive ? "ON" : "OFF")));
			}
			if (Pressed(TestToggle))
			{
				TestActive = !TestActive;
				Log.LogInfo((object)("Test mode " + (TestActive ? "ON" : "OFF")));
			}
			if (TestActive)
			{
				_step = 0;
				if (Pressed(TestNext))
				{
					_step = 1;
					_stepFrame = Time.frameCount;
				}
				else if (Pressed(TestPrev))
				{
					_step = -1;
					_stepFrame = Time.frameCount;
				}
				if (Pressed(TestPause))
				{
					_pauseFrame = Time.frameCount;
				}
			}
		}

		private bool LoadBundle()
		{
			string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "drifterbracken");
			if (!File.Exists(text))
			{
				Log.LogError((object)("Asset bundle missing - expected it next to the plugin at '" + text + "'."));
				return false;
			}
			AssetBundle val = AssetBundle.LoadFromFile(text);
			if ((Object)(object)val == (Object)null)
			{
				Log.LogError((object)"Asset bundle failed to load (built for the wrong Unity version?).");
				return false;
			}
			Mesh[] array = val.LoadAllAssets<Mesh>();
			foreach (Mesh val2 in array)
			{
				if (((Object)val2).name.EndsWith("_rebound"))
				{
					Meshes[((Object)val2).name.Substring(0, ((Object)val2).name.Length - "_rebound".Length)] = val2;
				}
			}
			GameObject[] array2 = val.LoadAllAssets<GameObject>();
			for (int i = 0; i < array2.Length; i++)
			{
				SkinnedMeshRenderer[] componentsInChildren = array2[i].GetComponentsInChildren<SkinnedMeshRenderer>(true);
				foreach (SkinnedMeshRenderer val3 in componentsInChildren)
				{
					MaterialNames[((Object)val3).name] = ((Renderer)val3).sharedMaterials.Select((Material x) => (!((Object)(object)x != (Object)null)) ? "" : ((Object)x).name).ToArray();
				}
			}
			Texture2D[] array3 = val.LoadAllAssets<Texture2D>();
			foreach (Texture2D val4 in array3)
			{
				Textures[((Object)val4).name] = val4;
			}
			AudioClip[] array4 = val.LoadAllAssets<AudioClip>();
			foreach (AudioClip val5 in array4)
			{
				string key = ((Object)val5).name.Split('_')[0];
				if (!Voice.TryGetValue(key, out var value))
				{
					value = (Voice[key] = new List<AudioClip>());
				}
				value.Add(val5);
			}
			if (Voice.Count > 0)
			{
				Log.LogInfo((object)("Voice lines: " + string.Join(", ", (from kv in Voice
					orderby kv.Key
					select kv.Key + " x" + kv.Value.Count).ToArray())));
			}
			if (Meshes.Count == 0)
			{
				Log.LogError((object)"No pre-bound meshes in the bundle.");
				return false;
			}
			Log.LogInfo((object)($"Loaded {Meshes.Count} pre-bound meshes and {Textures.Count} textures: " + string.Join(", ", Meshes.Keys.ToArray())));
			return true;
		}
	}
	[HarmonyPatch]
	internal static class FlowermanStartPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.DeclaredMethod(typeof(FlowermanAI), "Start", (Type[])null, (Type[])null) ?? AccessTools.Method(typeof(EnemyAI), "Start", (Type[])null, (Type[])null);
		}

		private static void Postfix(EnemyAI __instance)
		{
			if (__instance is FlowermanAI && !((Object)(object)((Component)__instance).GetComponent<DrifterBrackenSkin>() != (Object)null))
			{
				((Component)__instance).gameObject.AddComponent<DrifterBrackenSkin>();
				((Component)__instance).gameObject.AddComponent<BrackenAnimTester>();
			}
		}
	}
	[Serializable]
	public class PoseFrame
	{
		public float[] r;

		public float[] p;
	}
	[Serializable]
	public class PoseClip
	{
		public string name;

		public float fps;

		public PoseFrame[] frames;
	}
	[Serializable]
	public class PoseRecording
	{
		public string[] bones;

		public PoseClip[] clips;
	}
}