Decompiled source of TotemSentinel v1.5.2

TotemSentinel.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TotemSentinel.Commands;
using TotemSentinel.HUD;
using TotemSentinel.Services;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("TotemSentinel")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.5.2.0")]
[assembly: AssemblyInformationalVersion("1.5.2+2eadce900868234131b66f155718dc12e5871f67")]
[assembly: AssemblyProduct("TotemSentinel")]
[assembly: AssemblyTitle("TotemSentinel")]
[assembly: AssemblyVersion("1.5.2.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TotemSentinel
{
	[BepInPlugin("djcdevelopment.totemsentinel", "TotemSentinel", "1.5.2")]
	public sealed class TotemSentinelPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "djcdevelopment.totemsentinel";

		public const string PluginName = "TotemSentinel";

		public const string PluginVersion = "1.5.2";

		private const float ScanPulseInterval = 1f;

		public static ConfigEntry<int> MaxSonarCharges;

		public static ConfigEntry<int> MaxStoredSonarCharges;

		public static ConfigEntry<float> ScanRadius;

		public static ConfigEntry<KeyCode> PingHotkey;

		public static ConfigEntry<float> StateDuration;

		public static ConfigEntry<float> FinalSummaryDuration;

		public static ConfigEntry<float> GreedMultiplier;

		public static ConfigEntry<float> GreedDuration;

		public static ConfigEntry<KeyCode> GreedModifierKey;

		public static int ActiveSonarCharges = 0;

		public static Vector3 LastScanOrigin = Vector3.zero;

		private static bool _hasActiveSonarSession;

		private static bool _showAbilityPreview;

		private static bool _scanInProgress;

		private static float _scanStartedAt;

		private static float _nextScanPulseAt;

		private static long _scanCpuTicks;

		private static int _scanPulseCount;

		private static long _sessionWorldUid;

		private static bool _deathSuspended;

		private static bool _isGreedScan;

		private static float _greedUntil;

		private Harmony _harmony;

		private bool _patchesApplied;

		internal static bool HasActiveSonarSession => _hasActiveSonarSession;

		internal static bool IsGreedActive => Time.unscaledTime < _greedUntil;

		internal static int MaximumStoredSonarCharges
		{
			get
			{
				if (MaxStoredSonarCharges == null)
				{
					return 9;
				}
				return Math.Max(1, MaxStoredSonarCharges.Value);
			}
		}

		private void Awake()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Expected O, but got Unknown
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Expected O, but got Unknown
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Expected O, but got Unknown
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Expected O, but got Unknown
			MaxSonarCharges = ((BaseUnityPlugin)this).Config.Bind<int>("Sonar", "MaxSonarCharges", 3, new ConfigDescription("Number of camp checks granted by each Fuling Totem. Checks are spent only when the hotkey is pressed.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, int.MaxValue), Array.Empty<object>()));
			MaxStoredSonarCharges = ((BaseUnityPlugin)this).Config.Bind<int>("Sonar", "MaxStoredSonarCharges", 9, new ConfigDescription("Maximum number of camp checks that can be banked across multiple newly discovered Fuling Totems.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, int.MaxValue), Array.Empty<object>()));
			ScanRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Sonar", "ScanRadius", 64f, new ConfigDescription("Radius in metres around the picked-up Fuling Totem that is scanned for Fulings.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 128f), Array.Empty<object>()));
			PingHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "PingHotkey", (KeyCode)118, "Key used to spend another sonar charge while within range of the totem origin.");
			StateDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Interface", "StateDuration", 10f, new ConfigDescription("Seconds that scanning, result, and warning states remain visible.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 60f), Array.Empty<object>()));
			FinalSummaryDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Interface", "FinalSummaryDuration", 300f, new ConfigDescription("Seconds after the final scan before the completed camp-check card closes automatically.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 1800f), Array.Empty<object>()));
			GreedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Greed", "GreedMultiplier", 3f, new ConfigDescription("Multiplier applied to scan radius during Greed's Gambit wide loot searches.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1.5f, 5f), Array.Empty<object>()));
			GreedDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Greed", "GreedDuration", 35f, new ConfigDescription("Seconds that the Greed's Gambit cursed retribution window lasts after a wide search.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 120f), Array.Empty<object>()));
			GreedModifierKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "GreedModifierKey", (KeyCode)304, "Modifier key held while pressing PingHotkey to trigger Greed's Gambit wide loot search.");
			if (!SonarScanner.Initialize())
			{
				ZLog.LogError((object)"[TotemSentinel] Failed to initialize ZDO sector access; gameplay patches were not installed.");
				return;
			}
			try
			{
				_harmony = new Harmony("djcdevelopment.totemsentinel");
				_harmony.PatchAll(typeof(TotemSentinelPlugin).Assembly);
				TotemAlertCommands.Register();
				_patchesApplied = true;
				ZLog.Log((object)(string.Format("[{0}] Initialized with {1} charges per totem, ", "TotemSentinel", MaxSonarCharges.Value) + $"a {MaximumStoredSonarCharges}-charge storage cap, " + $"a {ScanRadius.Value:0.#}m radius, {StateDuration.Value:0.#}s states, " + $"and a {FinalSummaryDuration.Value:0.#}s final summary."));
			}
			catch (Exception arg)
			{
				ZLog.LogError((object)string.Format("[{0}] Failed to install Harmony patches: {1}", "TotemSentinel", arg));
			}
		}

		private void Update()
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			ZNet instance = ZNet.instance;
			if (_hasActiveSonarSession && (Object)(object)instance != (Object)null && _sessionWorldUid != 0L && instance.GetWorldUID() != _sessionWorldUid)
			{
				ZLog.Log((object)"[TotemSentinel] Cleared camp checks after the active world changed.");
				ResetSonarSession();
			}
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer))
			{
				if ((Object)(object)instance == (Object)null)
				{
					ResetSonarSession();
				}
				else
				{
					SuspendSonarForDeath();
				}
				return;
			}
			if (((Character)localPlayer).IsDead())
			{
				SuspendSonarForDeath();
				return;
			}
			ResumeSonarAfterDeath();
			if (_scanInProgress)
			{
				UpdateActiveScan(localPlayer);
			}
			else
			{
				if (!_hasActiveSonarSession || Console.IsVisible() || TextInput.IsVisible() || !Input.GetKeyDown(PingHotkey.Value))
				{
					return;
				}
				if (ActiveSonarCharges <= 0)
				{
					ZLog.Log((object)"[TotemSentinel] Ping rejected: no camp checks remain.");
					SonarPresenter.ShowNoChargesWarning();
					return;
				}
				if (!SonarAbilityPanel.CanBeginScan)
				{
					ZLog.Log((object)"[TotemSentinel] Ping ignored: the camp-check display is still presenting the previous state.");
					return;
				}
				bool key = Input.GetKey(GreedModifierKey.Value);
				float num = (key ? (ScanRadius.Value * GreedMultiplier.Value) : ScanRadius.Value);
				Vector3 val = ((Component)localPlayer).transform.position - LastScanOrigin;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				if (sqrMagnitude > num * num)
				{
					ZLog.Log((object)("[TotemSentinel] Ping rejected: out of range " + $"distance={Math.Sqrt(sqrMagnitude):0.0}m radius={num:0.0}m charges={ActiveSonarCharges}."));
					SonarPresenter.ShowOutOfRangeWarning();
				}
				else
				{
					StartActiveScan(key);
				}
			}
		}

		private void OnDestroy()
		{
			TotemAlertCommands.ClearTestScenario();
			ResetSonarSession();
			if (_patchesApplied)
			{
				_harmony.UnpatchSelf();
				_patchesApplied = false;
			}
		}

		private void OnGUI()
		{
			SonarAbilityPanel.Draw(_showAbilityPreview);
		}

		internal static bool SetAbilityPreview(bool? visible = null)
		{
			_showAbilityPreview = visible ?? (!_showAbilityPreview);
			return _showAbilityPreview;
		}

		internal static void GrantTotemSonar(Vector3 origin, int totemCount)
		{
			//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_00a8: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			if (totemCount > 0)
			{
				RestoreInterruptedScanCharge("a new totem was discovered");
				int num = (_hasActiveSonarSession ? ActiveSonarCharges : 0);
				long num2 = (long)Math.Max(1, MaxSonarCharges.Value) * (long)totemCount;
				ActiveSonarCharges = (int)Math.Min(MaximumStoredSonarCharges, Math.Min(2147483647L, num + num2));
				int num3 = ActiveSonarCharges - num;
				LastScanOrigin = origin;
				_sessionWorldUid = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetWorldUID() : 0);
				_hasActiveSonarSession = true;
				_deathSuspended = false;
				SonarAbilityPanel.Arm();
				ZLog.Log((object)("[TotemSentinel] Camp checks granted " + $"origin=({origin.x:0.0},{origin.y:0.0},{origin.z:0.0}) " + $"totems={totemCount} added={num3} " + $"charges={ActiveSonarCharges}/{MaximumStoredSonarCharges} " + $"radius={ScanRadius.Value:0.0}m hotkey={PingHotkey.Value}."));
			}
		}

		private static void StartActiveScan(bool isGreed = false)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			if (ActiveSonarCharges <= 0)
			{
				SonarPresenter.ShowNoChargesWarning();
				return;
			}
			_isGreedScan = isGreed;
			if (!TryReadLocalPulse(out var result, out var elapsedTicks))
			{
				ZLog.LogError((object)"[TotemSentinel] A sonar scan could not access the current ZDO sector table.");
				SonarPresenter.ShowScanUnavailableWarning();
				return;
			}
			ActiveSonarCharges--;
			_scanInProgress = true;
			_scanStartedAt = Time.unscaledTime;
			_nextScanPulseAt = _scanStartedAt + 1f;
			_scanCpuTicks = elapsedTicks;
			_scanPulseCount = 1;
			if (isGreed)
			{
				ArmGreedState();
			}
			SonarPresenter.BeginScan(LastScanOrigin, result, ActiveSonarCharges, isGreed);
		}

		private static void UpdateActiveScan(Player localPlayer)
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//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)
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime - _scanStartedAt < StateDuration.Value)
			{
				if (!(unscaledTime < _nextScanPulseAt))
				{
					if (!TryReadLocalPulse(out var result, out var elapsedTicks))
					{
						AbortActiveScan();
						return;
					}
					_scanCpuTicks += elapsedTicks;
					_scanPulseCount++;
					_nextScanPulseAt = unscaledTime + 1f;
					SonarAbilityPanel.UpdateScan(result);
				}
				return;
			}
			if (!TryReadLocalPulse(out var result2, out var elapsedTicks2))
			{
				AbortActiveScan();
				return;
			}
			_scanCpuTicks += elapsedTicks2;
			_scanPulseCount++;
			_scanInProgress = false;
			double num = (double)_scanCpuTicks * 1000.0 / (double)Stopwatch.Frequency;
			Vector3 val = ((Component)localPlayer).transform.position - LastScanOrigin;
			double num2 = Math.Sqrt(((Vector3)(ref val)).sqrMagnitude);
			float num3 = (_isGreedScan ? (ScanRadius.Value * GreedMultiplier.Value) : ScanRadius.Value);
			ZLog.Log((object)("[TotemSentinel] Camp scan complete " + $"origin=({LastScanOrigin.x:0.0},{LastScanOrigin.y:0.0},{LastScanOrigin.z:0.0}) " + $"distance={num2:0.0}m radius={num3:0.0}m isGreed={_isGreedScan} " + $"goblins={result2.Goblins} shamans={result2.Shamans} brutes={result2.Brutes} " + $"fulings={result2.Fulings} coins={result2.Coins} blackMetal={result2.BlackMetal} valuables={result2.Valuables} " + $"charges={ActiveSonarCharges} pulses={_scanPulseCount} " + $"scanCpu={num:0.000}ms source=local-zdo."));
			SonarPresenter.CompleteScan(result2, ActiveSonarCharges);
			ResetActiveScanMetrics();
		}

		private static bool TryReadLocalPulse(out SonarScanner.ScanResult result, out long elapsedTicks)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			float radius = (_isGreedScan ? (ScanRadius.Value * GreedMultiplier.Value) : ScanRadius.Value);
			long timestamp = Stopwatch.GetTimestamp();
			bool result2 = SonarScanner.TryScan(LastScanOrigin, radius, out result);
			elapsedTicks = Stopwatch.GetTimestamp() - timestamp;
			return result2;
		}

		private static void AbortActiveScan()
		{
			ZLog.LogError((object)"[TotemSentinel] A live scan pulse could not access the current local ZDO sector table.");
			ResetActiveScan();
			SonarAbilityPanel.CancelScan();
			SonarPresenter.ShowScanUnavailableWarning();
		}

		private static void SuspendSonarForDeath()
		{
			if (_hasActiveSonarSession && !_deathSuspended)
			{
				bool scanInProgress = _scanInProgress;
				RestoreInterruptedScanCharge("the player died");
				_deathSuspended = true;
				SonarAbilityPanel.Suspend();
				ZLog.Log((object)("[TotemSentinel] Camp checks preserved through death " + $"charges={ActiveSonarCharges}/{MaximumStoredSonarCharges} " + $"interruptedChargeRestored={scanInProgress}."));
			}
		}

		private static void ResumeSonarAfterDeath()
		{
			if (_deathSuspended)
			{
				_deathSuspended = false;
				SonarAbilityPanel.Resume();
				ZLog.Log((object)("[TotemSentinel] Camp checks restored after respawn " + $"charges={ActiveSonarCharges}/{MaximumStoredSonarCharges}."));
			}
		}

		private static void RestoreInterruptedScanCharge(string reason)
		{
			if (_scanInProgress)
			{
				ActiveSonarCharges = Math.Min(MaximumStoredSonarCharges, ActiveSonarCharges + 1);
				ResetActiveScan();
				SonarAbilityPanel.CancelScan();
				ZLog.Log((object)("[TotemSentinel] Interrupted camp check cancelled because " + reason + "; one charge was restored."));
			}
		}

		private static void ResetActiveScan()
		{
			_scanInProgress = false;
			_isGreedScan = false;
			ResetActiveScanMetrics();
		}

		private static void ResetActiveScanMetrics()
		{
			_scanStartedAt = 0f;
			_nextScanPulseAt = 0f;
			_scanCpuTicks = 0L;
			_scanPulseCount = 0;
		}

		private static void ResetSonarSession()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			ActiveSonarCharges = 0;
			LastScanOrigin = Vector3.zero;
			_hasActiveSonarSession = false;
			_sessionWorldUid = 0L;
			_deathSuspended = false;
			DisarmGreedState();
			ResetActiveScan();
			SonarAbilityPanel.Reset();
		}

		internal static void ArmGreedState()
		{
			_greedUntil = Time.unscaledTime + GreedDuration.Value;
			ZLog.Log((object)string.Format("[{0}] Greed's Gambit activated for {1:0}s. Any damage will enrage the horde!", "TotemSentinel", GreedDuration.Value));
		}

		internal static void DisarmGreedState()
		{
			_greedUntil = 0f;
		}

		internal static void TriggerGreedRetribution(Player localPlayer)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			if (!IsGreedActive)
			{
				return;
			}
			_greedUntil = 0f;
			ZLog.LogWarning((object)"[TotemSentinel] A single scratch triggered Greed's Retribution! Alerting horde across 3x sector.");
			if ((Object)(object)localPlayer != (Object)null)
			{
				((Character)localPlayer).Message((MessageType)2, "<color=#EF4444>CURSED! The Totem's greed awakens the horde!</color>", 0, (Sprite)null, false);
			}
			float num = ScanRadius.Value * GreedMultiplier.Value;
			float num2 = num * num;
			Vector3 val = (((Object)(object)localPlayer != (Object)null) ? ((Component)localPlayer).transform.position : LastScanOrigin);
			try
			{
				List<BaseAI> allInstances = BaseAI.GetAllInstances();
				int num3 = 0;
				if (allInstances != null)
				{
					foreach (BaseAI item in allInstances)
					{
						if (!((Object)(object)item == (Object)null))
						{
							Vector3 val2 = ((Component)item).transform.position - val;
							if (((Vector3)(ref val2)).sqrMagnitude <= num2)
							{
								item.Alert();
								item.SetHuntPlayer(true);
								num3++;
							}
						}
					}
				}
				ZLog.Log((object)string.Format("[{0}] Greed's Retribution: {1} creatures alerted.", "TotemSentinel", num3));
			}
			catch (Exception arg)
			{
				ZLog.LogError((object)string.Format("[{0}] Failed alerting creatures during retribution: {1}", "TotemSentinel", arg));
			}
			SonarPresenter.TriggerCursed(GreedDuration.Value);
		}
	}
}
namespace TotemSentinel.Services
{
	internal static class SonarScanner
	{
		internal readonly struct ScanResult
		{
			internal readonly int Goblins;

			internal readonly int Shamans;

			internal readonly int Brutes;

			internal readonly int Coins;

			internal readonly int BlackMetal;

			internal readonly int Valuables;

			internal int Fulings => Goblins + Shamans + Brutes;

			internal ScanResult(int goblins, int shamans, int brutes, int coins, int blackMetal, int valuables = 0)
			{
				Goblins = goblins;
				Shamans = shamans;
				Brutes = brutes;
				Coins = coins;
				BlackMetal = blackMetal;
				Valuables = valuables;
			}
		}

