Decompiled source of Hostile Mine v1.0.0
HostileMine.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
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))