Decompiled source of REPO Gachi Billboard Encounter v0.7.3

BepInEx\plugins\Prile.GachiBillboardEncounter\RepoGachiBillboardEncounter.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace RepoGachiBillboardEncounter;

internal sealed class EncounterAssetBank
{
	public Texture2D PortraitTexture;

	public AudioClip HitIntro;

	public AudioClip HitFinisher;

	public readonly List<AmbientLineDefinition> AmbientLines = new List<AmbientLineDefinition>();

	public readonly List<EncounterTrackDefinition> Tracks = new List<EncounterTrackDefinition>();
}
internal sealed class AmbientLineDefinition
{
	public readonly string Id;

	public readonly string FileName;

	public readonly string Caption;

	public readonly float Volume;

	public readonly string SourcePath;

	public AudioClip Clip;

	public AmbientLineDefinition(string id, string fileName, string caption, float volume)
		: this(id, fileName, caption, volume, string.Empty)
	{
	}

	public AmbientLineDefinition(string id, string fileName, string caption, float volume, string sourcePath)
	{
		Id = id;
		FileName = fileName;
		Caption = caption;
		Volume = volume;
		SourcePath = sourcePath;
	}
}
internal sealed class EncounterTrackDefinition
{
	public readonly string Id;

	public readonly string FileName;

	public readonly string Caption;

	public readonly float Volume;

	public readonly string SourcePath;

	public EncounterTrackDefinition(string id, string fileName, string caption, float volume, string sourcePath)
	{
		Id = id;
		FileName = fileName;
		Caption = caption;
		Volume = volume;
		SourcePath = sourcePath;
	}
}
internal static class BinaryStlMeshLoader
{
	public static Mesh Load(string path)
	{
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: 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_00ca: 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_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: 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_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Expected O, but got Unknown
		if (string.IsNullOrWhiteSpace(path))
		{
			throw new ArgumentException("STL path is empty.", "path");
		}
		using FileStream fileStream = File.OpenRead(path);
		using BinaryReader binaryReader = new BinaryReader(fileStream);
		if (fileStream.Length < 84)
		{
			throw new InvalidDataException("STL file is too small to contain a valid binary header.");
		}
		binaryReader.ReadBytes(80);
		uint num = binaryReader.ReadUInt32();
		long num2 = 84 + (long)num * 50L;
		if (fileStream.Length < num2)
		{
			throw new InvalidDataException("STL file ended before all triangles could be read.");
		}
		int num3 = checked((int)num * 3);
		Vector3[] array = (Vector3[])(object)new Vector3[num3];
		int[] array2 = new int[num3];
		for (int i = 0; i < num; i++)
		{
			int num4 = i * 3;
			binaryReader.ReadSingle();
			binaryReader.ReadSingle();
			binaryReader.ReadSingle();
			array[num4] = ReadVertex(binaryReader);
			array[num4 + 1] = ReadVertex(binaryReader);
			array[num4 + 2] = ReadVertex(binaryReader);
			array2[num4] = num4;
			array2[num4 + 1] = num4 + 1;
			array2[num4 + 2] = num4 + 2;
			binaryReader.ReadUInt16();
		}
		Mesh val = new Mesh
		{
			name = Path.GetFileNameWithoutExtension(path),
			vertices = array,
			triangles = array2
		};
		val.RecalculateNormals();
		val.RecalculateBounds();
		return val;
	}

	private static Vector3 ReadVertex(BinaryReader reader)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		float num = reader.ReadSingle();
		float num2 = reader.ReadSingle();
		float num3 = reader.ReadSingle();
		return new Vector3(num, num3, 0f - num2);
	}
}
internal sealed class GachiBillboardEnemy : MonoBehaviour
{
	private enum MovementPattern
	{
		Chase,
		Flank,
		Retreat,
		Charge
	}

	private GachiEncounterController _controller;

	private RepoGachiBillboardEncounterPlugin _plugin;

	private EncounterAssetBank _assets;

	private EncounterTrackDefinition _selectedTrack;

	private PlayerAvatar _localPlayer;

	private PlayerAvatar _player;

	private Transform _targetTransform;

	private AudioSource _musicSource;

	private AudioSource _voiceSource;

	private AudioSource _impactSource;

	private GameObject _visualRoot;

	private GameObject _quad;

	private GameObject _coreCube;

	private GameObject _faceOverlay;

	private Material _quadMaterial;

	private Material _coreMaterial;

	private Mesh _coreMesh;

	private Material _faceMaterial;

	private Texture2D _faceTexture;

	private BoxCollider _hitbox;

	private Rigidbody _hitboxBody;

	private NavMeshPath _navPath;

	private AudioClip _trackClip;

	private int _cornerIndex;

	private int _currentHealth;

	private bool _hasPath;

	private bool _cleanupStarted;

	private bool _spawnPulseTriggered;

	private bool _nearPulseTriggered;

	private bool _catchSequenceRunning;

	private bool _postSongPhaseStarted;

	private bool _songLoading;

	private bool _songLoaded;

	private bool _sharedEncounter;

	private float _lifetime;

	private float _bobTime;

	private float _nextRepathTime;

	private float _nextAmbientTime;

	private float _nextPatternTime;

	private float _nextCatchTime;

	private float _nextDamageTime;

	private float _despawnTime = float.PositiveInfinity;

	private float _stuckTimer;

	private float _patternStrafe;

	private float _patternForward;

	private float _trackVolumeMultiplier = 1f;

	private float _speedBurstEndTime;

	private float _songEndTime = float.PositiveInfinity;

	private float _evasionDirection = 1f;

	private float _nextTransformBroadcastTime;

	private bool _coreUsesCustomModel;

	private bool _hasReplicatedTransform;

	private int _cycleId;

	private int _targetActorNumber;

	private MovementPattern _movementPattern;

	private Vector3 _lastPosition;

	private Vector3 _replicatedPosition;

	private Vector3 _coreBaseScale = Vector3.one;

	private Vector3 _coreBaseLocalPosition = Vector3.zero;

	private Vector3 _faceAnchorLocal = Vector3.zero;

	private Vector3 _faceBaseScale = Vector3.one;

	private Quaternion _coreBaseLocalRotation = Quaternion.identity;

	private string _lastAmbientLineId = string.Empty;

	private string _spawnCueId = string.Empty;

	public int CycleId => _cycleId;

	public void Setup(GachiEncounterController controller, RepoGachiBillboardEncounterPlugin plugin, EncounterAssetBank assets, EncounterTrackDefinition selectedTrack, string spawnCueId, Vector3 spawnPosition, int targetActorNumber, int cycleId, int startingHealth, bool sharedEncounter)
	{
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Expected O, but got Unknown
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: 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_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: 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_00b6: 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_00c7: 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_009d: 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_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		_controller = controller;
		_plugin = plugin;
		_assets = assets ?? new EncounterAssetBank();
		_selectedTrack = selectedTrack;
		_spawnCueId = spawnCueId ?? string.Empty;
		_localPlayer = PlayerAvatar.instance;
		_sharedEncounter = sharedEncounter;
		_cycleId = cycleId;
		_targetActorNumber = targetActorNumber;
		_navPath = new NavMeshPath();
		_currentHealth = Mathf.Max(1, startingHealth);
		Vector3 val = spawnPosition;
		NavMeshHit val2 = default(NavMeshHit);
		if (NavMesh.SamplePosition(spawnPosition + Vector3.up * 2f, ref val2, 10f, -1))
		{
			val = ((NavMeshHit)(ref val2)).position;
		}
		((Component)this).transform.position = val;
		_lastPosition = ((Component)this).transform.position;
		_replicatedPosition = ((Component)this).transform.position;
		_hasReplicatedTransform = true;
		_nextTransformBroadcastTime = Time.time;
		CreateVisuals(_assets.PortraitTexture ?? CreateEmergencyTexture());
		CreateHitbox();
		CreateAudioSources();
		PlaySpawnAudioCue(_spawnCueId, fallbackOnly: false);
		ScheduleNextAmbient(_plugin.PostSongPhraseMinDelay.Value, _plugin.PostSongPhraseMaxDelay.Value);
		SetTargetActor(_targetActorNumber);
		PickNewPattern(immediate: true);
		RefreshPath(((Object)(object)_player != (Object)null) ? ((Component)_player).transform.position : val, immediate: true);
		((MonoBehaviour)this).StartCoroutine(LoadAndPlayTrackCoroutine(_selectedTrack));
	}