		private static readonly int GoblinPrefabHash = StringExtensionMethods.GetStableHashCode("Goblin");

		private static readonly int GoblinShamanPrefabHash = StringExtensionMethods.GetStableHashCode("GoblinShaman");

		private static readonly int GoblinBrutePrefabHash = StringExtensionMethods.GetStableHashCode("GoblinBrute");

		private static readonly int CoinsPrefabHash = StringExtensionMethods.GetStableHashCode("Coins");

		private static readonly int BlackMetalScrapPrefabHash = StringExtensionMethods.GetStableHashCode("BlackMetalScrap");

		private static readonly int RubyPrefabHash = StringExtensionMethods.GetStableHashCode("Ruby");

		private static readonly int AmberPrefabHash = StringExtensionMethods.GetStableHashCode("Amber");

		private static readonly int AmberPearlPrefabHash = StringExtensionMethods.GetStableHashCode("AmberPearl");

		private static readonly int SilverNecklacePrefabHash = StringExtensionMethods.GetStableHashCode("SilverNecklace");

		private static readonly int GoblinTotemPrefabHash = StringExtensionMethods.GetStableHashCode("GoblinTotem");

		private static FieldRef<ZDOMan, List<ZDO>[]> _objectsBySectorRef;

		private static FieldRef<ZDOMan, int> _widthRef;

