Decompiled source of Trapped Luggage v3.1.0

tony4twentys-Trapped Luggage.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using ExitGames.Client.Photon;
using HarmonyLib;
using Peak;
using Peak.Island;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyTitle("Trapped Luggage")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Trapped Luggage")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("116b48d9-8079-4ed0-9ea8-d6b2b553b8c6")]
[assembly: AssemblyFileVersion("3.1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("3.1.0.0")]
[module: UnverifiableCode]
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace TrappedLuggage
{
	[BepInPlugin("tony4twentys.Trapped_Luggage", "Trapped Luggage", "3.1.0")]
	public class TrappedLuggagePlugin : BaseUnityPlugin, IOnEventCallback, IInRoomCallbacks, IMatchmakingCallbacks
	{
		private struct EruptionTune
		{
			public Vector3 Pos;

			public float Speed;

			public float Skip;

			public float Expires;
		}

		private struct TrapChanceConfig
		{
			public ConfigEntry<bool> Enable;

			public ConfigEntry<int> Chance;

			public bool AllClients;

			public string Section;

			public string Prefix;
		}

		private struct TrapRoll
		{
			public TrapChanceConfig Trap;

			public string Name;

			public Action Spawn;

			public TrapRoll(TrapChanceConfig trap, string name, Action spawn)
			{
				Trap = trap;
				Name = name;
				Spawn = spawn;
			}
		}

		internal static bool CatalogLoadInProgress;

		private const ushort FallbackDynamiteID = 106;

		internal const byte EruptionEventCode = 199;

		internal const string EruptionEventMagic = "tony4twentys.Trapped_Luggage";

		private const int EruptionEventProtocol = 2;

		private const byte SubEruptionTiming = 1;

		private const byte SubHostSettings = 2;

		private const byte SubCloneTrap = 3;

		private const byte SubDynamiteNoCook = 4;

		private const byte SubPresence = 5;

		private const byte KindSpider = 1;

		private const byte KindFlytrap = 2;

		private const byte KindCondor = 3;

		private const byte KindRaven = 4;

		private const byte KindSpike = 5;

		private const byte KindJellyfish = 6;

		private const byte KindUrchin = 7;

		private const byte KindFlashPlant = 8;

		private const byte KindGeyser = 9;

		private const byte KindExploShroom = 10;

		private const byte KindPoisonShroom = 11;

		private const byte KindAntiSphere = 12;

		private const byte KindEruption = 13;

		private const byte KindGhostVfx = 14;

		private const byte KindRavenVfx = 15;

		private const byte KindTrickLuggage = 16;

		private const byte KindTumbleweed = 17;

		private const byte KindGhostBall = 18;

		private const byte KindArrows = 19;

		private const byte KindThornsStatus = 20;

		private bool _applyingRemoteClone;

		private Harmony _harmony;

		private PhotonView _tornadoInitView;

		private string _resolvedZombiePrefab;

		private string _resolvedGhostPrefab;

		private string _resolvedAntiSpherePrefab;

		private ushort _resolvedDynamiteId;

		private string _resolvedDynamitePrefabName;

		private bool _dynamiteResolved;

		internal static readonly HashSet<int> OurTornadoViewIds = new HashSet<int>();

		internal static readonly HashSet<int> OurRavenViewIds = new HashSet<int>();

		internal static readonly HashSet<int> OurTumbleweedIds = new HashSet<int>();

		internal static readonly HashSet<int> OurZombieViewIds = new HashSet<int>();

		internal static readonly HashSet<int> OurDynamiteViewIds = new HashSet<int>();

		internal static readonly HashSet<int> OurCondorIds = new HashSet<int>();

		internal static readonly HashSet<int> OurMobIds = new HashSet<int>();

		internal static bool NextExplosionNoCook;

		internal static float PendingTornadoLifetime = 5f;

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

		private readonly Dictionary<int, GameObject> _hazardProtos = new Dictionary<int, GameObject>();

		private readonly Dictionary<string, GameObject> _trapProtos = new Dictionary<string, GameObject>();

		private GameObject _eruptionProto;

		private bool _catalogLoadStarted;

		private bool _catalogLoadDone;

		private bool _catalogSandwichActive;

		private string _catalogReturnScene;

		private GameObject _protoHolder;

		private GameObject _catalogCover;

		private bool _loggedNetPrefabs;

		private const string NetPoolPrefix = "TL_Net_";

		private static readonly string[] NetworkedTrapKeys = new string[8] { "spider", "flytrap", "condor", "voicethief", "spiketrap", "jellyfish", "ghostball", "antisphere" };

		internal ConfigEntry<bool> enableHostOnlyTraps;

		internal ConfigEntry<bool> enableAllClientsTraps;

		internal ConfigEntry<bool> dynamiteCooksItems;

		internal ConfigEntry<bool> trapRespawnStatue;

		internal ConfigEntry<int> maxTrapsPerLuggage;

		internal ConfigEntry<int> trapChancePercent;

		internal ConfigEntry<bool> enableDebugLogging;

		internal ConfigEntry<KeyCode> rosterMenuKey;

		internal ConfigEntry<KeyCode> rosterMenuModifier;

		internal ConfigEntry<bool> rosterMenuUseModifier;

		private readonly HashSet<int> _peersWithMod = new HashSet<int>();

		private bool _rosterHotkeyErrorLogged;

		private TrapChanceConfig litDynamite;

		private ConfigEntry<int> dynamiteCountMin;

		private ConfigEntry<int> dynamiteCountMax;

		private ConfigEntry<float> dynamiteFuseSeconds;

		private TrapChanceConfig scorpions;

		private ConfigEntry<int> scorpionCountMin;

		private ConfigEntry<int> scorpionCountMax;

		private ConfigEntry<float> scorpionLifetime;

		private TrapChanceConfig beetles;

		private ConfigEntry<int> beetleCountMin;

		private ConfigEntry<int> beetleCountMax;

		private ConfigEntry<float> beetleLifetime;

		private TrapChanceConfig frogs;

		private ConfigEntry<int> frogCountMin;

		private ConfigEntry<int> frogCountMax;

		private ConfigEntry<float> frogLifetime;

		private TrapChanceConfig scoutmaster;

		private ConfigEntry<int> scoutmasterCountMin;

		private ConfigEntry<int> scoutmasterCountMax;

		private ConfigEntry<float> scoutmasterChaseTime;

		private TrapChanceConfig condors;

		private ConfigEntry<float> condorHeight;

		private ConfigEntry<float> condorRadius;

		private ConfigEntry<float> condorNestHeight;

		private ConfigEntry<float> condorLifetime;

		private TrapChanceConfig beeSwarm;

		private ConfigEntry<int> beeSwarmCountMin;

		private ConfigEntry<int> beeSwarmCountMax;

		private ConfigEntry<float> beeSwarmAngerTime;

		private TrapChanceConfig tornado;

		private ConfigEntry<int> tornadoCountMin;

		private ConfigEntry<int> tornadoCountMax;

		private ConfigEntry<float> tornadoLifetime;

		private TrapChanceConfig zombies;

		private ConfigEntry<int> zombieCountMin;

		private ConfigEntry<int> zombieCountMax;

		private ConfigEntry<float> zombieLifetime;

		private ConfigEntry<float> zombieChaseTime;

		private TrapChanceConfig ghostBall;

		private ConfigEntry<float> ghostBallLifetime;

		private ConfigEntry<float> ghostBallDelay;

		private ConfigEntry<float> ghostSpawnDistance;

		private ConfigEntry<float> ghostSpawnHeight;

		private ConfigEntry<bool> ghostBurstParticles;

		private ConfigEntry<float> ghostFaceTime;

		private ConfigEntry<float> ghostChargeSpeedMult;

		private TrapChanceConfig spiders;

		private ConfigEntry<float> spiderHeight;

		private ConfigEntry<float> spiderLifetime;

		private ConfigEntry<float> spiderDropDelay;

		private TrapChanceConfig flytraps;

		private ConfigEntry<int> flytrapCountMin;

		private ConfigEntry<int> flytrapCountMax;

		private TrapChanceConfig spikeTraps;

		private ConfigEntry<int> spikeTrapCountMin;

		private ConfigEntry<int> spikeTrapCountMax;

		private TrapChanceConfig thorns;

		private ConfigEntry<int> thornCount;

		private ConfigEntry<bool> thornsSpawnCactusBalls;

		private ConfigEntry<int> cactusBallCountMin;

		private ConfigEntry<int> cactusBallCountMax;

		private TrapChanceConfig arrowTraps;

		private ConfigEntry<int> arrowCountMin;

		private ConfigEntry<int> arrowCountMax;

		private TrapChanceConfig mandrakes;

		private ConfigEntry<int> mandrakeCountMin;

		private ConfigEntry<int> mandrakeCountMax;

		private TrapChanceConfig antiSphere;

		private ConfigEntry<int> antiSphereCountMin;

		private ConfigEntry<int> antiSphereCountMax;

		private TrapChanceConfig ravens;

		private ConfigEntry<int> ravenCountMin;

		private ConfigEntry<int> ravenCountMax;

		private ConfigEntry<bool> ravenBurstParticles;

		private ConfigEntry<float> ravenFlyLifetime;

		private TrapChanceConfig jellyfish;

		private ConfigEntry<int> jellyfishCountMin;

		private ConfigEntry<int> jellyfishCountMax;

		private TrapChanceConfig tumbleweeds;

		private ConfigEntry<int> tumbleweedCountMin;

		private ConfigEntry<int> tumbleweedCountMax;

		private TrapChanceConfig explodingMushrooms;

		private ConfigEntry<int> explodingMushroomCountMin;

		private ConfigEntry<int> explodingMushroomCountMax;

		private TrapChanceConfig poisonMushrooms;

		private ConfigEntry<int> poisonMushroomCountMin;

		private ConfigEntry<int> poisonMushroomCountMax;

		private TrapChanceConfig trickLuggage;

		private TrapChanceConfig tickTrap;

		private ConfigEntry<int> tickCountMin;

		private ConfigEntry<int> tickCountMax;

		private TrapChanceConfig urchins;

		private ConfigEntry<int> urchinCountMin;

		private ConfigEntry<int> urchinCountMax;

		private TrapChanceConfig flashPlant;

		private ConfigEntry<int> flashPlantCountMin;

		private ConfigEntry<int> flashPlantCountMax;

		private TrapChanceConfig geysers;

		private ConfigEntry<int> geyserCountMin;

		private ConfigEntry<int> geyserCountMax;

		private ConfigEntry<float> geyserKnockbackMult;

		private ConfigEntry<float> geyserVerticalKnockbackMult;

		private ConfigEntry<float> geyserParticleSpeedMult;

		private ConfigEntry<float> geyserRangeMult;

		private TrapChanceConfig eruptions;

		private ConfigEntry<float> eruptionWindupSpeed;

		private ConfigEntry<float> eruptionSkipAheadSeconds;

		private readonly List<EruptionTune> _pendingEruptionTunes = new List<EruptionTune>();

		private readonly HashSet<int> _timedEruptionIds = new HashSet<int>();

		private readonly List<ConfigEntryBase> _syncedConfig = new List<ConfigEntryBase>();

		private readonly Dictionary<string, object> _hostSettings = new Dictionary<string, object>();

		private bool _haveHostSettings;

		private static readonly List<Func<IEnumerator>> WilIslandPostCacheRoutines = new List<Func<IEnumerator>>();

		private static readonly SETTINGTYPE[] HazardSettingsToCache;

		public static TrappedLuggagePlugin Instance { get; private set; }

		public static int WilIslandPostCacheRoutineCount => WilIslandPostCacheRoutines.Count;

		public static bool RegisterWilIslandPostCacheRoutine(Func<IEnumerator> routine)
		{
			if (routine == null)
			{
				return false;
			}
			if (WilIslandPostCacheRoutines.Contains(routine))
			{
				return true;
			}
			WilIslandPostCacheRoutines.Add(routine);
			return true;
		}

		private IEnumerator RunWilIslandPostCacheRoutines()
		{
			if (WilIslandPostCacheRoutines.Count == 0)
			{
				yield break;
			}
			Log("[Trapped Luggage] Running " + WilIslandPostCacheRoutines.Count + " WilIsland post-cache routine(s).");
			for (int i = 0; i < WilIslandPostCacheRoutines.Count; i++)
			{
				Func<IEnumerator> factory = WilIslandPostCacheRoutines[i];
				if (factory == null)
				{
					continue;
				}
				IEnumerator routine;
				try
				{
					routine = factory();
				}
				catch (Exception ex)
				{
					Exception ex2 = ex;
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[Trapped Luggage] WilIsland post-cache routine failed to start: " + ex2.Message));
					continue;
				}
				if (routine != null)
				{
					while (routine.MoveNext())
					{
						yield return routine.Current;
					}
				}
			}
		}

		private void Awake()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			Instance = this;
			SetupConfig();
			WriteInfo("Trapped Luggage v3.1.0 loaded!");
			_harmony = new Harmony("tony4twentys.Trapped_Luggage");
			_harmony.PatchAll();
			SceneManager.sceneLoaded += OnSceneLoaded;
			PhotonNetwork.AddCallbackTarget((object)this);
			ModRosterMenu.Ensure();
			if (PhotonNetwork.InRoom)
			{
				BroadcastPresence();
				if (PhotonNetwork.IsMasterClient)
				{
					BroadcastHostSettings();
				}
			}
			Log("Harmony patches applied.");
		}

		private void Update()
		{
			try
			{
				if (IsRosterHotkeyDown())
				{
					ModRosterMenu.Toggle();
				}
				else if (ModRosterMenu.IsOpen && Input.GetKeyDown((KeyCode)27))
				{
					ModRosterMenu.Close();
				}
			}
			catch (Exception ex)
			{
				if (!_rosterHotkeyErrorLogged)
				{
					_rosterHotkeyErrorLogged = true;
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Roster hotkey failed: " + ex.Message));
				}
			}
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
			PhotonNetwork.RemoveCallbackTarget((object)this);
			ModRosterMenu.DestroyInstance();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		private unsafe void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (!((Scene)(ref scene)).IsValid())
			{
				return;
			}
			string text = ((Scene)(ref scene)).name ?? "";
			if (IsWilIslandName(text))
			{
				try
				{
					CacheWilIslandMap(scene);
					CacheAllHazardTemplatesFromLoadedBiomes("WilIsland:" + ((object)(*(LoadSceneMode*)(&mode))/*cast due to .constrained prefix*/).ToString());
					return;
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("WilIsland scrape failed: " + ex.Message));
					return;
				}
			}
			if (text.IndexOf("Title", StringComparison.OrdinalIgnoreCase) < 0)
			{
				try
				{
					CacheAllHazardTemplatesFromLoadedBiomes("SceneLoaded:" + text);
				}
				catch (Exception ex2)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Hazard cache at scene '" + text + "' failed: " + ex2.Message));
				}
				if (IsAirportName(text) && _catalogLoadDone)
				{
					HideCatalogCover();
				}
			}
		}

		internal bool ShouldInsertCatalogBeforeAirport(string sceneName)
		{
			if (_catalogLoadDone || _catalogLoadStarted || _catalogSandwichActive)
			{
				return false;
			}
			return IsAirportName(sceneName);
		}

		internal void StartAirportSandwichFromDirectLoad(string airportName)
		{
			ShowCatalogCover();
			_catalogLoadStarted = true;
			_catalogSandwichActive = true;
			CatalogLoadInProgress = true;
			_catalogReturnScene = airportName;
			((MonoBehaviour)this).StartCoroutine(CatalogSandwichRoutine());
		}

		internal IEnumerator CatalogThenAirportProcess(LoadingScreenHandler handler, string airportName, bool networked, bool yieldForCharacterSpawn, float extraYieldTimeOnEnd)
		{
			ShowCatalogCover();
			_catalogLoadStarted = true;
			_catalogSandwichActive = true;
			CatalogLoadInProgress = true;
			Log("Airport load intercepted — WilIsland catalog under the loading screen, then Airport. Once per session.");
			string wil = ResolveWilIslandSceneName();
			IEnumerator wilLoad = handler.LoadSceneProcess(wil, false, false, 0f);
			while (wilLoad.MoveNext())
			{
				yield return wilLoad.Current;
			}
			yield return null;
			yield return null;
			try
			{
				if (TryGetLoadedWilIsland(out var wilScene))
				{
					CacheWilIslandMap(wilScene);
				}
				CacheAllHazardTemplatesFromLoadedBiomes("WilIslandSandwich");
			}
			catch (Exception ex)
			{
				Exception ex2 = ex;
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Catalog sandwich scrape failed: " + ex2.Message));
			}
			IEnumerator postCache = RunWilIslandPostCacheRoutines();
			while (postCache.MoveNext())
			{
				yield return postCache.Current;
			}
			_catalogLoadDone = true;
			_catalogSandwichActive = false;
			CatalogLoadInProgress = false;
			RegisterNetworkedTrapPrefabs();
			Log(string.Format("Catalog sandwich done. eruption={0} trapProtos={1}. Continuing to '{2}'.", ((Object)(object)_eruptionProto != (Object)null) ? ((Object)_eruptionProto).name : "none", _trapProtos.Count, airportName));
			IEnumerator airportLoad = handler.LoadSceneProcess(airportName, networked, yieldForCharacterSpawn, extraYieldTimeOnEnd);
			while (airportLoad.MoveNext())
			{
				yield return airportLoad.Current;
			}
			HideCatalogCover();
		}

		private void TryStartCatalogSandwich(string current)
		{
			if (ShouldInsertCatalogBeforeAirport(current))
			{
				StartAirportSandwichFromDirectLoad(current);
			}
		}

		private IEnumerator CatalogSandwichRoutine()
		{
			string back = (string.IsNullOrEmpty(_catalogReturnScene) ? "Airport" : _catalogReturnScene);
			string wil = ResolveWilIslandSceneName();
			Log("Catalog sandwich: '" + wil + "' (Single), then '" + back + "'. Once per session.");
			AsyncOperation op = SceneManager.LoadSceneAsync(wil, (LoadSceneMode)0);
			if (op == null && !wil.Equals("WilIsland", StringComparison.OrdinalIgnoreCase))
			{
				op = SceneManager.LoadSceneAsync("WilIsland", (LoadSceneMode)0);
			}
			if (op == null && !wil.Equals("Willsland", StringComparison.OrdinalIgnoreCase))
			{
				op = SceneManager.LoadSceneAsync("Willsland", (LoadSceneMode)0);
			}
			if (op == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Catalog sandwich: could not load WilIsland.");
				_catalogSandwichActive = false;
				CatalogLoadInProgress = false;
				_catalogLoadStarted = false;
				HideCatalogCover();
				yield break;
			}
			while (!op.isDone)
			{
				yield return null;
			}
			yield return null;
			yield return null;
			try
			{
				if (TryGetLoadedWilIsland(out var wilScene))
				{
					CacheWilIslandMap(wilScene);
				}
				CacheAllHazardTemplatesFromLoadedBiomes("WilIslandSandwich");
			}
			catch (Exception ex)
			{
				Exception ex2 = ex;
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Catalog sandwich scrape failed: " + ex2.Message));
			}
			IEnumerator postCache = RunWilIslandPostCacheRoutines();
			while (postCache.MoveNext())
			{
				yield return postCache.Current;
			}
			_catalogLoadDone = true;
			_catalogSandwichActive = false;
			CatalogLoadInProgress = false;
			RegisterNetworkedTrapPrefabs();
			Log(string.Format("Catalog sandwich done. eruption={0} trapProtos={1}. Loading '{2}'.", ((Object)(object)_eruptionProto != (Object)null) ? ((Object)_eruptionProto).name : "none", _trapProtos.Count, back));
			op = SceneManager.LoadSceneAsync(back, (LoadSceneMode)0);
			if (op == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Catalog sandwich: failed to return to '" + back + "'."));
				HideCatalogCover();
				yield break;
			}
			while (!op.isDone)
			{
				yield return null;
			}
			HideCatalogCover();
		}

		internal void ShowCatalogCover()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_catalogCover != (Object)null))
			{
				_catalogCover = new GameObject("TL_CatalogCover");
				Object.DontDestroyOnLoad((Object)(object)_catalogCover);
				Camera val = _catalogCover.AddComponent<Camera>();
				val.clearFlags = (CameraClearFlags)2;
				val.backgroundColor = Color.black;
				val.cullingMask = 0;
				val.depth = 1000f;
				val.allowHDR = false;
				val.allowMSAA = false;
				val.useOcclusionCulling = false;
			}
		}

		internal void HideCatalogCover()
		{
			if (!((Object)(object)_catalogCover == (Object)null))
			{
				Object.Destroy((Object)(object)_catalogCover);
				_catalogCover = null;
			}
		}

		internal static bool IsWilIslandName(string n)
		{
			if (string.IsNullOrEmpty(n))
			{
				return false;
			}
			if (n.Equals("WilIsland", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (n.Equals("Willsland", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return n.IndexOf("Wil", StringComparison.OrdinalIgnoreCase) >= 0 && n.IndexOf("Island", StringComparison.OrdinalIgnoreCase) >= 0;
		}

		private static bool IsAirportName(string n)
		{
			return !string.IsNullOrEmpty(n) && n.IndexOf("Airport", StringComparison.OrdinalIgnoreCase) >= 0;
		}

		internal static bool ShouldSkipCatalogBehaviour(Component c)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)c == (Object)null) && !((Object)(object)c.gameObject == (Object)null))
			{
				Scene scene = c.gameObject.scene;
				if (IsWilIslandName(((Scene)(ref scene)).name))
				{
					return CatalogLoadInProgress || ((Object)(object)Instance != (Object)null && Instance._catalogSandwichActive);
				}
			}
			return false;
		}

		private static string FileNameNoExt(string path)
		{
			if (string.IsNullOrEmpty(path))
			{
				return "";
			}
			int num = Math.Max(path.LastIndexOf('/'), path.LastIndexOf('\\'));
			string text = ((num >= 0) ? path.Substring(num + 1) : path);
			int num2 = text.LastIndexOf('.');
			return (num2 >= 0) ? text.Substring(0, num2) : text;
		}

		private string ResolveWilIslandSceneName()
		{
			int sceneCountInBuildSettings = SceneManager.sceneCountInBuildSettings;
			List<string> list = new List<string>();
			string text = null;
			for (int i = 0; i < sceneCountInBuildSettings; i++)
			{
				string text2 = FileNameNoExt(SceneUtility.GetScenePathByBuildIndex(i));
				list.Add(text2);
				if (text == null && IsWilIslandName(text2))
				{
					text = text2;
				}
			}
			Log("Build scenes (" + list.Count + "): " + string.Join(", ", list.ToArray()));
			return text ?? "WilIsland";
		}

		private bool TryGetLoadedWilIsland(out Scene scene)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			int sceneCount = SceneManager.sceneCount;
			for (int i = 0; i < sceneCount; i++)
			{
				Scene sceneAt = SceneManager.GetSceneAt(i);
				if (((Scene)(ref sceneAt)).IsValid() && ((Scene)(ref sceneAt)).isLoaded && IsWilIslandName(((Scene)(ref sceneAt)).name))
				{
					scene = sceneAt;
					return true;
				}
			}
			scene = default(Scene);
			return false;
		}

		private void CacheWilIslandMapScenes()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			int sceneCount = SceneManager.sceneCount;
			for (int i = 0; i < sceneCount; i++)
			{
				Scene sceneAt = SceneManager.GetSceneAt(i);
				if (((Scene)(ref sceneAt)).IsValid() && ((Scene)(ref sceneAt)).isLoaded && IsWilIslandName(((Scene)(ref sceneAt)).name))
				{
					CacheWilIslandMap(sceneAt);
				}
			}
		}

		private void CacheWilIslandMap(Scene scene)
		{
			if (!((Scene)(ref scene)).IsValid() || !((Scene)(ref scene)).isLoaded)
			{
				return;
			}
			GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects();
			foreach (GameObject val in rootGameObjects)
			{
				if ((Object)(object)val == (Object)null || ((Object)val).name != "Map")
				{
					continue;
				}
				Log($"WilIsland Map in '{((Scene)(ref scene)).name}': children={val.transform.childCount}");
				for (int j = 0; j < val.transform.childCount; j++)
				{
					Transform child = val.transform.GetChild(j);
					if (!((Object)(object)child == (Object)null))
					{
						Log($"  Map/{((Object)child).name} active={((Component)child).gameObject.activeSelf}");
						CacheHazardsUnder(((Component)child).gameObject);
					}
				}
				CacheHazardsUnder(val);
			}
		}

		private TrapChanceConfig BindTrap(string prefix, int defaultChance = 10, bool allClients = false, bool defaultEnable = true)
		{
			string text = (allClients ? "AllClients" : "HostOnly");
			return new TrapChanceConfig
			{
				Enable = Track<bool>(((BaseUnityPlugin)this).Config.Bind<bool>(text, prefix + "Enable", defaultEnable, allClients ? ("Enable " + prefix + ". Scene/WilIsland clone — every player who should see it needs this mod.") : ("Enable " + prefix + ". Photon spawn — the whole lobby sees it even if only the host has this mod."))),
				Chance = Track<int>(((BaseUnityPlugin)this).Config.Bind<int>(text, prefix + "_ChancePercent", defaultChance, "Relative weight for " + prefix + " after the bag has already rolled a trap. Higher = more likely than other enabled types. 0 = never picked.")),
				AllClients = allClients,
				Section = text,
				Prefix = prefix
			};
		}

		private ConfigEntry<T> BindOpt<T>(TrapChanceConfig trap, string suffix, T defaultValue, string description)
		{
			return Track<T>(((BaseUnityPlugin)this).Config.Bind<T>(trap.Section, trap.Prefix + "_" + suffix, defaultValue, description));
		}

		private ConfigEntry<T> Track<T>(ConfigEntry<T> entry)
		{
			if (entry != null)
			{
				_syncedConfig.Add((ConfigEntryBase)(object)entry);
			}
			return entry;
		}

		internal void Log(string message)
		{
			if (enableDebugLogging != null && enableDebugLogging.Value)
			{
				WriteInfo(message);
			}
		}

		private void WriteInfo(string message)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)message);
		}

		internal T S<T>(ConfigEntry<T> entry)
		{
			if (entry == null)
			{
				return default(T);
			}
			if (PhotonNetwork.IsMasterClient || !_haveHostSettings)
			{
				return entry.Value;
			}
			if (_hostSettings.TryGetValue(ConfigKey((ConfigEntryBase)(object)entry), out var value) && value != null)
			{
				if (value is T result)
				{
					return result;
				}
				try
				{
					return (T)Convert.ChangeType(value, typeof(T));
				}
				catch
				{
				}
			}
			return entry.Value;
		}

		private static string ConfigKey(ConfigEntryBase entry)
		{
			return entry.Definition.Section + "." + entry.Definition.Key;
		}

		private void SetupConfig()
		{
			enableDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableDebugLogging", false, "If true, write trap rolls, scrapes, and spawn details to the BepInEx log. Off by default. Turn on only when testing or sending logs. Warnings still print either way. This setting is local and is not taken from the host.");
			rosterMenuKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "RosterMenuKey", (KeyCode)92, "Key that opens the player roster (who has this mod). Used with RosterMenuModifier when RosterMenuUseModifier is on.");
			rosterMenuModifier = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "RosterMenuModifier", (KeyCode)306, "Optional modifier for the roster menu. Default LeftControl (Ctrl+\\). LeftControl also accepts RightControl. Set to None or turn off RosterMenuUseModifier to use the key alone.");
			rosterMenuUseModifier = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RosterMenuUseModifier", true, "If true, hold RosterMenuModifier plus RosterMenuKey to open the roster. If false, RosterMenuKey alone toggles it.");
			enableHostOnlyTraps = Track<bool>(((BaseUnityPlugin)this).Config.Bind<bool>("HostOnly", "EnableHostOnlyTraps", true, "Master switch for Photon loot/mobs (scorpions, dynamite, Scoutmaster, ticks, …). The whole lobby sees them even if only the host has this mod. Clients with the mod still use the host's chances."));
			enableAllClientsTraps = Track<bool>(((BaseUnityPlugin)this).Config.Bind<bool>("AllClients", "EnableAllClientsTraps", true, "Master switch for WilIsland/scene clones (spiders, flytraps, condors, ravens, geysers, …). The host still rolls them. Anyone who should see the trap needs this mod. Turn this OFF to never roll any AllClients traps."));
			ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>("HostOnly", "TrapRespawnCoffin", false, "Obsolete. Use General.TrapRespawnStatue.");
			bool value = val.Value;
			((BaseUnityPlugin)this).Config.Remove(((ConfigEntryBase)val).Definition);
			trapRespawnStatue = Track<bool>(((BaseUnityPlugin)this).Config.Bind<bool>("General", "TrapRespawnStatue", value, "If false, opening a scout statue / respawn coffin never rolls traps. Those bags are for mystic items and player respawns."));
			ConfigEntry<int> val2 = ((BaseUnityPlugin)this).Config.Bind<int>("HostOnly", "MaxTrapsPerLuggage", 1, "Obsolete. Use General.MaxTrapsPerLuggage.");
			((BaseUnityPlugin)this).Config.Remove(((ConfigEntryBase)val2).Definition);
			maxTrapsPerLuggage = Track<int>(((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxTrapsPerLuggage", 1, "-1 = keep rolling extra traps (same TrapChancePercent) until a miss or every type is used. 0 = no traps. 1+ = at most that many different types per bag, never the same type twice. The first trap still has to pass TrapChancePercent."));
			trapChancePercent = Track<int>(((BaseUnityPlugin)this).Config.Bind<int>("General", "TrapChancePercent", 10, "Percentage chance (0-100) that opened luggage has any trap at all. If it hits and MaxTrapsPerLuggage allows more than one, this same chance is rolled again for each extra trap. Each trap type's ChancePercent is only a weight for which type is picked."));
			antiSphere = BindTrap("AntiGravSphere");
			antiSphereCountMin = BindOpt(antiSphere, "CountMin", 1, "Minimum anti-grav spheres.");
			antiSphereCountMax = BindOpt(antiSphere, "CountMax", 2, "Maximum anti-grav spheres.");
			beeSwarm = BindTrap("BeeSwarm");
			beeSwarmCountMin = BindOpt(beeSwarm, "CountMin", 1, "Minimum bee swarms.");
			beeSwarmCountMax = BindOpt(beeSwarm, "CountMax", 2, "Maximum bee swarms.");
			beeSwarmAngerTime = BindOpt(beeSwarm, "AngerDuration", 20f, "Seconds bees stay angry.");
			beetles = BindTrap("Beetles");
			beetleCountMin = BindOpt(beetles, "CountMin", 1, "Minimum beetles.");
			beetleCountMax = BindOpt(beetles, "CountMax", 2, "Maximum beetles.");
			beetleLifetime = BindOpt(beetles, "Lifetime", 30f, "Seconds before beetles despawn. 0 = stay until the biome unloads.");
			litDynamite = BindTrap("Dynamite");
			dynamiteCountMin = BindOpt(litDynamite, "CountMin", 1, "Minimum lit dynamite sticks to drop into the luggage.");
			dynamiteCountMax = BindOpt(litDynamite, "CountMax", 2, "Maximum lit dynamite sticks to drop into the luggage.");
			dynamiteFuseSeconds = BindOpt(litDynamite, "FuseSeconds", 0f, "Lit fuse length. 0 = explode instantly. Vanilla is about 5 seconds.");
			dynamiteCooksItems = BindOpt(litDynamite, "CookItemsOnExplode", defaultValue: false, "If false, only dynamite spawned by this trap will not cook nearby items. World / loot dynamite still cooks.");
			frogs = BindTrap("Frogs");
			frogCountMin = BindOpt(frogs, "CountMin", 1, "Minimum frogs.");
			frogCountMax = BindOpt(frogs, "CountMax", 2, "Maximum frogs.");
			frogLifetime = BindOpt(frogs, "Lifetime", 30f, "Seconds before frogs despawn. 0 = stay until the biome unloads.");
			ghostBall = BindTrap("GhostBall", 10, allClients: true);
			ghostBallLifetime = BindOpt(ghostBall, "Lifetime", 45f, "Seconds the ghost can exist before it fades. Counts up from 0.");
			ghostBallDelay = BindOpt(ghostBall, "SpawnDelay", 1f, "Seconds to wait after opening luggage before the ghost appears.");
			ghostSpawnDistance = BindOpt(ghostBall, "SpawnDistanceAhead", 1f, "How far in front of the opener the ghost appears, then charges in.");
			ghostSpawnHeight = BindOpt(ghostBall, "SpawnHeightOffset", 1.5f, "Height above the opener when the ghost appears (already in the air, not rising out of the ground).");
			ghostFaceTime = BindOpt(ghostBall, "FaceTargetSeconds", 0.55f, "How long the ghost holds and faces the opener before charging.");
			ghostChargeSpeedMult = BindOpt(ghostBall, "ChargeSpeedMultiplier", 3.5f, "Vanilla chase speed multiplied while charging at the opener.");
			ghostBurstParticles = BindOpt(ghostBall, "AlsoBurstFogGhosts", defaultValue: true, "Burst Gloom fog-ghost particles out of the luggage immediately (not delayed with the ball). Gloom only.");
			mandrakes = BindTrap("Mandrakes");
			mandrakeCountMin = BindOpt(mandrakes, "CountMin", 1, "Minimum mandrakes.");
			mandrakeCountMax = BindOpt(mandrakes, "CountMax", 2, "Maximum mandrakes.");
			zombies = BindTrap("MushroomZombies");
			zombieCountMin = BindOpt(zombies, "CountMin", 1, "Minimum zombies.");
			zombieCountMax = BindOpt(zombies, "CountMax", 2, "Maximum zombies.");
			zombieLifetime = BindOpt(zombies, "Lifetime", 60f, "Seconds before zombies die.");
			zombieChaseTime = BindOpt(zombies, "ForcedChaseTime", 60f, "Seconds zombies are forced onto the opener.");
			ravens = BindTrap("Ravens", 10, allClients: true);
			ravenCountMin = BindOpt(ravens, "CountMin", 2, "Minimum perched ravens to spawn and scare off.");
			ravenCountMax = BindOpt(ravens, "CountMax", 4, "Maximum perched ravens to spawn and scare off.");
			ravenBurstParticles = BindOpt(ravens, "AlsoBurstRavenParticles", defaultValue: true, "Also play the Raven Particles VFX from the luggage.");
			ravenFlyLifetime = BindOpt(ravens, "FlyAwayLifetime", 6f, "Seconds the perched ravens stay in the world after FlyAway starts. Vanilla is 2.5.");
			scorpions = BindTrap("Scorpions");
			scorpionCountMin = BindOpt(scorpions, "CountMin", 1, "Minimum scorpions.");
			scorpionCountMax = BindOpt(scorpions, "CountMax", 2, "Maximum scorpions.");
			scorpionLifetime = BindOpt(scorpions, "Lifetime", 30f, "Seconds before scorpions despawn. 0 = stay until the biome unloads.");
			scoutmaster = BindTrap("Scoutmaster");
			scoutmasterCountMin = BindOpt(scoutmaster, "CountMin", 1, "Minimum Scoutmasters.");
			scoutmasterCountMax = BindOpt(scoutmaster, "CountMax", 2, "Maximum Scoutmasters. Each is a new Scoutmaster.");
			scoutmasterChaseTime = BindOpt(scoutmaster, "ForcedChaseTime", 60f, "Seconds each Scoutmaster is forced to chase the opener.");
			condors = BindTrap("Condors", 10, allClients: true);
			condorHeight = BindOpt(condors, "HeightAbovePlayer", 1f, "How far above the opener the condor appears before it swoops.");
			condorRadius = BindOpt(condors, "LoopRadius", 10f, "How wide the condor circles after a miss / after dropping you.");
			condorNestHeight = BindOpt(condors, "NestHeight", 100f, "Dummy nest height above the luggage if the cloned condor has no nest.");
			condorLifetime = BindOpt(condors, "Lifetime", 25f, "Seconds before the spawned condor is destroyed.");
			tickTrap = BindTrap("TickTrap");
			tickCountMin = BindOpt(tickTrap, "CountMin", 1, "Minimum ticks to attach. Vanilla only keeps one unless PEAK Ticks is installed.");
			tickCountMax = BindOpt(tickTrap, "CountMax", 2, "Maximum ticks to attach. Extra attaches fail quietly without PEAK Ticks.");
			tornado = BindTrap("Tornado");
			tornadoCountMin = BindOpt(tornado, "CountMin", 1, "Minimum tornadoes.");
			tornadoCountMax = BindOpt(tornado, "CountMax", 1, "Maximum tornadoes.");
			tornadoLifetime = BindOpt(tornado, "Lifetime", 5f, "Seconds the tornado lasts.");
			tumbleweeds = BindTrap("Tumbleweeds", 10, allClients: true);
			tumbleweedCountMin = BindOpt(tumbleweeds, "CountMin", 1, "Minimum tumbleweeds.");
			tumbleweedCountMax = BindOpt(tumbleweeds, "CountMax", 2, "Maximum tumbleweeds.");
			arrowTraps = BindTrap("ArrowTraps", 10, allClients: true);
			arrowCountMin = BindOpt(arrowTraps, "CountMin", 1, "Minimum arrows stuck into the opener.");
			arrowCountMax = BindOpt(arrowTraps, "CountMax", 2, "Maximum arrows stuck into the opener.");
			eruptions = BindTrap("Eruptions", 10, allClients: true);
			eruptionWindupSpeed = BindOpt(eruptions, "WindupSpeed", 1f, "How fast the luggage eruption intro plays. 1 = vanilla Caldera rumble. Values below 1 are treated as 1 — lower breaks the spawn.");
			eruptionSkipAheadSeconds = BindOpt(eruptions, "SkipAheadSeconds", 1f, "Jump this many seconds into the eruption as soon as it spawns. Values below 1 are treated as 1 — lower can spawn nothing or the wrong trap.");
			explodingMushrooms = BindTrap("ExplodingMushrooms", 10, allClients: true);
			explodingMushroomCountMin = BindOpt(explodingMushrooms, "CountMin", 1, "Minimum exploding mushrooms.");
			explodingMushroomCountMax = BindOpt(explodingMushrooms, "CountMax", 2, "Maximum exploding mushrooms.");
			flashPlant = BindTrap("FlashPlant", 10, allClients: true);
			flashPlantCountMin = BindOpt(flashPlant, "CountMin", 1, "Minimum flash plants.");
			flashPlantCountMax = BindOpt(flashPlant, "CountMax", 2, "Maximum flash plants.");
			flytraps = BindTrap("Flytraps", 10, allClients: true);
			flytrapCountMin = BindOpt(flytraps, "CountMin", 1, "Minimum flytraps.");
			flytrapCountMax = BindOpt(flytraps, "CountMax", 2, "Maximum flytraps.");
			geysers = BindTrap("Geysers", 10, allClients: true);
			geyserCountMin = BindOpt(geysers, "CountMin", 1, "Minimum geysers.");
			geyserCountMax = BindOpt(geysers, "CountMax", 2, "Maximum geysers.");
			geyserKnockbackMult = BindOpt(geysers, "KnockbackMultiplier", 1f, "Horizontal launch power vs vanilla geyser. 2 = twice as strong.");
			geyserVerticalKnockbackMult = BindOpt(geysers, "VerticalKnockbackMultiplier", 1f, "Upward launch power vs vanilla geyser.");
			geyserParticleSpeedMult = BindOpt(geysers, "ParticleSpeedMultiplier", 1f, "How fast the geyser spray particles erupt.");
			geyserRangeMult = BindOpt(geysers, "RangeMultiplier", 1f, "AOE radius vs vanilla geyser.");
			jellyfish = BindTrap("Jellyfish", 10, allClients: true);
			jellyfishCountMin = BindOpt(jellyfish, "CountMin", 1, "Minimum jellyfish.");
			jellyfishCountMax = BindOpt(jellyfish, "CountMax", 2, "Maximum jellyfish.");
			poisonMushrooms = BindTrap("PoisonMushrooms", 10, allClients: true);
			poisonMushroomCountMin = BindOpt(poisonMushrooms, "CountMin", 1, "Minimum poison spore clouds.");
			poisonMushroomCountMax = BindOpt(poisonMushrooms, "CountMax", 2, "Maximum poison spore clouds.");
			spiders = BindTrap("Spiders", 10, allClients: true);
			spiderHeight = BindOpt(spiders, "HeightAbovePlayer", 5f, "How far above the opener the spider spawns.");
			spiderDropDelay = BindOpt(spiders, "DropDelay", 0.15f, "Seconds to wait after spawn before forcing the drop attack.");
			spiderLifetime = BindOpt(spiders, "Lifetime", 8f, "Seconds before the spider is destroyed (stops mid-air hangers).");
			spikeTraps = BindTrap("SpikeTraps", 10, allClients: true);
			spikeTrapCountMin = BindOpt(spikeTraps, "CountMin", 1, "Minimum spike traps.");
			spikeTrapCountMax = BindOpt(spikeTraps, "CountMax", 2, "Maximum spike traps.");
			thorns = BindTrap("Thorns", 10, allClients: true);
			thornCount = BindOpt(thorns, "ThornStatusCount", 4, "How many thorns to apply directly to the opener.");
			thornsSpawnCactusBalls = BindOpt(thorns, "AlsoSpawnCactusBalls", defaultValue: true, "Also spawn sticky cactus balls near the luggage.");
			cactusBallCountMin = BindOpt(thorns, "CactusBallCountMin", 1, "Minimum cactus balls.");
			cactusBallCountMax = BindOpt(thorns, "CactusBallCountMax", 2, "Maximum cactus balls.");
			trickLuggage = BindTrap("TrickLuggage", 10, allClients: true);
			urchins = BindTrap("Urchins", 10, allClients: true);
			urchinCountMin = BindOpt(urchins, "CountMin", 1, "Minimum urchins.");
			urchinCountMax = BindOpt(urchins, "CountMax", 2, "Maximum urchins.");
		}

		private bool TryResolveDynamite(out ushort id, out string prefabName)
		{
			if (_dynamiteResolved)
			{
				id = _resolvedDynamiteId;
				prefabName = _resolvedDynamitePrefabName;
				return id != 0 && !string.IsNullOrEmpty(prefabName);
			}
			Item val = null;
			if ((!ItemDatabase.TryGetItem("Dynamite", ref val) || !((Object)(object)val != (Object)null)) && (!ItemDatabase.TryGetItem((ushort)106, ref val) || !((Object)(object)val != (Object)null)))
			{
				val = null;
			}
			if ((Object)(object)val == (Object)null)
			{
				Dynamite[] array = Resources.FindObjectsOfTypeAll<Dynamite>();
				for (int i = 0; i < array.Length; i++)
				{
					if (!((Object)(object)array[i] == (Object)null))
					{
						Item component = ((Component)array[i]).GetComponent<Item>();
						if ((Object)(object)component != (Object)null)
						{
							val = component;
							break;
						}
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				_dynamiteResolved = true;
				_resolvedDynamiteId = 0;
				_resolvedDynamitePrefabName = null;
				id = 0;
				prefabName = null;
				return false;
			}
			_resolvedDynamiteId = val.itemID;
			_resolvedDynamitePrefabName = ((Object)((Component)val).gameObject).name.Replace("(Clone)", "").Trim();
			_dynamiteResolved = true;
			id = _resolvedDynamiteId;
			prefabName = _resolvedDynamitePrefabName;
			Log($"Resolved Dynamite -> ID {id}, prefab '{prefabName}'");
			return true;
		}

		public static void HandleLuggageOpened(Luggage luggage, Character opener)
		{
			if (PhotonNetwork.IsMasterClient && !((Object)(object)Instance == (Object)null) && !((Object)(object)luggage == (Object)null) && !IsBlockedLuggage(luggage))
			{
				Instance.RunTraps(luggage, opener);
			}
		}

		private static bool IsBlockedLuggage(Luggage luggage)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Invalid comparison between Unknown and I4
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Invalid comparison between Unknown and I4
			if ((Object)(object)luggage == (Object)null || (Object)(object)Instance == (Object)null)
			{
				return false;
			}
			if (Instance.S<bool>(Instance.trapRespawnStatue))
			{
				return false;
			}
			string text = (((Object)(object)((Component)luggage).gameObject != (Object)null) ? ((Object)((Component)luggage).gameObject).name : "");
			bool flag = !string.IsNullOrEmpty(text) && (text.IndexOf("statue", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("coffin", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("respawn", StringComparison.OrdinalIgnoreCase) >= 0);
			bool flag2 = false;
			try
			{
				flag2 = (int)((Spawner)luggage).GetSpawnPool() == 131072 || (int)((Spawner)luggage).spawnPool == 131072;
			}
			catch
			{
			}
			if (!flag && !flag2)
			{
				return false;
			}
			Instance.Log("Skipped traps on '" + text + "' (scout statue / respawn coffin). Set General.TrapRespawnStatue=true to allow traps here.");
			return true;
		}

		private void RunTraps(Luggage luggage, Character opener)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			Vector3 origin = ((Component)luggage).transform.position;
			Log("Luggage trap check at " + Fmt(origin) + " (opener: " + (((Object)(object)opener != (Object)null) ? opener.characterName : "unknown") + ", bag: " + ((Object)((Component)luggage).gameObject).name + ")");
			List<TrapRoll> list = new List<TrapRoll>
			{
				new TrapRoll(litDynamite, "LIT DYNAMITE", delegate
				{
					//IL_000d: Unknown result type (might be due to invalid IL or missing references)
					((MonoBehaviour)this).StartCoroutine(SpawnLitDynamite(origin));
				}),
				new TrapRoll(scorpions, "SCORPIONS", delegate
				{
					//IL_0022: Unknown result type (might be due to invalid IL or missing references)
					SpawnMobPack(new string[2] { "0_Items/Scorpion", "Scorpion" }, "scorpion", origin, opener, S<int>(scorpionCountMin), S<int>(scorpionCountMax), S<float>(scorpionLifetime));
				}),
				new TrapRoll(beetles, "BEETLES", delegate
				{
					//IL_0022: Unknown result type (might be due to invalid IL or missing references)
					SpawnMobPack(new string[2] { "0_Items/Beetle", "Beetle" }, "beetle", origin, opener, S<int>(beetleCountMin), S<int>(beetleCountMax), S<float>(beetleLifetime));
				}),
				new TrapRoll(frogs, "FROG TONGUES", delegate
				{
					//IL_0032: Unknown result type (might be due to invalid IL or missing references)
					SpawnMobPack(new string[4] { "0_Items/Frog", "Frog", "FrogTongue", "0_Items/FrogTongue" }, "frog", origin, opener, S<int>(frogCountMin), S<int>(frogCountMax), S<float>(frogLifetime));
				}),
				new TrapRoll(scoutmaster, "SCOUTMASTER", delegate
				{
					//IL_000d: Unknown result type (might be due to invalid IL or missing references)
					((MonoBehaviour)this).StartCoroutine(SummonScoutmasters(origin, opener));
				}),
				new TrapRoll(condors, "CONDORS", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnCondor(origin, opener);
				}),
				new TrapRoll(beeSwarm, "BEE SWARM", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnBeeSwarm(origin);
				}),
				new TrapRoll(tornado, "TORNADO", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnTornado(origin);
				}),
				new TrapRoll(zombies, "MUSHROOM ZOMBIES", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnZombies(origin, opener);
				}),
				new TrapRoll(ghostBall, "GHOST BALL", delegate
				{
					//IL_0067: Unknown result type (might be due to invalid IL or missing references)
					//IL_0030: Unknown result type (might be due to invalid IL or missing references)
					//IL_0035: Unknown result type (might be due to invalid IL or missing references)
					//IL_003f: Unknown result type (might be due to invalid IL or missing references)
					//IL_0044: Unknown result type (might be due to invalid IL or missing references)
					if (S<bool>(ghostBurstParticles))
					{
						BurstSceneVfx(new string[1] { "ghosts" }, origin + Vector3.up * 0.35f, 10f, "Fog ghosts", pinToSpawnPos: true);
					}
					((MonoBehaviour)this).StartCoroutine(SpawnGhostBallDelayed(origin, opener));
				}),
				new TrapRoll(spiders, "SPIDERS", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnSpiders(origin, opener);
				}),
				new TrapRoll(flytraps, "FLYTRAPS", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnFlytraps(origin, opener);
				}),
				new TrapRoll(spikeTraps, "SPIKE TRAPS", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnSpikeTraps(origin, opener);
				}),
				new TrapRoll(thorns, "THORNS", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					ApplyThorns(origin, opener);
				}),
				new TrapRoll(arrowTraps, "ARROW TRAPS", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnArrowTraps(origin, opener);
				}),
				new TrapRoll(mandrakes, "MANDRAKES", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnMandrakes(origin);
				}),
				new TrapRoll(antiSphere, "ANTI-GRAV SPHERE", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnAntiSphere(origin, opener);
				}),
				new TrapRoll(ravens, "RAVENS", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnRavens(origin);
				}),
				new TrapRoll(jellyfish, "JELLYFISH", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnJellyfish(origin, opener);
				}),
				new TrapRoll(tumbleweeds, "TUMBLEWEEDS", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnTumbleweeds(origin, opener);
				}),
				new TrapRoll(explodingMushrooms, "EXPLODING MUSHROOMS", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnExplodingMushrooms(origin);
				}),
				new TrapRoll(poisonMushrooms, "POISON MUSHROOMS", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnPoisonMushrooms(origin);
				}),
				new TrapRoll(trickLuggage, "TRICK LUGGAGE", delegate
				{
					//IL_0013: Unknown result type (might be due to invalid IL or missing references)
					((MonoBehaviour)this).StartCoroutine(SpawnTrickLuggage(luggage, origin));
				}),
				new TrapRoll(tickTrap, "TICK TRAP", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnTickTrap(origin, opener);
				}),
				new TrapRoll(urchins, "URCHINS", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnUrchins(origin, opener);
				}),
				new TrapRoll(flashPlant, "FLASH PLANT", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnFlashPlant(origin, opener);
				}),
				new TrapRoll(geysers, "GEYSERS", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnGeysers(origin, opener);
				}),
				new TrapRoll(eruptions, "ERUPTIONS", delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SpawnEruption(origin);
				})
			};
			int num = S<int>(maxTrapsPerLuggage);
			if (num == 0)
			{
				Log("No traps — MaxTrapsPerLuggage=0.");
				return;
			}
			List<TrapRoll> list2 = new List<TrapRoll>(list.Count);
			for (int num2 = 0; num2 < list.Count; num2++)
			{
				if (IsTrapEligible(list[num2].Trap, list[num2].Name, logSkip: true))
				{
					if (S<int>(list[num2].Trap.Chance) <= 0)
					{
						Log(list[num2].Name + ": skipped (weight 0)");
					}
					else
					{
						list2.Add(list[num2]);
					}
				}
			}
			if (list2.Count == 0)
			{
				Log("No traps — no eligible types.");
				return;
			}
			int chance = S<int>(trapChancePercent);
			if (!RollPercent(chance, "TrapChancePercent"))
			{
				Log("No traps — bag missed TrapChancePercent.");
				return;
			}
			int num3 = ((num < 0) ? list2.Count : Mathf.Min(num, list2.Count));
			int num4;
			for (num4 = 1; num4 < num3 && RollPercent(chance, "extra trap " + (num4 + 1)); num4++)
			{
			}
			Log($"Picking {num4} trap(s) (MaxTrapsPerLuggage={num}, eligible types={list2.Count}).");
			for (int num5 = 0; num5 < num4; num5++)
			{
				if (list2.Count <= 0)
				{
					break;
				}
				int num6 = PickWeightedIndex(list2);
				if (num6 < 0)
				{
					Log($"Trap pick failed ({num5}/{num4}).");
					break;
				}
				FireTrap(list2[num6].Name, list2[num6].Spawn);
				list2.RemoveAt(num6);
			}
		}

		private void FireTrap(string name, Action spawn)
		{
			try
			{
				spawn();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)(name + ": aborted (" + ex.GetType().Name + "): " + ex.Message));
			}
		}

		private bool IsTrapEligible(TrapChanceConfig trap, string name, bool logSkip)
		{
			if (trap.AllClients && enableAllClientsTraps != null && !S<bool>(enableAllClientsTraps))
			{
				if (logSkip)
				{
					Log(name + ": skipped (All Clients traps disabled)");
				}
				return false;
			}
			if (!trap.AllClients && enableHostOnlyTraps != null && !S<bool>(enableHostOnlyTraps))
			{
				if (logSkip)
				{
					Log(name + ": skipped (Host Only traps disabled)");
				}
				return false;
			}
			if (!S<bool>(trap.Enable))
			{
				if (logSkip)
				{
					Log(name + ": skipped (disabled in config)");
				}
				return false;
			}
			return true;
		}

		private bool RollPercent(int chance, string label)
		{
			chance = Mathf.Clamp(chance, 0, 100);
			int num = Random.Range(0, 100);
			bool flag = num < chance;
			Log(string.Format("{0}: chance={1} roll={2} -> {3}", label, chance, num, flag ? "HIT" : "miss"));
			return flag;
		}

		private int PickWeightedIndex(List<TrapRoll> remaining)
		{
			int num = 0;
			for (int i = 0; i < remaining.Count; i++)
			{
				num += Mathf.Max(0, S<int>(remaining[i].Trap.Chance));
			}
			if (num <= 0)
			{
				return -1;
			}
			int num2 = Random.Range(0, num);
			int num3 = 0;
			for (int j = 0; j < remaining.Count; j++)
			{
				int num4 = Mathf.Max(0, S<int>(remaining[j].Trap.Chance));
				num3 += num4;
				if (num2 < num3)
				{
					Log($"{remaining[j].Name}: picked (weight={num4} roll={num2}/{num})");
					return j;
				}
			}
			return remaining.Count - 1;
		}

		private static string Fmt(Vector3 v)
		{
			//IL_0006: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			return $"({v.x:0.00}, {v.y:0.00}, {v.z:0.00})";
		}

		private Vector3 RandomOffset(Vector3 origin, float xz = 2.5f, float y = 0.5f)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//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_0020: Unknown result type (might be due to invalid IL or missing references)
			return origin + new Vector3(Random.Range(0f - xz, xz), y, Random.Range(0f - xz, xz));
		}

		private GameObject TryInstantiate(string cacheKey, string[] candidates, Vector3 pos, Quaternion rot)
		{
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: 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)
			if (_prefabCache.TryGetValue(cacheKey, out var value) && !string.IsNullOrEmpty(value))
			{
				try
				{
					GameObject val = PhotonNetwork.Instantiate(value, pos, rot, (byte)0, (object[])null);
					if ((Object)(object)val != (Object)null)
					{
						val.SetActive(true);
						WirePhotonViewFields(val);
						return val;
					}
				}
				catch (Exception ex)
				{
					Log("Cached prefab '" + value + "' failed (" + ex.Message + "), re-resolving...");
					_prefabCache.Remove(cacheKey);
				}
			}
			foreach (string text in candidates)
			{
				try
				{
					GameObject val2 = PhotonNetwork.Instantiate(text, pos, rot, (byte)0, (object[])null);
					if ((Object)(object)val2 != (Object)null)
					{
						val2.SetActive(true);
						WirePhotonViewFields(val2);
						_prefabCache[cacheKey] = text;
						return val2;
					}
				}
				catch (Exception ex2)
				{
					Log("Prefab '" + text + "' failed: " + ex2.Message);
				}
			}
			GameObject val3 = TryInstantiateNetworked(cacheKey, pos, rot);
			if ((Object)(object)val3 != (Object)null)
			{
				_prefabCache[cacheKey] = NetPoolKey(cacheKey);
				return val3;
			}
			return CloneCachedProto(cacheKey, pos, rot);
		}

		private GameObject CloneCachedProto(string cacheKey, Vector3 pos, Quaternion rot)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			GameObject proto = GetProto(cacheKey);
			if ((Object)(object)proto == (Object)null)
			{
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(proto, pos, rot);
			((Object)val).name = cacheKey + "_TrappedLuggage";
			StripPhotonViews(val);
			val.SetActive(true);
			val.transform.SetPositionAndRotation(pos, rot);
			Log(cacheKey + ": cloned cached proto '" + ((Object)proto).name + "' at " + Fmt(pos));
			return val;
		}

		private static string NetPoolKey(string cacheKey)
		{
			return "TL_Net_" + cacheKey;
		}

		internal static bool IsOurTrapObject(GameObject go)
		{
			if ((Object)(object)go == (Object)null || string.IsNullOrEmpty(((Object)go).name))
			{
				return false;
			}
			return ((Object)go).name.StartsWith("TL_Net_", StringComparison.Ordinal) || ((Object)go).name.IndexOf("TrappedLuggage", StringComparison.Ordinal) >= 0;
		}

		private void RegisterNetworkedTrapPrefabs()
		{
			if (!(PhotonNetwork.PrefabPool is DefaultPool))
			{
				return;
			}
			List<string> list = new List<string>();
			for (int i = 0; i < NetworkedTrapKeys.Length; i++)
			{
				string text = NetworkedTrapKeys[i];
				if (EnsureNetworkedTrapPrefab(text))
				{
					list.Add(text);
				}
			}
			if (!_loggedNetPrefabs && list.Count > 0)
			{
				_loggedNetPrefabs = true;
				Log("Photon trap prefabs ready: " + string.Join(", ", list.ToArray()));
			}
		}

		private bool EnsureNetworkedTrapPrefab(string cacheKey)
		{
			//IL_008e: 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)
			try
			{
				IPunPrefabPool prefabPool = PhotonNetwork.PrefabPool;
				DefaultPool val = (DefaultPool)(object)((prefabPool is DefaultPool) ? prefabPool : null);
				if (val == null || val.ResourceCache == null)
				{
					return false;
				}
				string text = NetPoolKey(cacheKey);
				if (val.ResourceCache.TryGetValue(text, out var value) && (Object)(object)value != (Object)null)
				{
					return true;
				}
				GameObject proto = GetProto(cacheKey);
				if ((Object)(object)proto == (Object)null)
				{
					return false;
				}
				GameObject val2 = Object.Instantiate<GameObject>(proto);
				((Object)val2).name = text;
				val2.transform.position = Vector3.zero;
				val2.transform.rotation = Quaternion.identity;
				val2.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)val2);
				StripPhotonViews(val2);
				DisableRunSettingGates(val2);
				if (!AttachFreshPhotonView(val2))
				{
					Object.Destroy((Object)(object)val2);
					return false;
				}
				val.ResourceCache[text] = val2;
				return true;
			}
			catch (Exception ex)
			{
				Log("EnsureNetworkedTrapPrefab(" + cacheKey + ") failed: " + ex.Message);
				return false;
			}
		}

		private static bool AttachFreshPhotonView(GameObject proto)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)proto == (Object)null)
			{
				return false;
			}
			PhotonView val = proto.GetComponent<PhotonView>();
			if ((Object)(object)val == (Object)null)
			{
				val = proto.AddComponent<PhotonView>();
			}
			val.ViewID = 0;
			val.Synchronization = (ViewSynchronization)0;
			if (val.ObservedComponents == null)
			{
				val.ObservedComponents = new List<Component>();
			}
			else
			{
				val.ObservedComponents.Clear();
			}
			WirePhotonViewFields(proto, val);
			return true;
		}

		private static void WirePhotonViewFields(GameObject go, PhotonView pv = null)
		{
			if ((Object)(object)go == (Object)null)
			{
				return;
			}
			if ((Object)(object)pv == (Object)null)
			{
				pv = go.GetComponent<PhotonView>() ?? go.GetComponentInChildren<PhotonView>(true);
			}
			if (!((Object)(object)pv == (Object)null))
			{
				Spider val = go.GetComponent<Spider>() ?? go.GetComponentInChildren<Spider>(true);
				if ((Object)(object)val != (Object)null)
				{
					val.photonView = pv;
				}
				VenusFlyTrap val2 = go.GetComponent<VenusFlyTrap>() ?? go.GetComponentInChildren<VenusFlyTrap>(true);
				if ((Object)(object)val2 != (Object)null)
				{
					val2.view = pv;
				}
				Condor val3 = go.GetComponent<Condor>() ?? go.GetComponentInChildren<Condor>(true);
				if ((Object)(object)val3 != (Object)null)
				{
					val3.view = pv;
				}
				VoiceThief val4 = go.GetComponent<VoiceThief>() ?? go.GetComponentInChildren<VoiceThief>(true);
				if ((Object)(object)val4 != (Object)null)
				{
					val4._networkView = pv;
				}
				SpikeTrap val5 = go.GetComponent<SpikeTrap>() ?? go.GetComponentInChildren<SpikeTrap>(true);
				if ((Object)(object)val5 != (Object)null)
				{
					val5.view = pv;
				}
				TumbleWeed val6 = go.GetComponent<TumbleWeed>() ?? go.GetComponentInChildren<TumbleWeed>(true);
				if ((Object)(object)val6 != (Object)null)
				{
					val6.photonView = pv;
				}
			}
		}

		private GameObject TryInstantiateNetworked(string cacheKey, Vector3 pos, Quaternion rot)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.InRoom || !EnsureNetworkedTrapPrefab(cacheKey))
			{
				return null;
			}
			try
			{
				GameObject val = PhotonNetwork.Instantiate(NetPoolKey(cacheKey), pos, rot, (byte)0, (object[])null);
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				val.SetActive(true);
				if (!string.IsNullOrEmpty(((Object)val).name) && ((Object)val).name.IndexOf("TrappedLuggage", StringComparison.Ordinal) < 0)
				{
					((Object)val).name = cacheKey + "_TrappedLuggage";
				}
				WirePhotonViewFields(val);
				return val;
			}
			catch (Exception ex)
			{
				Log("Photon instantiate " + NetPoolKey(cacheKey) + " failed: " + ex.Message);
				return null;
			}
		}

		private void AggroMob(GameObject go, Character target)
		{
			if (!((Object)(object)go == (Object)null) && !((Object)(object)target == (Object)null))
			{
				((MonoBehaviour)this).StartCoroutine(AggroMobRoutine(go, target));
			}
		}

		private IEnumerator AggroMobRoutine(GameObject go, Character target)
		{
			yield return null;
			yield return (object)new WaitForSeconds(0.05f);
			for (int i = 0; i < 6; i++)
			{
				if ((Object)(object)go == (Object)null)
				{
					break;
				}
				if ((Object)(object)target == (Object)null)
				{
					break;
				}
				ForceMobAggro(go, target);
				yield return (object)new WaitForSeconds(0.2f);
			}
		}

		private static void ForceMobAggro(GameObject go, Character target)
		{
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)go == (Object)null || (Object)(object)target == (Object)null)
			{
				return;
			}
			Mob val = go.GetComponent<Mob>() ?? go.GetComponentInChildren<Mob>(true);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			OurMobIds.Add(((Object)val).GetInstanceID());
			val.sleeping = false;
			val.hasBrain = true;
			val.forceNoMovement = false;
			val.mobState = (MobState)1;
			val.aggroDistance = Mathf.Max(val.aggroDistance, 40f);
			val._timeSpawned = Time.time - 1f;
			val._timeLastAttacked = Time.time - 100f;
			val._timeLastCheckedForTarget = Time.time;
			val.SetForcedTarget(target);
			val.targetChar = target;
			val.targetPos = target.Center;
			val.UpdateSleeping();
			if (Beetle.playersIgnoredUntil != null)
			{
				PhotonView val2 = ((Component)target).GetComponent<PhotonView>() ?? ((MonoBehaviourPun)target).photonView;
				if ((Object)(object)val2 != (Object)null && val2.Owner != null)
				{
					Beetle.playersIgnoredUntil.Remove(val2.Owner);
				}
			}
			PhotonView val3 = go.GetComponent<PhotonView>() ?? go.GetComponentInChildren<PhotonView>(true);
			PhotonView val4 = ((Component)target).GetComponent<PhotonView>() ?? ((MonoBehaviourPun)target).photonView;
			if ((Object)(object)val3 != (Object)null && (Object)(object)val4 != (Object)null && val4.ViewID > 0)
			{
				val3.RPC("RPC_SyncMobState", (RpcTarget)0, new object[1] { 1 });
				val3.RPC("RPC_SyncTargetCharacter", (RpcTarget)0, new object[1] { val4.ViewID });
			}
		}

		private void SpawnMobPack(string[] paths, string cacheKey, Vector3 origin, Character opener, int min, int max, float lifetime = 0f)
		{
			//IL_0061: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_00ad: 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_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			int num = Random.Range(min, max + 1);
			Log(string.Format("{0}: spawning {1} (min={2} max={3} life={4:0.#}s) near {5} at {6}", cacheKey, num, min, max, lifetime, ((Object)(object)opener != (Object)null) ? opener.characterName : "luggage", Fmt(origin)));
			int num2 = 0;
			for (int i = 0; i < num; i++)
			{
				Vector3 val = (((Object)(object)opener != (Object)null) ? SpreadAround(opener.Center, i, num) : SpreadAround(origin, i, num));
				GameObject val2 = TryInstantiate(cacheKey, paths, val, Random.rotation);
				if ((Object)(object)val2 != (Object)null)
				{
					num2++;
					ScheduleDespawn(val2, lifetime);
					Log($"{cacheKey}[{i + 1}/{num}]: spawned '{((Object)val2).name}' at {Fmt(val2.transform.position)}");
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)$"{cacheKey}[{i + 1}/{num}]: instantiate failed at {Fmt(val)}");
				}
				AggroMob(val2, opener);
			}
			Log($"{cacheKey}: done ({num2}/{num} spawned)");
		}

		private void ScheduleDespawn(GameObject go, float seconds)
		{
			if (!((Object)(object)go == (Object)null) && !(seconds <= 0f))
			{
				((MonoBehaviour)this).StartCoroutine(DespawnAfter(go, seconds));
			}
		}

		private IEnumerator DespawnAfter(GameObject go, float seconds)
		{
			yield return (object)new WaitForSeconds(seconds);
			if ((Object)(object)go == (Object)null)
			{
				yield break;
			}
			PhotonView pv = go.GetComponent<PhotonView>() ?? go.GetComponentInChildren<PhotonView>(true);
			if ((Object)(object)pv != (Object)null && pv.ViewID > 0 && PhotonNetwork.InRoom)
			{
				try
				{
					PhotonNetwork.Destroy(go);
					yield break;
				}
				catch
				{
				}
			}
			Object.Destroy((Object)(object)go);
		}

		private static Vector3 SpreadAround(Vector3 center, int index, int count, float spacing = 2f)
		{
			//IL_0032: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			if (count <= 1 || index <= 0 || spacing <= 0f)
			{
				return center;
			}
			int num = count - 1;
			float num2 = 360f / (float)num * (float)(index - 1);
			Vector3 result = center + Quaternion.Euler(0f, num2, 0f) * (Vector3.forward * spacing);
			result.y = center.y;
			return result;
		}

		private IEnumerator SpawnLitDynamite(Vector3 origin)
		{
			//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 (!TryResolveDynamite(out var _, out var prefabName))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Lit Dynamite trap failed — could not resolve Dynamite prefab.");
				yield break;
			}
			yield return (object)new WaitForSeconds(0.2f);
			int count = Mathf.Max(1, Random.Range(S<int>(dynamiteCountMin), S<int>(dynamiteCountMax) + 1));
			Log($"LIT DYNAMITE: dropping {count} stick(s) fuse={S<float>(dynamiteFuseSeconds):0.##}s cook={S<bool>(dynamiteCooksItems)}");
			int spawned = 0;
			for (int i = 0; i < count; i++)
			{
				Vector3 pos = origin + Vector3.up * 0.9f + new Vector3(Random.Range(-0.12f, 0.12f), (float)i * 0.08f, Random.Range(-0.12f, 0.12f));
				GameObject go = null;
				try
				{
					go = PhotonNetwork.InstantiateItemRoom(prefabName, pos, Random.rotation, true);
				}
				catch (Exception ex)
				{
					Log("InstantiateItemRoom(" + prefabName + ") failed: " + ex.Message);
				}
				if ((Object)(object)go == (Object)null)
				{
					go = TryInstantiate("dynamite", new string[4]
					{
						"0_Items/" + prefabName,
						prefabName,
						"0_Items/Dynamite",
						"Dynamite"
					}, pos, Random.rotation);
				}
				if ((Object)(object)go == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)$"LIT DYNAMITE[{i + 1}/{count}]: spawn failed at {Fmt(pos)}");
					continue;
				}
				PhotonView pv = go.GetComponent<PhotonView>();
				Dynamite spawnedDyn = go.GetComponent<Dynamite>() ?? go.GetComponentInChildren<Dynamite>(true);
				if (!S<bool>(dynamiteCooksItems) && (Object)(object)pv != (Object)null)
				{
					OurDynamiteViewIds.Add(pv.ViewID);
					BroadcastDynamiteNoCook(pv.ViewID);
				}
				Item item = go.GetComponent<Item>();
				if ((Object)(object)item != (Object)null)
				{
					if ((Object)(object)item.rig == (Object)null)
					{
						item.AddPhysics();
					}
					item.SetKinematicNetworked(false);
					if ((Object)(object)item.rig != (Object)null)
					{
						item.rig.isKinematic = false;
						item.rig.useGravity = true;
						item.rig.WakeUp();
					}
				}
				if ((Object)(object)spawnedDyn != (Object)null)
				{
					ApplyTrapDynamiteFuse(spawnedDyn);
				}
				spawned++;
				Log($"LIT DYNAMITE[{i + 1}/{count}]: '{((Object)go).name}' at {Fmt(go.transform.position)} view={(((Object)(object)pv != (Object)null) ? pv.ViewID : 0)}");
			}
			Log($"LIT DYNAMITE: done ({spawned}/{count} spawned)");
		}

		private void ApplyTrapDynamiteFuse(Dynamite dyn)
		{
			float num = S<float>(dynamiteFuseSeconds);
			float num2 = ((num <= 0f) ? 1f : num);
			float num3 = ((num <= 0f) ? 0f : num);
			dyn.startingFuseTime = num2;
			dyn.fuseTime = num3;
			try
			{
				FloatItemData data = ((ItemComponent)dyn).GetData<FloatItemData>((DataEntryKey)10, (Func<FloatItemData>)dyn.SetupDefaultFuel);
				if (data != null)
				{
					data.Value = num3;
				}
			}
			catch (Exception ex)
			{
				Log("LIT DYNAMITE: could not write Fuel data (" + ex.Message + ")");
			}
			dyn.LightFlare();
			Log($"LIT DYNAMITE: lit fuse remaining={num3:0.##}s starting={num2:0.##}s");
		}

		internal IEnumerator ClearDynamiteNoCookFlag()
		{
			yield return null;
			yield return null;
			NextExplosionNoCook = false;
		}

		private void BroadcastDynamiteNoCook(int viewId)
		{
			//IL_0058: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			if (_applyingRemoteClone || !PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient || viewId <= 0)
			{
				return;
			}
			object[] array = new object[4]
			{
				"tony4twentys.Trapped_Luggage",
				2,
				(byte)4,
				viewId
			};
			try
			{
				PhotonNetwork.RaiseEvent((byte)199, (object)array, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)0
				}, SendOptions.SendReliable);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Dynamite no-cook event failed: " + ex.Message));
			}
		}

		private void ReceiveDynamiteNoCook(object[] arr)
		{
			if (!PhotonNetwork.IsMasterClient && arr != null && arr.Length >= 4)
			{
				int num = ToInt(arr[3]);
				if (num > 0)
				{
					OurDynamiteViewIds.Add(num);
				}
			}
		}

		private void SpawnBeeSwarm(Vector3 origin)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Max(1, Random.Range(S<int>(beeSwarmCountMin), S<int>(beeSwarmCountMax) + 1));
			Vector3 center = origin + Vector3.up;
			int num2 = 0;
			for (int i = 0; i < num; i++)
			{
				Vector3 pos = SpreadAround(center, i, num);
				GameObject val = TryInstantiate("beeswarm", new string[1] { "BeeSwarm" }, pos, Quaternion.identity);
				if (!((Object)(object)val == (Object)null))
				{
					BeeSwarm component = val.GetComponent<BeeSwarm>();
					if (!((Object)(object)component == (Object)null))
					{
						component.lastSawBeehivePosition = origin;
						component.GetAngry(S<float>(beeSwarmAngerTime));
						num2++;
					}
				}
			}
			if (num2 == 0)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Bee swarm spawn failed — no BeeSwarm prefab.");
			}
			else
			{
				Log($"Bee swarm: spawned {num2}/{num}.");
			}
		}

		private void SpawnCondor(Vector3 origin, Character opener)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_00a8: 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_00b4: 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)
			if ((Object)(object)opener == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Condor skipped — no opener.");
				return;
			}
			float num = Mathf.Max(4f, S<float>(condorHeight));
			Vector3 pos = opener.Center + Vector3.up * num;
			GameObject val = TrySpawnMapProp<Condor>("condor", new string[2] { "Condor", "0_Items/Condor" }, pos, Quaternion.identity);
			if ((Object)(object)val == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Condor skipped — no prefab or WilIsland proto cached.");
				return;
			}
			ArmCondor(val, opener, origin);
			BroadcastCloneIfLocal(val, 3, pos, Quaternion.identity, opener, origin.x, origin.y, origin.z);
		}

		private void ArmCondor(GameObject go, Character opener, Vector3 nestOrigin)
		{
			//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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)go == (Object)null || (Object)(object)opener == (Object)null)
			{
				return;
			}
			go.SetActive(true);
			Condor val = go.GetComponent<Condor>() ?? go.GetComponentInChildren<Condor>(true);
			if ((Object)(object)val == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Condor clone had no Condor component.");
				return;
			}
			Vector3 position = go.transform.position;
			OurCondorIds.Add(((Object)((Component)val).gameObject).GetInstanceID());
			val._initPos = position;
			val._lastPos = position;
			val.radius = Mathf.Max(2f, S<float>(condorRadius));
			EnsureCondorNest(val, nestOrigin);
			EnsureCondorCarryTrigger(val, go);
			PhotonView val2 = ((Component)opener).GetComponent<PhotonView>() ?? ((MonoBehaviourPun)opener).photonView;
			PhotonView val3 = val.view ?? go.GetComponent<PhotonView>();
			if ((Object)(object)val3 != (Object)null && val3.ViewID > 0 && (Object)(object)val2 != (Object)null)
			{
				val3.RPC("RPCA_CondorAction", (RpcTarget)0, new object[2]
				{
					val2,
					(object)(CondorActionType)0
				});
			}
			else
			{
				val.Swoop(opener);
			}
			float num = Mathf.Max(4f, S<float>(condorLifetime));
			Object.Destroy((Object)(object)go, num);
			Log($"Condor spawned '{((Object)go).name}' at {Fmt(position)} lifetime={num:0.##}s target={opener.characterName}");
		}

		private void EnsureCondorNest(Condor condor, Vector3 origin)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)condor.nest != (Object)null))
			{
				GameObject val = new GameObject("TL_CondorNest");
				val.transform.position = origin + Vector3.up * Mathf.Max(6f, S<float>(condorNestHeight));
				condor.nest = val;
				Object.Destroy((Object)(object)val, Mathf.Max(5f, S<float>(condorLifetime)) + 2f);
				Log("Condor: dummy nest at " + Fmt(val.transform.position));
			}
		}

		private static void EnsureCondorCarryTrigger(Condor condor, GameObject go)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (!((Object)(object)condor.carryTrigger != (Object)null))
			{
				GameObject val = new GameObject("TL_CondorCarryTrigger");
				val.transform.SetParent(go.transform, false);
				SphereCollider val2 = val.AddComponent<SphereCollider>();
				((Collider)val2).isTrigger = true;
				val2.radius = 2.2f;
				condor.carryTrigger = val;
				val.SetActive(false);
			}
		}

		internal static void RunLocalSpiderFixed(Spider spider)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: 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_01e3: 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_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: 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_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)spider == (Object)null)
			{
				return;
			}
			if ((int)spider.spiderState != 2)
			{
				if ((Object)(object)spider.anim != (Object)null)
				{
					spider.anim.SetBool("Weaving", false);
				}
				return;
			}
			spider.sinceGrab += Time.fixedDeltaTime;
			if ((Object)(object)spider.anim != (Object)null)
			{
				spider.anim.SetBool("Weaving", spider.sinceGrab < spider.pullWaitTime);
			}
			Character targetPlayer = spider.targetPlayer;
			if ((Object)(object)targetPlayer != (Object)null)
			{
				if ((Object)(object)targetPlayer.data != (Object)null && (targetPlayer.data.isCarried || targetPlayer.data.dead))
				{
					spider.RPCA_LetGo();
					return;
				}
				if ((Object)(object)spider.targetRig != (Object)null)
				{
					spider.targetPos = spider.targetRig.position;
				}
				if (targetPlayer.IsLocal && spider.sinceGrab > spider.pullWaitTime && ((Object)(object)targetPlayer.data == (Object)null || !targetPlayer.data.dead))
				{
					spider.UpdateAttack(true);
				}
				else if (!targetPlayer.IsLocal)
				{
					spider.UpdateAttack(false);
				}
				PhotonView val = ((MonoBehaviourPun)targetPlayer).photonView ?? ((Component)targetPlayer).GetComponent<PhotonView>();
				if ((targetPlayer.IsLocal || ((Object)(object)val != (Object)null && val.IsMine)) && (Object)(object)spider.dragToPoint != (Object)null && (Object)(object)spider.targetRig != (Object)null)
				{
					Vector3 val2 = spider.dragToPoint.position - (targetPlayer.Head + Vector3.up);
					Vector3 normalized = ((Vector3)(ref val2)).normalized;
					if (spider.sinceGrab > spider.pullWaitTime)
					{
						float num = ((spider.distancePullStrengthCurve != null) ? spider.distancePullStrengthCurve.Evaluate(Vector3.Distance(spider.dragToPoint.position, targetPlayer.Head + Vector3.up)) : 1f);
						if ((Object)(object)targetPlayer.refs?.movement != (Object)null)
						{
							targetPlayer.refs.movement.ApplyExtraDrag(spider.extraDrag, true);
						}
						targetPlayer.AddForceToBodyPart(spider.targetRig, normalized * (spider.dragForce * 0.2f) * num, normalized * spider.dragForce * num);
					}
					else
					{
						if ((Object)(object)targetPlayer.refs?.movement != (Object)null)
						{
							targetPlayer.refs.movement.ApplyExtraDrag(spider.extraDrag, true);
						}
						targetPlayer.AddForceToBodyPart(spider.targetRig, normalized * (spider.keepUprightForce * 0.2f), normalized * spider.keepUprightForce);
					}
					if ((Object)(object)targetPlayer.data != (Object)null)
					{
						targetPlayer.data.sinceGrounded = Mathf.Clamp(targetPlayer.data.sinceGrounded, 0f, 1f);
					}
					if ((Object)(object)targetPlayer.refs?.afflictions != (Object)null && targetPlayer.refs.afflictions.GetCurrentStatus((STATUSTYPE)11) < 0.025f)
					{
						spider.RPCA_LetGo();
						return;
					}
				}
			}
			if ((Object)(object)spider.startPoint != (Object)null)
			{
				spider.currentDistance = Vector3.Distance(spider.startPoint.position, spider.targetPos);
			}
		}

		internal static void RunLocalCondorFixed(Condor c)
		{
			//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_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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Invalid comparison between Unknown and I4
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Invalid comparison between Unknown and I4
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Invalid comparison between Unknown and I4
			//IL_03b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Invalid comparison between Unknown and I4
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: 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_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: 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_0338: 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_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: 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_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: 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_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: 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)
			if ((Object)(object)c == (Object)null || (Object)(object)c.rb == (Object)null)
			{
				return;
			}
			c._lastPos = c.rb.position;
			Vector3 val = c.rb.position;
			float time = c.time;
			if ((int)c._state == 0)
			{
				val = c.GetPosition(time);
				c.Rotate(val, 5f);
			}
			else if ((int)c._state == 1)
			{
				if ((Object)(object)c._targetChar == (Object)null)
				{
					c._state = (CondorState)3;
				}
				else
				{
					float num = c._currentSwoopTime / Mathf.Max(0.05f, c.swoopTime);
					c._swoopTarget = Vector3.Lerp(c._swoopTarget, c._targetChar.Head, Time.fixedDeltaTime * Mathf.Clamp01(1f - num * 2f) * 4f);
					Vector2 val2 = Vector2.LerpUnclamped(new Vector2(c._initialSwoopPos.x, c._initialSwoopPos.z), new Vector2(c._swoopTarget.x, c._swoopTarget.z), num * 2f);
					Vector3 position = c.GetPosition(time);
					val = Vector3.Lerp(val, new Vector3(val2.x, position.y, val2.y), Time.fixedDeltaTime * 4f);
					c.Rotate(val, 5f);
					if (num >= 1f)
					{
						c.GiveUp();
					}
				}
			}
			else if ((int)c._state == 2)
			{
				if ((Object)(object)c._targetChar == (Object)null || (Object)(object)c.nest == (Object)null)
				{
					if ((Object)(object)c._targetChar != (Object)null)
					{
						c.LetGo();
					}
					else
					{
						c._state = (CondorState)3;
					}
				}
				else
				{
					c._timeCarrying += Time.fixedDeltaTime;
					val = ((!(((Component)c).transform.position.y >= c.nest.transform.position.y)) ? (((Component)c).transform.position + Vector3.up * (Time.fixedDeltaTime * c.moveToNestSpeed)) : c.RotateAndMoveTo(c.nest.transform.position + Vector3.up * c.nestDropHeight, 1f, 1f + c._timeCarrying * 0.2f));
					if (HelperFunctions.FlatDistance(((Component)c).transform.position, c.nest.transform.position) < c.nestDropDistance || time - c._carryStartTime > c.carryTime)
					{
						c.LetGo();
					}
					else
					{
						c.PullCharacter();
					}
				}
			}
			else if ((int)c._state == 3)
			{
				c._returnToLoopSpeed += Time.fixedDeltaTime * 0.25f;
				Vector3 position2 = c.GetPosition(time);
				val = Vector3.Lerp(val, position2, (c._returnToLoopSpeed - 1f) * 0.2f);
				c.Rotate(val, 5f);
				if (HelperFunctions.FlatDistance(((Component)c).transform.position, position2) < c.returnToLoopDistance)
				{
					c._state = (CondorState)0;
					if ((Object)(object)c.anim != (Object)null)
					{
						c.anim.SetBool("Flap", false);
					}
				}
			}
			c.rb.MovePosition(val);
		}

		private void SpawnTornado(Vector3 origin)
		{
			//IL_0049: 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_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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			EnsureTornadoInitView();
			PendingTornadoLifetime = S<float>(tornadoLifetime);
			int num = Mathf.Max(1, Random.Range(S<int>(tornadoCountMin), S<int>(tornadoCountMax) + 1));
			int num2 = 0;
			for (int i = 0; i < num; i++)
			{
				Vector3 pos = SpreadAround(origin + Vector3.up * 2f, i, num);
				GameObject val = TryInstantiate("tornado", new string[1] { "Tornado" }, pos, Quaternion.identity);
				if (!((Object)(object)val == (Object)null))
				{
					PhotonView component = val.GetComponent<PhotonView>();
					if ((Object)(object)component != (Object)null)
					{
						OurTornadoViewIds.Add(component.ViewID);
					}
					Tornado component2 = val.GetComponent<Tornado>();
					if ((Object)(object)component2 != (Object)null)
					{
						component2.lifeTime = S<float>(tornadoLifetime);
					}
					if ((Object)(object)_tornadoInitView != (Object)null && (Object)(object)component != (Object)null)
					{
						component.RPC("RPCA_InitTornado", (RpcTarget)0, new object[1] { _tornadoInitView.ViewID });
					}
					num2++;
					Log($"Tornado[{i + 1}/{num}] spawned '{((Object)val).name}' lifetime={S<float>(tornadoLifetime):0.##}s at {Fmt(val.transform.position)}");
				}
			}
			if (num2 == 0)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Tornado spawn failed — Photon Tornado prefab and cached proto both missing.");
			}
		}

		private void EnsureTornadoInitView()
		{
			if ((Object)(object)_tornadoInitView != (Object)null)
			{
				return;
			}
			TornadoSpawner val = Object.FindFirstObjectByType<TornadoSpawner>();
			if ((Object)(object)val != (Object)null)
			{
				_tornadoInitView = ((Component)val).GetComponent<PhotonView>() ?? val.view;
				if ((Object)(object)_tornadoInitView != (Object)null)
				{
					return;
				}
			}
			PhotonView[] array = Object.FindObjectsByType<PhotonView>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] != (Object)null && (Object)(object)((Component)array[i]).transform.Find("TornadoPoints") != (Object)null)
				{
					_tornadoInitView = array[i];
					break;
				}
			}
		}

		private void SpawnZombies(Vector3 origin, Character opener)
		{
			//IL_0085: 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)
			ResolveZombiePrefab();
			string[] candidates = ((!string.IsNullOrEmpty(_resolvedZombiePrefab)) ? new string[3] { _resolvedZombiePrefab, "MushroomZombie", "MushroomZombie_Player" } : new string[3] { "MushroomZombie", "MushroomZombie_Player", "0_Items/MushroomZombie" });
			int num = Random.Range(S<int>(zombieCountMin), S<int>(zombieCountMax) + 1);
			for (int i = 0; i < num; i++)
			{
				GameObject val = TryInstantiate("zombie", candidates, RandomOffset(origin), Random.rotation);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				if (string.IsNullOrEmpty(_resolvedZombiePrefab) && _prefabCache.TryGetValue("zombie", out var value) && !string.IsNullOrEmpty(value))
				{
					_resolvedZombiePrefab = value;
				}
				PhotonView component = val.GetComponent<PhotonView>();
				if ((Object)(object)component != (Object)null)
				{
					OurZombieViewIds.Add(component.ViewID);
				}
				MushroomZombie component2 = val.GetComponent<MushroomZombie>();
				if (!((Object)(object)component2 == (Object)null))
				{
					component2.initialWakeUpTime = 0f;
					component2.lifetime = S<float>(zombieLifetime);
					component2.WakeUpFromSleep();
					if ((Object)(object)opener != (Object)null)
					{
						component2.SetCurrentTarget(opener, S<float>(zombieChaseTime));
					}
					component2.timeSpentWakingUp = 999f;
				}
			}
		}

		private void ResolveZombiePrefab()
		{
			if (string.IsNullOrEmpty(_resolvedZombiePrefab))
			{
				MushroomZombieSpawner val = Object.FindFirstObjectByType<MushroomZombieSpawner>();
				if ((Object)(object)val != (Object)null && (Object)(object)val.mushroomZombiePrefab != (Object)null)
				{
					_resolvedZombiePrefab = ((Object)((Component)val.mushroomZombiePrefab).gameObject).name;
				}
			}
		}

		private IEnumerator SpawnGhostBallDelayed(Vector3 origin, Character opener)
		{
			//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)
			float delay = Mathf.Max(0f, S<float>(ghostBallDelay));
			if (delay > 0f)
			{
				Log($"Ghost incoming in {delay:0.##}s...");
				yield return (object)new WaitForSeconds(delay);
			}
			SpawnGhostBall(origin, opener);
		}

		private void SpawnGhostBall(Vector3 origin, Character opener)
		{
			//IL_003d: 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_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_0063: 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_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: 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_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00