	private void CreateVisuals(Texture2D portraitTexture)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Expected O, but got Unknown
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Expected O, but got Unknown
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		_visualRoot = new GameObject("VisualRoot");
		_visualRoot.transform.SetParent(((Component)this).transform, false);
		_coreMaterial = new Material(Shader.Find("Standard") ?? Shader.Find("Sprites/Default"));
		_coreMaterial.color = new Color(0.25f, 0.95f, 1f, 0.96f);
		if (TryCreateCoreModel())
		{
			TryCreateFaceOverlay(portraitTexture);
			return;
		}
		CreateBillboardQuad(portraitTexture);
		CreateFallbackCoreCube();
	}

	private void CreateBillboardQuad(Texture2D portraitTexture)
	{
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Expected O, but got Unknown
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		_quad = GameObject.CreatePrimitive((PrimitiveType)5);
		((Object)_quad).name = "Billboard";
		_quad.transform.SetParent(_visualRoot.transform, false);
		Collider component = _quad.GetComponent<Collider>();
		if ((Object)(object)component != (Object)null)
		{
			Object.Destroy((Object)(object)component);
		}
		_quadMaterial = new Material(Shader.Find("Unlit/Transparent") ?? Shader.Find("Sprites/Default"));
		_quadMaterial.mainTexture = (Texture)(object)portraitTexture;
		_quadMaterial.color = Color.white;
		MeshRenderer component2 = _quad.GetComponent<MeshRenderer>();
		((Renderer)component2).material = _quadMaterial;
		((Renderer)component2).shadowCastingMode = (ShadowCastingMode)0;
		((Renderer)component2).receiveShadows = false;
	}

	private void TryCreateFaceOverlay(Texture2D portraitTexture)
	{
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Expected O, but got Unknown
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: 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_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_00d6: 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_00fd: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)_coreCube == (Object)null) && !((Object)(object)_coreMesh == (Object)null) && !((Object)(object)portraitTexture == (Object)null))
		{
			_faceTexture = CreateFaceOverlayTexture(portraitTexture);
			_faceMaterial = new Material(Shader.Find("Unlit/Transparent") ?? Shader.Find("Sprites/Default"));
			_faceMaterial.mainTexture = (Texture)(object)_faceTexture;
			_faceMaterial.color = Color.white;
			_faceOverlay = GameObject.CreatePrimitive((PrimitiveType)5);
			((Object)_faceOverlay).name = "FaceOverlay";
			_faceOverlay.transform.SetParent(_coreCube.transform, false);
			_faceAnchorLocal = CalculateFaceAnchorLocal(_coreMesh.bounds);
			_faceBaseScale = CalculateFaceBaseScale(_coreMesh.bounds);
			_faceOverlay.transform.localPosition = _faceAnchorLocal;
			_faceOverlay.transform.localScale = _faceBaseScale;
			Collider component = _faceOverlay.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			MeshRenderer component2 = _faceOverlay.GetComponent<MeshRenderer>();
			((Renderer)component2).material = _faceMaterial;
			((Renderer)component2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)component2).receiveShadows = false;
		}
	}

	private static Vector3 CalculateFaceAnchorLocal(Bounds bounds)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).min.y + ((Bounds)(ref bounds)).size.y * 0.825f, ((Bounds)(ref bounds)).center.z);
	}

	private static Vector3 CalculateFaceBaseScale(Bounds bounds)
	{
		//IL_0007: 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_003f: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Max(6f, ((Bounds)(ref bounds)).size.x * 0.24f);
		float num2 = Mathf.Max(8f, ((Bounds)(ref bounds)).size.y * 0.16f);
		return new Vector3(num, num2, 1f);
	}

	private Texture2D CreateFaceOverlayTexture(Texture2D sourceTexture)
	{
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Expected O, but got Unknown
		int width = ((Texture)sourceTexture).width;
		int height = ((Texture)sourceTexture).height;
		Color[] pixels = sourceTexture.GetPixels();
		for (int i = 0; i < pixels.Length; i++)
		{
			int num = i % width;
			int num2 = i / width;
			float num3 = ((width > 1) ? ((float)num / (float)(width - 1)) : 0.5f);
			float num4 = ((height > 1) ? ((float)num2 / (float)(height - 1)) : 0.5f);
			float num5 = (num3 - 0.5f) / 0.43f;
			float num6 = (num4 - 0.57f) / 0.42f;
			float num7 = Mathf.Sqrt(num5 * num5 + num6 * num6);
			float num8 = 1f - Mathf.SmoothStep(0.78f, 1.03f, num7);
			num8 *= Mathf.SmoothStep(0.16f, 0.32f, num4);
			pixels[i].a *= num8;
		}
		Texture2D val = new Texture2D(width, height, (TextureFormat)4, false);
		val.SetPixels(pixels);
		val.Apply(false, false);
		((Object)val).name = ((Object)sourceTexture).name + "_face";
		((Texture)val).wrapMode = (TextureWrapMode)1;
		((Texture)val).filterMode = (FilterMode)1;
		return val;
	}

	private Mesh BuildHeadFaceOverlayMesh(Mesh sourceMesh)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: 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_0061: 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_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//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_0106: 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_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_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: 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_0178: 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)
		//IL_017c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: 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_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_027f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0284: 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_02a2: 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)
		//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c1: Expected O, but got Unknown
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: 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)
		Bounds bounds = sourceMesh.bounds;
		Vector3[] vertices = sourceMesh.vertices;
		int[] triangles = sourceMesh.triangles;
		Vector3 center = ((Bounds)(ref bounds)).center;
		float num = ((Bounds)(ref bounds)).min.y + ((Bounds)(ref bounds)).size.y * 0.66f;
		float num2 = ((Bounds)(ref bounds)).min.y + ((Bounds)(ref bounds)).size.y * 0.97f;
		float num3 = ((Bounds)(ref bounds)).size.x * 0.18f;
		float faceMinX = center.x - ((Bounds)(ref bounds)).size.x * 0.12f;
		float faceMaxX = center.x + ((Bounds)(ref bounds)).size.x * 0.12f;
		float faceMinY = ((Bounds)(ref bounds)).min.y + ((Bounds)(ref bounds)).size.y * 0.69f;
		float faceMaxY = ((Bounds)(ref bounds)).min.y + ((Bounds)(ref bounds)).size.y * 0.93f;
		float num4 = 0f;
		float num5 = 0f;
		for (int i = 0; i < triangles.Length; i += 3)
		{
			Vector3 val = vertices[triangles[i]];
			Vector3 val2 = vertices[triangles[i + 1]];
			Vector3 val3 = vertices[triangles[i + 2]];
			Vector3 val4 = (val + val2 + val3) / 3f;
			if (val4.y < num || val4.y > num2 || Mathf.Abs(val4.x - center.x) > num3)
			{
				continue;
			}
			Vector3 val5 = Vector3.Cross(val2 - val, val3 - val);
			float magnitude = ((Vector3)(ref val5)).magnitude;
			if (magnitude < 0.001f)
			{
				continue;
			}
			Vector3 val6 = val5 / magnitude;
			if (!(Mathf.Abs(val6.y) > 0.78f))
			{
				if (val6.z >= 0f)
				{
					num4 += val6.z * magnitude;
				}
				else
				{
					num5 += (0f - val6.z) * magnitude;
				}
			}
		}
		float faceDirection = ((num4 >= num5) ? 1f : (-1f));
		List<Vector3> list = new List<Vector3>();
		List<Vector2> list2 = new List<Vector2>();
		List<int> list3 = new List<int>();
		if (TryAppendHeadFaceTriangles(vertices, triangles, center, num, num2, num3, faceDirection, 0.12f, faceMinX, faceMaxX, faceMinY, faceMaxY, list, list2, list3) == 0)
		{
			TryAppendHeadFaceTriangles(vertices, triangles, center, num, num2, num3, faceDirection, -1f, faceMinX, faceMaxX, faceMinY, faceMaxY, list, list2, list3);
		}
		if (list3.Count == 0)
		{
			return null;
		}
		Mesh val7 = new Mesh
		{
			name = ((Object)sourceMesh).name + "_face"
		};
		val7.SetVertices(list);
		val7.SetUVs(0, list2);
		val7.SetTriangles(list3, 0);
		val7.RecalculateNormals();
		val7.RecalculateBounds();
		return val7;
	}

	private int TryAppendHeadFaceTriangles(Vector3[] vertices, int[] triangles, Vector3 center, float headMinY, float headMaxY, float headHalfWidth, float faceDirection, float facingThreshold, float faceMinX, float faceMaxX, float faceMinY, float faceMaxY, List<Vector3> overlayVertices, List<Vector2> overlayUvs, List<int> overlayTriangles)
	{
		//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_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//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_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: 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_007c: 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_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: 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_010b: 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_0119: 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_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
		int num = 0;
		for (int i = 0; i < triangles.Length; i += 3)
		{
			Vector3 val = vertices[triangles[i]];
			Vector3 val2 = vertices[triangles[i + 1]];
			Vector3 val3 = vertices[triangles[i + 2]];
			Vector3 val4 = (val + val2 + val3) / 3f;
			if (val4.y < headMinY || val4.y > headMaxY || Mathf.Abs(val4.x - center.x) > headHalfWidth)
			{
				continue;
			}
			Vector3 val5 = Vector3.Cross(val2 - val, val3 - val);
			float magnitude = ((Vector3)(ref val5)).magnitude;
			if (!(magnitude < 0.001f))
			{
				Vector3 val6 = val5 / magnitude;
				if (!(Mathf.Abs(val6.y) > 0.78f) && (!(facingThreshold >= 0f) || !(faceDirection * val6.z < facingThreshold)))
				{
					int count = overlayVertices.Count;
					Vector3 val7 = val6 * 0.75f;
					overlayVertices.Add(val + val7);
					overlayVertices.Add(val2 + val7);
					overlayVertices.Add(val3 + val7);
					overlayUvs.Add(CreateFaceUv(val, faceMinX, faceMaxX, faceMinY, faceMaxY));
					overlayUvs.Add(CreateFaceUv(val2, faceMinX, faceMaxX, faceMinY, faceMaxY));
					overlayUvs.Add(CreateFaceUv(val3, faceMinX, faceMaxX, faceMinY, faceMaxY));
					overlayTriangles.Add(count);
					overlayTriangles.Add(count + 1);
					overlayTriangles.Add(count + 2);
					num++;
				}
			}
		}
		return num;
	}

	private static Vector2 CreateFaceUv(Vector3 vertex, float faceMinX, float faceMaxX, float faceMinY, float faceMaxY)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.InverseLerp(faceMinX, faceMaxX, vertex.x);
		float num2 = Mathf.InverseLerp(faceMinY, faceMaxY, vertex.y);
		return new Vector2(num, num2);
	}

	private void CreateFallbackCoreCube()
	{
		//IL_0054: 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_008e: 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_00a4: 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_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		_coreUsesCustomModel = false;
		_coreCube = GameObject.CreatePrimitive((PrimitiveType)3);
		((Object)_coreCube).name = "CoreCube";
		_coreCube.transform.SetParent(((Component)this).transform, false);
		_coreCube.transform.localPosition = new Vector3(0f, 0.58f, 0f);
		_coreCube.transform.localScale = new Vector3(0.8f, 0.8f, 0.8f);
		_coreBaseLocalPosition = _coreCube.transform.localPosition;
		_coreBaseScale = _coreCube.transform.localScale;
		_coreBaseLocalRotation = Quaternion.identity;
		Collider component = _coreCube.GetComponent<Collider>();
		if ((Object)(object)component != (Object)null)
		{
			Object.Destroy((Object)(object)component);
		}
		MeshRenderer component2 = _coreCube.GetComponent<MeshRenderer>();
		if ((Object)(object)component2 != (Object)null)
		{
			((Renderer)component2).material = _coreMaterial;
			((Renderer)component2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)component2).receiveShadows = false;
		}
	}

	private bool TryCreateCoreModel()
	{
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Expected O, but got Unknown
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: 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_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0210: Unknown result type (might be due to invalid IL or missing references)
		//IL_0234: Unknown result type (might be due to invalid IL or missing references)
		string text = FindCoreModelPath(((Object)(object)_plugin != (Object)null && _plugin.CoreModelPath != null) ? _plugin.CoreModelPath.Value : string.Empty);
		if (string.IsNullOrWhiteSpace(text))
		{
			return false;
		}
		try
		{
			_coreMesh = BinaryStlMeshLoader.Load(text);
		}
		catch (Exception ex)
		{
			if ((Object)(object)_plugin != (Object)null)
			{
				_plugin.LogSource.LogWarning((object)("Failed to load core STL model " + text + ": " + ex.Message));
			}
			_coreMesh = null;
			return false;
		}
		if ((Object)(object)_coreMesh == (Object)null || _coreMesh.vertexCount < 3)
		{
			_coreMesh = null;
			return false;
		}
		_coreUsesCustomModel = true;
		_coreCube = new GameObject("CoreModel");
		_coreCube.transform.SetParent(((Component)this).transform, false);
		_coreCube.AddComponent<MeshFilter>().sharedMesh = _coreMesh;
		MeshRenderer obj = _coreCube.AddComponent<MeshRenderer>();
		((Renderer)obj).material = _coreMaterial;
		((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
		((Renderer)obj).receiveShadows = false;
		Bounds bounds = _coreMesh.bounds;
		float num = Mathf.Max(0.001f, ((Bounds)(ref bounds)).size.y);
		float num2 = Mathf.Clamp(_plugin.CoreModelHeight.Value, 0.25f, 5f) / num;
		_coreBaseScale = Vector3.one * num2;
		_coreBaseLocalPosition = new Vector3((0f - ((Bounds)(ref bounds)).center.x) * num2, (0f - ((Bounds)(ref bounds)).min.y) * num2, (0f - ((Bounds)(ref bounds)).center.z) * num2);
		_coreBaseLocalRotation = Quaternion.Euler(0f, _plugin.CoreModelYawOffset.Value, 0f);
		_coreCube.transform.localPosition = _coreBaseLocalPosition;
		_coreCube.transform.localRotation = _coreBaseLocalRotation;
		_coreCube.transform.localScale = _coreBaseScale;
		_coreMaterial.color = new Color(0.95f, 0.79f, 0.71f, 1f);
		if ((Object)(object)_plugin != (Object)null)
		{
			_plugin.LogSource.LogInfo((object)("Loaded core STL model: " + Path.GetFileName(text)));
		}
		return true;
	}

	private string FindCoreModelPath(string configuredPath)
	{
		if (!string.IsNullOrWhiteSpace(configuredPath))
		{
			if (File.Exists(configuredPath))
			{
				return configuredPath;
			}
			string fileName = Path.GetFileName(configuredPath);
			if (!string.IsNullOrWhiteSpace(fileName))
			{
				string text = Path.Combine(GetAssetsDirectory(), fileName);
				if (File.Exists(text))
				{
					return text;
				}
			}
		}
		string text2 = Path.Combine(GetAssetsDirectory(), "billy_core.stl");
		if (!File.Exists(text2))
		{
			return string.Empty;
		}
		return text2;
	}

	private string GetAssetsDirectory()
	{
		return Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)_plugin).Info.Location) ?? string.Empty, "Assets");
	}

	private void CreateHitbox()
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		_hitbox = ((Component)this).gameObject.AddComponent<BoxCollider>();
		((Collider)_hitbox).isTrigger = false;
		_hitbox.center = new Vector3(0f, 0.58f, 0f);
		_hitbox.size = new Vector3(0.9f, 0.9f, 0.9f);
		_hitboxBody = ((Component)this).gameObject.AddComponent<Rigidbody>();
		_hitboxBody.useGravity = false;
		_hitboxBody.isKinematic = true;
		_hitboxBody.collisionDetectionMode = (CollisionDetectionMode)3;
	}

	private void CreateAudioSources()
	{
		_musicSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		_musicSource.playOnAwake = false;
		_musicSource.loop = false;
		_musicSource.spatialBlend = 1f;
		_musicSource.rolloffMode = (AudioRolloffMode)1;
		_musicSource.minDistance = 3f;
		_musicSource.maxDistance = _plugin.MusicDistanceMax.Value;
		_musicSource.volume = _plugin.MusicVolumeFar.Value;
		_voiceSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		_voiceSource.playOnAwake = false;
		_voiceSource.loop = false;
		_voiceSource.spatialBlend = 1f;
		_voiceSource.rolloffMode = (AudioRolloffMode)1;
		_voiceSource.minDistance = 7f;
		_voiceSource.maxDistance = Mathf.Max(18f, _plugin.MusicDistanceMax.Value * 0.9f);
		_voiceSource.volume = 1f;
		_impactSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		_impactSource.playOnAwake = false;
		_impactSource.loop = false;
		_impactSource.spatialBlend = 1f;
		_impactSource.rolloffMode = (AudioRolloffMode)1;
		_impactSource.minDistance = 3f;
		_impactSource.maxDistance = Mathf.Max(10f, _plugin.MusicDistanceMax.Value * 0.65f);
	}

	private IEnumerator LoadAndPlayTrackCoroutine(EncounterTrackDefinition track)
	{
		_songLoading = true;
		List<EncounterTrackDefinition> candidates = BuildTrackLoadCandidates(track);
		bool playedTrack = false;
		for (int candidateIndex = 0; candidateIndex < candidates.Count; candidateIndex++)
		{
			EncounterTrackDefinition candidate = candidates[candidateIndex];
			if (candidate == null || string.IsNullOrWhiteSpace(candidate.SourcePath) || !File.Exists(candidate.SourcePath))
			{
				continue;
			}
			UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(ToFileUri(candidate.SourcePath), GuessAudioType(candidate.SourcePath));
			try
			{
				yield return request.SendWebRequest();
				if ((int)request.result != 1)
				{
					_plugin.LogSource.LogWarning((object)("Failed to load encounter track " + candidate.FileName + ": " + request.error));
					continue;
				}
				AudioClip content = DownloadHandlerAudioClip.GetContent(request);
				if ((Object)(object)content == (Object)null)
				{
					_plugin.LogSource.LogWarning((object)("Encounter track returned no clip: " + candidate.FileName));
					continue;
				}
				_selectedTrack = candidate;
				_trackClip = content;
				((Object)_trackClip).name = Path.GetFileNameWithoutExtension(candidate.SourcePath);
				_trackVolumeMultiplier = Mathf.Clamp(candidate.Volume * CalculateTrackNormalization(content), 0.45f, 1.2f);
				_musicSource.clip = _trackClip;
				_musicSource.Play();
				_songLoaded = true;
				_songEndTime = Time.time + Mathf.Max(2f, _trackClip.length);
				_despawnTime = float.PositiveInfinity;
				playedTrack = true;
				_plugin.LogSource.LogInfo((object)("Encounter track started: " + candidate.FileName));
				break;
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
		}
		if (!playedTrack)
		{
			_plugin.LogSource.LogWarning((object)"No encounter track could be started. Falling back to spawn cue and chatter.");
			PlaySpawnAudioCue(_spawnCueId, fallbackOnly: true);
			_despawnTime = Time.time + _plugin.MaxEncounterDuration.Value + _plugin.PostSongChatterDuration.Value;
		}
		_songLoading = false;
	}

	private List<EncounterTrackDefinition> BuildTrackLoadCandidates(EncounterTrackDefinition preferredTrack)
	{
		List<EncounterTrackDefinition> list = new List<EncounterTrackDefinition>();
		if (preferredTrack != null)
		{
			list.Add(preferredTrack);
		}
		if (_assets == null || _assets.Tracks == null || _assets.Tracks.Count == 0)
		{
			return list;
		}
		List<EncounterTrackDefinition> list2 = new List<EncounterTrackDefinition>();
		for (int i = 0; i < _assets.Tracks.Count; i++)
		{
			EncounterTrackDefinition encounterTrackDefinition = _assets.Tracks[i];
			if (encounterTrackDefinition != null && encounterTrackDefinition != preferredTrack)
			{
				list2.Add(encounterTrackDefinition);
			}
		}
		for (int num = list2.Count - 1; num > 0; num--)
		{
			int index = Random.Range(0, num + 1);
			EncounterTrackDefinition value = list2[num];
			list2[num] = list2[index];
			list2[index] = value;
		}
		for (int j = 0; j < list2.Count; j++)
		{
			list.Add(list2[j]);
		}
		return list;
	}

	private float CalculateTrackNormalization(AudioClip clip)
	{
		if ((Object)(object)clip == (Object)null)
		{
			return 1f;
		}
		int num = Mathf.Min(clip.samples * Mathf.Max(1, clip.channels), 131072);
		if (num <= 0)
		{
			return 1f;
		}
		float[] array = new float[num];
		try
		{
			if (!clip.GetData(array, 0))
			{
				return 1f;
			}
			float num2 = 0f;
			for (int i = 0; i < array.Length; i++)
			{
				float num3 = Mathf.Abs(array[i]);
				if (num3 > num2)
				{
					num2 = num3;
				}
			}
			if (num2 <= 0.001f)
			{
				return 1f;
			}
			return Mathf.Clamp(0.82f / num2, 0.85f, 1.55f);
		}
		catch
		{
			return 1f;
		}
	}

	private void Update()
	{
		//IL_0182: 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_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_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_019f: 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_01d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
		if (_cleanupStarted)
		{
			return;
		}
		_lifetime += Time.deltaTime;
		_bobTime += Time.deltaTime;
		RefreshTargetPlayer();
		if ((Object)(object)_player == (Object)null || (Object)(object)Camera.main == (Object)null || (Object)(object)_targetTransform == (Object)null)
		{
			if (!_sharedEncounter || _controller.HasEncounterAuthority)
			{
				_controller.RequestEncounterFinish(this, killed: false);
			}
			return;
		}
		if (!_songLoaded && !_songLoading && _lifetime > _plugin.MaxEncounterDuration.Value)
		{
			if (!_sharedEncounter || _controller.HasEncounterAuthority)
			{
				_controller.RequestEncounterFinish(this, killed: false);
			}
			return;
		}
		if (_songLoaded && !_postSongPhaseStarted && (!_musicSource.isPlaying || Time.time >= _songEndTime))
		{
			BeginPostSongChatter();
		}
		if (!_songLoading && !_catchSequenceRunning && Time.time >= _despawnTime && ((Object)(object)_voiceSource == (Object)null || !_voiceSource.isPlaying || Time.time >= _despawnTime + 2f))
		{
			if (!_sharedEncounter || _controller.HasEncounterAuthority)
			{
				_controller.RequestEncounterFinish(this, killed: false);
			}
			return;
		}
		if (!_spawnPulseTriggered)
		{
			_spawnPulseTriggered = true;
		}
		Vector3 position = ((Component)_player).transform.position;
		Vector3 position2 = _targetTransform.position;
		float num = Vector3.Distance(((Component)this).transform.position, position);
		float num2 = 1f - Mathf.Clamp01(num / Mathf.Max(1f, _plugin.MusicDistanceMax.Value));
		if (HasMovementAuthority())
		{
			UpdateMovement(position, num2);
			BroadcastSharedTransformIfNeeded();
		}
		else
		{
			ApplyReplicatedMovement();
			num = Vector3.Distance(((Component)this).transform.position, position);
			num2 = 1f - Mathf.Clamp01(num / Mathf.Max(1f, _plugin.MusicDistanceMax.Value));
		}
		UpdateVisuals(num2);
		UpdateAudio(num2);
		UpdateAmbientBehavior(num2);
		if (!_nearPulseTriggered && num2 > 0.63f)
		{
			_nearPulseTriggered = true;
			_controller.PulseLights(_plugin.LightPulseDuration.Value * 0.8f, _plugin.LightPulseMultiplier.Value + 0.35f);
			if (IsLocalTarget())
			{
				_player.FlashlightFlicker(1.7f);
				_player.PlayerGlitchShort();
			}
		}
		if (!_catchSequenceRunning && Time.time >= _nextCatchTime && num <= _plugin.CatchDistance.Value && HasLineOfSight(position2))
		{
			((MonoBehaviour)this).StartCoroutine(CatchSequence());
		}
	}

	private void UpdateMovement(Vector3 playerGround, float proximity)
	{
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0170: 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)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_023a: Unknown result type (might be due to invalid IL or missing references)
		//IL_023f: 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)
		if (_catchSequenceRunning)
		{
			return;
		}
		float num = Mathf.Clamp01((float)_currentHealth / (float)Mathf.Max(1, _plugin.MonsterHealth.Value));
		float num2 = 1f - num;
		if (Time.time >= _nextPatternTime)
		{
			PickNewPattern(immediate: false);
		}
		if (Time.time >= _nextRepathTime)
		{
			_nextRepathTime = Time.time + Mathf.Max(0.05f, _plugin.RepathInterval.Value);
			RefreshPath(playerGround, immediate: false);
		}
		float num3 = 1f;
		if (_movementPattern == MovementPattern.Charge)
		{
			num3 = _plugin.DashSpeedMultiplier.Value;
		}
		else if (_movementPattern == MovementPattern.Flank)
		{
			num3 = 1.08f;
		}
		else if (_movementPattern == MovementPattern.Retreat)
		{
			num3 = 0.82f;
		}
		if (Time.time < _speedBurstEndTime)
		{
			num3 = Mathf.Max(num3, _plugin.DashSpeedMultiplier.Value * (0.95f + num2 * 0.08f));
		}
		num3 *= Mathf.Lerp(0.94f, 1.1f, num2);
		num3 = Mathf.Lerp(num3, Mathf.Max(1.02f, _plugin.DashSpeedMultiplier.Value * (0.86f + num2 * 0.08f)), proximity * 0.1f);
		AdvanceAlongPath(_plugin.ChaseSpeed.Value * num3);
		float num4 = Vector2.Distance(new Vector2(((Component)this).transform.position.x, ((Component)this).transform.position.z), new Vector2(_lastPosition.x, _lastPosition.z));
		if (_hasPath && RemainingPathDistance() > Mathf.Max(2f, _plugin.CatchDistance.Value) && num4 < 0.025f)
		{
			_stuckTimer += Time.deltaTime;
			if (_stuckTimer >= _plugin.StuckRepositionDelay.Value)
			{
				_stuckTimer = 0f;
				TryFunnyReposition(playerGround);
			}
		}
		else
		{
			_stuckTimer = Mathf.Max(0f, _stuckTimer - Time.deltaTime * 0.6f);
		}
		_lastPosition = ((Component)this).transform.position;
	}

	private bool HasMovementAuthority()
	{
		if (_sharedEncounter)
		{
			if ((Object)(object)_controller != (Object)null)
			{
				return _controller.HasEncounterAuthority;
			}
			return false;
		}
		return true;
	}

	private void BroadcastSharedTransformIfNeeded()
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		if (_sharedEncounter && HasMovementAuthority() && !((Object)(object)_controller == (Object)null) && !(Time.time < _nextTransformBroadcastTime))
		{
			_nextTransformBroadcastTime = Time.time + 0.08f;
			_controller.BroadcastEncounterTransform(this, ((Component)this).transform.position);
		}
	}

	private void ApplyReplicatedMovement()
	{
		//IL_0030: 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_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		if (_hasReplicatedTransform)
		{
			float num = Mathf.Max(4.5f, _plugin.StuckRepositionRadius.Value * 1.1f);
			if (Vector3.Distance(((Component)this).transform.position, _replicatedPosition) >= num)
			{
				((Component)this).transform.position = _replicatedPosition;
			}
			else
			{
				float num2 = _plugin.ChaseSpeed.Value * _plugin.DashSpeedMultiplier.Value * 1.45f * Time.deltaTime;
				((Component)this).transform.position = Vector3.MoveTowards(((Component)this).transform.position, _replicatedPosition, num2);
			}
			_lastPosition = ((Component)this).transform.position;
		}
	}

	private void RefreshPath(Vector3 playerGround, bool immediate)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: 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_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Invalid comparison between Unknown and I4
		NavMeshHit val = default(NavMeshHit);
		if (!NavMesh.SamplePosition(((Component)this).transform.position + Vector3.up * 2f, ref val, 8f, -1))
		{
			_hasPath = false;
			if (!immediate)
			{
				TryFunnyReposition(playerGround);
			}
			return;
		}
		((Component)this).transform.position = ((NavMeshHit)(ref val)).position;
		NavMeshHit val2 = default(NavMeshHit);
		if (!NavMesh.SamplePosition(ComputeDesiredDestination(playerGround) + Vector3.up * 2f, ref val2, 5f, -1) && !NavMesh.SamplePosition(playerGround + Vector3.up * 2f, ref val2, 5f, -1))
		{
			_hasPath = false;
			return;
		}
		bool hasPath = NavMesh.CalculatePath(((NavMeshHit)(ref val)).position, ((NavMeshHit)(ref val2)).position, -1, _navPath) && _navPath.corners != null && _navPath.corners.Length > 1 && (int)_navPath.status != 2;
		_hasPath = hasPath;
		_cornerIndex = (_hasPath ? 1 : 0);
	}

	private void AdvanceAlongPath(float moveSpeed)
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: 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_0105: 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)
		if (!_hasPath || _navPath == null || _navPath.corners == null || _navPath.corners.Length <= 1)
		{
			return;
		}
		Vector3 val2 = default(Vector3);
		NavMeshHit val4 = default(NavMeshHit);
		while (_cornerIndex < _navPath.corners.Length)
		{
			Vector3 val = _navPath.corners[_cornerIndex];
			((Vector3)(ref val2))..ctor(val.x - ((Component)this).transform.position.x, 0f, val.z - ((Component)this).transform.position.z);
			if (((Vector3)(ref val2)).magnitude <= 0.3f)
			{
				_cornerIndex++;
				continue;
			}
			float num = Mathf.Min(((Vector3)(ref val2)).magnitude, moveSpeed * Time.deltaTime);
			Vector3 val3 = ((Component)this).transform.position + ((Vector3)(ref val2)).normalized * num;
			if (NavMesh.SamplePosition(val3 + Vector3.up, ref val4, 1.3f, -1))
			{
				((Component)this).transform.position = ((NavMeshHit)(ref val4)).position;
			}
			else
			{
				((Component)this).transform.position = val3;
			}
			return;
		}
		_hasPath = false;
	}

	private float RemainingPathDistance()
	{
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: 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)
		if (!_hasPath || _navPath == null || _navPath.corners == null || _cornerIndex >= _navPath.corners.Length)
		{
			return 0f;
		}
		float num = 0f;
		Vector3 val = ((Component)this).transform.position;
		for (int i = _cornerIndex; i < _navPath.corners.Length; i++)
		{
			num += Vector3.Distance(val, _navPath.corners[i]);
			val = _navPath.corners[i];
		}
		return num;
	}

	private Vector3 ComputeDesiredDestination(Vector3 playerGround)
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: 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_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_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: 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_015c: 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_016e: 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_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		Transform val = (((Object)(object)Camera.main != (Object)null) ? ((Component)Camera.main).transform : null);
		Vector3 val2;
		Vector3 normalized;
		if (!((Object)(object)val != (Object)null))
		{
			val2 = Vector3.ProjectOnPlane(((Component)_player).transform.forward, Vector3.up);
			normalized = ((Vector3)(ref val2)).normalized;
		}
		else
		{
			val2 = Vector3.ProjectOnPlane(val.forward, Vector3.up);
			normalized = ((Vector3)(ref val2)).normalized;
		}
		Vector3 val3 = normalized;
		if (((Vector3)(ref val3)).sqrMagnitude < 0.001f)
		{
			val3 = Vector3.forward;
		}
		val2 = Vector3.Cross(Vector3.up, val3);
		Vector3 normalized2 = ((Vector3)(ref val2)).normalized;
		float num = Mathf.Clamp01((float)_currentHealth / (float)Mathf.Max(1, _plugin.MonsterHealth.Value));
		float num2 = 1f - num;
		float num3 = _plugin.OrbitDistance.Value * Mathf.Lerp(1.05f, 1.22f, num2);
		float num4 = num3 * Mathf.Lerp(0.12f, 0.36f, num2);
		if (Time.time < _speedBurstEndTime)
		{
			num4 *= 1.08f;
		}
		float num5 = Mathf.Sin(_bobTime * (5.5f + num2 * 2.4f)) * num4 * _evasionDirection;
		float num6 = _patternForward * num3;
		if (_movementPattern == MovementPattern.Charge)
		{
			num6 += Mathf.Lerp(0.05f, 0.32f, num2);
		}
		return playerGround + normalized2 * (_patternStrafe * num3 + num5) + val3 * num6;
	}

	private void PickNewPattern(bool immediate)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		float num = (((Object)(object)_player != (Object)null) ? Vector3.Distance(((Component)this).transform.position, ((Component)_player).transform.position) : 999f);
		float num2 = Mathf.Clamp01((float)_currentHealth / (float)Mathf.Max(1, _plugin.MonsterHealth.Value));
		float num3 = 1f - num2;
		float value = Random.value;
		if (num < 4.8f)
		{
			if (value < 0.2f + num3 * 0.08f)
			{
				_movementPattern = MovementPattern.Charge;
			}
			else if (value < 0.78f)
			{
				_movementPattern = MovementPattern.Flank;
			}
			else
			{
				_movementPattern = MovementPattern.Retreat;
			}
		}
		else if (value < 0.38f)
		{
			_movementPattern = MovementPattern.Chase;
		}
		else if (value < 0.82f + num3 * 0.04f)
		{
			_movementPattern = MovementPattern.Flank;
		}
		else if (value < 0.96f)
		{
			_movementPattern = MovementPattern.Retreat;
		}
		else
		{
			_movementPattern = MovementPattern.Charge;
		}
		switch (_movementPattern)
		{
		case MovementPattern.Chase:
			_patternStrafe = Random.Range(-0.28f, 0.28f);
			_patternForward = Random.Range(-0.15f, 0.15f);
			break;
		case MovementPattern.Flank:
			_patternStrafe = ((Random.value < 0.5f) ? (-1f) : 1f);
			_patternForward = Random.Range(0.02f, 0.55f);
			break;
		case MovementPattern.Retreat:
			_patternStrafe = Random.Range(-1f, 1f);
			_patternForward = Random.Range(-1f, -0.45f);
			break;
		case MovementPattern.Charge:
			_patternStrafe = Random.Range(-0.42f, 0.42f);
			_patternForward = Random.Range(0.02f, 0.18f);
			break;
		}
		_evasionDirection = ((Random.value < 0.5f) ? (-1f) : 1f);
		_nextPatternTime = Time.time + (immediate ? 1.05f : Random.Range(1.1f, 2.2f));
	}

	private void UpdateVisuals(float proximity)
	{
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_030e: 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_0239: 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_0254: Unknown result type (might be due to invalid IL or missing references)
		//IL_025b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0271: Unknown result type (might be due to invalid IL or missing references)
		//IL_028c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0291: Unknown result type (might be due to invalid IL or missing references)
		//IL_0440: Unknown result type (might be due to invalid IL or missing references)
		//IL_0459: Unknown result type (might be due to invalid IL or missing references)
		//IL_0465: Unknown result type (might be due to invalid IL or missing references)
		//IL_046a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0352: Unknown result type (might be due to invalid IL or missing references)
		//IL_0357: Unknown result type (might be due to invalid IL or missing references)
		//IL_035c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0360: Unknown result type (might be due to invalid IL or missing references)
		//IL_0365: 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_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b4: 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_0386: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_0404: Unknown result type (might be due to invalid IL or missing references)
		//IL_0409: Unknown result type (might be due to invalid IL or missing references)
		//IL_053d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0487: Unknown result type (might be due to invalid IL or missing references)
		//IL_049d: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_058c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0571: Unknown result type (might be due to invalid IL or missing references)
		//IL_0510: Unknown result type (might be due to invalid IL or missing references)
		//IL_0526: Unknown result type (might be due to invalid IL or missing references)
		//IL_0530: Unknown result type (might be due to invalid IL or missing references)
		//IL_0535: Unknown result type (might be due to invalid IL or missing references)
		//IL_05c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_05cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_05cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_05dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0636: Unknown result type (might be due to invalid IL or missing references)
		//IL_05fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0610: Unknown result type (might be due to invalid IL or missing references)
		//IL_0629: Unknown result type (might be due to invalid IL or missing references)
		//IL_062e: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Camera.main == (Object)null)
		{
			return;
		}
		if ((Object)(object)_visualRoot != (Object)null && (Object)(object)_quad != (Object)null)
		{
			float num = _plugin.SpawnHeightOffset.Value + _plugin.BillboardHeight.Value * 0.35f;
			float num2 = Mathf.Sin(_bobTime * _plugin.BobFrequency.Value) * _plugin.BobAmplitude.Value;
			float num3 = Mathf.Sin(_bobTime * 3.9f) * 0.08f * (0.45f + proximity);
			float num4 = (Mathf.PerlinNoise(_bobTime * 10f, 0.37f) - 0.5f) * 0.1f * proximity;
			_visualRoot.transform.localPosition = new Vector3(num3 + num4, num + num2, 0f);
			Transform transform = ((Component)Camera.main).transform;
			_quad.transform.LookAt(transform.position, Vector3.up);
			_quad.transform.Rotate(0f, 180f, 0f);
			float num5 = _plugin.BillboardWidth.Value * (1f + proximity * 0.1f);
			float num6 = _plugin.BillboardHeight.Value * (1f + proximity * 0.05f + (((Object)(object)_voiceSource != (Object)null && _voiceSource.isPlaying) ? 0.03f : 0f));
			_quad.transform.localScale = new Vector3(num5, num6, 1f);
		}
		if ((Object)(object)_coreCube != (Object)null)
		{
			if (_coreUsesCustomModel)
			{
				float num7 = 1f + Mathf.Sin(_bobTime * 7.2f) * 0.035f + proximity * 0.06f;
				float num8 = Mathf.Sin(_bobTime * 4.8f) * 0.035f * (0.45f + proximity);
				_coreCube.transform.localPosition = _coreBaseLocalPosition + new Vector3(0f, num8, 0f);
				_coreCube.transform.localScale = _coreBaseScale * num7;
				_coreCube.transform.localRotation = _coreBaseLocalRotation * Quaternion.Euler(0f, _bobTime * 62f, 0f);
			}
			else
			{
				float num9 = 0.78f + Mathf.Sin(_bobTime * 7.2f) * 0.08f + proximity * 0.12f;
				_coreCube.transform.localScale = new Vector3(num9, num9, num9);
				_coreCube.transform.localRotation = Quaternion.Euler(_bobTime * 115f, _bobTime * 150f, _bobTime * 85f);
			}
		}
		if ((Object)(object)_faceOverlay != (Object)null && (Object)(object)_coreCube != (Object)null)
		{
			Transform transform2 = ((Component)Camera.main).transform;
			Vector3 val = _coreCube.transform.TransformPoint(_faceAnchorLocal);
			Vector3 val2 = transform2.position - val;
			if (((Vector3)(ref val2)).sqrMagnitude > 0.0001f)
			{
				Vector3 normalized = ((Vector3)(ref val2)).normalized;
				float num10 = 1f + Mathf.Sin(_bobTime * 6.4f) * 0.018f + proximity * 0.04f;
				_faceOverlay.transform.position = val + normalized * (0.05f + proximity * 0.018f);
				_faceOverlay.transform.localScale = _faceBaseScale * num10;
				_faceOverlay.transform.LookAt(transform2.position, Vector3.up);
				_faceOverlay.transform.Rotate(0f, 180f, 0f);
			}
		}
		if ((Object)(object)_quadMaterial != (Object)null)
		{
			Color val3 = Color.Lerp(Color.white, new Color(1f, 0.87f, 0.88f, 1f), proximity * 0.45f);
			if ((Object)(object)_voiceSource != (Object)null && _voiceSource.isPlaying)
			{
				val3 = Color.Lerp(val3, new Color(1f, 0.96f, 0.8f, 1f), 0.25f);
			}
			_quadMaterial.color = val3;
		}
		if ((Object)(object)_faceMaterial != (Object)null)
		{
			Color val4 = Color.Lerp(Color.white, new Color(1f, 0.96f, 0.93f, 1f), proximity * 0.22f);
			if ((Object)(object)_voiceSource != (Object)null && _voiceSource.isPlaying)
			{
				val4 = Color.Lerp(val4, new Color(1f, 0.98f, 0.88f, 1f), 0.14f);
			}
			_faceMaterial.color = val4;
		}
		if ((Object)(object)_coreMaterial != (Object)null)
		{
			Color val5 = (_coreUsesCustomModel ? new Color(0.95f, 0.79f, 0.71f, 1f) : new Color(0.2f, 0.85f, 1f, 0.96f));
			Color val6 = (_coreUsesCustomModel ? new Color(1f, 0.67f, 0.38f, 1f) : new Color(1f, 0.55f, 0.15f, 0.98f));
			Color val7 = Color.Lerp(val5, val6, proximity * 0.35f);
			if ((Object)(object)_voiceSource != (Object)null && _voiceSource.isPlaying)
			{
				val7 = Color.Lerp(val7, new Color(1f, 0.92f, 0.45f, 1f), _coreUsesCustomModel ? 0.18f : 0.28f);
			}
			_coreMaterial.color = val7;
		}
	}

	private void UpdateAudio(float proximity)
	{
		if (!((Object)(object)_musicSource == (Object)null))
		{
			float num = 1f;
			if ((Object)(object)_voiceSource != (Object)null && _voiceSource.isPlaying)
			{
				num *= 0.9f;
			}
			if ((Object)(object)_impactSource != (Object)null && _impactSource.isPlaying)
			{
				num *= 0.78f;
			}
			_musicSource.volume = Mathf.Lerp(_plugin.MusicVolumeFar.Value, _plugin.MusicVolumeNear.Value, proximity) * num * _trackVolumeMultiplier;
			_musicSource.pitch = Mathf.Lerp(0.98f, 1.06f, proximity);
		}
	}

	private void UpdateAmbientBehavior(float proximity)
	{
		if (_assets == null || _assets.AmbientLines.Count == 0 || _catchSequenceRunning || !_postSongPhaseStarted || (_sharedEncounter && !_controller.HasEncounterAuthority) || Time.time < _nextAmbientTime)
		{
			return;
		}
		if ((Object)(object)_voiceSource != (Object)null && _voiceSource.isPlaying)
		{
			ScheduleNextAmbient(_plugin.AmbientMinDelay.Value * 0.4f, _plugin.AmbientMaxDelay.Value * 0.4f);
			return;
		}
		float num = Mathf.Lerp(0.18f, 0.35f, proximity);
		if (Random.value > num)
		{
			ScheduleNextAmbient();
		}
		else
		{
			TryPlayAmbientRandom(force: false);
		}
	}

	private bool TryPlayAmbientRandom(bool force)
	{
		if (_assets == null || _assets.AmbientLines.Count == 0)
		{
			return false;
		}
		if (!force && Time.time < _nextAmbientTime)
		{
			return false;
		}
		int num = Random.Range(0, _assets.AmbientLines.Count);
		for (int i = 0; i < _assets.AmbientLines.Count; i++)
		{
			AmbientLineDefinition ambientLineDefinition = _assets.AmbientLines[(num + i) % _assets.AmbientLines.Count];
			if (ambientLineDefinition != null && (Object)(object)ambientLineDefinition.Clip != (Object)null && (force || !string.Equals(ambientLineDefinition.Id, _lastAmbientLineId, StringComparison.Ordinal)))
			{
				PlayAmbientLine(ambientLineDefinition);
				if (_sharedEncounter && _controller.HasEncounterAuthority)
				{
					_controller.BroadcastAmbientLine(this, ambientLineDefinition.Id);
				}
				return true;
			}
		}
		return false;
	}

	private void PlayAmbientLine(AmbientLineDefinition line)
	{
		if ((Object)(object)_voiceSource == (Object)null || line == null || (Object)(object)line.Clip == (Object)null)
		{
			ScheduleNextAmbient();
			return;
		}
		_voiceSource.pitch = Random.Range(0.97f, 1.03f);
		_voiceSource.PlayOneShot(line.Clip, line.Volume);
		_lastAmbientLineId = line.Id ?? string.Empty;
		if (!string.IsNullOrWhiteSpace(line.Caption) && Random.value < _plugin.AmbientTextChance.Value)
		{
			_controller.ShowEncounterText(line.Caption);
		}
		TriggerLineFlavor(line.Id);
		ScheduleNextAmbient();
	}

	public void PlaySynchronizedAmbientLine(string lineId)
	{
		if (!string.IsNullOrWhiteSpace(lineId))
		{
			AmbientLineDefinition ambientLineDefinition = FindAmbientLine(lineId);
			if (ambientLineDefinition != null)
			{
				PlayAmbientLine(ambientLineDefinition);
			}
			else
			{
				ScheduleNextAmbient();
			}
		}
	}

	private void PlaySpawnAudioCue(string preferredLineId, bool fallbackOnly)
	{
		if ((Object)(object)_voiceSource == (Object)null)
		{
			return;
		}
		if (!string.IsNullOrWhiteSpace(preferredLineId))
		{
			AmbientLineDefinition ambientLineDefinition = FindAmbientLine(preferredLineId);
			if (ambientLineDefinition != null && (Object)(object)ambientLineDefinition.Clip != (Object)null && !IsBlockedSpawnCue(ambientLineDefinition.Id))
			{
				_voiceSource.pitch = Random.Range(0.98f, 1.02f);
				_voiceSource.PlayOneShot(ambientLineDefinition.Clip, Mathf.Clamp(ambientLineDefinition.Volume * 0.95f, 0.65f, 1f));
				_lastAmbientLineId = ambientLineDefinition.Id ?? string.Empty;
				return;
			}
		}
		if (_assets != null && _assets.AmbientLines != null && _assets.AmbientLines.Count > 0)
		{
			int num = Random.Range(0, _assets.AmbientLines.Count);
			for (int i = 0; i < _assets.AmbientLines.Count; i++)
			{
				AmbientLineDefinition ambientLineDefinition2 = _assets.AmbientLines[(num + i) % _assets.AmbientLines.Count];
				if (ambientLineDefinition2 != null && !((Object)(object)ambientLineDefinition2.Clip == (Object)null) && !IsBlockedSpawnCue(ambientLineDefinition2.Id) && (fallbackOnly || ambientLineDefinition2.Id == null || !ambientLineDefinition2.Id.StartsWith("short_track_", StringComparison.Ordinal)))
				{
					_voiceSource.pitch = Random.Range(0.98f, 1.02f);
					_voiceSource.PlayOneShot(ambientLineDefinition2.Clip, Mathf.Clamp(ambientLineDefinition2.Volume * 0.95f, 0.65f, 1f));
					_lastAmbientLineId = ambientLineDefinition2.Id ?? string.Empty;
					return;
				}
			}
		}
		if (_assets != null && (Object)(object)_assets.HitIntro != (Object)null)
		{
			_impactSource.pitch = Random.Range(0.98f, 1.02f);
			_impactSource.PlayOneShot(_assets.HitIntro, 0.82f);
		}
	}

	private static bool IsBlockedSpawnCue(string lineId)
	{
		if (!string.Equals(lineId, "gravity_falls", StringComparison.Ordinal) && !string.Equals(lineId, "angry_birds", StringComparison.Ordinal))
		{
			return string.Equals(lineId, "boi", StringComparison.Ordinal);
		}
		return true;
	}

	private void TriggerLineFlavor(string lineId)
	{
		if (string.IsNullOrEmpty(lineId) || lineId == null)
		{
			return;
		}
		switch (lineId)
		{
		case "wrong_door":
			_movementPattern = MovementPattern.Retreat;
			_patternStrafe = Random.Range(-1f, 1f);
			_patternForward = -0.85f;
			_nextPatternTime = Time.time + 1.1f;
			_speedBurstEndTime = Time.time + 0.9f;
			break;
		case "woo":
		case "boi":
		case "boss_in_this_gym":
			_movementPattern = MovementPattern.Charge;
			_patternStrafe = Random.Range(-0.35f, 0.35f);
			_patternForward = 0.12f;
			_nextPatternTime = Time.time + 1f;
			_speedBurstEndTime = Time.time + 1f;
			break;
		case "rip_ears":
			_controller.PulseLights(0.2f, _plugin.LightPulseMultiplier.Value + 0.1f);
			if ((Object)(object)_player != (Object)null && IsLocalTarget())
			{
				_player.FlashlightFlicker(0.9f);
			}
			break;
		case "dungeon_master":
		case "deep_dark_fantasies":
		case "gravity_falls":
			_controller.PulseLights(0.3f, _plugin.LightPulseMultiplier.Value + 0.18f);
			break;
		}
	}

	private AmbientLineDefinition FindAmbientLine(string lineId)
	{
		if (_assets == null || _assets.AmbientLines == null || _assets.AmbientLines.Count == 0)
		{
			return null;
		}
		for (int i = 0; i < _assets.AmbientLines.Count; i++)
		{
			AmbientLineDefinition ambientLineDefinition = _assets.AmbientLines[i];
			if (ambientLineDefinition != null && string.Equals(ambientLineDefinition.Id, lineId, StringComparison.Ordinal))
			{
				return ambientLineDefinition;
			}
		}
		return null;
	}

	private void ScheduleNextAmbient()
	{
		ScheduleNextAmbient(_plugin.PostSongPhraseMinDelay.Value, _plugin.PostSongPhraseMaxDelay.Value);
	}

	private void ScheduleNextAmbient(float minDelay, float maxDelay)
	{
		float num = Mathf.Max(0.75f, minDelay);
		float num2 = Mathf.Max(num, maxDelay);
		_nextAmbientTime = Time.time + Random.Range(num, num2);
	}

	private bool TryFunnyReposition(Vector3 playerGround)
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		NavMeshHit val = default(NavMeshHit);
		for (int i = 0; i < 8; i++)
		{
			float num = Random.Range(0f, 360f) * ((float)Math.PI / 180f);
			float num2 = Random.Range(_plugin.StuckRepositionRadius.Value * 0.75f, _plugin.StuckRepositionRadius.Value * 1.15f);
			if (NavMesh.SamplePosition(playerGround + new Vector3(Mathf.Cos(num), 0f, Mathf.Sin(num)) * num2 + Vector3.up * 2f, ref val, 4.5f, -1))
			{
				((Component)this).transform.position = ((NavMeshHit)(ref val)).position;
				_hasPath = false;
				_nextRepathTime = 0f;
				_speedBurstEndTime = Time.time + 1f;
				_nextTransformBroadcastTime = 0f;
				_controller.PulseLights(0.35f, _plugin.LightPulseMultiplier.Value + 0.22f);
				_controller.ShowEncounterText((Random.value < 0.5f) ? "WRONG DOOR" : "GACHI TELEPORT");
				return true;
			}
		}
		return false;
	}

	private bool HasLineOfSight(Vector3 targetPosition)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: 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)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = ((Component)this).transform.position + Vector3.up * Mathf.Max(1.2f, _plugin.SpawnHeightOffset.Value + 0.8f);
		Vector3 val2 = targetPosition + Vector3.up * 0.15f;
		RaycastHit val3 = default(RaycastHit);
		if (!Physics.Linecast(val, val2, ref val3, -5, (QueryTriggerInteraction)1))
		{
			return true;
		}
		if ((Object)(object)((RaycastHit)(ref val3)).transform != (Object)null && (Object)(object)_player != (Object)null)
		{
			if (!((Object)(object)((RaycastHit)(ref val3)).transform == (Object)(object)((Component)_player).transform))
			{
				return ((RaycastHit)(ref val3)).transform.IsChildOf(((Component)_player).transform);
			}
			return true;
		}
		return false;
	}

	public void ApplyConfirmedDamage(int damage)
	{
		if (!_cleanupStarted && damage > 0 && !(Time.time < _nextDamageTime))
		{
			int num = Mathf.Max(0, _currentHealth - damage);
			ApplyReplicatedHealth(num);
			if (_sharedEncounter)
			{
				_controller.BroadcastEncounterHealth(this, num);
			}
			if (num <= 0)
			{
				_controller.RequestEncounterFinish(this, killed: true);
			}
		}
	}

	public void SetTargetActor(int targetActorNumber)
	{
		_targetActorNumber = targetActorNumber;
		RefreshTargetPlayer();
		_hasPath = false;
		_nextRepathTime = 0f;
	}

	public void ApplyReplicatedHealth(int newHealth)
	{
		newHealth = Mathf.Max(0, newHealth);
		if (newHealth == _currentHealth)
		{
			return;
		}
		bool num = newHealth < _currentHealth;
		_currentHealth = newHealth;
		_nextDamageTime = Time.time + _plugin.DamageCooldown.Value;
		if (num)
		{
			_controller.PulseLights(0.18f, _plugin.LightPulseMultiplier.Value + 0.12f);
			if (_currentHealth > 0)
			{
				_controller.ShowEncounterText("GACHI HP " + _currentHealth);
				TriggerEvasiveBurst(allowTeleport: false);
			}
			else
			{
				_controller.ShowEncounterText("GACHI DEFEATED");
			}
		}
	}

	public void ApplyReplicatedTransform(Vector3 newPosition)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		if (_sharedEncounter && (!((Object)(object)_controller != (Object)null) || !_controller.HasEncounterAuthority))
		{
			_replicatedPosition = newPosition;
			_hasReplicatedTransform = true;
		}
	}

	public void HandleNetworkFinish(bool killed)
	{
		if (!_cleanupStarted)
		{
			_cleanupStarted = true;
			_controller.NotifyEncounterFinished(this, killed);
			if ((Object)(object)_musicSource != (Object)null)
			{
				_musicSource.Stop();
			}
			if ((Object)(object)_voiceSource != (Object)null)
			{
				_voiceSource.Stop();
			}
			if ((Object)(object)_impactSource != (Object)null)
			{
				_impactSource.Stop();
			}
			if ((Object)(object)_trackClip != (Object)null)
			{
				Object.Destroy((Object)(object)_trackClip);
			}
			if ((Object)(object)_quadMaterial != (Object)null)
			{
				Object.Destroy((Object)(object)_quadMaterial);
			}
			if ((Object)(object)_coreMaterial != (Object)null)
			{
				Object.Destroy((Object)(object)_coreMaterial);
			}
			if ((Object)(object)_faceMaterial != (Object)null)
			{
				Object.Destroy((Object)(object)_faceMaterial);
			}
			if ((Object)(object)_coreMesh != (Object)null)
			{
				Object.Destroy((Object)(object)_coreMesh);
			}
			if ((Object)(object)_faceTexture != (Object)null)
			{
				Object.Destroy((Object)(object)_faceTexture);
			}
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}
	}

	public void ForceCleanup()
	{
		HandleNetworkFinish(killed: false);
	}

	private void RefreshTargetPlayer()
	{
		PlayerAvatar val = ((_targetActorNumber >= 0) ? _controller.ResolvePlayerAvatar(_targetActorNumber) : null);
		if ((Object)(object)val != (Object)null)
		{
			_player = val;
		}
		else if ((Object)(object)_player == (Object)null)
		{
			_player = _localPlayer;
		}
		_targetTransform = (((Object)(object)_player != (Object)null && (Object)(object)_player.PlayerVisionTarget != (Object)null) ? _player.PlayerVisionTarget.VisionTransform : (((Object)(object)_player != (Object)null) ? ((Component)_player).transform : null));
	}

	private void BeginPostSongChatter()
	{
		if (!_postSongPhaseStarted)
		{
			_postSongPhaseStarted = true;
			_despawnTime = Time.time + Mathf.Max(5f, _plugin.PostSongChatterDuration.Value + _plugin.TrackGraceDuration.Value);
			_controller.ShowEncounterText("ENCORE PHASE");
			ScheduleNextAmbient(0.45f, 1.1f);
			if (!_sharedEncounter || _controller.HasEncounterAuthority)
			{
				TryPlayAmbientRandom(force: true);
			}
		}
	}

	private bool IsLocalTarget()
	{
		if ((Object)(object)_localPlayer != (Object)null && (Object)(object)_localPlayer.photonView != (Object)null)
		{
			return _localPlayer.photonView.OwnerActorNr == _targetActorNumber;
		}
		return false;
	}

	private IEnumerator CatchSequence()
	{
		_catchSequenceRunning = true;
		_nextCatchTime = Time.time + _plugin.CatchCooldown.Value;
		_controller.ShowEncounterText("BEBRA CONTACT");
		_controller.PulseLights(_plugin.LightPulseDuration.Value, _plugin.LightPulseMultiplier.Value + 0.55f);
		bool flag = IsLocalTarget();
		PlayerController val = (flag ? PlayerController.instance : null);
		PlayerVoiceChat val2 = (flag ? PlayerVoiceChat.instance : null);
		if ((Object)(object)_player != (Object)null && flag)
		{
			_player.PlayerGlitchShort();
			_player.FlashlightFlicker(2.4f);
			Vector3 val3;
			if ((Object)(object)_player.tumble != (Object)null)
			{
				val3 = ((Component)_player).transform.position - ((Component)this).transform.position;
				Vector3 val4 = ((Vector3)(ref val3)).normalized;
				if (((Vector3)(ref val4)).sqrMagnitude < 0.001f)
				{
					val4 = -((Component)this).transform.forward;
				}
				_player.tumble.TumbleSet(true, false);
				_player.tumble.TumbleForce(val4 * _plugin.TumbleForce.Value + Vector3.up * _plugin.TumbleUpwardForce.Value);
				_player.tumble.TumbleOverrideTime(_plugin.TumbleDuration.Value);
				_player.tumble.OverrideLookAtCamera(_plugin.GlitchDuration.Value, 18f, 0.7f);
			}
			val3 = ((Component)_player).transform.position - ((Component)this).transform.position;
			Vector3 normalized = ((Vector3)(ref val3)).normalized;
			_player.ForceImpulse(normalized * _plugin.PushbackForce.Value);
		}
		if ((Object)(object)val != (Object)null)
		{
			val.InputDisable(_plugin.InputLockDuration.Value);
			val.OverrideSpeed(_plugin.SlowMultiplier.Value, _plugin.SlowDuration.Value);
			val.OverrideLookSpeed(_plugin.LookSpeedMultiplier.Value, 0.05f, 0.25f, _plugin.SlowDuration.Value);
		}
		if ((Object)(object)val2 != (Object)null)
		{
			val2.OverridePitch(1.4f, 0.05f, 0.2f, _plugin.GlitchDuration.Value, 0.18f, 28f);
			val2.OverrideVolumeStutter(_plugin.GlitchDuration.Value);
			val2.OverrideHearSelf(0f, _plugin.GlitchDuration.Value);
		}
		if (flag)
		{
			TryKnockItemsAway();
		}
		if ((Object)(object)_impactSource != (Object)null && _assets != null)
		{
			if ((Object)(object)_assets.HitIntro != (Object)null)
			{
				_impactSource.PlayOneShot(_assets.HitIntro, 1f);
			}
			yield return (object)new WaitForSeconds(((Object)(object)_assets.HitIntro != (Object)null) ? Mathf.Clamp(_assets.HitIntro.length * 0.92f, 0.35f, 1.35f) : 0.4f);
			_controller.PulseLights(_plugin.LightPulseDuration.Value * 0.5f, _plugin.LightPulseMultiplier.Value + 0.35f);
			if ((Object)(object)_assets.HitFinisher != (Object)null)
			{
				_impactSource.PlayOneShot(_assets.HitFinisher, 1f);
			}
		}
		else
		{
			yield return (object)new WaitForSeconds(0.45f);
		}
		yield return (object)new WaitForSeconds(0.35f);
		TriggerEvasiveBurst(allowTeleport: true);
		_catchSequenceRunning = false;
	}

	private void OnTriggerEnter(Collider other)
	{
		TryTakeImpactDamage(other);
	}

	private void OnTriggerStay(Collider other)
	{
		TryTakeImpactDamage(other);
	}

	private void OnCollisionEnter(Collision collision)
	{
		if (collision != null)
		{
			TryTakeImpactDamage(collision.collider);
		}
	}

	private void OnCollisionStay(Collision collision)
	{
		if (collision != null)
		{
			TryTakeImpactDamage(collision.collider);
		}
	}

	private void TryTakeImpactDamage(Collider other)
	{
		//IL_00b4: 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)
		if (_cleanupStarted || Time.time < _nextDamageTime || (Object)(object)other == (Object)null || other.isTrigger || (Object)(object)((Component)other).transform == (Object)(object)((Component)this).transform || ((Component)other).transform.IsChildOf(((Component)this).transform) || (Object)(object)((Component)other).GetComponentInParent<PlayerAvatar>() != (Object)null)
		{
			return;
		}
		PhysGrabObject componentInParent = ((Component)other).GetComponentInParent<PhysGrabObject>();
		Rigidbody val = null;
		if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.rb != (Object)null)
		{
			val = componentInParent.rb;
		}
		else if ((Object)(object)other.attachedRigidbody != (Object)null)
		{
			val = other.attachedRigidbody;
		}
		if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)_hitboxBody)
		{
			return;
		}
		Vector3 velocity = val.velocity;
		float magnitude = ((Vector3)(ref velocity)).magnitude;
		bool flag = magnitude >= _plugin.DamageImpactSpeed.Value;
		if ((Object)(object)componentInParent != (Object)null)
		{
			flag = flag || componentInParent.lightImpactImpulse || componentInParent.mediumImpactImpulse || componentInParent.heavyImpactImpulse;
		}
		if (flag)
		{
			int damage = 1;
			if (magnitude >= _plugin.DamageImpactSpeed.Value * 1.85f || ((Object)(object)componentInParent != (Object)null && (componentInParent.mediumImpactImpulse || componentInParent.heavyImpactImpulse)))
			{
				damage = 3;
			}
			ApplyDamage(damage);
		}
	}

	private void ApplyDamage(int damage)
	{
		if (_sharedEncounter)
		{
			if (!_controller.HasEncounterAuthority)
			{
				_nextDamageTime = Time.time + _plugin.DamageCooldown.Value;
			}
			_controller.RequestSharedDamage(this, damage);
		}
		else
		{
			ApplyConfirmedDamage(damage);
		}
	}

	private void TriggerEvasiveBurst(bool allowTeleport)
	{
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		_movementPattern = ((Random.value < 0.72f) ? MovementPattern.Flank : MovementPattern.Charge);
		_patternStrafe = ((Random.value < 0.5f) ? (-1f) : 1f);
		_patternForward = Random.Range(-0.24f, 0.18f);
		_evasionDirection = ((Random.value < 0.5f) ? (-1f) : 1f);
		_nextPatternTime = Time.time + Random.Range(0.8f, 1.45f);
		_nextRepathTime = 0f;
		_speedBurstEndTime = Time.time + Random.Range(0.7f, 1.15f);
		if (allowTeleport && (!_sharedEncounter || _controller.HasEncounterAuthority) && Random.value < 0.1f && (Object)(object)_player != (Object)null)
		{
			TryFunnyReposition(((Component)_player).transform.position);
		}
	}

	private void TryKnockItemsAway()
	{
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		Inventory instance = Inventory.instance;
		if ((Object)(object)instance != (Object)null)
		{
			instance.ForceUnequip();
			if (_plugin.DropInventoryOnCatch.Value && (Object)(object)_localPlayer != (Object)null && (Object)(object)_localPlayer.photonView != (Object)null)
			{
				instance.InventoryDropAll(((Component)_localPlayer).transform.position + ((Component)_localPlayer).transform.forward + Vector3.up * 0.4f, _localPlayer.photonView.ViewID);
			}
		}
		PhysGrabber instance2 = PhysGrabber.instance;
		if ((Object)(object)instance2 == (Object)null || !instance2.grabbed)
		{
			return;
		}
		object? obj = ((object)instance2).GetType().GetField("grabbedPhysGrabObject", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(instance2);
		PhysGrabObject val = (PhysGrabObject)((obj is PhysGrabObject) ? obj : null);
		if ((Object)(object)val != (Object)null)
		{
			PhotonView component = ((Component)val).GetComponent<PhotonView>();
			if ((Object)(object)component != (Object)null)
			{
				instance2.ReleaseObject(component.ViewID, 0.5f);
			}
		}
	}

	private static AudioType GuessAudioType(string path)
	{
		string extension = Path.GetExtension(path);
		if (!string.Equals(extension, ".mp3", StringComparison.OrdinalIgnoreCase))
		{
			if (!string.Equals(extension, ".wav", StringComparison.OrdinalIgnoreCase))
			{
				if (!string.Equals(extension, ".ogg", StringComparison.OrdinalIgnoreCase))
				{
					return (AudioType)0;
				}
				return (AudioType)14;
			}
			return (AudioType)20;
		}
		return (AudioType)13;
	}

	private static string ToFileUri(string path)
	{
		return new Uri(path).AbsoluteUri;
	}

	private static Texture2D CreateEmergencyTexture()
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Expected O, but got Unknown
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = new Texture2D(8, 8, (TextureFormat)4, false);
		for (int i = 0; i < ((Texture)val).height; i++)
		{
			for (int j = 0; j < ((Texture)val).width; j++)
			{
				val.SetPixel(j, i, ((j + i) % 2 == 0) ? new Color(1f, 0.75f, 0.22f) : new Color(0.16f, 0.11f, 0.04f));
			}
		}
		val.Apply();
		((Texture)val).wrapMode = (TextureWrapMode)1;
		((Texture)val).filterMode = (FilterMode)0;
		((Object)val).name = "emergency_fallback";
		return val;
	}
}
internal sealed class GachiEncounterController : MonoBehaviour, IOnEventCallback
{
	private struct PendingSpawnState
	{
		public bool Active;

		public int CycleId;

		public int TargetActor;

		public int StartingHealth;

		public string TrackId;

		public string SpawnCueId;

		public Vector3 SpawnPosition;
	}

	private RepoGachiBillboardEncounterPlugin _plugin;

	private float _nextSpawnRollTime = -1f;

	private float _spawnChanceWindowSeconds = -1f;

	private bool _assetsRequested;

	private bool _assetsLoaded;

	private string _lastTrackId = string.Empty;

	private int _cycleCounter;

	private int _activeTargetActor = -1;

	private float _nextRetargetCheckTime;

	private PendingSpawnState _pendingSpawn;

	private EncounterAssetBank _assets;

	private GachiBillboardEnemy _activeEncounter;

	private const byte EventSpawnEncounter = 71;

	private const byte EventHealthSync = 72;

	private const byte EventFinishEncounter = 73;

	private const byte EventRetargetEncounter = 74;

	private const byte EventForceSpawnRequest = 75;

	private const byte EventAmbientLine = 76;

	private const byte EventDamageEncounter = 77;

	private const byte EventTransformSync = 78;

	private const long ShortPhraseFileSizeThresholdBytes = 2000000L;

	internal bool HasEncounterAuthority
	{
		get
		{
			if (PhotonNetwork.InRoom)
			{
				return PhotonNetwork.IsMasterClient;
			}
			return true;
		}
	}