		private static bool _initialized;

		internal static bool Initialize()
		{
			try
			{
				_objectsBySectorRef = AccessTools.FieldRefAccess<ZDOMan, List<ZDO>[]>("m_objectsBySector");
				_widthRef = AccessTools.FieldRefAccess<ZDOMan, int>("m_width");
				_initialized = true;
				return true;
			}
			catch (Exception arg)
			{
				_initialized = false;
				ZLog.LogError((object)string.Format("[{0}] Could not bind ZDOMan sector fields: {1}", "TotemSentinel", arg));
				return false;
			}
		}

		internal static bool TryScan(Vector3 centerPoint, float radius, out ScanResult result)
		{
			//IL_0051: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			result = default(ScanResult);
			ZDOMan instance = ZDOMan.instance;
			if (!_initialized || instance == null || (Object)(object)ZoneSystem.instance == (Object)null)
			{
				return false;
			}
			List<ZDO>[] array = _objectsBySectorRef.Invoke(instance);
			int num = _widthRef.Invoke(instance);
			if (array == null || num <= 0 || array.Length != num * num)
			{
				return false;
			}
			Vector2s zone = ZoneSystem.GetZone(centerPoint);
			float num2 = radius * radius;
			int num3 = 0;
			int num4 = 0;
			int num5 = 0;
			int num6 = 0;
			int num7 = 0;
			int num8 = 0;
			int num9 = Mathf.Clamp(Mathf.CeilToInt(radius / 64f) + 1, 2, 5);
			for (int i = zone.y - num9; i <= zone.y + num9; i++)
			{
				int num10 = num / 2;
				if (i < -num10 || i >= num10)
				{
					continue;
				}
				for (int j = zone.x - num9; j <= zone.x + num9; j++)
				{
					if (j < -num10 || j >= num10)
					{
						continue;
					}
					uint sector = ZoneSystem.SectorToIndex(j, i).Sector;
					if (sector >= array.Length)
					{
						continue;
					}
					List<ZDO> list = array[sector];
					if (list == null)
					{
						continue;
					}
					for (int k = 0; k < list.Count; k++)
					{
						ZDO val = list[k];
						if (val == null)
						{
							continue;
						}
						int prefab = val.GetPrefab();
						if (prefab != GoblinPrefabHash && prefab != GoblinShamanPrefabHash && prefab != GoblinBrutePrefabHash && prefab != CoinsPrefabHash && prefab != BlackMetalScrapPrefabHash && prefab != RubyPrefabHash && prefab != AmberPrefabHash && prefab != AmberPearlPrefabHash && prefab != SilverNecklacePrefabHash && prefab != GoblinTotemPrefabHash)
						{
							continue;
						}
						Vector3 val2 = val.GetPosition() - centerPoint;
						if (!(((Vector3)(ref val2)).sqrMagnitude > num2))
						{
							if (prefab == CoinsPrefabHash)
							{
								int num11 = val.GetInt(ZDOVars.s_stack, 1);
								num6 += ((num11 <= 0) ? 1 : num11);
							}
							else if (prefab == BlackMetalScrapPrefabHash)
							{
								int num12 = val.GetInt(ZDOVars.s_stack, 1);
								num7 += ((num12 <= 0) ? 1 : num12);
							}
							else if (prefab == RubyPrefabHash || prefab == AmberPrefabHash || prefab == AmberPearlPrefabHash || prefab == SilverNecklacePrefabHash || prefab == GoblinTotemPrefabHash)
							{
								int num13 = val.GetInt(ZDOVars.s_stack, 1);
								num8 += ((num13 <= 0) ? 1 : num13);
							}
							else if (prefab == GoblinPrefabHash)
							{
								num3++;
							}
							else if (prefab == GoblinShamanPrefabHash)
							{
								num4++;
							}
							else
							{
								num5++;
							}
						}
					}
				}
			}
			result = new ScanResult(num3, num4, num5, num6, num7, num8);
			return true;
		}
	}
}
namespace TotemSentinel.Patches
{
	[HarmonyPatch(typeof(Character), "ApplyDamage")]
	internal static class PlayerDamagePatch
	{
		private static void Postfix(Character __instance, HitData hit)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && hit != null && hit.GetTotalDamage() > 0.05f && TotemSentinelPlugin.IsGreedActive)
			{
				TotemSentinelPlugin.TriggerGreedRetribution(Player.m_localPlayer);
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "Pickup", new Type[]
	{
		typeof(GameObject),
		typeof(bool),
		typeof(bool)
	})]
	internal static class TotemPickupPatch
	{
		private readonly struct PickupState
		{
			internal readonly bool Eligible;

			internal readonly Vector3 Origin;

			internal readonly int TotemCount;

			internal PickupState(bool eligible, Vector3 origin, int totemCount)
			{
				//IL_0008: 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)
				Eligible = eligible;
				Origin = origin;
				TotemCount = totemCount;
			}
		}

		private static readonly int GoblinTotemPrefabHash = StringExtensionMethods.GetStableHashCode("GoblinTotem");

		private static void Prefix(Humanoid __instance, GameObject go, ref PickupState __state)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			__state = default(PickupState);
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || (Object)(object)go == (Object)null)
			{
				return;
			}
			ItemDrop component = go.GetComponent<ItemDrop>();
			if (!((Object)(object)component == (Object)null))
			{
				component.Load();
				ItemData itemData = component.m_itemData;
				GameObject val = itemData?.m_dropPrefab;
				if (!((Object)(object)val == (Object)null) && StringExtensionMethods.GetStableHashCode(((Object)val).name) == GoblinTotemPrefabHash && !itemData.m_pickedUp)
				{
					__state = new PickupState(eligible: true, ((Component)component).transform.position, Mathf.Max(1, itemData.m_stack));
				}
			}
		}

		private static void Postfix(PickupState __state, ref bool __result)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (__state.Eligible & __result)
			{
				TotemSentinelPlugin.GrantTotemSonar(__state.Origin, __state.TotemCount);
			}
		}
	}
}
namespace TotemSentinel.HUD
{
	internal static class SonarAbilityPanel
	{
		private enum PanelState
		{
			Hidden,
			Ready,
			Scanning,
			Found,
			Clear,
			Complete,
			OutOfRange,
			Depleted,
			Unavailable,
			Cursed
		}

