Decompiled source of BobaBees v1.0.0

BobaBees.dll

Decompiled 2 hours ago
using System;
using System.Collections;
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 GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Audio;
using UnityEngine.Networking;
using UnityEngine.Rendering;
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("BobaBees")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ec315e338f23562674ae8651f8f7d0f3e363e8c2")]
[assembly: AssemblyProduct("BobaBees")]
[assembly: AssemblyTitle("BobaBees")]
[assembly: AssemblyVersion("1.0.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 BobaBees
{
	internal enum Face
	{
		Neutral,
		Angry,
		Crying
	}
	internal static class Assets
	{
		private class Loader : MonoBehaviour
		{
		}

		private static readonly string[] FaceFiles = new string[3] { "neutral.png", "angry.png", "crying.png" };

		private static readonly Texture2D[] Textures = (Texture2D[])(object)new Texture2D[3];

		private static Material[] materials;

		private static bool materialsFailed;

		public static AudioClip Attack;

		public static AudioClip[] Idle = (AudioClip[])(object)new AudioClip[0];

		private static readonly string[] ExtraKeywords = new string[14]
		{
			"_SURFACE_TYPE_TRANSPARENT", "_NORMALMAP", "_NORMALMAP_TANGENT_SPACE", "_MASKMAP", "_EMISSIVE_COLOR_MAP", "_DETAIL_MAP", "_HEIGHTMAP", "_BENTNORMALMAP", "_SPECULARCOLORMAP", "_MATERIAL_FEATURE_SUBSURFACE_SCATTERING",
			"_MATERIAL_FEATURE_TRANSMISSION", "_MATERIAL_FEATURE_IRIDESCENCE", "_PIXEL_DISPLACEMENT", "_VERTEX_DISPLACEMENT"
		};

		public static void Init(string dir)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Expected O, but got Unknown
			//IL_00d7: 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_004f: Expected O, but got Unknown
			for (int i = 0; i < 3; i++)
			{
				string text = Find(dir, "Faces", FaceFiles[i]).FirstOrDefault();
				if (text == null)
				{
					Plugin.Log.LogError((object)("Missing face " + FaceFiles[i] + " under " + dir));
					continue;
				}
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true);
				ImageConversion.LoadImage(val, File.ReadAllBytes(text), false);
				((Object)val).name = "BeeFace_" + FaceFiles[i];
				((Texture)val).wrapMode = (TextureWrapMode)1;
				((Texture)val).filterMode = (FilterMode)2;
				((Texture)val).anisoLevel = 2;
				if (((Texture)val).width % 4 == 0 && ((Texture)val).height % 4 == 0)
				{
					val.Compress(true);
				}
				val.Apply(false, true);
				((Object)val).hideFlags = (HideFlags)61;
				Textures[i] = val;
			}
			GameObject val2 = new GameObject("BobaBees.Loader");
			Object.DontDestroyOnLoad((Object)val2);
			((Object)val2).hideFlags = (HideFlags)61;
			((MonoBehaviour)val2.AddComponent<Loader>()).StartCoroutine(LoadAudio(dir));
		}

		private static string[] Find(string dir, string sub, string pattern)
		{
			try
			{
				string path = Path.Combine(dir, sub);
				string[] array = (Directory.Exists(path) ? Directory.GetFiles(path, pattern) : new string[0]);
				if (array.Length == 0)
				{
					array = Directory.GetFiles(dir, pattern);
				}
				if (array.Length == 0)
				{
					array = Directory.GetFiles(dir, pattern, SearchOption.AllDirectories);
				}
				return (from g in array.GroupBy(Path.GetFileName)
					select g.First()).ToArray();
			}
			catch
			{
				return new string[0];
			}
		}

		private static IEnumerator LoadAudio(string dir)
		{
			string text = Find(dir, "Audio", "attack.*").FirstOrDefault();
			if (text != null)
			{
				yield return Load(text, delegate(AudioClip c)
				{
					Attack = c;
				});
			}
			else
			{
				Plugin.Log.LogError((object)("Missing attack.mp3 under " + dir));
			}
			List<AudioClip> idle = new List<AudioClip>();
			foreach (string item in from x in Find(dir, "Audio", "idle*.*")
				orderby Path.GetFileName(x)
				select x)
			{
				yield return Load(item, delegate(AudioClip c)
				{
					idle.Add(c);
				});
			}
			Idle = idle.ToArray();
			Plugin.Log.LogInfo((object)string.Format("Audio loaded: attack={0}, idle clips={1}", ((Object)(object)Attack != (Object)null) ? $"{Attack.length:0}s" : "MISSING", Idle.Length));
		}

		private static IEnumerator Load(string path, Action<AudioClip> done)
		{
			string text = Path.GetExtension(path).ToLowerInvariant();
			AudioType val = (AudioType)((text == ".mp3") ? 13 : ((text == ".ogg") ? 14 : 20));
			UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip(new Uri(path).AbsoluteUri, val);
			try
			{
				DownloadHandlerAudioClip dh = (DownloadHandlerAudioClip)req.downloadHandler;
				dh.compressed = (int)val == 13;
				yield return req.SendWebRequest();
				if ((int)req.result != 1)
				{
					Plugin.Log.LogError((object)("Audio " + path + ": " + req.error));
					yield break;
				}
				AudioClip audioClip = dh.audioClip;
				if ((Object)(object)audioClip == (Object)null)
				{
					Plugin.Log.LogError((object)("Audio decode failed: " + path));
					yield break;
				}
				((Object)audioClip).name = Path.GetFileNameWithoutExtension(path);
				((Object)audioClip).hideFlags = (HideFlags)61;
				done(audioClip);
			}
			finally
			{
				((IDisposable)req)?.Dispose();
			}
		}

		public static Material Get(Face face)
		{
			if (materials == null && !materialsFailed)
			{
				Build();
			}
			Material[] array = materials;
			if (array == null)
			{
				return null;
			}
			return array[(int)face];
		}

		private static void Build()
		{
			//IL_0089: 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_0090: Expected O, but got Unknown
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Material val = ((IEnumerable<Material>)Resources.FindObjectsOfTypeAll<Material>()).FirstOrDefault((Func<Material, bool>)((Material m) => (Object)(object)m != (Object)null && (Object)(object)m.shader != (Object)null && ((Object)m.shader).name == "HDRP/Lit" && m.IsKeywordEnabled("_ALPHATEST_ON") && !((IEnumerable<string>)ExtraKeywords).Any((Func<string, bool>)m.IsKeywordEnabled)));
				Shader val2 = (((Object)(object)val != (Object)null) ? val.shader : Shader.Find("HDRP/Lit"));
				if ((Object)(object)val2 == (Object)null)
				{
					materialsFailed = true;
					Plugin.Log.LogError((object)"HDRP/Lit not found; faces disabled.");
					return;
				}
				Material[] array = (Material[])(object)new Material[3];
				for (int num = 0; num < 3; num++)
				{
					Material val3 = (((Object)(object)val != (Object)null) ? new Material(val) : new Material(val2));
					Face face = (Face)num;
					((Object)val3).name = "BeeFace_" + face;
					val3.SetTexture("_BaseColorMap", (Texture)(object)Textures[num]);
					val3.SetTextureScale("_BaseColorMap", Vector2.one);
					val3.SetTextureOffset("_BaseColorMap", Vector2.zero);
					val3.SetColor("_BaseColor", Color.white);
					if (val3.HasProperty("_Metallic"))
					{
						val3.SetFloat("_Metallic", 0f);
					}
					if (val3.HasProperty("_Smoothness"))
					{
						val3.SetFloat("_Smoothness", 0.2f);
					}
					if (val3.HasProperty("_AlphaCutoff"))
					{
						val3.SetFloat("_AlphaCutoff", 0.5f);
					}
					if ((Object)(object)val == (Object)null)
					{
						HDMaterial.SetAlphaClipping(val3, true);
						HDMaterial.SetAlphaCutoff(val3, 0.5f);
						HDMaterial.ValidateMaterial(val3);
					}
					((Object)val3).hideFlags = (HideFlags)61;
					array[num] = val3;
				}
				materials = array;
				Plugin.Log.LogInfo((object)(((Object)(object)val != (Object)null) ? ("Face material cloned from '" + ((Object)val).name + "'.") : "Face material built from HDRP/Lit."));
			}
			catch (Exception ex)
			{
				materialsFailed = true;
				Plugin.Log.LogError((object)("Face materials failed: " + ex));
			}
		}
	}
	public class BeeFaces : MonoBehaviour
	{
		private static readonly FieldRef<RedLocustBees, bool> OverrideTarget = AccessTools.FieldRefAccess<RedLocustBees, bool>("overrideBeeParticleTarget");

		private RedLocustBees bee;

		private Renderer vfxRenderer;

		private GameObject drawGo;

		private Mesh mesh;

		private MeshRenderer mr;

		private int n;

		private Vector3[] pos;

		private Vector3[] verts;

		private Vector3[] normals;

		private Vector3[] dir;

		private Vector3[] axis;

		private float[] seed;

		private float[] spin;

		private float scale = 1f;

		private float leaveRadius;

		private Face face;

		private Face pendingFace;

		private float pendingFaceSince;

		private bool idleMode = true;

		private bool pendingIdle = true;

		private float pendingIdleSince;

		private GameObject audioGo;

		private AudioSource attackSrc;

		private AudioSource idleSrc;

		private bool attackStarted;

		private int lastIdle = -1;

		private bool vanillaMuted;

		private bool ready;

		public void Init(RedLocustBees b)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: 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_0113: 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_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Expected O, but got Unknown
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Expected O, but got Unknown
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Expected O, but got Unknown
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: 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_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			bee = b;
			vfxRenderer = (((Object)(object)b.beeParticles != (Object)null) ? ((Component)b.beeParticles).GetComponent<Renderer>() : null);
			Vector3 val = Centre();
			n = Mathf.Clamp(Plugin.FaceCount.Value, 5, 60);
			pos = (Vector3[])(object)new Vector3[n];
			dir = (Vector3[])(object)new Vector3[n];
			axis = (Vector3[])(object)new Vector3[n];
			seed = new float[n];
			spin = new float[n];
			verts = (Vector3[])(object)new Vector3[n * 4];
			normals = (Vector3[])(object)new Vector3[n * 4];
			Vector2[] array = (Vector2[])(object)new Vector2[n * 4];
			int[] array2 = new int[n * 6];
			for (int i = 0; i < n; i++)
			{
				pos[i] = val + Random.insideUnitSphere * 0.5f;
				dir[i] = Random.onUnitSphere;
				axis[i] = Random.onUnitSphere;
				seed[i] = Random.Range(0f, 100f);
				spin[i] = Random.Range(40f, 140f) * ((Random.value < 0.5f) ? (-1f) : 1f);
				int num = i * 4;
				int num2 = i * 6;
				array[num] = new Vector2(0f, 0f);
				array[num + 1] = new Vector2(1f, 0f);
				array[num + 2] = new Vector2(0f, 1f);
				array[num + 3] = new Vector2(1f, 1f);
				array2[num2] = num;
				array2[num2 + 1] = num + 2;
				array2[num2 + 2] = num + 3;
				array2[num2 + 3] = num;
				array2[num2 + 4] = num + 3;
				array2[num2 + 5] = num + 1;
			}
			mesh = new Mesh
			{
				name = "BeeFacesMesh"
			};
			mesh.MarkDynamic();
			mesh.vertices = verts;
			mesh.uv = array;
			mesh.triangles = array2;
			mesh.normals = normals;
			drawGo = new GameObject("BobaBees.Swarm");
			drawGo.AddComponent<MeshFilter>().sharedMesh = mesh;
			mr = drawGo.AddComponent<MeshRenderer>();
			((Renderer)mr).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)mr).enabled = false;
			audioGo = new GameObject("BobaBees.Audio");
			audioGo.transform.position = val;
			attackSrc = MakeSource(b.beesAngry);
			attackSrc.loop = true;
			idleSrc = MakeSource(b.beesIdle);
			idleSrc.loop = false;
			audioGo.AddComponent<AudioLowPassFilter>().cutoffFrequency = 10000f;
			audioGo.AddComponent<OccludeAudio>();
			if (Plugin.DebugLog.Value)
			{
				DumpVanillaAudio();
			}
			ready = true;
		}

		private AudioSource MakeSource(AudioSource like)
		{
			//IL_0056: 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_0097: Invalid comparison between Unknown and I4
			AudioSource val = audioGo.AddComponent<AudioSource>();
			val.playOnAwake = false;
			val.volume = 0f;
			val.spatialBlend = 1f;
			val.spread = 0f;
			val.dopplerLevel = 0f;
			if ((Object)(object)like != (Object)null)
			{
				val.outputAudioMixerGroup = like.outputAudioMixerGroup;
				val.rolloffMode = like.rolloffMode;
				val.minDistance = like.minDistance;
				val.maxDistance = like.maxDistance;
				val.priority = like.priority;
				val.reverbZoneMix = like.reverbZoneMix;
				if ((int)like.rolloffMode == 2)
				{
					val.SetCustomCurve((AudioSourceCurveType)0, like.GetCustomCurve((AudioSourceCurveType)0));
				}
			}
			else
			{
				val.rolloffMode = (AudioRolloffMode)1;
				val.minDistance = 3f;
				val.maxDistance = 40f;
			}
			return val;
		}

		private Vector3 Centre()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//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_004c: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)bee != (Object)null) || !((Object)(object)bee.beeParticlesTarget != (Object)null))
			{
				return ((Component)this).transform.position + Vector3.up * 1.5f;
			}
			return bee.beeParticlesTarget.position;
		}

		private Face DesiredFace()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			switch (((EnemyAI)bee).currentBehaviourStateIndex)
			{
			case 1:
				return Face.Angry;
			case 2:
				if (OverrideTarget.Invoke(bee) || PlayerNear(Centre(), Plugin.AngryRadius.Value))
				{
					return Face.Angry;
				}
				return Face.Crying;
			default:
				return Face.Neutral;
			}
		}

		private bool DesiredIdle()
		{
			if (((EnemyAI)bee).currentBehaviourStateIndex == 0)
			{
				if (!((Object)(object)bee.hive == (Object)null))
				{
					return !bee.hive.isHeld;
				}
				return true;
			}
			return false;
		}

		private static bool PlayerNear(Vector3 c, float r)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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)
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			PlayerControllerB[] allPlayerScripts = instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if ((Object)(object)val != (Object)null && val.isPlayerControlled && !val.isPlayerDead)
				{
					Vector3 val2 = ((Component)val).transform.position - c;
					if (((Vector3)(ref val2)).sqrMagnitude < r * r)
					{
						return true;
					}
				}
			}
			return false;
		}

		private void UpdateState(float now)
		{
			Face face = DesiredFace();
			if (face != pendingFace)
			{
				pendingFace = face;
				pendingFaceSince = now;
			}
			if (pendingFace != this.face && now - pendingFaceSince > 0.3f)
			{
				this.face = pendingFace;
				if (Plugin.DebugLog.Value)
				{
					Plugin.Log.LogInfo((object)$"Bee {((NetworkBehaviour)bee).NetworkObjectId}: face {this.face} (state {((EnemyAI)bee).currentBehaviourStateIndex})");
				}
			}
			bool flag = DesiredIdle();
			if (flag != pendingIdle)
			{
				pendingIdle = flag;
				pendingIdleSince = now;
			}
			if (pendingIdle != idleMode && now - pendingIdleSince > 0.3f)
			{
				idleMode = pendingIdle;
				if (Plugin.DebugLog.Value)
				{
					Plugin.Log.LogInfo((object)string.Format("Bee {0}: audio {1}", ((NetworkBehaviour)bee).NetworkObjectId, idleMode ? "idle" : "attack"));
				}
			}
		}

		private void LateUpdate()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_005f: 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)
			if (ready && !((Object)(object)bee == (Object)null))
			{
				float time = Time.time;
				float deltaTime = Time.deltaTime;
				UpdateState(time);
				Vector3 val = Centre();
				audioGo.transform.position = Vector3.Lerp(audioGo.transform.position, val, 1f - Mathf.Exp(-8f * deltaTime));
				UpdateAudio(deltaTime);
				UpdateFaces(val, time, deltaTime);
			}
		}

		private void UpdateAudio(float dt)
		{
			bool num = Plugin.AudioEnabled.Value && !((EnemyAI)bee).isEnemyDead;
			bool flag = Plugin.AudioEnabled.Value && ((Object)(object)Assets.Attack != (Object)null || Assets.Idle.Length != 0);
			if (flag != vanillaMuted)
			{
				vanillaMuted = flag;
				if ((Object)(object)bee.beesIdle != (Object)null)
				{
					bee.beesIdle.mute = flag;
				}
				if ((Object)(object)bee.beesDefensive != (Object)null)
				{
					bee.beesDefensive.mute = flag;
				}
				if ((Object)(object)bee.beesAngry != (Object)null)
				{
					bee.beesAngry.mute = flag;
				}
			}
			float num2 = dt * 2f;
			float num3 = ((num && !idleMode) ? Mathf.Clamp01(Plugin.MusicVolume.Value) : 0f);
			float num4 = ((num && idleMode) ? Mathf.Clamp01(Plugin.IdleVolume.Value) : 0f);
			if (num3 > 0f && (Object)(object)Assets.Attack != (Object)null && !attackSrc.isPlaying)
			{
				if (!attackStarted)
				{
					attackSrc.clip = Assets.Attack;
					attackSrc.time = Random.Range(0f, Assets.Attack.length * 0.9f);
					attackStarted = true;
					attackSrc.Play();
				}
				else
				{
					attackSrc.UnPause();
				}
				if (!attackSrc.isPlaying)
				{
					attackSrc.Play();
				}
			}
			attackSrc.volume = Mathf.MoveTowards(attackSrc.volume, num3, num2);
			if (num3 == 0f && attackSrc.isPlaying && attackSrc.volume <= 0f)
			{
				attackSrc.Pause();
			}
			if (num4 > 0f && Assets.Idle.Length != 0 && !idleSrc.isPlaying)
			{
				int num5 = Random.Range(0, Assets.Idle.Length);
				if (Assets.Idle.Length > 1 && num5 == lastIdle)
				{
					num5 = (num5 + 1 + Random.Range(0, Assets.Idle.Length - 1)) % Assets.Idle.Length;
				}
				lastIdle = num5;
				idleSrc.clip = Assets.Idle[num5];
				idleSrc.time = 0f;
				idleSrc.Play();
			}
			idleSrc.volume = Mathf.MoveTowards(idleSrc.volume, num4, num2);
			if (num4 == 0f && idleSrc.isPlaying && idleSrc.volume <= 0f)
			{
				idleSrc.Stop();
			}
		}

		private void UpdateFaces(Vector3 c, float now, float dt)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: 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_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_0356: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_038c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0391: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03de: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e7: 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_03ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0419: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_041c: Unknown result type (might be due to invalid IL or missing references)
			//IL_041e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0423: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Unknown result type (might be due to invalid IL or missing references)
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_0428: Unknown result type (might be due to invalid IL or missing references)
			//IL_042d: Unknown result type (might be due to invalid IL or missing references)
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0430: Unknown result type (might be due to invalid IL or missing references)
			//IL_0432: Unknown result type (might be due to invalid IL or missing references)
			//IL_0437: Unknown result type (might be due to invalid IL or missing references)
			//IL_0439: Unknown result type (might be due to invalid IL or missing references)
			Material val = (Plugin.FacesEnabled.Value ? Assets.Get(face) : null);
			bool flag = (Object)(object)bee.beeParticles == (Object)null || bee.beeParticles.GetBool("Alive");
			Camera val2 = (((Object)(object)StartOfRound.Instance != (Object)null && (Object)(object)StartOfRound.Instance.activeCamera != (Object)null) ? StartOfRound.Instance.activeCamera : Camera.main);
			Vector3 val3;
			int num;
			if ((Object)(object)val != (Object)null && flag && !((EnemyAI)bee).isEnemyDead && (Object)(object)val2 != (Object)null)
			{
				val3 = ((Component)val2).transform.position - c;
				num = ((((Vector3)(ref val3)).sqrMagnitude < 8100f) ? 1 : 0);
			}
			else
			{
				num = 0;
			}
			bool flag2 = (byte)num != 0;
			if ((Object)(object)vfxRenderer != (Object)null)
			{
				vfxRenderer.enabled = (Object)(object)val == (Object)null;
			}
			else if ((Object)(object)bee.beeParticles != (Object)null)
			{
				((Behaviour)bee.beeParticles).enabled = (Object)(object)val == (Object)null;
			}
			((Renderer)mr).enabled = flag2;
			if (flag2)
			{
				if ((Object)(object)((Renderer)mr).sharedMaterial != (Object)(object)val)
				{
					((Renderer)mr).sharedMaterial = val;
				}
				int currentBehaviourStateIndex = ((EnemyAI)bee).currentBehaviourStateIndex;
				bool num2 = face == Face.Neutral;
				float num3 = (num2 ? 0.35f : 1f);
				float num4 = currentBehaviourStateIndex switch
				{
					1 => 0.7f, 
					0 => 0.25f, 
					_ => 1f, 
				};
				float num5 = (num2 ? 6f : ((currentBehaviourStateIndex == 1) ? 3f : 4.5f));
				if (((EnemyAI)bee).daytimeEnemyLeaving)
				{
					leaveRadius += dt * 4f;
					num5 = 1.5f;
				}
				num3 += leaveRadius;
				float num6 = ((face == Face.Angry) ? Mathf.Max(0.1f, Plugin.AngryScale.Value) : 1f);
				scale = Mathf.MoveTowards(scale, num6, dt * 3f);
				float num7 = Mathf.Max(0.02f, Plugin.FaceSize.Value) * scale * 0.5f;
				Transform transform = ((Component)val2).transform;
				Vector3 val4 = transform.right * num7;
				Vector3 val5 = transform.up * num7;
				Vector3 val6 = -transform.forward;
				float num8 = 1f - Mathf.Exp((0f - num5) * dt);
				for (int i = 0; i < n; i++)
				{
					dir[i] = Quaternion.AngleAxis(spin[i] * dt, axis[i]) * dir[i];
					float num9 = now * 0.8f + seed[i];
					Vector3 val7 = new Vector3(Mathf.PerlinNoise(num9, seed[i]) - 0.5f, Mathf.PerlinNoise(seed[i], num9) - 0.5f, Mathf.PerlinNoise(num9 + 17.3f, num9) - 0.5f) * (2f * num4);
					Vector3 val8 = c + dir[i] * num3 + val7;
					pos[i] = Vector3.Lerp(pos[i], val8, num8);
					Vector3 val9 = pos[i];
					int num10 = i * 4;
					verts[num10] = val9 - val4 - val5;
					verts[num10 + 1] = val9 + val4 - val5;
					verts[num10 + 2] = val9 - val4 + val5;
					verts[num10 + 3] = val9 + val4 + val5;
					Vector3[] array = normals;
					Vector3[] array2 = normals;
					int num11 = num10 + 1;
					Vector3[] array3 = normals;
					int num12 = num10 + 2;
					val3 = (normals[num10 + 3] = val6);
					val3 = (array3[num12] = val3);
					val3 = (array[num10] = (array2[num11] = val3));
				}
				mesh.vertices = verts;
				mesh.normals = normals;
				mesh.RecalculateBounds();
			}
		}

		private void DumpVanillaAudio()
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			AudioSource[] componentsInChildren = ((Component)bee).GetComponentsInChildren<AudioSource>(true);
			foreach (AudioSource val in componentsInChildren)
			{
				string text = string.Join(",", Array.ConvertAll(((Component)val).GetComponents<Component>(), (Component x) => ((object)x).GetType().Name));
				ManualLogSource log = Plugin.Log;
				object[] obj = new object[5]
				{
					((Object)val).name,
					null,
					null,
					null,
					null
				};
				AudioClip clip = val.clip;
				obj[1] = ((clip != null) ? ((Object)clip).name : null);
				obj[2] = val.loop;
				obj[3] = val.volume;
				obj[4] = val.spatialBlend;
				string text2 = string.Format("[Debug] bee audio '{0}': clip={1} loop={2} vol={3} spatial={4} ", obj);
				object[] obj2 = new object[5] { val.rolloffMode, val.minDistance, val.maxDistance, null, null };
				AudioMixerGroup outputAudioMixerGroup = val.outputAudioMixerGroup;
				obj2[3] = ((outputAudioMixerGroup != null) ? ((Object)outputAudioMixerGroup).name : null);
				obj2[4] = text;
				log.LogInfo((object)(text2 + string.Format("rolloff={0} {1}-{2} mixer={3} comps=[{4}]", obj2)));
			}
			Plugin.Log.LogInfo((object)("[Debug] swarm renderer: " + (((object)vfxRenderer)?.GetType().Name ?? "none")));
		}

		private void OnDestroy()
		{
			if ((Object)(object)drawGo != (Object)null)
			{
				Object.Destroy((Object)(object)drawGo);
			}
			if ((Object)(object)audioGo != (Object)null)
			{
				Object.Destroy((Object)(object)audioGo);
			}
			if ((Object)(object)mesh != (Object)null)
			{
				Object.Destroy((Object)(object)mesh);
			}
		}
	}
	[HarmonyPatch]
	internal static class Patches
	{
		[HarmonyPatch(typeof(RedLocustBees), "Start")]
		[HarmonyPostfix]
		private static void AttachFaces(RedLocustBees __instance)
		{
			try
			{
				if ((Object)(object)((Component)__instance).GetComponent<BeeFaces>() != (Object)null)
				{
					return;
				}
				BeeFaces beeFaces = ((Component)__instance).gameObject.AddComponent<BeeFaces>();
				try
				{
					beeFaces.Init(__instance);
				}
				catch
				{
					Object.Destroy((Object)(object)beeFaces);
					throw;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Attach failed: " + ex));
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "OnShipLandedMiscEvents")]
		[HarmonyPostfix]
		private static void SpawnTestBees()
		{
			//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_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: 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_0155: 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_016c: 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)
			try
			{
				if (!Plugin.TestSpawnBees.Value)
				{
					return;
				}
				NetworkManager singleton = NetworkManager.Singleton;
				RoundManager instance = RoundManager.Instance;
				if ((Object)(object)singleton == (Object)null || !singleton.IsServer || (Object)(object)instance == (Object)null)
				{
					return;
				}
				EnemyType val = ((IEnumerable<EnemyType>)Resources.FindObjectsOfTypeAll<EnemyType>()).FirstOrDefault((Func<EnemyType, bool>)((EnemyType t) => (Object)(object)t != (Object)null && (Object)(object)t.enemyPrefab != (Object)null && (Object)(object)t.enemyPrefab.GetComponent<RedLocustBees>() != (Object)null));
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogWarning((object)"RedLocustBees EnemyType not found.");
					return;
				}
				Vector3 ship = StartOfRound.Instance.shipLandingPosition.position;
				List<Vector3> list = (from _ in (from g in GameObject.FindGameObjectsWithTag("OutsideAINode")
						select g.transform.position).Where(delegate(Vector3 p)
					{
						//IL_0000: Unknown result type (might be due to invalid IL or missing references)
						//IL_0002: Unknown result type (might be due to invalid IL or missing references)
						float num2 = Vector3.Distance(p, ship);
						return num2 > 20f && num2 < 70f;
					})
					orderby Random.value
					select _).ToList();
				if (list.Count == 0)
				{
					Plugin.Log.LogInfo((object)"No outside nodes near the ship; no test bees.");
					return;
				}
				for (int num = 0; num < Mathf.Min(Plugin.TestBeeCount.Value, list.Count); num++)
				{
					Vector3 navMeshPosition = instance.GetNavMeshPosition(list[num], default(NavMeshHit), 5f, -1);
					instance.SpawnEnemyGameObject(navMeshPosition, 0f, -1, val);
					Plugin.Log.LogInfo((object)$"Test bees spawned at {navMeshPosition} ({Vector3.Distance(navMeshPosition, ship):0} m from the ship).");
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Test bee spawn failed: " + ex));
			}
		}
	}
	[BepInPlugin("luver_inn.bobabees", "BobaBees", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "luver_inn.bobabees";

		public const string Version = "1.0.0";

		internal static ManualLogSource Log;

		internal static string Dir;

		internal static ConfigEntry<bool> FacesEnabled;

		internal static ConfigEntry<bool> AudioEnabled;

		internal static ConfigEntry<bool> TestSpawnBees;

		internal static ConfigEntry<bool> DebugLog;

		internal static ConfigEntry<int> FaceCount;

		internal static ConfigEntry<int> TestBeeCount;

		internal static ConfigEntry<float> FaceSize;

		internal static ConfigEntry<float> AngryScale;

		internal static ConfigEntry<float> MusicVolume;

		internal static ConfigEntry<float> IdleVolume;

		internal static ConfigEntry<float> AngryRadius;

		private void Awake()
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Dir = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			FacesEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Faces", "Enabled", true, "Replace the bee swarm with faces.");
			FaceCount = ((BaseUnityPlugin)this).Config.Bind<int>("Faces", "Count", 20, new ConfigDescription("Faces per swarm.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 60), Array.Empty<object>()));
			FaceSize = ((BaseUnityPlugin)this).Config.Bind<float>("Faces", "Size", 0.45f, "Size of one face in game units (calm / crying).");
			AngryScale = ((BaseUnityPlugin)this).Config.Bind<float>("Faces", "AngryScale", 1.6f, "Faces grow by this factor while the bees attack.");
			AngryRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Faces", "AngryRadius", 10f, "Hive stolen: bees count as attacking (angry face) while a player is this close to the swarm; otherwise they search (crying face).");
			AudioEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "Enabled", true, "Replace the bee buzzing with the songs.");
			MusicVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "AttackVolume", 0.8f, "0 to 1. Attack song volume.");
			IdleVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "IdleVolume", 0.8f, "0 to 1. Idle sounds volume.");
			TestSpawnBees = ((BaseUnityPlugin)this).Config.Bind<bool>("Testing", "SpawnBeesOnLanding", false, "TEST ONLY (host): spawn bee swarms near the ship on every landing.");
			TestBeeCount = ((BaseUnityPlugin)this).Config.Bind<int>("Testing", "SpawnBeesCount", 2, "How many swarms the test option spawns.");
			DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Testing", "DebugLog", false, "Log bee state changes and the vanilla bee audio setup.");
			Assets.Init(Dir);
			new Harmony("luver_inn.bobabees").PatchAll(typeof(Patches));
			Log.LogInfo((object)("BobaBees 1.0.0 loaded." + (TestSpawnBees.Value ? "  ** TEST: SpawnBeesOnLanding is ON **" : "")));
		}
	}
}