	public void Initialize(RepoGachiBillboardEncounterPlugin plugin)
	{
		_plugin = plugin;
	}

	private void OnEnable()
	{
		SceneManager.sceneLoaded += OnSceneLoaded;
		RegisterNetworkCallbacks();
	}

	private void OnDisable()
	{
		SceneManager.sceneLoaded -= OnSceneLoaded;
		UnregisterNetworkCallbacks();
	}

	private void OnSceneLoaded(Scene _, LoadSceneMode __)
	{
		if ((Object)(object)_activeEncounter != (Object)null)
		{
			_activeEncounter.ForceCleanup();
			_activeEncounter = null;
		}
		ResetAutoSpawnChanceState();
		_lastTrackId = string.Empty;
		_cycleCounter = 0;
		_activeTargetActor = -1;
		_nextRetargetCheckTime = 0f;
		_pendingSpawn = default(PendingSpawnState);
	}

	private void Update()
	{
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_plugin == (Object)null || !_plugin.ModEnabled.Value)
		{
			return;
		}
		if (!IsGameplayReady())
		{
			ResetAutoSpawnChanceState();
			return;
		}
		if (!_assetsRequested)
		{
			_assetsRequested = true;
			((MonoBehaviour)this).StartCoroutine(LoadAssetsCoroutine());
		}
		if (PhotonNetwork.InRoom)
		{
			if (_assetsLoaded && _pendingSpawn.Active)
			{
				TryConsumePendingSpawn();
			}
			HandleSharedUpdate();
			return;
		}
		KeyboardShortcut value = _plugin.ForceSpawnHotkey.Value;
		if (((KeyboardShortcut)(ref value)).IsDown())
		{
			SpawnEncounter(shared: false, forced: true);
		}
		if (!((Object)(object)_activeEncounter != (Object)null) && _assetsLoaded && ShouldTriggerAutomaticSpawnChance())
		{
			SpawnEncounter(shared: false, forced: false);
		}
	}

	private bool IsGameplayReady()
	{
		if ((Object)(object)PlayerController.instance == (Object)null || (Object)(object)PlayerAvatar.instance == (Object)null || (Object)(object)Camera.main == (Object)null)
		{
			return false;
		}
		if (SemiFunc.IsMainMenu() || SemiFunc.MenuLevel() || !SemiFunc.LevelGenDone())
		{
			return false;
		}
		return true;
	}

	private IEnumerator LoadAssetsCoroutine()
	{
		yield return null;
		_assets = new EncounterAssetBank();
		_assets.PortraitTexture = LoadPortraitTexture(FindPortraitPath(_plugin.PortraitPath.Value)) ?? CreateFallbackTexture();
		yield return LoadAudioClipCoroutine(Path.Combine(GetAssetsDirectory(), "hit_ahhhh.mp3"), "hit intro", delegate(AudioClip clip)
		{
			_assets.HitIntro = clip;
		});
		yield return LoadAudioClipCoroutine(Path.Combine(GetAssetsDirectory(), "hit_fuckyou.mp3"), "hit finisher", delegate(AudioClip clip)
		{
			_assets.HitFinisher = clip;
		});
		List<EncounterTrackDefinition> list = BuildTrackList();
		for (int j = 0; j < list.Count; j++)
		{
			_assets.Tracks.Add(list[j]);
		}
		List<AmbientLineDefinition> ambientLines = BuildAmbientLines(list);
		for (int i = 0; i < ambientLines.Count; i++)
		{
			AmbientLineDefinition ambient = ambientLines[i];
			string path = ((!string.IsNullOrWhiteSpace(ambient.SourcePath)) ? ambient.SourcePath : Path.Combine(GetAssetsDirectory(), ambient.FileName));
			yield return LoadAudioClipCoroutine(path, ambient.Id, delegate(AudioClip clip)
			{
				ambient.Clip = clip;
				if ((Object)(object)clip != (Object)null)
				{
					_assets.AmbientLines.Add(ambient);
				}
			});
		}
		_assetsLoaded = true;
		_plugin.LogSource.LogInfo((object)string.Format("Assets ready. Portrait={0}, Tracks={1}, AmbientClips={2}", ((Object)(object)_assets.PortraitTexture != (Object)null) ? ((Object)_assets.PortraitTexture).name : "fallback", _assets.Tracks.Count, _assets.AmbientLines.Count));
	}

	private IEnumerator LoadAudioClipCoroutine(string path, string friendlyName, Action<AudioClip> assign)
	{
		if (assign == null)
		{
			yield break;
		}
		if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
		{
			_plugin.LogSource.LogWarning((object)("Audio file not found for " + friendlyName + ": " + path));
			assign(null);
			yield break;
		}
		UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(ToFileUri(path), GuessAudioType(path));
		try
		{
			yield return request.SendWebRequest();
			if ((int)request.result == 1)
			{
				AudioClip content = DownloadHandlerAudioClip.GetContent(request);
				((Object)content).name = Path.GetFileNameWithoutExtension(path);
				assign(content);
			}
			else
			{
				_plugin.LogSource.LogWarning((object)("Failed to load " + friendlyName + ": " + request.error));
				assign(null);
			}
		}
		finally
		{
			((IDisposable)request)?.Dispose();
		}
	}

	private void SpawnEncounter(bool shared, bool forced)
	{
		//IL_0057: 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)
		if (TryBuildSpawnState(shared, out var selectedTrack, out var targetAvatar, out var targetActor, out var spawnPosition))
		{
			if (shared)
			{
				_cycleCounter++;
				BroadcastEncounterSpawn(_cycleCounter, targetActor, (selectedTrack != null) ? selectedTrack.Id : string.Empty, spawnPosition, _plugin.MonsterHealth.Value);
			}
			else
			{
				SpawnEncounterInstance(0, targetActor, selectedTrack, spawnPosition, _plugin.MonsterHealth.Value);
			}
			PulseLights(_plugin.LightPulseDuration.Value * 0.55f, _plugin.LightPulseMultiplier.Value);
			string text = ((selectedTrack != null && !string.IsNullOrWhiteSpace(selectedTrack.Caption)) ? ("TRACK: " + selectedTrack.Caption) : "GACHI APPROACHING");
			string avatarDisplayName = GetAvatarDisplayName(targetAvatar);
			if (!string.IsNullOrWhiteSpace(avatarDisplayName))
			{
				text = text + " | TARGET: " + avatarDisplayName;
			}
			if (forced)
			{
				text = "TEST " + text;
			}
			ShowEncounterText(text);
		}
	}

	internal void NotifyEncounterFinished(GachiBillboardEnemy encounter, bool killed)
	{
		if (!((Object)(object)_activeEncounter != (Object)(object)encounter))
		{
			_activeEncounter = null;
			_activeTargetActor = -1;
			if (killed && _plugin.SuppressRespawnsAfterKill.Value)
			{
				ShowEncounterText("GACHI DOWN. ROUND SAFE.");
				DisableAutoSpawns();
			}
			else
			{
				ArmNextSpawnChanceWindow(_plugin.SpawnIntervalSeconds.Value);
			}
		}
	}

	internal void PulseLights(float duration, float multiplier)
	{
		((MonoBehaviour)this).StartCoroutine(PulseLightsCoroutine(duration, multiplier));
	}

	internal void ShowEncounterText(string text)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)MissionUI.instance != (Object)null)
		{
			MissionUI.instance.MissionText(text, new Color(1f, 0.72f, 0.16f), Color.white, 1.25f);
		}
	}

	private IEnumerator PulseLightsCoroutine(float duration, float multiplier)
	{
		Light[] array = Object.FindObjectsOfType<Light>();
		Dictionary<Light, float> originals = new Dictionary<Light, float>();
		foreach (Light val in array)
		{
			if ((Object)(object)val != (Object)null)
			{
				originals[val] = val.intensity;
			}
		}
		float elapsed = 0f;
		while (elapsed < duration)
		{
			elapsed += Time.deltaTime;
			float num = 0.5f + Mathf.Sin(elapsed * 24f) * 0.5f;
			float num2 = Mathf.Lerp(1f, multiplier, num);
			foreach (KeyValuePair<Light, float> item in originals)
			{
				if ((Object)(object)item.Key != (Object)null)
				{
					item.Key.intensity = item.Value * num2;
				}
			}
			yield return null;
		}
		foreach (KeyValuePair<Light, float> item2 in originals)
		{
			if ((Object)(object)item2.Key != (Object)null)
			{
				item2.Key.intensity = item2.Value;
			}
		}
	}

	private Texture2D LoadPortraitTexture(string portraitPath)
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Expected O, but got Unknown
		if (string.IsNullOrWhiteSpace(por