		private static readonly Vector3[] MapCorners = (Vector3[])(object)new Vector3[4];

		private static readonly Color ReadyColor = new Color(0.94f, 0.94f, 0.94f, 1f);

		private static readonly Color GoldColor = new Color(1f, 0.69f, 0.18f, 1f);

		private static readonly Color OrangeColor = new Color(1f, 0.45f, 0.08f, 1f);

		private static readonly Color RedColor = new Color(1f, 0.16f, 0.19f, 1f);

		private static readonly Color GreenColor = new Color(0.08f, 0.78f, 0.3f, 1f);

		private static readonly Color MutedColor = new Color(0.72f, 0.72f, 0.72f, 1f);

		private static readonly Color BackgroundColor = new Color(0.025f, 0.025f, 0.025f, 0.9f);

		private static PanelState _state;

		private static SonarScanner.ScanResult _result;

		private static bool _hasResult;

		private static SonarScanner.ScanResult _resultBeforeScan;

		private static bool _hadResultBeforeScan;

		private static bool _hasScanBackup;

		private static bool _dismissed;

		private static bool _suspended;

		private static float _suspendedAt;

		private static float _stateStarted;

		private static float _finalScanStarted = -1f;

		private static bool _isGreedScan;

		private static float _cursedUntil;

		private static float _cursedStarted;

		private static GUIStyle _titleStyle;

		private static GUIStyle _mainStyle;

		private static GUIStyle _detailStyle;

		private static GUIStyle _summaryStyle;

		private static GUIStyle _closeStyle;

		internal static bool CanBeginScan
		{
			get
			{
				if (_state != PanelState.Ready)
				{
					return _state == PanelState.Hidden;
				}
				return true;
			}
		}

		internal static void Arm()
		{
			_result = default(SonarScanner.ScanResult);
			_hasResult = false;
			_hasScanBackup = false;
			_dismissed = false;
			_suspended = false;
			_finalScanStarted = -1f;
			SetState(PanelState.Ready);
		}

		internal static void BeginScan(SonarScanner.ScanResult result, int charges, bool isGreed = false)
		{
			_isGreedScan = isGreed;
			_resultBeforeScan = _result;
			_hadResultBeforeScan = _hasResult;
			_hasScanBackup = true;
			_result = result;
			_hasResult = true;
			_dismissed = false;
			SetState(PanelState.Scanning);
		}

		internal static void TriggerCursed(float duration)
		{
			_cursedStarted = Time.unscaledTime;
			_cursedUntil = Time.unscaledTime + duration;
			_dismissed = false;
			SetState(PanelState.Cursed);
		}

		internal static void UpdateScan(SonarScanner.ScanResult result)
		{
			if (_state == PanelState.Scanning)
			{
				_result = result;
				_hasResult = true;
			}
		}

		internal static void CompleteScan(SonarScanner.ScanResult result, int charges)
		{
			_result = result;
			_hasResult = true;
			_hasScanBackup = false;
			_dismissed = false;
			if (charges <= 0)
			{
				_finalScanStarted = Time.unscaledTime;
			}
			SetState((result.Fulings > 0) ? PanelState.Found : PanelState.Clear);
		}

		internal static void CancelScan()
		{
			if (_hasScanBackup)
			{
				_result = _resultBeforeScan;
				_hasResult = _hadResultBeforeScan;
			}
			_hasScanBackup = false;
			SetState((TotemSentinelPlugin.ActiveSonarCharges > 0) ? PanelState.Ready : PanelState.Hidden);
		}

		internal static void Suspend()
		{
			if (!_suspended)
			{
				_suspended = true;
				_suspendedAt = Time.unscaledTime;
			}
		}

		internal static void Resume()
		{
			if (_suspended)
			{
				float num = Time.unscaledTime - _suspendedAt;
				if (_finalScanStarted >= 0f)
				{
					_finalScanStarted += num;
				}
				_suspended = false;
				_suspendedAt = 0f;
				SetState((TotemSentinelPlugin.ActiveSonarCharges > 0) ? PanelState.Ready : (_hasResult ? PanelState.Complete : PanelState.Hidden));
			}
		}

		internal static void ShowOutOfRange()
		{
			_dismissed = false;
			SetState(PanelState.OutOfRange);
		}

		internal static void ShowDepleted()
		{
			_dismissed = false;
			SetState(PanelState.Depleted);
		}

		internal static void ShowUnavailable()
		{
			_dismissed = false;
			SetState(PanelState.Unavailable);
		}

		internal static void Reset()
		{
			_result = default(SonarScanner.ScanResult);
			_hasResult = false;
			_resultBeforeScan = default(SonarScanner.ScanResult);
			_hadResultBeforeScan = false;
			_hasScanBackup = false;
			_dismissed = false;
			_suspended = false;
			_suspendedAt = 0f;
			_state = PanelState.Hidden;
			_stateStarted = 0f;
			_finalScanStarted = -1f;
			_isGreedScan = false;
			_cursedUntil = 0f;
			_cursedStarted = 0f;
		}

