Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of HazardsOutside v1.4.0
plugins/LCHazardsOutside/LCHazardsOutside.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using LCHazardsOutside.Abstract; using LCHazardsOutside.Config; using LCHazardsOutside.Data; using LCHazardsOutside.Feature; using LCHazardsOutside.ModCompatibility; using LCHazardsOutside.Patch; using LCHazardsOutside.Strategy; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("LCHazardsOutside")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.4.0.0")] [assembly: AssemblyInformationalVersion("1.4.0+75fc9115aab5666bf2a1bb84ca7d83c639705612")] [assembly: AssemblyProduct("LCHazardsOutside")] [assembly: AssemblyTitle("LCHazardsOutside")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.4.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LCHazardsOutside { public class LCUtils { public const int MAX_SPAWN_RATE = 100; public static readonly Dictionary<string, string[]> CUSTOM_LAYER_MASK = new Dictionary<string, string[]> { { VanillaMoon.march.ToString(), new string[1] { "Room" } } }; private static readonly Dictionary<SpawnStrategyType, SpawnStrategy> STRATEGY_MAP = new Dictionary<SpawnStrategyType, SpawnStrategy>(4) { { SpawnStrategyType.MainAndFireExit, MainAndFireExitSpawnStrategy.GetInstance() }, { SpawnStrategyType.MainEntranceOnly, MainEntranceOnlySpawnStrategy.GetInstance() }, { SpawnStrategyType.FireExitsOnly, FireExitsOnlySpawnStrategy.GetInstance() }, { SpawnStrategyType.Scattered, ScatteredSpawnStrategy.GetInstance() } }; private static readonly char[] INVALID_CONFIG_CHARS = new char[8] { '=', '\n', '\t', '\\', '"', '\'', '[', ']' }; public static SpawnStrategy GetSpawnStrategy(string typeString) { try { SpawnStrategyType key = (SpawnStrategyType)Enum.Parse(typeof(SpawnStrategyType), typeString); if (STRATEGY_MAP.TryGetValue(key, out var value)) { return value; } } catch (Exception) { Plugin.GetLogger().LogError((object)("Type " + typeString + " could not be parsed into a SpawnStrategyType. Reverting to default...")); } return MainAndFireExitSpawnStrategy.GetInstance(); } public static string GetNumberlessMoonName(SelectableLevel selectableLevel) { if ((Object)(object)selectableLevel != (Object)null) { return new string(selectableLevel.PlanetName.SkipWhile((char c) => !char.IsLetter(c)).ToArray()).ToLower(); } return string.Empty; } public static bool IsVanillaMoon(string moonName) { object result; return Enum.TryParse(typeof(VanillaMoon), moonName, ignoreCase: true, out result); } public static bool IsVanillaMoon(SelectableLevel selectableLevel) { object result; return Enum.TryParse(typeof(VanillaMoon), GetNumberlessMoonName(selectableLevel), ignoreCase: true, out result); } public static List<HazardDefinition> GetLevelHazards(SelectableLevel level) { if ((Object)(object)level == (Object)null) { return new List<HazardDefinition>(); } try { return GetIndoorMapHazards(level); } catch (Exception ex) when (ex is MissingFieldException || ex is TypeLoadException) { return GetLegacySpawnableMapObjects(level); } } [MethodImpl(MethodImplOptions.NoInlining)] private static List<HazardDefinition> GetIndoorMapHazards(SelectableLevel level) { List<HazardDefinition> list = new List<HazardDefinition>(); IndoorMapHazard[] array = level.indoorMapHazards ?? Array.Empty<IndoorMapHazard>(); for (int i = 0; i < array.Length; i++) { IndoorMapHazardType val = array[i]?.hazardType; if (!((Object)(object)val == (Object)null) && !((Object)(object)val.prefabToSpawn == (Object)null)) { list.Add(new HazardDefinition(i, val.prefabToSpawn, GetHazardType(val.prefabToSpawn), val.spawnFacingAwayFromWall, val.spawnFacingWall, val.spawnWithBackToWall, val.spawnWithBackFlushAgainstWall)); } } return list; } [MethodImpl(MethodImplOptions.NoInlining)] private static List<HazardDefinition> GetLegacySpawnableMapObjects(SelectableLevel level) { List<HazardDefinition> list = new List<HazardDefinition>(); SpawnableMapObject[] array = level.spawnableMapObjects ?? Array.Empty<SpawnableMapObject>(); for (int i = 0; i < array.Length; i++) { SpawnableMapObject val = array[i]; if (val != null && !((Object)(object)val.prefabToSpawn == (Object)null)) { list.Add(new HazardDefinition(i, val.prefabToSpawn, GetHazardType(val.prefabToSpawn), val.spawnFacingAwayFromWall, val.spawnFacingWall, val.spawnWithBackToWall, val.spawnWithBackFlushAgainstWall)); } } return list; } public static HazardType GetHazardType(GameObject prefab) { if ((Object)(object)prefab.GetComponentInChildren<Landmine>(true) != (Object)null) { return HazardType.Landmine; } if ((Object)(object)prefab.GetComponentInChildren<Turret>(true) != (Object)null) { return HazardType.Turret; } if ((Object)(object)prefab.GetComponentInChildren<SpikeRoofTrap>(true) != (Object)null) { return HazardType.SpikeRoofTrap; } return HazardType.Modded; } public static HazardDefinition FindHazardOfType(List<HazardDefinition> levelHazards, HazardType hazardType) { HazardDefinition hazardDefinition = levelHazards.FirstOrDefault((HazardDefinition h) => h.Type == hazardType); if (hazardDefinition != null || (Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.levels == null) { return hazardDefinition; } SelectableLevel[] levels = StartOfRound.Instance.levels; foreach (SelectableLevel level in levels) { hazardDefinition = GetLevelHazards(level).FirstOrDefault((HazardDefinition h) => h.Type == hazardType); if (hazardDefinition != null) { return hazardDefinition; } } return null; } public static List<Vector3> GetOutsideNodePositions(Vector3 shipLandPosition) { //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) return (from node in GameObject.FindGameObjectsWithTag("OutsideAINode") select node.transform.position into position orderby Vector3.Distance(position, shipLandPosition), position.x, position.z select position).ToList(); } public static bool IsInvalidSpawnPoint(List<Vector3> spawnDenialPoints, Vector3 randomPosition, float safetyDistance) { //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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) foreach (Vector3 spawnDenialPoint in spawnDenialPoints) { if (Vector3.Distance(randomPosition, spawnDenialPoint) < safetyDistance) { return true; } } return false; } public static bool IsBlockListed(GameObject prefab) { return Plugin.instance.hazardBlockList.Any((Type type) => (Object)(object)prefab.GetComponent(type) != (Object)null); } public static string SanitizeConfigName(string name) { string text = new string(name.Where((char c) => !INVALID_CONFIG_CHARS.Contains(c)).ToArray()).Trim(); return (text.Length > 0) ? text : "Unnamed"; } private static float RandomNumberInRadius(float radius, Random randomSeed) { return ((float)randomSeed.NextDouble() - 0.5f) * radius; } public static (Vector3, Quaternion) GetRandomGroundPositionAndRotation(Vector3 centerPoint, float radius = 10f, Random randomSeed = null, int layerMask = -1, int maxAttempts = 10) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0038: 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_0043: 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_006a: 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) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) float y = centerPoint.y; NavMeshHit val2 = default(NavMeshHit); RaycastHit val3 = default(RaycastHit); for (int i = 0; i < maxAttempts; i++) { try { float num = RandomNumberInRadius(radius, randomSeed); float num2 = RandomNumberInRadius(radius, randomSeed); float num3 = RandomNumberInRadius(radius, randomSeed); Vector3 val = centerPoint + new Vector3(num, num2, num3); val.y = y; float num4 = Vector3.Distance(centerPoint, val) + 30f; if (NavMesh.SamplePosition(val, ref val2, num4, -1)) { if (Physics.Raycast(((NavMeshHit)(ref val2)).position + Vector3.up, Vector3.down, ref val3, 50f, layerMask, (QueryTriggerInteraction)1)) { return (((RaycastHit)(ref val3)).point + Vector3.up * 0.1f, Quaternion.FromToRotation(Vector3.up, ((RaycastHit)(ref val3)).normal)); } Plugin.GetLogger().LogDebug((object)$"Nav hit at: {((NavMeshHit)(ref val2)).position} but ray cast failed."); } } catch (Exception) { } } return (Vector3.zero, Quaternion.identity); } public static void DetermineMinMaxSpawnRates(bool increasedMapHazardSpawnRate, int configMinSpawnRate, int configMaxSpawnRate, MoonMinMax moonMinMax, float multiplier, MoonMinMax minimum, out int minSpawnRate, out int maxSpawnRate) { int num = moonMinMax?.Min ?? configMinSpawnRate; int num2 = moonMinMax?.Max ?? configMaxSpawnRate; maxSpawnRate = Mathf.Clamp(num2, 0, 100); minSpawnRate = Mathf.Clamp(num, 0, maxSpawnRate); if (multiplier != 1f) { minSpawnRate = ScaleSpawnRate(minSpawnRate, multiplier); maxSpawnRate = ScaleSpawnRate(maxSpawnRate, multiplier); } if (minimum != null) { minSpawnRate = Mathf.Max(minSpawnRate, minimum.Min); maxSpawnRate = Mathf.Max(maxSpawnRate, minimum.Max); } if (increasedMapHazardSpawnRate) { minSpawnRate = Mathf.Min(minSpawnRate * 2, 100); maxSpawnRate = Mathf.Min(maxSpawnRate * 2, 100); } maxSpawnRate = Mathf.Min(maxSpawnRate, 100); minSpawnRate = Mathf.Min(minSpawnRate, maxSpawnRate); } private static int ScaleSpawnRate(int spawnRate, float multiplier) { return Mathf.Clamp((int)Math.Round((float)spawnRate * multiplier, MidpointRounding.AwayFromZero), 0, 100); } public static EntranceContainer FindAllExitPositions() { //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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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) EntranceTeleport[] array = Object.FindObjectsOfType<EntranceTeleport>(false); List<Vector3> list = new List<Vector3>(); Vector3 mainEntrancePosition = Vector3.zero; for (int i = 0; i < array.Length; i++) { EntranceTeleport val = array[i]; if (val.isEntranceToBuilding) { if (val.entranceId == 0) { mainEntrancePosition = ((Component)val).transform.position; } else { list.Add(((Component)array[i]).transform.position); } } } return new EntranceContainer(mainEntrancePosition, list); } public static Dictionary<string, MoonMinMax> ParseMoonString(string moonString) { if (string.IsNullOrEmpty(moonString)) { return new Dictionary<string, MoonMinMax>(); } Dictionary<string, MoonMinMax> dictionary = new Dictionary<string, MoonMinMax>(); string[] array = moonString.Trim().ToLower().Split(','); string[] array2 = array; foreach (string text in array2) { try { string[] array3 = text.Trim().Split(':'); dictionary.TryAdd(array3[0], new MoonMinMax(int.Parse(array3[1]), int.Parse(array3[2]))); } catch (Exception) { Plugin.GetLogger().LogError((object)("There was an error while parsing the moon string " + text + ". Make sure it has the format moon:min:max.")); } } return dictionary; } } [BepInPlugin("snake.tech.LCHazardsOutside", "LCHazardsOutside", "1.4.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string modGUID = "snake.tech.LCHazardsOutside"; private const string modName = "LCHazardsOutside"; private const string modVersion = "1.4.0"; private readonly Harmony harmony = new Harmony("snake.tech.LCHazardsOutside"); public static Plugin instance; public HashSet<Type> hazardBlockList = new HashSet<Type>(); public ConfigManager configManager; private void Awake() { if ((Object)(object)instance == (Object)null) { instance = this; } configManager = new ConfigManager(((BaseUnityPlugin)this).Config); configManager.LoadConfig(); new LateGameUpgradesHandler().Apply(); harmony.PatchAll(typeof(RoundManagerPatch)); harmony.PatchAll(typeof(StartOfRoundPatch)); GetLogger().LogInfo((object)"Plugin LCHazardsOutside is loaded!"); } public static ManualLogSource GetLogger() { return ((BaseUnityPlugin)instance).Logger; } } public static class PluginInfo { public const string PLUGIN_GUID = "LCHazardsOutside"; public const string PLUGIN_NAME = "LCHazardsOutside"; public const string PLUGIN_VERSION = "1.4.0"; } } namespace LCHazardsOutside.Strategy { internal class FireExitsOnlySpawnStrategy : SpawnStrategy { private static FireExitsOnlySpawnStrategy instance; private FireExitsOnlySpawnStrategy() { } public static FireExitsOnlySpawnStrategy GetInstance() { if (instance == null) { instance = new FireExitsOnlySpawnStrategy(); } return instance; } public override List<SpawnPositionData> CalculateCenterPositions(SpawnContext context, float spawnRadiusMultiplier) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) List<SpawnPositionData> list = new List<SpawnPositionData>(); foreach (Vector3 fireExitPosition in context.FireExitPositions) { list.Add(CalculateCenterWithSpawnRadius(context.ShipLandPosition, fireExitPosition, spawnRadiusMultiplier)); } return list; } } internal class MainAndFireExitSpawnStrategy : SpawnStrategy { private static MainAndFireExitSpawnStrategy instance; private MainAndFireExitSpawnStrategy() { } public static MainAndFireExitSpawnStrategy GetInstance() { if (instance == null) { instance = new MainAndFireExitSpawnStrategy(); } return instance; } public override List<SpawnPositionData> CalculateCenterPositions(SpawnContext context, float spawnRadiusMultiplier) { //IL_000a: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_0042: Unknown result type (might be due to invalid IL or missing references) List<SpawnPositionData> list = new List<SpawnPositionData>(1) { CalculateCenterWithSpawnRadius(context.ShipLandPosition, context.MainEntrancePosition, spawnRadiusMultiplier) }; foreach (Vector3 fireExitPosition in context.FireExitPositions) { list.Add(CalculateCenterWithSpawnRadius(context.ShipLandPosition, fireExitPosition, spawnRadiusMultiplier)); } return list; } } internal class MainEntranceOnlySpawnStrategy : SpawnStrategy { private static MainEntranceOnlySpawnStrategy instance; private MainEntranceOnlySpawnStrategy() { } public static MainEntranceOnlySpawnStrategy GetInstance() { if (instance == null) { instance = new MainEntranceOnlySpawnStrategy(); } return instance; } public override List<SpawnPositionData> CalculateCenterPositions(SpawnContext context, float spawnRadiusMultiplier) { //IL_0003: 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) SpawnPositionData item = CalculateCenterWithSpawnRadius(context.ShipLandPosition, context.MainEntrancePosition, spawnRadiusMultiplier); return new List<SpawnPositionData>(1) { item }; } } internal class ScatteredSpawnStrategy : SpawnStrategy { private const float NODE_SPAWN_RADIUS = 14f; private static ScatteredSpawnStrategy instance; private ScatteredSpawnStrategy() { } public static ScatteredSpawnStrategy GetInstance() { if (instance == null) { instance = new ScatteredSpawnStrategy(); } return instance; } public override List<SpawnPositionData> CalculateCenterPositions(SpawnContext context, float spawnRadiusMultiplier) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) if (context.OutsideNodePositions.Count == 0) { Plugin.GetLogger().LogWarning((object)"This moon has no outside AI nodes. Falling back to MainAndFireExit."); return MainAndFireExitSpawnStrategy.GetInstance().CalculateCenterPositions(context, spawnRadiusMultiplier); } List<Vector3> list = new List<Vector3>(context.OutsideNodePositions); for (int num = list.Count - 1; num > 0; num--) { int num2 = context.Random.Next(0, num + 1); List<Vector3> list2 = list; int index = num; int index2 = num2; Vector3 value = list[num2]; Vector3 value2 = list[num]; list2[index] = value; list[index2] = value2; } List<SpawnPositionData> list3 = new List<SpawnPositionData>(); foreach (Vector3 item in list) { list3.Add(new SpawnPositionData(item, 14f * spawnRadiusMultiplier)); } return list3; } } internal class TurretNestSpawnStrategy : SpawnStrategy { private const float DISTANCE_TO_ENTRANCE = 0.75f; private const float NEST_SPAWN_RADIUS = 30f; private static TurretNestSpawnStrategy instance; private TurretNestSpawnStrategy() { } public static TurretNestSpawnStrategy GetInstance() { if (instance == null) { instance = new TurretNestSpawnStrategy(); } return instance; } public override List<SpawnPositionData> CalculateCenterPositions(SpawnContext context, float spawnRadiusMultiplier) { //IL_0002: 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_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_001b: 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_0041: Unknown result type (might be due to invalid IL or missing references) Vector3 centerPosition = Vector3.Lerp(context.ShipLandPosition, context.MainEntrancePosition, 0.75f); centerPosition.y = Mathf.Max(context.ShipLandPosition.y, context.MainEntrancePosition.y); return new List<SpawnPositionData>(1) { new SpawnPositionData(centerPosition, 30f) }; } } } namespace LCHazardsOutside.Patch { [HarmonyPatch(typeof(RoundManager))] internal class RoundManagerPatch { private const int SEED_OFFSET = 4587; private const int EVENT_SEED_OFFSET = 4588; private const int GUARD_SEED_OFFSET = 4589; [HarmonyPatch("SpawnOutsideHazards")] [HarmonyPrefix] private static void SpawnHazardsOutsidePatch(RoundManager __instance) { if (!__instance.currentLevel.spawnEnemiesAndScrap || !((NetworkBehaviour)__instance).IsServer || !((NetworkBehaviour)__instance).IsHost) { return; } int randomMapSeed = StartOfRound.Instance.randomMapSeed; Plugin.GetLogger().LogDebug((object)("randomMapSeed: " + randomMapSeed)); Random random = new Random(randomMapSeed + 4587); int value = Plugin.instance.configManager.noHazardSpawnChance.Value; if (value > 0) { double num = (double)value / 100.0; if (random.NextDouble() < num) { Plugin.GetLogger().LogInfo((object)"No hazards spawned outside due to global chance."); return; } } List<HazardDefinition> levelHazards = LCUtils.GetLevelHazards(__instance.currentLevel); if (levelHazards.Count != 0) { Random random2 = new Random(randomMapSeed + 4588); HazardEvent hazardEvent = HazardEvents.Roll(random2, GetConfigManager()); if (hazardEvent == HazardEvent.QuietDay) { Plugin.GetLogger().LogInfo((object)"Hazard event: QuietDay. No hazards spawned outside."); HazardEvents.Announce(hazardEvent); } else { ((MonoBehaviour)__instance).StartCoroutine(SpawnHazardsAfterExitSpawn(__instance, levelHazards, random, hazardEvent, random2, new Random(randomMapSeed + 4589))); } } } private static void SpawnHazardsOutside(RoundManager __instance, List<HazardDefinition> hazards, EntranceContainer entranceContainer, Random random, HazardEvent hazardEvent, Random eventRandom, Random guardRandom) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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) string numberlessMoonName = LCUtils.GetNumberlessMoonName(__instance.currentLevel); Plugin.GetLogger().LogDebug((object)("Planetname: " + numberlessMoonName)); LCUtils.CUSTOM_LAYER_MASK.TryGetValue(numberlessMoonName, out var value); if (value == null) { value = new string[2] { "Room", "Default" }; } int mask = LayerMask.GetMask(value); List<Vector3> spawnDenialPositions = GetSpawnDenialPositions(__instance); List<GameObject> list = new List<GameObject>(); Vector3 position = __instance.shipSpawnPathPoints.Last().position; SpawnContext context = new SpawnContext(position, entranceContainer.MainEntrancePosition, entranceContainer.FireExitPositions, LCUtils.GetOutsideNodePositions(position), random); float multiplier = Scaling.GetMultiplier(GetConfigManager()); Plugin.GetLogger().LogInfo((object)$"Run scaling multiplier: {multiplier:0.##}"); if (hazardEvent != HazardEvent.None) { Plugin.GetLogger().LogInfo((object)$"Hazard event: {hazardEvent}"); } bool flag = false; foreach (HazardDefinition hazard in hazards) { Plugin.GetLogger().LogDebug((object)("Current spawnable object: " + hazard.Name)); if (LCUtils.IsBlockListed(hazard.Prefab)) { Plugin.GetLogger().LogInfo((object)("Hazard blocked from spawning due to blacklist: " + hazard.Name)); continue; } bool isIncreasedSpawnRate = __instance.increasedMapHazardSpawnRateIndex == hazard.Index; try { int num = ProcessHazard(hazard, __instance, isIncreasedSpawnRate, spawnDenialPositions, numberlessMoonName, context, random, mask, list, hazardEvent, multiplier); flag |= num > 0 && HazardEvents.IsForced(hazardEvent, hazard.Type); } catch (Exception arg) { Plugin.GetLogger().LogError((object)$"Could not spawn {hazard.Name} outside: {arg}"); } } if (hazardEvent == HazardEvent.TurretNest) { try { flag = SpawnTurretNest(__instance, hazards, spawnDenialPositions, context, eventRandom, mask, list) > 0; } catch (Exception arg2) { Plugin.GetLogger().LogError((object)$"Could not spawn the turret nest: {arg2}"); } } if (GetConfigManager().FireExitGuardsEnabled) { try { SpawnFireExitGuards(__instance, hazards, spawnDenialPositions, context, guardRandom, mask, list); } catch (Exception arg3) { Plugin.GetLogger().LogError((object)$"Could not spawn fire exit guards: {arg3}"); } } if (flag) { HazardEvents.Announce(hazardEvent); } else if (hazardEvent != HazardEvent.None) { Plugin.GetLogger().LogWarning((object)$"Hazard event {hazardEvent} had nothing to spawn on this moon."); } ((MonoBehaviour)__instance).StartCoroutine(SpawnHazardsInBulk(list)); Plugin.GetLogger().LogInfo((object)"Outside hazard spawning done."); } private static int SpawnTurretNest(RoundManager __instance, List<HazardDefinition> hazards, List<Vector3> denialPoints, SpawnContext context, Random eventRandom, int layerMask, List<GameObject> hazardObjects) { HazardDefinition hazardDefinition = LCUtils.FindHazardOfType(hazards, HazardType.Turret); if (hazardDefinition == null) { Plugin.GetLogger().LogWarning((object)"No turret found in any level. Skipping the turret nest."); return 0; } HazardCalculationContainer hazardCalculationContainer = new HazardCalculationContainer(eventRandom, denialPoints, hazardDefinition, 3, 6, layerMask) { NeedsSafetyZone = true }; return CalculateHazardSpawn(__instance, hazardCalculationContainer, context, TurretNestSpawnStrategy.GetInstance(), hazardObjects); } private static void SpawnFireExitGuards(RoundManager __instance, List<HazardDefinition> hazards, List<Vector3> denialPoints, SpawnContext context, Random guardRandom, int layerMask, List<GameObject> hazardObjects) { if (context.FireExitPositions.Count != 0) { HazardDefinition hazardDefinition = LCUtils.FindHazardOfType(hazards, HazardType.Turret); if (hazardDefinition == null) { Plugin.GetLogger().LogWarning((object)"No turret found in any level. Skipping fire exit guards."); } else { FireExitGuards.Spawn(__instance, hazardDefinition, context, denialPoints, layerMask, guardRandom, hazardObjects); } } } private static int ProcessHazard(HazardDefinition hazard, RoundManager __instance, bool isIncreasedSpawnRate, List<Vector3> denialPoints, string moonName, SpawnContext context, Random random, int layerMask, List<GameObject> hazardObjects, HazardEvent hazardEvent, float scalingMultiplier) { HazardConfiguration hazardConfig = GetConfigManager().GetHazardConfig(hazard); if (HazardEvents.IsSuppressed(hazardEvent, hazard.Type)) { Plugin.GetLogger().LogDebug((object)$"{hazard.Name} skipped because of the {hazardEvent} event."); return 0; } if (!hazardConfig.Enabled && !HazardEvents.IsForced(hazardEvent, hazard.Type)) { return 0; } Plugin.GetLogger().LogInfo((object)$"Spawning {hazard.Name} ({hazard.Type}) outside..."); hazardConfig.MoonMap.TryGetValue(moonName, out var value); float multiplier = scalingMultiplier * HazardEvents.GetMultiplier(hazardEvent, hazard.Type); LCUtils.DetermineMinMaxSpawnRates(isIncreasedSpawnRate, hazardConfig.MinSpawnRate, hazardConfig.MaxSpawnRate, value, multiplier, HazardEvents.GetMinimum(hazardEvent, hazard.Type), out var minSpawnRate, out var maxSpawnRate); HazardCalculationContainer hazardCalculationContainer = new HazardCalculationContainer(random, denialPoints, hazard, minSpawnRate, maxSpawnRate, layerMask); if (hazard.Type == HazardType.Turret) { hazardCalculationContainer.NeedsSafetyZone = true; hazardCalculationContainer.SpawnRatioMultiplier = 1.25f; } if (hazard.Type == HazardType.SpikeRoofTrap) { hazardCalculationContainer.NeedsSafetyZone = true; } return CalculateHazardSpawn(__instance, hazardCalculationContainer, context, hazardConfig.SpawnStrategy, hazardObjects); } private unsafe static int CalculateHazardSpawn(RoundManager __instance, HazardCalculationContainer hazardCalculationContainer, SpawnContext context, SpawnStrategy spawnStrategy, List<GameObject> gameObjects) { //IL_0128: 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_0146: 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_014d: 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_0178: 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_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) Random random = hazardCalculationContainer.Random; int num = random.Next(hazardCalculationContainer.MinSpawnRate, hazardCalculationContainer.MaxSpawnRate + 1); Plugin.GetLogger().LogDebug((object)("Random spawn rate: " + num)); List<SpawnPositionData> list = spawnStrategy.CalculateCenterPositions(context, hazardCalculationContainer.SpawnRatioMultiplier); if (list.Count == 0) { Plugin.GetLogger().LogWarning((object)(spawnStrategy.GetType().Name + " found no spawn positions on this moon. Skipping " + hazardCalculationContainer.Hazard.Name + ".")); return 0; } int count = list.Count; int num2 = num / count; int num3 = num % count; int num4 = random.Next(0, count); Plugin.GetLogger().LogDebug((object)$"Spawn rate per position: {num2}, remainder: {num3}"); int num5 = 0; int layerMask = hazardCalculationContainer.LayerMask; float safetyDistance = (hazardCalculationContainer.NeedsSafetyZone ? 18f : 8f); for (int i = 0; i < count; i++) { SpawnPositionData spawnPositionData = list[i]; bool flag = (i - num4 + count) % count < num3; int num6 = num2 + (flag ? 1 : 0); for (int j = 0; j < num6; j++) { var (val, groundRotation) = LCUtils.GetRandomGroundPositionAndRotation(spawnPositionData.CenterPosition, spawnPositionData.SpawnRadius, random, layerMask); if (val == Vector3.zero) { Plugin.GetLogger().LogDebug((object)"No NavMesh hit!"); } else if (LCUtils.IsInvalidSpawnPoint(hazardCalculationContainer.SpawnDenialPoints, val, safetyDistance)) { ManualLogSource logger = Plugin.GetLogger(); Vector3 val2 = val; logger.LogDebug((object)("Hazard was too close to denial or safety zone and was therefore deleted: " + ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString())); } else { gameObjects.Add(InstantiateHazardObject(__instance, hazardCalculationContainer.Hazard, val, groundRotation, random)); num5++; } } } Plugin.GetLogger().LogDebug((object)("Total hazard amount: " + num5)); return num5; } private static List<Vector3> GetSpawnDenialPositions(RoundManager __instance) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) List<Vector3> list = new List<Vector3>(1) { __instance.shipSpawnPathPoints.Last().position }; list.AddRange(from x in GameObject.FindGameObjectsWithTag("SpawnDenialPoint") select x.transform.position); GameObject val = GameObject.Find("PlayerShipNavmesh"); if ((Object)(object)val != (Object)null) { list.Add(val.transform.position); } return list; } private unsafe static GameObject InstantiateHazardObject(RoundManager __instance, HazardDefinition hazard, Vector3 position, Quaternion groundRotation, Random random) { //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_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_006a: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: 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_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: 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_00cd: 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_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: 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_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) ManualLogSource logger = Plugin.GetLogger(); Vector3 val = position; logger.LogDebug((object)("Spawn hazard outside at: " + ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString())); GameObject val2 = Object.Instantiate<GameObject>(hazard.Prefab, position, groundRotation, __instance.mapPropsContainer.transform); bool flag = hazard.Type == HazardType.Landmine; if (hazard.SpawnFacingAwayFromWall && !flag) { val2.transform.eulerAngles = new Vector3(0f, __instance.YRotationThatFacesTheFarthestFromPosition(position + Vector3.up * 0.2f, 25f, 6), 0f); } else if (hazard.SpawnFacingWall && !flag) { val2.transform.eulerAngles = new Vector3(0f, __instance.YRotationThatFacesTheNearestFromPosition(position + Vector3.up * 0.2f, 25f, 6), 0f); } else { val2.transform.rotation = groundRotation * Quaternion.Euler(0f, (float)random.Next(0, 360), 0f); } RaycastHit val3 = default(RaycastHit); if (hazard.SpawnWithBackToWall && Physics.Raycast(val2.transform.position, -val2.transform.forward, ref val3, 300f, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1)) { RaycastHit val4 = default(RaycastHit); if (Physics.Raycast(((RaycastHit)(ref val3)).point + Vector3.up * 0.2f, Vector3.down, ref val4, 50f, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1)) { val2.transform.position = ((RaycastHit)(ref val4)).point; } else { val2.transform.position = ((RaycastHit)(ref val3)).point; } if (hazard.SpawnWithBackFlushAgainstWall) { val2.transform.forward = ((RaycastHit)(ref val3)).normal; val2.transform.eulerAngles = new Vector3(0f, val2.transform.eulerAngles.y, 0f); } } val2.SetActive(true); return val2; } public static IEnumerator SpawnHazardsInBulk(List<GameObject> gameObjects) { Plugin.GetLogger().LogDebug((object)"SpawnHazardsInBulk Coroutine running."); for (int i = 0; i < gameObjects.Count; i += 10) { int range = Mathf.Min(10, gameObjects.Count - i); for (int j = 0; j < range; j++) { GameObject objectToSpawn = gameObjects[i + j]; try { if ((Object)(object)objectToSpawn != (Object)null) { NetworkObject networkObject = objectToSpawn.GetComponent<NetworkObject>(); if ((Object)(object)networkObject != (Object)null) { networkObject.Spawn(true); } else { Plugin.GetLogger().LogError((object)("Hazard " + ((Object)objectToSpawn).name + " had no network object and cannot be spawned.")); } } else { Plugin.GetLogger().LogError((object)"Hazard object was destroyed before it could spawn. Probably needs compatibility patch."); } } catch (Exception arg) { Plugin.GetLogger().LogError((object)$"NetworkObject {((Object)objectToSpawn).name} could not be spawned: {arg}"); } } yield return (object)new WaitForSeconds(0.5f); } Plugin.GetLogger().LogDebug((object)"SpawnHazardsInBulk Coroutine done."); } public static IEnumerator SpawnHazardsAfterExitSpawn(RoundManager __instance, List<HazardDefinition> hazards, Random random, HazardEvent hazardEvent, Random eventRandom, Random guardRandom) { float startTime = Time.timeSinceLevelLoad; EntranceContainer entranceContainer = LCUtils.FindAllExitPositions(); Plugin.GetLogger().LogDebug((object)$"Time since level loaded: {startTime}"); while (!entranceContainer.IsInitialized() && Time.timeSinceLevelLoad - startTime < 15f) { Plugin.GetLogger().LogDebug((object)"Waiting for main entrance to load..."); yield return (object)new WaitForSeconds(1f); entranceContainer = LCUtils.FindAllExitPositions(); } SpawnHazardsOutside(__instance, hazards, entranceContainer, random, hazardEvent, eventRandom, guardRandom); } private static ConfigManager GetConfigManager() { return Plugin.instance.configManager; } } [HarmonyPatch(typeof(StartOfRound))] internal class StartOfRoundPatch { [HarmonyPatch("Start")] [HarmonyPostfix] private static void RegisterModdedHazardConfigs(StartOfRound __instance) { if (__instance.levels == null) { return; } SelectableLevel[] levels = __instance.levels; foreach (SelectableLevel val in levels) { try { foreach (HazardDefinition levelHazard in LCUtils.GetLevelHazards(val)) { if (levelHazard.Type == HazardType.Modded && !LCUtils.IsBlockListed(levelHazard.Prefab)) { Plugin.instance.configManager.GetOrBindModdedHazardConfig(levelHazard.Name); } } } catch (Exception arg) { Plugin.GetLogger().LogError((object)$"Could not register modded hazard configs for level {val?.PlanetName}: {arg}"); } } } } } namespace LCHazardsOutside.ModCompatibility { internal class LateGameUpgradesHandler : AbstractCompatibilityHandler { [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] protected override void DoApply() { LogApply(); Assembly targetAssembly = GetTargetAssembly("MoreShipUpgrades"); if (targetAssembly == null) { Plugin.GetLogger().LogError((object)"Target assembly 'MoreShipUpgrades' not found."); return; } AddTypeToHazardBlockList(targetAssembly, "MoreShipUpgrades.UpgradeComponents.Items.Wheelbarrow.ScrapWheelbarrow"); AddContractItemsToBlocklist(targetAssembly); } private void AddTypeToHazardBlockList(Assembly assembly, string typeName) { Type type = assembly.GetTypes().FirstOrDefault((Type t) => t.FullName == typeName); if (type != null) { Plugin.instance.hazardBlockList.Add(type); Plugin.GetLogger().LogDebug((object)("Added " + typeName + " to hazardBlockList.")); } else { Plugin.GetLogger().LogWarning((object)("Type " + typeName + " not found in assembly.")); } } private void AddContractItemsToBlocklist(Assembly assembly) { Type baseType = assembly.GetTypes().FirstOrDefault((Type t) => t.Name == "ContractObject"); if (baseType == null) { Plugin.GetLogger().LogError((object)"Base type ContractObject not found in assembly."); return; } IEnumerable<Type> enumerable = from t in assembly.GetTypes() where t.IsClass && !t.IsAbstract && t.IsSubclassOf(baseType) select t; foreach (Type item in enumerable) { Plugin.instance.hazardBlockList.Add(item); Plugin.GetLogger().LogDebug((object)("Added " + item.Name + " to hazardBlockList.")); } } protected override string GetModGUID() { return "com.malco.lethalcompany.moreshipupgrades"; } } } namespace LCHazardsOutside.Feature { internal static class FireExitGuards { private const float MIN_DOOR_DISTANCE = 8f; private const float MAX_DOOR_DISTANCE = 14f; private const float MAX_ANGLE = 40f; private const float SAFETY_DISTANCE = 18f; public unsafe static int Spawn(RoundManager roundManager, HazardDefinition turret, SpawnContext context, List<Vector3> denialPoints, int layerMask, Random random, List<GameObject> hazardObjects) { //IL_0094: 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_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: 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) //IL_00de: 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_0135: 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_014a: 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_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) ConfigManager configManager = Plugin.instance.configManager; double num = (double)configManager.GuardChancePerExit / 100.0; int num2 = Mathf.Clamp(configManager.TurretsPerExit, 1, 3); int num3 = 0; List<Vector3> list = (from position in context.FireExitPositions orderby position.x, position.z select position).ToList(); foreach (Vector3 item2 in list) { if (random.NextDouble() >= num) { continue; } Vector3 val = context.ShipLandPosition - item2; val.y = 0f; val = ((((Vector3)(ref val)).sqrMagnitude > 0.01f) ? ((Vector3)(ref val)).normalized : Vector3.forward); for (int num4 = 0; num4 < num2; num4++) { float num5 = (float)(random.NextDouble() * 2.0 * 40.0 - 40.0); float num6 = 8f + (float)random.NextDouble() * 6f; Vector3 centerPoint = item2 + Quaternion.Euler(0f, num5, 0f) * val * num6; Vector3 item = LCUtils.GetRandomGroundPositionAndRotation(centerPoint, 2f, random, layerMask).Item1; if (item == Vector3.zero) { Plugin.GetLogger().LogDebug((object)"No ground found for a fire exit guard."); continue; } float num7 = Vector3.Distance(item, item2); if (num7 < 5f || num7 > 20f) { Plugin.GetLogger().LogDebug((object)$"Fire exit guard position too far from the door ({num7:0.0} m)."); continue; } if (LCUtils.IsInvalidSpawnPoint(denialPoints, item, 18f)) { ManualLogSource logger = Plugin.GetLogger(); Vector3 val2 = item; logger.LogDebug((object)("Fire exit guard too close to the ship or a spawn denial point: " + ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString())); continue; } Vector3 val3 = item2 - item; val3.y = 0f; Quaternion val4 = ((((Vector3)(ref val3)).sqrMagnitude > 0.01f) ? Quaternion.LookRotation(((Vector3)(ref val3)).normalized) : Quaternion.identity); GameObject val5 = Object.Instantiate<GameObject>(turret.Prefab, item, val4, roundManager.mapPropsContainer.transform); val5.SetActive(true); hazardObjects.Add(val5); num3++; } } Plugin.GetLogger().LogDebug((object)$"Fire exit guards: {num3}"); return num3; } } internal static class HazardEvents { private const float MINEFIELD_MULTIPLIER = 2.5f; private static readonly MoonMinMax MINEFIELD_MINIMUM = new MoonMinMax(20, 40); public const int TURRET_NEST_MIN = 3; public const int TURRET_NEST_MAX = 6; public static HazardEvent Roll(Random random, ConfigManager configManager) { double num = random.NextDouble(); List<HazardEvent> enabledEvents = configManager.GetEnabledEvents(); if (enabledEvents.Count == 0 || num >= (double)configManager.EventChance / 100.0) { return HazardEvent.None; } return enabledEvents[random.Next(0, enabledEvents.Count)]; } public static bool IsSuppressed(HazardEvent hazardEvent, HazardType hazardType) { return hazardEvent switch { HazardEvent.Minefield => hazardType == HazardType.Turret || hazardType == HazardType.SpikeRoofTrap, HazardEvent.QuietDay => true, _ => false, }; } public static bool IsForced(HazardEvent hazardEvent, HazardType hazardType) { return hazardEvent == HazardEvent.Minefield && hazardType == HazardType.Landmine; } public static float GetMultiplier(HazardEvent hazardEvent, HazardType hazardType) { return IsForced(hazardEvent, hazardType) ? 2.5f : 1f; } public static MoonMinMax GetMinimum(HazardEvent hazardEvent, HazardType hazardType) { return IsForced(hazardEvent, hazardType) ? MINEFIELD_MINIMUM : null; } public static void Announce(HazardEvent hazardEvent) { if (!Plugin.instance.configManager.announceEvents.Value || (Object)(object)HUDManager.Instance == (Object)null) { return; } if (1 == 0) { } string text = hazardEvent switch { HazardEvent.Minefield => "Warning: high landmine activity detected outside.", HazardEvent.TurretNest => "Warning: turret nest detected near the main entrance.", HazardEvent.QuietDay => "No hazard activity detected outside today.", _ => null, }; if (1 == 0) { } string text2 = text; if (text2 == null) { return; } try { HUDManager.Instance.AddTextToChatOnServer(text2, -1); } catch (Exception arg) { Plugin.GetLogger().LogError((object)$"Could not announce hazard event {hazardEvent}: {arg}"); } } } internal static class Scaling { public static float GetMultiplier(ConfigManager configManager) { ScalingMode scalingMode = configManager.ScalingMode; if (1 == 0) { } int num = scalingMode switch { ScalingMode.Days => (StartOfRound.Instance?.gameStats?.daysSpent).GetValueOrDefault(), ScalingMode.Quotas => TimeOfDay.Instance?.timesFulfilledQuota ?? 0, _ => 0, }; if (1 == 0) { } int num2 = num; float num3 = Mathf.Max(1f, configManager.ScalingMaxMultiplier); return Mathf.Clamp(1f + (float)(num2 * configManager.ScalingPercentPerStep) / 100f, 1f, num3); } } } namespace LCHazardsOutside.Data { public class EntranceContainer(Vector3 mainEntrancePosition, List<Vector3> fireExitPositions) { public Vector3 MainEntrancePosition { get; set; } = mainEntrancePosition; public List<Vector3> FireExitPositions { get; set; } = fireExitPositions; public bool IsInitialized() { //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) return MainEntrancePosition != Vector3.zero && FireExitPositions.All((Vector3 x) => x != Vector3.zero); } } internal class HazardCalculationContainer { public Random Random { get; set; } public List<Vector3> SpawnDenialPoints { get; set; } public HazardDefinition Hazard { get; set; } public int MinSpawnRate { get; set; } public int MaxSpawnRate { get; set; } public bool NeedsSafetyZone { get; set; } public float SpawnRatioMultiplier { get; set; } public int LayerMask { get; set; } public HazardCalculationContainer(Random random, List<Vector3> spawnDenialPoints, HazardDefinition hazard, int minSpawnRate, int maxSpawnRate, int layerMask) { Random = random; SpawnDenialPoints = spawnDenialPoints; Hazard = hazard; MinSpawnRate = minSpawnRate; MaxSpawnRate = maxSpawnRate; NeedsSafetyZone = false; SpawnRatioMultiplier = 1.5f; LayerMask = layerMask; base..ctor(); } } public class HazardConfiguration(bool enabled, int minSpawnRate, int maxSpawnRate, Dictionary<string, MoonMinMax> moonMap, SpawnStrategy spawnStrategy) { public bool Enabled { get; set; } = enabled; public int MinSpawnRate { get; set; } = minSpawnRate; public int MaxSpawnRate { get; set; } = maxSpawnRate; public Dictionary<string, MoonMinMax> MoonMap { get; set; } = moonMap; public SpawnStrategy SpawnStrategy { get; set; } = spawnStrategy; } public class HazardDefinition(int index, GameObject prefab, HazardType hazardType, bool spawnFacingAwayFromWall, bool spawnFacingWall, bool spawnWithBackToWall, bool spawnWithBackFlushAgainstWall) { public int Index { get; } = index; public GameObject Prefab { get; } = prefab; public HazardType Type { get; } = hazardType; public bool SpawnFacingAwayFromWall { get; } = spawnFacingAwayFromWall; public bool SpawnFacingWall { get; } = spawnFacingWall; public bool SpawnWithBackToWall { get; } = spawnWithBackToWall; public bool SpawnWithBackFlushAgainstWall { get; } = spawnWithBackFlushAgainstWall; public string Name => ((Object)Prefab).name; } public enum HazardEvent { None, Minefield, TurretNest, QuietDay } public enum HazardType { Landmine, Turret, SpikeRoofTrap, Modded } public class MoonMinMax(int min, int max) { public int Min { get; set; } = min; public int Max { get; set; } = max; } public enum Preset { Custom, Chill, Classic, Minefield, Warzone } public class PresetHazard(bool enabled, int minSpawnRate, int maxSpawnRate) { public bool Enabled { get; } = enabled; public int MinSpawnRate { get; } = minSpawnRate; public int MaxSpawnRate { get; } = maxSpawnRate; } public class PresetValues(Dictionary<HazardType, PresetHazard> hazards, int eventChance, bool fireExitGuardsEnabled, int guardChancePerExit, int turretsPerExit, ScalingMode scalingMode, int scalingPercentPerStep, float scalingMaxMultiplier) { public Dictionary<HazardType, PresetHazard> Hazards { get; } = hazards; public int EventChance { get; } = eventChance; public bool FireExitGuardsEnabled { get; } = fireExitGuardsEnabled; public int GuardChancePerExit { get; } = guardChancePerExit; public int TurretsPerExit { get; } = turretsPerExit; public ScalingMode ScalingMode { get; } = scalingMode; public int ScalingPercentPerStep { get; } = scalingPercentPerStep; public float ScalingMaxMultiplier { get; } = scalingMaxMultiplier; } public enum ScalingMode { Off, Days, Quotas } public class SpawnContext(Vector3 shipLandPosition, Vector3 mainEntrancePosition, List<Vector3> fireExitPositions, List<Vector3> outsideNodePositions, Random random) { public Vector3 ShipLandPosition { get; } = shipLandPosition; public Vector3 MainEntrancePosition { get; } = mainEntrancePosition; public List<Vector3> FireExitPositions { get; } = fireExitPositions; public List<Vector3> OutsideNodePositions { get; } = outsideNodePositions; public Random Random { get; } = random; } public record struct SpawnPositionData { public Vector3 CenterPosition { get; set; } public float SpawnRadius { get; set; } public SpawnPositionData(Vector3 centerPosition, float spawnRadius) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) this = default(SpawnPositionData); CenterPosition = centerPosition; SpawnRadius = spawnRadius; } } public enum SpawnStrategyType { MainAndFireExit, MainEntranceOnly, FireExitsOnly, Scattered } internal enum VanillaMoon { experimentation, assurance, offense, vow, march, rend, dine, titan, adamance, embrion, artifice, liquidation } } namespace LCHazardsOutside.Config { public class ConfigManager(ConfigFile config) { private const string MODDED_CATEGORY_PREFIX = "4. Modded - "; private const string PRESET_NOTE = " Ignored while Preset is not Custom."; private readonly ConfigFile config = config; public readonly Dictionary<HazardType, HazardConfiguration> hazardConfigMap = new Dictionary<HazardType, HazardConfiguration>(); public readonly Dictionary<string, HazardConfiguration> moddedHazardConfigMap = new Dictionary<string, HazardConfiguration>(); public ConfigEntry<int> noHazardSpawnChance; public ConfigEntry<Preset> preset; public ConfigEntry<bool> announceEvents; private ConfigEntry<int> eventChance; private ConfigEntry<string> events; private ConfigEntry<bool> fireExitGuardsEnabled; private ConfigEntry<int> guardChancePerExit; private ConfigEntry<int> turretsPerExit; private ConfigEntry<ScalingMode> scalingMode; private ConfigEntry<int> scalingPercentPerStep; private ConfigEntry<float> scalingMaxMultiplier; private ConfigDescription spawnStrategyDescription; private AcceptableValueRange<int> spawnRateRange; private PresetValues ActivePreset => Presets.Get(preset.Value); public int EventChance => ActivePreset?.EventChance ?? eventChance.Value; public bool FireExitGuardsEnabled => ActivePreset?.FireExitGuardsEnabled ?? fireExitGuardsEnabled.Value; public int GuardChancePerExit => ActivePreset?.GuardChancePerExit ?? guardChancePerExit.Value; public int TurretsPerExit => ActivePreset?.TurretsPerExit ?? turretsPerExit.Value; public ScalingMode ScalingMode => ActivePreset?.ScalingMode ?? scalingMode.Value; public int ScalingPercentPerStep => ActivePreset?.ScalingPercentPerStep ?? scalingPercentPerStep.Value; public float ScalingMaxMultiplier => ActivePreset?.ScalingMaxMultiplier ?? scalingMaxMultiplier.Value; public void LoadConfig() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Expected O, but got Unknown //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Expected O, but got Unknown //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Expected O, but got Unknown //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Expected O, but got Unknown //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Expected O, but got Unknown //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Expected O, but got Unknown //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Expected O, but got Unknown //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Expected O, but got Unknown //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Expected O, but got Unknown spawnStrategyDescription = new ConfigDescription("This setting dictates how spawn positions are allocated. It has 4 possible options: \"MainAndFireExit\", \"MainEntranceOnly\", \"FireExitsOnly\" and \"Scattered\" (spread over the whole outdoor map).", (AcceptableValueBase)(object)new AcceptableValueList<string>(Enum.GetNames(typeof(SpawnStrategyType))), Array.Empty<object>()); spawnRateRange = new AcceptableValueRange<int>(0, 100); noHazardSpawnChance = config.Bind<int>("0. General", "NoHazardSpawnChance", 0, new ConfigDescription("A global chance from 0 to 100 in % for NO hazards to spawn outside.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); noHazardSpawnChance.SettingChanged += delegate { Plugin.GetLogger().LogInfo((object)$"NoHazardSpawnChance updated: {noHazardSpawnChance.Value}"); }; preset = BindLogged("0. General", "Preset", Preset.Custom, new ConfigDescription("Custom uses the values in this config. Chill, Classic, Minefield and Warzone replace the enable/min/max settings of landmines, turrets and spike traps, and all settings in 5. Events, 6. Guarded fire exits and 7. Scaling. Per-moon settings, spawn strategies, NoHazardSpawnChance and modded hazards still come from this config.", (AcceptableValueBase)null, Array.Empty<object>())); hazardConfigMap[HazardType.Landmine] = BindHazardConfig(HazardType.Landmine.ToString().ToLower(), "1. Landmine", "EnableLandmineOutside", "LandmineMinSpawnRate", "LandmineMaxSpawnRate", "LandmineMoons", "LandmineSpawnStrategy", defaultEnable: true, 15, 30); hazardConfigMap[HazardType.Turret] = BindHazardConfig(HazardType.Turret.ToString().ToLower(), "2. Turret", "EnableTurretOutside", "TurretMinSpawnRate", "TurretMaxSpawnRate", "TurretMoons", "TurretSpawnStrategy", defaultEnable: false, 0, 1); hazardConfigMap[HazardType.SpikeRoofTrap] = BindHazardConfig(HazardType.SpikeRoofTrap.ToString().ToLower(), "3. SpikeRoofTrap", "EnableSpikeRoofTrapOutside", "SpikeRoofTraptMinSpawnRate", "SpikeRoofTrapMaxSpawnRate", "SpikeRoofTrapMoons", "SpikeRoofTrapSpawnStrategy", defaultEnable: true, 0, 2); eventChance = BindLogged("5. Events", "EventChance", 10, new ConfigDescription("Chance from 0 to 100 in % per landing for a hazard event (see Events). Ignored while Preset is not Custom.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); events = BindLogged("5. Events", "Events", "Minefield,TurretNest,QuietDay", new ConfigDescription("Comma-separated list of events that can happen. Minefield: many more landmines, no turrets or spike traps. TurretNest: a group of turrets in front of the main entrance. QuietDay: no hazards outside at all.", (AcceptableValueBase)null, Array.Empty<object>())); announceEvents = BindLogged("5. Events", "AnnounceEvents", defaultValue: true, new ConfigDescription("Whether to announce events in the chat. Every player sees it, even without the mod.", (AcceptableValueBase)null, Array.Empty<object>())); fireExitGuardsEnabled = BindLogged("6. Guarded fire exits", "Enabled", defaultValue: true, new ConfigDescription("Whether fire exits can get turrets outside that aim at the door. Works even if turrets are disabled in 2. Turret. Ignored while Preset is not Custom.", (AcceptableValueBase)null, Array.Empty<object>())); guardChancePerExit = BindLogged("6. Guarded fire exits", "ChancePerExit", 35, new ConfigDescription("Chance from 0 to 100 in % for each fire exit to be guarded. Ignored while Preset is not Custom.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); turretsPerExit = BindLogged("6. Guarded fire exits", "TurretsPerExit", 1, new ConfigDescription("Turrets placed at a guarded fire exit. Ignored while Preset is not Custom.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 3), Array.Empty<object>())); scalingMode = BindLogged("7. Scaling", "Mode", ScalingMode.Quotas, new ConfigDescription("Spawn more hazards outside as the run goes on. Off, Days (days spent) or Quotas (quotas met). Both reset when the crew gets fired. Ignored while Preset is not Custom.", (AcceptableValueBase)null, Array.Empty<object>())); scalingPercentPerStep = BindLogged("7. Scaling", "PercentPerStep", 10, new ConfigDescription("Extra hazards in % per day or quota, applied to min and max. Ignored while Preset is not Custom.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); scalingMaxMultiplier = BindLogged("7. Scaling", "MaxMultiplier", 2f, new ConfigDescription("Upper limit for the scaling, e.g. 2 means at most twice as many hazards. Ignored while Preset is not Custom.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>())); } public List<HazardEvent> GetEnabledEvents() { HashSet<string> names = new HashSet<string>(from name in events.Value.Split(',') select name.Trim() into name where name.Length > 0 select name, StringComparer.OrdinalIgnoreCase); return (from HazardEvent hazardEvent in Enum.GetValues(typeof(HazardEvent)) where hazardEvent != HazardEvent.None && names.Contains(hazardEvent.ToString()) select hazardEvent).ToList(); } public HazardConfiguration GetHazardConfig(HazardDefinition hazard) { if (hazard.Type == HazardType.Modded) { return GetOrBindModdedHazardConfig(hazard.Name); } HazardConfiguration hazardConfiguration = hazardConfigMap[hazard.Type]; PresetValues activePreset = ActivePreset; if (activePreset == null || !activePreset.Hazards.TryGetValue(hazard.Type, out var value)) { return hazardConfiguration; } return new HazardConfiguration(value.Enabled, value.MinSpawnRate, value.MaxSpawnRate, hazardConfiguration.MoonMap, hazardConfiguration.SpawnStrategy); } public HazardConfiguration GetOrBindModdedHazardConfig(string hazardName) { if (moddedHazardConfigMap.TryGetValue(hazardName, out var value)) { return value; } string text = LCUtils.SanitizeConfigName(hazardName); value = BindHazardConfig("the modded hazard " + hazardName, "4. Modded - " + text, "EnableOutside", "MinSpawnRate", "MaxSpawnRate", "Moons", "SpawnStrategy", defaultEnable: false, 0, 3, coveredByPreset: false); moddedHazardConfigMap[hazardName] = value; Plugin.GetLogger().LogInfo((object)("Registered config for modded hazard " + hazardName + ".")); return value; } private HazardConfiguration BindHazardConfig(string hazardDisplayName, string category, string enableKey, string minRateKey, string maxRateKey, string moonKey, string strategyKey, bool defaultEnable, int defaultMinRate, int defaultMaxRate, bool coveredByPreset = true) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown string text = (coveredByPreset ? " Ignored while Preset is not Custom." : ""); ConfigEntry<bool> enable = config.Bind<bool>(category, enableKey, defaultEnable, "Whether or not to spawn " + hazardDisplayName + " outside." + text); ConfigEntry<int> minRate = config.Bind<int>(category, minRateKey, defaultMinRate, new ConfigDescription("Minimum amount to spawn outside." + text, (AcceptableValueBase)(object)spawnRateRange, Array.Empty<object>())); ConfigEntry<int> maxRate = config.Bind<int>(category, maxRateKey, defaultMaxRate, new ConfigDescription("Maximum amount to spawn outside." + text, (AcceptableValueBase)(object)spawnRateRange, Array.Empty<object>())); ConfigEntry<string> moonString = config.Bind<string>(category, moonKey, "", "Per-moon min/max for " + hazardDisplayName + ", overriding the values above. Format: moon:min:max separated by commas, e.g. experimentation:5:10,titan:0:0"); ConfigEntry<string> strategyString = config.Bind<string>(category, strategyKey, SpawnStrategyType.MainAndFireExit.ToString(), spawnStrategyDescription); HazardConfiguration hazardConfig = new HazardConfiguration(enable.Value, minRate.Value, maxRate.Value, LCUtils.ParseMoonString(moonString.Value), LCUtils.GetSpawnStrategy(strategyString.Value)); enable.SettingChanged += delegate { hazardConfig.Enabled = enable.Value; Plugin.GetLogger().LogInfo((object)$"{category} {enableKey} updated: {enable.Value}"); }; minRate.SettingChanged += delegate { hazardConfig.MinSpawnRate = minRate.Value; Plugin.GetLogger().LogInfo((object)$"{category} {minRateKey} updated: {minRate.Value}"); }; maxRate.SettingChanged += delegate { hazardConfig.MaxSpawnRate = maxRate.Value; Plugin.GetLogger().LogInfo((object)$"{category} {maxRateKey} updated: {maxRate.Value}"); }; moonString.SettingChanged += delegate { hazardConfig.MoonMap = LCUtils.ParseMoonString(moonString.Value); Plugin.GetLogger().LogInfo((object)(category + " " + moonKey + " updated: " + moonString.Value)); }; strategyString.SettingChanged += delegate { hazardConfig.SpawnStrategy = LCUtils.GetSpawnStrategy(strategyString.Value); Plugin.GetLogger().LogInfo((object)(category + " " + strategyKey + " updated: " + strategyString.Value)); }; return hazardConfig; } private ConfigEntry<T> BindLogged<T>(string category, string key, T defaultValue, ConfigDescription description) { ConfigEntry<T> entry = config.Bind<T>(category, key, defaultValue, description); entry.SettingChanged += delegate { Plugin.GetLogger().LogInfo((object)$"{category} {key} updated: {entry.Value}"); }; return entry; } } internal static class Presets { private static readonly Dictionary<Preset, PresetValues> PRESET_MAP = new Dictionary<Preset, PresetValues> { { Preset.Chill, new PresetValues(new Dictionary<HazardType, PresetHazard> { { HazardType.Landmine, new PresetHazard(enabled: true, 3, 8) }, { HazardType.Turret, new PresetHazard(enabled: false, 0, 0) }, { HazardType.SpikeRoofTrap, new PresetHazard(enabled: true, 0, 1) } }, 0, fireExitGuardsEnabled: false, 0, 1, ScalingMode.Off, 0, 1f) }, { Preset.Classic, new PresetValues(new Dictionary<HazardType, PresetHazard> { { HazardType.Landmine, new PresetHazard(enabled: true, 15, 30) }, { HazardType.Turret, new PresetHazard(enabled: false, 0, 1) }, { HazardType.SpikeRoofTrap, new PresetHazard(enabled: true, 0, 2) } }, 10, fireExitGuardsEnabled: true, 35, 1, ScalingMode.Quotas, 10, 2f) }, { Preset.Minefield, new PresetValues(new Dictionary<HazardType, PresetHazard> { { HazardType.Landmine, new PresetHazard(enabled: true, 30, 50) }, { HazardType.Turret, new PresetHazard(enabled: true, 0, 1) }, { HazardType.SpikeRoofTrap, new PresetHazard(enabled: true, 2, 4) } }, 15, fireExitGuardsEnabled: true, 35, 1, ScalingMode.Quotas, 15, 2.5f) }, { Preset.Warzone, new PresetValues(new Dictionary<HazardType, PresetHazard> { { HazardType.Landmine, new PresetHazard(enabled: true, 20, 35) }, { HazardType.Turret, new PresetHazard(enabled: true, 3, 6) }, { HazardType.SpikeRoofTrap, new PresetHazard(enabled: true, 3, 6) } }, 25, fireExitGuardsEnabled: true, 75, 2, ScalingMode.Quotas, 15, 3f) } }; public static PresetValues Get(Preset preset) { PresetValues value; return PRESET_MAP.TryGetValue(preset, out value) ? value : null; } } } namespace LCHazardsOutside.Abstract { internal abstract class AbstractCompatibilityHandler { protected abstract void DoApply(); protected abstract string GetModGUID(); private bool IsEnabled() { return Chainloader.PluginInfos.ContainsKey(GetModGUID()); } public void Apply() { if (IsEnabled()) { try { DoApply(); } catch (Exception arg) { Plugin.GetLogger().LogError((object)$"There was an error in patching {GetModGUID()}. Skipping... \n {arg}\n"); } } } protected void LogApply() { Plugin.GetLogger().LogInfo((object)("Applying compatibility fixes for " + GetModGUID() + ".")); } protected Assembly GetTargetAssembly(string assemblyName) { return AccessTools.AllAssemblies().FirstOrDefault((Assembly assembly) => assembly.GetName().Name.Equals(assemblyName, StringComparison.OrdinalIgnoreCase)); } } public abstract class SpawnStrategy { public abstract List<SpawnPositionData> CalculateCenterPositions(SpawnContext context, float spawnRadiusMultiplier); protected SpawnPositionData CalculateCenterWithSpawnRadius(Vector3 shipLandPosition, Vector3 targetPosition, float spawnRadiusMultiplier) { //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_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_0014: 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) //IL_0035: Unknown result type (might be due to invalid IL or missing references) Vector3 val = (shipLandPosition + targetPosition) / 2f; float spawnRadius = Vector3.Distance(targetPosition, val) * spawnRadiusMultiplier; val.y = Mathf.Max(shipLandPosition.y, targetPosition.y); return new SpawnPositionData(val, spawnRadius); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }