Decompiled source of Loot Topup v1.2.3

LootTopup.dll

Decompiled 2 weeks ago
using 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.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using REPOLib.Modules;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("LootTopup")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("LootTopup")]
[assembly: AssemblyTitle("LootTopup")]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace LootTopup
{
	[BepInPlugin("themorningstar.loottopup", "Loot Topup", "1.2.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal struct SpawnSpot
		{
			public Vector3 position;

			public Quaternion rotation;

			public Type type;
		}

		internal struct TemplateInfo
		{
			public GameObject prefab;

			public string resourceId;

			public PrefabRef repoLibRef;

			public float value;

			public Type volumeType;
		}

		public const string Guid = "themorningstar.loottopup";

		internal static ManualLogSource Log = null;

		internal static ConfigEntry<float> TargetMultiplier;

		internal static ConfigEntry<int> MinValuables;

		internal static ConfigEntry<bool> WatchdogEnabled;

		internal static ConfigEntry<float> WatchdogInterval;

		internal static ConfigEntry<bool> RespectHuntingSeason;

		internal static ConfigEntry<string> SkipMutatorNames;

		internal static ConfigEntry<int> MaxSpawnsPerLevel;

		internal static bool ToppedUpThisLevel;

		internal static int SpawnedThisLevel;

		internal static readonly List<TemplateInfo> Templates = new List<TemplateInfo>();

		internal static bool Busy;

		internal static readonly HashSet<string> SpawnBlacklist = new HashSet<string>();

		internal static readonly List<SpawnSpot> Spots = new List<SpawnSpot>();

		internal static List<TemplateInfo> PresetTemplates;

		internal static bool WarnedNoTemplates;

		internal static bool WarnedNoSpots;

		private void Awake()
		{
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			TargetMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Topup", "TargetMultiplier", 1.3f, "Top up until achievable value is at least haulGoal * this. 1.0 = exactly completable; 1.3 = 30% buffer.");
			MinValuables = ((BaseUnityPlugin)this).Config.Bind<int>("Topup", "MinValuables", 8, "Guarantee at least this many valuables on the map at level start (anti-fragility for sparse maps). 0 disables.");
			WatchdogEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Watchdog", "Enabled", true, "Detect mid-level softlocks (too much value destroyed to finish) and top up so the run stays winnable.");
			WatchdogInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Watchdog", "IntervalSeconds", 4f, "How often the watchdog re-checks completability during a level.");
			RespectHuntingSeason = ((BaseUnityPlugin)this).Config.Bind<bool>("Mutators", "RespectNoLootMutators", true, "Skip all topup when a mutator that intentionally removes loot (e.g. Hunting Season) is active.");
			SkipMutatorNames = ((BaseUnityPlugin)this).Config.Bind<string>("Mutators", "SkipMutatorNames", "Hunting Season", "Comma-separated mutator display names during which topup is disabled.");
			MaxSpawnsPerLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Topup", "MaxSpawnsPerLevel", 60, "Hard cap on how many valuables this mod will spawn in a single level (runaway guard). Failed spawns also count toward this cap.");
			try
			{
				new Harmony("themorningstar.loottopup").PatchAll();
				Log.LogInfo((object)"LootTopup: armed (min-count floor + mid-level softlock watchdog; respects no-loot mutators).");
			}
			catch (Exception ex)
			{
				Log.LogError((object)("LootTopup: patch failed: " + ex));
			}
		}
	}
	[HarmonyPatch(typeof(LevelGenerator), "Start")]
	internal static class ResetGuardPatch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			Plugin.ToppedUpThisLevel = false;
			Plugin.SpawnedThisLevel = 0;
			Plugin.Templates.Clear();
			Plugin.SpawnBlacklist.Clear();
			Plugin.Spots.Clear();
			Plugin.PresetTemplates = null;
			Plugin.WarnedNoTemplates = false;
			Plugin.WarnedNoSpots = false;
			Plugin.Busy = false;
		}
	}
	[HarmonyPatch(typeof(ValuableVolume), "Setup")]
	internal static class CaptureSpotsPatch
	{
		[HarmonyPrefix]
		private static void Prefix(ValuableVolume __instance)
		{
			//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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (!((Object)(object)__instance == (Object)null) && ((Behaviour)__instance).isActiveAndEnabled)
			{
				Plugin.Spots.Add(new Plugin.SpawnSpot
				{
					position = ((Component)__instance).transform.position,
					rotation = ((Component)__instance).transform.rotation,
					type = __instance.VolumeType
				});
			}
		}
	}
	[HarmonyPatch(typeof(ValuablePropSwitch), "Setup")]
	internal static class DropPropSpotsPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ValuablePropSwitch __instance)
		{
			//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)
			if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.ValuableParent == (Object)null || __instance.ValuableParent.activeSelf)
			{
				return;
			}
			ValuableVolume componentInChildren = ((Component)__instance).GetComponentInChildren<ValuableVolume>(true);
			if (!((Object)(object)componentInChildren == (Object)null))
			{
				Vector3 p = ((Component)componentInChildren).transform.position;
				Plugin.Spots.RemoveAll(delegate(Plugin.SpawnSpot s)
				{
					//IL_0001: 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_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)
					Vector3 val = s.position - p;
					return ((Vector3)(ref val)).sqrMagnitude < 0.01f;
				});
			}
		}
	}
	[HarmonyPatch(typeof(RoundDirector), "StartRoundLogic")]
	internal static class StartPatch
	{
		[HarmonyPostfix]
		private static void Postfix(RoundDirector __instance)
		{
			if (!Plugin.ToppedUpThisLevel && SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.RunIsLevel())
			{
				Plugin.ToppedUpThisLevel = true;
				((MonoBehaviour)__instance).StartCoroutine(Driver(__instance));
			}
		}

		private static IEnumerator Driver(RoundDirector rd)
		{
			yield return (object)new WaitForSeconds(2.5f);
			TopupLogic.CaptureTemplates();
			TopupLogic.Evaluate(rd, "level start");
			if (!Plugin.WatchdogEnabled.Value)
			{
				yield break;
			}
			WaitForSeconds wait = new WaitForSeconds(Mathf.Max(1f, Plugin.WatchdogInterval.Value));
			while ((Object)(object)rd != (Object)null && SemiFunc.RunIsLevel())
			{
				yield return wait;
				if ((Object)(object)rd == (Object)null || !SemiFunc.RunIsLevel())
				{
					break;
				}
				TopupLogic.Evaluate(rd, "watchdog");
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabObjectImpactDetector), "BreakRPC")]
	internal static class BreakTriggerPatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			if (Plugin.WatchdogEnabled.Value && SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.RunIsLevel())
			{
				RoundDirector instance = RoundDirector.instance;
				if ((Object)(object)instance != (Object)null)
				{
					TopupLogic.Evaluate(instance, "item damaged");
				}
			}
		}
	}
	internal static class TopupLogic
	{
		private static Type _mutatorManagerType;

		private static bool _mutatorLookupDone;

		private const float SpotClearRadius = 1f;

		private static IEnumerable<ValuableObject> LiveValuables()
		{
			ValuableDirector instance = ValuableDirector.instance;
			if ((Object)(object)instance != (Object)null && instance.valuableList != null)
			{
				return instance.valuableList;
			}
			return Object.FindObjectsOfType<ValuableObject>();
		}

		public static void CaptureTemplates()
		{
			Plugin.Templates.Clear();
			foreach (ValuableObject item in LiveValuables())
			{
				if (!((Object)(object)item == (Object)null))
				{
					GameObject gameObject = ((Component)item).gameObject;
					if (!((Object)(object)gameObject == (Object)null))
					{
						Plugin.Templates.Add(MakeTemplate(gameObject, item.dollarValueCurrent));
					}
				}
			}
		}

		private static Plugin.TemplateInfo MakeTemplate(GameObject go, float value)
		{
			//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)
			string text = "Valuables/" + ((Object)go).name.Replace("(Clone)", "").Trim();
			PrefabRef repoLibRef = default(PrefabRef);
			NetworkPrefabs.TryGetNetworkPrefabRef(text, ref repoLibRef);
			ValuableObject component = go.GetComponent<ValuableObject>();
			return new Plugin.TemplateInfo
			{
				prefab = go,
				resourceId = text,
				repoLibRef = repoLibRef,
				value = value,
				volumeType = (Type)((!((Object)(object)component != (Object)null)) ? 2 : ((int)component.volumeType))
			};
		}

		private static List<Plugin.TemplateInfo> PresetTemplates()
		{
			List<Plugin.TemplateInfo> list = FromPresets(((Object)(object)LevelGenerator.Instance != (Object)null && (Object)(object)LevelGenerator.Instance.Level != (Object)null) ? LevelGenerator.Instance.Level.ValuablePresets : null);
			string arg = "this level's presets";
			if (list.Count == 0 && (Object)(object)RunManager.instance != (Object)null && RunManager.instance.levels != null)
			{
				list = FromPresets(RunManager.instance.levels.Where((Level l) => (Object)(object)l != (Object)null && l.ValuablePresets != null).SelectMany((Level l) => l.ValuablePresets));
				arg = "all run levels' presets";
			}
			list = (from t in list
				group t by t.resourceId into g
				select g.First()).ToList();
			Plugin.Log.LogInfo((object)$"LootTopup: no live valuables to copy; using {list.Count} valuable prefab(s) from {arg}.");
			return list;
		}

		private static List<Plugin.TemplateInfo> FromPresets(IEnumerable<LevelValuables> presets)
		{
			List<Plugin.TemplateInfo> result = new List<Plugin.TemplateInfo>();
			if (presets == null)
			{
				return result;
			}
			foreach (LevelValuables preset in presets)
			{
				if (!((Object)(object)preset == (Object)null))
				{
					Add(result, preset.tiny, (Type)0);
					Add(result, preset.small, (Type)1);
					Add(result, preset.medium, (Type)2);
					Add(result, preset.big, (Type)3);
					Add(result, preset.wide, (Type)4);
					Add(result, preset.tall, (Type)5);
					Add(result, preset.veryTall, (Type)6);
				}
			}
			return result;
		}

		private static void Add(List<Plugin.TemplateInfo> result, List<PrefabRef> refs, Type type)
		{
			//IL_0071: 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)
			if (refs == null)
			{
				return;
			}
			foreach (PrefabRef @ref in refs)
			{
				if (@ref != null && ((PrefabRef<GameObject>)(object)@ref).IsValid() && !string.IsNullOrEmpty(((PrefabRef<GameObject>)(object)@ref).ResourcePath))
				{
					GameObject prefab = ((PrefabRef<GameObject>)(object)@ref).Prefab;
					if (!((Object)(object)prefab == (Object)null))
					{
						result.Add(new Plugin.TemplateInfo
						{
							prefab = prefab,
							resourceId = ((PrefabRef<GameObject>)(object)@ref).ResourcePath,
							repoLibRef = null,
							value = 0f,
							volumeType = type
						});
					}
				}
			}
		}

		private static bool SpotTaken(Vector3 spot, List<Vector3> reserved, List<ValuableObject> live)
		{
			//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_0017: 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_0054: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			float num = 1f;
			Vector3 val;
			for (int i = 0; i < reserved.Count; i++)
			{
				val = reserved[i] - spot;
				if (((Vector3)(ref val)).sqrMagnitude < num)
				{
					return true;
				}
			}
			for (int j = 0; j < live.Count; j++)
			{
				ValuableObject val2 = live[j];
				if (!((Object)(object)val2 == (Object)null))
				{
					val = ((Component)val2).transform.position - spot;
					if (((Vector3)(ref val)).sqrMagnitude < num)
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool TryPickSpot(Type preferred, List<Vector3> reserved, List<ValuableObject> live, out Vector3 pos, out Quaternion rot)
		{
			//IL_0001: 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_000e: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected I4, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: 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_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_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: 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)
			pos = default(Vector3);
			rot = Quaternion.identity;
			if (Plugin.Spots.Count == 0)
			{
				return false;
			}
			List<Plugin.SpawnSpot> list = new List<Plugin.SpawnSpot>();
			int num = int.MaxValue;
			for (int i = 0; i < Plugin.Spots.Count; i++)
			{
				Plugin.SpawnSpot item = Plugin.Spots[i];
				bool flag = SpotTaken(item.position, reserved, live);
				int num2 = item.type - preferred;
				int num3 = ((flag || num2 != 0) ? ((!flag && num2 > 0) ? 1 : ((flag && num2 == 0) ? 2 : (flag ? 4 : 3))) : 0);
				if (num3 < num)
				{
					num = num3;
					list.Clear();
					list.Add(item);
				}
				else if (num3 == num)
				{
					list.Add(item);
				}
			}
			Plugin.SpawnSpot spawnSpot = list[Random.Range(0, list.Count)];
			pos = spawnSpot.position;
			rot = spawnSpot.rotation;
			if (num >= 2 && SpotTaken(spawnSpot.position, reserved, live))
			{
				pos += Vector3.up * 0.7f;
			}
			return true;
		}

		private static GameObject TrySpawn(Plugin.TemplateInfo tmpl, bool mp, Vector3 pos, Quaternion rot)
		{
			//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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (!mp)
			{
				return Object.Instantiate<GameObject>(tmpl.prefab, pos, rot);
			}
			if (tmpl.repoLibRef != null)
			{
				return NetworkPrefabs.SpawnNetworkPrefab(tmpl.repoLibRef, pos, rot, (byte)0, (object[])null);
			}
			return PhotonNetwork.InstantiateRoomObject(tmpl.resourceId, pos, rot, (byte)0, (object[])null);
		}

		public static void Evaluate(RoundDirector rd, string reason)
		{
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03df: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.Busy || (Object)(object)rd == (Object)null)
			{
				return;
			}
			int haulGoal = rd.haulGoal;
			if (haulGoal <= 0 || Plugin.SpawnedThisLevel >= Plugin.MaxSpawnsPerLevel.Value || (Plugin.RespectHuntingSeason.Value && NoLootMutatorActive()))
			{
				return;
			}
			List<ValuableObject> list = (from v in LiveValuables()
				where (Object)(object)v != (Object)null
				select v).ToList();
			int count = list.Count;
			float num = 0f;
			for (int num2 = 0; num2 < list.Count; num2++)
			{
				num += list[num2].dollarValueCurrent;
			}
			int num3 = Mathf.Max(1, rd.extractionPoints);
			float num4 = (float)haulGoal / (float)num3;
			float num5 = (float)rd.extractionPointsCompleted * num4;
			float num6 = num + num5;
			float num7 = (float)haulGoal * Plugin.TargetMultiplier.Value;
			int value = Plugin.MinValuables.Value;
			bool num8 = num6 < num7;
			bool flag = count < value;
			if (!num8 && !flag)
			{
				return;
			}
			List<Plugin.TemplateInfo> source = ((Plugin.Templates.Count > 0) ? Plugin.Templates : list.Select((ValuableObject v) => MakeTemplate(((Component)v).gameObject, v.dollarValueCurrent)).ToList());
			source = source.Where((Plugin.TemplateInfo t) => (Object)(object)t.prefab != (Object)null).ToList();
			if (source.Count == 0)
			{
				if (Plugin.PresetTemplates == null)
				{
					Plugin.PresetTemplates = PresetTemplates();
				}
				source = Plugin.PresetTemplates;
			}
			if (source.Count == 0)
			{
				if (!Plugin.WarnedNoTemplates)
				{
					Plugin.WarnedNoTemplates = true;
					Plugin.Log.LogWarning((object)$"LootTopup ({reason}): level short (goal={haulGoal}, achievable={num6:0}, items={count}) but no templates to spawn from.");
				}
				return;
			}
			float avgVal = source.Average((Plugin.TemplateInfo t) => t.value);
			List<Plugin.TemplateInfo> list2 = source.Where((Plugin.TemplateInfo t) => t.value <= avgVal).ToList();
			if (list2.Count == 0)
			{
				list2 = source;
			}
			if (Plugin.Spots.Count == 0)
			{
				if (!Plugin.WarnedNoSpots)
				{
					Plugin.WarnedNoSpots = true;
					Plugin.Log.LogWarning((object)$"LootTopup ({reason}): level short (goal={haulGoal}, achievable={num6:0}, items={count}) but no valuable spawn points were recorded.");
				}
				return;
			}
			bool mp = SemiFunc.IsMultiplayer();
			Plugin.Busy = true;
			int num9 = 0;
			int num10 = 0;
			int num11 = 0;
			List<Vector3> list3 = new List<Vector3>();
			Plugin.Log.LogInfo((object)$"LootTopup ({reason}): topping up. goal={haulGoal} achievable={num6:0} (target {num7:0}), items={count} (min {value}), spawn points={Plugin.Spots.Count}.");
			try
			{
				while ((num6 < num7 || count + num9 < value) && num11 < 500 && Plugin.SpawnedThisLevel + num10 < Plugin.MaxSpawnsPerLevel.Value)
				{
					num11++;
					List<Plugin.TemplateInfo> list4 = ((num6 < num7) ? source : list2).Where((Plugin.TemplateInfo x) => !Plugin.SpawnBlacklist.Contains(x.resourceId)).ToList();
					if (list4.Count == 0)
					{
						Plugin.Log.LogWarning((object)("LootTopup (" + reason + "): all viable templates are blacklisted; stopping topup."));
						break;
					}
					Plugin.TemplateInfo tmpl = list4[Random.Range(0, list4.Count)];
					if ((Object)(object)tmpl.prefab == (Object)null)
					{
						continue;
					}
					if (!TryPickSpot(tmpl.volumeType, list3, list, out var pos, out var rot))
					{
						Plugin.Log.LogWarning((object)("LootTopup (" + reason + "): no valuable spawn point left to place a copy."));
						break;
					}
					list3.Add(pos);
					GameObject val;
					try
					{
						val = TrySpawn(tmpl, mp, pos, rot);
					}
					catch (Exception ex)
					{
						if (Plugin.SpawnBlacklist.Add(tmpl.resourceId))
						{
							Plugin.Log.LogWarning((object)("LootTopup: spawn exception for '" + tmpl.resourceId + "' (" + ex.Message + "); blacklisting for this level."));
						}
						num10++;
						continue;
					}
					if ((Object)(object)val == (Object)null)
					{
						if (Plugin.SpawnBlacklist.Add(tmpl.resourceId))
						{
							Plugin.Log.LogWarning((object)("LootTopup: spawn returned null for '" + tmpl.resourceId + "'; blacklisting for this level."));
						}
						num10++;
						continue;
					}
					ValuableObject component = val.GetComponent<ValuableObject>();
					if (!((Object)(object)component == (Object)null))
					{
						try
						{
							component.DollarValueSetLogic();
						}
						catch
						{
						}
						num6 += component.dollarValueCurrent;
						num9++;
						num10++;
					}
				}
			}
			finally
			{
				Plugin.Busy = false;
			}
			Plugin.SpawnedThisLevel += num10;
			int num12 = num10 - num9;
			string text = ((num12 > 0) ? $" ({num12} failed/blacklisted)" : "");
			Plugin.Log.LogInfo((object)$"LootTopup ({reason}): spawned {num9} valuable(s){text}; achievable now ~{num6:0} vs goal {haulGoal}, level total spawned {Plugin.SpawnedThisLevel}.");
		}

		private static bool NoLootMutatorActive()
		{
			try
			{
				string[] array = (from s in (Plugin.SkipMutatorNames.Value ?? "").Split(',')
					select s.Trim() into s
					where s.Length > 0
					select s).ToArray();
				if (array.Length == 0)
				{
					return false;
				}
				if (!_mutatorLookupDone)
				{
					_mutatorLookupDone = true;
					_mutatorManagerType = AppDomain.CurrentDomain.GetAssemblies().SelectMany(delegate(Assembly a)
					{
						try
						{
							return a.GetTypes();
						}
						catch
						{
							return Array.Empty<Type>();
						}
					}).FirstOrDefault((Type t) => t.Name == "MutatorManager");
				}
				if (_mutatorManagerType == null)
				{
					return false;
				}
				object obj = (_mutatorManagerType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public) ?? _mutatorManagerType.GetProperty("instance", BindingFlags.Static | BindingFlags.Public))?.GetValue(null);
				if (obj == null)
				{
					return false;
				}
				if (!(obj.GetType().GetProperty("RegisteredMutators")?.GetValue(obj) is IEnumerable enumerable))
				{
					return false;
				}
				foreach (object item in enumerable)
				{
					object obj2 = item.GetType().GetProperty("Value")?.GetValue(item);
					if (obj2 == null)
					{
						continue;
					}
					PropertyInfo property = obj2.GetType().GetProperty("Active");
					if (property == null)
					{
						continue;
					}
					object value = property.GetValue(obj2);
					if (value is bool && (bool)value)
					{
						string mname = (obj2.GetType().GetProperty("MutatorName")?.GetValue(obj2) as string) ?? "";
						if (array.Any((string s) => string.Equals(s, mname, StringComparison.OrdinalIgnoreCase)))
						{
							Plugin.Log.LogInfo((object)("LootTopup: '" + mname + "' mutator active - skipping topup (intentional no-loot)."));
							return true;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("LootTopup: mutator check failed (proceeding): " + ex.Message));
			}
			return false;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		internal IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}