		internal static void Draw(bool preview)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			if (_suspended)
			{
				return;
			}
			UpdateState();
			bool flag = TotemSentinelPlugin.HasActiveSonarSession && TotemSentinelPlugin.ActiveSonarCharges > 0;
			if (preview || (!_dismissed && (_state != PanelState.Hidden || flag)))
			{
				if (_state == PanelState.Hidden && flag && !_dismissed)
				{
					SetState(PanelState.Ready);
				}
				EnsureStyles();
				bool showSummary = ShouldShowSummary();
				Rect cardRect = GetCardRect(showSummary);
				float num = Mathf.Clamp((float)Screen.height / 1080f, 0.8f, 1.45f);
				float num2 = Mathf.Max(3f, 4f * num);
				Color accentColor = GetAccentColor(preview);
				DrawSolidRect(cardRect, accentColor);
				DrawSolidRect(new Rect(((Rect)(ref cardRect)).x + num2, ((Rect)(ref cardRect)).y + num2, ((Rect)(ref cardRect)).width - num2 * 2f, ((Rect)(ref cardRect)).height - num2 * 2f), BackgroundColor);
				_titleStyle.fontSize = Mathf.RoundToInt(17f * num);
				_mainStyle.fontSize = Mathf.RoundToInt(27f * num);
				_detailStyle.fontSize = Mathf.RoundToInt(13f * num);
				_summaryStyle.fontSize = Mathf.RoundToInt(13f * num);
				_closeStyle.fontSize = Mathf.RoundToInt(16f * num);
				DrawContent(cardRect, num, preview, accentColor, showSummary);
			}
		}

