Decompiled source of Hostile Mine v1.0.0

HostileMine.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.Json;
using System.Text.Json.Serialization;
using AK;
using Agents;
using BepInEx;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using GTFO.API;
using GameData;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using LevelGeneration;
using MTFO.API;
using Microsoft.CodeAnalysis;
using Player;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("HostileMine")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("HostileMine")]
[assembly: AssemblyTitle("HostileMine")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace HostileMine
{
	internal static class ConfigLoader
	{
		private const string CustomNamespace = "HostileMine";

		private const string FileName = "HostileMines.json";

		private const string ExampleFileName = "HostileMines.example.json";

		private static readonly JsonSerializerOptions s_options = new JsonSerializerOptions
		{
			AllowTrailingCommas = true,
			ReadCommentHandling = JsonCommentHandling.Skip,
			PropertyNameCaseInsensitive = true,
			WriteIndented = true,
			Converters = { (JsonConverter)new JsonStringEnumConverter() }
		};

		public static string ConfigRoot { get; private set; } = string.Empty;

		public static IReadOnlyList<string> ConfigRoots { get; private set; } = Array.Empty<string>();

		public static void EnsureLocalFiles()
		{
			try
			{
				EnsureRoots();
				if (ConfigRoots.Count == 0)
				{
					Log.Warn("HostileMine config root is unavailable.");
					return;
				}
				EnsureExampleFile();
				EnsureStarterConfigFile();
			}
			catch (Exception ex)
			{
				Log.Error("Failed to ensure HostileMine local config files", ex);
			}
		}

		public static IReadOnlyList<HostileMineConfig> LoadAll()
		{
			EnsureLocalFiles();
			if (ConfigRoots.Count == 0)
			{
				Log.Warn("HostileMine config root is unavailable.");
				return Array.Empty<HostileMineConfig>();
			}
			List<HostileMineConfig> list = new List<HostileMineConfig>();
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			foreach (string configRoot in ConfigRoots)
			{
				string path = Path.Combine(configRoot, "HostileMines.json");
				if (!File.Exists(path))
				{
					continue;
				}
				foreach (HostileMineConfig item2 in LoadFile(path))
				{
					item2.Normalize();
					string item = $"{item2.Name}|{item2.Type}|{item2.Position.X:F2},{item2.Position.Y:F2},{item2.Position.Z:F2}";
					if (hashSet.Add(item))
					{
						list.Add(item2);
					}
				}
			}
			return list;
		}

		private static void EnsureRoots()
		{
			ConfigRoot = string.Empty;
			ConfigRoots = Array.Empty<string>();
			if (!TryGetLiveCustomRoot(out string root))
			{
				root = GetPluginCustomRoot();
				Log.Warn("MTFO live rundown Custom path is unavailable; using plugin Custom fallback: " + root);
			}
			ConfigRoot = root;
			ConfigRoots = new string[1] { ConfigRoot };
		}

		private static bool TryGetLiveCustomRoot(out string root)
		{
			root = string.Empty;
			try
			{
				if (!MTFOPathAPI.HasRundownPath)
				{
					return false;
				}
				string customPath = MTFOPathAPI.CustomPath;
				if (string.IsNullOrWhiteSpace(customPath))
				{
					return false;
				}
				customPath = Path.GetFullPath(customPath);
				if (IsBlockedGameDataCustomPath(customPath))
				{
					Log.Error("Refusing to use blocked MTFO Custom path: " + customPath);
					return false;
				}
				root = Path.Combine(customPath, "HostileMine");
				return true;
			}
			catch (Exception ex)
			{
				Log.Error("Failed to resolve MTFO live rundown Custom path", ex);
				return false;
			}
		}

		private static string GetPluginCustomRoot()
		{
			return Path.GetFullPath(Path.Combine(Paths.PluginPath, "Custom", "HostileMine"));
		}

		private static bool IsBlockedGameDataCustomPath(string path)
		{
			return IsSameOrChildPath(Path.GetFullPath(Path.Combine(Paths.GameRootPath, "BepInEx", "GameData", "Custom")), path);
		}

		private static bool IsSameOrChildPath(string parent, string path)
		{
			parent = Path.TrimEndingDirectorySeparator(parent);
			path = Path.TrimEndingDirectorySeparator(path);
			if (string.Equals(parent, path, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			string value = parent + Path.DirectorySeparatorChar;
			return path.StartsWith(value, StringComparison.OrdinalIgnoreCase);
		}

		private static IReadOnlyList<HostileMineConfig> LoadFile(string path)
		{
			try
			{
				return JsonSerializer.Deserialize<List<HostileMineConfig>>(File.ReadAllText(path), s_options) ?? new List<HostileMineConfig>();
			}
			catch (Exception ex)
			{
				Log.Error("Failed to load hostile mine config: " + path, ex);
				return Array.Empty<HostileMineConfig>();
			}
		}

		private static void EnsureExampleFile()
		{
			Directory.CreateDirectory(ConfigRoot);
			string text = Path.Combine(ConfigRoot, "HostileMines.example.json");
			if (!File.Exists(text))
			{
				File.WriteAllText(text, ExampleConfig.CreateExampleText());
				Log.Info("Created example config reference: " + text);
			}
		}

		private static void EnsureStarterConfigFile()
		{
			Directory.CreateDirectory(ConfigRoot);
			string text = Path.Combine(ConfigRoot, "HostileMines.json");
			if (!File.Exists(text))
			{
				File.WriteAllText(text, ExampleConfig.CreateStarterText());
				Log.Info("Created starter config: " + text);
			}
		}
	}
	[BepInPlugin("com.kain.hostilemine", "HostileMine", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class EntryPoint : BasePlugin
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static Action <0>__EnsureLocalFiles;

			public static LevelSelectedEvent <1>__SetSelectedExpedition;

			public static Action <2>__SpawnForCurrentLevel;

			public static Action <3>__Clear;
		}

		private Harmony? m_harmony;

		public override void Load()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_005b: 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_0066: Expected O, but got Unknown
			Log.Init(((BasePlugin)this).Log);
			RegisterIl2CppTypes();
			m_harmony = new Harmony("com.kain.hostilemine");
			m_harmony.PatchAll();
			AssetAPI.OnStartupAssetsLoaded += ConfigLoader.EnsureLocalFiles;
			object obj = <>O.<1>__SetSelectedExpedition;
			if (obj == null)
			{
				LevelSelectedEvent val = MineRuntime.SetSelectedExpedition;
				<>O.<1>__SetSelectedExpedition = val;
				obj = (object)val;
			}
			LevelAPI.OnLevelSelected += (LevelSelectedEvent)obj;
			LevelAPI.OnEnterLevel += MineRuntime.SpawnForCurrentLevel;
			LevelAPI.OnLevelCleanup += MineRuntime.Clear;
			Log.Info("HostileMine 1.0.0 loaded");
		}

		private static void RegisterIl2CppTypes()
		{
			if (!ClassInjector.IsTypeRegisteredInIl2Cpp<HostileMineBehaviour>())
			{
				ClassInjector.RegisterTypeInIl2Cpp<HostileMineBehaviour>();
			}
		}
	}
	internal static class ExampleConfig
	{
		public static string CreateExampleText()
		{
			return "[\n  { // 一个配置项通常对应同一关卡中的一类敌对绊雷\n    \"Enabled\": false, // 是否启用这个配置项;示例默认关闭,改成 true 才会生效\n    \"Name\": \"Example fixed tripwire mines\", // 配置名称,也会出现在日志和生成物体名称中\n    \"Type\": \"Tripwire\", // 默认绊雷类型:Tripwire 为可见绊线,Proximity 为隐藏接近触发\n    \"LevelLayoutID\": 0, // 目标 LevelLayoutData ID;内部放置组可以继承这个值\n    \"CanBeDisarmed\": true, // 是否允许使用原生绊雷交互近身拆除\n    \"DisarmRange\": 1.6, // fallback 拆除距离;原生 MineDeployerInstance 会优先用自己的交互组件\n    \"DisarmRequiresLineOfSight\": true, // fallback 拆除是否要求玩家和绊雷之间没有墙体遮挡\n    \"CanBeShotDetonated\": true, // 是否允许原生受击组件或 fallback 命中组件被子弹命中后引爆\n    \"ShotHitboxRadius\": 0.45, // fallback 命中球半径;原生 MineDeployerInstance 会优先用自己的受击组件\n    \"FixedPlacements\": [ // 定点放置组列表;每组先指定 zone,再批量写 Mines 坐标\n      { // 一个固定 zone 放置组\n        \"Enabled\": false, // 是否启用这个 zone 放置组\n        \"Name\": \"zone_0_tripwires\", // 这个放置组的名称后缀\n        \"Index\": 0, // 目标 zone 的 local index,也就是 LevelLayout 中的 index\n        \"Layer\": \"MainLayer\", // 目标层:MainLayer、SecondaryLayer 或 ThirdLayer;省略时按 LayoutID 自动判断\n        \"Mines\": [ // 该 zone 内的批量定点写作区域;每一项就是一颗绊雷\n          { // 第一颗地雷\n            \"Name\": \"door_left\", // 单颗地雷名称后缀,可以省略\n            \"Position\": { \"X\": 0, \"Y\": 0, \"Z\": 0 }, // 相对该 zone transform 的局部坐标\n            \"Forward\": { \"X\": 0, \"Y\": 0, \"Z\": 1 } // 地雷朝向向量;也可以改用 Rotation、Yaw 或 Angle\n          }, // 第一颗地雷结束\n          { // 第二颗地雷\n            \"Name\": \"door_right\", // 单颗地雷名称后缀,可以省略\n            \"Position\": { \"X\": 2, \"Y\": 0, \"Z\": 0 }, // 相对该 zone transform 的局部坐标\n            \"Yaw\": 90 // 水平角度;和 Forward、Rotation、Angle 任选一种即可\n          } // 第二颗地雷结束\n        ] // 批量定点地雷列表结束\n      } // 固定 zone 放置组结束\n    ], // 定点放置组列表结束\n    \"TripwireLength\": 8, // 绊线长度\n    \"TripwireRadius\": 0.25, // 绊线触发半径\n    \"ExplosionRadius\": 5, // 爆炸半径\n    \"DamageMin\": 8, // 爆炸最小伤害\n    \"DamageMax\": 35 // 爆炸最大伤害\n  }, // 定点绊线地雷示例结束\n  { // 随机隐藏地雷配置\n    \"Enabled\": false, // 是否启用这个配置项;示例默认关闭,改成 true 才会生效\n    \"Name\": \"Example random hidden mines\", // 配置名称,也会出现在日志和生成物体名称中\n    \"Type\": \"Proximity\", // Proximity 为无绊线,玩家进入范围后闪烁警告并延迟爆炸\n    \"LevelLayoutID\": 0, // 目标 LevelLayoutData ID;内部随机组可以继承这个值\n    \"CanBeDisarmed\": true, // 是否允许使用原生绊雷交互近身拆除\n    \"DisarmRange\": 1.6, // fallback 拆除距离;原生 MineDeployerInstance 会优先用自己的交互组件\n    \"DisarmRequiresLineOfSight\": true, // fallback 拆除是否要求玩家和绊雷之间没有墙体遮挡\n    \"CanBeShotDetonated\": true, // 是否允许原生受击组件或 fallback 命中组件被子弹命中后引爆\n    \"ShotHitboxRadius\": 0.45, // fallback 命中球半径;原生 MineDeployerInstance 会优先用自己的受击组件\n    \"RandomDistributions\": [ // 随机分布列表;适合在指定 zone 中随机生成多颗绊雷\n      { // 一个随机分布组\n        \"Enabled\": false, // 是否启用这个随机分布组\n        \"Name\": \"zone_0_hidden_wall_mines\", // 这个随机分布组的名称后缀\n        \"Index\": 0, // 目标 zone 的 local index,也就是 LevelLayout 中的 index\n        \"Layer\": \"MainLayer\", // 目标层:MainLayer、SecondaryLayer 或 ThirdLayer;省略时按 LayoutID 自动判断\n        \"Count\": 3, // 在该 zone 中随机生成的绊雷数量\n        \"UseEnemySpawnPoints\": true, // 是否优先使用该 zone 内的 enemy spawn point 作为随机起点\n        \"AlignToSpawnPointRotation\": true, // 未贴墙时是否沿用 enemy spawn point 的旋转方向\n        \"MinDistance\": 2, // 随机生成时每颗绊雷之间的最小水平距离,避免堆在一起\n        \"MaxSampleAttempts\": 64, // 为单颗绊雷寻找不重叠随机点的最大尝试次数\n        \"AllowStacking\": false, // 是否允许多颗随机绊雷生成在同一位置;通常保持 false\n        \"FloorOffset\": 0.05, // 使用地面采样时离地面的高度偏移\n        \"AttachToWall\": true, // 是否把随机绊雷贴到附近墙面;开启后最终位置会从地面点投射到墙面\n        \"WallSearchRadius\": 6, // 从随机点向四周寻找墙面的最大距离,单位为米\n        \"WallOffset\": 0.08, // 贴墙后让绊雷离墙面稍微外移的距离,避免模型嵌墙\n        \"WallMountHeight\": 1.1, // 从地面点向上多少高度开始寻找墙面,决定墙上安装高度\n        \"WallSampleDirections\": 16, // 向四周采样的方向数量;越高越容易找到墙,但也略微更耗时\n        \"SkipIfWallNotFound\": true // 如果附近找不到墙面,是否跳过这颗随机绊雷;想永远贴墙时保持 true\n      } // 随机分布组结束\n    ], // 随机分布列表结束\n    \"TriggerRange\": 2.75, // 玩家进入这个范围后触发警告计时\n    \"WarningDelay\": 1.35, // 警告闪烁后到爆炸的延迟秒数\n    \"WarningFlashInterval\": 0.12, // 警告闪烁间隔秒数\n    \"ExplosionRadius\": 5, // 爆炸半径\n    \"DamageMin\": 8, // 爆炸最小伤害\n    \"DamageMax\": 35, // 爆炸最大伤害\n    \"HideTripwireRenderer\": true // 是否隐藏绊线渲染;Proximity 类型通常保持 true\n  } // 随机隐藏地雷示例结束\n] // 根节点结束";
		}

		public static string CreateStarterText()
		{
			return "[\n  {\n    \"Enabled\": false,\n    \"Name\": \"Fixed tripwire mines\",\n    \"Type\": \"Tripwire\",\n    \"LevelLayoutID\": 0,\n    \"CanBeDisarmed\": true,\n    \"DisarmRange\": 1.6,\n    \"DisarmRequiresLineOfSight\": true,\n    \"CanBeShotDetonated\": true,\n    \"ShotHitboxRadius\": 0.45,\n    \"FixedPlacements\": [\n      {\n        \"Enabled\": false,\n        \"Name\": \"zone_0_tripwires\",\n        \"Index\": 0,\n        \"Layer\": \"MainLayer\",\n        \"Mines\": [\n          {\n            \"Name\": \"mine_0\",\n            \"Position\": { \"X\": 0, \"Y\": 0, \"Z\": 0 },\n            \"Forward\": { \"X\": 0, \"Y\": 0, \"Z\": 1 }\n          },\n          {\n            \"Name\": \"mine_1\",\n            \"Position\": { \"X\": 2, \"Y\": 0, \"Z\": 0 },\n            \"Yaw\": 90\n          }\n        ]\n      }\n    ],\n    \"TripwireLength\": 8,\n    \"TripwireRadius\": 0.25,\n    \"ExplosionRadius\": 5,\n    \"DamageMin\": 8,\n    \"DamageMax\": 35\n  },\n  {\n    \"Enabled\": false,\n    \"Name\": \"Random hidden wall mines\",\n    \"Type\": \"Proximity\",\n    \"LevelLayoutID\": 0,\n    \"CanBeDisarmed\": true,\n    \"DisarmRange\": 1.6,\n    \"DisarmRequiresLineOfSight\": true,\n    \"CanBeShotDetonated\": true,\n    \"ShotHitboxRadius\": 0.45,\n    \"RandomDistributions\": [\n      {\n        \"Enabled\": false,\n        \"Name\": \"zone_0_hidden_wall_mines\",\n        \"Index\": 0,\n        \"Layer\": \"MainLayer\",\n        \"Count\": 3,\n        \"UseEnemySpawnPoints\": true,\n        \"AlignToSpawnPointRotation\": true,\n        \"MinDistance\": 2,\n        \"MaxSampleAttempts\": 64,\n        \"AllowStacking\": false,\n        \"FloorOffset\": 0.05,\n        \"AttachToWall\": true,\n        \"WallSearchRadius\": 6,\n        \"WallOffset\": 0.08,\n        \"WallMountHeight\": 1.1,\n        \"WallSampleDirections\": 16,\n        \"SkipIfWallNotFound\": true\n      }\n    ],\n    \"TriggerRange\": 2.75,\n    \"WarningDelay\": 1.35,\n    \"WarningFlashInterval\": 0.12,\n    \"ExplosionRadius\": 5,\n    \"DamageMin\": 8,\n    \"DamageMax\": 35,\n    \"HideTripwireRenderer\": true\n  }\n]";
		}
	}
	public sealed class HostileMineBehaviour : MonoBehaviour
	{
		private sealed class MineState
		{
			private const float PlayerBodyHeight = 1.8f;

			private const float ExplosionCleanupDelay = 5f;

			private readonly HostileMineBehaviour m_owner;

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

			private readonly Color[] m_originalColors;

			private LineRenderer? m_tripwire;

			private Light? m_warningLight;

			private MineDeployerInstance? m_nativeMine;

			private MineDeployerInstance_Detonate_Explosive? m_builtinExplosive;

			private GenericDamageComponent? m_damage;

			private Action<float>? m_damageTakenDelegate;

			private SphereCollider? m_shotHitbox;

			private float m_scanTimer;

			private float m_warningTimer;

			private float m_flashTimer;

			private bool m_warningStarted;

			private bool m_flashOn;

			private bool m_exploded;

			private bool m_disposed;

			public MineRuntimeConfig Config { get; }

			public MineState(HostileMineBehaviour owner, MineRuntimeConfig config)
			{
				m_owner = owner;
				Config = config;
				m_originalColors = Array.Empty<Color>();
			}

			public void SetupVisuals()
			{
				CacheRenderers();
				SetupNativeMine();
				SetupBuiltinExplosive();
				SetupWarningLight();
				SetupTripwire();
				SetupShotDetonation();
			}

			public void Update(float deltaTime)
			{
				if (m_exploded || m_disposed)
				{
					return;
				}
				if ((Object)(object)m_nativeMine == (Object)null && Config.CanBeDisarmed && IsInteractionPressed() && TryFindPlayerInDisarmRange(out PlayerAgent _))
				{
					Disarm();
					return;
				}
				if (Config.Type == HostileMineKind.Proximity && m_warningStarted)
				{
					UpdateWarning(deltaTime);
					return;
				}
				m_scanTimer -= deltaTime;
				if (m_scanTimer > 0f)
				{
					return;
				}
				m_scanTimer = Config.ScanInterval;
				if (Config.Type == HostileMineKind.Tripwire)
				{
					if (IsTripwireTouched())
					{
						Explode();
					}
				}
				else if (IsAnyPlayerInProximity())
				{
					StartWarning();
				}
			}

			public void DestroyMine()
			{
				if ((Object)(object)m_owner != (Object)null && (Object)(object)((Component)m_owner).gameObject != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)m_owner).gameObject);
				}
			}

			public void Dispose()
			{
				m_disposed = true;
				if ((Object)(object)m_damage != (Object)null && m_damageTakenDelegate != null)
				{
					try
					{
						m_damage.OnGenericDamageTaken -= m_damageTakenDelegate;
					}
					catch (Exception ex)
					{
						Log.Debug($"Failed to detach damage callback for '{Config.Name}': {ex.GetType().Name}: {ex.Message}");
					}
				}
				m_damage = null;
				m_damageTakenDelegate = null;
			}

			private void CacheRenderers()
			{
				Il2CppArrayBase<Renderer> componentsInChildren = ((Component)m_owner).GetComponentsInChildren<Renderer>(true);
				for (int i = 0; i < componentsInChildren.Count; i++)
				{
					Renderer val = componentsInChildren[i];
					if ((Object)(object)val != (Object)null)
					{
						m_renderers.Add(val);
					}
				}
			}

			private void SetupNativeMine()
			{
				m_nativeMine = ((Component)m_owner).GetComponentInChildren<MineDeployerInstance>(true);
				if ((Object)(object)m_nativeMine == (Object)null)
				{
					return;
				}
				try
				{
					m_nativeMine.Alive = true;
					m_nativeMine.Mode = (eStickyMineMode)2;
					m_nativeMine.m_detectionEnabled = false;
					m_nativeMine.m_canBePickedUp = Config.CanBeDisarmed;
					if ((Object)(object)m_nativeMine.m_interactPickup != (Object)null)
					{
						((Interact_Base)m_nativeMine.m_interactPickup).SetActive(Config.CanBeDisarmed);
					}
					if ((Object)(object)m_nativeMine.m_damage != (Object)null)
					{
						m_nativeMine.m_damage.DebugName = "HostileMine_" + Config.Name;
						((Behaviour)m_nativeMine.m_damage).enabled = Config.CanBeShotDetonated;
					}
					Log.Debug("Hostile mine '" + Config.Name + "' is using native MineDeployerInstance interaction/damage wiring.");
				}
				catch (Exception ex)
				{
					Log.Warn($"Failed to prepare native mine runtime for '{Config.Name}': {ex.GetType().Name}: {ex.Message}");
				}
			}

			private void SetupBuiltinExplosive()
			{
				m_builtinExplosive = ((Component)m_owner).GetComponentInChildren<MineDeployerInstance_Detonate_Explosive>(true);
				if (!((Object)(object)m_builtinExplosive == (Object)null))
				{
					m_builtinExplosive.m_delay = 0f;
					m_builtinExplosive.m_explosionDelay = 0f;
					m_builtinExplosive.m_radius = Config.ExplosionRadius;
					m_builtinExplosive.m_stickyMineExplosionRadius = Config.ExplosionRadius;
					m_builtinExplosive.m_damageMin = Config.DamageMin;
					m_builtinExplosive.m_damageMax = Config.DamageMax;
					m_builtinExplosive.m_stickyMineMaxDamage = Config.DamageMax;
				}
			}

			private void SetupWarningLight()
			{
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				m_warningLight = ((Component)m_owner).gameObject.AddComponent<Light>();
				m_warningLight.type = (LightType)2;
				m_warningLight.color = new Color(1f, 0.08f, 0.02f, 1f);
				m_warningLight.range = Math.Max(2f, Config.ExplosionRadius);
				m_warningLight.intensity = ((Config.Type == HostileMineKind.Tripwire) ? 0.45f : 0f);
				((Behaviour)m_warningLight).enabled = true;
			}

			private void SetupTripwire()
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Expected O, but got Unknown
				//IL_003f: 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: Expected O, but got Unknown
				//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
				if (Config.HideTripwireRenderer)
				{
					DisableExistingTripwireRenderers();
					return;
				}
				GameObject val = new GameObject("HostileMine_Tripwire");
				val.transform.SetParent(((Component)m_owner).transform, false);
				val.transform.localPosition = Vector3.zero;
				m_tripwire = val.AddComponent<LineRenderer>();
				m_tripwire.positionCount = 2;
				m_tripwire.useWorldSpace = true;
				m_tripwire.startWidth = 0.035f;
				m_tripwire.endWidth = 0.035f;
				((Renderer)m_tripwire).material = new Material(Shader.Find("Sprites/Default"));
				m_tripwire.startColor = new Color(1f, 0.02f, 0.02f, 0.95f);
				m_tripwire.endColor = new Color(1f, 0.02f, 0.02f, 0.95f);
				UpdateTripwireLine();
			}

			private void SetupShotDetonation()
			{
				//IL_0137: Unknown result type (might be due to invalid IL or missing references)
				if (!Config.CanBeShotDetonated)
				{
					return;
				}
				try
				{
					if ((Object)(object)m_nativeMine != (Object)null)
					{
						if ((Object)(object)m_nativeMine.m_damage != (Object)null)
						{
							m_nativeMine.m_damage.DebugName = "HostileMine_" + Config.Name;
							((Behaviour)m_nativeMine.m_damage).enabled = true;
						}
						return;
					}
					m_damage = FindOrCreateDamageComponent();
					if ((Object)(object)m_damage != (Object)null)
					{
						m_damage.DebugName = "HostileMine_" + Config.Name;
						m_damageTakenDelegate = DelegateSupport.ConvertDelegate<Action<float>>((Delegate)new Action<float>(OnDamageTaken));
						m_damage.OnGenericDamageTaken += m_damageTakenDelegate;
					}
					m_shotHitbox = ((Component)m_owner).GetComponentInChildren<SphereCollider>(true);
					if ((Object)(object)m_shotHitbox == (Object)null)
					{
						m_shotHitbox = ((Component)m_owner).gameObject.AddComponent<SphereCollider>();
					}
					((Collider)m_shotHitbox).isTrigger = false;
					m_shotHitbox.radius = Config.ShotHitboxRadius;
					m_shotHitbox.center = Vector3.zero;
					((Collider)m_shotHitbox).enabled = true;
					((Component)m_owner).gameObject.layer = LayerManager.LAYER_ENEMY_DAMAGABLE;
				}
				catch (Exception ex)
				{
					Log.Warn($"Failed to set up shot detonation for hostile mine '{Config.Name}': {ex.GetType().Name}: {ex.Message}");
				}
			}

			private GenericDamageComponent FindOrCreateDamageComponent()
			{
				MineDeployerInstance componentInChildren = ((Component)m_owner).GetComponentInChildren<MineDeployerInstance>(true);
				if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.m_damage != (Object)null)
				{
					return componentInChildren.m_damage;
				}
				GenericDamageComponent componentInChildren2 = ((Component)m_owner).GetComponentInChildren<GenericDamageComponent>(true);
				if (!((Object)(object)componentInChildren2 != (Object)null))
				{
					return ((Component)m_owner).gameObject.AddComponent<GenericDamageComponent>();
				}
				return componentInChildren2;
			}

			private void OnDamageTaken(float _)
			{
				if (!m_exploded && !m_disposed && Config.CanBeShotDetonated)
				{
					Explode();
				}
			}

			private void DisableExistingTripwireRenderers()
			{
				Il2CppArrayBase<LineRenderer> componentsInChildren = ((Component)m_owner).GetComponentsInChildren<LineRenderer>(true);
				for (int i = 0; i < componentsInChildren.Count; i++)
				{
					((Renderer)componentsInChildren[i]).enabled = false;
				}
			}

			private void UpdateTripwireLine()
			{
				//IL_0020: 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)
				if (!((Object)(object)m_tripwire == (Object)null))
				{
					GetTripwireSegment(out var start, out var end);
					m_tripwire.SetPosition(0, start);
					m_tripwire.SetPosition(1, end);
				}
			}

			private bool IsTripwireTouched()
			{
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				GetTripwireSegment(out var start, out var end);
				foreach (PlayerAgent item in EnumeratePlayers())
				{
					GetPlayerBodySegment(item, out var bottom, out var top);
					if (DistanceSegmentToSegment(start, end, bottom, top, out var _, out var closest2) <= Config.TripwireRadius && (!Config.RequiresLineOfSight || HasLineOfSight(closest2)))
					{
						return true;
					}
				}
				return false;
			}

			private bool IsAnyPlayerInProximity()
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: 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_0033: 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)
				Vector3 position = ((Component)m_owner).transform.position;
				foreach (PlayerAgent item in EnumeratePlayers())
				{
					GetPlayerBodySegment(item, out var bottom, out var top);
					if (DistancePointToSegment(position, bottom, top, out var closest) <= Config.TriggerRange && (!Config.RequiresLineOfSight || HasLineOfSight(closest)))
					{
						return true;
					}
				}
				return false;
			}

			private bool TryFindPlayerInDisarmRange(out PlayerAgent? foundPlayer)
			{
				//IL_000e: 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_0034: 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_0036: 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)
				foundPlayer = null;
				Vector3 position = ((Component)m_owner).transform.position;
				foreach (PlayerAgent item in EnumeratePlayers())
				{
					GetPlayerBodySegment(item, out var bottom, out var top);
					if (DistancePointToSegment(position, bottom, top, out var closest) <= Config.DisarmRange && (!Config.DisarmRequiresLineOfSight || HasLineOfSight(closest)))
					{
						foundPlayer = item;
						return true;
					}
				}
				return false;
			}

			private bool IsInteractionPressed()
			{
				try
				{
					if (InputMapper.GetButtonDown != null && InputMapper.GetButtonDown.Invoke((InputAction)6, (eFocusState)0))
					{
						return true;
					}
				}
				catch (Exception ex)
				{
					Log.Debug($"InputMapper.GetButtonDown failed for '{Config.Name}': {ex.GetType().Name}: {ex.Message}");
				}
				try
				{
					return InputMapper.GetButtonDownKeyMouseGamepad((InputAction)6, (eFocusState)0);
				}
				catch (Exception ex2)
				{
					Log.Debug($"InputMapper.GetButtonDownKeyMouseGamepad failed for '{Config.Name}': {ex2.GetType().Name}: {ex2.Message}");
					return false;
				}
			}

			private void Disarm()
			{
				if (!m_exploded && !m_disposed)
				{
					m_disposed = true;
					DisableMineBodyAfterExplosion();
					TryPlayDisarmSound();
					if ((Object)(object)m_owner != (Object)null && (Object)(object)((Component)m_owner).gameObject != (Object)null)
					{
						Object.Destroy((Object)(object)((Component)m_owner).gameObject);
					}
				}
			}

			private void StartWarning()
			{
				m_warningStarted = true;
				m_warningTimer = Config.WarningDelay;
				m_flashTimer = 0f;
				m_flashOn = false;
				if ((Object)(object)m_warningLight != (Object)null)
				{
					((Behaviour)m_warningLight).enabled = true;
				}
			}

			private void UpdateWarning(float deltaTime)
			{
				m_warningTimer -= deltaTime;
				m_flashTimer -= deltaTime;
				if (m_flashTimer <= 0f)
				{
					m_flashTimer = Config.WarningFlashInterval;
					m_flashOn = !m_flashOn;
					SetWarningVisual(m_flashOn);
				}
				if (m_warningTimer <= 0f)
				{
					Explode();
				}
			}

			private void SetWarningVisual(bool on)
			{
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0091: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)m_warningLight != (Object)null)
				{
					m_warningLight.intensity = (on ? 3.5f : 0.2f);
				}
				Color color = (Color)(on ? new Color(1f, 0.05f, 0.02f, 1f) : Color.white);
				foreach (Renderer renderer in m_renderers)
				{
					if (!((Object)(object)renderer == (Object)null) && !((Object)(object)renderer.material == (Object)null) && renderer.material.HasProperty("_Color"))
					{
						renderer.material.color = color;
					}
				}
			}

			private void Explode()
			{
				if (m_exploded)
				{
					return;
				}
				m_exploded = true;
				if ((Object)(object)m_tripwire != (Object)null)
				{
					((Renderer)m_tripwire).enabled = false;
				}
				if (TryTriggerNativeExplosion())
				{
					TriggerExplosionFlash();
					if ((Object)(object)m_owner != (Object)null && (Object)(object)((Component)m_owner).gameObject != (Object)null)
					{
						Object.Destroy((Object)(object)((Component)m_owner).gameObject, 5f);
					}
					return;
				}
				ApplyPlayerDamage();
				bool num = TryPlayBuiltinExplosionEffect();
				bool flag = TrySpawnExplosionEffectPrefab();
				TryPlayExplosionSound();
				TriggerExplosionFlash();
				DisableMineBodyAfterExplosion();
				if (!num && !flag)
				{
					Log.Warn("Explosion effect assets were unavailable for hostile mine '" + Config.Name + "'. Damage was still applied.");
				}
				if ((Object)(object)m_owner != (Object)null && (Object)(object)((Component)m_owner).gameObject != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)m_owner).gameObject, 5f);
				}
			}

			private bool TryTriggerNativeExplosion()
			{
				if ((Object)(object)m_nativeMine == (Object)null && (Object)(object)m_builtinExplosive == (Object)null)
				{
					return false;
				}
				if ((Object)(object)m_nativeMine != (Object)null)
				{
					try
					{
						if (m_nativeMine.Alive)
						{
							((Item)m_nativeMine).SyncedTrigger((PlayerAgent)null);
							return true;
						}
					}
					catch (Exception ex)
					{
						Log.Debug($"Native SyncedTrigger failed for '{Config.Name}': {ex.GetType().Name}: {ex.Message}");
					}
				}
				if ((Object)(object)m_builtinExplosive != (Object)null)
				{
					try
					{
						m_builtinExplosive.TriggerDetonate(0f);
						return true;
					}
					catch (Exception ex2)
					{
						Log.Debug($"Native TriggerDetonate failed for '{Config.Name}': {ex2.GetType().Name}: {ex2.Message}");
					}
				}
				return false;
			}

			private void ApplyPlayerDamage()
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_0047: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: 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_004c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
				Vector3 position = ((Component)m_owner).transform.position;
				float explosionRadius = Config.ExplosionRadius;
				float num = explosionRadius * explosionRadius;
				foreach (PlayerAgent item in EnumeratePlayers())
				{
					Vector3 playerCenterPosition = GetPlayerCenterPosition(item);
					Vector3 val = playerCenterPosition - position;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (sqrMagnitude > num)
					{
						continue;
					}
					float num2 = Mathf.Sqrt(sqrMagnitude);
					if (!Config.RequiresLineOfSight || HasLineOfSight(playerCenterPosition))
					{
						float num3 = Mathf.Clamp01(num2 / explosionRadius);
						float num4 = Mathf.Lerp(Config.DamageMax, Config.DamageMin, num3);
						val = playerCenterPosition - position;
						Vector3 val2 = ((Vector3)(ref val)).normalized * num4;
						Dam_PlayerDamageBase damage = item.Damage;
						if (damage != null)
						{
							((Dam_SyncedDamageBase)damage).ExplosionDamage(num4, position, val2, 0u);
						}
					}
				}
			}

			private bool TryPlayBuiltinExplosionEffect()
			{
				if (!Config.UseBuiltInExplosionEffect || (Object)(object)m_builtinExplosive == (Object)null)
				{
					return false;
				}
				try
				{
					m_builtinExplosive.DoExplode(0f);
					return true;
				}
				catch (Exception ex)
				{
					Log.Debug($"Built-in explosion effect failed for '{Config.Name}': {ex.GetType().Name}: {ex.Message}");
					return false;
				}
			}

			private bool TrySpawnExplosionEffectPrefab()
			{
				//IL_004f: 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)
				if (!Config.UseBuiltInExplosionEffect)
				{
					return false;
				}
				try
				{
					GameObject loadedAsset = AssetAPI.GetLoadedAsset<GameObject>("Assets/AssetPrefabs/FX_Effects/FX_Tripmine.prefab");
					if ((Object)(object)loadedAsset == (Object)null)
					{
						Log.Debug("Explosion FX prefab is not loaded: Assets/AssetPrefabs/FX_Effects/FX_Tripmine.prefab");
						return false;
					}
					GameObject obj = Object.Instantiate<GameObject>(loadedAsset);
					obj.transform.position = ((Component)m_owner).transform.position;
					obj.transform.rotation = ((Component)m_owner).transform.rotation;
					obj.SetActive(true);
					Object.Destroy((Object)(object)obj, 8f);
					return true;
				}
				catch (Exception ex)
				{
					Log.Debug($"Explosion FX prefab failed for '{Config.Name}': {ex.GetType().Name}: {ex.Message}");
					return false;
				}
			}

			private void TryPlayExplosionSound()
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					CellSound.Post(EVENTS.STICKYMINEEXPLODE, ((Component)m_owner).transform.position);
				}
				catch (Exception ex)
				{
					Log.Debug($"Explosion sound failed for '{Config.Name}': {ex.GetType().Name}: {ex.Message}");
				}
			}

			private void TryPlayDisarmSound()
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					CellSound.Post(EVENTS.STICKYMINEOFF, ((Component)m_owner).transform.position);
				}
				catch (Exception ex)
				{
					Log.Debug($"Disarm sound failed for '{Config.Name}': {ex.GetType().Name}: {ex.Message}");
				}
			}

			private void TriggerExplosionFlash()
			{
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)m_warningLight == (Object)null))
				{
					((Behaviour)m_warningLight).enabled = true;
					m_warningLight.color = new Color(1f, 0.32f, 0.08f, 1f);
					m_warningLight.range = Math.Max(Config.ExplosionRadius, 3f);
					m_warningLight.intensity = 8f;
					Object.Destroy((Object)(object)m_warningLight, 0.35f);
					m_warningLight = null;
				}
			}

			private void DisableMineBodyAfterExplosion()
			{
				if ((Object)(object)m_tripwire != (Object)null)
				{
					((Renderer)m_tripwire).enabled = false;
				}
				foreach (Renderer renderer in m_renderers)
				{
					if ((Object)(object)renderer != (Object)null)
					{
						renderer.enabled = false;
					}
				}
				Il2CppArrayBase<Collider> componentsInChildren = ((Component)m_owner).GetComponentsInChildren<Collider>(true);
				for (int i = 0; i < componentsInChildren.Count; i++)
				{
					Collider val = componentsInChildren[i];
					if ((Object)(object)val != (Object)null)
					{
						val.enabled = false;
					}
				}
			}

			private IEnumerable<PlayerAgent> EnumeratePlayers()
			{
				List<PlayerAgent> players = PlayerManager.PlayerAgentsInLevel;
				if (players == null)
				{
					yield break;
				}
				for (int i = 0; i < players.Count; i++)
				{
					PlayerAgent val = players[i];
					if (!((Object)(object)val == (Object)null) && ((Agent)val).Alive && !val.IsBeingDestroyed && !val.IsBeingDespawned)
					{
						yield return val;
					}
				}
			}

			private Vector3 GetPlayerPosition(PlayerAgent player)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: 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_0014: Unknown result type (might be due to invalid IL or missing references)
				Vector3 navigationPosition = ((Agent)player).NavigationPosition;
				if (navigationPosition != Vector3.zero)
				{
					return navigationPosition;
				}
				return ((Component)player).transform.position;
			}

			private Vector3 GetPlayerCenterPosition(PlayerAgent player)
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				GetPlayerBodySegment(player, out var bottom, out var top);
				return Vector3.Lerp(bottom, top, 0.5f);
			}

			private void GetPlayerBodySegment(PlayerAgent player, out Vector3 bottom, out Vector3 top)
			{
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: 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)
				bottom = GetPlayerPosition(player);
				top = bottom + Vector3.up * 1.8f;
			}

			private bool HasLineOfSight(Vector3 target)
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: 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_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_0054: 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_00a6: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val = ((Component)m_owner).transform.position + Vector3.up * 0.1f;
				Vector3 val2 = target - val;
				float magnitude = ((Vector3)(ref val2)).magnitude;
				if (magnitude <= 0.01f)
				{
					return true;
				}
				Vector3 val3 = val2 / magnitude;
				Vector3 val4 = val;
				float num = magnitude;
				RaycastHit val5 = default(RaycastHit);
				for (int i = 0; i < 8; i++)
				{
					if (!Physics.Raycast(val4, val3, ref val5, num, s_solidMask, (QueryTriggerInteraction)1))
					{
						return true;
					}
					if (!IsOwnCollider(((RaycastHit)(ref val5)).collider))
					{
						return false;
					}
					float num2 = Math.Max(((RaycastHit)(ref val5)).distance + 0.05f, 0.05f);
					num -= num2;
					if (num <= 0.01f)
					{
						return true;
					}
					val4 += val3 * num2;
				}
				return true;
			}

			private void GetTripwireSegment(out Vector3 start, out Vector3 end)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: 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_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_0045: Unknown result type (might be due to invalid IL or missing references)
				start = ((Component)m_owner).transform.position;
				end = start + ((Component)m_owner).transform.forward * Config.TripwireLength;
			}

			private bool IsOwnCollider(Collider? collider)
			{
				if ((Object)(object)collider == (Object)null || (Object)(object)((Component)collider).transform == (Object)null)
				{
					return false;
				}
				if (!((Object)(object)((Component)collider).transform == (Object)(object)((Component)m_owner).transform))
				{
					return ((Component)collider).transform.IsChildOf(((Component)m_owner).transform);
				}
				return true;
			}

			private static float DistancePointToSegment(Vector3 point, Vector3 start, Vector3 end)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				Vector3 closest;
				return DistancePointToSegment(point, start, end, out closest);
			}

			private static float DistancePointToSegment(Vector3 point, Vector3 start, Vector3 end, out Vector3 closest)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_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_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_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_0040: Unknown result type (might be due to invalid IL or missing references)
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				//IL_004f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val = end - start;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				if (sqrMagnitude <= 0.0001f)
				{
					closest = start;
					return Vector3.Distance(point, start);
				}
				float num = Mathf.Clamp01(Vector3.Dot(point - start, val) / sqrMagnitude);
				closest = start + val * num;
				return Vector3.Distance(point, closest);
			}

			private static float DistanceSegmentToSegment(Vector3 p1, Vector3 q1, Vector3 p2, Vector3 q2, out Vector3 closest1, out Vector3 closest2)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: 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_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_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_0045: 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_004d: 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_0055: Unknown result type (might be due to invalid IL or missing references)
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
				//IL_0136: Unknown result type (might be due to invalid IL or missing references)
				//IL_0137: Unknown result type (might be due to invalid IL or missing references)
				//IL_013a: Unknown result type (might be due to invalid IL or missing references)
				//IL_013f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0144: Unknown result type (might be due to invalid IL or missing references)
				//IL_014b: Unknown result type (might be due to invalid IL or missing references)
				//IL_014c: Unknown result type (might be due to invalid IL or missing references)
				//IL_014f: 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_0159: Unknown result type (might be due to invalid IL or missing references)
				//IL_0160: Unknown result type (might be due to invalid IL or missing references)
				//IL_0167: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val = q1 - p1;
				Vector3 val2 = q2 - p2;
				Vector3 val3 = p1 - p2;
				float num = Vector3.Dot(val, val);
				float num2 = Vector3.Dot(val2, val2);
				float num3 = Vector3.Dot(val2, val3);
				if (num <= 0.0001f && num2 <= 0.0001f)
				{
					closest1 = p1;
					closest2 = p2;
					return Vector3.Distance(closest1, closest2);
				}
				float num4;
				float num5;
				if (num <= 0.0001f)
				{
					num4 = 0f;
					num5 = Mathf.Clamp01(num3 / num2);
				}
				else
				{
					float num6 = Vector3.Dot(val, val3);
					if (num2 <= 0.0001f)
					{
						num5 = 0f;
						num4 = Mathf.Clamp01((0f - num6) / num);
					}
					else
					{
						float num7 = Vector3.Dot(val, val2);
						float num8 = num * num2 - num7 * num7;
						num4 = ((num8 != 0f) ? Mathf.Clamp01((num7 * num3 - num6 * num2) / num8) : 0f);
						num5 = (num7 * num4 + num3) / num2;
						if (num5 < 0f)
						{
							num5 = 0f;
							num4 = Mathf.Clamp01((0f - num6) / num);
						}
						else if (num5 > 1f)
						{
							num5 = 1f;
							num4 = Mathf.Clamp01((num7 - num6) / num);
						}
					}
				}
				closest1 = p1 + val * num4;
				closest2 = p2 + val2 * num5;
				return Vector3.Distance(closest1, closest2);
			}
		}

		private static readonly Dictionary<IntPtr, MineState> s_states = new Dictionary<IntPtr, MineState>();

		private static readonly int s_solidMask = ResolveSolidMask();

		public HostileMineBehaviour(IntPtr pointer)
			: base(pointer)
		{
		}

		[HideFromIl2Cpp]
		internal void Init(MineRuntimeConfig config)
		{
			MineState mineState = new MineState(this, config);
			s_states[((Il2CppObjectBase)this).Pointer] = mineState;
			mineState.SetupVisuals();
		}

		private void Update()
		{
			if (!s_states.TryGetValue(((Il2CppObjectBase)this).Pointer, out MineState value))
			{
				return;
			}
			try
			{
				value.Update(Time.deltaTime);
			}
			catch (Exception ex)
			{
				Log.Error("Hostile mine update failed: " + value.Config.Name, ex);
				value.DestroyMine();
			}
		}

		private void OnDestroy()
		{
			if (((Il2CppObjectBase)this).Pointer != IntPtr.Zero && s_states.Remove(((Il2CppObjectBase)this).Pointer, out MineState value))
			{
				value.Dispose();
			}
		}

		private static int ResolveSolidMask()
		{
			int mask = LayerMask.GetMask(new string[3] { "Default", "Dynamic", "Static" });
			if (mask != 0)
			{
				return mask;
			}
			return -1;
		}
	}
	internal static class Log
	{
		private static ManualLogSource? s_source;

		public static void Init(ManualLogSource source)
		{
			s_source = source;
		}

		public static void Info(string message)
		{
			ManualLogSource? obj = s_source;
			if (obj != null)
			{
				obj.LogMessage((object)message);
			}
		}

		public static void Debug(string message)
		{
			ManualLogSource? obj = s_source;
			if (obj != null)
			{
				obj.LogDebug((object)message);
			}
		}

		public static void Warn(string message)
		{
			ManualLogSource? obj = s_source;
			if (obj != null)
			{
				obj.LogWarning((object)message);
			}
		}

		public static void Error(string message)
		{
			ManualLogSource? obj = s_source;
			if (obj != null)
			{
				obj.LogError((object)message);
			}
		}

		public static void Error(string message, Exception ex)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			ManualLogSource val = s_source;
			if (val != null)
			{
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(1, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(message);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("\n");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(SafeExceptionSummary(ex));
				}
				val.LogError(val2);
			}
		}

		private static string SafeExceptionSummary(Exception ex)
		{
			string text = ex.GetType().FullName ?? ex.GetType().Name;
			if (text.Contains("Il2Cpp", StringComparison.OrdinalIgnoreCase))
			{
				return text + " (IL2CPP exception details suppressed to avoid recursive native exception formatting)";
			}
			string text2 = text + ": " + ex.Message;
			if (!string.IsNullOrWhiteSpace(ex.StackTrace))
			{
				text2 = text2 + "\n" + ex.StackTrace;
			}
			return text2;
		}
	}
	internal static class MineRuntime
	{
		private readonly struct MineSpawnRequest
		{
			public string Name { get; }

			public Vector3 Position { get; }

			public Quaternion Rotation { get; }

			public Vector3 Scale { get; }

			public MineSpawnRequest(string name, Vector3 position, Quaternion rotation, Vector3 scale)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: 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)
				Name = name;
				Position = position;
				Rotation = rotation;
				Scale = scale;
			}
		}

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

		private static IReadOnlyList<HostileMineConfig> s_cachedConfigs = Array.Empty<HostileMineConfig>();

		private static eRundownTier? s_selectedTier;

		private static int? s_selectedExpeditionIndex;

		private static uint? s_selectedMainLayoutID;

		private static uint? s_selectedSecondaryLayoutID;

		private static uint? s_selectedThirdLayoutID;

		private static int s_selectedSessionSeed;

		public static void SetSelectedExpedition(eRundownTier tier, int expeditionIndex, ExpeditionInTierData expeditionData)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			s_selectedTier = tier;
			s_selectedExpeditionIndex = expeditionIndex;
			s_selectedMainLayoutID = null;
			s_selectedSecondaryLayoutID = null;
			s_selectedThirdLayoutID = null;
			s_selectedSessionSeed = 0;
			if (expeditionData != null)
			{
				s_selectedMainLayoutID = expeditionData.LevelLayoutData;
				s_selectedSecondaryLayoutID = (expeditionData.SecondaryLayerEnabled ? new uint?(expeditionData.SecondaryLayout) : ((uint?)null));
				s_selectedThirdLayoutID = (expeditionData.ThirdLayerEnabled ? new uint?(expeditionData.ThirdLayout) : ((uint?)null));
				s_selectedSessionSeed = expeditionData.SessionSeed;
			}
			Log.Debug($"Selected expedition: {tier} index {expeditionIndex}, layouts main={s_selectedMainLayoutID}, secondary={s_selectedSecondaryLayoutID}, third={s_selectedThirdLayoutID}");
		}

		public static void SpawnForCurrentLevel()
		{
			Clear();
			try
			{
				s_cachedConfigs = ConfigLoader.LoadAll();
				HostileMineConfig[] array = s_cachedConfigs.Where((HostileMineConfig c) => c.Enabled && MatchesCurrentLevel(c)).ToArray();
				if (array.Length == 0)
				{
					Log.Info("No enabled hostile mines matched the current level.");
					return;
				}
				int spawned = 0;
				int requested = 0;
				HostileMineConfig[] array2 = array;
				for (int num = 0; num < array2.Length; num++)
				{
					SpawnConfig(array2[num], ref spawned, ref requested);
				}
				Log.Info($"Spawned {spawned}/{requested} hostile mines from {array.Length} matching config entries.");
			}
			catch (Exception ex)
			{
				Log.Error("Failed to spawn hostile mines", ex);
			}
		}

		public static void Clear()
		{
			for (int num = s_spawned.Count - 1; num >= 0; num--)
			{
				GameObject val = s_spawned[num];
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
			}
			s_spawned.Clear();
		}

		private static bool MatchesCurrentLevel(HostileMineConfig config)
		{
			uint? layoutID = config.GetLayoutID();
			if (layoutID.HasValue && !MatchesCurrentLayout(layoutID.Value))
			{
				return false;
			}
			if (!MatchesTier(config.Tier))
			{
				return false;
			}
			if (config.ExpeditionIndex.HasValue && !MatchesExpeditionIndex(config.ExpeditionIndex.Value))
			{
				return false;
			}
			return true;
		}

		private static bool MatchesCurrentLayout(uint layoutID)
		{
			if ((!s_selectedMainLayoutID.HasValue || s_selectedMainLayoutID.Value != layoutID) && (!s_selectedSecondaryLayoutID.HasValue || s_selectedSecondaryLayoutID.Value != layoutID))
			{
				if (s_selectedThirdLayoutID.HasValue)
				{
					return s_selectedThirdLayoutID.Value == layoutID;
				}
				return false;
			}
			return true;
		}

		private static bool MatchesTier(string? tier)
		{
			//IL_0060: 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)
			if (string.IsNullOrWhiteSpace(tier))
			{
				return true;
			}
			if (!s_selectedTier.HasValue)
			{
				return false;
			}
			string text = tier.Trim();
			if (text.Length == 1 && char.IsLetter(text[0]))
			{
				text = "Tier" + char.ToUpperInvariant(text[0]);
			}
			if (Enum.TryParse<eRundownTier>(text, ignoreCase: true, out eRundownTier result))
			{
				return result == s_selectedTier.Value;
			}
			return false;
		}

		private static bool MatchesExpeditionIndex(int configuredIndex)
		{
			if (!s_selectedExpeditionIndex.HasValue)
			{
				return false;
			}
			int value = s_selectedExpeditionIndex.Value;
			if (configuredIndex != value)
			{
				return configuredIndex == value + 1;
			}
			return true;
		}

		private static void SpawnConfig(HostileMineConfig config, ref int spawned, ref int requested)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			config.Normalize();
			if (!config.UsesPlacementSets)
			{
				requested++;
				if (TrySpawn(config, new MineSpawnRequest(config.DisplayName, config.Position.ToVector3(), Quaternion.Euler(config.Rotation.ToVector3()), config.Scale.ToVector3())))
				{
					spawned++;
				}
				return;
			}
			for (int i = 0; i < config.FixedPlacements.Count; i++)
			{
				HostileMinePlacement hostileMinePlacement = config.FixedPlacements[i];
				if (!hostileMinePlacement.Enabled || !MatchesPlacementLayout(config, hostileMinePlacement))
				{
					continue;
				}
				if (hostileMinePlacement.Mines.Count > 0)
				{
					for (int j = 0; j < hostileMinePlacement.Mines.Count; j++)
					{
						HostileMinePlacementPoint hostileMinePlacementPoint = hostileMinePlacement.Mines[j];
						if (hostileMinePlacementPoint.Enabled)
						{
							requested++;
							if (TryBuildFixedPlacementPointRequest(config, hostileMinePlacement, hostileMinePlacementPoint, i, j, out var request) && TrySpawn(config, request, hostileMinePlacementPoint.Type ?? hostileMinePlacement.Type))
							{
								spawned++;
							}
						}
					}
				}
				else
				{
					requested++;
					if (TryBuildFixedPlacementRequest(config, hostileMinePlacement, i, out var request2) && TrySpawn(config, request2, hostileMinePlacement.Type))
					{
						spawned++;
					}
				}
			}
			for (int k = 0; k < config.RandomDistributions.Count; k++)
			{
				HostileMineDistribution hostileMineDistribution = config.RandomDistributions[k];
				if (hostileMineDistribution.Enabled && MatchesDistributionLayout(config, hostileMineDistribution))
				{
					int num = Math.Max(0, hostileMineDistribution.Count);
					requested += num;
					spawned += SpawnDistribution(config, hostileMineDistribution, k);
				}
			}
		}

		private static bool TrySpawn(HostileMineConfig config, MineSpawnRequest request, HostileMineKind? typeOverride = null)
		{
			//IL_0092: 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_00b6: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			string instancePrefab = config.InstancePrefab;
			GameObject obj = null;
			if (ShouldUseNativeMineSpawner(instancePrefab) && !TrySpawnNativeMine(request, out obj))
			{
				Log.Debug("Native mine spawn failed for '" + request.Name + "', falling back to prefab path: " + instancePrefab);
			}
			if ((Object)(object)obj == (Object)null && !TrySpawnPrefab(instancePrefab, request, out obj))
			{
				return false;
			}
			if ((Object)(object)obj == (Object)null)
			{
				Log.Warn("Skipping hostile mine '" + request.Name + "': spawn returned no object.");
				return false;
			}
			((Object)obj).name = "HostileMine_" + request.Name;
			obj.transform.position = request.Position;
			obj.transform.rotation = request.Rotation;
			obj.transform.localScale = request.Scale;
			obj.AddComponent<HostileMineBehaviour>().Init(new MineRuntimeConfig(config, request.Position, request.Rotation, request.Scale, request.Name, typeOverride));
			s_spawned.Add(obj);
			Log.Info("Spawned hostile mine '" + request.Name + "' at " + Format(request.Position));
			return true;
		}

		private static bool ShouldUseNativeMineSpawner(string prefabPath)
		{
			if (!string.IsNullOrWhiteSpace(prefabPath) && !string.Equals(prefabPath, "Assets/AssetPrefabs/Items/Tools/MineDeployer/MineDeployerInstance_Explosive.prefab", StringComparison.OrdinalIgnoreCase) && !string.Equals(prefabPath, "Assets/AssetPrefabs/Items/Tools/MineDeployer/MineDeployerInstance_Explosive.prefab", StringComparison.OrdinalIgnoreCase))
			{
				return string.Equals(prefabPath, "Assets/AssetPrefabs/Items/Tools/MineDeployer/TripMine_1.prefab", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private static bool TrySpawnNativeMine(MineSpawnRequest request, out GameObject? obj)
		{
			//IL_0078: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			obj = null;
			try
			{
				if (!ItemSpawnManager.ReadyToSpawnItems)
				{
					Log.Debug("ItemSpawnManager is not ready while spawning hostile mine '" + request.Name + "'.");
					return false;
				}
				if (!ItemSpawnManager.ItemHasMode(125u, (ItemMode)3))
				{
					Log.Warn($"Native explosive tripmine item {125} has no Instance mode.");
					return false;
				}
				Item val = ItemSpawnManager.SpawnItem(125u, (ItemMode)3, request.Position, request.Rotation, true, default(pItemData), (Transform)null);
				if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null)
				{
					Log.Warn("ItemSpawnManager returned no object for hostile mine '" + request.Name + "'.");
					return false;
				}
				obj = ((Component)val).gameObject;
				return true;
			}
			catch (Exception ex)
			{
				Log.Warn($"Native mine spawn failed for '{request.Name}': {ex.GetType().Name}: {ex.Message}");
				return false;
			}
		}

		private static bool TrySpawnPrefab(string prefabPath, MineSpawnRequest request, out GameObject? obj)
		{
			obj = null;
			GameObject loadedAsset = AssetAPI.GetLoadedAsset<GameObject>(prefabPath);
			if ((Object)(object)loadedAsset == (Object)null)
			{
				Log.Warn("Skipping hostile mine '" + request.Name + "': prefab not loaded: " + prefabPath);
				return false;
			}
			obj = Object.Instantiate<GameObject>(loadedAsset);
			return (Object)(object)obj != (Object)null;
		}

		private static bool MatchesPlacementLayout(HostileMineConfig config, HostileMinePlacement placement)
		{
			uint? layoutID = placement.GetLayoutID();
			if (layoutID.HasValue)
			{
				return MatchesCurrentLayout(layoutID.Value);
			}
			uint? layoutID2 = config.GetLayoutID();
			if (layoutID2.HasValue)
			{
				return MatchesCurrentLayout(layoutID2.Value);
			}
			return true;
		}

		private static bool MatchesDistributionLayout(HostileMineConfig config, HostileMineDistribution distribution)
		{
			uint? layoutID = distribution.GetLayoutID();
			if (layoutID.HasValue)
			{
				return MatchesCurrentLayout(layoutID.Value);
			}
			uint? layoutID2 = config.GetLayoutID();
			if (layoutID2.HasValue)
			{
				return MatchesCurrentLayout(layoutID2.Value);
			}
			return true;
		}

		private static bool TryBuildFixedPlacementRequest(HostileMineConfig config, HostileMinePlacement placement, int placementIndex, out MineSpawnRequest request)
		{
			//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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			request = default(MineSpawnRequest);
			Vector3 val = placement.Position.ToVector3();
			Quaternion val2 = ResolveRotation(placement.Rotation, placement.Forward, placement.Yaw ?? placement.Angle, Quaternion.Euler(config.Rotation.ToVector3()));
			Vector3 scale = placement.Scale?.ToVector3() ?? config.Scale.ToVector3();
			int? index = placement.GetIndex();
			if (index.HasValue)
			{
				int value = index.Value;
				uint? layoutID = placement.GetLayoutID() ?? config.GetLayoutID();
				if (!TryGetZone(value, placement.Layer ?? placement.LevelLayer ?? config.Layer, layoutID, placement.Dimension, placement.DimensionIndex, out LG_Zone zone) || (Object)(object)zone == (Object)null)
				{
					Log.Warn($"Skipping fixed hostile mine '{config.DisplayName}' placement {placementIndex}: zone index {value} was not found.");
					return false;
				}
				Transform transform = ((Component)zone).transform;
				val = transform.TransformPoint(val);
				val2 = transform.rotation * val2;
			}
			string text = (string.IsNullOrWhiteSpace(placement.Name) ? $"fixed_{placementIndex}" : placement.Name.Trim());
			request = new MineSpawnRequest(config.DisplayName + "_" + text, val, val2, scale);
			return true;
		}

		private static bool TryBuildFixedPlacementPointRequest(HostileMineConfig config, HostileMinePlacement placement, HostileMinePlacementPoint point, int placementIndex, int pointIndex, out MineSpawnRequest request)
		{
			//IL_000e: 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_0041: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: 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_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: 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_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			request = default(MineSpawnRequest);
			Vector3 val = point.Position.ToVector3();
			Quaternion fallback = ResolveRotation(placement.Rotation, placement.Forward, placement.Yaw ?? placement.Angle, Quaternion.Euler(config.Rotation.ToVector3()));
			Quaternion val2 = ResolveRotation(point.Rotation, point.Forward, point.Yaw ?? point.Angle, fallback);
			Vector3 scale = point.Scale?.ToVector3() ?? placement.Scale?.ToVector3() ?? config.Scale.ToVector3();
			int? index = placement.GetIndex();
			if (index.HasValue)
			{
				int value = index.Value;
				uint? layoutID = placement.GetLayoutID() ?? config.GetLayoutID();
				if (!TryGetZone(value, placement.Layer ?? placement.LevelLayer ?? config.Layer, layoutID, placement.Dimension, placement.DimensionIndex, out LG_Zone zone) || (Object)(object)zone == (Object)null)
				{
					Log.Warn($"Skipping fixed hostile mine '{config.DisplayName}' placement {placementIndex} point {pointIndex}: zone index {value} was not found.");
					return false;
				}
				Transform transform = ((Component)zone).transform;
				val = transform.TransformPoint(val);
				val2 = transform.rotation * val2;
			}
			string value2 = (string.IsNullOrWhiteSpace(placement.Name) ? $"fixed_{placementIndex}" : placement.Name.Trim());
			string value3 = (string.IsNullOrWhiteSpace(point.Name) ? pointIndex.ToString() : point.Name.Trim());
			request = new MineSpawnRequest($"{config.DisplayName}_{value2}_{value3}", val, val2, scale);
			return true;
		}

		private static int SpawnDistribution(HostileMineConfig config, HostileMineDistribution distribution, int distributionIndex)
		{
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: 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_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: 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_037f: Unknown result type (might be due to invalid IL or missing references)
			if (distribution.Count <= 0)
			{
				return 0;
			}
			int? index = distribution.GetIndex();
			if (!index.HasValue)
			{
				Log.Warn($"Skipping hostile mine distribution '{config.DisplayName}' index {distributionIndex}: Index is required.");
				return 0;
			}
			int value = index.Value;
			uint? layoutID = distribution.GetLayoutID() ?? config.GetLayoutID();
			if (!TryGetZone(value, distribution.Layer ?? distribution.LevelLayer ?? config.Layer, layoutID, distribution.Dimension, distribution.DimensionIndex, out LG_Zone zone) || (Object)(object)zone == (Object)null)
			{
				Log.Warn($"Skipping hostile mine distribution '{config.DisplayName}' index {distributionIndex}: zone index {value} was not found.");
				return 0;
			}
			List<LG_Area> list = CollectAreas(zone);
			if (list.Count == 0)
			{
				Log.Warn($"Skipping hostile mine distribution '{config.DisplayName}' index {distributionIndex}: zone {value} has no areas.");
				return 0;
			}
			Random random = new Random(distribution.Seed ?? HashSeed(config.DisplayName, distribution.Name, distributionIndex, value));
			List<Vector3> list2 = new List<Vector3>(distribution.Count);
			int num = 0;
			for (int i = 0; i < distribution.Count; i++)
			{
				if (!TrySampleSpacedDistributionPoint(list, distribution, random, list2, out var position, out var rotation))
				{
					Log.Warn($"Failed to sample hostile mine distribution '{config.DisplayName}' point {i} in zone {value}.");
					continue;
				}
				Quaternion fallback = (distribution.AttachToWall ? rotation : (distribution.AlignToSpawnPointRotation ? rotation : Quaternion.identity));
				Quaternion rotation2 = ResolveRotation(distribution.Rotation, distribution.Forward, distribution.Yaw ?? distribution.Angle, fallback);
				Vector3 scale = distribution.Scale?.ToVector3() ?? config.Scale.ToVector3();
				string value2 = (string.IsNullOrWhiteSpace(distribution.Name) ? $"random_{distributionIndex}" : distribution.Name.Trim());
				MineSpawnRequest request = new MineSpawnRequest($"{config.DisplayName}_{value2}_{i}", position, rotation2, scale);
				if (TrySpawn(config, request, distribution.Type))
				{
					list2.Add(position);
					num++;
				}
			}
			return num;
		}

		private static bool TryGetZone(int zoneIndex, string? layerName, uint? layoutID, string? dimensionName, int? dimensionNumber, out LG_Zone? zone)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Invalid comparison between Unknown and I4
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			zone = null;
			if (zoneIndex < 0 || zoneIndex > 20)
			{
				return false;
			}
			LG_LayerType val = ParseLayer(layerName, layoutID);
			eDimensionIndex val2 = ParseDimension(dimensionName, dimensionNumber);
			LG_Zone val3 = default(LG_Zone);
			foreach (LG_Floor item in Object.FindObjectsOfType<LG_Floor>())
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				try
				{
					if (item.TryGetZoneByLocalIndex(val2, val, (eLocalZoneIndex)zoneIndex, ref val3) && (Object)(object)val3 != (Object)null)
					{
						zone = val3;
						return true;
					}
				}
				catch (Exception ex)
				{
					Log.Debug($"Zone lookup failed on floor {((Object)item).name}: {ex.GetType().Name}: {ex.Message}");
				}
			}
			foreach (LG_Zone item2 in Object.FindObjectsOfType<LG_Zone>())
			{
				if ((Object)(object)item2 == (Object)null)
				{
					continue;
				}
				try
				{
					if ((int)item2.LocalIndex == zoneIndex && item2.DimensionIndex == val2 && item2.Layer != null && item2.Layer.m_type == val)
					{
						zone = item2;
						return true;
					}
				}
				catch (Exception ex2)
				{
					Log.Debug($"Fallback zone lookup failed on {((Object)item2).name}: {ex2.GetType().Name}: {ex2.Message}");
				}
			}
			return false;
		}

		private static List<LG_Area> CollectAreas(LG_Zone zone)
		{
			List<LG_Area> list = new List<LG_Area>();
			try
			{
				List<LG_Area> areas = zone.m_areas;
				if (areas != null)
				{
					for (int i = 0; i < areas.Count; i++)
					{
						LG_Area val = areas[i];
						if ((Object)(object)val != (Object)null)
						{
							list.Add(val);
						}
					}
				}
			}
			catch (Exception ex)
			{
				Log.Debug($"Failed to collect areas for zone {((Object)zone).name}: {ex.GetType().Name}: {ex.Message}");
			}
			return list;
		}

		private static bool TrySampleSpacedDistributionPoint(IReadOnlyList<LG_Area> areas, HostileMineDistribution distribution, Random random, IReadOnlyList<Vector3> usedPositions, out Vector3 position, out Quaternion rotation)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			position = Vector3.zero;
			rotation = Quaternion.identity;
			Vector3 val = distribution.PositionOffset?.ToVector3() ?? Vector3.zero;
			if (distribution.AllowStacking || distribution.MinDistance <= 0f || usedPositions.Count == 0)
			{
				if (!TrySampleDistributionPoint(areas, distribution, random, distribution.UseEnemySpawnPoints, out position, out rotation))
				{
					return false;
				}
				position += val;
				if (!TryResolveDistributionPlacement(position, rotation, distribution, random, out position, out rotation))
				{
					return false;
				}
				return true;
			}
			float num = distribution.MinDistance * distribution.MinDistance;
			int num2 = Math.Max(1, distribution.MaxSampleAttempts);
			int num3 = (distribution.UseEnemySpawnPoints ? Math.Max(1, num2 / 3) : 0);
			for (int i = 0; i < num2; i++)
			{
				bool useEnemySpawnPoints = distribution.UseEnemySpawnPoints && i < num3;
				if (TrySampleDistributionPoint(areas, distribution, random, useEnemySpawnPoints, out var position2, out var rotation2))
				{
					position2 += val;
					if (TryResolveDistributionPlacement(position2, rotation2, distribution, random, out position2, out rotation2) && GetNearestHorizontalDistanceSqr(position2, usedPositions) >= num)
					{
						position = position2;
						rotation = rotation2;
						return true;
					}
				}
			}
			Log.Warn($"Distribution '{distribution.Name}' could not find a point at least {distribution.MinDistance:F1}m from previous mines after {num2} attempts. Skipping this mine to avoid stacking.");
			return false;
		}

		private static bool TryResolveDistributionPlacement(Vector3 sampledPosition, Quaternion sampledRotation, HostileMineDistribution distribution, Random random, out Vector3 position, out Quaternion rotation)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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)
			position = sampledPosition;
			rotation = sampledRotation;
			if (!distribution.AttachToWall)
			{
				return true;
			}
			if (TryAttachToWall(sampledPosition, sampledRotation, distribution, random, out position, out rotation))
			{
				return true;
			}
			if (distribution.SkipIfWallNotFound)
			{
				return false;
			}
			return true;
		}

		private static bool TryAttachToWall(Vector3 floorPosition, Quaternion baseRotation, HostileMineDistribution distribution, Random random, out Vector3 wallPosition, out Quaternion wallRotation)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: 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_0141: 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_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			wallPosition = floorPosition;
			wallRotation = baseRotation;
			Vector3 val = floorPosition + Vector3.up * distribution.WallMountHeight;
			int num = Math.Max(4, distribution.WallSampleDirections);
			float num2 = (float)(random.NextDouble() * 360.0);
			float num3 = float.MaxValue;
			RaycastHit val2 = default(RaycastHit);
			bool flag = false;
			RaycastHit val4 = default(RaycastHit);
			for (int i = 0; i < num; i++)
			{
				float num4 = num2 + 360f * (float)i / (float)num;
				Vector3 val3 = Quaternion.Euler(0f, num4, 0f) * Vector3.forward;
				if (Physics.Raycast(val, val3, ref val4, distribution.WallSearchRadius, -1, (QueryTriggerInteraction)1) && !IsOwnOrPlayerCollider(((RaycastHit)(ref val4)).collider) && !(Mathf.Abs(((RaycastHit)(ref val4)).normal.y) > 0.4f) && ((RaycastHit)(ref val4)).distance < num3)
				{
					num3 = ((RaycastHit)(ref val4)).distance;
					val2 = val4;
					flag = true;
				}
			}
			if (!flag)
			{
				return false;
			}
			Vector3 normal = ((RaycastHit)(ref val2)).normal;
			normal.y = 0f;
			if (((Vector3)(ref normal)).sqrMagnitude <= 0.0001f)
			{
				return false;
			}
			((Vector3)(ref normal)).Normalize();
			wallPosition = ((RaycastHit)(ref val2)).point + normal * distribution.WallOffset;
			wallRotation = Quaternion.LookRotation(normal, Vector3.up);
			return true;
		}

		private static bool IsOwnOrPlayerCollider(Collider? collider)
		{
			if ((Object)(object)collider == (Object)null || (Object)(object)((Component)collider).gameObject == (Object)null)
			{
				return true;
			}
			int layer = ((Component)collider).gameObject.layer;
			if (layer != LayerManager.LAYER_PLAYER_MOVER && layer != LayerManager.LAYER_PLAYER_SYNCED)
			{
				return layer == LayerManager.LAYER_ENEMY_DAMAGABLE;
			}
			return true;
		}

		private static bool TrySampleDistributionPoint(IReadOnlyList<LG_Area> areas, HostileMineDistribution distribution, Random random, bool useEnemySpawnPoints, out Vector3 position, out Quaternion rotation)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			position = Vector3.zero;
			rotation = Quaternion.identity;
			for (int i = 0; i < Math.Max(8, areas.Count * 2); i++)
			{
				LG_Area area = areas[random.Next(areas.Count)];
				if (useEnemySpawnPoints && TrySampleAreaEnemySpawnPoint(area, random, out position, out rotation))
				{
					return true;
				}
				if (TrySampleAreaBounds(area, random, distribution.FloorOffset, out position))
				{
					rotation = Quaternion.Euler(0f, (float)(random.NextDouble() * 360.0), 0f);
					return true;
				}
			}
			return false;
		}

		private static float GetNearestHorizontalDistanceSqr(Vector3 candidate, IReadOnlyList<Vector3> usedPositions)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			float num = float.MaxValue;
			for (int i = 0; i < usedPositions.Count; i++)
			{
				Vector3 val = usedPositions[i];
				float num2 = candidate.x - val.x;
				float num3 = candidate.z - val.z;
				float num4 = num2 * num2 + num3 * num3;
				if (num4 < num)
				{
					num = num4;
				}
			}
			return num;
		}

		private static bool TrySampleAreaEnemySpawnPoint(LG_Area area, Random random, out Vector3 position, out Quaternion rotation)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			position = Vector3.zero;
			rotation = Quaternion.identity;
			try
			{
				List<Transform> enemySpawnPoints = area.m_enemySpawnPoints;
				if (enemySpawnPoints != null && enemySpawnPoints.Count > 0)
				{
					Transform val = enemySpawnPoints[random.Next(enemySpawnPoints.Count)];
					if ((Object)(object)val != (Object)null)
					{
						position = val.position;
						rotation = val.rotation;
						return true;
					}
				}
				if (area.TryGetRandomEnemySpawnPointInside(ref position, ref rotation))
				{
					return true;
				}
			}
			catch (Exception ex)
			{
				Log.Debug($"Enemy spawn point sampling failed for area {((Object)area).name}: {ex.GetType().Name}: {ex.Message}");
			}
			return false;
		}

		private static bool TrySampleAreaBounds(LG_Area area, Random random, float floorOffset, out Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			position = Vector3.zero;
			try
			{
				Bounds bounds = area.m_bounds;
				if (((Bounds)(ref bounds)).size.x <= 0.1f || ((Bounds)(ref bounds)).size.z <= 0.1f)
				{
					position = area.Position;
					return true;
				}
				Vector3 val = default(Vector3);
				((Vector3)(ref val))..ctor(Mathf.Lerp(((Bounds)(ref bounds)).min.x, ((Bounds)(ref bounds)).max.x, (float)random.NextDouble()), ((Bounds)(ref bounds)).max.y + 1f, Mathf.Lerp(((Bounds)(ref bounds)).min.z, ((Bounds)(ref bounds)).max.z, (float)random.NextDouble()));
				RaycastHit val2 = default(RaycastHit);
				if (Physics.Raycast(val, Vector3.down, ref val2, ((Bounds)(ref bounds)).size.y + 8f, -1, (QueryTriggerInteraction)1))
				{
					position = ((RaycastHit)(ref val2)).point + Vector3.up * floorOffset;
					return true;
				}
				position = new Vector3(val.x, ((Bounds)(ref bounds)).center.y + floorOffset, val.z);
				return true;
			}
			catch (Exception ex)
			{
				Log.Debug($"Bounds sampling failed for area {((Object)area).name}: {ex.GetType().Name}: {ex.Message}");
				return false;
			}
		}

		private static Quaternion ResolveRotation(SerializableVector3? rotation, SerializableVector3? forward, float? yaw, Quaternion fallback)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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)
			if (forward != null)
			{
				Vector3 val = forward.ToVector3();
				if (((Vector3)(ref val)).sqrMagnitude > 0.0001f)
				{
					return Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up);
				}
			}
			if (rotation != null)
			{
				return Quaternion.Euler(rotation.ToVector3());
			}
			if (yaw.HasValue)
			{
				return Quaternion.Euler(0f, yaw.Value, 0f);
			}
			return fallback;
		}

		private static LG_LayerType ParseLayer(string? layer, uint? layoutID)
		{
			if (string.IsNullOrWhiteSpace(layer))
			{
				if (layoutID.HasValue)
				{
					if (s_selectedSecondaryLayoutID.HasValue && s_selectedSecondaryLayoutID.Value == layoutID.Value)
					{
						return (LG_LayerType)1;
					}
					if (s_selectedThirdLayoutID.HasValue && s_selectedThirdLayoutID.Value == layoutID.Value)
					{
						return (LG_LayerType)2;
					}
				}
				return (LG_LayerType)0;
			}
			string text = layer.Trim();
			if (!text.Equals("Secondary", StringComparison.OrdinalIgnoreCase) && !text.Equals("SecondaryLayer", StringComparison.OrdinalIgnoreCase))
			{
				if (!text.Equals("Third", StringComparison.OrdinalIgnoreCase) && !text.Equals("ThirdLayer", StringComparison.OrdinalIgnoreCase))