Decompiled source of Hufsa v0.2.3

Hufsa.dll

Decompiled 19 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Splatform;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Networking;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[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 Hufsa
{
	internal class FrostVisuals : MonoBehaviour
	{
		private class Entry
		{
			public float Amount;

			public Color[] BaseColors;
		}

		private const float FadeSeconds = 3f;

		private static readonly int ColorId = Shader.PropertyToID("_Color");

		private readonly Dictionary<Renderer, Entry> entries = new Dictionary<Renderer, Entry>();

		private readonly Dictionary<Renderer, float> targets = new Dictionary<Renderer, float>();

		private readonly HashSet<GameObject> scannedRoots = new HashSet<GameObject>();

		private readonly List<Renderer> removeBuffer = new List<Renderer>();

		private readonly Collider[] hits = (Collider[])(object)new Collider[4096];

		private MaterialPropertyBlock mpb;

		private float scanTimer;

		private void Update()
		{
			if (!HufsaConfig.FoliageFrostEnabled.Value)
			{
				if (entries.Count > 0)
				{
					ClearAll();
				}
				return;
			}
			scanTimer -= Time.deltaTime;
			if (scanTimer <= 0f)
			{
				scanTimer = 1f;
				Scan();
			}
			Fade(Time.deltaTime);
		}

		private void Scan()
		{
			//IL_0078: 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_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_00ae: Unknown result type (might be due to invalid IL or missing references)
			targets.Clear();
			scannedRoots.Clear();
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer))
			{
				return;
			}
			foreach (HufsaEntity instance in HufsaEntity.Instances)
			{
				if (instance.Vanishing)
				{
					continue;
				}
				float num = (instance.IsHunter ? HufsaConfig.ColdRadius.Value : HufsaConfig.WatcherFrostRadius.Value);
				if (num <= 0f)
				{
					continue;
				}
				Vector3 val = ((Component)instance).transform.position - ((Component)localPlayer).transform.position;
				if (((Vector3)(ref val)).sqrMagnitude > 40000f)
				{
					continue;
				}
				float frostFactor = instance.FrostFactor;
				int num2 = Physics.OverlapSphereNonAlloc(((Component)instance).transform.position, num, hits);
				for (int i = 0; i < num2; i++)
				{
					GameObject val2 = FindFrostableRoot(hits[i]);
					if (!Object.op_Implicit((Object)(object)val2) || !scannedRoots.Add(val2))
					{
						continue;
					}
					Renderer[] componentsInChildren = val2.GetComponentsInChildren<Renderer>();
					foreach (Renderer val3 in componentsInChildren)
					{
						if (!(val3 is ParticleSystemRenderer) && (!targets.TryGetValue(val3, out var value) || frostFactor > value))
						{
							targets[val3] = frostFactor;
						}
					}
				}
			}
		}

		private static GameObject FindFrostableRoot(Collider c)
		{
			if (!Object.op_Implicit((Object)(object)c) || Object.op_Implicit((Object)(object)((Component)c).GetComponentInParent<Piece>()) || Object.op_Implicit((Object)(object)((Component)c).GetComponentInParent<Character>()))
			{
				return null;
			}
			Component componentInParent = (Component)(object)((Component)c).GetComponentInParent<TreeBase>();
			if (!Object.op_Implicit((Object)(object)componentInParent))
			{
				componentInParent = (Component)(object)((Component)c).GetComponentInParent<TreeLog>();
			}
			if (!Object.op_Implicit((Object)(object)componentInParent))
			{
				componentInParent = (Component)(object)((Component)c).GetComponentInParent<Pickable>();
			}
			if (!Object.op_Implicit((Object)(object)componentInParent))
			{
				componentInParent = (Component)(object)((Component)c).GetComponentInParent<Destructible>();
			}
			if (!Object.op_Implicit((Object)(object)componentInParent))
			{
				componentInParent = (Component)(object)((Component)c).GetComponentInParent<MineRock>();
			}
			if (!Object.op_Implicit((Object)(object)componentInParent))
			{
				componentInParent = (Component)(object)((Component)c).GetComponentInParent<MineRock5>();
			}
			if (!Object.op_Implicit((Object)(object)componentInParent))
			{
				return null;
			}
			return componentInParent.gameObject;
		}

		private void Fade(float dt)
		{
			//IL_0018: 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)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//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_0191: Unknown result type (might be due to invalid IL or missing references)
			if (mpb == null)
			{
				mpb = new MaterialPropertyBlock();
			}
			Color value = HufsaConfig.FrostColor.Value;
			float value2 = HufsaConfig.FrostStrength.Value;
			foreach (Renderer key2 in targets.Keys)
			{
				if (Object.op_Implicit((Object)(object)key2) && !entries.ContainsKey(key2))
				{
					entries[key2] = new Entry
					{
						BaseColors = ReadBaseColors(key2)
					};
				}
			}
			removeBuffer.Clear();
			foreach (KeyValuePair<Renderer, Entry> entry in entries)
			{
				Renderer key = entry.Key;
				Entry value3 = entry.Value;
				if (!Object.op_Implicit((Object)(object)key))
				{
					removeBuffer.Add(key);
					continue;
				}
				float value4;
				float num = (targets.TryGetValue(key, out value4) ? value4 : 0f);
				if (Mathf.Approximately(value3.Amount, num) && num > 0f)
				{
					continue;
				}
				value3.Amount = Mathf.MoveTowards(value3.Amount, num, dt / 3f);
				if (value3.Amount <= 0f)
				{
					Restore(key, value3);
					removeBuffer.Add(key);
					continue;
				}
				for (int i = 0; i < value3.BaseColors.Length; i++)
				{
					mpb.Clear();
					mpb.SetColor(ColorId, Color.Lerp(value3.BaseColors[i], value, value3.Amount * value2));
					key.SetPropertyBlock(mpb, i);
				}
			}
			foreach (Renderer item in removeBuffer)
			{
				entries.Remove(item);
			}
		}

		private static Color[] ReadBaseColors(Renderer r)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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)
			Material[] sharedMaterials = r.sharedMaterials;
			Color[] array = (Color[])(object)new Color[sharedMaterials.Length];
			for (int i = 0; i < sharedMaterials.Length; i++)
			{
				array[i] = ((Object.op_Implicit((Object)(object)sharedMaterials[i]) && sharedMaterials[i].HasProperty(ColorId)) ? sharedMaterials[i].GetColor(ColorId) : Color.white);
			}
			return array;
		}

		private void Restore(Renderer r, Entry e)
		{
			mpb.Clear();
			for (int i = 0; i < e.BaseColors.Length; i++)
			{
				r.SetPropertyBlock(mpb, i);
			}
		}

		private void ClearAll()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			if (mpb == null)
			{
				mpb = new MaterialPropertyBlock();
			}
			foreach (KeyValuePair<Renderer, Entry> entry in entries)
			{
				if (Object.op_Implicit((Object)(object)entry.Key))
				{
					Restore(entry.Key, entry.Value);
				}
			}
			entries.Clear();
		}
	}
	internal class HufsaArms : MonoBehaviour
	{
		private class Arm
		{
			public HufsaModel.ArmRig Rig;

			public Transform Pivot;

			public Transform Twist;

			public Transform Reach;

			public Transform[] Fingers;

			public Mesh Mesh;

			public Vector3[] Verts;

			public Vector3[] Normals;

			public SilhouetteGlow Glow;

			public Quaternion Aim;

			public bool HasAim;
		}

		private readonly List<Arm> arms = new List<Arm>();

		private HufsaEntity entity;

		private Transform visual;

		private float raise;

		private float shownRest = -1f;

		public readonly List<Renderer> ArmRenderers = new List<Renderer>();

		public readonly List<Renderer> FingerRenderers = new List<Renderer>();

		private void Awake()
		{
			entity = ((Component)this).GetComponent<HufsaEntity>();
			visual = ((Component)this).transform.Find("HufsaVisual");
			if (!Object.op_Implicit((Object)(object)visual) || HufsaModel.Arms == null)
			{
				return;
			}
			for (int i = 0; i < HufsaModel.Arms.Length; i++)
			{
				Transform val = visual.Find("ArmPivot" + i);
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				Transform val2 = val.Find("Axis/Twist");
				Transform val3 = (Object.op_Implicit((Object)(object)val2) ? val2.Find("Reach") : null);
				Transform val4 = (Object.op_Implicit((Object)(object)val3) ? val3.Find("Arm") : null);
				if (!Object.op_Implicit((Object)(object)val4))
				{
					continue;
				}
				Arm obj = new Arm
				{
					Rig = HufsaModel.Arms[i],
					Pivot = val,
					Twist = val2,
					Reach = val3,
					Mesh = ((Component)val4).GetComponent<MeshFilter>().mesh
				};
				Transform obj2 = val3.Find("ArmGlow");
				obj.Glow = ((obj2 != null) ? ((Component)obj2).GetComponent<SilhouetteGlow>() : null);
				Arm arm = obj;
				arm.Mesh.MarkDynamic();
				arm.Verts = (Vector3[])(object)new Vector3[arm.Rig.RaisedVertices.Length];
				arm.Normals = (Vector3[])(object)new Vector3[arm.Rig.RaisedVertices.Length];
				arm.Fingers = (Transform[])(object)new Transform[arm.Rig.Fingers.Length];
				for (int j = 0; j < arm.Fingers.Length; j++)
				{
					arm.Fingers[j] = val3.Find("Finger" + j);
					if (Object.op_Implicit((Object)(object)arm.Fingers[j]))
					{
						FingerRenderers.Add(((Component)arm.Fingers[j]).GetComponent<Renderer>());
					}
				}
				ArmRenderers.Add(((Component)val4).GetComponent<Renderer>());
				arms.Add(arm);
			}
		}

		private void OnDestroy()
		{
			foreach (Arm arm in arms)
			{
				if (Object.op_Implicit((Object)(object)arm.Mesh))
				{
					Object.Destroy((Object)(object)arm.Mesh);
				}
			}
		}

		public void SetGlowVisibility(float v)
		{
			foreach (Arm arm in arms)
			{
				if (Object.op_Implicit((Object)(object)arm.Glow))
				{
					arm.Glow.Visibility = v;
				}
			}
		}

		private void LateUpdate()
		{
			//IL_0074: 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_0083: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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_00b5: 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_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: 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_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: 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_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: 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)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_036a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0378: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0384: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c2: 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_04ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
			if (arms.Count == 0)
			{
				return;
			}
			float deltaTime = Time.deltaTime;
			Player localPlayer = Player.m_localPlayer;
			bool flag = Object.op_Implicit((Object)(object)localPlayer) && !((Character)localPlayer).IsDead() && (!Object.op_Implicit((Object)(object)entity) || !entity.Vanishing);
			Vector3 val = ((HufsaEntity.PhotoHold && Object.op_Implicit((Object)(object)GameCamera.instance)) ? ((Component)GameCamera.instance).transform.position : (Object.op_Implicit((Object)(object)localPlayer) ? (((Component)localPlayer).transform.position + Vector3.up * 1.3f) : Vector3.zero));
			float num = 0f;
			if (flag)
			{
				Vector3 val2 = val - ((Component)this).transform.position;
				val2.y = 0f;
				num = 1f - HufsaModel.Smooth(4f, 6f, ((Vector3)(ref val2)).magnitude);
			}
			raise = Mathf.MoveTowards(raise, num, deltaTime * 0.6f);
			float num2 = raise * raise * (3f - 2f * raise);
			float num3 = 1f - num2;
			Vector3 val3 = (flag ? visual.InverseTransformPoint(val) : Vector3.zero);
			float num4 = 1f - Mathf.Exp((0f - deltaTime) * 3f);
			bool flag2 = Mathf.Abs(num3 - shownRest) > 0.001f;
			foreach (Arm arm in arms)
			{
				HufsaModel.ArmRig rig = arm.Rig;
				Quaternion val4 = Quaternion.AngleAxis(16f, Vector3.right) * Quaternion.AngleAxis(rig.Side * 20.5f, Vector3.forward);
				Vector3 val5;
				if (flag)
				{
					val5 = val3 - rig.Shoulder;
					Vector3 normalized = ((Vector3)(ref val5)).normalized;
					float num5 = Mathf.Atan2(normalized.x, normalized.z);
					float num6 = Mathf.Sqrt(normalized.x * normalized.x + normalized.z * normalized.z);
					float num7 = 0.43633232f;
					if (Mathf.Abs(num5) > num7)
					{
						float num8 = Mathf.Sign(num5) * num7;
						((Vector3)(ref normalized))..ctor(Mathf.Sin(num8) * num6, normalized.y, Mathf.Cos(num8) * num6);
					}
					Quaternion val6 = Quaternion.FromToRotation(rig.End, normalized);
					arm.Aim = (arm.HasAim ? Quaternion.Slerp(arm.Aim, val6, num4) : val6);
					arm.HasAim = true;
				}
				arm.Pivot.localRotation = (arm.HasAim ? Quaternion.Slerp(val4, arm.Aim, num2) : val4);
				arm.Twist.localRotation = Quaternion.AngleAxis(rig.Side * num2 * 59f, Vector3.up);
				arm.Reach.localPosition = new Vector3(0f, ((0f - num2) * 0f + num3 * 0.15f) * rig.Len, 0f);
				if (!flag2)
				{
					continue;
				}
				for (int i = 0; i < arm.Verts.Length; i++)
				{
					arm.Verts[i] = Vector3.LerpUnclamped(rig.RaisedVertices[i], rig.RestVertices[i], num3);
					Vector3[] normals = arm.Normals;
					int num9 = i;
					val5 = Vector3.LerpUnclamped(rig.RaisedNormals[i], rig.RestNormals[i], num3);
					normals[num9] = ((Vector3)(ref val5)).normalized;
				}
				arm.Mesh.vertices = arm.Verts;
				arm.Mesh.normals = arm.Normals;
				arm.Mesh.RecalculateBounds();
				if (Object.op_Implicit((Object)(object)arm.Glow))
				{
					arm.Glow.SetShape(arm.Verts, arm.Normals);
				}
				float num10 = rig.Side * num3 * 47f;
				float num11 = Mathf.Cos(num10 * ((float)Math.PI / 180f));
				float num12 = Mathf.Sin(num10 * ((float)Math.PI / 180f));
				for (int j = 0; j < arm.Fingers.Length; j++)
				{
					if (Object.op_Implicit((Object)(object)arm.Fingers[j]))
					{
						HufsaModel.FingerPlace fingerPlace = rig.Fingers[j];
						float num13 = Mathf.Lerp(fingerPlace.RaisedCx, fingerPlace.RestCx, num3);
						arm.Fingers[j].localPosition = new Vector3(num13 + fingerPlace.Dx * num11, fingerPlace.Y, fingerPlace.Cz - fingerPlace.Dx * num12);
						arm.Fingers[j].localRotation = Quaternion.AngleAxis(fingerPlace.Tilt, Vector3.right) * Quaternion.AngleAxis(num10, Vector3.up) * Quaternion.AngleAxis(Mathf.Lerp(fingerPlace.RaisedRz, fingerPlace.RestRz, num3), Vector3.forward);
					}
				}
			}
			if (flag2)
			{
				shownRest = num3;
			}
		}
	}
	internal class RevealFader
	{
		private readonly List<Renderer> renderers;

		public readonly Material Lit;

		private readonly Material see;

		private Material current;

		private bool shown = true;

		public RevealFader(List<Renderer> renderers)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//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_0084: Expected O, but got Unknown
			this.renderers = renderers;
			if (renderers.Count != 0 && Object.op_Implicit((Object)(object)renderers[0]))
			{
				Lit = new Material(renderers[0].sharedMaterial);
				if (Object.op_Implicit((Object)(object)HufsaPrefabs.SpriteShader))
				{
					see = new Material(HufsaPrefabs.SpriteShader)
					{
						mainTexture = (Lit.HasProperty("_MainTex") ? Lit.mainTexture : null)
					};
				}
				Use(Lit);
			}
		}

		public void Set(float k)
		{
			//IL_00ad: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_00e5: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)Lit))
			{
				return;
			}
			bool flag = k > 0.01f;
			if (flag != shown)
			{
				foreach (Renderer renderer in renderers)
				{
					if (Object.op_Implicit((Object)(object)renderer))
					{
						renderer.enabled = flag;
					}
				}
				shown = flag;
			}
			if (flag)
			{
				if (k >= 0.99f || !Object.op_Implicit((Object)(object)see))
				{
					Use(Lit);
					return;
				}
				Color val2 = (Lit.HasProperty("_Color") ? Lit.color : Color.white);
				Color ambientLight = RenderSettings.ambientLight;
				float num = Mathf.Clamp(((Color)(ref ambientLight)).maxColorComponent * 1.5f, 0.15f, 1f);
				see.color = new Color(val2.r * num, val2.g * num, val2.b * num, k);
				Use(see);
			}
		}

		private void Use(Material m)
		{
			if ((Object)(object)current == (Object)(object)m)
			{
				return;
			}
			foreach (Renderer renderer in renderers)
			{
				if (Object.op_Implicit((Object)(object)renderer))
				{
					renderer.sharedMaterial = m;
				}
			}
			current = m;
		}

		public void Destroy()
		{
			if (Object.op_Implicit((Object)(object)Lit))
			{
				Object.Destroy((Object)(object)Lit);
			}
			if (Object.op_Implicit((Object)(object)see))
			{
				Object.Destroy((Object)(object)see);
			}
		}
	}
	internal class HufsaAudio : MonoBehaviour
	{
		private const string FileName = "hufsa_loop.mp3";

		private AudioSource source;

		private float volume;

		private IEnumerator Start()
		{
			((MonoBehaviour)this).StartCoroutine(HufsaSoundBank.Load());
			string text = Path.Combine(Path.GetDirectoryName(typeof(HufsaAudio).Assembly.Location) ?? "", "hufsa_loop.mp3");
			if (!File.Exists(text))
			{
				HufsaPlugin.Log.LogWarning((object)("No Hufsa audio at " + text));
				yield break;
			}
			UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip(new Uri(text).AbsoluteUri, (AudioType)13);
			try
			{
				yield return req.SendWebRequest();
				if ((int)req.result != 1)
				{
					HufsaPlugin.Log.LogError((object)("Failed to load Hufsa audio: " + req.error));
					yield break;
				}
				AudioClip content = DownloadHandlerAudioClip.GetContent(req);
				((Object)content).name = "HufsaLoop";
				source = ((Component)this).gameObject.AddComponent<AudioSource>();
				source.clip = content;
				source.loop = true;
				source.playOnAwake = false;
				source.spatialBlend = 0f;
				source.volume = 0f;
			}
			finally
			{
				((IDisposable)req)?.Dispose();
			}
		}

		private void Update()
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)source))
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)source.outputAudioMixerGroup) && Object.op_Implicit((Object)(object)AudioMan.instance))
			{
				source.outputAudioMixerGroup = AudioMan.instance.m_ambientMixer;
			}
			float num = 0f;
			Player localPlayer = Player.m_localPlayer;
			if (Object.op_Implicit((Object)(object)localPlayer) && !((Character)localPlayer).IsDead())
			{
				float value = HufsaConfig.AudioRange.Value;
				foreach (HufsaEntity instance in HufsaEntity.Instances)
				{
					if (instance.IsHunter && !instance.Vanishing)
					{
						float num2 = Vector3.Distance(((Component)instance).transform.position, ((Component)localPlayer).transform.position);
						num = Mathf.Max(num, Mathf.Clamp01(1f - num2 / value));
					}
				}
			}
			float num3 = HufsaConfig.AudioVolume.Value * Mathf.Pow(num, 0.6f);
			float num4 = ((num3 > volume) ? 2f : 3f);
			volume = Mathf.MoveTowards(volume, num3, Time.deltaTime / num4);
			source.volume = volume;
			if (volume > 0.001f && !source.isPlaying)
			{
				source.Play();
			}
			else if (volume <= 0.001f && source.isPlaying)
			{
				source.Stop();
			}
		}
	}
	internal class HufsaAuraManager : MonoBehaviour
	{
		internal static float LocalSpeedFactor = 1f;

		private float timer;

		private string forcedEnv;

		private bool templatePrepared;

		internal static float GlowWeatherFactor = 1f;

		private float lastWatcherSeen = float.MinValue;

		private readonly Dictionary<Biome, string> fogByBiome = new Dictionary<Biome, string>();

		private float gameTransition = -1f;

		private float restoreTransitionAt = -1f;

		private void Update()
		{
			//IL_008b: 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_01ef: Unknown result type (might be due to invalid IL or missing references)
			timer += Time.deltaTime;
			if (timer < 0.25f)
			{
				return;
			}
			timer = 0f;
			Player localPlayer = Player.m_localPlayer;
			LocalSpeedFactor = 1f;
			if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead())
			{
				SetWeather(null);
				return;
			}
			HufsaEntity hufsaEntity = null;
			float num = float.MaxValue;
			foreach (HufsaEntity instance in HufsaEntity.Instances)
			{
				if (instance.IsHunter && !instance.Vanishing)
				{
					float num2 = Vector3.Distance(((Component)instance).transform.position, ((Component)localPlayer).transform.position);
					if (num2 < num)
					{
						num = num2;
						hufsaEntity = instance;
					}
				}
			}
			if (Object.op_Implicit((Object)(object)hufsaEntity) && num <= HufsaConfig.CatchRadius.Value && HufsaHuntState.IsHuntable(localPlayer))
			{
				Caught(localPlayer);
				return;
			}
			float value = HufsaConfig.ColdRadius.Value;
			float num3 = Falloff(hufsaEntity, num, value);
			if (Object.op_Implicit((Object)(object)hufsaEntity) && num < value)
			{
				float num4 = Mathf.Pow(Mathf.Clamp01(1f - num / value), HufsaConfig.SlowCurve.Value);
				LocalSpeedFactor = 1f - HufsaConfig.MaxSlow.Value * num4;
			}
			if (num3 > 0f)
			{
				float value2 = HufsaConfig.StaminaRegenStopRadius.Value;
				float regen = Mathf.Clamp01((num - value2) / Mathf.Max(value - value2, 1f));
				float drain = Mathf.Clamp01(1f - num / Mathf.Max(HufsaConfig.StaminaDrainRadius.Value, 0.1f));
				ApplyChill(localPlayer, hufsaEntity, num3, regen, drain);
			}
			if (HufsaConfig.WeatherEnabled.Value && Object.op_Implicit((Object)(object)hufsaEntity) && !hufsaEntity.Mild && num < value)
			{
				SetWeather(HufsaConfig.WeatherEnvironment.Value);
			}
			else if (HufsaConfig.WatcherFog.Value && FoggyWatcherRecently())
			{
				SetWeather(FogEnvironment(((Component)localPlayer).transform.position));
			}
			else
			{
				SetWeather(null);
			}
		}

		private void LateUpdate()
		{
			RestoreTransition();
			float num = (IsFoggy() ? HufsaConfig.FogGlow.Value : 1f);
			GlowWeatherFactor = Mathf.MoveTowards(GlowWeatherFactor, num, Time.deltaTime / 4f);
		}

		private static bool IsFoggy()
		{
			string text = HufsaEntity.CurrentWeather().ToLowerInvariant();
			if (!text.Contains("mist"))
			{
				return text.Contains("fog");
			}
			return true;
		}

		private bool FoggyWatcherRecently()
		{
			foreach (HufsaEntity instance in HufsaEntity.Instances)
			{
				if (!instance.IsHunter && instance.DreadAtArrival >= HufsaConfig.WatcherFogFromSightings.Value)
				{
					lastWatcherSeen = Time.time;
					return true;
				}
			}
			return Time.time - lastWatcherSeen < HufsaConfig.WatcherFogLinger.Value;
		}

		private string FogEnvironment(Vector3 pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: 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_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)
			Biome val = HufsaEntity.BiomeAt(pos);
			if (fogByBiome.TryGetValue(val, out var value))
			{
				return value;
			}
			string text = null;
			float num = -1f;
			if (Object.op_Implicit((Object)(object)EnvMan.instance))
			{
				foreach (BiomeEnvSetup biome in EnvMan.instance.m_biomes)
				{
					if (biome.m_biome != val)
					{
						continue;
					}
					foreach (EnvEntry environment in biome.m_environments)
					{
						string text2 = (environment.m_environment ?? "").ToLowerInvariant();
						if (environment.m_env != null && (text2.Contains("mist") || text2.Contains("fog")) && environment.m_env.m_fogDensityNight > num)
						{
							num = environment.m_env.m_fogDensityNight;
							text = environment.m_environment;
						}
					}
				}
			}
			fogByBiome[val] = text;
			HufsaPlugin.Log.LogInfo((object)string.Format("Hufsa fog for {0}: {1}", val, text ?? "none"));
			return text;
		}

		private static float Falloff(HufsaEntity nearest, float dist, float radius)
		{
			if (!Object.op_Implicit((Object)(object)nearest) || radius <= 0f)
			{
				return 0f;
			}
			return Mathf.Pow(Mathf.Clamp01(1f - dist / radius), HufsaConfig.AuraCurve.Value);
		}

		private static void Caught(Player player)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0018: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			HitData val = new HitData();
			val.m_damage.m_damage = 1000000f;
			val.m_hitType = (HitType)6;
			val.m_point = ((Character)player).GetCenterPoint();
			((Character)player).ApplyDamage(val, true, true, (DamageModifier)0);
			HufsaPlugin.Log.LogInfo((object)"Hufsa caught the local player");
		}

		private void ApplyChill(Player player, HufsaEntity hufsa, float cold, float regen, float drain)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_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_0076: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
			PrepareTemplate();
			SEMan sEMan = ((Character)player).GetSEMan();
			SE_HufsaChill sE_HufsaChill = sEMan.GetStatusEffect(SE_HufsaChill.Hash) as SE_HufsaChill;
			if (!Object.op_Implicit((Object)(object)sE_HufsaChill))
			{
				sE_HufsaChill = sEMan.AddStatusEffect(SE_HufsaChill.Hash, true, 0, 0f, (short)(-1)) as SE_HufsaChill;
			}
			if (Object.op_Implicit((Object)(object)sE_HufsaChill))
			{
				Vector3 velocity = ((Character)player).GetVelocity();
				velocity.y = 0f;
				Vector3 val = ((Component)hufsa).transform.position - ((Component)player).transform.position;
				val.y = 0f;
				float num = ((((Vector3)(ref velocity)).magnitude > 0.5f) ? Mathf.Max(0f, Vector3.Dot(((Vector3)(ref velocity)).normalized, ((Vector3)(ref val)).normalized)) : 0f);
				sE_HufsaChill.ColdStrength = cold;
				sE_HufsaChill.RegenFactor = regen;
				sE_HufsaChill.DrainStrength = drain;
				sE_HufsaChill.ApproachMultiplier = 1f + num * (HufsaConfig.ApproachMultiplier.Value - 1f);
				((StatusEffect)sE_HufsaChill).ResetTime();
			}
		}

		private void PrepareTemplate()
		{
			if (!templatePrepared && Object.op_Implicit((Object)(object)ObjectDB.instance))
			{
				StatusEffect statusEffect = ObjectDB.instance.GetStatusEffect(SE_HufsaChill.Hash);
				StatusEffect statusEffect2 = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Freezing"));
				if (Object.op_Implicit((Object)(object)statusEffect) && Object.op_Implicit((Object)(object)statusEffect2))
				{
					statusEffect.m_icon = statusEffect2.m_icon;
					statusEffect.m_startEffects = statusEffect2.m_startEffects;
				}
				templatePrepared = true;
			}
		}

		private void SetWeather(string want)
		{
			EnvMan instance = EnvMan.instance;
			if (Object.op_Implicit((Object)(object)instance) && !(want == forcedEnv))
			{
				if (forcedEnv != null && instance.m_forceEnv == forcedEnv)
				{
					SlowTransition(instance);
					instance.SetForceEnvironment("");
				}
				forcedEnv = null;
				if (!string.IsNullOrEmpty(want) && string.IsNullOrEmpty(instance.m_forceEnv))
				{
					SlowTransition(instance);
					instance.SetForceEnvironment(want);
					forcedEnv = want;
				}
			}
		}

		private void SlowTransition(EnvMan env)
		{
			if (gameTransition < 0f)
			{
				gameTransition = env.m_transitionDuration;
			}
			env.m_transitionDuration = Mathf.Max(gameTransition, HufsaConfig.WeatherFade.Value);
			restoreTransitionAt = Time.time + env.m_transitionDuration + 1f;
		}

		private void RestoreTransition()
		{
			if (!(restoreTransitionAt < 0f) && !(Time.time < restoreTransitionAt))
			{
				if (Object.op_Implicit((Object)(object)EnvMan.instance) && gameTransition >= 0f)
				{
					EnvMan.instance.m_transitionDuration = gameTransition;
				}
				restoreTransitionAt = -1f;
			}
		}

		private void OnDestroy()
		{
			SetWeather(null);
			if (Object.op_Implicit((Object)(object)EnvMan.instance) && gameTransition >= 0f)
			{
				EnvMan.instance.m_transitionDuration = gameTransition;
			}
		}
	}
	internal class HufsaCommand : ConsoleCommand
	{
		public override string Name => "hufsa";

		public override string Help => "hufsa watcher|hunter|weather|dread [n]|testmode|availableSpots - spawn a Hufsa near you (ignores time of day), check the weather, show/set your Watcher sightings, or toggle a debug mode";

		public override bool IsCheat => true;

		public override void Run(string[] args)
		{
			//IL_00fc: 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_0101: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			string text = ((args.Length != 0) ? args[0].ToLowerInvariant() : "watcher");
			if (text == "testmode" && Object.op_Implicit((Object)(object)HufsaDebug.Instance))
			{
				HufsaDebug.Instance.ToggleTestMode();
			}
			else if (text == "availablespots" && Object.op_Implicit((Object)(object)HufsaDebug.Instance))
			{
				HufsaDebug.Instance.ToggleSpots();
			}
			else if (text.StartsWith("dr") && Object.op_Implicit((Object)(object)HufsaDread.Instance))
			{
				if (args.Length > 1 && int.TryParse(args[1], out var result))
				{
					HufsaDread.Instance.SetCount(result);
				}
				Console.instance.Print($"Watcher sightings: {HufsaDread.Instance.Count}/{HufsaConfig.SightingsForHunt.Value}" + " (a hunt starts on the next night you can be hunted once it's full)");
			}
			else if (text.StartsWith("we"))
			{
				Vector3 pos = (Object.op_Implicit((Object)(object)Player.m_localPlayer) ? ((Component)Player.m_localPlayer).transform.position : Vector3.zero);
				Console.instance.Print($"Weather '{HufsaEntity.CurrentWeather()}' in {HufsaEntity.BiomeAt(pos)}: " + $"storm/fog={HufsaEntity.IsBadWeather()}, night={EnvMan.IsNight()}, " + $"Watcher can appear={HufsaEntity.IsWatcherTime(pos)}, Hunter can appear={HufsaEntity.IsHufsaTime(pos)}");
			}
			else
			{
				string text2 = (text.StartsWith("h") ? "Hufsa_Hunter" : "Hufsa_Watcher");
				HufsaEntity hufsaEntity = HufsaSpawner.SpawnNearLocalPlayer(text2, force: true);
				Console.instance.Print(Object.op_Implicit((Object)(object)hufsaEntity) ? ("Spawned " + text2) : ("Could not find a spot for " + text2));
			}
		}

		public override List<string> CommandOptionList()
		{
			return new List<string> { "watcher", "hunter", "weather", "dread", "testmode", "availableSpots" };
		}
	}
	internal static class HufsaConfig
	{
		public static ConfigEntry<float> SpawnCheckInterval;

		public static ConfigEntry<bool> ForceEveryNight;

		public static ConfigEntry<bool> DeepNorthDaytime;

		public static ConfigEntry<bool> WatcherEnabled;

		public static ConfigEntry<float> WatcherChance;

		public static ConfigEntry<float> WatcherCooldown;

		public static ConfigEntry<float> WatcherEscalation;

		public static ConfigEntry<int> SightingsForHunt;

		public static ConfigEntry<int> DreadDecayDays;

		public static ConfigEntry<float> SightSeconds;

		public static ConfigEntry<bool> DreadMessages;

		public static ConfigEntry<float> WatcherMinDistance;

		public static ConfigEntry<float> WatcherMaxDistance;

		public static ConfigEntry<bool> HunterEnabled;

		public static ConfigEntry<float> HunterChance;

		public static ConfigEntry<float> HunterCooldownMinutes;

		public static ConfigEntry<float> HunterMinDistance;

		public static ConfigEntry<float> HunterMaxDistance;

		public static ConfigEntry<float> WatcherVanishDistance;

		public static ConfigEntry<float> WatcherLifetime;

		public static ConfigEntry<int> WatcherBlinks;

		public static ConfigEntry<float> WatcherLookAwaySeconds;

		public static ConfigEntry<bool> WatcherHidesBehindCover;

		public static ConfigEntry<string> WatcherDayBiomes;

		public static ConfigEntry<string> WatcherBadWeatherBiomes;

		public static ConfigEntry<string> BadWeatherKeywords;

		public static ConfigEntry<float> MistlandsMinDistance;

		public static ConfigEntry<float> MistlandsMaxDistance;

		public static ConfigEntry<float> MistlandsVanishDistance;

		public static ConfigEntry<float> LookAwayVanishChance;

		public static ConfigEntry<string> WoodedBiomes;

		public static ConfigEntry<string> DenseBiomes;

		public static ConfigEntry<int> DenseCoverBlocks;

		public static ConfigEntry<float> RetargetAfterDeathRadius;

		public static ConfigEntry<float> RespawnAfterVanish;

		public static ConfigEntry<float> HunterSpeed;

		public static ConfigEntry<float> HunterCloseDistance;

		public static ConfigEntry<float> HunterSpeedScale;

		public static ConfigEntry<float> HunterMaxSpeed;

		public static ConfigEntry<float> EscapeDistance;

		public static ConfigEntry<float> ClimbSpeed;

		public static ConfigEntry<float> WaterSpeedFactor;

		public static ConfigEntry<float> LungeSpeed;

		public static ConfigEntry<float> LungeSeconds;

		public static ConfigEntry<float> LungeStopDistance;

		public static ConfigEntry<float> RushEaseOut;

		public static ConfigEntry<float> SafeCloseDistance;

		public static ConfigEntry<float> SafeCloseSeconds;

		public static ConfigEntry<bool> WatcherEveryNight;

		public static ConfigEntry<float> WatcherGuaranteeWithin;

		public static ConfigEntry<float> WatcherVanishDense;

		public static ConfigEntry<float> SpottedFadeSeconds;

		public static ConfigEntry<float> SightScreenWidth;

		public static ConfigEntry<float> SightRange;

		public static ConfigEntry<float> OpenSpawnMinDistance;

		public static ConfigEntry<float> OpenSpawnMaxDistance;

		public static ConfigEntry<float> SafeSeconds;

		public static ConfigEntry<bool> FollowThroughPortals;

		public static ConfigEntry<float> FollowDelay;

		public static ConfigEntry<float> ColdRadius;

		public static ConfigEntry<float> StaminaRegenStopRadius;

		public static ConfigEntry<float> StaminaDrainRadius;

		public static ConfigEntry<float> CatchRadius;

		public static ConfigEntry<float> AuraCurve;

		public static ConfigEntry<float> MaxSlow;

		public static ConfigEntry<float> SlowCurve;

		public static ConfigEntry<float> StaminaDrain;

		public static ConfigEntry<float> ApproachMultiplier;

		public static ConfigEntry<float> FireQuenchBeyondCold;

		public static ConfigEntry<bool> WeatherEnabled;

		public static ConfigEntry<string> WeatherEnvironment;

		public static ConfigEntry<bool> WatcherFog;

		public static ConfigEntry<int> WatcherFogFromSightings;

		public static ConfigEntry<float> WatcherFogLinger;

		public static ConfigEntry<float> WeatherFade;

		public static ConfigEntry<float> FogGlow;

		public static ConfigEntry<bool> FoliageFrostEnabled;

		public static ConfigEntry<float> WatcherFrostRadius;

		public static ConfigEntry<float> FrostStrength;

		public static ConfigEntry<Color> FrostColor;

		public static ConfigEntry<string> MildBiomes;

		public static ConfigEntry<float> WatcherGlow;

		public static ConfigEntry<float> HunterGlow;

		public static ConfigEntry<float> MildFrostFactor;

		public static ConfigEntry<float> FaceRevealNear;

		public static ConfigEntry<float> FaceRevealFar;

		public static ConfigEntry<float> SmileRevealNear;

		public static ConfigEntry<float> SmileRevealFar;

		public static ConfigEntry<float> HunterSmileRevealNear;

		public static ConfigEntry<float> HunterSmileRevealFar;

		public static ConfigEntry<float> HemSway;

		public static ConfigEntry<bool> TrailEnabled;

		public static ConfigEntry<float> TrailLifetime;

		public static ConfigEntry<float> FootprintSize;

		public static ConfigEntry<float> AudioVolume;

		public static ConfigEntry<float> AudioRange;

		public static ConfigEntry<bool> SoundsEnabled;

		public static ConfigEntry<float> VoiceVolume;

		public static ConfigEntry<float> MoveVolume;

		public static ConfigEntry<float> BreathVolume;

		public static ConfigEntry<float> DespawnVolume;

		public static void Bind(ConfigFile cfg)
		{
			//IL_096b: Unknown result type (might be due to invalid IL or missing references)
			SpawnCheckInterval = Synced(cfg, "1 - Spawning", "CheckInterval", 30f, "Seconds between server spawn rolls per player.");
			ForceEveryNight = Synced(cfg, "1 - Spawning", "TestForceEveryNight", value: false, "TESTING: when night falls, always start a hunt (or Watchers if hunts are off), ignoring chances and cooldowns.");
			DeepNorthDaytime = Synced(cfg, "1 - Spawning", "DeepNorthDaytime", value: true, "Allow Hufsa to appear during the day in the Deep North.");
			WatcherEnabled = Synced(cfg, "1 - Spawning", "WatcherEnabled", value: true, "Enable the distant staring Hufsa.");
			WatcherChance = Synced(cfg, "1 - Spawning", "WatcherChanceEachRoll", 0.08f, "Chance per roll (every CheckInterval) that a Watcher appears, on top of the one guaranteed per night.");
			WatcherEveryNight = Synced(cfg, "1 - Spawning", "WatcherEveryNight", value: true, "Every player gets at least one Watcher each night (where a Watcher can appear), at a random time early in the night.");
			WatcherGuaranteeWithin = Synced(cfg, "1 - Spawning", "WatcherGuaranteeWithinSeconds", 240f, "The guaranteed Watcher comes at a random moment within this many seconds after nightfall.");
			WatcherCooldown = Synced(cfg, "1 - Spawning", "WatcherMinSecondsBetween", 300f, "Minimum seconds between Watchers for the same player.");
			WatcherEscalation = Synced(cfg, "1 - Spawning", "WatcherEscalation", 0.5f, "Each sighting a player has makes Watchers this much more likely (0.5 = +50% per sighting), sooner and closer.");
			SightingsForHunt = Synced(cfg, "1 - Spawning", "SightingsBeforeHunt", 6, "After this many real sightings of a Watcher, Hufsa hunts that player on the next night they can be hunted.");
			DreadDecayDays = Synced(cfg, "1 - Spawning", "SightingDecayDays", 2, "One sighting is forgotten after this many in-game days without seeing one.");
			WatcherMinDistance = Synced(cfg, "1 - Spawning", "WatcherSpawnMinDistanceFar", 60f, "Closest a Watcher appears (m). Keep it above VanishDistanceOpen.");
			WatcherMaxDistance = Synced(cfg, "1 - Spawning", "WatcherSpawnMaxDistanceFar", 95f, "Furthest a Watcher appears (m) among trees.");
			OpenSpawnMinDistance = Synced(cfg, "1 - Spawning", "OpenSpawnMinDistanceFar", 125f, "On open land (no trees within 30 m) it appears this far away (m) or more; scales with how open it is.");
			OpenSpawnMaxDistance = Synced(cfg, "1 - Spawning", "OpenSpawnMaxDistanceFar", 170f, "...and at most this far. Each sighting brings the next one closer, down to about half before a hunt.");
			HunterEnabled = Synced(cfg, "1 - Spawning", "HunterEnabled", value: true, "Enable the hunting Hufsa.");
			HunterChance = Synced(cfg, "1 - Spawning", "RandomHuntChance", 0f, "Chance per roll of a hunt with no warning. 0 = hunts only come after enough Watcher sightings.");
			HunterCooldownMinutes = Synced(cfg, "1 - Spawning", "HunterCooldownMinutes", 20f, "Minimum real minutes between Hunter spawns.");
			HunterMinDistance = Synced(cfg, "1 - Spawning", "HunterMinDistance", 45f, "");
			HunterMaxDistance = Synced(cfg, "1 - Spawning", "HunterMaxDistance", 65f, "");
			WatcherVanishDistance = Synced(cfg, "2 - Watcher", "VanishDistanceOpen", 35f, "It leaves when a player comes this close (m) across open ground (nothing between you).");
			WatcherVanishDense = Synced(cfg, "2 - Watcher", "VanishDistanceDense", 14f, "...and this close (m) when trees and rocks stand between you (4 or more). In between, it scales.");
			SpottedFadeSeconds = Synced(cfg, "2 - Watcher", "FadeAfterSpottedDelay", 0.2f, "Once you have really spotted it, it fades away this many seconds later (0 = stays).");
			WatcherLifetime = Synced(cfg, "2 - Watcher", "LifetimeSeconds", 180f, "The Watcher vanishes after this long.");
			WatcherBlinks = Synced(cfg, "2 - Watcher", "Blinks", 3, "Times the Watcher moves somewhere else (just outside your view, a little closer) when you look away, before it leaves for good.");
			WatcherLookAwaySeconds = Synced(cfg, "2 - Watcher", "LookAwaySeconds", 1.2f, "How long you must look away (after having seen it) before it moves or leaves.");
			WatcherHidesBehindCover = Synced(cfg, "2 - Watcher", "VanishWhenViewBlocked", value: false, "If a tree, rock or building blocks your view of it while you are within 70 m, it is gone when you look again. Off by default: it tended to vanish before you could properly look at it. Walking up to it still makes it leave.");
			SightSeconds = Synced(cfg, "2 - Watcher", "SightSecondsRequired", 0.5f, "How long it must be in the middle of your screen, with nothing in the way, to count as a sighting.");
			SightScreenWidth = Synced(cfg, "2 - Watcher", "SightScreenWidth", 1f / 3f, "How much of the screen's width, around the centre, counts as looking at it (0.33 = the middle third).");
			SightRange = Synced(cfg, "2 - Watcher", "SightRange", 180f, "Furthest away (m) a sighting can count.");
			DreadMessages = cfg.Bind<bool>("2 - Watcher", "SightingMessages", true, "Show a quiet line of text (top left) when you spot a Watcher, growing more ominous as a hunt nears.");
			WatcherDayBiomes = Synced(cfg, "2 - Watcher", "DayBiomesAnyWeather", "Swamp,Mountain,Mistlands,DeepNorth", "Biomes where the Watcher may also appear by day, in any weather. It never appears in the Ashlands.");
			WatcherBadWeatherBiomes = Synced(cfg, "2 - Watcher", "DayBiomesBadWeather", "Meadows,BlackForest,Plains", "Biomes where the Watcher may appear by day only in storm or fog.");
			BadWeatherKeywords = Synced(cfg, "2 - Watcher", "BadWeatherKeywords", "storm,thunder,mist,fog", "A weather counts as storm or fog when its name contains one of these (console: 'hufsa weather' shows the current one).");
			MistlandsMinDistance = Synced(cfg, "2 - Watcher", "LowVisibilityMinDistance", 40f, "In low visibility (the Mistlands, or daytime storm/fog anywhere) it stands a bit closer than usual.");
			MistlandsMaxDistance = Synced(cfg, "2 - Watcher", "LowVisibilityMaxDistance", 60f, "");
			MistlandsVanishDistance = Synced(cfg, "2 - Watcher", "LowVisibilityVanishDistance", 18f, "In low visibility you can get this close before it leaves.");
			WoodedBiomes = Synced(cfg, "2 - Watcher", "WoodedBiomes", "Meadows,BlackForest,Swamp,Mistlands", "Biomes where the Watcher only stands between trees or on a hilltop. Elsewhere any spot you can see it from will do.");
			DenseBiomes = Synced(cfg, "2 - Watcher", "DenseBiomes", "Swamp,Mistlands", "Biomes so full of trees and roots that cover blocks your view all the time.");
			DenseCoverBlocks = Synced(cfg, "2 - Watcher", "DenseCoverBlocks", 4, "In dense biomes it only vanishes after cover has blocked your view this many times (elsewhere: once). Looking away still counts as normal.");
			LookAwayVanishChance = Synced(cfg, "2 - Watcher", "LookAwayVanishChance", 0.5f, "Each time you look away, the chance it is simply gone instead of moving somewhere else.");
			RespawnAfterVanish = Synced(cfg, "2 - Watcher", "RespawnAfterVanishSeconds", 30f, "When it vanishes because you looked away or hid behind cover, a new Watcher comes back for you after this long (if it's still Watcher time).");
			HunterSpeed = Synced(cfg, "3 - Hunter", "CloseSpeed", 1.9f, "Glide speed when close (player walk is ~1.6, run ~7).");
			HunterCloseDistance = Synced(cfg, "3 - Hunter", "CloseDistance", 15f, "Within this distance (m) it glides at the slow Speed.");
			HunterSpeedScale = Synced(cfg, "3 - Hunter", "SpeedScale", 40f, "Beyond CloseDistance its speed grows exponentially: Speed x e^((distance - CloseDistance) / SpeedScale). Lower = faster catch-up.");
			HunterMaxSpeed = Synced(cfg, "3 - Hunter", "MaxSpeed", 5.5f, "Top speed (m/s). A fresh player runs ~7, so you can pull away while your stamina lasts, but not by walking.");
			EscapeDistance = Synced(cfg, "3 - Hunter", "WarningDistance", 110f, "Players within this distance (m) of a Hunter when it appears get the \"Someone is hunting you!\" warning. Distance never ends a hunt: if you outrun it, it comes after you again (FollowDelaySeconds).");
			LungeSpeed = Synced(cfg, "3 - Hunter", "RushSpeed", 11f, "When the Watcher you kept seeing turns on you, it bursts at you this fast (m/s; a running player does ~7).");
			LungeSeconds = Synced(cfg, "3 - Hunter", "RushSeconds", 1.2f, "How long the burst lasts at full speed.");
			RushEaseOut = Synced(cfg, "3 - Hunter", "RushEaseOutSeconds", 2.5f, "How long it takes to ease smoothly from the rush back into the normal chase.");
			LungeStopDistance = Synced(cfg, "3 - Hunter", "RushStopDistance", 25f, "It stops rushing once this close (m), so the burst can't carry it all the way to you.");
			WaterSpeedFactor = Synced(cfg, "3 - Hunter", "WaterSpeedFactor", 0.6f, "Its speed while gliding across rivers and lakes, as a fraction of its chase speed (the swamp is full of water).");
			ClimbSpeed = Synced(cfg, "3 - Hunter", "ClimbSpeed", 0.7f, "How fast (m/s) it climbs up rocks, cliffs and steep slopes after you. Slow, so you have time to think.");
			SafeSeconds = Synced(cfg, "3 - Hunter", "SafePlaceSeconds", 60f, "Shelter is the only way out: if everyone is indoors, in bed, in a dungeon, on a boat or at sea for this long, it leaves (and goes after another player if there is one).");
			SafeCloseDistance = Synced(cfg, "3 - Hunter", "SafeCloseDistance", 7f, "...or sooner: if it has come right up to the shelter (within this many m) and can't get closer...");
			SafeCloseSeconds = Synced(cfg, "3 - Hunter", "SafeCloseSeconds", 10f, "...for this many seconds.");
			FollowThroughPortals = Synced(cfg, "3 - Hunter", "FollowWhenLost", value: true, "If it loses you (you outran it, or used a portal), it comes for you again after FollowDelaySeconds.");
			FollowDelay = Synced(cfg, "3 - Hunter", "FollowDelaySeconds", 20f, "");
			RetargetAfterDeathRadius = Synced(cfg, "3 - Hunter", "RetargetAfterDeathRadius", 1000f, "When its prey dies, it goes after another player within this distance (m) of where they died; otherwise the hunt ends.");
			ColdRadius = Synced(cfg, "4 - Aura", "ColdRadius", 80f, "Outer cold: snow weather, frost, slow and reduced stamina regen.");
			StaminaRegenStopRadius = Synced(cfg, "4 - Aura", "StaminaRegenStopRadius", 20f, "Stamina regen slows across the cold radius and stops completely within this distance (m).");
			StaminaDrainRadius = Synced(cfg, "4 - Aura", "StaminaDrainRadius", 10f, "Within this distance (m) stamina is drained.");
			CatchRadius = Synced(cfg, "4 - Aura", "CatchRadius", 2.2f, "If the Hunter gets this close (m, from its centre) it catches you and you die. It never hurts you otherwise.");
			AuraCurve = Synced(cfg, "4 - Aura", "Curve", 1.5f, "Higher = effects ramp up later / closer.");
			MaxSlow = Synced(cfg, "4 - Aura", "MaxSlow", 0.7f, "Walk, jog and sprint slow at point blank (0.7 = -70%), scaled over the cold radius.");
			SlowCurve = Synced(cfg, "4 - Aura", "SlowCurve", 1f, "1 = slows steadily from the edge of the cold to point blank; higher = mostly when close.");
			StaminaDrain = Synced(cfg, "4 - Aura", "StaminaDrainPerSec", 12f, "Stamina drained per second at point blank.");
			ApproachMultiplier = Synced(cfg, "4 - Aura", "ApproachMultiplier", 2f, "Stamina drain multiplier while moving toward Hufsa.");
			FireQuenchBeyondCold = Synced(cfg, "4 - Aura", "FireQuenchBeyondCold", 10f, "Fires go out (like in rain) everywhere in the cold radius plus this many metres. -1 = off.");
			WeatherEnabled = cfg.Bind<bool>("5 - Visuals", "WeatherEnabled", true, "Force snowy weather while inside the Hunter's cold radius.");
			WeatherEnvironment = cfg.Bind<string>("5 - Visuals", "WeatherEnvironment", "Snow", "Environment name to force (e.g. Snow, SnowStorm, Twilight_Snow).");
			WatcherFog = cfg.Bind<bool>("5 - Visuals", "WatcherFog", true, "While a Watcher is about, bring the biome's own fog (where the biome has a misty weather).");
			WatcherFogFromSightings = cfg.Bind<int>("5 - Visuals", "WatcherFogFromSightings", 4, "...once you have this many sightings (dread). 0 = always.");
			WeatherFade = cfg.Bind<float>("5 - Visuals", "WeatherFadeSeconds", 15f, "How slowly Hufsa's fog and snow roll in and lift again (seconds), like the game's own weather changes but longer.");
			WatcherFogLinger = cfg.Bind<float>("5 - Visuals", "WatcherFogLingerSeconds", 240f, "The fog stays this long after the last Watcher has gone, so it doesn't flicker on and off as Watchers come and go.");
			FogGlow = cfg.Bind<float>("5 - Visuals", "SilhouetteGlowInFog", 0.1f, "How much of the silhouette glow is left in misty or foggy weather (1 = all, 0 = none): in fog the glow would give Hufsa away.");
			FoliageFrostEnabled = cfg.Bind<bool>("5 - Visuals", "FoliageFrostEnabled", true, "Tint nearby trees, bushes and rocks frosty.");
			WatcherFrostRadius = cfg.Bind<float>("5 - Visuals", "WatcherFrostRadius", 14f, "");
			FrostStrength = cfg.Bind<float>("5 - Visuals", "FrostStrength", 0.75f, "0-1 how strongly vegetation is tinted.");
			FrostColor = cfg.Bind<Color>("5 - Visuals", "FrostColor", new Color(0.82f, 0.9f, 1f), "");
			WatcherGlow = cfg.Bind<float>("5 - Visuals", "WatcherSilhouetteGlow", 0.45f, "Faint glow along the Watcher's outline, fading inward (0 = off).");
			HunterGlow = cfg.Bind<float>("5 - Visuals", "HunterSilhouetteGlow", 0.45f, "Faint glow along the Hunter's outline, fading inward (0 = off).");
			MildBiomes = cfg.Bind<string>("5 - Visuals", "MildBiomes", "Meadows,BlackForest", "Biomes where Hufsa brings no snowfall (no falling snow around it, no snowy weather) and less frost.");
			MildFrostFactor = cfg.Bind<float>("5 - Visuals", "MildFrostFactor", 0.4f, "How strong the frost on plants and the frozen trail is in the mild biomes (1 = same as elsewhere).");
			SmileRevealFar = cfg.Bind<float>("5 - Visuals", "WatcherSmileRevealFar", 80f, "Watcher: distance (m) where the grin starts fading in. It stands 60-100 m away and leaves at ~25 m.");
			SmileRevealNear = cfg.Bind<float>("5 - Visuals", "WatcherSmileRevealNear", 40f, "Watcher: distance (m) where the grin is fully visible.");
			HunterSmileRevealFar = cfg.Bind<float>("5 - Visuals", "HunterSmileRevealFar", 60f, "Hunter: distance (m) where the grin starts fading in.");
			HunterSmileRevealNear = cfg.Bind<float>("5 - Visuals", "HunterSmileRevealNear", 25f, "Hunter: distance (m) where the grin is fully visible.");
			FaceRevealFar = cfg.Bind<float>("5 - Visuals", "FaceRevealFar", 22f, "Distance (m) where the pupils and nose start to appear.");
			FaceRevealNear = cfg.Bind<float>("5 - Visuals", "FaceRevealNear", 6f, "Distance (m) where the pupils and nose are fully visible.");
			HemSway = cfg.Bind<float>("5 - Visuals", "HemMovement", 1f, "How much the hem moves while the Hunter glides (0 = stiff).");
			TrailEnabled = cfg.Bind<bool>("5 - Visuals", "FrozenTrail", true, "Leave frost patches and footprints behind the Hunter.");
			TrailLifetime = cfg.Bind<float>("5 - Visuals", "FrozenTrailSeconds", 25f, "How long frost patches and footprints last.");
			FootprintSize = cfg.Bind<float>("5 - Visuals", "FootprintLength", 0.45f, "Footprint length in metres.");
			AudioVolume = cfg.Bind<float>("6 - Audio", "Volume", 0.8f, "Volume of Hufsa loop at point blank.");
			AudioRange = cfg.Bind<float>("6 - Audio", "HunterRange", 45f, "Distance (m) at which the Hunter's loop starts fading in. Only the Hunter has music.");
			SoundsEnabled = cfg.Bind<bool>("6 - Audio", "Sounds", true, "Voice, footsteps and creaks from the 'sounds' folder next to the mod (voice*, step*, creak* files).");
			VoiceVolume = cfg.Bind<float>("6 - Audio", "VoiceVolume", 1f, "");
			MoveVolume = cfg.Bind<float>("6 - Audio", "MovementVolume", 0.8f, "Footsteps and creaks.");
			BreathVolume = cfg.Bind<float>("6 - Audio", "WatcherBreathVolume", 1f, "The Watcher's breathing, heard now and then while it stands behind you (breath* files).");
			DespawnVolume = cfg.Bind<float>("6 - Audio", "DespawnVolume", 1f, "Hufsa leaving (despawn* files). Heard only within the Watcher's leave distance, up to 40% louder up close.");
		}

		private static ConfigEntry<T> Synced<T>(ConfigFile cfg, string section, string key, T value, string description)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			return cfg.Bind<T>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
		}
	}
	internal class HufsaDebug : MonoBehaviour
	{
		private const float TestRespawnSeconds = 10f;

		private const float SpotSpacing = 8f;

		private const int MaxPreviews = 400;

		internal static HufsaDebug Instance;

		private bool testMode;

		private HufsaEntity current;

		private PinData pin;

		private Vector3 pinPos;

		private bool hadCurrent;

		private float nextSpawnAt;

		private readonly List<GameObject> previews = new List<GameObject>();

		private float previewTimer;

		public static bool TestMode
		{
			get
			{
				if (Object.op_Implicit((Object)(object)Instance))
				{
					return Instance.testMode;
				}
				return false;
			}
		}

		private void Awake()
		{
			Instance = this;
		}

		public void ToggleTestMode()
		{
			testMode = !testMode;
			current = null;
			ClearPin();
			hadCurrent = false;
			nextSpawnAt = Time.time;
			Say(testMode ? ("Test mode ON: a Watcher now, and another 10 s after each one is gone. Sightings " + Sightings() + ".") : "Test mode OFF.");
		}

		public static void OnSpotted(int count)
		{
			if (TestMode)
			{
				Instance.Say($"SPOTTED! Sightings {count}/{HufsaConfig.SightingsForHunt.Value}", center: true);
			}
		}

		public static void OnHuntStarted()
		{
			if (TestMode)
			{
				Instance.testMode = false;
				Instance.ClearPin();
				Instance.Say("The last one turned on you: hunt started. Test mode OFF.", center: true);
			}
		}

		private static string Sightings()
		{
			return $"{(Object.op_Implicit((Object)(object)HufsaDread.Instance) ? HufsaDread.Instance.Count : 0)}/{HufsaConfig.SightingsForHunt.Value}";
		}

		private void UpdateTestMode()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			if (!testMode || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || HufsaEntity.AnyHunterLoaded())
			{
				return;
			}
			if (Object.op_Implicit((Object)(object)current) && !current.Vanishing)
			{
				UpdatePin(((Component)current).transform.position);
				return;
			}
			if (hadCurrent)
			{
				hadCurrent = false;
				ClearPin();
				nextSpawnAt = Time.time + 10f;
				Say($"Watcher gone. Next one in {10f:0} s.");
			}
			if (!(Time.time < nextSpawnAt))
			{
				current = HufsaSpawner.SpawnNearLocalPlayer("Hufsa_Watcher", force: true);
				if (Object.op_Implicit((Object)(object)current))
				{
					hadCurrent = true;
					float num = Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)current).transform.position);
					UpdatePin(((Component)current).transform.position);
					Say($"Watcher spawned {num:0} m away (pinned on the map). Sightings {Sightings()}.");
				}
				else
				{
					nextSpawnAt = Time.time + 3f;
					Say("No spot for a Watcher here, trying again in 3 s.");
				}
			}
		}

		private void UpdatePin(Vector3 at)
		{
			//IL_003d: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0015: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)Minimap.instance))
			{
				return;
			}
			if (pin != null)
			{
				Vector3 val = at - pinPos;
				if (((Vector3)(ref val)).sqrMagnitude < 4f)
				{
					return;
				}
			}
			ClearPin();
			pin = Minimap.instance.AddPin(at, (PinType)3, "Hufsa", false, false, 0L, default(PlatformUserID));
			pinPos = at;
		}

		private void ClearPin()
		{
			if (pin != null && Object.op_Implicit((Object)(object)Minimap.instance))
			{
				Minimap.instance.RemovePin(pin);
			}
			pin = null;
		}

		public void ToggleSpots()
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: 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_0177: 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_0183: 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_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Invalid comparison between Unknown and I4
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			if (previews.Count > 0)
			{
				ClearPreviews();
				Say("Spot previews cleared.");
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			Camera val = (Object.op_Implicit((Object)(object)GameCamera.instance) ? ((Component)GameCamera.instance).GetComponent<Camera>() : Camera.main);
			GameObject val2 = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.GetPrefab("Hufsa_Watcher") : null);
			Transform val3 = (Object.op_Implicit((Object)(object)val2) ? val2.transform.Find("HufsaVisual") : null);
			if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val3))
			{
				return;
			}
			Vector3 position = ((Component)localPlayer).transform.position;
			Vector3 position2 = ((Component)val).transform.position;
			bool num = HufsaEntity.LowVisibility(position);
			float num2 = (num ? 0f : HufsaEntity.Openness(position));
			float num3 = (num ? HufsaConfig.MistlandsMinDistance.Value : Mathf.Lerp(HufsaConfig.WatcherMinDistance.Value, HufsaConfig.OpenSpawnMinDistance.Value, num2));
			float num4 = (num ? HufsaConfig.MistlandsMaxDistance.Value : Mathf.Lerp(HufsaConfig.WatcherMaxDistance.Value, HufsaConfig.OpenSpawnMaxDistance.Value, num2));
			int num5 = 0;
			float num8 = default(float);
			for (float num6 = num3; num6 <= num4 + 0.01f; num6 += 8f)
			{
				if (previews.Count >= 400)
				{
					break;
				}
				int num7 = Mathf.Max(8, Mathf.CeilToInt((float)Math.PI * 2f * num6 / 8f));
				for (int i = 0; i < num7; i++)
				{
					if (previews.Count >= 400)
					{
						break;
					}
					num5++;
					Vector3 val4 = position + Quaternion.Euler(0f, (float)i * 360f / (float)num7, 0f) * Vector3.forward * num6;
					if (ZoneSystem.instance.GetGroundHeight(val4, ref num8) && !(num8 < ZoneSystem.instance.m_waterLevel + 0.3f))
					{
						val4.y = num8;
						if ((int)HufsaEntity.BiomeAt(val4) != 32 && !Object.op_Implicit((Object)(object)EffectArea.IsPointInsideArea(val4, (Type)4, 5f)) && HufsaSpawner.IsGoodWatcherSpot(val4, position2, out var _))
						{
							previews.Add(MakePreview(((Component)val3).gameObject, val4, position));
						}
					}
				}
			}
			Say($"{previews.Count} possible Watcher spots {num3:0}-{num4:0} m around you ({num5} checked). " + "Walk toward them; run the command again to clear.");
		}

		private static GameObject MakePreview(GameObject visual, Vector3 at, Vector3 lookAt)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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_002b: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = lookAt - at;
			val.y = 0f;
			GameObject val2 = Object.Instantiate<GameObject>(visual, at, (((Vector3)(ref val)).sqrMagnitude > 0.01f) ? Quaternion.LookRotation(val) : Quaternion.identity);
			((Object)val2).name = "HufsaSpotPreview";
			ParticleSystem[] componentsInChildren = val2.GetComponentsInChildren<ParticleSystem>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.Destroy((Object)(object)((Component)componentsInChildren[i]).gameObject);
			}
			SilhouetteGlow[] componentsInChildren2 = val2.GetComponentsInChildren<SilhouetteGlow>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.Destroy((Object)(object)((Component)componentsInChildren2[i]).gameObject);
			}
			return val2;
		}

		private void UpdatePreviews()
		{
			//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_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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			if (previews.Count == 0)
			{
				return;
			}
			previewTimer -= Time.deltaTime;
			if (previewTimer > 0f)
			{
				return;
			}
			previewTimer = 0.15f;
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer))
			{
				ClearPreviews();
				return;
			}
			Vector3 playerEye = ((Component)localPlayer).transform.position + Vector3.up * 1.6f;
			float value = HufsaConfig.WatcherVanishDistance.Value;
			for (int num = previews.Count - 1; num >= 0; num--)
			{
				GameObject val = previews[num];
				if (!Object.op_Implicit((Object)(object)val))
				{
					previews.RemoveAt(num);
				}
				else
				{
					float num2 = Vector3.Distance(val.transform.position, ((Component)localPlayer).transform.position);
					if (!(num2 > value + 1f) && num2 < HufsaEntity.WatcherVanishDistance(val.transform.position, playerEye))
					{
						Object.Destroy((Object)(object)val);
						previews.RemoveAt(num);
					}
				}
			}
		}

		private void ClearPreviews()
		{
			foreach (GameObject preview in previews)
			{
				if (Object.op_Implicit((Object)(object)preview))
				{
					Object.Destroy((Object)(object)preview);
				}
			}
			previews.Clear();
		}

		private void Update()
		{
			UpdateTestMode();
			UpdatePreviews();
		}

		private void Say(string text, bool center = false)
		{
			HufsaPlugin.Log.LogInfo((object)("[debug] " + text));
			if (Object.op_Implicit((Object)(object)MessageHud.instance))
			{
				MessageHud.instance.ShowMessage((MessageType)((!center) ? 1 : 2), "<color=#9FD4FF>[Hufsa debug] " + text + "</color>", 0, (Sprite)null, false, true);
			}
		}
	}
	internal class HufsaDread : MonoBehaviour
	{
		public const string RpcDread = "Hufsa_Dread";

		public const string RpcDreadReset = "Hufsa_DreadReset";

		private const string CountKey = "hufsa_dread";

		private const string DayKey = "hufsa_dread_day";

		internal static HufsaDread Instance;

		private Player loadedFor;

		private int lastDay;

		private int lastReported = -1;

		private float reportTimer;

		public int Count { get; private set; }

		private void Awake()
		{
			Instance = this;
		}

		internal static void RegisterRpcs()
		{
			ZRoutedRpc.instance.Register("Hufsa_DreadReset", (Action<long>)delegate
			{
				Instance?.ResetAfterHunt();
			});
		}

		private void Update()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer))
			{
				loadedFor = null;
				return;
			}
			if ((Object)(object)localPlayer != (Object)(object)loadedFor)
			{
				Load(localPlayer);
			}
			Decay();
			reportTimer -= Time.deltaTime;
			if (Count != lastReported || reportTimer <= 0f)
			{
				Report();
			}
		}

		private void Load(Player p)
		{
			loadedFor = p;
			string[] array = new string[2] { "hufsa_dread", "hufsa_dread_day" };
			foreach (string text in array)
			{
				string key = text.Replace("hufsa", "groke");
				if (!p.m_customData.ContainsKey(text) && p.m_customData.TryGetValue(key, out var value))
				{
					p.m_customData[text] = value;
				}
				p.m_customData.Remove(key);
			}
			Count = ((p.m_customData.TryGetValue("hufsa_dread", out var value2) && int.TryParse(value2, out var result)) ? result : 0);
			lastDay = ((p.m_customData.TryGetValue("hufsa_dread_day", out var value3) && int.TryParse(value3, out var result2)) ? result2 : Today());
			lastReported = -1;
		}

		private void Save()
		{
			if (Object.op_Implicit((Object)(object)loadedFor))
			{
				loadedFor.m_customData["hufsa_dread"] = Count.ToString();
				loadedFor.m_customData["hufsa_dread_day"] = lastDay.ToString();
			}
		}

		private static int Today()
		{
			if (!Object.op_Implicit((Object)(object)EnvMan.instance))
			{
				return 0;
			}
			return EnvMan.instance.GetDay();
		}

		private void Decay()
		{
			if (Count > 0 && Object.op_Implicit((Object)(object)EnvMan.instance))
			{
				int num = Mathf.Max(1, HufsaConfig.DreadDecayDays.Value);
				if (Today() - lastDay >= num)
				{
					Count--;
					lastDay = Today();
					Save();
				}
			}
		}

		public void AddSighting()
		{
			Count++;
			lastDay = Today();
			Save();
			HufsaPlugin.Log.LogInfo((object)$"Hufsa sighted ({Count}/{HufsaConfig.SightingsForHunt.Value})");
			ShowMessage();
		}

		public void SetCount(int n)
		{
			Count = Mathf.Max(0, n);
			lastDay = Today();
			Save();
		}

		public void ResetAfterHunt()
		{
			Count = 0;
			lastDay = Today();
			Save();
		}

		private void Report()
		{
			if (ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "Hufsa_Dread", new object[1] { Count });
				lastReported = Count;
				reportTimer = 60f;
			}
		}

		private void ShowMessage()
		{
			if (HufsaConfig.DreadMessages.Value && Object.op_Implicit((Object)(object)MessageHud.instance))
			{
				int num = Mathf.Max(1, HufsaConfig.SightingsForHunt.Value);
				string text = ((Count >= num) ? "It knows where you are." : ((Count == num - 1) ? "It is getting closer." : ((Count == 1) ? "You feel watched." : "Something is watching you.")));
				MessageHud.instance.ShowMessage((MessageType)1, "<color=#B9A6D9>" + text + "</color>", 0, (Sprite)null, false, true);
			}
		}
	}
	internal class HufsaEntity : MonoBehaviour
	{
		internal static readonly List<HufsaEntity> Instances = new List<HufsaEntity>();

		private const string VanishKey = "hufsa_vanish";

		private const string ForcedKey = "hufsa_forced";

		private const float VanishDuration = 1f;

		private const float ShrinkDuration = 0.35f;

		public bool IsHunter;

		internal ZNetView NView;

		private Transform visual;

		private Vector3 visualBasePos;

		private Vector3 visualBaseScale;

		private ParticleSystem[] particles;

		private float vanishTime = -1f;

		private readonly List<Material> pupilMats = new List<Material>();

		private readonly List<Material> toothMats = new List<Material>();

		private readonly List<Renderer> toothRenderers = new List<Renderer>();

		private Renderer noseRenderer;

		private RevealFader noseFader;

		private RevealFader armFader;

		private RevealFader fingerFader;

		private HufsaArms arms;

		private Mesh bodyMesh;

		private Vector3[] hemWork;

		private float motion;

		private bool hemDirty;

		private Vector3 lastPos;

		private ParticleSystem snowfall;

		private float biomeCheck;

		private const string FadeKey = "hufsa_fade";

		private const float FadeDuration = 0.5f;

		private float fadeTime = -1f;

		private readonly List<Material> fadeMats = new List<Material>();

		private readonly List<float> fadeBaseAlpha = new List<float>();

		private static readonly RaycastHit[] lineHits = (RaycastHit[])(object)new RaycastHit[32];

		private static readonly HashSet<Transform> lineRoots = new HashSet<Transform>();

		private static int obstacleMask = -1;

		private static readonly Collider[] openHits = (Collider[])(object)new Collider[256];

		private static readonly HashSet<TreeBase> openTrees = new HashSet<TreeBase>();

		private float spotTime;

		private bool spotted;

		private static int sightMask = -1;

		private float fadeRequestAt = -1f;

		private const string FadeOutRpc = "Hufsa_FadeOut";

		private const string BecomeHunterRpc = "Hufsa_BecomeHunter";

		private readonly float[] groundOffset = new float[49];

		private float groundTimer;

		private bool groundChanged;

		private bool onSlope;

		public bool Mild { get; private set; }

		public float GlideSpeed { get; private set; }

		public Vector3[] MovingBodyVertices
		{
			get
			{
				if (!hemDirty)
				{
					return null;
				}
				return hemWork;
			}
		}

		public bool Vanishing
		{
			get
			{
				if (!(vanishTime >= 0f))
				{
					return fadeTime >= 0f;
				}
				return true;
			}
		}

		public bool Forced
		{
			get
			{
				if (Object.op_Implicit((Object)(object)NView) && NView.IsValid())
				{
					return NView.GetZDO().GetBool("hufsa_forced", false);
				}
				return false;
			}
		}

		public int DreadAtArrival { get; private set; } = -1;

		public float FadeAlpha { get; private set; } = 1f;

		public float FrostFactor
		{
			get
			{
				if (!Mild)
				{
					return 1f;
				}
				return Mathf.Clamp01(HufsaConfig.MildFrostFactor.Value);
			}
		}

		public static bool PhotoHold => GameCamera.InFreeFly();

		private void Awake()
		{
			//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_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_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			NView = ((Component)this).GetComponent<ZNetView>();
			visual = ((Component)this).transform.Find("HufsaVisual");
			if (Object.op_Implicit((Object)(object)visual))
			{
				visualBasePos = visual.localPosition;
				visualBaseScale = visual.localScale;
				foreach (Transform item in visual)
				{
					Transform val = item;
					Renderer component = ((Component)val).GetComponent<Renderer>();
					if (Object.op_Implicit((Object)(object)component))
					{
						if (((Object)val).name == "Pupil")
						{
							pupilMats.Add(component.material);
						}
						else if (((Object)val).name == "Tooth")
						{
							toothMats.Add(component.material);
							toothRenderers.Add(component);
						}
						else if (((Object)val).name == "Nose")
						{
							noseRenderer = component;
						}
					}
				}
				if (HufsaModel.BodyRest != null)
				{
					Transform obj = visual.Find("Body");
					MeshFilter val2 = ((obj != null) ? ((Component)obj).GetComponent<MeshFilter>() : null);
					if (Object.op_Implicit((Object)(object)val2))
					{
						bodyMesh = val2.mesh;
						hemWork = (Vector3[])(object)new Vector3[HufsaModel.BodyRest.Length];
					}
				}
			}
			particles = ((Component)this).GetComponentsInChildren<ParticleSystem>();
			ParticleSystem[] array = particles;
			foreach (ParticleSystem val3 in array)
			{
				if (((Object)val3).name == "FrostSnow")
				{
					snowfall = val3;
				}
			}
			if (Object.op_Implicit((Object)(object)NView) && !IsHunter)
			{
				NView.Register("Hufsa_BecomeHunter", (Action<long>)delegate
				{
					if (NView.IsValid() && NView.IsOwner())
					{
						ZNetScene.instance.Destroy(((Component)this).gameObject);
					}
				});
				NView.Register("Hufsa_FadeOut", (Action<long>)delegate
				{
					if (NView.IsValid() && NView.IsOwner())
					{
						VanishSilently();
					}
				});
			}
			lastPos = ((Component)this).transform.position;
			Instances.Add(this);
		}

		private void Start()
		{
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			if (!IsHunter && Object.op_Implicit((Object)(object)HufsaDread.Instance))
			{
				DreadAtArrival = HufsaDread.Instance.Count;
			}
			if (Object.op_Implicit((Object)(object)noseRenderer))
			{
				noseFader = new RevealFader(new List<Renderer> { noseRenderer });
			}
			arms = ((Component)this).GetComponent<HufsaArms>();
			if (Object.op_Implicit((Object)(object)arms))
			{
				armFader = new RevealFader(arms.ArmRenderers);
				fingerFader = new RevealFader(arms.FingerRenderers);
			}
			UpdateReveal();
			if (IsHunter && Object.op_Implicit((Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)MessageHud.instance) && (!Object.op_Implicit((Object)(object)NView) || !NView.IsValid() || !NView.GetZDO().GetBool("hufsa_vanish", false)) && !(Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)this).transform.position) > HufsaConfig.EscapeDistance.Value))
			{
				MessageHud.instance.ShowMessage((MessageType)2, "<color=#E0301E>Someone is hunting you!</color>", 0, (Sprite)null, false, true);
			}
		}

		private void OnDestroy()
		{
			Instances.Remove(this);
			foreach (Material pupilMat in pupilMats)
			{
				if (Object.op_Implicit((Object)(object)pupilMat))
				{
					Object.Destroy((Object)(object)pupilMat);
				}
			}
			foreach (Material toothMat in toothMats)
			{
				if (Object.op_Implicit((Object)(object)toothMat))
				{
					Object.Destroy((Object)(object)toothMat);
				}
			}
			foreach (Material fadeMat in fadeMats)
			{
				if (Object.op_Implicit((Object)(object)fadeMat))
				{
					Object.Destroy((Object)(object)fadeMat);
				}
			}
			noseFader?.Destroy();
			armFader?.Destroy();
			fingerFader?.Destroy();
			if (Object.op_Implicit((Object)(object)bodyMesh))
			{
				Object.Destroy((Object)(object)bodyMesh);
			}
		}

		public void MarkForced()
		{
			if (Object.op_Implicit((Object)(object)NView) && NView.IsValid())
			{
				NView.GetZDO().Set("hufsa_forced", true);
			}
		}

		public void Vanish()
		{
			if (Object.op_Implicit((Object)(object)NView) && NView.IsValid() && NView.IsOwner())
			{
				NView.GetZDO().Set("hufsa_vanish", true);
			}
		}

		public void VanishSilently()
		{
			if (Object.op_Implicit((Object)(object)NView) && NView.IsValid() && NView.IsOwner())
			{
				NView.GetZDO().Set("hufsa_fade", true);
			}
		}

		private void BeginFade()
		{
			//IL_0011: 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)
			//IL_002e: 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_00b1: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			fadeTime = 0f;
			HufsaSoundBank.PlayDespawn(((Component)this).transform.position);
			ParticleSystem[] array = particles;
			for (int i = 0; i < array.Length; i++)
			{
				EmissionModule emission = array[i].emission;
				((EmissionModule)(ref emission)).enabled = false;
			}
			if (!Object.op_Implicit((Object)(object)visual))
			{
				return;
			}
			Renderer[] componentsInChildren = ((Component)visual).GetComponentsInChildren<Renderer>();
			foreach (Renderer val in componentsInChildren)
			{
				if (!(val is ParticleSystemRenderer) && !Object.op_Implicit((Object)(object)((Component)val).GetComponent<SilhouetteGlow>()))
				{
					Material val2 = val.material;
					if ((Object)(object)val2.shader != (Object)(object)HufsaPrefabs.SpriteShader && Object.op_Implicit((Object)(object)HufsaPrefabs.SpriteShader))
					{
						Material val3 = new Material(HufsaPrefabs.SpriteShader)
						{
							mainTexture = (val2.HasProperty("_MainTex") ? val2.mainTexture : null),
							color = (val2.HasProperty("_Color") ? val2.color : Color.white)
						};
						Object.Destroy((Object)(object)val2);
						val.material = val3;
						val2 = val3;
					}
					fadeMats.Add(val2);
					fadeBaseAlpha.Add(val2.color.a);
				}
			}
		}

		private void UpdateFade()
		{
			//IL_0060: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			if (fadeTime < 0f)
			{
				return;
			}
			fadeTime += Time.deltaTime;
			FadeAlpha = 1f - Mathf.Clamp01(fadeTime / 0.5f);
			for (int i = 0; i < fadeMats.Count; i++)
			{
				if (Object.op_Implicit((Object)(object)fadeMats[i]))
				{
					Color color = fadeMats[i].color;
					color.a = fadeBaseAlpha[i] * FadeAlpha;
					fadeMats[i].color = color;
				}
			}
			if (fadeTime >= 0.6f && NView.IsOwner())
			{
				ZNetScene.instance.Destroy(((Component)this).gameObject);
			}
		}

		public static Biome BiomeAt(Vector3 pos)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (WorldGenerator.instance == null)
			{
				return (Biome)0;
			}
			return WorldGenerator.instance.GetBiome(pos);
		}

		public static bool IsHufsaTime(Vector3 pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Invalid comparison between Unknown and I4
			Biome val = BiomeAt(pos);
			if ((int)val == 32)
			{
				return false;
			}
			if (EnvMan.IsNight())
			{
				return true;
			}
			if (HufsaConfig.DeepNorthDaytime.Value)
			{
				return (int)val == 64;
			}
			return false;
		}

		public static bool WatcherMayAppear(Vector3 pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			//IL_001f: 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)
			Biome val = BiomeAt(pos);
			if ((int)val == 32)
			{
				return false;
			}
			if (!EnvMan.IsNight() && !InList(HufsaConfig.WatcherDayBiomes.Value, val))
			{
				return InList(HufsaConfig.WatcherBadWeatherBiomes.Value, val);
			}
			return true;
		}

		public static bool IsWatcherTime(Vector3 pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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)
			if (!WatcherMayAppear(pos))
			{
				return false;
			}
			if (EnvMan.IsNight() || InList(HufsaConfig.WatcherDayBiomes.Value, BiomeAt(pos)))
			{
				return true;
			}
			return IsBadWeather();
		}

		public static string CurrentWeather()
		{
			if (!Object.op_Implicit((Object)(object)EnvMan.instance))
			{
				return "";
			}
			return EnvMan.instance.GetCurrentEnvironment()?.m_name ?? "";
		}

		public static bool IsBadWeather()
		{
			string text = CurrentWeather().ToLowerInvariant();
			if (text.Length == 0)
			{
				return false;
			}
			string[] array = HufsaConfig.BadWeatherKeywords.Value.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim().ToLowerInvariant();
				if (text2.Length > 0 && text.Contains(text2))
				{
					return true;
				}
			}
			return false;
		}

		public static bool IsDenseBiome(Vector3 pos)
		{
			//IL_000a: 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)
			return InList(HufsaConfig.DenseBiomes.Value, BiomeAt(pos));
		}

		public static bool IsWoodedBiome(Vector3 pos)
		{
			//IL_000a: 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)
			return InList(HufsaConfig.WoodedBiomes.Value, BiomeAt(pos));
		}

		public static bool IsMildBiome(Vector3 pos)
		{
			//IL_000a: 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)
			return InList(HufsaConfig.MildBiomes.Value, BiomeAt(pos));
		}

		private unsafe static bool InList(string list, Biome biome)
		{
			string[] array = list.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				if (string.Equals(array[i].Trim(), ((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString(), StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		public static bool LowVisibility(Vector3 pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			if ((int)BiomeAt(pos) != 512)
			{
				if (!EnvMan.IsNight())
				{
					return IsBadWeather();
				}
				return false;
			}
			return true;
		}

		public static int ObstaclesBetween(Vector3 a, Vector3 b)
		{
			//IL_0038: 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_003a: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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)
			if (obstacleMask < 0)
			{
				obstacleMask = LayerMask.GetMask(new string[4] { "Default", "static_solid", "Default_small", "piece" });
			}
			Vector3 val = b - a;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < 0.1f)
			{
				return 0;
			}
			int num = Physics.RaycastNonAlloc(a, val / magnitude, lineHits, magnitude, obstacleMask, (QueryTriggerInteraction)1);
			lineRoots.Clear();
			for (int i = 0; i < num; i++)
			{
				if (Object.op_Implicit((Object)(object)((RaycastHit)(ref lineHits[i])).collider))
				{
					lineRoots.Add(((Component)((RaycastHit)(ref lineHits[i])).collider).transform.root);
				}
			}
			return lineRoots.Count;
		}

		public static float WatcherVanishDistance(Vector3 watcherPos, Vector3 playerEye)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			int num = ObstaclesBetween(playerEye, watcherPos + Vector3.up * 1.5f);
			float num2 = Mathf.Lerp(HufsaConfig.WatcherVanishDistance.Value, HufsaConfig.WatcherVanishDense.Value, Mathf.Clamp01((float)num / 4f));
			if (LowVisibility(watcherPos))
			{
				num2 = Mathf.Min(num2, HufsaConfig.MistlandsVanishDistance.Value);
			}
			return num2;
		}

		public static float Openness(Vector3 pos)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (obstacleMask < 0)
			{
				obstacleMask = LayerMask.GetMask(new string[4] { "Default", "static_solid", "Default_small", "piece" });
			}
			int num = Physics.OverlapSphereNonAlloc(pos, 30f, openHits, obstacleMask, (QueryTriggerInteraction)1);
			openTrees.Clear();
			for (int i = 0; i < num; i++)
			{
				TreeBase val = (Object.op_Implicit((Object)(object)openHits[i]) ? ((Component)openHits[i]).GetComponentInParent<TreeBase>() : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					openTrees.Add(val);
				}
			}
			return 1f - Mathf.Clamp01((float)openTrees.Count / 8f);
		}

		public static float WatcherVanishDistanceAt(Vector3 pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (!LowVisibility(pos))
			{
				return HufsaConfig.WatcherVanishDistance.Value;
			}
			return HufsaConfig.MistlandsVanishDistance.Value;
		}

		public static bool AnyHunterWithin(Vector3 pos, float radius)
		{
			//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_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)
			foreach (HufsaEntity instance in Instances)
			{
				if (instance.IsHunter && !instance.Vanishing)
				{
					Vector3 val = ((Component)instance).transform.position - pos;
					if (((Vector3)(ref val)).sqrMagnitude < radius * radius)
					{
						return true;
					}
				}
			}
			return false;
		}

		public static bool AnyHunterLoaded()
		{
			foreach (HufsaEntity instance in Instances)
			{
				if (instance.IsHunter && !instance.Vanishing)
				{
					return true;
				}
			}
			return false;
		}

		public static Player FindNearestPlayer(Vector3 pos, out float distance)
		{
			//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)
			Player result = null;
			distance = float.MaxValue;
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				if (Object.op_Implicit((Object)(object)allPlayer) && !((Character)allPlayer).IsDead())
				{
					float num = Vector3.Distance(((Component)allPlayer).transform.position, pos);
					if (num < distance)
					{
						distance = num;
						result = allPlayer;
					}
				}
			}
			return result;
		}

		private void Update()
		{
			//IL_00f2: 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_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: 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_005e: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)NView) || !NView.IsValid())
			{
				return;
			}
			if (vanishTime < 0f && NView.GetZDO().GetBool("hufsa_vanish", false))
			{
				vanishTime = 0f;
				ParticleSystem[] array = particles;
				for (int i = 0; i < array.Length; i++)
				{
					EmissionModule emission = array[i].emission;
					((EmissionModule)(ref emission)).enabled = false;
				}
				HufsaPrefabs.SpawnVanishPuff(((Component)this).transform.position, visualBaseScale.x);
				HufsaSoundBank.PlayDespawn(((Component)this).transform.position);
			}
			if (vanishTime >= 0f && Object.op_Implicit((Object)(object)visual))
			{
				vanishTime += Time.deltaTime;
				float num = Mathf.Clamp01(vanishTime / 0.35f);
				float num2 = 1f - num * num;
				visual.localPosition = visualBasePos + new Vector3(0f, (1f - num2) * 1.2f * visualBaseScale.y, 0f);
				visual.localScale = visualBaseScale * num2;
			}
			if (fadeTime < 0f && vanishTime < 0f && NView.GetZDO().GetBool("hufsa_fade", false))
			{
				BeginFade();
			}
			UpdateBiome();
			UpdateHem();
			UpdateReveal();
			UpdateSighting();
			UpdateFadeRequest();
			UpdateFade();
			if (vanishTime >= 1f && NView.IsOwner())
			{
				ZNetScene.instance.Destroy(((Component)this).gameObject);
			}
		}

		private void UpdateSighting()
		{
			//IL_00b7: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//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_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_00dd: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			//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_0103: 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_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: 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_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be du