		private static void DrawContent(Rect card, float scale, bool preview, Color accent, bool showSummary)
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: 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_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_0356: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			//IL_0389: 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_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			float num = 10f * scale;
			float num2 = ((Rect)(ref card)).width - num * 2f;
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref card)).x + num, ((Rect)(ref card)).y + 9f * scale, num2, 25f * scale);
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(((Rect)(ref card)).x + num, ((Rect)(ref card)).y + 35f * scale, num2, 42f * scale);
			Rect val3 = default(Rect);
			((Rect)(ref val3))..ctor(((Rect)(ref card)).x + num, ((Rect)(ref card)).y + 79f * scale, num2, 38f * scale);
			_titleStyle.normal.textColor = accent;
			_mainStyle.normal.textColor = accent;
			_detailStyle.normal.textColor = ReadyColor;
			PanelState state = _state;
			if (state == PanelState.Hidden && preview)
			{
				GUI.Label(val, "CAMP CHECKS", _titleStyle);
				GUI.Label(val2, "-- / --", _mainStyle);
				GUI.Label(val3, "WAITING FOR A TOTEM", _detailStyle);
				return;
			}
			switch (state)
			{
			case PanelState.Ready:
				DrawReady(val, val2, val3);
				break;
			case PanelState.Scanning:
			{
				float num4 = Mathf.Max(0f, GetStateDuration() - (Time.unscaledTime - _stateStarted));
				string text = (_isGreedScan ? "GREED SCAN" : "SCANNING");
				string text2 = (_isGreedScan ? "3x WIDE LOOT SEARCH" : "LISTENING ACROSS THE CAMP");
				GUI.Label(val, text, _titleStyle);
				GUI.Label(val2, $"{num4:0}s", _mainStyle);
				GUI.Label(val3, text2, _detailStyle);
				break;
			}
			case PanelState.Cursed:
			{
				float num3 = Mathf.Max(0f, _cursedUntil - Time.unscaledTime);
				GUI.Label(val, "CURSED!", _titleStyle);
				GUI.Label(val2, $"{num3:0}s", _mainStyle);
				GUI.Label(val3, "HORDE ALERTED ACROSS CAMP", _detailStyle);
				break;
			}
			case PanelState.Found:
				GUI.Label(val, "FULINGS FOUND", _titleStyle);
				GUI.Label(val2, _result.Fulings.ToString(), _mainStyle);
				GUI.Label(val3, "LAST CAMP CHECK", _detailStyle);
				break;
			case PanelState.Clear:
				GUI.Label(val, "CAMP", _titleStyle);
				GUI.Label(val2, "CLEAR", _mainStyle);
				GUI.Label(val3, "LAST CAMP CHECK", _detailStyle);
				break;
			case PanelState.Complete:
				GUI.Label(val, "CHECKS COMPLETE", _titleStyle);
				GUI.Label(val2, $"0 / {TotemSentinelPlugin.MaximumStoredSonarCharges}", _mainStyle);
				GUI.Label(val3, "CLOSES IN " + FormatFinalTimeRemaining(), _detailStyle);
				DrawCloseButton(card, scale);
				break;
			case PanelState.OutOfRange:
				GUI.Label(val, "OUT OF RANGE", _titleStyle);
				GUI.Label(val2, $"> {TotemSentinelPlugin.ScanRadius.Value:0}m", _mainStyle);
				GUI.Label(val3, "RETURN TO THE TOTEM'S CAMP", _detailStyle);
				break;
			case PanelState.Depleted:
				GUI.Label(val, "NO CHECKS", _titleStyle);
				GUI.Label(val2, "0", _mainStyle);
				GUI.Label(val3, "LAST RESULT REMAINS BELOW", _detailStyle);
				break;
			case PanelState.Unavailable:
				GUI.Label(val, "SCAN FAILED", _titleStyle);
				GUI.Label(val2, "--", _mainStyle);
				GUI.Label(val3, "CHECK THE COMFYSENTINEL LOG", _detailStyle);
				break;
			}
			if (showSummary)
			{
				DrawSummary(card, scale);
			}
		}

		private static void DrawReady(Rect titleRect, Rect mainRect, Rect detailRect)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			int activeSonarCharges = TotemSentinelPlugin.ActiveSonarCharges;
			int maximumStoredSonarCharges = TotemSentinelPlugin.MaximumStoredSonarCharges;
			GUI.Label(titleRect, "CAMP CHECKS", _titleStyle);
			_mainStyle.richText = true;
			string text = ((activeSonarCharges < maximumStoredSonarCharges) ? $"<color=#FFB02E>{activeSonarCharges}</color> / {maximumStoredSonarCharges}" : $"{activeSonarCharges} / {maximumStoredSonarCharges}");
			GUI.Label(mainRect, text, _mainStyle);
			_mainStyle.richText = false;
			GUI.Label(detailRect, $"\"{TotemSentinelPlugin.PingHotkey.Value}\" CHECK  ·  SHIFT GREED", _detailStyle);
		}

		private static void DrawSummary(Rect card, float scale)
		{
			//IL_0048: 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_014a: Unknown result type (might be due to invalid IL or missing references)
			float num = 14f * scale;
			float num2 = ((Rect)(ref card)).y + 123f * scale;
			float num3 = 17f * scale;
			float num4 = ((Rect)(ref card)).width - num * 2f;
			DrawSolidRect(new Rect(((Rect)(ref card)).x + num, num2 - 6f * scale, num4, 1f), new Color(1f, 0.69f, 0.18f, 0.45f));
			int row = 0;
			DrawSummaryRow(((Rect)(ref card)).x + num, num2, num4, num3, ref row, "FULINGS", _result.Goblins);
			DrawSummaryRow(((Rect)(ref card)).x + num, num2, num4, num3, ref row, "SHAMANS", _result.Shamans);
			DrawSummaryRow(((Rect)(ref card)).x + num, num2, num4, num3, ref row, "BRUTES", _result.Brutes);
			DrawSummaryRow(((Rect)(ref card)).x + num, num2, num4, num3, ref row, "COINS", _result.Coins);
			DrawSummaryRow(((Rect)(ref card)).x + num, num2, num4, num3, ref row, "BLACK METAL", _result.BlackMetal);
			DrawSummaryRow(((Rect)(ref card)).x + num, num2, num4, num3, ref row, "VALUABLES", _result.Valuables);
			if (row == 0)
			{
				GUI.Label(new Rect(((Rect)(ref card)).x + num, num2, num4, num3), "NOTHING DETECTED", _summaryStyle);
			}
		}

		private static void DrawSummaryRow(float x, float top, float width, float rowHeight, ref int row, string label, int count)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if (count > 0)
			{
				GUI.Label(new Rect(x, top + (float)row * rowHeight, width, rowHeight), $"{label}   {count}", _summaryStyle);
				row++;
			}
		}

		private static void DrawCloseButton(Rect card, float scale)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (GUI.Button(new Rect(((Rect)(ref card)).xMax - 31f * scale, ((Rect)(ref card)).y + 7f * scale, 23f * scale, 23f * scale), "X", _closeStyle))
			{
				_dismissed = true;
				SetState(PanelState.Hidden);
				ZLog.Log((object)"[TotemSentinel] Final camp-check summary dismissed by the player.");
			}
		}

		private static void UpdateState()
		{
			if (_finalScanStarted >= 0f && Time.unscaledTime - _finalScanStarted >= GetFinalSummaryDuration())
			{
				if (_state != PanelState.Hidden)
				{
					ZLog.Log((object)"[TotemSentinel] Final camp-check summary closed after its timer elapsed.");
				}
				_dismissed = true;
				_state = PanelState.Hidden;
				return;
			}
			float num = Time.unscaledTime - _stateStarted;
			float stateDuration = GetStateDuration();
			if (_state == PanelState.Cursed && Time.unscaledTime >= _cursedUntil)
			{
				SetState((TotemSentinelPlugin.ActiveSonarCharges > 0) ? PanelState.Ready : PanelState.Complete);
			}
			else if ((_state == PanelState.Found || _state == PanelState.Clear) && num >= stateDuration)
			{
				SetState((TotemSentinelPlugin.ActiveSonarCharges > 0) ? PanelState.Ready : PanelState.Complete);
			}
			else if ((_state == PanelState.OutOfRange || _state == PanelState.Unavailable) && num >= stateDuration)
			{
				SetState((TotemSentinelPlugin.ActiveSonarCharges > 0) ? PanelState.Ready : PanelState.Complete);
			}
			else if (_state == PanelState.Depleted && num >= stateDuration)
			{
				SetState(_hasResult ? PanelState.Complete : PanelState.Hidden);
			}
		}

		private static bool ShouldShowSummary()
		{
			if (!_hasResult)
			{
				return false;
			}
			if (_state != PanelState.Ready && _state != PanelState.Scanning && _state != PanelState.Found && _state != PanelState.Clear && _state != PanelState.Complete && _state != PanelState.Depleted)
			{
				return _state == PanelState.Cursed;
			}
			return true;
		}

		private static Rect GetCardRect(bool showSummary)
		{
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp((float)Screen.height / 1080f, 0.8f, 1.45f);
			float num2 = 230f * num;
			float num3 = (showSummary ? Mathf.Max(1, GetSummaryRowCount()) : 0);
			float num4 = (125f + num3 * 17f + (showSummary ? 8f : 0f)) * num;
			float num5 = (float)Screen.width - num2 - 22f * num;
			float num6 = 285f * num;
			Minimap instance = Minimap.instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)instance.m_smallRoot != (Object)null && instance.m_smallRoot.activeInHierarchy && (Object)(object)instance.m_mapImageSmall != (Object)null)
			{
				((Graphic)instance.m_mapImageSmall).rectTransform.GetWorldCorners(MapCorners);
				float num7 = MapCorners[0].x;
				float num8 = MapCorners[0].y;
				for (int i = 1; i < MapCorners.Length; i++)
				{
					num7 = Mathf.Max(num7, MapCorners[i].x);
					num8 = Mathf.Min(num8, MapCorners[i].y);
				}
				num5 = num7 - num2;
				num6 = (float)Screen.height - num8 + 10f * num;
			}
			num5 = Mathf.Clamp(num5, 8f, (float)Screen.width - num2 - 8f);
			num6 = Mathf.Clamp(num6, 8f, (float)Screen.height - num4 - 8f);
			return new Rect(num5, num6, num2, num4);
		}

		private static int GetSummaryRowCount()
		{
			return 0 + ((_result.Goblins > 0) ? 1 : 0) + ((_result.Shamans > 0) ? 1 : 0) + ((_result.Brutes > 0) ? 1 : 0) + ((_result.Coins > 0) ? 1 : 0) + ((_result.BlackMetal > 0) ? 1 : 0) + ((_result.Valuables > 0) ? 1 : 0);
		}

		private static Color GetAccentColor(bool preview)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			switch (_state)
			{
			case PanelState.Cursed:
				return RedColor;
			case PanelState.Scanning:
				if (!_isGreedScan)
				{
					return OrangeColor;
				}
				return GoldColor;
			case PanelState.Found:
				return RedColor;
			case PanelState.Clear:
				return GreenColor;
			case PanelState.Complete:
				return GoldColor;
			case PanelState.OutOfRange:
			case PanelState.Depleted:
			case PanelState.Unavailable:
				return OrangeColor;
			case PanelState.Ready:
				return ReadyColor;
			default:
				if (!preview)
				{
					return ReadyColor;
				}
				return MutedColor;
			}
		}

		private static string FormatFinalTimeRemaining()
		{
			int num = Mathf.Max(0, Mathf.CeilToInt(GetFinalSummaryDuration() - (Time.unscaledTime - _finalScanStarted)));
			return $"{num / 60}:{num % 60:00}";
		}

		private static float GetStateDuration()
		{
			if (TotemSentinelPlugin.StateDuration == null)
			{
				return 10f;
			}
			return TotemSentinelPlugin.StateDuration.Value;
		}

		private static float GetFinalSummaryDuration()
		{
			if (TotemSentinelPlugin.FinalSummaryDuration == null)
			{
				return 300f;
			}
			return TotemSentinelPlugin.FinalSummaryDuration.Value;
		}

		private static void DrawSolidRect(Rect rect, Color color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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)
			Color color2 = GUI.color;
			GUI.color = color;
			GUI.DrawTexture(rect, (Texture)(object)Texture2D.whiteTexture);
			GUI.color = color2;
		}

		private static void SetState(PanelState state)
		{
			_state = state;
			_stateStarted = Time.unscaledTime;
		}

		private static void EnsureStyles()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			if (_titleStyle == null)
			{
				_titleStyle = CreateCenteredStyle((FontStyle)1, ReadyColor);
				_mainStyle = CreateCenteredStyle((FontStyle)1, ReadyColor);
				_detailStyle = CreateCenteredStyle((FontStyle)0, ReadyColor);
				_detailStyle.wordWrap = true;
				_summaryStyle = CreateCenteredStyle((FontStyle)0, GoldColor);
				_closeStyle = CreateCenteredStyle((FontStyle)1, ReadyColor);
				_closeStyle.hover.textColor = RedColor;
				_closeStyle.active.textColor = OrangeColor;
			}
		}

		private static GUIStyle CreateCenteredStyle(FontStyle fontStyle, Color color)
		{
			//IL_000a: 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)
			//IL_0016: 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_001d: 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)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			GUIStyle val = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)4,
				fontStyle = fontStyle,
				clipping = (TextClipping)1
			};
			val.normal.textColor = color;
			return val;
		}
	}
	internal static class SonarPresenter
	{
		internal static void BeginScan(Vector3 origin, SonarScanner.ScanResult result, int charges, bool isGreed = false)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			PlayPingEffect(origin);
			SonarAbilityPanel.BeginScan(result, charges, isGreed);
		}

		internal static void TriggerCursed(float duration)
		{
			SonarAbilityPanel.TriggerCursed(duration);
		}

		internal static void CompleteScan(SonarScanner.ScanResult result, int charges)
		{
			SonarAbilityPanel.CompleteScan(result, charges);
		}

		internal static void ShowOutOfRangeWarning()
		{
			SonarAbilityPanel.ShowOutOfRange();
		}

		internal static void ShowNoChargesWarning()
		{
			SonarAbilityPanel.ShowDepleted();
		}

		internal static void ShowScanUnavailableWarning()
		{
			SonarAbilityPanel.ShowUnavailable();
		}

		private static void PlayPingEffect(Vector3 origin)
		{
			//IL_0058: 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)
			try
			{
				ZNetScene instance = ZNetScene.instance;
				if ((Object)(object)instance == (Object)null)
				{
					ZLog.LogWarning((object)"[TotemSentinel] ZNetScene was unavailable for the sonar effect.");
					return;
				}
				GameObject prefab = instance.GetPrefab("vfx_WishbonePing");
				if ((Object)(object)prefab == (Object)null)
				{
					ZLog.LogWarning((object)"[TotemSentinel] Could not find vfx_WishbonePing.");
				}
				else if ((Object)(object)prefab.GetComponentInChildren<ZNetView>(true) != (Object)null)
				{
					ZLog.LogWarning((object)"[TotemSentinel] Skipped networked vfx_WishbonePing to preserve local-only scanning.");
				}
				else
				{
					Object.Instantiate<GameObject>(prefab, origin, Quaternion.identity);
				}
			}
			catch (Exception arg)
			{
				ZLog.LogError((object)string.Format("[{0}] Failed to play the sonar effect: {1}", "TotemSentinel", arg));
			}
		}
	}
}
namespace TotemSentinel.Commands
{
	internal static class TotemAlertCommands
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static ConsoleEventFailable <0>__RunTotemAlertCommand;

