Decompiled source of Hoardgoblin v0.1.0

Hoardgoblin.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json.Linq;
using UnityEngine;
using UnityEngine.Rendering;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MyMods
{
	public static class HallClient
	{
		private struct Pending
		{
			public string Id;

			public string Title;

			public int Order;

			public Action<Rect> Draw;
		}

		private static readonly List<Pending> s_pending = new List<Pending>();

		private static Type s_type;

		private static bool s_miss;

		private static MethodInfo s_register;

		private static MethodInfo s_open;

		private static MethodInfo s_close;

		private static MethodInfo s_hosting;

		private static MethodInfo s_yield;

		private static MethodInfo s_hold;

		private static PropertyInfo s_ready;

		private static PropertyInfo s_openProp;

		private static Type HallType
		{
			get
			{
				if (s_type != null || s_miss)
				{
					return s_type;
				}
				s_type = Type.GetType("DFGHub.HallBoard, DFGHub");
				s_miss = s_type == null;
				return s_type;
			}
		}

		public static bool Ready
		{
			get
			{
				if (s_ready == null && HallType != null)
				{
					s_ready = HallType.GetProperty("Ready", BindingFlags.Static | BindingFlags.Public);
				}
				if (s_ready == null)
				{
					return false;
				}
				object value = s_ready.GetValue(null, null);
				bool flag = default(bool);
				int num;
				if (value is bool)
				{
					flag = (bool)value;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
		}

		public static bool IsOpen
		{
			get
			{
				if (s_openProp == null && HallType != null)
				{
					s_openProp = HallType.GetProperty("IsOpen", BindingFlags.Static | BindingFlags.Public);
				}
				if (s_openProp == null)
				{
					return false;
				}
				object value = s_openProp.GetValue(null, null);
				bool flag = default(bool);
				int num;
				if (value is bool)
				{
					flag = (bool)value;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
		}

		public static void Bind(string id, string title, int order, Action<Rect> draw)
		{
			if (string.IsNullOrEmpty(id) || draw == null)
			{
				return;
			}
			for (int num = s_pending.Count - 1; num >= 0; num--)
			{
				if (string.Equals(s_pending[num].Id, id, StringComparison.OrdinalIgnoreCase))
				{
					s_pending.RemoveAt(num);
				}
			}
			s_pending.Add(new Pending
			{
				Id = id,
				Title = title,
				Order = order,
				Draw = draw
			});
			Flush();
		}

		public static void Flush()
		{
			if (s_pending.Count != 0 && Ready)
			{
				for (int i = 0; i < s_pending.Count; i++)
				{
					Pending pending = s_pending[i];
					TryRegister(pending.Id, pending.Title, pending.Order, pending.Draw);
				}
				s_pending.Clear();
			}
		}

		public static bool TryOpen(string tabId)
		{
			if (!Ready)
			{
				return false;
			}
			if (s_open == null)
			{
				s_open = HallType.GetMethod("Open", BindingFlags.Static | BindingFlags.Public);
			}
			if (s_open == null)
			{
				return false;
			}
			try
			{
				object obj = s_open.Invoke(null, new object[1] { tabId });
				bool flag = default(bool);
				int num;
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			catch (Exception)
			{
				return false;
			}
		}

		public static void Close()
		{
			if (HallType == null)
			{
				return;
			}
			if (s_close == null)
			{
				s_close = HallType.GetMethod("Close", BindingFlags.Static | BindingFlags.Public);
			}
			try
			{
				s_close?.Invoke(null, null);
			}
			catch (Exception)
			{
			}
		}

		public static bool IsHosting(string id)
		{
			if (HallType == null || string.IsNullOrEmpty(id))
			{
				return false;
			}
			if (s_hosting == null)
			{
				s_hosting = HallType.GetMethod("IsHosting", BindingFlags.Static | BindingFlags.Public);
			}
			if (s_hosting == null)
			{
				return false;
			}
			try
			{
				object obj = s_hosting.Invoke(null, new object[1] { id });
				bool flag = default(bool);
				int num;
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			catch (Exception)
			{
				return false;
			}
		}

		public static void SetYield(bool yieldScreen)
		{
			if (HallType == null)
			{
				return;
			}
			if (s_yield == null)
			{
				s_yield = HallType.GetMethod("SetYield", BindingFlags.Static | BindingFlags.Public);
			}
			try
			{
				s_yield?.Invoke(null, new object[1] { yieldScreen });
			}
			catch (Exception)
			{
			}
		}

		public static void HoldEscape()
		{
			if (HallType == null)
			{
				return;
			}
			if (s_hold == null)
			{
				s_hold = HallType.GetMethod("HoldEscape", BindingFlags.Static | BindingFlags.Public);
			}
			try
			{
				s_hold?.Invoke(null, null);
			}
			catch (Exception)
			{
			}
		}

		private static void TryRegister(string id, string title, int order, Action<Rect> draw)
		{
			if (s_register == null)
			{
				s_register = HallType.GetMethod("Register", BindingFlags.Static | BindingFlags.Public);
			}
			s_register?.Invoke(null, new object[4] { id, title, order, draw });
		}
	}
}
namespace Hoardgoblin
{
	public class HoardgoblinAnimator : MonoBehaviour
	{
		private const float DefaultFadeSeconds = 0.18f;

		private readonly Dictionary<string, Transform> m_bones = new Dictionary<string, Transform>(StringComparer.OrdinalIgnoreCase);

		private Pose m_current;

		private Pose m_previous;

		private float m_time;

		private float m_previousTime;

		private float m_fade = 1f;

		private float m_fadeDuration = 0.18f;

		private bool m_loop = true;

		private float m_speed = 1f;

		public string CurrentClip
		{
			get
			{
				if (m_current == null)
				{
					return null;
				}
				return m_current.Name;
			}
		}

		public bool IsBusy
		{
			get
			{
				if (m_current != null && !m_loop)
				{
					return m_time < m_current.Length;
				}
				return false;
			}
		}

		public float NormalizedTime
		{
			get
			{
				if (m_current == null || !(m_current.Length > 0.001f))
				{
					return 0f;
				}
				return Mathf.Clamp01(m_time / m_current.Length);
			}
		}

		public void Bind(Transform armature)
		{
			m_bones.Clear();
			if ((Object)(object)armature == (Object)null)
			{
				return;
			}
			foreach (Pose value in HoardgoblinGlb.Poses.Values)
			{
				for (int i = 0; i < value.Tracks.Length; i++)
				{
					string path = value.Tracks[i].Path;
					if (!m_bones.ContainsKey(path))
					{
						Transform val = armature.Find(path);
						if ((Object)(object)val != (Object)null)
						{
							m_bones[path] = val;
						}
					}
				}
			}
			MapBonesRecursive(armature, "");
		}

		private void MapBonesRecursive(Transform current, string parentPath)
		{
			string text = (string.IsNullOrEmpty(parentPath) ? ((Object)current).name : (parentPath + "/" + ((Object)current).name));
			if (!m_bones.ContainsKey(((Object)current).name))
			{
				m_bones[((Object)current).name] = current;
			}
			if (!m_bones.ContainsKey(text))
			{
				m_bones[text] = current;
			}
			for (int i = 0; i < current.childCount; i++)
			{
				MapBonesRecursive(current.GetChild(i), text);
			}
		}

		public bool Play(string clip, bool loop, float speed = 1f, bool restart = false, float fadeSeconds = 0.18f)
		{
			Pose pose = HoardgoblinGlb.Get(clip);
			if (pose == null)
			{
				return false;
			}
			if (pose == m_current && !restart)
			{
				m_loop = loop;
				m_speed = speed;
				return true;
			}
			m_previous = m_current;
			m_previousTime = m_time;
			m_current = pose;
			m_time = 0f;
			m_fadeDuration = Mathf.Max(0.01f, fadeSeconds);
			m_fade = ((m_previous == null) ? 1f : 0f);
			m_loop = loop;
			m_speed = speed;
			return true;
		}

		private void LateUpdate()
		{
			if (m_current != null)
			{
				float deltaTime = Time.deltaTime;
				m_time = Advance(m_time, deltaTime * m_speed, m_current.Length, m_loop);
				if (m_fade < 1f)
				{
					m_fade = Mathf.Min(1f, m_fade + deltaTime / m_fadeDuration);
				}
				if (m_previous != null && m_fade < 1f)
				{
					m_previousTime = Advance(m_previousTime, deltaTime, m_previous.Length, loop: true);
					Track(m_previous, m_previousTime, 1f);
					Track(m_current, m_time, m_fade);
				}
				else
				{
					Track(m_current, m_time, 1f);
				}
			}
		}

		private void Track(Pose pose, float time, float weight)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			Pose.Track[] tracks = pose.Tracks;
			foreach (Pose.Track track in tracks)
			{
				if (!m_bones.TryGetValue(track.Path, out var value) || (Object)(object)value == (Object)null)
				{
					int num = track.Path.LastIndexOf('/');
					string key = ((num >= 0) ? track.Path.Substring(num + 1) : track.Path);
					if (!m_bones.TryGetValue(key, out value) || (Object)(object)value == (Object)null)
					{
						continue;
					}
				}
				if (track.SampleRotation(time, out var value2))
				{
					value.localRotation = ((weight >= 1f) ? value2 : Quaternion.Slerp(value.localRotation, value2, weight));
				}
				if (track.SamplePosition(time, out var value3))
				{
					value.localPosition = ((weight >= 1f) ? value3 : Vector3.Lerp(value.localPosition, value3, weight));
				}
				if (track.SampleScale(time, out var value4))
				{
					value.localScale = ((weight >= 1f) ? value4 : Vector3.Lerp(value.localScale, value4, weight));
				}
			}
		}

		private static float Advance(float time, float dt, float length, bool loop)
		{
			if (length <= 0.0001f)
			{
				return 0f;
			}
			time += dt;
			if (time < length)
			{
				return time;
			}
			if (!loop)
			{
				return length;
			}
			return time % length;
		}
	}
	public class HoardgoblinController : MonoBehaviour
	{
		public const string PrefabName = "DFG_Hoardgoblin";

		private static int s_obstacleMask;

		private Character m_character;

		private ZNetView m_nview;

		private AnimalAI m_animalAI;

		private BaseAI m_baseAI;

		private Transform m_model;

		private HoardgoblinAnimator m_anim;

		private float m_trailTimer;

		private float m_chaseTimer;

		private bool m_isChannelingEscape;

		private float m_escapeChannelTimer;

		private GameObject m_portalEffectInstance;

		private bool m_isDead;

		private float m_deathTimer;

		private float m_panicTimer;

		private float m_lastHealth;

		private Vector3 m_lastStuckPos;

		private float m_stuckCheckTimer;

		private float m_jumpCooldown;

		private void Awake()
		{
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			if (s_obstacleMask == 0)
			{
				s_obstacleMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "terrain" });
				if (s_obstacleMask == 0)
				{
					s_obstacleMask = -1;
				}
			}
			m_character = ((Component)this).GetComponent<Character>();
			m_nview = ((Component)this).GetComponent<ZNetView>();
			m_animalAI = ((Component)this).GetComponent<AnimalAI>();
			m_baseAI = ((Component)this).GetComponent<BaseAI>();
			if ((Object)(object)m_character != (Object)null)
			{
				m_character.m_speed = HoardgoblinSettings.WalkSpeed.Value;
				m_character.m_runSpeed = HoardgoblinSettings.RunSpeed.Value;
				m_character.m_turnSpeed = 450f;
				m_character.m_jumpForce = HoardgoblinSettings.JumpForce.Value;
				m_lastHealth = m_character.GetHealth();
			}
			m_lastStuckPos = ((Component)this).transform.position;
			AttachCustomModel();
			HideVanillaRenderers();
		}

		private void Start()
		{
			if ((Object)(object)m_character != (Object)null)
			{
				m_lastHealth = m_character.GetHealth();
				m_character.m_speed = HoardgoblinSettings.WalkSpeed.Value;
				m_character.m_runSpeed = HoardgoblinSettings.RunSpeed.Value;
			}
		}

		private void AttachCustomModel()
		{
			//IL_003f: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)HoardgoblinGlb.Template == (Object)null)
			{
				HoardgoblinPlugin.Log.LogError((object)"Hoardgoblin: template model is null!");
				return;
			}
			GameObject val = Object.Instantiate<GameObject>(HoardgoblinGlb.Template, ((Component)this).transform);
			((Object)val).name = "Hoardgoblin_Visual";
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = Quaternion.identity;
			val.transform.localScale = Vector3.one * HoardgoblinSettings.ModelScale.Value;
			val.SetActive(true);
			m_model = val.transform;
			m_anim = val.AddComponent<HoardgoblinAnimator>();
			Transform val2 = val.transform.Find("Armature");
			if ((Object)(object)val2 != (Object)null)
			{
				m_anim.Bind(val2);
			}
			else
			{
				m_anim.Bind(val.transform);
			}
			m_anim.Play("walk", loop: true);
		}

		private void HideVanillaRenderers()
		{
			Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!((Object)(object)m_model != (Object)null) || !((Component)val).transform.IsChildOf(m_model))
				{
					val.enabled = false;
				}
			}
			LODGroup[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<LODGroup>(true);
			foreach (LODGroup val2 in componentsInChildren2)
			{
				if (!((Object)(object)m_model != (Object)null) || !((Component)val2).transform.IsChildOf(m_model))
				{
					val2.enabled = false;
				}
			}
			Animator[] componentsInChildren3 = ((Component)this).GetComponentsInChildren<Animator>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				componentsInChildren3[i].cullingMode = (AnimatorCullingMode)0;
			}
		}

		private void Update()
		{
			if ((Object)(object)m_character == (Object)null || (Object)(object)m_anim == (Object)null)
			{
				return;
			}
			if (m_isDead || m_character.IsDead() || m_character.GetHealth() <= 0f)
			{
				HandleDeath();
				return;
			}
			m_character.m_speed = HoardgoblinSettings.RunSpeed.Value;
			m_character.m_walkSpeed = HoardgoblinSettings.WalkSpeed.Value;
			m_character.m_runSpeed = HoardgoblinSettings.RunSpeed.Value;
			m_character.m_acceleration = 35f;
			m_character.m_turnSpeed = 600f;
			m_character.m_runTurnSpeed = 600f;
			float health = m_character.GetHealth();
			if (health < m_lastHealth - 0.1f)
			{
				OnDamaged();
			}
			m_lastHealth = health;
			if (m_panicTimer > 0f)
			{
				m_panicTimer -= Time.deltaTime;
			}
			if (m_jumpCooldown > 0f)
			{
				m_jumpCooldown -= Time.deltaTime;
			}
			if ((Object)(object)m_nview == (Object)null || m_nview.IsOwner())
			{
				TickAI();
			}
			SyncAnimations();
		}

		private void OnDamaged()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			m_panicTimer = 1.5f;
			if (m_isChannelingEscape)
			{
				CancelEscapeChannel("Interrupted by damage!");
			}
			PlayPanicSqueal();
			HoardgoblinLoot.DropTrailPouch(((Component)this).transform.position);
			if ((Object)(object)m_baseAI != (Object)null)
			{
				m_baseAI.Alert();
			}
		}

		private void TickAI()
		{
			//IL_0006: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: 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_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: 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_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: 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_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: 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_0157: 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_0170: Unknown result type (might be due to invalid IL or missing references)
			Player closestPlayer = Player.GetClosestPlayer(((Component)this).transform.position, HoardgoblinSettings.FleeDistance.Value * 1.5f);
			bool flag = (Object)(object)closestPlayer != (Object)null;
			float num = (flag ? Vector3.Distance(((Component)this).transform.position, ((Component)closestPlayer).transform.position) : 999f);
			if (m_isChannelingEscape)
			{
				if ((Object)(object)m_baseAI != (Object)null)
				{
					m_baseAI.StopMoving();
				}
				m_escapeChannelTimer += Time.deltaTime;
				if (m_escapeChannelTimer >= HoardgoblinSettings.EscapeChannelDuration.Value)
				{
					CompleteEscape();
				}
			}
			else if (((flag && num <= HoardgoblinSettings.AlertRange.Value) || m_panicTimer > 0f) && (Object)(object)closestPlayer != (Object)null)
			{
				m_chaseTimer += Time.deltaTime;
				if ((Object)(object)m_baseAI != (Object)null)
				{
					m_baseAI.Alert();
				}
				Vector3 val;
				if ((Object)(object)m_character != (Object)null)
				{
					m_character.SetWalk(false);
					m_character.SetRun(true);
					Vector3 moveDir = m_character.GetMoveDir();
					if (((Vector3)(ref moveDir)).sqrMagnitude < 0.1f)
					{
						val = ((Component)this).transform.position - ((Component)closestPlayer).transform.position;
						Vector3 normalized = ((Vector3)(ref val)).normalized;
						normalized.y = 0f;
						m_character.SetMoveDir(normalized);
					}
				}
				val = ((Component)this).transform.position - ((Component)closestPlayer).transform.position;
				Vector3 normalized2 = ((Vector3)(ref val)).normalized;
				normalized2.y = 0f;
				HandleObstacleJumping(normalized2);
				m_trailTimer += Time.deltaTime;
				if (m_trailTimer >= HoardgoblinSettings.CoinTrailInterval.Value)
				{
					m_trailTimer = 0f;
					HoardgoblinLoot.DropTrailPouch(((Component)this).transform.position);
				}
				if (m_chaseTimer >= HoardgoblinSettings.ChaseTimeBeforeEscape.Value && num >= 14f)
				{
					StartEscapeChannel();
				}
			}
			else
			{
				m_trailTimer = 0f;
				if (m_chaseTimer > 0f)
				{
					m_chaseTimer = Mathf.Max(0f, m_chaseTimer - Time.deltaTime * 0.5f);
				}
			}
		}

		private void HandleObstacleJumping(Vector3 fleeDir)
		{
			//IL_005b: 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_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_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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)
			//IL_00bc: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			if (!HoardgoblinSettings.JumpObstacles.Value || (Object)(object)m_character == (Object)null || !m_character.IsOnGround())
			{
				return;
			}
			m_stuckCheckTimer += Time.deltaTime;
			if (m_stuckCheckTimer >= 1f)
			{
				m_stuckCheckTimer = 0f;
				if (Vector3.Distance(((Component)this).transform.position, m_lastStuckPos) < 0.4f && m_jumpCooldown <= 0f)
				{
					m_character.Jump(false);
					m_jumpCooldown = 3.5f;
					Vector3 val = Vector3.Cross(fleeDir, Vector3.up) * ((Random.value < 0.5f) ? 1f : (-1f));
					Vector3 val2 = fleeDir + val * 1.2f;
					Vector3 normalized = ((Vector3)(ref val2)).normalized;
					m_character.SetMoveDir(normalized);
					m_character.SetLookDir(normalized, 0f);
				}
				m_lastStuckPos = ((Component)this).transform.position;
			}
		}

		private void SyncAnimations()
		{
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: 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_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			if (m_isDead)
			{
				m_anim.Play("defeat_03", loop: false);
				return;
			}
			if (m_isChannelingEscape)
			{
				m_anim.Play("cast_a_spell", loop: true, 1.2f);
				return;
			}
			if (m_character.IsSwimming())
			{
				m_anim.Play("swim", loop: true, 1.2f);
				return;
			}
			if (!m_character.IsOnGround())
			{
				m_anim.Play("dive", loop: true, 1.4f);
				return;
			}
			if (m_panicTimer > 0f)
			{
				m_anim.Play("frightened", loop: true, 1.4f);
				return;
			}
			bool num = (Object)(object)Player.GetClosestPlayer(((Component)this).transform.position, HoardgoblinSettings.AlertRange.Value) != (Object)null || m_panicTimer > 0f;
			Vector3 velocity = m_character.GetVelocity();
			Vector2 val = new Vector2(velocity.x, velocity.z);
			float magnitude = ((Vector2)(ref val)).magnitude;
			if (num || magnitude > 2.5f)
			{
				m_anim.Play("run", loop: true, 1.65f);
			}
			else if (magnitude > 0.2f)
			{
				m_anim.Play("walk", loop: true, 1.2f);
			}
			else
			{
				m_anim.Play("walk", loop: true, 0.4f);
			}
		}

		private void StartEscapeChannel()
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			m_isChannelingEscape = true;
			m_escapeChannelTimer = 0f;
			HoardgoblinPlugin.Log.LogInfo((object)"Hoardgoblin: started escape portal channel!");
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				GameObject val = ZNetScene.instance.GetPrefab("vfx_bifrost") ?? ZNetScene.instance.GetPrefab("vfx_portal_connected") ?? ZNetScene.instance.GetPrefab("vfx_spawn");
				if ((Object)(object)val != (Object)null)
				{
					m_portalEffectInstance = Object.Instantiate<GameObject>(val, ((Component)this).transform.position, Quaternion.identity);
					m_portalEffectInstance.transform.localScale = Vector3.one * 0.6f;
				}
			}
		}

		private void CancelEscapeChannel(string reason)
		{
			if (m_isChannelingEscape)
			{
				m_isChannelingEscape = false;
				m_escapeChannelTimer = 0f;
				m_chaseTimer = 0f;
				if ((Object)(object)m_portalEffectInstance != (Object)null)
				{
					Object.Destroy((Object)(object)m_portalEffectInstance);
					m_portalEffectInstance = null;
				}
				HoardgoblinPlugin.Log.LogInfo((object)("Hoardgoblin: escape canceled (" + reason + ")"));
			}
		}

		private void CompleteEscape()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			m_isChannelingEscape = false;
			if ((Object)(object)m_portalEffectInstance != (Object)null)
			{
				Object.Destroy((Object)(object)m_portalEffectInstance, 2.5f);
			}
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				GameObject val = ZNetScene.instance.GetPrefab("vfx_creature_soared") ?? ZNetScene.instance.GetPrefab("vfx_troll_death");
				if ((Object)(object)val != (Object)null)
				{
					Object.Instantiate<GameObject>(val, ((Component)this).transform.position, Quaternion.identity);
				}
			}
			HoardgoblinPlugin.Log.LogInfo((object)"Hoardgoblin escaped through the rift!");
			if ((Object)(object)m_nview != (Object)null && m_nview.IsValid())
			{
				ZNetScene.instance.Destroy(((Component)this).gameObject);
			}
			else
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private void HandleDeath()
		{
			//IL_0020: 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_0031: 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)
			if (!m_isDead)
			{
				m_isDead = true;
				m_deathTimer = 0f;
				Biome biome = Heightmap.FindBiome(((Component)this).transform.position);
				HoardgoblinLoot.DropJackpot(((Component)this).transform.position, biome);
				m_anim.Play("defeat_03", loop: false, 1f, restart: true);
				if ((Object)(object)m_portalEffectInstance != (Object)null)
				{
					Object.Destroy((Object)(object)m_portalEffectInstance);
				}
			}
			m_deathTimer += Time.deltaTime;
			if (m_deathTimer >= 3f)
			{
				if ((Object)(object)m_nview != (Object)null && m_nview.IsValid())
				{
					ZNetScene.instance.Destroy(((Component)this).gameObject);
				}
				else
				{
					Object.Destroy((Object)(object)((Component)this).gameObject);
				}
			}
		}

		private void PlayPanicSqueal()
		{
			//IL_0031: 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_0044: 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)
			if ((Object)(object)m_character != (Object)null && m_character.m_hitEffects.m_effectPrefabs != null)
			{
				m_character.m_hitEffects.Create(((Component)this).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)m_portalEffectInstance != (Object)null)
			{
				Object.Destroy((Object)(object)m_portalEffectInstance);
			}
		}
	}
	public static class HoardgoblinGlb
	{
		private sealed class Node
		{
			public string Name;

			public int[] Children;

			public Vector3 Translation = Vector3.zero;

			public Quaternion Rotation = Quaternion.identity;

			public Vector3 Scale = Vector3.one;

			public int Mesh = -1;
		}

		private sealed class Doc
		{
			private struct Accessor
			{
				public int Count;

				public int Components;

				public int ComponentSize;

				public int Offset;

				public int Stride;
			}

			public readonly JObject Root;

			public readonly List<Node> Nodes = new List<Node>();

			public readonly int SceneRoot;

			public readonly int[] SkinJoints;

			public readonly int BaseColorImage;

			private readonly Bin m_bin;

			private readonly JArray m_accessors;

			private readonly JArray m_views;

			private readonly JArray m_images;

			public Doc(JObject root, Bin bin)
			{
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Expected O, but got Unknown
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Expected O, but got Unknown
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Expected O, but got Unknown
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0072: Expected O, but got Unknown
				//IL_0085: Unknown result type (might be due to invalid IL or missing references)
				//IL_008f: Expected O, but got Unknown
				//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00eb: Expected O, but got Unknown
				//IL_0165: Unknown result type (might be due to invalid IL or missing references)
				//IL_016b: Expected O, but got Unknown
				//IL_0108: Unknown result type (might be due to invalid IL or missing references)
				//IL_010f: Expected O, but got Unknown
				Root = root;
				m_bin = bin;
				m_accessors = (JArray)root["accessors"];
				m_views = (JArray)root["bufferViews"];
				m_images = (JArray)root["images"];
				JArray val = (JArray)root["nodes"];
				for (int i = 0; i < ((JContainer)val).Count; i++)
				{
					Nodes.Add(ReadNode((JObject)val[i]));
				}
				SceneRoot = (int)root["scenes"][(object)0][(object)"nodes"][(object)0];
				JArray val2 = (JArray)root["skins"];
				if (val2 != null && ((JContainer)val2).Count > 0)
				{
					JArray val3 = (JArray)val2[0][(object)"joints"];
					SkinJoints = new int[((JContainer)val3).Count];
					for (int j = 0; j < ((JContainer)val3).Count; j++)
					{
						SkinJoints[j] = (int)val3[j];
					}
				}
				JToken val4 = ((JToken)root).SelectToken("materials[0].pbrMetallicRoughness.baseColorTexture.index");
				JArray val5 = (JArray)root["textures"];
				if (val4 != null && val5 != null && (int)val4 < ((JContainer)val5).Count && val5[(int)val4][(object)"source"] != null)
				{
					BaseColorImage = (int)val5[(int)val4][(object)"source"];
				}
			}

			public Mesh ReadMesh(int boneCount)
			{
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Expected O, but got Unknown
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_0047: Expected O, but got Unknown
				//IL_00df: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
				//IL_011e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0123: Unknown result type (might be due to invalid IL or missing references)
				//IL_0136: Unknown result type (might be due to invalid IL or missing references)
				//IL_013b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0148: Expected O, but got Unknown
				JObject val = (JObject)Root["meshes"][(object)0][(object)"primitives"][(object)0];
				JObject val2 = (JObject)val["attributes"];
				Vector3[] array = ReadVec3((int)val2["POSITION"]);
				Vector3[] normals = ReadVec3((int)val2["NORMAL"]);
				Vector2[] uv = ReadVec2((int)val2["TEXCOORD_0"]);
				int[] array2 = ReadIndices((int)val["indices"]);
				BoneWeight[] boneWeights = ReadWeights((int)val2["JOINTS_0"], (int)val2["WEIGHTS_0"], boneCount);
				Matrix4x4[] array3 = (Matrix4x4[])(object)new Matrix4x4[boneCount];
				for (int i = 0; i < array3.Length; i++)
				{
					array3[i] = Matrix4x4.identity;
				}
				Color32[] array4 = (Color32[])(object)new Color32[array.Length];
				for (int j = 0; j < array4.Length; j++)
				{
					array4[j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
				}
				Mesh val3 = new Mesh
				{
					name = "Hoardgoblin_Mesh"
				};
				if (array.Length > 65535)
				{
					val3.indexFormat = (IndexFormat)1;
				}
				val3.vertices = array;
				val3.normals = normals;
				val3.uv = uv;
				val3.colors32 = array4;
				val3.boneWeights = boneWeights;
				val3.bindposes = array3;
				int[] array5 = new int[array2.Length * 2];
				Array.Copy(array2, array5, array2.Length);
				for (int k = 0; k < array2.Length; k += 3)
				{
					array5[array2.Length + k] = array2[k];
					array5[array2.Length + k + 1] = array2[k + 2];
					array5[array2.Length + k + 2] = array2[k + 1];
				}
				val3.triangles = array5;
				val3.RecalculateTangents();
				val3.RecalculateBounds();
				return val3;
			}

			public float[] ReadFloats(int accessor)
			{
				Accessor accessor2 = GetAccessor(accessor);
				int num = accessor2.Count * accessor2.Components;
				float[] array = new float[num];
				for (int i = 0; i < num; i++)
				{
					int num2 = i / accessor2.Components;
					int num3 = i % accessor2.Components;
					array[i] = m_bin.Float(accessor2.Offset + num2 * accessor2.Stride + num3 * 4);
				}
				return array;
			}

			public Texture2D ReadImage(int imageIndex, bool linear)
			{
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Expected O, but got Unknown
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				//IL_005e: Expected O, but got Unknown
				//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a8: Expected O, but got Unknown
				if (m_images == null || imageIndex < 0 || imageIndex >= ((JContainer)m_images).Count)
				{
					return null;
				}
				JObject val = (JObject)m_images[imageIndex];
				if (val["bufferView"] == null)
				{
					return null;
				}
				JObject val2 = (JObject)m_views[(int)val["bufferView"]];
				int offset = ((val2["byteOffset"] != null) ? ((int)val2["byteOffset"]) : 0);
				byte[] array = m_bin.Slice(offset, (int)val2["byteLength"]);
				Texture2D val3 = new Texture2D(2, 2, (TextureFormat)4, true, linear);
				if (!ImageConversion.LoadImage(val3, array))
				{
					HoardgoblinPlugin.Log.LogWarning((object)("Hoardgoblin: failed to decode image " + (object)val["name"]));
					Object.Destroy((Object)(object)val3);
					return null;
				}
				((Object)val3).name = ((string)val["name"]) ?? "hoardgoblin_tex";
				((Texture)val3).wrapMode = (TextureWrapMode)1;
				((Texture)val3).anisoLevel = 4;
				return val3;
			}

			private Vector3[] ReadVec3(int accessor)
			{
				//IL_0053: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				Accessor accessor2 = GetAccessor(accessor);
				Vector3[] array = (Vector3[])(object)new Vector3[accessor2.Count];
				for (int i = 0; i < accessor2.Count; i++)
				{
					int num = accessor2.Offset + i * accessor2.Stride;
					array[i] = new Vector3(m_bin.Float(num), m_bin.Float(num + 4), 0f - m_bin.Float(num + 8));
				}
				return array;
			}

			private Vector2[] ReadVec2(int accessor)
			{
				//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)
				Accessor accessor2 = GetAccessor(accessor);
				Vector2[] array = (Vector2[])(object)new Vector2[accessor2.Count];
				for (int i = 0; i < accessor2.Count; i++)
				{
					int num = accessor2.Offset + i * accessor2.Stride;
					array[i] = new Vector2(m_bin.Float(num), 1f - m_bin.Float(num + 4));
				}
				return array;
			}

			private int[] ReadIndices(int accessor)
			{
				Accessor accessor2 = GetAccessor(accessor);
				int[] array = new int[accessor2.Count];
				int componentSize = accessor2.ComponentSize;
				for (int i = 0; i < accessor2.Count; i++)
				{
					int offset = accessor2.Offset + i * componentSize;
					array[i] = componentSize switch
					{
						2 => m_bin.UInt16(offset), 
						4 => (int)m_bin.UInt32(offset), 
						_ => m_bin.Byte(offset), 
					};
				}
				return array;
			}

			private BoneWeight[] ReadWeights(int jointsAccessor, int weightsAccessor, int boneCount)
			{
				//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
				//IL_0139: Unknown result type (might be due to invalid IL or missing references)
				//IL_013b: Unknown result type (might be due to invalid IL or missing references)
				Accessor accessor = GetAccessor(jointsAccessor);
				Accessor accessor2 = GetAccessor(weightsAccessor);
				BoneWeight[] array = (BoneWeight[])(object)new BoneWeight[accessor.Count];
				for (int i = 0; i < accessor.Count; i++)
				{
					int elementOffset = accessor.Offset + i * accessor.Stride;
					int num = accessor2.Offset + i * accessor2.Stride;
					float num2 = m_bin.Float(num);
					float num3 = m_bin.Float(num + 4);
					float num4 = m_bin.Float(num + 8);
					float num5 = m_bin.Float(num + 12);
					float num6 = num2 + num3 + num4 + num5;
					if (num6 > 0.0001f)
					{
						num2 /= num6;
						num3 /= num6;
						num4 /= num6;
						num5 /= num6;
					}
					else
					{
						num2 = 1f;
					}
					int num7 = i;
					BoneWeight val = default(BoneWeight);
					((BoneWeight)(ref val)).boneIndex0 = Joint(accessor, elementOffset, 0, boneCount);
					((BoneWeight)(ref val)).weight0 = num2;
					((BoneWeight)(ref val)).boneIndex1 = Joint(accessor, elementOffset, 1, boneCount);
					((BoneWeight)(ref val)).weight1 = num3;
					((BoneWeight)(ref val)).boneIndex2 = Joint(accessor, elementOffset, 2, boneCount);
					((BoneWeight)(ref val)).weight2 = num4;
					((BoneWeight)(ref val)).boneIndex3 = Joint(accessor, elementOffset, 3, boneCount);
					((BoneWeight)(ref val)).weight3 = num5;
					array[num7] = val;
				}
				return array;
			}

			private int Joint(Accessor acc, int elementOffset, int component, int boneCount)
			{
				int offset = elementOffset + component * acc.ComponentSize;
				int num = ((acc.ComponentSize == 1) ? m_bin.Byte(offset) : ((acc.ComponentSize == 2) ? m_bin.UInt16(offset) : ((int)m_bin.UInt32(offset))));
				if (num >= 0 && num < boneCount)
				{
					return num;
				}
				return 0;
			}

			private Accessor GetAccessor(int index)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Expected O, but got Unknown
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Expected O, but got Unknown
				JObject val = (JObject)m_accessors[index];
				JObject val2 = (JObject)m_views[(int)val["bufferView"]];
				int num = (int)val["componentType"];
				int num2 = (string)val["type"] switch
				{
					"VEC2" => 2, 
					"VEC3" => 3, 
					"VEC4" => 4, 
					"MAT4" => 16, 
					_ => 1, 
				};
				int num3;
				switch (num)
				{
				default:
					num3 = 1;
					break;
				case 5122:
				case 5123:
					num3 = 2;
					break;
				case 5125:
				case 5126:
					num3 = 4;
					break;
				}
				int num4 = num3;
				int num5 = ((val2["byteOffset"] != null) ? ((int)val2["byteOffset"]) : 0);
				int num6 = ((val["byteOffset"] != null) ? ((int)val["byteOffset"]) : 0);
				int stride = ((val2["byteStride"] != null) ? ((int)val2["byteStride"]) : (num4 * num2));
				return new Accessor
				{
					Count = (int)val["count"],
					Components = num2,
					ComponentSize = num4,
					Offset = num5 + num6,
					Stride = stride
				};
			}

			private static Node ReadNode(JObject n)
			{
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_005d: Expected O, but got Unknown
				//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_00a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ae: Expected O, but got Unknown
				//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
				//IL_0107: Unknown result type (might be due to invalid IL or missing references)
				//IL_010d: Expected O, but got Unknown
				//IL_0135: Unknown result type (might be due to invalid IL or missing references)
				//IL_013a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0157: Unknown result type (might be due to invalid IL or missing references)
				//IL_015e: Expected O, but got Unknown
				Node node = new Node
				{
					Name = (string)n["name"]
				};
				if (n["mesh"] != null)
				{
					node.Mesh = (int)n["mesh"];
				}
				if (n["translation"] != null)
				{
					JArray val = (JArray)n["translation"];
					node.Translation = new Vector3((float)val[0], (float)val[1], 0f - (float)val[2]);
				}
				if (n["rotation"] != null)
				{
					JArray val2 = (JArray)n["rotation"];
					node.Rotation = new Quaternion((float)val2[0], (float)val2[1], 0f - (float)val2[2], 0f - (float)val2[3]);
				}
				if (n["scale"] != null)
				{
					JArray val3 = (JArray)n["scale"];
					node.Scale = new Vector3((float)val3[0], (float)val3[1], (float)val3[2]);
				}
				if (n["children"] != null)
				{
					JArray val4 = (JArray)n["children"];
					node.Children = new int[((JContainer)val4).Count];
					for (int i = 0; i < ((JContainer)val4).Count; i++)
					{
						node.Children[i] = (int)val4[i];
					}
				}
				return node;
			}
		}

		private sealed class Bin
		{
			private readonly byte[] m_file;

			private readonly int m_start;

			public Bin(byte[] file, int start, int length)
			{
				m_file = file;
				m_start = start;
			}

			public float Float(int offset)
			{
				return BitConverter.ToSingle(m_file, m_start + offset);
			}

			public int Byte(int offset)
			{
				return m_file[m_start + offset];
			}

			public int UInt16(int offset)
			{
				return BitConverter.ToUInt16(m_file, m_start + offset);
			}

			public uint UInt32(int offset)
			{
				return BitConverter.ToUInt32(m_file, m_start + offset);
			}

			public byte[] Slice(int offset, int length)
			{
				byte[] array = new byte[length];
				Buffer.BlockCopy(m_file, m_start + offset, array, 0, length);
				return array;
			}
		}

		private const uint GlbMagic = 1179937895u;

		private const int FloatType = 5126;

		private static readonly string[] RootMotionBones = new string[4] { "mixamorig:Hips", "Hips", "pelvis", "root" };

		public static readonly Dictionary<string, Pose> Poses = new Dictionary<string, Pose>(StringComparer.OrdinalIgnoreCase);

		public static GameObject Template { get; private set; }

		public static float RawHeight { get; private set; }

		public static bool Load(string path, Material sourceMaterial, Transform holder)
		{
			if ((Object)(object)Template != (Object)null)
			{
				return true;
			}
			try
			{
				Template = Build(path, sourceMaterial);
				Template.SetActive(false);
				((Object)Template).hideFlags = (HideFlags)61;
				if ((Object)(object)holder != (Object)null)
				{
					Template.transform.SetParent(holder, false);
				}
				return true;
			}
			catch (Exception ex)
			{
				HoardgoblinPlugin.Log.LogError((object)("Hoardgoblin: failed to build the model from " + Path.GetFileName(path) + ": " + ex));
				Template = null;
				return false;
			}
		}

		public static Pose Get(string name)
		{
			if (name == null || !Poses.TryGetValue(name, out var value))
			{
				return null;
			}
			return value;
		}

		private static GameObject Build(string path, Material sourceMaterial)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//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_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			byte[] array = File.ReadAllBytes(path);
			if (array.Length < 20 || BitConverter.ToUInt32(array, 0) != 1179937895)
			{
				throw new InvalidDataException("Not a GLB file: " + path);
			}
			int num = BitConverter.ToInt32(array, 12);
			string text = Encoding.UTF8.GetString(array, 20, num);
			int num2 = 20 + num;
			int length = BitConverter.ToInt32(array, num2);
			int start = num2 + 8;
			JObject obj = JObject.Parse(text);
			Doc doc = new Doc(obj, new Bin(array, start, length));
			GameObject val = new GameObject("Hoardgoblin_Model");
			Dictionary<int, Transform> transforms;
			Dictionary<int, string> paths;
			GameObject obj2 = BuildHierarchy(doc, out transforms, out paths);
			((Object)obj2).name = "Armature";
			obj2.transform.SetParent(val.transform, false);
			obj2.transform.localRotation = Quaternion.Euler(0f, 180f, 0f);
			AttachMesh(material: CreateMaterial(doc, sourceMaterial), doc: doc, transforms: transforms);
			JArray val2 = (JArray)obj["animations"];
			Poses.Clear();
			if (val2 != null)
			{
				for (int i = 0; i < ((JContainer)val2).Count; i++)
				{
					Pose pose = BuildPose(doc, paths, (JObject)val2[i]);
					if (pose != null)
					{
						Poses[pose.Name] = pose;
					}
				}
			}
			SkinnedMeshRenderer componentInChildren = val.GetComponentInChildren<SkinnedMeshRenderer>();
			float rawHeight;
			if (!((Object)(object)componentInChildren != (Object)null) || !((Object)(object)componentInChildren.sharedMesh != (Object)null))
			{
				rawHeight = 1f;
			}
			else
			{
				Bounds bounds = componentInChildren.sharedMesh.bounds;
				rawHeight = ((Bounds)(ref bounds)).size.y;
			}
			RawHeight = rawHeight;
			HoardgoblinPlugin.Log.LogInfo((object)string.Format("Hoardgoblin: built model from {0} ({1:0.00} m in the file), {2} clips: {3}.", Path.GetFileName(path), RawHeight, Poses.Count, string.Join(", ", Poses.Keys)));
			return val;
		}

		private static GameObject BuildHierarchy(Doc doc, out Dictionary<int, Transform> transforms, out Dictionary<int, string> paths)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_0064: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			int count = doc.Nodes.Count;
			GameObject[] array = (GameObject[])(object)new GameObject[count];
			transforms = new Dictionary<int, Transform>(count);
			for (int i = 0; i < count; i++)
			{
				Node node = doc.Nodes[i];
				GameObject val = new GameObject(string.IsNullOrEmpty(node.Name) ? ("node" + i) : node.Name);
				val.transform.localPosition = node.Translation;
				val.transform.localRotation = node.Rotation;
				val.transform.localScale = node.Scale;
				array[i] = val;
				transforms[i] = val.transform;
			}
			for (int j = 0; j < count; j++)
			{
				int[] children = doc.Nodes[j].Children;
				if (children != null)
				{
					for (int k = 0; k < children.Length; k++)
					{
						array[children[k]].transform.SetParent(array[j].transform, false);
					}
				}
			}
			paths = new Dictionary<int, string>();
			WritePaths(doc, doc.SceneRoot, "", paths);
			return array[doc.SceneRoot];
		}

		private static void WritePaths(Doc doc, int index, string path, Dictionary<int, string> paths)
		{
			paths[index] = path;
			int[] children = doc.Nodes[index].Children;
			if (children == null)
			{
				return;
			}
			for (int i = 0; i < children.Length; i++)
			{
				int index2 = children[i];
				string text = doc.Nodes[index2].Name;
				if (string.IsNullOrEmpty(text))
				{
					text = "node" + index2;
				}
				WritePaths(doc, index2, string.IsNullOrEmpty(path) ? text : (path + "/" + text), paths);
			}
		}

		private static void AttachMesh(Doc doc, Dictionary<int, Transform> transforms, Material material)
		{
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: 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_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			int num = -1;
			for (int i = 0; i < doc.Nodes.Count; i++)
			{
				if (doc.Nodes[i].Mesh >= 0)
				{
					num = i;
					break;
				}
			}
			if (num < 0 || doc.SkinJoints == null)
			{
				throw new InvalidDataException("GLB has no skinned mesh.");
			}
			int[] skinJoints = doc.SkinJoints;
			Transform[] array = (Transform[])(object)new Transform[skinJoints.Length];
			for (int j = 0; j < skinJoints.Length; j++)
			{
				array[j] = transforms[skinJoints[j]];
			}
			Mesh val = doc.ReadMesh(array.Length);
			SkinnedMeshRenderer val2 = ((Component)transforms[num]).gameObject.AddComponent<SkinnedMeshRenderer>();
			val2.sharedMesh = val;
			val2.bones = array;
			val2.rootBone = ((array.Length != 0) ? array[0] : null);
			((Renderer)val2).sharedMaterial = material;
			val2.updateWhenOffscreen = false;
			val2.quality = (SkinQuality)4;
			Matrix4x4[] array2 = (Matrix4x4[])(object)new Matrix4x4[array.Length];
			Matrix4x4 localToWorldMatrix = ((Component)val2).transform.localToWorldMatrix;
			for (int k = 0; k < array.Length; k++)
			{
				array2[k] = (((Object)(object)array[k] == (Object)null) ? Matrix4x4.identity : (array[k].worldToLocalMatrix * localToWorldMatrix));
			}
			val.bindposes = array2;
			Bounds bounds = val.bounds;
			((Bounds)(ref bounds)).Expand(new Vector3(1.5f, 0.6f, 1.5f));
			((Renderer)val2).localBounds = bounds;
		}

		private static Material CreateMaterial(Doc doc, Material sourceMaterial)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_002f: 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_0092: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = doc.ReadImage(doc.BaseColorImage, linear: false);
			Material val2 = (((Object)(object)sourceMaterial != (Object)null) ? new Material(sourceMaterial) : new Material(Shader.Find("Custom/Creature") ?? Shader.Find("Standard")));
			((Object)val2).name = "Hoardgoblin_Mat";
			if ((Object)(object)val != (Object)null)
			{
				val2.mainTexture = (Texture)(object)val;
				SetTex(val2, "_MainTex", (Texture)(object)val);
				SetTex(val2, "_BaseMap", (Texture)(object)val);
				SetTex(val2, "_Albedo", (Texture)(object)val);
				val2.SetTextureScale("_MainTex", Vector2.one);
				val2.SetTextureOffset("_MainTex", Vector2.zero);
			}
			SetTex(val2, "_BumpMap", null);
			SetTex(val2, "_EmissionMap", null);
			if (val2.HasProperty("_EmissionColor"))
			{
				val2.SetColor("_EmissionColor", Color.black);
			}
			val2.DisableKeyword("_EMISSION");
			if (val2.HasProperty("_Color"))
			{
				val2.SetColor("_Color", Color.white);
			}
			if (val2.HasProperty("_BaseColor"))
			{
				val2.SetColor("_BaseColor", Color.white);
			}
			if (val2.HasProperty("_Mode"))
			{
				val2.SetFloat("_Mode", 0f);
			}
			if (val2.HasProperty("_Cutoff"))
			{
				val2.SetFloat("_Cutoff", 0f);
			}
			val2.DisableKeyword("_ALPHATEST_ON");
			val2.DisableKeyword("_ALPHABLEND_ON");
			val2.DisableKeyword("_ALPHAPREMULTIPLY_ON");
			val2.renderQueue = 2000;
			HoardgoblinPlugin.Log.LogInfo((object)string.Format("Hoardgoblin: material cloned from '{0}', shader '{1}', albedo {2}.", ((Object)(object)sourceMaterial != (Object)null) ? ((Object)sourceMaterial).name : "none", ((Object)(object)val2.shader != (Object)null) ? ((Object)val2.shader).name : "none", ((Object)(object)val != (Object)null) ? (((Texture)val).width + "x" + ((Texture)val).height) : "missing"));
			return val2;
		}

		private static void SetTex(Material mat, string prop, Texture tex)
		{
			if (mat.HasProperty(prop))
			{
				mat.SetTexture(prop, tex);
			}
		}

		private static Pose BuildPose(Doc doc, Dictionary<int, string> paths, JObject anim)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: 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_0276: Unknown result type (might be due to invalid IL or missing references)
			string text = (string)anim["name"];
			if (string.IsNullOrEmpty(text))
			{
				return null;
			}
			Dictionary<string, Pose.Track> dictionary = new Dictionary<string, Pose.Track>();
			float num = 0f;
			float travel = 0f;
			JArray val = (JArray)anim["channels"];
			JArray val2 = (JArray)anim["samplers"];
			for (int i = 0; i < ((JContainer)val).Count; i++)
			{
				JObject val3 = (JObject)val[i];
				JObject val4 = (JObject)val2[(int)val3["sampler"]];
				int key = (int)val3["target"][(object)"node"];
				string text2 = (string)val3["target"][(object)"path"];
				if (!paths.TryGetValue(key, out var value) || string.IsNullOrEmpty(value))
				{
					continue;
				}
				bool flag = string.Equals((string)val4["interpolation"], "STEP", StringComparison.OrdinalIgnoreCase);
				float[] array = doc.ReadFloats((int)val4["input"]);
				float[] array2 = doc.ReadFloats((int)val4["output"]);
				if (array.Length != 0 && array[^1] > num)
				{
					num = array[^1];
				}
				if (!dictionary.TryGetValue(value, out var value2))
				{
					Pose.Track obj = new Pose.Track
					{
						Path = value
					};
					value2 = (dictionary[value] = obj);
				}
				switch (text2)
				{
				case "rotation":
				{
					Quaternion[] array5 = (Quaternion[])(object)new Quaternion[array.Length];
					for (int m = 0; m < array.Length; m++)
					{
						array5[m] = new Quaternion(array2[m * 4], array2[m * 4 + 1], 0f - array2[m * 4 + 2], 0f - array2[m * 4 + 3]);
					}
					value2.RotTimes = array;
					value2.Rotations = array5;
					value2.RotationStep = flag;
					break;
				}
				case "translation":
				{
					bool flag2 = IsRootMotionBone(value);
					Vector3[] array4 = (Vector3[])(object)new Vector3[array.Length];
					for (int k = 0; k < array.Length; k++)
					{
						array4[k] = new Vector3(array2[k * 3], array2[k * 3 + 1], 0f - array2[k * 3 + 2]);
					}
					if (flag2 && array.Length > 1)
					{
						Vector3 val5 = array4[array.Length - 1] - array4[0];
						val5.y = 0f;
						float num2 = array[^1] - array[0];
						travel = ((num2 > 0.0001f) ? (((Vector3)(ref val5)).magnitude / num2) : 0f);
						for (int l = 1; l < array.Length; l++)
						{
							array4[l].x = array4[0].x;
							array4[l].z = array4[0].z;
						}
					}
					value2.PosTimes = array;
					value2.Positions = array4;
					value2.PositionStep = flag;
					break;
				}
				case "scale":
				{
					Vector3[] array3 = (Vector3[])(object)new Vector3[array.Length];
					for (int j = 0; j < array.Length; j++)
					{
						array3[j] = new Vector3(array2[j * 3], array2[j * 3 + 1], array2[j * 3 + 2]);
					}
					value2.ScaleTimes = array;
					value2.Scales = array3;
					value2.ScaleStep = flag;
					break;
				}
				}
			}
			Pose pose = new Pose
			{
				Name = text,
				Length = num,
				Travel = travel,
				Tracks = new Pose.Track[dictionary.Count]
			};
			dictionary.Values.CopyTo(pose.Tracks, 0);
			return pose;
		}

		private static bool IsRootMotionBone(string path)
		{
			int num = path.LastIndexOf('/');
			string value = ((num >= 0) ? path.Substring(num + 1) : path);
			return Array.IndexOf(RootMotionBones, value) >= 0;
		}
	}
	public sealed class Pose
	{
		public sealed class Track
		{
			public string Path;

			public float[] PosTimes;

			public Vector3[] Positions;

			public bool PositionStep;

			public float[] RotTimes;

			public Quaternion[] Rotations;

			public bool RotationStep;

			public float[] ScaleTimes;

			public Vector3[] Scales;

			public bool ScaleStep;

			public bool SamplePosition(float time, out Vector3 value)
			{
				return Sample(PosTimes, Positions, PositionStep, time, out value);
			}

			public bool SampleScale(float time, out Vector3 value)
			{
				return Sample(ScaleTimes, Scales, ScaleStep, time, out value);
			}

			public bool SampleRotation(float time, out Quaternion value)
			{
				//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_0050: 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_0064: 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_0084: Unknown result type (might be due to invalid IL or missing references)
				//IL_0089: Unknown result type (might be due to invalid IL or missing references)
				value = Quaternion.identity;
				if (RotTimes == null || Rotations == null || RotTimes.Length == 0)
				{
					return false;
				}
				int num = Index(RotTimes, time);
				if (RotationStep || num + 1 >= RotTimes.Length)
				{
					value = Rotations[num];
					return true;
				}
				value = Quaternion.Slerp(Rotations[num], Rotations[num + 1], Blend(RotTimes, num, time));
				return true;
			}

			private static bool Sample(float[] times, Vector3[] values, bool step, float time, out Vector3 value)
			{
				//IL_0002: 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_0030: 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_0044: 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)
				//IL_0056: Unknown result type (might be due to invalid IL or missing references)
				value = default(Vector3);
				if (times == null || values == null || times.Length == 0)
				{
					return false;
				}
				int num = Index(times, time);
				if (step || num + 1 >= times.Length)
				{
					value = values[num];
					return true;
				}
				value = Vector3.Lerp(values[num], values[num + 1], Blend(times, num, time));
				return true;
			}

			private static int Index(float[] times, float time)
			{
				int num = 0;
				int num2 = times.Length - 1;
				if (time <= times[0])
				{
					return 0;
				}
				if (time >= times[num2])
				{
					return num2;
				}
				while (num2 - num > 1)
				{
					int num3 = num + num2 >> 1;
					if (times[num3] <= time)
					{
						num = num3;
					}
					else
					{
						num2 = num3;
					}
				}
				return num;
			}

			private static float Blend(float[] times, int i, float time)
			{
				float num = times[i + 1] - times[i];
				if (!(num <= 1E-05f))
				{
					return Mathf.Clamp01((time - times[i]) / num);
				}
				return 0f;
			}
		}

		public string Name;

		public float Length;

		public float Travel;

		public Track[] Tracks;
	}
	public static class HoardgoblinLoot
	{
		private static readonly string[] TrailGems = new string[3] { "Amber", "Ruby", "AmberPearl" };

		private static readonly string[] Valuables = new string[4] { "Amber", "AmberPearl", "Ruby", "SilverNecklace" };

		public static void DropTrailPouch(Vector3 position)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_0031: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_0070: 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)
			try
			{
				int amount = Random.Range(HoardgoblinSettings.CoinTrailMin.Value, HoardgoblinSettings.CoinTrailMax.Value + 1);
				DropItemPrefab("Coins", position + Vector3.up * 0.4f, amount, 1.8f);
				if (Random.value < HoardgoblinSettings.TrailGemChance.Value)
				{
					DropItemPrefab(TrailGems[Random.Range(0, TrailGems.Length)], position + Vector3.up * 0.5f, 1, 2.2f);
				}
				SpawnCoinSparkle(position + Vector3.up * 0.3f);
			}
			catch (Exception ex)
			{
				HoardgoblinPlugin.Log.LogWarning((object)("Hoardgoblin: trail drop failed: " + ex.Message));
			}
		}

		public static void DropJackpot(Vector3 position, Biome biome)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_00bc: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: 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_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				int num = Random.Range(HoardgoblinSettings.JackpotCoinMin.Value, HoardgoblinSettings.JackpotCoinMax.Value + 1);
				while (num > 0)
				{
					int num2 = Mathf.Min(num, Random.Range(20, 60));
					num -= num2;
					Vector3 val = Random.insideUnitSphere * 1.5f;
					val.y = Mathf.Abs(val.y) + 0.3f;
					DropItemPrefab("Coins", position + val, num2, 3.5f);
				}
				int num3 = Random.Range(HoardgoblinSettings.JackpotGemsMin.Value, HoardgoblinSettings.JackpotGemsMax.Value + 1);
				for (int i = 0; i < num3; i++)
				{
					string prefabName = Valuables[Random.Range(0, Valuables.Length)];
					int amount = Random.Range(1, 3);
					Vector3 val2 = Random.insideUnitSphere * 1.8f;
					val2.y = Mathf.Abs(val2.y) + 0.4f;
					DropItemPrefab(prefabName, position + val2, amount, 3.8f);
				}
				if (HoardgoblinSettings.JackpotBonusMaterials.Value)
				{
					DropBiomeMaterials(position, biome);
				}
				SpawnJackpotBurst(position);
			}
			catch (Exception ex)
			{
				HoardgoblinPlugin.Log.LogWarning((object)("Hoardgoblin: jackpot drop failed: " + ex.Message));
			}
		}

		private static void DropBiomeMaterials(Vector3 position, Biome biome)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected I4, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Invalid comparison between Unknown and I4
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Invalid comparison between Unknown and I4
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Invalid comparison between Unknown and I4
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			List<Tuple<string, int>> list = new List<Tuple<string, int>>();
			if ((int)biome <= 8)
			{
				switch (biome - 1)
				{
				case 0:
					goto IL_004b;
				case 1:
					goto IL_00e1;
				case 3:
					goto IL_012d;
				case 2:
					goto IL_0288;
				}
				if ((int)biome != 8)
				{
					goto IL_0288;
				}
				list.Add(Tuple.Create("CopperOre", Random.Range(3, 8)));
				list.Add(Tuple.Create("TinOre", Random.Range(2, 6)));
				list.Add(Tuple.Create("Bronze", Random.Range(1, 4)));
				list.Add(Tuple.Create("SurtlingCore", Random.Range(1, 3)));
			}
			else if ((int)biome != 16)
			{
				if ((int)biome != 32)
				{
					if ((int)biome != 512)
					{
						goto IL_0288;
					}
					list.Add(Tuple.Create("Softtissue", Random.Range(4, 10)));
					list.Add(Tuple.Create("Eitr", Random.Range(2, 5)));
					list.Add(Tuple.Create("BlackMarble", Random.Range(8, 18)));
					list.Add(Tuple.Create("Carapace", Random.Range(4, 10)));
				}
				else
				{
					list.Add(Tuple.Create("FlametalOreNew", Random.Range(4, 10)));
					list.Add(Tuple.Create("CharredBone", Random.Range(4, 10)));
					list.Add(Tuple.Create("MorgenSinew", Random.Range(1, 3)));
				}
			}
			else
			{
				list.Add(Tuple.Create("BlackMetalScrap", Random.Range(5, 12)));
				list.Add(Tuple.Create("Barley", Random.Range(8, 20)));
				list.Add(Tuple.Create("Flax", Random.Range(8, 20)));
				list.Add(Tuple.Create("Needle", Random.Range(4, 10)));
			}
			goto IL_02a4;
			IL_02a4:
			foreach (Tuple<string, int> item in list)
			{
				Vector3 val = Random.insideUnitSphere * 2f;
				val.y = Mathf.Abs(val.y) + 0.5f;
				DropItemPrefab(item.Item1, position + val, item.Item2, 4f);
			}
			return;
			IL_004b:
			list.Add(Tuple.Create("FineWood", Random.Range(5, 12)));
			list.Add(Tuple.Create("Feathers", Random.Range(4, 10)));
			goto IL_02a4;
			IL_012d:
			list.Add(Tuple.Create("SilverOre", Random.Range(4, 10)));
			list.Add(Tuple.Create("Obsidian", Random.Range(6, 15)));
			list.Add(Tuple.Create("FreezeGland", Random.Range(2, 6)));
			goto IL_02a4;
			IL_0288:
			list.Add(Tuple.Create("Coins", Random.Range(50, 150)));
			goto IL_02a4;
			IL_00e1:
			list.Add(Tuple.Create("IronScrap", Random.Range(4, 10)));
			list.Add(Tuple.Create("Chain", Random.Range(1, 3)));
			list.Add(Tuple.Create("AncientBark", Random.Range(6, 14)));
			goto IL_02a4;
		}

		private static void DropItemPrefab(string prefabName, Vector3 spawnPos, int amount, float burstSpeed)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(prefabName) || amount <= 0)
			{
				return;
			}
			GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(prefabName) : null);
			if ((Object)(object)val == (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
			{
				val = ZNetScene.instance.GetPrefab(prefabName);
			}
			if (!((Object)(object)val == (Object)null))
			{
				GameObject obj = Object.Instantiate<GameObject>(val, spawnPos, Quaternion.identity);
				ItemDrop component = obj.GetComponent<ItemDrop>();
				if ((Object)(object)component != (Object)null)
				{
					component.m_itemData.m_stack = amount;
				}
				Rigidbody component2 = obj.GetComponent<Rigidbody>();
				if ((Object)(object)component2 != (Object)null)
				{
					Vector3 val2 = Random.onUnitSphere + Vector3.up * 1.5f;
					Vector3 velocity = ((Vector3)(ref val2)).normalized * Random.Range(burstSpeed * 0.6f, burstSpeed);
					component2.velocity = velocity;
				}
			}
		}

		private static void SpawnCoinSparkle(Vector3 position)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)ZNetScene.instance == (Object)null))
			{
				GameObject prefab = ZNetScene.instance.GetPrefab("vfx_Place_wood_wall");
				if ((Object)(object)prefab != (Object)null)
				{
					Object.Instantiate<GameObject>(prefab, position, Quaternion.identity);
				}
			}
		}

		private static void SpawnJackpotBurst(Vector3 position)
		{
			//IL_0041: 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)
			if (!((Object)(object)ZNetScene.instance == (Object)null))
			{
				GameObject prefab = ZNetScene.instance.GetPrefab("vfx_lootchest_open");
				if ((Object)(object)prefab == (Object)null)
				{
					prefab = ZNetScene.instance.GetPrefab("vfx_troll_death");
				}
				if ((Object)(object)prefab != (Object)null)
				{
					Object.Instantiate<GameObject>(prefab, position, Quaternion.identity);
				}
			}
		}
	}
	[BepInPlugin("com.dfg.hoardgoblin", "Hoardgoblin", "0.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class HoardgoblinPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.dfg.hoardgoblin";

		public const string PluginName = "Hoardgoblin";

		public const string PluginVersion = "0.1.0";

		internal static ManualLogSource Log;

		private Harmony m_harmony;

		internal static HoardgoblinPlugin Instance { get; private set; }

		private void Awake()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			HoardgoblinSettings.Bind(((BaseUnityPlugin)this).Config);
			if (!HoardgoblinSettings.Enabled.Value)
			{
				Log.LogInfo((object)"Hoardgoblin is disabled in config.");
				return;
			}
			HoardgoblinPrefabs.Init();
			try
			{
				m_harmony = new Harmony("com.dfg.hoardgoblin");
				m_harmony.PatchAll();
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Hoardgoblin: failed to apply Harmony patches: " + ex));
			}
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new SpawnHoardgoblinCommand());
			Log.LogInfo((object)"Hoardgoblin v0.1.0 initialized.");
		}

		private void OnDestroy()
		{
			Harmony harmony = m_harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	public class SpawnHoardgoblinCommand : ConsoleCommand
	{
		public override string Name => "spawn_hoardgoblin";

		public override string Help => "Spawns a Hoardgoblin near the player for testing.";

		public unsafe override void Run(string[] args)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				Console.instance.Print("Must be in game to spawn a Hoardgoblin.");
				return;
			}
			GameObject prefab = PrefabManager.Instance.GetPrefab("DFG_Hoardgoblin");
			if ((Object)(object)prefab == (Object)null)
			{
				Console.instance.Print("Hoardgoblin prefab 'DFG_Hoardgoblin' not found.");
				return;
			}
			Vector3 val = ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * 4f + Vector3.up * 0.5f;
			Object.Instantiate<GameObject>(prefab, val, Quaternion.identity);
			Console instance = Console.instance;
			Vector3 val2 = val;
			instance.Print("Spawned Hoardgoblin at " + ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString());
		}
	}
	public static class HoardgoblinPrefabs
	{
		public const string PrefabName = "DFG_Hoardgoblin";

		public const string SourcePrefab = "Goblin";

		public const string ModelFile = "Hoardgoblin.glb";

		public static GameObject HoardgoblinPrefab { get; private set; }

		public static void Init()
		{
			PrefabManager.OnVanillaPrefabsAvailable += Register;
			LocalizationManager.Instance.AddToken("hoardgoblin_name", "Hoardgoblin", false);
			LocalizationManager.Instance.AddToken("hoardgoblin_desc", "A cowardly hoarder weighed down by a massive sack of stolen treasures. Catch it if you can!", false);
		}

		private static void Register()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= Register;
			try
			{
				BuildCreature();
			}
			catch (Exception ex)
			{
				HoardgoblinPlugin.Log.LogError((object)("Hoardgoblin: registration failed: " + ex));
			}
		}

		private static void BuildCreature()
		{
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Expected O, but got Unknown
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Expected O, but got Unknown
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Expected O, but got Unknown
			GameObject prefab = PrefabManager.Instance.GetPrefab("Goblin");
			if ((Object)(object)prefab == (Object)null)
			{
				prefab = PrefabManager.Instance.GetPrefab("Greydwarf");
			}
			if ((Object)(object)prefab == (Object)null)
			{
				HoardgoblinPlugin.Log.LogError((object)"Hoardgoblin: base creature prefab not found!");
				return;
			}
			Material sourceMaterial = null;
			SkinnedMeshRenderer componentInChildren = prefab.GetComponentInChildren<SkinnedMeshRenderer>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				sourceMaterial = ((Renderer)componentInChildren).sharedMaterial;
			}
			string text = Path.Combine(Path.GetDirectoryName(typeof(HoardgoblinPrefabs).Assembly.Location) ?? "", "Hoardgoblin.glb");
			if (!File.Exists(text))
			{
				HoardgoblinPlugin.Log.LogError((object)("Hoardgoblin: Hoardgoblin.glb is missing beside DLL at " + text));
			}
			else
			{
				if (!HoardgoblinGlb.Load(text, sourceMaterial, ((Component)HoardgoblinPlugin.Instance).transform))
				{
					return;
				}
				GameObject val = PrefabManager.Instance.CreateClonedPrefab("DFG_Hoardgoblin", prefab);
				((Object)val).name = "DFG_Hoardgoblin";
				Character component = val.GetComponent<Character>();
				if ((Object)(object)component != (Object)null)
				{
					component.m_name = "$hoardgoblin_name";
					component.m_health = HoardgoblinSettings.BaseHealth.Value;
					component.m_speed = HoardgoblinSettings.RunSpeed.Value;
					component.m_walkSpeed = HoardgoblinSettings.WalkSpeed.Value;
					component.m_runSpeed = HoardgoblinSettings.RunSpeed.Value;
					component.m_acceleration = 25f;
					component.m_turnSpeed = 600f;
					component.m_runTurnSpeed = 600f;
					component.m_jumpForce = HoardgoblinSettings.JumpForce.Value;
					component.m_deathEffects = new EffectList();
				}
				Humanoid component2 = val.GetComponent<Humanoid>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.m_defaultItems = (GameObject[])(object)new GameObject[0];
					component2.m_randomWeapon = (GameObject[])(object)new GameObject[0];
					component2.m_randomArmor = (GameObject[])(object)new GameObject[0];
					component2.m_randomShield = (GameObject[])(object)new GameObject[0];
					component2.m_randomSets = (ItemSet[])(object)new ItemSet[0];
					component2.m_unarmedWeapon = null;
				}
				MonsterAI component3 = val.GetComponent<MonsterAI>();
				if ((Object)(object)component3 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)component3);
				}
				AnimalAI obj = val.GetComponent<AnimalAI>() ?? val.AddComponent<AnimalAI>();
				((BaseAI)obj).m_viewRange = HoardgoblinSettings.AlertRange.Value * 1.5f;
				((BaseAI)obj).m_hearRange = HoardgoblinSettings.AlertRange.Value;
				((BaseAI)obj).m_viewAngle = 360f;
				((BaseAI)obj).m_fleeRange = HoardgoblinSettings.FleeDistance.Value;
				((BaseAI)obj).m_fleeAngle = 180f;
				((BaseAI)obj).m_fleeInterval = 0.4f;
				obj.m_timeToSafe = 10f;
				((BaseAI)obj).m_jumpInterval = 0f;
				((BaseAI)obj).m_avoidFire = true;
				((BaseAI)obj).m_avoidWater = true;
				((BaseAI)obj).m_avoidLava = true;
				((BaseAI)obj).m_canBeAlerted = true;
				((BaseAI)obj).m_smoothMovement = true;
				CharacterDrop[] componentsInChildren = val.GetComponentsInChildren<CharacterDrop>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
				}
				val.AddComponent<HoardgoblinController>();
				CreatureConfig val2 = new CreatureConfig
				{
					Name = "$hoardgoblin_name"
				};
				List<SpawnConfig> list = ParseBiomeSpawns();
				if (list.Count > 0)
				{
					foreach (SpawnConfig item in list)
					{
						val2.AddSpawnConfig(item);
					}
				}
				CustomCreature val3 = new CustomCreature(val, false, val2);
				CreatureManager.Instance.AddCreature(val3);
				HoardgoblinPrefab = val;
				HoardgoblinPlugin.Log.LogInfo((object)("Hoardgoblin: successfully registered 'DFG_Hoardgoblin' with biomes: " + HoardgoblinSettings.EnabledBiomes.Value));
			}
		}

		private static List<SpawnConfig> ParseBiomeSpawns()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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_00d1: 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_00e4: Expected O, but got Unknown
			List<SpawnConfig> list = new List<SpawnConfig>();
			string[] array = (HoardgoblinSettings.EnabledBiomes.Value ?? "").Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (string.Equals(text, "Ashlands", StringComparison.OrdinalIgnoreCase))
				{
					text = "AshLands";
				}
				if (Enum.TryParse<Biome>(text, ignoreCase: true, out Biome result))
				{
					list.Add(new SpawnConfig
					{
						Name = "Spawn_DFG_Hoardgoblin_" + text,
						Biome = result,
						BiomeArea = (BiomeArea)3,
						MaxSpawned = HoardgoblinSettings.MaxSpawned.Value,
						SpawnInterval = HoardgoblinSettings.SpawnInterval.Value,
						SpawnChance = HoardgoblinSettings.SpawnChance.Value,
						SpawnDistance = 30f,
						MinLevel = 1,
						MaxLevel = 1,
						SpawnAtDay = true,
						SpawnAtNight = true
					});
				}
			}
			return list;
		}
	}
	public static class HoardgoblinSettings
	{
		public static ConfigEntry<bool> Enabled { get; private set; }

		public static ConfigEntry<float> ModelScale { get; private set; }

		public static ConfigEntry<float> BaseHealth { get; private set; }

		public static ConfigEntry<float> RunSpeed { get; private set; }

		public static ConfigEntry<float> WalkSpeed { get; private set; }

		public static ConfigEntry<float> AlertRange { get; private set; }

		public static ConfigEntry<float> FleeDistance { get; private set; }

		public static ConfigEntry<bool> JumpObstacles { get; private set; }

		public static ConfigEntry<float> JumpForce { get; private set; }

		public static ConfigEntry<float> ChaseTimeBeforeEscape { get; private set; }

		public static ConfigEntry<float> EscapeChannelDuration { get; private set; }

		public static ConfigEntry<float> CoinTrailInterval { get; private set; }

		public static ConfigEntry<int> CoinTrailMin { get; private set; }

		public static ConfigEntry<int> CoinTrailMax { get; private set; }

		public static ConfigEntry<float> TrailGemChance { get; private set; }

		public static ConfigEntry<int> JackpotCoinMin { get; private set; }

		public static ConfigEntry<int> JackpotCoinMax { get; private set; }

		public static ConfigEntry<int> JackpotGemsMin { get; private set; }

		public static ConfigEntry<int> JackpotGemsMax { get; private set; }

		public static ConfigEntry<bool> JackpotBonusMaterials { get; private set; }

		public static ConfigEntry<float> SpawnChance { get; private set; }

		public static ConfigEntry<float> SpawnInterval { get; private set; }

		public static ConfigEntry<int> MaxSpawned { get; private set; }

		public static ConfigEntry<string> EnabledBiomes { get; private set; }

		public static void Bind(ConfigFile config)
		{
			Enabled = config.Bind<bool>("1 - General", "Enabled", true, "Enable the Hoardgoblin mod.");
			ModelScale = config.Bind<float>("1 - General", "ModelScale", 1.2f, "Visual scale of the Hoardgoblin model.");
			BaseHealth = config.Bind<float>("1 - General", "BaseHealth", 200f, "Base health of the Hoardgoblin.");
			RunSpeed = config.Bind<float>("1 - General", "RunSpeed", 22f, "Sprint speed when fleeing in terror (fast and frantic).");
			WalkSpeed = config.Bind<float>("1 - General", "WalkSpeed", 8f, "Wander/walk speed.");
			AlertRange = config.Bind<float>("1 - General", "AlertRange", 25f, "Distance at which the goblin spots the player and flees.");
			FleeDistance = config.Bind<float>("1 - General", "FleeDistance", 55f, "Distance the goblin tries to put between itself and players.");
			JumpObstacles = config.Bind<bool>("1 - General", "JumpObstacles", true, "Enable jumping over rocks, fences, and obstacles when fleeing.");
			JumpForce = config.Bind<float>("1 - General", "JumpForce", 8.5f, "Upward jump velocity when encountering obstacles or getting stuck.");
			ChaseTimeBeforeEscape = config.Bind<float>("2 - Escape Portal", "ChaseTimeBeforeEscape", 30f, "Seconds of continuous chase before the goblin attempts to summon an escape portal.");
			EscapeChannelDuration = config.Bind<float>("2 - Escape Portal", "EscapeChannelDuration", 5f, "Seconds needed to channel the escape portal before disappearing. Stagger or damage interrupts it!");
			CoinTrailInterval = config.Bind<float>("3 - Loot Trail", "CoinTrailInterval", 3f, "Seconds between coin/gem breadcrumb drops while sprinting.");
			CoinTrailMin = config.Bind<int>("3 - Loot Trail", "CoinTrailMin", 4, "Minimum coins dropped per breadcrumb tick.");
			CoinTrailMax = config.Bind<int>("3 - Loot Trail", "CoinTrailMax", 10, "Maximum coins dropped per breadcrumb tick.");
			TrailGemChance = config.Bind<float>("3 - Loot Trail", "TrailGemChance", 0.25f, "Chance (0-1) to drop a loose Amber, Ruby, or Amber Pearl while sprinting.");
			JackpotCoinMin = config.Bind<int>("4 - Jackpot Loot", "JackpotCoinMin", 300, "Minimum coins dropped upon slaying the Hoardgoblin.");
			JackpotCoinMax = config.Bind<int>("4 - Jackpot Loot", "JackpotCoinMax", 700, "Maximum coins dropped upon slaying the Hoardgoblin.");
			JackpotGemsMin = config.Bind<int>("4 - Jackpot Loot", "JackpotGemsMin", 6, "Minimum assorted gems/valuables dropped upon death.");
			JackpotGemsMax = config.Bind<int>("4 - Jackpot Loot", "JackpotGemsMax", 14, "Maximum assorted gems/valuables dropped upon death.");
			JackpotBonusMaterials = config.Bind<bool>("4 - Jackpot Loot", "JackpotBonusMaterials", true, "Drop biome-scaled rare materials (e.g. Copper/Bronze in Black Forest, Iron in Swamp, Silver in Mountains, Black Metal in Plains, Eitr in Mistlands, Flametal in Ashlands).");
			SpawnChance = config.Bind<float>("5 - Spawning", "SpawnChance", 15f, "Spawn check percentage chance (0-100%).");
			SpawnInterval = config.Bind<float>("5 - Spawning", "SpawnInterval", 1000f, "Seconds between spawn check attempts.");
			MaxSpawned = config.Bind<int>("5 - Spawning", "MaxSpawned", 1, "Maximum simultaneous Hoardgoblins per loaded zone.");
			EnabledBiomes = config.Bind<string>("5 - Spawning", "EnabledBiomes", "Meadows,BlackForest,Swamp,Mountain,Plains,Mistlands,Ashlands", "Comma-separated biomes where Hoardgoblins can spawn.");
		}
	}
}