Decompiled source of ChiikawaCompany v0.1.8

BepInEx/plugins/ChiikawaCompany/ChiikawaCompany.dll

Decompiled 3 days 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 LethalLib.Modules;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;

[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("ChiikawaCompany")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.8.0")]
[assembly: AssemblyInformationalVersion("0.1.8")]
[assembly: AssemblyProduct("ChiikawaCompany")]
[assembly: AssemblyTitle("ChiikawaCompany")]
[assembly: AssemblyVersion("0.1.8.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 ChiikawaCompany
{
	public sealed class LocalAudioOverrides : MonoBehaviour
	{
		public void Load(string file, ManualLogSource log)
		{
			((MonoBehaviour)this).StartCoroutine(Read(file, log));
		}

		private IEnumerator Read(string file, ManualLogSource log)
		{
			if (!File.Exists(file))
			{
				log.LogWarning((object)"Happy voice file not provided; using the clearly provisional synthesized cue.");
				Object.Destroy((Object)(object)((Component)this).gameObject);
				yield break;
			}
			AudioType val;
			switch (Path.GetExtension(file).ToLowerInvariant())
			{
			case ".wav":
				val = (AudioType)20;
				break;
			case ".ogg":
				val = (AudioType)14;
				break;
			case ".mp3":
				val = (AudioType)13;
				break;
			default:
				log.LogError((object)"HappyAudioFile must be WAV, OGG or MP3.");
				Object.Destroy((Object)(object)((Component)this).gameObject);
				yield break;
			}
			UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(new Uri(Path.GetFullPath(file)).AbsoluteUri, val);
			try
			{
				yield return request.SendWebRequest();
				if ((int)request.result != 1)
				{
					log.LogError((object)("Cannot load happy audio: " + request.error));
				}
				else
				{
					AudioClip content = DownloadHandlerAudioClip.GetContent(request);
					if ((Object)(object)content != (Object)null && content.length > 0f && content.length <= 10f)
					{
						ChiikawaAI.HappySoundOverride = content;
						log.LogInfo((object)("Happy voice override loaded: " + content.length.ToString("F2") + " seconds."));
					}
					else
					{
						log.LogError((object)"Happy voice must be a nonempty clip up to 10 seconds.");
					}
				}
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}
	}
	internal static class MaterialRepair
	{
		private static readonly Dictionary<Material, Material> replacements = new Dictionary<Material, Material>();

		internal static void Apply(EnemyType[] enemies, ManualLogSource log, GameObject[]? extraPrefabs = null)
		{
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Expected O, but got Unknown
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			Material[] source = (from m in Resources.FindObjectsOfTypeAll<Material>()
				where (Object)(object)m != (Object)null && !((Object)m).name.StartsWith("ChiikawaRuntime/") && (Object)(object)m.shader != (Object)null && ((Object)m.shader).name == "HDRP/Lit" && m.shader.isSupported && m.HasProperty("_SurfaceType") && m.GetFloat("_SurfaceType") == 0f
				select m).ToArray();
			Material val = ((IEnumerable<Material>)source).FirstOrDefault((Func<Material, bool>)((Material m) => !m.IsKeywordEnabled("_ALPHATEST_ON")));
			Material val2 = ((IEnumerable<Material>)source).FirstOrDefault((Func<Material, bool>)((Material m) => m.IsKeywordEnabled("_ALPHATEST_ON"))) ?? val;
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				log.LogWarning((object)"Native HDRP/Lit material not loaded yet; will retry after the next scene loads.");
				return;
			}
			int num = 0;
			foreach (GameObject item in enemies.Select((EnemyType e) => e.enemyPrefab).Concat(extraPrefabs ?? Array.Empty<GameObject>()))
			{
				Renderer[] componentsInChildren = item.GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val3 in componentsInChildren)
				{
					Material[] sharedMaterials = val3.sharedMaterials;
					for (int num3 = 0; num3 < sharedMaterials.Length; num3++)
					{
						Material val4 = sharedMaterials[num3];
						if ((Object)(object)val4 == (Object)null || ((Object)val4).name.StartsWith("ChiikawaRuntime/"))
						{
							continue;
						}
						if (!replacements.TryGetValue(val4, out Material value))
						{
							bool flag = ((Object)val4).name.StartsWith("Eyes");
							Color color = val4.GetColor("_UnlitColor");
							Texture texture = val4.GetTexture("_UnlitColorMap");
							value = new Material(flag ? val2 : val)
							{
								name = "ChiikawaRuntime/" + ((Object)val4).name
							};
							value.SetColor("_BaseColor", color);
							value.SetTexture("_BaseColorMap", texture);
							value.SetTexture("_MaskMap", (Texture)null);
							value.SetTexture("_NormalMap", (Texture)null);
							value.SetTexture("_DetailMap", (Texture)null);
							value.SetTexture("_EmissiveColorMap", (Texture)null);
							value.SetColor("_EmissiveColor", Color.black);
							value.SetFloat("_Metallic", 0f);
							value.SetFloat("_Smoothness", 0.15f);
							value.SetFloat("_AlphaCutoffEnable", (float)(flag ? 1 : 0));
							value.SetFloat("_AlphaCutoff", 0.4f);
							value.SetFloat("_DoubleSidedEnable", 0f);
							value.SetFloat("_CullMode", 2f);
							value.SetFloat("_CullModeForward", 2f);
							string[] array = new string[6] { "_MASKMAP", "_NORMALMAP", "_NORMALMAP_TANGENT_SPACE", "_DETAIL_MAP", "_EMISSIVE_COLOR_MAP", "_DOUBLESIDED_ON" };
							foreach (string text in array)
							{
								value.DisableKeyword(text);
							}
							if (flag)
							{
								value.EnableKeyword("_ALPHATEST_ON");
							}
							else
							{
								value.DisableKeyword("_ALPHATEST_ON");
							}
							value.renderQueue = (flag ? 2450 : 2000);
							value.SetOverrideTag("RenderType", flag ? "TransparentCutout" : "Opaque");
							replacements[val4] = value;
							log.LogInfo((object)("Material repaired: " + ((Object)val4).name + " -> native HDRP/Lit; face texture=" + ((Object)(object)texture != (Object)null)));
						}
						sharedMaterials[num3] = value;
						num++;
					}
					val3.sharedMaterials = sharedMaterials;
				}
			}
			if (num > 0)
			{
				log.LogInfo((object)("Native HDRP material slots repaired: " + num));
			}
		}
	}
	[BepInPlugin("elias.chiikawacompany", "Chiikawa Company", "0.1.8")]
	[BepInDependency("evaisa.lethallib", "1.2.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "elias.chiikawacompany";

		public const string Version = "0.1.8";

		private AssetBundle? bundle;

		private bool requestedAudio;

		private bool plushValidated;

		private void Awake()
		{
			//IL_0375: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: Expected O, but got Unknown
			//IL_0491: Unknown result type (might be due to invalid IL or missing references)
			//IL_049b: Expected O, but got Unknown
			//IL_04e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ee: Expected O, but got Unknown
			string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "chiikawacompanyassets");
			if (!File.Exists(text))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Missing chiikawacompanyassets. Build the Unity assets before installing this plugin.");
				return;
			}
			bundle = AssetBundle.LoadFromFile(text);
			if ((Object)(object)bundle == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Cannot load Chiikawa asset bundle.");
				return;
			}
			HashSet<uint> hashSet = new HashSet<uint>();
			List<EnemyType> testEnemies = new List<EnemyType>();
			List<Item> plushItems = new List<Item>();
			string[] array = new string[3] { "Chiikawa", "Hachiware", "Usagi" };
			foreach (string text2 in array)
			{
				EnemyType val = bundle.LoadAsset<EnemyType>(text2 + "Enemy");
				TerminalNode val2 = bundle.LoadAsset<TerminalNode>(text2 + "Info");
				if ((Object)(object)val == (Object)null || (Object)(object)val.enemyPrefab == (Object)null || (Object)(object)val2 == (Object)null)
				{
					throw new InvalidOperationException("Incomplete asset bundle: " + text2);
				}
				val.MaxCount = 1;
				val2.displayText = text2 + "\n\n" + ((text2 == "Chiikawa") ? "A timid guide. Stay close and follow it to the most valuable reachable loose scrap. It waits if you fall behind and celebrates at the treasure. Hitting it makes it flee." : ((text2 == "Usagi") ? "Hunts employees on sight within twelve metres. Its warning gives you time to retreat. Break line of sight for five seconds to escape, or fight back with a shovel." : "Haunts one employee at a time, while everyone can see its appearances. After three sightings, it pursues its victim. Hit it to interrupt the haunting; it can be killed.")) + "\n\n";
				ChiikawaAI component = val.enemyPrefab.GetComponent<ChiikawaAI>();
				if ((Object)(object)component == (Object)null || (Object)(object)((EnemyAI)component).creatureAnimator == (Object)null)
				{
					throw new InvalidOperationException("Invalid enemy prefab: " + text2);
				}
				EnemyAICollisionDetect componentInChildren = val.enemyPrefab.GetComponentInChildren<EnemyAICollisionDetect>(true);
				if ((Object)(object)componentInChildren == (Object)null || (Object)(object)componentInChildren.mainScript != (Object)(object)component || (Object)(object)((EnemyAI)component).eye == (Object)null || (Object)(object)((EnemyAI)component).agent == (Object)null || ((EnemyAI)component).enemyBehaviourStates == null || ((EnemyAI)component).enemyBehaviourStates.Length != 4)
				{
					throw new InvalidOperationException("Incomplete prefab references: " + text2);
				}
				RuntimeAnimatorController controller = ((EnemyAI)component).creatureAnimator.runtimeAnimatorController;
				string[] source = new string[7] { "Idle", "Walk", "Run", "Attack", "Hit", "Angry", "Die" };
				if ((Object)(object)controller == (Object)null || source.Any((string n) => !controller.animationClips.Any((AnimationClip c) => ((Object)c).name == n && c.length > 0f)))
				{
					throw new InvalidOperationException("Missing animation clips: " + text2);
				}
				NetworkObject component2 = val.enemyPrefab.GetComponent<NetworkObject>();
				FieldInfo field = typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if ((Object)(object)component2 == (Object)null || field == null)
				{
					throw new InvalidOperationException("Missing NetworkObject identity: " + text2);
				}
				uint num = (uint)field.GetValue(component2);
				if (num == 0 || !hashSet.Add(num))
				{
					throw new InvalidOperationException("Invalid or duplicate network prefab identity: " + text2);
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Asset checks passed for " + text2 + ": 7 clips, collision reference, 4 behaviour states, network hash " + num));
				int value = ((BaseUnityPlugin)this).Config.Bind<int>(text2, "SpawnWeight", (text2 == "Usagi") ? 12 : 20, new ConfigDescription("Interior spawn weight; 0 disables natural spawns.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())).Value;
				NetworkPrefabs.RegisterNetworkPrefab(val.enemyPrefab);
				Enemies.RegisterEnemy(val, value, (LevelTypes)(-1), (SpawnType)0, val2, (TerminalKeyword)null);
				testEnemies.Add(val);
				Item val3 = bundle.LoadAsset<Item>(text2 + "Plush");
				if ((Object)(object)val3 == (Object)null || !val3.isScrap || (Object)(object)val3.spawnPrefab == (Object)null || (Object)(object)val3.spawnPrefab.GetComponent<PlushItem>() == (Object)null)
				{
					throw new InvalidOperationException("Missing plush item assets: " + text2);
				}
				NetworkObject component3 = val3.spawnPrefab.GetComponent<NetworkObject>();
				uint num2 = (((Object)(object)component3 != (Object)null) ? ((uint)field.GetValue(component3)) : 0u);
				if (num2 == 0 || !hashSet.Add(num2))
				{
					throw new InvalidOperationException("Invalid plush network identity: " + text2);
				}
				val3.minValue = ((BaseUnityPlugin)this).Config.Bind<int>(text2, "PlushMinValue", (text2 == "Chiikawa") ? 25 : 50, new ConfigDescription("Minimum value of the sellable death-drop plush.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 999), Array.Empty<object>())).Value;
				val3.maxValue = Math.Max(val3.minValue, ((BaseUnityPlugin)this).Config.Bind<int>(text2, "PlushMaxValue", (text2 == "Chiikawa") ? 40 : 80, new ConfigDescription("Maximum value of the sellable death-drop plush.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 999), Array.Empty<object>())).Value);
				NetworkPrefabs.RegisterNetworkPrefab(val3.spawnPrefab);
				Items.RegisterItem(val3);
				plushItems.Add(val3);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Registered death-drop plush: " + text2 + "; value=" + val3.minValue + "-" + val3.maxValue + "; network hash=" + num2));
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Registered " + text2 + " with spawn weight " + value + "; natural round cap=" + val.MaxCount));
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Chiikawa Company loaded. Install the same version on every player's client.");
			ChiikawaAI.PlushDrops = plushItems.ToArray();
			ChiikawaAI.HachiwareVisibleToEveryone = ((BaseUnityPlugin)this).Config.Bind<bool>("Hachiware", "VisibleToEveryone", true, "All players see Hachiware's manifestations, but only the haunted employee is attacked.").Value;
			string audioFile = ((BaseUnityPlugin)this).Config.Bind<string>("Chiikawa", "HappyAudioFile", "chiikawa_happy.wav", "Optional WAV/OGG/MP3 beside the plugin, up to 10 seconds. Missing file uses a provisional cue.").Value;
			SceneManager.sceneLoaded += delegate
			{
				//IL_00e8: 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_00f3: Expected O, but got Unknown
				try
				{
					if (!plushValidated)
					{
						foreach (Item item in plushItems)
						{
							ValidatePlushPrefab(item);
						}
						plushValidated = true;
					}
					MaterialRepair.Apply(testEnemies.ToArray(), ((BaseUnityPlugin)this).Logger, plushItems.Select((Item val5) => val5.spawnPrefab).ToArray());
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("Material repair failed: " + ex));
				}
				if (!requestedAudio)
				{
					requestedAudio = true;
					GameObject val4 = new GameObject("ChiikawaAudioLoader");
					Object.DontDestroyOnLoad((Object)val4);
					val4.AddComponent<LocalAudioOverrides>().Load(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), audioFile), ((BaseUnityPlugin)this).Logger);
				}
			};
		}

		private void ValidatePlushPrefab(Item item)
		{
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(item.spawnPrefab);
			val.SetActive(false);
			try
			{
				PlushItem component = val.GetComponent<PlushItem>();
				if (!((GrabbableObject)component).grabbable || (Object)(object)item.itemIcon == (Object)null || (Object)(object)((GrabbableObject)component).propBody == (Object)null || (Object)(object)val.GetComponent<AudioSource>() == (Object)null || (Object)(object)val.GetComponent<Collider>() == (Object)null || (Object)(object)val.GetComponentInChildren<ScanNodeProperties>() == (Object)null || val.GetComponentsInChildren<MeshRenderer>().Length == 0 || (Object)(object)val.GetComponent<EnemyAI>() != (Object)null)
				{
					throw new InvalidOperationException("Incomplete grabbable plush: " + item.itemName);
				}
				ScanNodeProperties componentInChildren = val.GetComponentInChildren<ScanNodeProperties>();
				((GrabbableObject)component).SetScrapValue(37);
				if (componentInChildren.nodeType != 2 || componentInChildren.minRange != 0 || componentInChildren.creatureScanID != -1 || componentInChildren.scrapValue != 37 || componentInChildren.subText != "Value: $37" || ((Object)item.itemIcon).name != item.itemName.Replace("Peluche de ", "") + "_plush_icon")
				{
					throw new InvalidOperationException("Invalid plush scan/value or individual icon: " + item.itemName);
				}
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				typeof(NetworkBehaviour).GetMethod("InitializeVariables", bindingAttr).Invoke(component, null);
				IEnumerable obj = (IEnumerable)typeof(NetworkBehaviour).GetField("NetworkVariableFields", bindingAttr).GetValue(component);
				int num = 0;
				foreach (NetworkVariableBase item2 in obj)
				{
					if (item2.Name == "saleValue")
					{
						num++;
					}
				}
				if (num != 1)
				{
					throw new InvalidOperationException("Plush sale value network registration failed.");
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Plush prefab checks passed: " + item.itemName + "; scrap scan $37, minRange=0, creatureScanID=-1; icon=" + ((Object)item.itemIcon).name + "; pocket AudioSource; one synced saleValue field."));
			}
			finally
			{
				Object.Destroy((Object)(object)val);
			}
		}
	}
}

BepInEx/plugins/ChiikawaCompany/ChiikawaCompany.Runtime.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using GameNetcodeStuff;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;

[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("ChiikawaCompany.Runtime")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("ChiikawaCompany.Runtime")]
[assembly: AssemblyTitle("ChiikawaCompany.Runtime")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 ChiikawaCompany
{
	public sealed class ChiikawaAI : EnemyAI
	{
		public enum Character
		{
			Chiikawa,
			Hachiware,
			Usagi
		}

		private enum State
		{
			Friendly,
			Angry,
			Chase,
			Attack
		}

		public Character character;

		private int observedState = -1;

		private float stateTime;

		private float provokedUntil;

		private float hurtUntil;

		private bool appliedAttack;

		private bool playedDeath;

		private Vector3 lastPosition;

		private string playing = "";

		private float visualSpeed;

		private Vector3 lastThreatPosition;

		private float lastSeenPlayer;

		private float nextCry;

		private static AudioClip? fearCry;

		private bool plushDropScheduled;

		private GrabbableObject? guideTarget;

		private float nextScrapScan;

		private Vector3 guideDestination;

		private float nextHappy;

		private static AudioClip? happySound;

		private Renderer[] hauntRenderers = Array.Empty<Renderer>();

		private Collider[] hauntColliders = Array.Empty<Collider>();

		private float nextHaunt;

		private float nextHauntTargetCheck;

		private float hauntingUntil;

		private int hauntVisits;

		private bool noticedThisVisit;

		private ulong observedHauntOwner = ulong.MaxValue;

		private bool assignedHauntTarget;

		public static Item[] PlushDrops { get; set; } = Array.Empty<Item>();

		public static AudioClip? HappySoundOverride { get; set; }

		public string GuideDescription
		{
			get
			{
				if (!((Object)(object)guideTarget != (Object)null))
				{
					return "Sin objetivo accesible";
				}
				return guideTarget.itemProperties.itemName + " ($" + guideTarget.scrapValue + ")";
			}
		}

		public static bool HachiwareVisibleToEveryone { get; set; } = true;

		private PlayerControllerB? HauntedPlayer => ((IEnumerable<PlayerControllerB>)StartOfRound.Instance.allPlayerScripts).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB p) => (Object)(object)p != (Object)null && p.actualClientId == ((NetworkBehaviour)this).OwnerClientId && p.isPlayerControlled));

		public override void Start()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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)
			((EnemyAI)this).Start();
			lastPosition = ((Component)this).transform.position;
			if (character == Character.Hachiware)
			{
				InitializeHaunt();
			}
			else if (((NetworkBehaviour)this).IsOwner)
			{
				((EnemyAI)this).StartSearch(((Component)this).transform.position, (AISearchRoutine)null);
			}
		}

		public override void Update()
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			((EnemyAI)this).Update();
			if (character == Character.Hachiware)
			{
				UpdateHauntPresentation();
			}
			if (base.isEnemyDead)
			{
				if (!playedDeath)
				{
					playedDeath = true;
					Play("Die");
				}
				return;
			}
			if (observedState != base.currentBehaviourStateIndex)
			{
				observedState = base.currentBehaviourStateIndex;
				stateTime = 0f;
				appliedAttack = false;
				if (character == Character.Chiikawa && base.currentBehaviourStateIndex == 1)
				{
					PlayHappySound();
				}
			}
			stateTime += Time.deltaTime;
			Vector3 val = ((Component)this).transform.position - lastPosition;
			float num = ((Vector3)(ref val)).magnitude / Mathf.Max(0.001f, Time.deltaTime);
			lastPosition = ((Component)this).transform.position;
			visualSpeed = Mathf.Lerp(visualSpeed, num, Time.deltaTime * 8f);
			State currentBehaviourStateIndex = (State)base.currentBehaviourStateIndex;
			if (Time.time < hurtUntil)
			{
				Play("Hit");
			}
			else
			{
				switch (currentBehaviourStateIndex)
				{
				case State.Angry:
					Play((character == Character.Chiikawa || character == Character.Hachiware) ? "Idle" : "Angry");
					break;
				case State.Attack:
					Play("Attack");
					break;
				default:
					if (base.stunNormalizedTimer > 0f || base.stunnedIndefinitely > 0)
					{
						Play("Idle");
					}
					else
					{
						Play((visualSpeed > 2.4f) ? "Run" : ((visualSpeed > 0.15f) ? "Walk" : "Idle"));
					}
					break;
				}
			}
			if (character != Character.Chiikawa && currentBehaviourStateIndex == State.Attack && !appliedAttack && stateTime >= 0.47f && stateTime <= 0.8f && base.stunNormalizedTimer <= 0f && base.stunnedIndefinitely <= 0)
			{
				appliedAttack = true;
				PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
				if ((Object)(object)localPlayerController != (Object)null && ((EnemyAI)this).PlayerIsTargetable(localPlayerController, false, false, true) && (character != Character.Hachiware || localPlayerController.actualClientId == ((NetworkBehaviour)this).OwnerClientId) && Vector3.Distance(((Component)this).transform.position, ((Component)localPlayerController).transform.position) < 1.25f && ((EnemyAI)this).CheckLineOfSightForPosition(((Component)localPlayerController.gameplayCamera).transform.position, 180f, 3, -1f, (Transform)null))
				{
					int num2 = ((character == Character.Usagi) ? 30 : ((character == Character.Hachiware) ? 40 : 20));
					val = default(Vector3);
					localPlayerController.DamagePlayer(num2, true, true, (CauseOfDeath)0, 0, false, val);
				}
			}
		}

		public override void DoAIInterval()
		{
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0433: Unknown result type (might be due to invalid IL or missing references)
			//IL_0445: Unknown result type (might be due to invalid IL or missing references)
			//IL_0455: 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_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: 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_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: 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_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_0477: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			((EnemyAI)this).DoAIInterval();
			if (!((NetworkBehaviour)this).IsOwner || base.isEnemyDead || StartOfRound.Instance.allPlayersDead)
			{
				return;
			}
			if (base.stunNormalizedTimer > 0f || base.stunnedIndefinitely > 0)
			{
				base.agent.speed = 0f;
				return;
			}
			State currentBehaviourStateIndex = (State)base.currentBehaviourStateIndex;
			if (character == Character.Hachiware)
			{
				DoHauntInterval();
				return;
			}
			if (character == Character.Chiikawa)
			{
				if (currentBehaviourStateIndex == State.Chase)
				{
					FleeFromThreat();
				}
				else
				{
					GuideToScrap();
				}
				return;
			}
			if (character == Character.Usagi)
			{
				if ((Object)(object)base.targetPlayer == (Object)null || !((EnemyAI)this).PlayerIsTargetable(base.targetPlayer, false, false, true))
				{
					((EnemyAI)this).TargetClosestPlayer(1.5f, true, 70f, false, false, true);
				}
				if ((Object)(object)base.targetPlayer != (Object)null && ((EnemyAI)this).PlayerIsTargetable(base.targetPlayer, false, false, true) && Vector3.Distance(((Component)this).transform.position, ((Component)base.targetPlayer).transform.position) <= 12f && ((EnemyAI)this).CheckLineOfSightForPosition(((Component)base.targetPlayer.gameplayCamera).transform.position, 100f, 12, -1f, (Transform)null))
				{
					lastSeenPlayer = Time.time;
					provokedUntil = Time.time + 5f;
					lastThreatPosition = ((Component)base.targetPlayer).transform.position;
					if (currentBehaviourStateIndex == State.Friendly)
					{
						EndSearch();
						Change(State.Angry);
						HoldPosition();
						return;
					}
				}
				else if (currentBehaviourStateIndex != State.Friendly)
				{
					if (Time.time - lastSeenPlayer >= 5f)
					{
						base.targetPlayer = null;
						Change(State.Friendly);
						base.agent.speed = 1.7f;
						((EnemyAI)this).StartSearch(((Component)this).transform.position, (AISearchRoutine)null);
						return;
					}
					switch (currentBehaviourStateIndex)
					{
					case State.Angry:
						HoldPosition();
						if (stateTime >= 1.9f)
						{
							Change(State.Chase);
						}
						break;
					case State.Attack:
						HoldPosition();
						if (stateTime >= 1.15f)
						{
							Change(State.Chase);
						}
						break;
					default:
						EndSearch();
						base.agent.speed = 4.5f;
						((EnemyAI)this).SetDestinationToPosition(lastThreatPosition, true);
						break;
					}
					return;
				}
			}
			if (currentBehaviourStateIndex != State.Friendly && Time.time >= provokedUntil)
			{
				base.targetPlayer = null;
				Change(State.Friendly);
				((EnemyAI)this).StartSearch(((Component)this).transform.position, (AISearchRoutine)null);
				return;
			}
			switch (currentBehaviourStateIndex)
			{
			case State.Friendly:
			{
				base.agent.speed = ((character == Character.Usagi) ? 1.7f : 1.1f);
				((EnemyAI)this).TargetClosestPlayer(1.5f, true, 70f, false, false, true);
				if ((Object)(object)base.targetPlayer == (Object)null)
				{
					EnsureSearch();
					break;
				}
				float num = Vector3.Distance(((Component)this).transform.position, ((Component)base.targetPlayer).transform.position);
				if (character == Character.Hachiware && num < 7f)
				{
					EndSearch();
					if (num > 2.2f)
					{
						((EnemyAI)this).SetDestinationToPosition(((Component)base.targetPlayer).transform.position, true);
					}
					else
					{
						HoldPosition();
					}
				}
				else if (character == Character.Chiikawa && num < 1.5f)
				{
					EndSearch();
					Vector3 position = ((Component)this).transform.position;
					Vector3 val = ((Component)this).transform.position - ((Component)base.targetPlayer).transform.position;
					NavMeshHit val2 = default(NavMeshHit);
					if (NavMesh.SamplePosition(position + ((Vector3)(ref val)).normalized * 3f, ref val2, 3f, -1))
					{
						((EnemyAI)this).SetDestinationToPosition(((NavMeshHit)(ref val2)).position, true);
					}
				}
				else
				{
					EnsureSearch();
				}
				break;
			}
			case State.Angry:
				HoldPosition();
				if (stateTime >= 1.9f)
				{
					Change(State.Chase);
				}
				break;
			case State.Chase:
				base.agent.speed = ((character == Character.Usagi) ? 4.5f : 3.4f);
				if ((Object)(object)base.targetPlayer == (Object)null || !((EnemyAI)this).PlayerIsTargetable(base.targetPlayer, false, false, true))
				{
					((EnemyAI)this).TargetClosestPlayer(1.5f, true, 70f, false, false, true);
				}
				if ((Object)(object)base.targetPlayer == (Object)null)
				{
					EnsureSearch();
					break;
				}
				EndSearch();
				((EnemyAI)this).SetDestinationToPosition(((Component)base.targetPlayer).transform.position, true);
				if (Vector3.Distance(((Component)this).transform.position, ((Component)base.targetPlayer).transform.position) < 1.3f && ((EnemyAI)this).CheckLineOfSightForPosition(((Component)base.targetPlayer.gameplayCamera).transform.position, 180f, 3, -1f, (Transform)null))
				{
					Change(State.Attack);
				}
				break;
			case State.Attack:
				HoldPosition();
				if (stateTime >= 1.15f)
				{
					Change(State.Chase);
				}
				break;
			}
		}

		public override void HitEnemy(int force = 1, PlayerControllerB? playerWhoHit = null, bool playHitSFX = false, int hitID = -1)
		{
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: 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)
			((EnemyAI)this).HitEnemy(force, playerWhoHit, playHitSFX, hitID);
			if (base.isEnemyDead || force <= 0)
			{
				return;
			}
			hurtUntil = Time.time + 0.5f;
			if (character == Character.Chiikawa)
			{
				PlayFearCry();
			}
			if (!((NetworkBehaviour)this).IsOwner)
			{
				return;
			}
			base.enemyHP -= force;
			if (base.enemyHP <= 0)
			{
				EndSearch();
				((EnemyAI)this).KillEnemyOnOwnerClient(false);
				return;
			}
			if (character == Character.Hachiware)
			{
				RetreatFromHaunt(12f);
				return;
			}
			guideTarget = null;
			provokedUntil = Time.time + (float)((character == Character.Chiikawa) ? 12 : ((character == Character.Usagi) ? 5 : 25));
			base.targetPlayer = playerWhoHit;
			if ((Object)(object)base.targetPlayer == (Object)null)
			{
				((EnemyAI)this).TargetClosestPlayer(1.5f, true, 70f, false, false, true);
			}
			lastThreatPosition = (((Object)(object)base.targetPlayer != (Object)null) ? ((Component)base.targetPlayer).transform.position : (((Component)this).transform.position - ((Component)this).transform.forward));
			lastSeenPlayer = Time.time;
			EndSearch();
			Change((character != Character.Chiikawa) ? State.Angry : State.Chase);
		}

		private void FleeFromThreat()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Expected O, but got Unknown
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: 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_0171: 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_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time >= provokedUntil)
			{
				base.targetPlayer = null;
				Change(State.Friendly);
				base.agent.speed = 1.1f;
				((EnemyAI)this).StartSearch(((Component)this).transform.position, (AISearchRoutine)null);
				return;
			}
			if ((Object)(object)base.targetPlayer != (Object)null && ((EnemyAI)this).PlayerIsTargetable(base.targetPlayer, false, false, true) && ((EnemyAI)this).CheckLineOfSightForPosition(((Component)base.targetPlayer.gameplayCamera).transform.position, 180f, 20, -1f, (Transform)null))
			{
				lastThreatPosition = ((Component)base.targetPlayer).transform.position;
			}
			EndSearch();
			base.agent.speed = 3.6f;
			Vector3 val = ((Component)this).transform.position - lastThreatPosition;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.1f)
			{
				val = -((Component)this).transform.forward;
			}
			Vector3 position = ((Component)this).transform.position;
			Vector3 val2 = position - lastThreatPosition;
			float num = ((Vector3)(ref val2)).sqrMagnitude;
			NavMeshPath val3 = new NavMeshPath();
			float[] array = new float[5] { 0f, 45f, -45f, 90f, -90f };
			NavMeshHit val4 = default(NavMeshHit);
			foreach (float num2 in array)
			{
				if (NavMesh.SamplePosition(((Component)this).transform.position + Quaternion.Euler(0f, num2, 0f) * ((Vector3)(ref val)).normalized * 7f, ref val4, 2f, -1) && NavMesh.CalculatePath(((Component)this).transform.position, ((NavMeshHit)(ref val4)).position, -1, val3) && (int)val3.status == 0)
				{
					val2 = ((NavMeshHit)(ref val4)).position - lastThreatPosition;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (sqrMagnitude > num)
					{
						position = ((NavMeshHit)(ref val4)).position;
						num = sqrMagnitude;
					}
				}
			}
			val2 = position - ((Component)this).transform.position;
			if (((Vector3)(ref val2)).sqrMagnitude > 0.25f)
			{
				((EnemyAI)this).SetDestinationToPosition(position, true);
			}
			else
			{
				HoldPosition();
			}
		}

		private void PlayFearCry()
		{
			if ((Object)(object)base.creatureVoice == (Object)null || Time.time < nextCry)
			{
				return;
			}
			nextCry = Time.time + 2f;
			if ((Object)(object)fearCry == (Object)null)
			{
				float[] array = new float[15435];
				double num = 0.0;
				for (int i = 0; i < array.Length; i++)
				{
					float num2 = (float)i / 22050f;
					float num3 = Mathf.Sin(MathF.PI * num2 / 0.7f);
					float num4 = 750f + 450f * Mathf.Sin(MathF.PI * num2 / 0.7f) + 40f * Mathf.Sin(num2 * 65f);
					num += Math.PI * 2.0 * (double)num4 / 22050.0;
					array[i] = (float)(Math.Sin(num) + 0.22 * Math.Sin(num * 2.0)) * num3 * 0.22f;
				}
				fearCry = AudioClip.Create("Chiikawa_Original_Fear_Squeal", array.Length, 1, 22050, false);
				fearCry.SetData(array, 0);
			}
			base.creatureVoice.minDistance = 1f;
			base.creatureVoice.maxDistance = 20f;
			base.creatureVoice.dopplerLevel = 0f;
			base.creatureVoice.PlayOneShot(fearCry, 0.8f);
		}

		private void Change(State state)
		{
			if (base.currentBehaviourStateIndex != (int)state)
			{
				((EnemyAI)this).SwitchToBehaviourState((int)state);
			}
		}

		private void HoldPosition()
		{
			base.agent.speed = 0f;
			base.movingTowardsTargetPlayer = false;
			base.moveTowardsDestination = false;
			if (base.agent.isOnNavMesh)
			{
				base.agent.ResetPath();
			}
		}

		private void EnsureSearch()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (base.searchCoroutine == null)
			{
				((EnemyAI)this).StartSearch(((Component)this).transform.position, (AISearchRoutine)null);
			}
		}

		private void EndSearch()
		{
			if (base.currentSearch != null)
			{
				((EnemyAI)this).StopSearch(base.currentSearch, true);
			}
		}

		private void Play(string clip)
		{
			if (!(playing == clip) && !((Object)(object)base.creatureAnimator == (Object)null))
			{
				playing = clip;
				base.creatureAnimator.CrossFadeInFixedTime(clip, 0.07f, 0);
			}
		}

		public override void KillEnemy(bool destroy = false)
		{
			bool num = ((NetworkBehaviour)this).IsServer && !plushDropScheduled && base.enemyType.canDie && (!destroy || base.enemyHP <= 0);
			if (num && destroy)
			{
				plushDropScheduled = true;
				SpawnPlush();
			}
			((EnemyAI)this).KillEnemy(destroy);
			if (num && !destroy && base.isEnemyDead)
			{
				plushDropScheduled = true;
				((MonoBehaviour)this).StartCoroutine(ConvertAfterDeath());
			}
		}

		private IEnumerator ConvertAfterDeath()
		{
			yield return (object)new WaitForSeconds(1.85f);
			if (((NetworkBehaviour)this).IsServer && ((NetworkBehaviour)this).IsSpawned && !((Object)(object)StartOfRound.Instance == (Object)null) && !StartOfRound.Instance.inShipPhase && SpawnPlush())
			{
				((NetworkBehaviour)this).NetworkObject.Despawn(true);
			}
		}

		private bool SpawnPlush()
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			int num = (int)character;
			if (num >= PlushDrops.Length || (Object)(object)PlushDrops[num] == (Object)null || (Object)(object)PlushDrops[num].spawnPrefab == (Object)null)
			{
				Debug.LogError((object)("Chiikawa Company: missing plush drop definition for " + character));
				return false;
			}
			Item val = PlushDrops[num];
			Vector3 val2 = ((Component)this).transform.position + Vector3.up * 0.25f;
			RaycastHit val3 = default(RaycastHit);
			if (Physics.Raycast(val2 + Vector3.up, Vector3.down, ref val3, 4f, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1))
			{
				val2 = ((RaycastHit)(ref val3)).point + Vector3.up * 0.15f;
			}
			GameObject obj = Object.Instantiate<GameObject>(val.spawnPrefab, val2, Quaternion.identity);
			PlushItem component = obj.GetComponent<PlushItem>();
			int scrapValue = Random.Range(val.minValue, val.maxValue + 1);
			((GrabbableObject)component).SetScrapValue(scrapValue);
			((GrabbableObject)component).isInFactory = !base.isOutside;
			obj.GetComponent<NetworkObject>().Spawn(false);
			Debug.Log((object)("Chiikawa Company: dropped one " + val.itemName + ", value=" + scrapValue));
			return true;
		}

		private static bool IsGuideScrap(GrabbableObject item)
		{
			if ((Object)(object)item != (Object)null && ((Component)item).gameObject.activeInHierarchy && !item.deactivated && (Object)(object)item.itemProperties != (Object)null && item.itemProperties.isScrap && item.scrapValue > 0 && item.isInFactory && !item.isInShipRoom && !item.isInElevator && !item.isHeld)
			{
				return !item.isHeldByEnemy;
			}
			return false;
		}

		private void GuideToScrap()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_00aa: Expected O, but got Unknown
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: 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_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: 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_017a: Unknown result type (might be due to invalid IL or missing references)
			((EnemyAI)this).TargetClosestPlayer(1.5f, false, 70f, false, false, true);
			if ((Object)(object)base.targetPlayer == (Object)null || Vector3.Distance(((Component)this).transform.position, ((Component)base.targetPlayer).transform.position) > 10f)
			{
				EndSearch();
				HoldPosition();
				return;
			}
			if (Time.time >= nextScrapScan || ((Object)(object)guideTarget != (Object)null && !IsGuideScrap(guideTarget)))
			{
				nextScrapScan = Time.time + 3f;
				GrabbableObject val = guideTarget;
				guideTarget = null;
				NavMeshPath val2 = new NavMeshPath();
				NavMeshHit val3 = default(NavMeshHit);
				foreach (GrabbableObject item in from i in Object.FindObjectsOfType<GrabbableObject>().Where(IsGuideScrap)
					orderby i.scrapValue descending
					select i)
				{
					if (NavMesh.SamplePosition(((Component)item).transform.position, ref val3, 1.8f, -1) && !(Mathf.Abs(((NavMeshHit)(ref val3)).position.y - ((Component)item).transform.position.y) > 1.8f) && NavMesh.CalculatePath(((Component)this).transform.position, ((NavMeshHit)(ref val3)).position, -1, val2) && (int)val2.status == 0)
					{
						guideTarget = item;
						guideDestination = ((NavMeshHit)(ref val3)).position;
						break;
					}
				}
				if ((Object)(object)guideTarget != (Object)(object)val)
				{
					Change(State.Friendly);
				}
			}
			EndSearch();
			if ((Object)(object)guideTarget == (Object)null)
			{
				HoldPosition();
				Change(State.Friendly);
			}
			else if (Vector3.Distance(((Component)this).transform.position, guideDestination) <= 1.25f)
			{
				HoldPosition();
				Change(State.Angry);
				Vector3 val4 = ((Component)guideTarget).transform.position - ((Component)this).transform.position;
				val4.y = 0f;
				if (((Vector3)(ref val4)).sqrMagnitude > 0.01f)
				{
					((Component)this).transform.rotation = Quaternion.LookRotation(val4);
				}
			}
			else
			{
				Change(State.Friendly);
				if (Vector3.Distance(((Component)this).transform.position, ((Component)base.targetPlayer).transform.position) > 6f)
				{
					HoldPosition();
					return;
				}
				base.agent.speed = 1.7f;
				((EnemyAI)this).SetDestinationToPosition(guideDestination, true);
			}
		}

		private void PlayHappySound()
		{
			if ((Object)(object)base.creatureVoice == (Object)null || Time.time < nextHappy)
			{
				return;
			}
			nextHappy = Time.time + 15f;
			if ((Object)(object)HappySoundOverride != (Object)null)
			{
				base.creatureVoice.PlayOneShot(HappySoundOverride, 0.8f);
				return;
			}
			if ((Object)(object)happySound == (Object)null)
			{
				float[] array = new float[14332];
				double num = 0.0;
				for (int i = 0; i < array.Length; i++)
				{
					float num2 = (float)i / 22050f;
					float num3 = num2 % 0.22f / 0.22f;
					float num4 = ((num2 < 0.22f) ? 659 : ((num2 < 0.44f) ? 784 : 988));
					num += Math.PI * 2.0 * (double)num4 / 22050.0;
					array[i] = (float)Math.Sin(num) * Mathf.Sin(MathF.PI * num3) * 0.2f;
				}
				happySound = AudioClip.Create("Chiikawa_Happy_TEMPORARY", array.Length, 1, 22050, false);
				happySound.SetData(array, 0);
			}
			base.creatureVoice.PlayOneShot(happySound, 0.8f);
		}

		private static bool CanHaunt(PlayerControllerB player)
		{
			if ((Object)(object)player != (Object)null && player.isPlayerControlled && !player.isPlayerDead)
			{
				return player.isInsideFactory;
			}
			return false;
		}

		private void InitializeHaunt()
		{
			hauntRenderers = ((Component)this).GetComponentsInChildren<Renderer>(true);
			hauntColliders = ((Component)this).GetComponentsInChildren<Collider>(true);
			EndSearch();
			nextHaunt = Time.time + 6f;
			SetHauntVisible(visible: false);
		}

		private void UpdateHauntPresentation()
		{
			if (((NetworkBehaviour)this).IsServer && !base.isEnemyDead && Time.time >= nextHauntTargetCheck)
			{
				nextHauntTargetCheck = Time.time + 1f;
				if (!assignedHauntTarget || !CanHaunt(HauntedPlayer))
				{
					PlayerControllerB val = (from p in StartOfRound.Instance.allPlayerScripts.Where(CanHaunt)
						orderby Vector3.Distance(((Component)this).transform.position, ((Component)p).transform.position)
						select p).FirstOrDefault();
					if ((Object)(object)val != (Object)null)
					{
						assignedHauntTarget = true;
						Change(State.Friendly);
						((EnemyAI)this).ChangeOwnershipOfEnemy(val.actualClientId);
					}
				}
			}
			if (observedHauntOwner != ((NetworkBehaviour)this).OwnerClientId)
			{
				observedHauntOwner = ((NetworkBehaviour)this).OwnerClientId;
				hauntVisits = 0;
				nextHaunt = Time.time + 6f;
				noticedThisVisit = false;
			}
			bool hauntVisible = base.currentBehaviourStateIndex != 0 && CanHaunt(HauntedPlayer) && (HachiwareVisibleToEveryone || ((NetworkBehaviour)this).IsOwner);
			SetHauntVisible(hauntVisible);
		}

		private void SetHauntVisible(bool visible)
		{
			Renderer[] array = hauntRenderers;
			foreach (Renderer val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.enabled = visible;
				}
			}
			Collider[] array2 = hauntColliders;
			foreach (Collider val2 in array2)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					val2.enabled = visible;
				}
			}
			if ((Object)(object)base.creatureVoice != (Object)null)
			{
				base.creatureVoice.mute = !visible;
			}
			if ((Object)(object)base.creatureSFX != (Object)null)
			{
				base.creatureSFX.mute = !visible;
			}
		}

		private void DoHauntInterval()
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			EndSearch();
			base.targetPlayer = HauntedPlayer;
			if (!CanHaunt(base.targetPlayer))
			{
				HoldPosition();
				Change(State.Friendly);
				return;
			}
			State currentBehaviourStateIndex = (State)base.currentBehaviourStateIndex;
			switch (currentBehaviourStateIndex)
			{
			case State.Friendly:
				HoldPosition();
				if (!(Time.time < nextHaunt))
				{
					nextHaunt = Time.time + 3f;
					if (FindHauntPoint(base.targetPlayer, out var point) && base.agent.Warp(point))
					{
						lastPosition = point;
						((EnemyAI)this).SyncPositionToClients();
						noticedThisVisit = false;
						Change(State.Angry);
					}
				}
				return;
			case State.Angry:
			{
				HoldPosition();
				Vector3 val = ((Component)base.targetPlayer).transform.position - ((Component)this).transform.position;
				val.y = 0f;
				if (((Vector3)(ref val)).sqrMagnitude > 0.01f)
				{
					((Component)this).transform.rotation = Quaternion.LookRotation(val);
				}
				if (!noticedThisVisit && base.targetPlayer.HasLineOfSightToPosition(((Component)this).transform.position + Vector3.up * 0.4f, 65f, 25, -1f, -1))
				{
					noticedThisVisit = true;
					hauntVisits++;
				}
				if (hauntVisits >= 3 && stateTime >= 1.5f)
				{
					hauntingUntil = Time.time + 10f;
					Change(State.Chase);
				}
				else if (stateTime >= 6f || Vector3.Distance(((Component)this).transform.position, ((Component)base.targetPlayer).transform.position) < 2.5f)
				{
					RetreatFromHaunt(6f);
				}
				return;
			}
			}
			if (Time.time >= hauntingUntil)
			{
				RetreatFromHaunt(8f);
				return;
			}
			if (currentBehaviourStateIndex == State.Attack)
			{
				HoldPosition();
				if (stateTime >= 1.15f)
				{
					Change(State.Chase);
				}
				return;
			}
			base.agent.speed = 4f;
			((EnemyAI)this).SetDestinationToPosition(((Component)base.targetPlayer).transform.position, true);
			if (Vector3.Distance(((Component)this).transform.position, ((Component)base.targetPlayer).transform.position) < 1.3f && ((EnemyAI)this).CheckLineOfSightForPosition(((Component)base.targetPlayer.gameplayCamera).transform.position, 180f, 3, -1f, (Transform)null))
			{
				Change(State.Attack);
			}
		}

		private bool FindHauntPoint(PlayerControllerB player, out Vector3 point)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_00d8: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: 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)
			point = default(Vector3);
			NavMeshHit val = default(NavMeshHit);
			if (!NavMesh.SamplePosition(((Component)player).transform.position, ref val, 2f, -1))
			{
				return false;
			}
			NavMeshPath val2 = new NavMeshPath();
			Vector3 forward = ((Component)player.gameplayCamera).transform.forward;
			forward.y = 0f;
			float[] array = new float[4] { 8f, 6f, 10f, 4f };
			NavMeshHit val3 = default(NavMeshHit);
			foreach (float num in array)
			{
				float[] array2 = new float[5] { 180f, 135f, -135f, 90f, -90f };
				foreach (float num2 in array2)
				{
					if (NavMesh.SamplePosition(((NavMeshHit)(ref val)).position + Quaternion.Euler(0f, num2, 0f) * ((Vector3)(ref forward)).normalized * num, ref val3, 1.5f, -1) && !(Mathf.Abs(((NavMeshHit)(ref val3)).position.y - ((NavMeshHit)(ref val)).position.y) > 1.5f) && !(Vector3.Distance(((Component)player).transform.position, ((NavMeshHit)(ref val3)).position) < 3f) && !player.HasLineOfSightToPosition(((NavMeshHit)(ref val3)).position + Vector3.up * 0.4f, 70f, 25, -1f, -1) && NavMesh.CalculatePath(((NavMeshHit)(ref val)).position, ((NavMeshHit)(ref val3)).position, -1, val2) && (int)val2.status == 0 && !Physics.CheckCapsule(((NavMeshHit)(ref val3)).position + Vector3.up * 0.3f, ((NavMeshHit)(ref val3)).position + Vector3.up * 0.6f, 0.22f, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1))
					{
						point = ((NavMeshHit)(ref val3)).position;
						return true;
					}
				}
			}
			return false;
		}

		private void RetreatFromHaunt(float delay)
		{
			HoldPosition();
			nextHaunt = Time.time + delay;
			noticedThisVisit = false;
			Change(State.Friendly);
		}
	}
	public sealed class PlushItem : GrabbableObject
	{
		private readonly NetworkVariable<int> saleValue = new NetworkVariable<int>(0, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public override void Start()
		{
			((GrabbableObject)this).Start();
			ScanNodeProperties componentInChildren = ((Component)this).GetComponentInChildren<ScanNodeProperties>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.nodeType = 2;
				componentInChildren.creatureScanID = -1;
				componentInChildren.minRange = 0;
				componentInChildren.maxRange = 15;
				componentInChildren.headerText = base.itemProperties.itemName;
			}
			((GrabbableObject)this).SetScrapValue(base.scrapValue);
		}

		protected override void __initializeVariables()
		{
			((GrabbableObject)this).__initializeVariables();
			((NetworkVariableBase)saleValue).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)saleValue, "saleValue");
			((NetworkBehaviour)this).NetworkVariableFields.Add((NetworkVariableBase)(object)saleValue);
		}

		public override void OnNetworkSpawn()
		{
			((NetworkBehaviour)this).OnNetworkSpawn();
			NetworkVariable<int> obj = saleValue;
			obj.OnValueChanged = (OnValueChangedDelegate<int>)(object)Delegate.Combine((Delegate?)(object)obj.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<int>(ApplyValue));
			if (((NetworkBehaviour)this).IsServer)
			{
				saleValue.Value = base.scrapValue;
			}
			else if (saleValue.Value > 0)
			{
				((GrabbableObject)this).SetScrapValue(saleValue.Value);
			}
		}

		public override void Update()
		{
			((GrabbableObject)this).Update();
			if (((NetworkBehaviour)this).IsSpawned && ((NetworkBehaviour)this).IsServer && saleValue.Value != base.scrapValue)
			{
				saleValue.Value = base.scrapValue;
			}
		}

		private void ApplyValue(int previous, int current)
		{
			((GrabbableObject)this).SetScrapValue(current);
		}

		public override void OnNetworkDespawn()
		{
			NetworkVariable<int> obj = saleValue;
			obj.OnValueChanged = (OnValueChangedDelegate<int>)(object)Delegate.Remove((Delegate?)(object)obj.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<int>(ApplyValue));
			((NetworkBehaviour)this).OnNetworkDespawn();
		}
	}
}