			public static ConsoleEventFailable <1>__RunTotemCommand;
		}

		private static readonly List<GameObject> SpawnedTestObjects = new List<GameObject>(7);

		private static bool _registered;

		internal static void Register()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			if (!_registered)
			{
				object obj = <>O.<0>__RunTotemAlertCommand;
				if (obj == null)
				{
					ConsoleEventFailable val = RunTotemAlertCommand;
					<>O.<0>__RunTotemAlertCommand = val;
					obj = (object)val;
				}
				new ConsoleCommand("totemalert", "[on/off/status] - preview the ComfySentinel camp-check panel", (ConsoleEventFailable)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				object obj2 = <>O.<1>__RunTotemCommand;
				if (obj2 == null)
				{
					ConsoleEventFailable val2 = RunTotemCommand;
					<>O.<1>__RunTotemCommand = val2;
					obj2 = (object)val2;
				}
				new ConsoleCommand("totem", "1 - spawn the ComfySentinel test camp; 'totem clear' removes it", (ConsoleEventFailable)obj2, false, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				_registered = true;
			}
		}

		private static object RunTotemAlertCommand(ConsoleEventArgs args)
		{
			bool flag;
			if (args.Length == 1)
			{
				flag = TotemSentinelPlugin.SetAbilityPreview();
			}
			else if (string.Equals(args[1], "on", StringComparison.OrdinalIgnoreCase))
			{
				flag = TotemSentinelPlugin.SetAbilityPreview(true);
			}
			else
			{
				if (!string.Equals(args[1], "off", StringComparison.OrdinalIgnoreCase))
				{
					if (string.Equals(args[1], "status", StringComparison.OrdinalIgnoreCase))
					{
						WriteStatus(args.Context);
						return true;
					}
					return "Use: totemalert [on|off|status]";
				}
				flag = TotemSentinelPlugin.SetAbilityPreview(false);
			}
			Terminal context = args.Context;
			if (context != null)
			{
				context.AddString("ComfySentinel 1.5.2 is running. Panel preview: " + (flag ? "open" : "closed") + ".");
			}
			Terminal context2 = args.Context;
			if (context2 != null)
			{
				context2.AddString("Use 'totem 1' to create the test camp and 'totem clear' to remove it.");
			}
			return true;
		}

		private static object RunTotemCommand(ConsoleEventArgs args)
		{
			if (args.Length < 2)
			{
				return "Use: totem 1 | totem clear";
			}
			if (string.Equals(args[1], "clear", StringComparison.OrdinalIgnoreCase))
			{
				int num = ClearTestScenario();
				Terminal context = args.Context;
				if (context != null)
				{
					context.AddString($"ComfySentinel test camp cleared ({num} tracked objects removed).");
				}
				return true;
			}
			if (args[1] != "1")
			{
				return "Unknown scenario. Use: totem 1 | totem clear";
			}
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return "Test spawning is restricted to a local world or a world hosted by this client.";
			}
			Player localPlayer = Player.m_localPlayer;
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)instance == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null)
			{
				return "Enter a fully loaded local/hosted world before spawning the test camp.";
			}
			try
			{
				ClearTestScenario();
				string text = SpawnScenarioOne(localPlayer, instance);
				if (text != null)
				{
					ClearTestScenario();
					return text;
				}
				Terminal context2 = args.Context;
				if (context2 != null)
				{
					context2.AddString("ComfySentinel scenario 1 created: totem, three Fuling types, 12 coins, and 8 black metal.");
				}
				Terminal context3 = args.Context;
				if (context3 != null)
				{
					context3.AddString("Close the console, pick up the loose totem to add " + $"{TotemSentinelPlugin.MaxSonarCharges.Value} checks, then press the configured hotkey when ready.");
				}
				ZLog.Log((object)"[TotemSentinel] Test scenario 1 created with 7 tracked objects.");
				return true;
			}
			catch (Exception ex)
			{
				ClearTestScenario();
				ZLog.LogError((object)string.Format("[{0}] Failed to create test scenario 1: {1}", "TotemSentinel", ex));
				return "Scenario creation failed: " + ex.Message;
			}
		}

		private static string SpawnScenarioOne(Player player, ZNetScene scene)
		{
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: 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_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: 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_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: 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_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: 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_0133: 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_01fc: 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_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: 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_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: 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_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = FindPrefab(scene, "itemstand", "itemstandh", "piece_itemstand");
			GameObject val2 = FindPrefab(scene, "GoblinTotem");
			GameObject val3 = FindPrefab(scene, "Goblin");
			GameObject val4 = FindPrefab(scene, "GoblinShaman");
			GameObject val5 = FindPrefab(scene, "GoblinBrute");
			GameObject val6 = FindPrefab(scene, "Coins");
			GameObject val7 = FindPrefab(scene, "BlackMetalScrap");
			GameObject val8 = FindPickableTemplate(scene);
			if ((Object)(object)val == (Object)null)
			{
				return "Could not find an item stand prefab in this Valheim build.";
			}
			if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null || (Object)(object)val5 == (Object)null || (Object)(object)val6 == (Object)null || (Object)(object)val7 == (Object)null)
			{
				return "One or more required Fuling or loose-loot prefabs are unavailable in this world.";
			}
			if ((Object)(object)val8 == (Object)null)
			{
				return "Could not find a native Pickable prefab to use as the test interaction proxy.";
			}
			Vector3 forward = ((Component)player).transform.forward;
			forward.y = 0f;
			if (((Vector3)(ref forward)).sqrMagnitude < 0.01f)
			{
				forward = Vector3.forward;
			}
			((Vector3)(ref forward)).Normalize();
			Vector3 val9 = Vector3.Cross(Vector3.up, forward);
			Vector3 val10 = GroundPosition(((Component)player).transform.position + forward * 5f);
			Quaternion rotation = Quaternion.LookRotation(-forward, Vector3.up);
			GameObject obj = Spawn(val, val10, rotation);
			ItemStand component = obj.GetComponent<ItemStand>();
			ZNetView component2 = obj.GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || !component2.IsValid())
			{
				return "The available item stand prefab is missing its expected Valheim components.";
			}
			ConfigureStandVisual(component2, ((Object)val2).name);
			Vector3 position = (((Object)(object)component.m_attachOther != (Object)null) ? component.m_attachOther.position : (val10 + Vector3.up * 1.25f));
			ConfigurePickableTotem(Spawn(val8, position, rotation), val2);
			Spawn(val3, GroundPosition(val10 + forward * 13f + val9 * 9f) + Vector3.up, Quaternion.identity);
			Spawn(val4, GroundPosition(val10 + forward * 17f - val9 * 11f) + Vector3.up, Quaternion.identity);
			Spawn(val5, GroundPosition(val10 + forward * 23f + val9 * 2f) + Vector3.up, Quaternion.identity);
			SpawnItemStack(val6, 12, GroundPosition(val10 + forward * 9f - val9 * 4f) + Vector3.up);
			SpawnItemStack(val7, 8, GroundPosition(val10 + forward * 11f + val9 * 4f) + Vector3.up);
			return null;
		}

		private static void SpawnItemStack(GameObject prefab, int stack, Vector3 position)
		{
			//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)
			ItemDrop component = Spawn(prefab, position, Quaternion.identity).GetComponent<ItemDrop>();
			if ((Object)(object)component == (Object)null)
			{
				throw new InvalidOperationException("Test loot prefab " + ((Object)prefab).name + " is not an ItemDrop.");
			}
			component.SetStack(stack);
		}

		private static void ConfigureStandVisual(ZNetView standNetView, string itemPrefabName)
		{
			ZDO zDO = standNetView.GetZDO();
			zDO.Set(ZDOVars.s_item, itemPrefabName);
			zDO.Set(ZDOVars.s_type, 0, false);
			standNetView.InvokeRPC(ZNetView.Everybody, "SetVisualItem", new object[4] { itemPrefabName, 0, 1, 0 });
		}

		private static void ConfigurePickableTotem(GameObject pickableObject, GameObject totemPrefab)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			Pickable component = pickableObject.GetComponent<Pickable>();
			if ((Object)(object)component == (Object)null)
			{
				throw new InvalidOperationException("The selected Pickable template did not instantiate correctly.");
			}
			((MonoBehaviour)component).CancelInvoke();
			component.m_itemPrefab = totemPrefab;
			component.m_amount = 1;
			component.m_minAmountScaled = 1;
			component.m_dontScale = true;
			component.m_extraDrops = new DropTable();
			component.m_hideWhenPicked = null;
			component.m_respawnTimeMinutes = 0f;
			component.m_tarPreventsPicking = false;
			component.m_aggravateRange = 0f;
			component.m_harvestable = false;
			component.m_pickRaiseSkill = (SkillType)0;
			Renderer[] componentsInChildren = pickableObject.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].enabled = false;
			}
			SphereCollider obj = pickableObject.AddComponent<SphereCollider>();
			obj.radius = 0.6f;
			((Collider)obj).isTrigger = false;
		}

		private static GameObject FindPickableTemplate(ZNetScene scene)
		{
			GameObject val = FindPrefab(scene, "Pickable_Branch", "pickable_branch", "Pickable_Barley", "pickable_barley");
			if ((Object)(object)val != (Object)null && (Object)(object)val.GetComponent<Pickable>() != (Object)null)
			{
				return val;
			}
			for (int i = 0; i < scene.m_prefabs.Count; i++)
			{
				GameObject val2 = scene.m_prefabs[i];
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2.GetComponent<Pickable>() != (Object)null)
				{
					return val2;
				}
			}
			return null;
		}

		private static GameObject FindPrefab(ZNetScene scene, params string[] candidateNames)
		{
			for (int i = 0; i < candidateNames.Length; i++)
			{
				GameObject prefab = scene.GetPrefab(candidateNames[i]);
				if ((Object)(object)prefab != (Object)null)
				{
					return prefab;
				}
			}
			for (int j = 0; j < scene.m_prefabs.Count; j++)
			{
				GameObject val = scene.m_prefabs[j];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				for (int k = 0; k < candidateNames.Length; k++)
				{
					if (string.Equals(((Object)val).name, candidateNames[k], StringComparison.OrdinalIgnoreCase))
					{
						return val;
					}
				}
			}
			return null;
		}

		private static GameObject Spawn(GameObject prefab, Vector3 position, Quaternion rotation)
		{
			//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)
			GameObject val = Object.Instantiate<GameObject>(prefab, position, rotation);
			ZNetView component = val.GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid())
			{
				component.GetZDO().Persistent = false;
			}
			SpawnedTestObjects.Add(val);
			return val;
		}

		private static Vector3 GroundPosition(Vector3 position)
		{
			//IL_0005: 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)
			float y = default(float);
			if (ZoneSystem.instance.GetGroundHeight(position, ref y))
			{
				position.y = y;
			}
			return position;
		}

		internal static int ClearTestScenario()
		{
			int num = 0;
			ZNetScene instance = ZNetScene.instance;
			for (int num2 = SpawnedTestObjects.Count - 1; num2 >= 0; num2--)
			{
				GameObject val = SpawnedTestObjects[num2];
				if (!((Object)(object)val == (Object)null))
				{
					if ((Object)(object)instance != (Object)null)
					{
						instance.Destroy(val);
					}
					else
					{
						Object.Destroy((Object)(object)val);
					}
					num++;
				}
			}
			SpawnedTestObjects.Clear();
			if (num > 0)
			{
				ZLog.Log((object)string.Format("[{0}] Cleared {1} tracked test scenario objects.", "TotemSentinel", num));
			}
			return num;
		}

		private static void WriteStatus(Terminal context)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			if (context != null)
			{
				context.AddString("ComfySentinel 1.5.2: running");
			}
			if (context != null)
			{
				context.AddString("Sonar session: " + (TotemSentinelPlugin.HasActiveSonarSession ? "active" : "waiting for a totem") + "; " + $"charges: {TotemSentinelPlugin.ActiveSonarCharges}/{TotemSentinelPlugin.MaximumStoredSonarCharges}; " + $"per totem: {TotemSentinelPlugin.MaxSonarCharges.Value}; radius: {TotemSentinelPlugin.ScanRadius.Value:0.#}m; " + $"hotkey: {TotemSentinelPlugin.PingHotkey.Value}");
			}
			if (context != null)
			{
				context.AddString($"State duration: {TotemSentinelPlugin.StateDuration.Value:0.#}s; " + $"final summary: {TotemSentinelPlugin.FinalSummaryDuration.Value:0.#}s");
			}
			if (context != null)
			{
				context.AddString($"Tracked scenario objects: {SpawnedTestObjects.Count}");
			}
		}
	}
}