Decompiled source of DrifterBracken v2.2.0

DrifterBracken.dll

Decompiled a month 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 HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
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("2.0.1.0")]
[assembly: AssemblyInformationalVersion("2.0.1")]
[assembly: AssemblyProduct("DrifterBracken")]
[assembly: AssemblyTitle("DrifterBracken")]
[assembly: AssemblyVersion("2.0.1.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
{
	internal static class AudioHook
	{
		private static readonly Dictionary<int, FlowermanAI> AngerSources = new Dictionary<int, FlowermanAI>();

		private static readonly HashSet<int> Steps = new HashSet<int>();

		private static readonly HashSet<int> Ours = new HashSet<int>();

		private static readonly Dictionary<int, FlowermanAI> Owners = new Dictionary<int, FlowermanAI>();

		private static float _lastStep = -99f;

		internal static void Reset()
		{
			AngerSources.Clear();
			Steps.Clear();
		}

		internal static void Register(FlowermanAI f, AudioSource anger)
		{
			if ((Object)(object)anger != (Object)null && (Object)(object)f != (Object)null)
			{
				AngerSources[((Object)anger).GetInstanceID()] = f;
			}
			if (Steps.Count == 0 && Plugin.Voice.TryGetValue("footstep", out var value))
			{
				foreach (AudioClip item in value)
				{
					if ((Object)(object)item != (Object)null)
					{
						Steps.Add(((Object)item).GetInstanceID());
					}
				}
			}
			if (Ours.Count != 0)
			{
				return;
			}
			foreach (KeyValuePair<string, List<AudioClip>> item2 in Plugin.Voice)
			{
				foreach (AudioClip item3 in item2.Value)
				{
					if ((Object)(object)item3 != (Object)null)
					{
						Ours.Add(((Object)item3).GetInstanceID());
					}
				}
			}
		}

		private static FlowermanAI Owner(AudioSource src)
		{
			if ((Object)(object)src == (Object)null)
			{
				return null;
			}
			int instanceID = ((Object)src).GetInstanceID();
			if (Owners.TryGetValue(instanceID, out var value))
			{
				return value;
			}
			value = ((Component)src).GetComponentInParent<FlowermanAI>();
			Owners[instanceID] = value;
			return value;
		}

		private static AudioClip Swap(AudioSource src, AudioClip clip)
		{
			if ((Object)(object)clip == (Object)null)
			{
				return null;
			}
			if (Ours.Contains(((Object)clip).GetInstanceID()))
			{
				return null;
			}
			FlowermanAI val = Owner(src);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			return DrifterVoice.Pick(DrifterVoice.IsAngry((EnemyAI)(object)val) ? "enraged" : "spotted");
		}

		private static bool Angry(FlowermanAI f)
		{
			try
			{
				return DrifterVoice.IsAngry((EnemyAI)(object)f);
			}
			catch
			{
				return false;
			}
		}

		internal static void OnPlay(AudioSource src)
		{
			if ((Object)(object)src == (Object)null || !DrifterVoice.Enabled)
			{
				return;
			}
			if (AngerSources.TryGetValue(((Object)src).GetInstanceID(), out var value))
			{
				AudioClip val = DrifterVoice.Pick(Angry(value) ? "enraged" : "spotted");
				if ((Object)(object)val != (Object)null)
				{
					src.clip = val;
					src.loop = false;
				}
			}
			else
			{
				AudioClip val2 = Swap(src, src.clip);
				if ((Object)(object)val2 != (Object)null)
				{
					src.clip = val2;
					src.loop = false;
				}
			}
		}

		internal static bool OnOneShot(AudioSource src, ref AudioClip clip, ref float volumeScale)
		{
			if ((Object)(object)clip == (Object)null || !DrifterVoice.Enabled)
			{
				return true;
			}
			if (Steps.Contains(((Object)clip).GetInstanceID()))
			{
				if (Time.time - _lastStep < 0.28f)
				{
					return false;
				}
				_lastStep = Time.time;
				volumeScale *= 0.45f;
				return true;
			}
			AudioClip val = Swap(src, clip);
			if ((Object)(object)val != (Object)null)
			{
				clip = val;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(AudioSource), "Play", new Type[] { })]
	internal static class AudioPlayPatch
	{
		private static void Prefix(AudioSource __instance)
		{
			AudioHook.OnPlay(__instance);
		}
	}
	[HarmonyPatch(typeof(AudioSource), "PlayOneShot", new Type[]
	{
		typeof(AudioClip),
		typeof(float)
	})]
	internal static class AudioOneShotPatch
	{
		private static bool Prefix(AudioSource __instance, ref AudioClip clip, ref float volumeScale)
		{
			return AudioHook.OnOneShot(__instance, ref clip, ref volumeScale);
		}
	}
	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 bool _stepsDone;

		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 void Start()
		{
			try
			{
				Setup();
			}
			catch
			{
			}
		}

		private void Setup()
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_010f: 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)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			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();
			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)
				{
					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);
				}
			}
			_mine = list.ToArray();
			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()
		{
			_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 (!_stepsDone && (Object)(object)_ai != (Object)null)
					{
						DrifterVoice.SetFootsteps(_ai);
						EnemyAI ai = _ai;
						EnemyAI f = ((ai is FlowermanAI) ? ai : null);
						AudioHook.Register((FlowermanAI)(object)f, DrifterVoice.AngerSource((FlowermanAI)(object)f));
						_stepsDone = true;
					}
				}
			}
			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;
				}
			}
			for (int j = 0; j < _hidden.Length; j++)
			{
				if ((Object)(object)_hidden[j] != (Object)null)
				{
					_hidden[j].forceRenderingOff = true;
				}
			}
		}

		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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: 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);
			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 t = Tex(text4);
			SetTex(val2, t, "_BaseColorMap", "_MainTex", "_BaseMap");
			SetColor(val2, Color.white, "_BaseColor", "_Color");
			if (text4 == "drifter_head")
			{
				Texture2D val3 = Tex("drifter_head_normal");
				if ((Object)(object)val3 != (Object)null && SetTex(val2, val3, "_NormalMap", "_BumpMap"))
				{
					val2.EnableKeyword("_NORMALMAP");
				}
			}
			if (val2.HasProperty("_Smoothness"))
			{
				val2.SetFloat("_Smoothness", 0.35f);
			}
			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);
				}
				Texture2D val4 = Tex("drifter_eyes");
				if ((Object)(object)val4 != (Object)null)
				{
					SetTex(val2, val4, "_EmissiveColorMap", "_EmissionMap");
					SetColor(val2, Color.white * 2f, "_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
			{
			}
			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 readonly FieldInfo FStates = AccessTools.Field(typeof(EnemyAI), "enemyBehaviourStates");

		private static readonly FieldInfo FCurState = AccessTools.Field(typeof(EnemyAI), "currentBehaviourState");

		private static readonly FieldInfo FVoiceClip = AccessTools.Field(typeof(EnemyBehaviourState), "VoiceClip");

		private static readonly FieldInfo FStateName = AccessTools.Field(typeof(EnemyBehaviourState), "name");

		private static readonly FieldInfo FSfxClip = AccessTools.Field(typeof(EnemyBehaviourState), "SFXClip");

		private static readonly FieldInfo FRandom1 = AccessTools.Field(typeof(PlayAudioAnimationEvent), "randomClips");

		private static readonly FieldInfo FRandom2 = AccessTools.Field(typeof(PlayAudioAnimationEvent), "randomClips2");

		private static bool _stunDone;

		internal static bool Enabled => Plugin.Voice.Count > 0;

		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 bool IsAngry(EnemyAI ai)
		{
			if (FAngerMode != null && ai is FlowermanAI)
			{
				return (bool)FAngerMode.GetValue(ai);
			}
			return false;
		}

		internal static AudioSource AngerSource(FlowermanAI f)
		{
			if (!((Object)(object)f != (Object)null) || !(FAngerVoice != null))
			{
				return null;
			}
			object? value = FAngerVoice.GetValue(f);
			return (AudioSource)((value is AudioSource) ? value : null);
		}

		internal static void FillState(EnemyAI ai)
		{
			if ((Object)(object)ai == (Object)null)
			{
				return;
			}
			bool angry = FAngerMode != null && ai is FlowermanAI && (bool)FAngerMode.GetValue(ai);
			if (FVoiceClip != null)
			{
				object obj = ((FCurState != null) ? FCurState.GetValue(ai) : null);
				if (obj != null)
				{
					Silence(obj);
				}
				Array array = ((FStates != null) ? (FStates.GetValue(ai) as Array) : null);
				if (array != null)
				{
					for (int i = 0; i < array.Length; i++)
					{
						object value = array.GetValue(i);
						if (value != null)
						{
							Silence(value);
						}
					}
				}
			}
			SetAngerVoice((FlowermanAI)(object)((ai is FlowermanAI) ? ai : null), angry);
			if (!_stunDone && FStunSFX != null && (Object)(object)ai.enemyType != (Object)null)
			{
				AudioClip val = Pick("stunned");
				if ((Object)(object)val != (Object)null)
				{
					FStunSFX.SetValue(ai.enemyType, val);
					_stunDone = true;
				}
			}
		}

		private static void Silence(object state)
		{
			if (FVoiceClip != null)
			{
				FVoiceClip.SetValue(state, null);
			}
			if (FSfxClip != null)
			{
				FSfxClip.SetValue(state, null);
			}
		}

		internal static void SetAngerVoice(FlowermanAI f, bool angry)
		{
			if ((Object)(object)f == (Object)null || FAngerVoice == null)
			{
				return;
			}
			object? value = FAngerVoice.GetValue(f);
			AudioSource val = (AudioSource)((value is AudioSource) ? value : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			string text = (angry ? "enraged" : "spotted");
			if (!((Object)(object)val.clip != (Object)null) || !Plugin.Voice.TryGetValue(text, out var value2) || !value2.Contains(val.clip) || !val.isPlaying)
			{
				AudioClip val2 = Pick(text);
				if ((Object)(object)val2 != (Object)null)
				{
					val.clip = val2;
					val.loop = false;
				}
			}
		}

		internal static void SetFootsteps(EnemyAI ai)
		{
			if ((Object)(object)ai == (Object)null || !Plugin.Voice.TryGetValue("footstep", out var value) || value.Count == 0 || (FRandom1 == null && FRandom2 == null))
			{
				return;
			}
			Animator componentInChildren = ((Component)ai).GetComponentInChildren<Animator>(true);
			PlayAudioAnimationEvent[] array = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).GetComponents<PlayAudioAnimationEvent>() : ((Component)ai).GetComponentsInChildren<PlayAudioAnimationEvent>(true));
			if (array == null || array.Length == 0)
			{
				return;
			}
			AudioClip[] value2 = value.ToArray();
			PlayAudioAnimationEvent[] array2 = array;
			foreach (PlayAudioAnimationEvent val in array2)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				FieldInfo[] array3 = new FieldInfo[2] { FRandom1, FRandom2 };
				foreach (FieldInfo fieldInfo in array3)
				{
					if (!(fieldInfo == null) && fieldInfo.GetValue(val) is AudioClip[] array4 && array4.Length != 0)
					{
						fieldInfo.SetValue(val, value2);
					}
				}
			}
		}

		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, angry: true);
			}
		}
	}
	[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", "2.0.1")]
	public class Plugin : BaseUnityPlugin
	{
		internal static class Tuning
		{
			public const float Smoothness = 0.35f;

			public const float EyeBrightness = 2f;

			public const float FootstepVolume = 0.45f;

			public const float FootstepMinGap = 0.28f;
		}

		public const string Guid = "drifterbracken";

		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>>();

		private void Awake()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (LoadBundle())
			{
				new Harmony("drifterbracken").PatchAll(Assembly.GetExecutingAssembly());
			}
		}

		private bool LoadBundle()
		{
			string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "drifterbracken");
			if (!File.Exists(text))
			{
				return false;
			}
			AssetBundle val = AssetBundle.LoadFromFile(text);
			if ((Object)(object)val == (Object)null)
			{
				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);
			}
			return Meshes.Count > 0;
		}
	}
	[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>();
			}
		}
	}
}