Decompiled source of EnemyDrops v2.1.1

EnemyDrops.dll

Decompiled 2 days 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 System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EnemyDrops.Configuration;
using EnemyDrops.Drops;
using EnemyDrops.Reflection;
using EnemyDrops.Tracking;
using EnemyDrops.Visuals;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using RepoAPI.Game;
using RepoAPI.Items;
using UnityEngine;
using UnityEngine.Events;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("Osmar Briones")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.1.1.0")]
[assembly: AssemblyInformationalVersion("2.1.1+ddc01d5ba362671fb32eea4d8a58f01ec37af9e2")]
[assembly: AssemblyProduct("EnemyDrops")]
[assembly: AssemblyTitle("EnemyDrops")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.1.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public static class GameKeyEnumExtensions
{
	public static string GetGameKey<T>(this T value) where T : Enum
	{
		return typeof(T).GetMember(value.ToString()).First().GetCustomAttribute<GameKeyAttribute>()?.Key ?? value.ToString();
	}

	public static bool TryFromGameKey<T>(string key, out T result) where T : Enum
	{
		foreach (T item in Enum.GetValues(typeof(T)).Cast<T>())
		{
			if (item.GetGameKey().Equals(key, StringComparison.OrdinalIgnoreCase))
			{
				result = item;
				return true;
			}
		}
		result = default(T);
		return false;
	}

	public static string[] GetAllGameKeys<T>() where T : Enum
	{
		return (from T v in Enum.GetValues(typeof(T))
			select v.GetGameKey()).ToArray();
	}

	public static T FromGameKey<T>(string key) where T : Enum
	{
		if (TryFromGameKey<T>(key, out var result))
		{
			return result;
		}
		throw new ArgumentException("Invalid game key '" + key + "' for enum " + typeof(T).Name);
	}
}
namespace RepoAPI.Game
{
	[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
	public sealed class GameKeyAttribute(string key) : Attribute()
	{
		public string Key { get; } = key;
	}
}
namespace RepoAPI.Items
{
	public static class ItemProvider
	{
		private static readonly Random s_rng = new Random();

		public static bool TrySpawnRandomItem(Vector3 position, Quaternion rotation, out GameObject? spawned, float upwardOffset = 0.15f)
		{
			//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)
			spawned = null;
			string randomKey = ItemKeysProvider.GetRandomKey();
			if (string.IsNullOrEmpty(randomKey))
			{
				return false;
			}
			return TrySpawnByKey(randomKey, position, rotation, out spawned, upwardOffset);
		}

		public static bool TrySpawn(ItemName itemName, Vector3 position, Quaternion rotation, out GameObject? spawned, float upwardOffset = 0.15f)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return TrySpawnByKey(itemName.GetGameKey(), position, rotation, out spawned, upwardOffset);
		}

		public static bool TrySpawnByKey(string key, Vector3 position, Quaternion rotation, out GameObject? spawned, float upwardOffset = 0.15f)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			spawned = null;
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return false;
			}
			StatsManager instance = StatsManager.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			Dictionary<string, Item> itemDictionary = instance.itemDictionary;
			if (itemDictionary == null || !itemDictionary.TryGetValue(key, out var value) || (Object)(object)value == (Object)null || value.prefab == null)
			{
				return false;
			}
			Vector3 val = position + Vector3.up * upwardOffset;
			try
			{
				if (SemiFunc.IsMultiplayer())
				{
					spawned = PhotonNetwork.InstantiateRoomObject(((PrefabRef<GameObject>)(object)value.prefab).ResourcePath, val, rotation, (byte)0, (object[])null);
				}
				else
				{
					spawned = Object.Instantiate<GameObject>(((PrefabRef<GameObject>)(object)value.prefab).Prefab, val, rotation);
				}
			}
			catch (Exception)
			{
				return false;
			}
			ApplySpawnImpulse(spawned);
			return true;
		}

		public static bool TrySpawnWeightedItem(IReadOnlyList<WeightedKey> weights, Vector3 position, Quaternion rotation, out GameObject? spawned, float upwardOffset = 0.15f, float dropChance = 1f)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			spawned = null;
			if (!EvaluateDropChance(dropChance))
			{
				return false;
			}
			string text = ItemKeysProvider.PickWeightedKey(weights, s_rng);
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			return TrySpawnByKey(text, position, rotation, out spawned, upwardOffset);
		}

		public static bool TrySpawnWeightedItem(IEnumerable<WeightedKey> weights, Vector3 position, Quaternion rotation, out GameObject? spawned, float upwardOffset = 0.15f, float dropChance = 1f)
		{
			//IL_001e: 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_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)
			if (weights is IReadOnlyList<WeightedKey> weights2)
			{
				return TrySpawnWeightedItem(weights2, position, rotation, out spawned, upwardOffset, dropChance);
			}
			return TrySpawnWeightedItem(weights.ToList(), position, rotation, out spawned, upwardOffset, dropChance);
		}

		public static bool TrySpawnWeightedItem(ItemKeysProvider provider, Vector3 position, Quaternion rotation, out GameObject? spawned, float upwardOffset = 0.15f, float dropChance = 1f)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			spawned = null;
			if (provider == null)
			{
				return false;
			}
			if (!EvaluateDropChance(dropChance))
			{
				return false;
			}
			try
			{
				return TrySpawn(provider.GetWeightedRandomKey(), position, rotation, out spawned, upwardOffset);
			}
			catch (InvalidOperationException)
			{
				return false;
			}
		}

		public static bool TrySpawnWeightedItem(Dictionary<ItemName, float> weights, Vector3 position, Quaternion rotation, out GameObject? spawned, float upwardOffset = 0.15f, float dropChance = 1f)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return TrySpawnWeightedItem(new ItemKeysProvider(weights), position, rotation, out spawned, upwardOffset, dropChance);
		}

		public static bool TrySpawnWeightedItem(Dictionary<string, float> weights, Vector3 position, Quaternion rotation, out GameObject? spawned, float upwardOffset = 0.15f, float dropChance = 1f)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			spawned = null;
			if (weights == null || weights.Count == 0)
			{
				return false;
			}
			if (!EvaluateDropChance(dropChance))
			{
				return false;
			}
			string text = ItemKeysProvider.PickWeightedKey(weights, s_rng);
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			return TrySpawnByKey(text, position, rotation, out spawned, upwardOffset);
		}

		private static bool EvaluateDropChance(float dropChance)
		{
			if (dropChance <= 0f)
			{
				return false;
			}
			if (dropChance >= 1f)
			{
				return true;
			}
			double num;
			lock (s_rng)
			{
				num = s_rng.NextDouble();
			}
			return num <= (double)dropChance;
		}

		private static void ApplySpawnImpulse(GameObject? go)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody val = default(Rigidbody);
			if (go != null && Object.op_Implicit((Object)(object)go) && go.TryGetComponent<Rigidbody>(ref val))
			{
				val.AddForce(Random.insideUnitSphere * 1.25f + Vector3.up * 2f, (ForceMode)1);
			}
		}
	}
	public class ItemKeysProvider
	{
		private class WeightedKeySelector
		{
			private readonly List<(ItemName key, float threshold)> cumulativeWeights;

			private readonly float totalWeight;

			public Dictionary<ItemName, float> Weights { get; }

			public WeightedKeySelector(Dictionary<ItemName, float>? weights)
			{
				Weights = weights ?? new Dictionary<ItemName, float>();
				cumulativeWeights = new List<(ItemName, float)>(Weights.Count);
				float num = 0f;
				foreach (KeyValuePair<ItemName, float> item in Weights.OrderBy((KeyValuePair<ItemName, float> x) => x.Key))
				{
					if (!(item.Value <= 0f))
					{
						num += item.Value;
						cumulativeWeights.Add((item.Key, num));
					}
				}
				totalWeight = num;
			}

			public ItemName GetRandomKey(Random rng)
			{
				if (cumulativeWeights.Count == 0)
				{
					throw new InvalidOperationException("ItemKeysProvider weights have not been set.");
				}
				if (cumulativeWeights.Count == 1)
				{
					return cumulativeWeights[0].key;
				}
				float value = (float)(rng.NextDouble() * (double)totalWeight);
				int index = BinarySearchThreshold(value);
				return cumulativeWeights[index].key;
			}

			private int BinarySearchThreshold(float value)
			{
				int num = 0;
				int num2 = cumulativeWeights.Count - 1;
				while (num < num2)
				{
					int num3 = num + (num2 - num) / 2;
					if (value < cumulativeWeights[num3].threshold)
					{
						num2 = num3;
					}
					else
					{
						num = num3 + 1;
					}
				}
				return num;
			}
		}

		private static readonly Random random = new Random();

		public static string[] AllKeys = GameKeyEnumExtensions.GetAllGameKeys<ItemName>();

		private WeightedKeySelector selector = new WeightedKeySelector(weights);

		public ItemKeysProvider(Dictionary<ItemName, float>? weights)
		{
		}

		public ItemKeysProvider(IEnumerable<WeightedKey>? weightedKeys)
			: this(FromWeightedKeys(weightedKeys))
		{
		}

		private static Dictionary<ItemName, float>? FromWeightedKeys(IEnumerable<WeightedKey>? weightedKeys)
		{
			if (weightedKeys == null)
			{
				return null;
			}
			Dictionary<ItemName, float> dictionary = new Dictionary<ItemName, float>();
			foreach (WeightedKey weightedKey in weightedKeys)
			{
				if (weightedKey != null && GameKeyEnumExtensions.TryFromGameKey<ItemName>(weightedKey.Key, out var result))
				{
					dictionary[result] = weightedKey.Weight;
				}
			}
			return dictionary;
		}

		public Dictionary<ItemName, float> GetWeights()
		{
			return new Dictionary<ItemName, float>(selector.Weights);
		}

		public void SetWeights(Dictionary<ItemName, float>? weights)
		{
			selector = new WeightedKeySelector(weights);
		}

		public void SetWeight(ItemName itemName, float weight)
		{
			Dictionary<ItemName, float> dictionary = new Dictionary<ItemName, float>(selector.Weights);
			dictionary[itemName] = weight;
			selector = new WeightedKeySelector(dictionary);
		}

		public bool RemoveWeight(ItemName itemName)
		{
			Dictionary<ItemName, float> dictionary = new Dictionary<ItemName, float>(selector.Weights);
			if (!dictionary.Remove(itemName))
			{
				return false;
			}
			selector = new WeightedKeySelector(dictionary);
			return true;
		}

		public static string? GetRandomKey()
		{
			if (AllKeys.Length == 0)
			{
				return null;
			}
			int num;
			lock (random)
			{
				num = random.Next(AllKeys.Length);
			}
			return AllKeys[num];
		}

		public ItemName GetWeightedRandomKey()
		{
			lock (random)
			{
				return selector.GetRandomKey(random);
			}
		}

		public string GetWeightedRandomGameKey()
		{
			return GetWeightedRandomKey().GetGameKey();
		}

		public static string? PickWeightedKey(IReadOnlyList<WeightedKey>? weights, Random? rng = null)
		{
			if (weights == null || weights.Count == 0)
			{
				return null;
			}
			float num = 0f;
			for (int i = 0; i < weights.Count; i++)
			{
				WeightedKey weightedKey = weights[i];
				if (weightedKey != null && weightedKey.Weight > 0f)
				{
					num += weightedKey.Weight;
				}
			}
			if (num <= 0f)
			{
				return null;
			}
			double num2;
			if (rng != null)
			{
				num2 = rng.NextDouble() * (double)num;
			}
			else
			{
				lock (random)
				{
					num2 = random.NextDouble() * (double)num;
				}
			}
			float num3 = 0f;
			for (int j = 0; j < weights.Count; j++)
			{
				WeightedKey weightedKey2 = weights[j];
				if (weightedKey2 != null && !(weightedKey2.Weight <= 0f))
				{
					num3 += weightedKey2.Weight;
					if (num2 <= (double)num3)
					{
						return weightedKey2.Key;
					}
				}
			}
			for (int num4 = weights.Count - 1; num4 >= 0; num4--)
			{
				WeightedKey weightedKey3 = weights[num4];
				if (weightedKey3 != null && weightedKey3.Weight > 0f)
				{
					return weightedKey3.Key;
				}
			}
			return null;
		}

		public static string? PickWeightedKey(IEnumerable<WeightedKey>? weights, Random? rng = null)
		{
			if (weights == null)
			{
				return null;
			}
			if (weights is IReadOnlyList<WeightedKey> weights2)
			{
				return PickWeightedKey(weights2, rng);
			}
			return PickWeightedKey(weights.ToList(), rng);
		}

		public static string? PickWeightedKey(IDictionary<string, float>? weights, Random? rng = null)
		{
			if (weights == null || weights.Count == 0)
			{
				return null;
			}
			List<WeightedKey> list = new List<WeightedKey>(weights.Count);
			foreach (KeyValuePair<string, float> weight in weights)
			{
				list.Add(new WeightedKey(weight.Key, weight.Value));
			}
			return PickWeightedKey(list, rng);
		}
	}
	public enum ItemName
	{
		[GameKey("Item Cart Cannon")]
		CartCannon,
		[GameKey("Item Cart Laser")]
		CartLaser,
		[GameKey("Item Cart Medium")]
		CartMedium,
		[GameKey("Item Cart Small")]
		CartSmall,
		[GameKey("Item Drone Battery")]
		DroneBattery,
		[GameKey("Item Drone Feather")]
		DroneFeather,
		[GameKey("Item Drone Indestructible")]
		DroneIndestructible,
		[GameKey("Item Drone Torque")]
		DroneTorque,
		[GameKey("Item Drone Zero Gravity")]
		DroneZeroGravity,
		[GameKey("Item Duck Bucket")]
		DuckBucket,
		[GameKey("Item Extraction Tracker")]
		ExtractionTracker,
		[GameKey("Item Grenade Duct Taped")]
		GrenadeDuctTaped,
		[GameKey("Item Grenade Explosive")]
		GrenadeExplosive,
		[GameKey("Item Grenade Human")]
		GrenadeHuman,
		[GameKey("Item Grenade Shockwave")]
		GrenadeShockwave,
		[GameKey("Item Grenade Stun")]
		GrenadeStun,
		[GameKey("Item Gun Handgun")]
		GunHandgun,
		[GameKey("Item Gun Laser")]
		GunLaser,
		[GameKey("Item Gun Shockwave")]
		GunShockwave,
		[GameKey("Item Gun Shotgun")]
		GunShotgun,
		[GameKey("Item Gun Stun")]
		GunStun,
		[GameKey("Item Gun Tranq")]
		GunTranq,
		[GameKey("Item Health Pack Large")]
		HealthPackLarge,
		[GameKey("Item Health Pack Medium")]
		HealthPackMedium,
		[GameKey("Item Health Pack Small")]
		HealthPackSmall,
		[GameKey("Item Melee Baseball Bat")]
		MeleeBaseballBat,
		[GameKey("Item Melee Frying Pan")]
		MeleeFryingPan,
		[GameKey("Item Melee Inflatable Hammer")]
		MeleeInflatableHammer,
		[GameKey("Item Melee Sledge Hammer")]
		MeleeSledgeHammer,
		[GameKey("Item Melee Stun Baton")]
		MeleeStunBaton,
		[GameKey("Item Melee Sword")]
		MeleeSword,
		[GameKey("Item Mine Explosive")]
		MineExplosive,
		[GameKey("Item Mine Shockwave")]
		MineShockwave,
		[GameKey("Item Mine Stun")]
		MineStun,
		[GameKey("Item Orb Zero Gravity")]
		OrbZeroGravity,
		[GameKey("Item Phase Bridge")]
		PhaseBridge,
		[GameKey("Item Leaf Blower")]
		LeafBlower,
		[GameKey("Item Power Crystal")]
		PowerCrystal,
		[GameKey("Item ReviveItem")]
		ReviveItem,
		[GameKey("Item Rubber Duck")]
		RubberDuck,
		[GameKey("Item Staff Torque")]
		StaffTorque,
		[GameKey("Item Staff Void")]
		StaffVoid,
		[GameKey("Item Staff Zero Gravity")]
		StaffZeroGravity,
		[GameKey("Item Vehicle Semiscooter")]
		VehicleSemiscooter,
		[GameKey("Item Vehicle Semiscooter Small")]
		VehicleSemiscooterSmall,
		[GameKey("Item WalkieTalkieBox")]
		WalkieTalkieBox,
		[GameKey("Item Upgrade Death Head Battery")]
		UpgradeDeathHeadBattery,
		[GameKey("Item Upgrade Map Player Count")]
		UpgradeMapPlayerCount,
		[GameKey("Item Upgrade Player Crouch Rest")]
		UpgradePlayerCrouchRest,
		[GameKey("Item Upgrade Player Energy")]
		UpgradePlayerEnergy,
		[GameKey("Item Upgrade Player Extra Jump")]
		UpgradePlayerExtraJump,
		[GameKey("Item Upgrade Player Grab Range")]
		UpgradePlayerGrabRange,
		[GameKey("Item Upgrade Player Grab Strength")]
		UpgradePlayerGrabStrength,
		[GameKey("Item Upgrade Player Health")]
		UpgradePlayerHealth,
		[GameKey("Item Upgrade Player Sprint Speed")]
		UpgradePlayerSprintSpeed,
		[GameKey("Item Upgrade Player Tumble Climb")]
		UpgradePlayerTumbleClimb,
		[GameKey("Item Upgrade Player Tumble Launch")]
		UpgradePlayerTumbleLaunch,
		[GameKey("Item Upgrade Player Tumble Wings")]
		UpgradePlayerTumbleWings,
		[GameKey("Item Valuable Tracker")]
		ValuableTracker
	}
	public static class ItemPreservation
	{
		public static bool IsItemSecured(ItemAttributes? itemAttr)
		{
			//IL_00eb: 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)
			if ((Object)(object)itemAttr == (Object)null)
			{
				return false;
			}
			RoomVolumeCheck component = ((Component)itemAttr).GetComponent<RoomVolumeCheck>();
			if ((Object)(object)component != (Object)null && component.inTruck)
			{
				return true;
			}
			ItemEquippable component2 = ((Component)itemAttr).GetComponent<ItemEquippable>();
			if ((Object)(object)component2 != (Object)null && (component2.IsEquipped() || component2.isEquipped))
			{
				return true;
			}
			PhysGrabObject component3 = ((Component)itemAttr).GetComponent<PhysGrabObject>();
			if ((Object)(object)component3 != (Object)null && (component3.grabbed || component3.grabbedLocal || (component3.playerGrabbing != null && component3.playerGrabbing.Count > 0)))
			{
				return true;
			}
			if (!string.IsNullOrEmpty(itemAttr.instanceName))
			{
				int hashCode = itemAttr.instanceName.GetHashCode();
				StatsManager instance = StatsManager.instance;
				if ((Object)(object)instance != (Object)null && (instance.playerInventorySpot1.ContainsValue(hashCode) || instance.playerInventorySpot2.ContainsValue(hashCode) || instance.playerInventorySpot3.ContainsValue(hashCode)))
				{
					return true;
				}
			}
			if ((Object)(object)TruckSafetySpawnPoint.instance != (Object)null && Vector3.Distance(((Component)itemAttr).transform.position, ((Component)TruckSafetySpawnPoint.instance).transform.position) <= 8f)
			{
				return true;
			}
			return false;
		}

		public static bool TryPreserveSecuredItem(ItemAttributes? itemAttr, out string baseItemName)
		{
			baseItemName = string.Empty;
			if ((Object)(object)itemAttr == (Object)null)
			{
				return false;
			}
			StatsManager instance = StatsManager.instance;
			if ((Object)(object)instance == (Object)null || instance.itemDictionary == null || instance.itemsPurchased == null || instance.itemsPurchasedTotal == null)
			{
				return false;
			}
			string instanceName = itemAttr.instanceName;
			baseItemName = (((Object)(object)itemAttr.item != (Object)null) ? ((Object)itemAttr.item).name : (instanceName.Contains("/") ? instanceName.Split(new char[1] { '/' })[0] : instanceName));
			if (string.IsNullOrEmpty(baseItemName) || !instance.itemDictionary.ContainsKey(baseItemName))
			{
				return false;
			}
			int value;
			int num = (instance.itemsPurchased.TryGetValue(baseItemName, out value) ? value : 0);
			instance.itemsPurchased[baseItemName] = num + 1;
			int value2;
			int num2 = (instance.itemsPurchasedTotal.TryGetValue(baseItemName, out value2) ? value2 : 0);
			instance.itemsPurchasedTotal[baseItemName] = num2 + 1;
			return true;
		}

		public static void CleanupUnpreservedInstance(string instanceName)
		{
			if (string.IsNullOrEmpty(instanceName))
			{
				return;
			}
			StatsManager instance = StatsManager.instance;
			if (!((Object)(object)instance == (Object)null))
			{
				if (instance.item != null && instance.item.ContainsKey(instanceName))
				{
					instance.item.Remove(instanceName);
				}
				if (instance.itemStatBattery != null && instance.itemStatBattery.ContainsKey(instanceName))
				{
					instance.itemStatBattery.Remove(instanceName);
				}
			}
		}

		public static Dictionary<string, int>? GetOrCreateStatsDictionary(string dictionaryKey)
		{
			if (string.IsNullOrEmpty(dictionaryKey))
			{
				throw new ArgumentNullException("dictionaryKey");
			}
			StatsManager instance = StatsManager.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			if (!instance.dictionaryOfDictionaries.TryGetValue(dictionaryKey, out var value))
			{
				value = new Dictionary<string, int>();
				instance.dictionaryOfDictionaries[dictionaryKey] = value;
			}
			return value;
		}

		public static int GetTotalCount(string dictionaryKey)
		{
			Dictionary<string, int> orCreateStatsDictionary = GetOrCreateStatsDictionary(dictionaryKey);
			if (orCreateStatsDictionary == null)
			{
				return 0;
			}
			int num = 0;
			foreach (KeyValuePair<string, int> item in orCreateStatsDictionary)
			{
				if (item.Value > 0)
				{
					num += item.Value;
				}
			}
			return num;
		}

		public static void RecordCount(string dictionaryKey, string baseItemName)
		{
			if (!string.IsNullOrEmpty(baseItemName))
			{
				Dictionary<string, int> orCreateStatsDictionary = GetOrCreateStatsDictionary(dictionaryKey);
				if (orCreateStatsDictionary != null)
				{
					orCreateStatsDictionary[baseItemName] = ((!orCreateStatsDictionary.TryGetValue(baseItemName, out var value)) ? 1 : (value + 1));
				}
			}
		}

		public static bool DecrementCount(string dictionaryKey, string instanceName, out string baseItemName, out int remaining)
		{
			baseItemName = string.Empty;
			remaining = 0;
			if (string.IsNullOrEmpty(instanceName))
			{
				return false;
			}
			baseItemName = (instanceName.Contains("/") ? instanceName.Split(new char[1] { '/' })[0] : instanceName);
			Dictionary<string, int> orCreateStatsDictionary = GetOrCreateStatsDictionary(dictionaryKey);
			if (orCreateStatsDictionary == null)
			{
				return false;
			}
			if (orCreateStatsDictionary.TryGetValue(baseItemName, out var value) && value > 0)
			{
				remaining = value - 1;
				orCreateStatsDictionary[baseItemName] = remaining;
				return true;
			}
			return false;
		}

		public static void ResetCounts(string dictionaryKey)
		{
			Dictionary<string, int> orCreateStatsDictionary = GetOrCreateStatsDictionary(dictionaryKey);
			if (orCreateStatsDictionary != null && orCreateStatsDictionary.Count > 0)
			{
				orCreateStatsDictionary.Clear();
			}
		}
	}
	public sealed class WeightedKey
	{
		public string Key { get; }

		public float Weight { get; }

		public WeightedKey(string key, float weight)
		{
			Key = key ?? throw new ArgumentNullException("key");
			Weight = weight;
		}

		public WeightedKey(ItemName itemName, float weight)
			: this(itemName.GetGameKey(), weight)
		{
		}

		public void Deconstruct(out string key, out float weight)
		{
			key = Key;
			weight = Weight;
		}
	}
}
namespace EnemyDrops
{
	[BepInPlugin("osmarbriones.EnemyDrops", "EnemyDrops", "2.1.1")]
	public class EnemyDropsPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "osmarbriones.EnemyDrops";

		public const string PluginName = "EnemyDrops";

		public const string PluginVersion = "2.1.1";

		internal static EnemyDropsPlugin Instance { get; private set; }

		internal static ManualLogSource Logger { get; private set; }

		internal Harmony? Harmony { get; private set; }

		private void Awake()
		{
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			ConfigurationController.Initialize(((BaseUnityPlugin)this).Config, Logger);
			Patch();
			Logger.LogInfo((object)"EnemyDrops v2.1.1 loaded!");
		}

		internal void Patch()
		{
			//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_0015: Expected O, but got Unknown
			//IL_001a: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony val = new Harmony("osmarbriones.EnemyDrops");
				Harmony val2 = val;
				Harmony = val;
			}
			Harmony.PatchAll();
		}

		internal void Unpatch()
		{
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}
namespace EnemyDrops.Visuals
{
	internal sealed class EnemyDropVisuals : MonoBehaviour
	{
		private static readonly Color FaintRedLow = new Color(0.9f, 0.12f, 0.12f);

		private static readonly Color FaintRedHigh = new Color(1f, 0.28f, 0.28f);

		private GameObject? auraLightObject;

		private Light? auraLight;

		private PhysGrabObject? physGrabObject;

		private ItemEquippable? itemEquippable;

		private bool visualsApplied;

		private IEnumerator Start()
		{
			physGrabObject = ((Component)this).GetComponent<PhysGrabObject>() ?? ((Component)this).GetComponentInParent<PhysGrabObject>();
			itemEquippable = ((Component)this).GetComponent<ItemEquippable>() ?? ((Component)this).GetComponentInParent<ItemEquippable>();
			ApplyVisuals();
			yield return null;
			ApplyVisuals();
		}

		internal void ApplyVisuals()
		{
			if (ConfigurationController.EnableColorModification)
			{
				ApplyMaterialColorModification();
			}
			if (ConfigurationController.EnableDropAura)
			{
				SetupAuraLight();
			}
			else if ((Object)(object)auraLight != (Object)null && ((Behaviour)auraLight).enabled)
			{
				((Behaviour)auraLight).enabled = false;
			}
			visualsApplied = true;
		}

		private void ApplyMaterialColorModification()
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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_00e0: 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_0118: 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_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: 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_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			float colorMultiplierR = ConfigurationController.ColorMultiplierR;
			float colorMultiplierG = ConfigurationController.ColorMultiplierG;
			float colorMultiplierB = ConfigurationController.ColorMultiplierB;
			float colorAdd = ConfigurationController.ColorAdd;
			Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true);
			int num = 0;
			Color val4 = default(Color);
			Color val5 = default(Color);
			foreach (Renderer val in componentsInChildren)
			{
				if (!Object.op_Implicit((Object)(object)val) || (!(val is MeshRenderer) && !(val is SkinnedMeshRenderer)))
				{
					continue;
				}
				Material[] materials = val.materials;
				bool flag = false;
				foreach (Material val2 in materials)
				{
					if (Object.op_Implicit((Object)(object)val2))
					{
						Color val3 = (val2.HasProperty("_Color") ? val2.GetColor("_Color") : val2.color);
						((Color)(ref val4))..ctor(Mathf.Clamp01(val3.r * colorMultiplierR + colorAdd), Mathf.Clamp01(val3.g * colorMultiplierG + colorAdd), Mathf.Clamp01(val3.b * colorMultiplierB + colorAdd), val3.a);
						val2.color = val4;
						if (val2.HasProperty("_Color"))
						{
							val2.SetColor("_Color", val4);
						}
						if (val2.HasProperty("_BaseColor"))
						{
							val2.SetColor("_BaseColor", val4);
						}
						if (val2.HasProperty("_EmissionColor"))
						{
							Color color = val2.GetColor("_EmissionColor");
							((Color)(ref val5))..ctor(Mathf.Clamp01(color.r * colorMultiplierR), Mathf.Clamp01(color.g * colorMultiplierG), Mathf.Clamp01(color.b * colorMultiplierB), color.a);
							val2.SetColor("_EmissionColor", val5);
						}
						flag = true;
					}
				}
				if (flag)
				{
					val.materials = materials;
					num++;
				}
			}
			if (!visualsApplied)
			{
				EnemyDropsPlugin.Logger.LogInfo((object)$"EnemyDropVisuals: Applied material color modification (mult=[{colorMultiplierR:F2},{colorMultiplierG:F2},{colorMultiplierB:F2}], add={colorAdd:F2}) to {num} renderer(s) on '{((Object)((Component)this).gameObject).name}'.");
			}
		}

		private void SetupAuraLight()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: 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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)auraLight != (Object)null)
			{
				return;
			}
			ItemLight componentInChildren = ((Component)this).GetComponentInChildren<ItemLight>();
			if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.itemLight != (Object)null)
			{
				((Behaviour)componentInChildren.itemLight).enabled = false;
			}
			auraLightObject = new GameObject("EnemyDrop_AuraLight");
			auraLightObject.transform.SetParent(((Component)this).transform, false);
			Vector3 val = Vector3.zero;
			Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true);
			bool flag = false;
			Bounds val2 = default(Bounds);
			foreach (Renderer val3 in componentsInChildren)
			{
				if (val3 is MeshRenderer || val3 is SkinnedMeshRenderer)
				{
					if (!flag)
					{
						val2 = val3.bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref val2)).Encapsulate(val3.bounds);
					}
				}
			}
			if (flag)
			{
				val = ((Component)this).transform.InverseTransformPoint(((Bounds)(ref val2)).center);
			}
			auraLightObject.transform.localPosition = val;
			auraLight = auraLightObject.AddComponent<Light>();
			auraLight.type = (LightType)2;
			auraLight.color = FaintRedHigh;
			auraLight.range = ConfigurationController.AuraRange;
			auraLight.intensity = ConfigurationController.AuraIntensity;
			auraLight.shadows = (LightShadows)0;
			auraLight.renderMode = (LightRenderMode)1;
			auraLight.cullingMask = -1;
			((Behaviour)auraLight).enabled = true;
			EnemyDropsPlugin.Logger.LogInfo((object)$"EnemyDropVisuals: Attached centered aura light at local offset {val} on '{((Object)((Component)this).gameObject).name}'.");
		}

		private void Update()
		{
			//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_00b4: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)auraLight == (Object)null) && ConfigurationController.EnableDropAura)
			{
				bool num = (Object)(object)physGrabObject != (Object)null && (physGrabObject.grabbed || physGrabObject.grabbedLocal);
				bool flag = (Object)(object)itemEquippable != (Object)null && itemEquippable.IsEquipped();
				bool flag2 = !num && !flag;
				if (((Behaviour)auraLight).enabled != flag2)
				{
					((Behaviour)auraLight).enabled = flag2;
				}
				if (flag2)
				{
					float num2 = (Mathf.Sin(Time.time * 2.5f) + 1f) * 0.5f;
					auraLight.color = Color.Lerp(FaintRedLow, FaintRedHigh, num2);
					auraLight.intensity = ConfigurationController.AuraIntensity * (0.85f + 0.3f * num2);
					auraLight.range = ConfigurationController.AuraRange;
				}
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)auraLightObject != (Object)null)
			{
				Object.Destroy((Object)(object)auraLightObject);
			}
		}
	}
}
namespace EnemyDrops.Tracking
{
	internal static class DroppedInstanceTracker
	{
		private static readonly HashSet<string> droppedInstances = new HashSet<string>();

		internal static void MarkDropped(GameObject go)
		{
			if (Object.op_Implicit((Object)(object)go))
			{
				if (!Object.op_Implicit((Object)(object)go.GetComponent<DroppedItemTag>()))
				{
					go.AddComponent<DroppedItemTag>();
				}
				if (!Object.op_Implicit((Object)(object)go.GetComponent<EnemyDropVisuals>()))
				{
					go.AddComponent<EnemyDropVisuals>();
				}
			}
		}

		internal static void RegisterInstance(string instanceName)
		{
			if (!string.IsNullOrEmpty(instanceName) && droppedInstances.Add(instanceName))
			{
				EnemyDropsPlugin.Logger.LogDebug((object)("EnemyDrops: Registered dropped instance '" + instanceName + "'."));
			}
		}

		internal static bool IsDropped(string instanceName)
		{
			if (!string.IsNullOrEmpty(instanceName))
			{
				return droppedInstances.Contains(instanceName);
			}
			return false;
		}

		internal static bool IsItemSecured(ItemAttributes itemAttr)
		{
			return ItemPreservation.IsItemSecured(itemAttr);
		}

		internal static void ProcessSceneSwitch(bool gameOver, bool leaveGame)
		{
			if (gameOver || leaveGame)
			{
				if (gameOver)
				{
					PreservedItemTracker.Reset();
				}
				ClearForNewLevel();
				return;
			}
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				ClearForNewLevel();
				return;
			}
			StatsManager instance = StatsManager.instance;
			if ((Object)(object)instance == (Object)null || instance.item == null || instance.itemStatBattery == null || instance.itemsPurchased == null)
			{
				EnemyDropsPlugin.Logger.LogWarning((object)"EnemyDrops: StatsManager tables are null; cannot process scene switch.");
				ClearForNewLevel();
				return;
			}
			bool preserveItemsBetweenLevels = ConfigurationController.PreserveItemsBetweenLevels;
			int maxPreservedItems = ConfigurationController.MaxPreservedItems;
			int num = PreservedItemTracker.GetTotalPreservedCount();
			DroppedItemTag[] array = Object.FindObjectsOfType<DroppedItemTag>();
			HashSet<string> hashSet = new HashSet<string>();
			if (preserveItemsBetweenLevels && array != null)
			{
				foreach (DroppedItemTag droppedItemTag in array)
				{
					if (!Object.op_Implicit((Object)(object)droppedItemTag))
					{
						continue;
					}
					ItemAttributes component = ((Component)droppedItemTag).GetComponent<ItemAttributes>();
					if (!Object.op_Implicit((Object)(object)component) || !IsItemSecured(component))
					{
						continue;
					}
					string instanceName = component.instanceName;
					string baseItemName = (((Object)(object)component.item != (Object)null) ? ((Object)component.item).name : (instanceName.Contains("/") ? instanceName.Split(new char[1] { '/' })[0] : instanceName));
					if (num >= maxPreservedItems)
					{
						EnemyDropsPlugin.Logger.LogInfo((object)$"EnemyDrops: Item '{baseItemName}' ({instanceName}) is secured, but MaxPreservedItems limit ({maxPreservedItems}) has been reached. Item will not persist.");
					}
					else if (ItemPreservation.TryPreserveSecuredItem(component, out baseItemName))
					{
						PreservedItemTracker.RecordPreservedItem(baseItemName);
						num++;
						if (!string.IsNullOrEmpty(instanceName))
						{
							hashSet.Add(instanceName);
						}
						EnemyDropsPlugin.Logger.LogInfo((object)$"EnemyDrops: Preserved item '{baseItemName}' ({instanceName}) into truck/next level. Total preserved: {num}/{maxPreservedItems}");
					}
				}
			}
			List<string> list = new List<string>(droppedInstances);
			List<string> list2 = new List<string>();
			for (int j = 0; j < list.Count; j++)
			{
				string text = list[j];
				if (!string.IsNullOrEmpty(text) && !hashSet.Contains(text))
				{
					ItemPreservation.CleanupUnpreservedInstance(text);
					list2.Add(text);
				}
			}
			if (list2.Count > 0)
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine($"EnemyDrops: Cleaned up {list2.Count} non-preserved dropped instance(s) from item + itemStatBattery:");
				for (int k = 0; k < list2.Count; k++)
				{
					stringBuilder.AppendLine("  " + list2[k]);
				}
				EnemyDropsPlugin.Logger.LogDebug((object)stringBuilder.ToString());
			}
			ClearForNewLevel();
		}

		internal static void ClearBatteriesForDroppedInstances()
		{
			ProcessSceneSwitch(gameOver: false, leaveGame: false);
		}

		internal static void ClearForNewLevel()
		{
			if (droppedInstances.Count > 0)
			{
				EnemyDropsPlugin.Logger.LogDebug((object)$"EnemyDrops: Clearing dropped-instance tracker ({droppedInstances.Count} entries).");
			}
			droppedInstances.Clear();
		}
	}
	internal sealed class DroppedItemTag : MonoBehaviour
	{
	}
	internal static class PreservedItemTracker
	{
		private const string PreservedDictionaryKey = "enemyDropsPreserved";

		internal static Dictionary<string, int>? GetDictionary()
		{
			return ItemPreservation.GetOrCreateStatsDictionary("enemyDropsPreserved");
		}

		internal static int GetTotalPreservedCount()
		{
			return ItemPreservation.GetTotalCount("enemyDropsPreserved");
		}

		internal static void RecordPreservedItem(string baseItemName)
		{
			ItemPreservation.RecordCount("enemyDropsPreserved", baseItemName);
		}

		internal static void OnItemRemoved(string instanceName)
		{
			if (ItemPreservation.DecrementCount("enemyDropsPreserved", instanceName, out string baseItemName, out int remaining))
			{
				EnemyDropsPlugin.Logger.LogDebug((object)$"EnemyDrops: Decremented preserved count for '{baseItemName}' ({remaining} remaining).");
			}
		}

		internal static void Reset()
		{
			EnemyDropsPlugin.Logger.LogDebug((object)$"EnemyDrops: Resetting preserved drop count (was {GetTotalPreservedCount()}).");
			ItemPreservation.ResetCounts("enemyDropsPreserved");
		}
	}
}
namespace EnemyDrops.Reflection
{
	internal static class EnemyDifficultyAccessor
	{
		private static FieldInfo? enemyParentField;

		private static FieldInfo? difficultyField;

		private static Type? enemyType;

		private static Type? enemyParentType;

		private static bool initialized;

		private static void Init(Enemy enemy)
		{
			if (initialized || !Object.op_Implicit((Object)(object)enemy))
			{
				return;
			}
			try
			{
				enemyType = ((object)enemy).GetType();
				enemyParentField = enemyType.GetField("EnemyParent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				object obj = enemyParentField?.GetValue(enemy);
				if (obj != null)
				{
					enemyParentType = obj.GetType();
					difficultyField = enemyParentType.GetField("difficulty", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
			catch (Exception ex)
			{
				EnemyDropsPlugin.Logger.LogDebug((object)("EnemyDifficultyAccessor.Init reflection failed: " + ex.Message));
			}
			finally
			{
				initialized = true;
			}
		}

		private static object? GetDifficultyEnum(Enemy enemy)
		{
			Init(enemy);
			if (!Object.op_Implicit((Object)(object)enemy) || enemyParentField == null || difficultyField == null)
			{
				return null;
			}
			try
			{
				object value = enemyParentField.GetValue(enemy);
				return (value != null) ? difficultyField.GetValue(value) : null;
			}
			catch (Exception ex)
			{
				EnemyDropsPlugin.Logger.LogDebug((object)("EnemyDifficultyAccessor.GetDifficultyEnum failed: " + ex.Message));
				return null;
			}
		}

		public static int GetDangerLevel(Enemy enemy)
		{
			try
			{
				object difficultyEnum = GetDifficultyEnum(enemy);
				if (difficultyEnum == null)
				{
					return 1;
				}
				return (int)Convert.ChangeType(difficultyEnum, typeof(int)) + 1;
			}
			catch
			{
				return 1;
			}
		}
	}
}
namespace EnemyDrops.Patches
{
	[HarmonyPatch(typeof(EnemyDirector), "Start")]
	internal static class EnemyDirector_Start_Patch
	{
		private static void Postfix()
		{
			if (!SemiFunc.RunIsLevel())
			{
				return;
			}
			try
			{
				ConfigurationController.Reload(EnemyDropsPlugin.Logger);
				ItemDropper.ResetForNewLevel();
				DroppedInstanceTracker.ClearForNewLevel();
			}
			catch (Exception arg)
			{
				EnemyDropsPlugin.Logger.LogError((object)$"EnemyDirector_Start_Patch: Failed during level-start reload/reset: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(EnemyHealth), "Awake")]
	internal static class EnemyHealth_Awake_Patch
	{
		private static readonly ConditionalWeakTable<EnemyHealth, object> subscribed = new ConditionalWeakTable<EnemyHealth, object>();

		private static void Postfix(EnemyHealth __instance)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			if (!subscribed.TryGetValue(__instance, out object _))
			{
				subscribed.Add(__instance, new object());
				__instance.onDeath.AddListener((UnityAction)delegate
				{
					OnEnemyDeath(__instance);
				});
			}
		}

		private static void OnEnemyDeath(EnemyHealth health)
		{
			try
			{
				if (SemiFunc.IsMasterClientOrSingleplayer())
				{
					Enemy component = ((Component)health).GetComponent<Enemy>();
					GameObject spawned;
					if ((Object)(object)component == (Object)null)
					{
						EnemyDropsPlugin.Logger.LogWarning((object)"EnemyHealth_Awake_Patch: Enemy component not found on dead object.");
					}
					else if (!ItemDropper.TrySpawnForEnemy(component, out spawned))
					{
						EnemyDropsPlugin.Logger.LogDebug((object)"EnemyHealth_Awake_Patch: ItemDropper did not spawn an item for enemy.");
					}
				}
			}
			catch (Exception arg)
			{
				EnemyDropsPlugin.Logger.LogError((object)$"EnemyHealth_Awake_Patch.OnEnemyDeath failed: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(PunManager), "SetItemNameLOGIC")]
	internal static class PunManager_SetItemNameLOGIC_Patch
	{
		private static void Postfix(string _name, int photonViewID, ItemAttributes _itemAttributes)
		{
			ItemAttributes val = _itemAttributes;
			if (SemiFunc.IsMultiplayer())
			{
				PhotonView val2 = PhotonView.Find(photonViewID);
				if ((Object)(object)val2 != (Object)null)
				{
					val = ((Component)val2).GetComponent<ItemAttributes>();
				}
			}
			if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)((Component)val).GetComponent<DroppedItemTag>()))
			{
				DroppedInstanceTracker.RegisterInstance(_name);
			}
		}
	}
	[HarmonyPatch(typeof(SemiFunc), "OnSceneSwitch")]
	internal static class SemiFunc_OnSceneSwitch_Patch
	{
		private static void Prefix(bool _gameOver, bool _leaveGame)
		{
			try
			{
				DroppedInstanceTracker.ProcessSceneSwitch(_gameOver, _leaveGame);
			}
			catch (Exception arg)
			{
				EnemyDropsPlugin.Logger.LogError((object)$"SemiFunc_OnSceneSwitch_Patch: Failed to process dropped instances on scene switch: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(StatsManager), "ItemRemove")]
	internal static class StatsManager_ItemRemove_Patch
	{
		private static void Postfix(string instanceName)
		{
			try
			{
				PreservedItemTracker.OnItemRemoved(instanceName);
			}
			catch (Exception arg)
			{
				EnemyDropsPlugin.Logger.LogError((object)$"StatsManager_ItemRemove_Patch: Failed to update preserved count on ItemRemove: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(StatsManager), "RunStartStats")]
	internal static class StatsManager_RunStartStats_Patch
	{
		private static void Postfix()
		{
			try
			{
				PreservedItemTracker.Reset();
			}
			catch (Exception arg)
			{
				EnemyDropsPlugin.Logger.LogError((object)$"StatsManager_RunStartStats_Patch: Failed to reset preserved tracker on RunStartStats: {arg}");
			}
		}
	}
}
namespace EnemyDrops.Drops
{
	internal static class ItemDropper
	{
		private static int dropsThisLevel;

		private static readonly string[] excludedEnemyNames = new string[2] { "Gnome", "Banger" };

		private static FieldInfo? enemyParentField;

		private static FieldInfo? enemyNameField;

		internal static void ResetForNewLevel()
		{
			dropsThisLevel = 0;
			EnemyDropsPlugin.Logger.LogInfo((object)$"ItemDropper: Drop counter reset for new level. MaxDropsPerLevel={ConfigurationController.MaxDropsPerLevel}");
		}

		internal static bool TrySpawnForEnemy(Enemy enemy, out GameObject? spawned, float upwardOffset = 0.15f)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			spawned = null;
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return false;
			}
			if (!Object.op_Implicit((Object)(object)enemy))
			{
				EnemyDropsPlugin.Logger.LogDebug((object)"ItemDropper: Enemy null.");
				return false;
			}
			if (dropsThisLevel >= ConfigurationController.MaxDropsPerLevel)
			{
				EnemyDropsPlugin.Logger.LogInfo((object)$"ItemDropper: Max drops per level reached ({ConfigurationController.MaxDropsPerLevel}).");
				return false;
			}
			Transform obj = (Object.op_Implicit((Object)(object)enemy.CustomValuableSpawnTransform) ? enemy.CustomValuableSpawnTransform : (Object.op_Implicit((Object)(object)enemy.CenterTransform) ? enemy.CenterTransform : ((Component)enemy).transform));
			Vector3 position = obj.position + Vector3.up * upwardOffset;
			Quaternion rotation = obj.rotation;
			int dangerLevel = EnemyDifficultyAccessor.GetDangerLevel(enemy);
			string enemyNameSafe = GetEnemyNameSafe(enemy);
			EnemyDropsPlugin.Logger.LogInfo((object)$"ItemDropper: Enemy='{enemyNameSafe}' DangerLevel={dangerLevel}");
			if (IsExcludedEnemy(enemyNameSafe))
			{
				EnemyDropsPlugin.Logger.LogInfo((object)("ItemDropper: Excluding enemy '" + enemyNameSafe + "' from drops."));
				return false;
			}
			bool num = ItemProvider.TrySpawnWeightedItem(dangerLevel switch
			{
				1 => ItemDropTables.GetWeightsFor((Difficulty)0), 
				2 => ItemDropTables.GetWeightsFor((Difficulty)1), 
				3 => ItemDropTables.GetWeightsFor((Difficulty)2), 
				_ => ItemDropTables.GetWeightsFor((Difficulty)0), 
			}, position, rotation, out spawned, 0f);
			if (num)
			{
				DroppedInstanceTracker.MarkDropped(spawned);
				dropsThisLevel++;
				return num;
			}
			EnemyDropsPlugin.Logger.LogDebug((object)$"ItemDropper: TrySpawnWeightedItem returned false (dangerLevel={dangerLevel}).");
			return num;
		}

		private static bool IsExcludedEnemy(string enemyName)
		{
			if (string.IsNullOrEmpty(enemyName))
			{
				return false;
			}
			for (int i = 0; i < excludedEnemyNames.Length; i++)
			{
				if (string.Equals(enemyName, excludedEnemyNames[i], StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		private static string GetEnemyNameSafe(Enemy enemy)
		{
			try
			{
				if ((object)enemyParentField == null)
				{
					enemyParentField = typeof(Enemy).GetField("EnemyParent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				object obj = enemyParentField?.GetValue(enemy);
				if (obj != null)
				{
					if ((object)enemyNameField == null)
					{
						enemyNameField = obj.GetType().GetField("enemyName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					}
					if (enemyNameField != null)
					{
						string text = enemyNameField.GetValue(obj) as string;
						if (!string.IsNullOrEmpty(text))
						{
							return text;
						}
					}
				}
			}
			catch (Exception ex)
			{
				EnemyDropsPlugin.Logger.LogDebug((object)("ItemDropper: enemy name reflection failed: " + ex.Message));
			}
			if (!Object.op_Implicit((Object)(object)enemy))
			{
				return "Unknown";
			}
			return ((Object)((Component)enemy).gameObject).name;
		}
	}
	internal static class ItemDropTables
	{
		private static readonly IReadOnlyList<WeightedKey> commonItems = new WeightedKey[17]
		{
			new WeightedKey("Item Grenade Stun", 3f),
			new WeightedKey("Item Grenade Shockwave", 3f),
			new WeightedKey("Item Grenade Explosive", 2f),
			new WeightedKey("Item Grenade Duct Taped", 2f),
			new WeightedKey("Item Grenade Human", 2f),
			new WeightedKey("Item Mine Stun", 3f),
			new WeightedKey("Item Mine Explosive", 2f),
			new WeightedKey("Item Mine Shockwave", 3f),
			new WeightedKey("Item Health Pack Small", 3f),
			new WeightedKey("Item Drone Torque", 1f),
			new WeightedKey("Item Duck Bucket", 1f),
			new WeightedKey("Item Rubber Duck", 1f),
			new WeightedKey("Item Melee Frying Pan", 1f),
			new WeightedKey("Item Melee Inflatable Hammer", 1f),
			new WeightedKey("Item Valuable Tracker", 1f),
			new WeightedKey("Item Extraction Tracker", 1f),
			new WeightedKey("Item Leaf Blower", 1f)
		};

		private static readonly IReadOnlyList<WeightedKey> mediumItems = new WeightedKey[17]
		{
			new WeightedKey("Item Health Pack Medium", 3f),
			new WeightedKey("Item Melee Stun Baton", 2f),
			new WeightedKey("Item Melee Sword", 1f),
			new WeightedKey("Item Cart Small", 1f),
			new WeightedKey("Item Gun Handgun", 1f),
			new WeightedKey("Item Gun Tranq", 1f),
			new WeightedKey("Item Gun Stun", 1f),
			new WeightedKey("Item Gun Shockwave", 1f),
			new WeightedKey("Item Upgrade Player Tumble Climb", 1f),
			new WeightedKey("Item Upgrade Death Head Battery", 1f),
			new WeightedKey("Item Upgrade Player Energy", 1f),
			new WeightedKey("Item Phase Bridge", 1f),
			new WeightedKey("Item Vehicle Semiscooter Small", 1f),
			new WeightedKey("Item Staff Torque", 1f),
			new WeightedKey("Item Staff Void", 1f),
			new WeightedKey("Item Staff Zero Gravity", 1f),
			new WeightedKey("Item WalkieTalkieBox", 1f)
		};

		private static readonly IReadOnlyList<WeightedKey> rareItems = new WeightedKey[25]
		{
			new WeightedKey("Item Health Pack Large", 3f),
			new WeightedKey("Item Drone Feather", 2f),
			new WeightedKey("Item Drone Indestructible", 2f),
			new WeightedKey("Item Drone Battery", 1f),
			new WeightedKey("Item Drone Zero Gravity", 1f),
			new WeightedKey("Item Cart Medium", 1f),
			new WeightedKey("Item Cart Cannon", 1f),
			new WeightedKey("Item Cart Laser", 1f),
			new WeightedKey("Item Orb Zero Gravity", 1f),
			new WeightedKey("Item Gun Shotgun", 1f),
			new WeightedKey("Item Gun Laser", 1f),
			new WeightedKey("Item Melee Sledge Hammer", 1f),
			new WeightedKey("Item Melee Baseball Bat", 1f),
			new WeightedKey("Item Power Crystal", 0f),
			new WeightedKey("Item Upgrade Player Health", 1f),
			new WeightedKey("Item Upgrade Player Sprint Speed", 1f),
			new WeightedKey("Item Upgrade Player Grab Range", 1f),
			new WeightedKey("Item Upgrade Player Grab Strength", 1f),
			new WeightedKey("Item Upgrade Player Extra Jump", 1f),
			new WeightedKey("Item Upgrade Player Tumble Launch", 1f),
			new WeightedKey("Item Upgrade Player Tumble Wings", 1f),
			new WeightedKey("Item Upgrade Player Crouch Rest", 1f),
			new WeightedKey("Item Upgrade Map Player Count", 0f),
			new WeightedKey("Item Vehicle Semiscooter", 1f),
			new WeightedKey("Item ReviveItem", 1f)
		};

		private static DropTableConfigMatrix? configMatrix;

		private static IReadOnlyList<WeightedKey>? fullDefaults1;

		private static IReadOnlyList<WeightedKey>? fullDefaults2;

		private static IReadOnlyList<WeightedKey>? fullDefaults3;

		private static bool fullDefaultsBuilt;

		internal static void InitializeConfig(ConfigFile config)
		{
			configMatrix = new DropTableConfigMatrix(config, commonItems, mediumItems, rareItems);
		}

		internal static IReadOnlyList<WeightedKey> GetWeightsFor(Difficulty difficulty)
		{
			//IL_0018: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Invalid comparison between Unknown and I4
			if (configMatrix != null)
			{
				return configMatrix.Get(difficulty);
			}
			EnsureFullDefaults();
			if ((int)difficulty != 0)
			{
				if ((int)difficulty == 1)
				{
					return fullDefaults2;
				}
				return fullDefaults3;
			}
			return fullDefaults1;
		}

		private static void EnsureFullDefaults()
		{
			if (!fullDefaultsBuilt)
			{
				fullDefaults1 = BuildFullFromDefaults(commonItems);
				fullDefaults2 = BuildFullFromDefaults(mediumItems);
				fullDefaults3 = BuildFullFromDefaults(rareItems);
				fullDefaultsBuilt = true;
			}
		}

		private static IReadOnlyList<WeightedKey> BuildFullFromDefaults(IReadOnlyList<WeightedKey> defaultsForLevel)
		{
			Dictionary<string, float> dictionary = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase);
			for (int i = 0; i < defaultsForLevel.Count; i++)
			{
				dictionary[defaultsForLevel[i].Key] = defaultsForLevel[i].Weight;
			}
			WeightedKey[] array = new WeightedKey[ItemKeys.All.Length];
			for (int j = 0; j < ItemKeys.All.Length; j++)
			{
				string key = ItemKeys.All[j];
				float value;
				float weight = (dictionary.TryGetValue(key, out value) ? value : 0f);
				array[j] = new WeightedKey(key, weight);
			}
			return array;
		}

		internal static void LogWeights(ManualLogSource logger)
		{
			if (logger == null)
			{
				throw new ArgumentNullException("logger");
			}
			LogLevel("Difficulty1", (Difficulty)0);
			LogLevel("Difficulty2", (Difficulty)1);
			LogLevel("Difficulty3", (Difficulty)2);
			void LogLevel(string name, Difficulty diff)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				IReadOnlyList<WeightedKey> weightsFor = GetWeightsFor(diff);
				int num = 0;
				for (int i = 0; i < weightsFor.Count; i++)
				{
					WeightedKey weightedKey = weightsFor[i];
					if (weightedKey.Weight > 0f)
					{
						if (num == 0)
						{
							logger.LogInfo((object)("DropTable " + name + ":"));
						}
						logger.LogInfo((object)$"  {weightedKey.Key} = {weightedKey.Weight}");
						num++;
					}
				}
				if (num == 0)
				{
					logger.LogInfo((object)("DropTable " + name + ": (no non-zero entries)"));
				}
			}
		}
	}
	internal static class ItemKeys
	{
		public const string CartCannon = "Item Cart Cannon";

		public const string CartLaser = "Item Cart Laser";

		public const string CartMedium = "Item Cart Medium";

		public const string CartSmall = "Item Cart Small";

		public const string VehicleSemiscooter = "Item Vehicle Semiscooter";

		public const string VehicleSemiscooterSmall = "Item Vehicle Semiscooter Small";

		public const string DroneBattery = "Item Drone Battery";

		public const string DroneFeather = "Item Drone Feather";

		public const string DroneIndestructible = "Item Drone Indestructible";

		public const string DroneTorque = "Item Drone Torque";

		public const string DroneZeroGravity = "Item Drone Zero Gravity";

		public const string DuckBucket = "Item Duck Bucket";

		public const string ExtractionTracker = "Item Extraction Tracker";

		public const string GrenadeDuctTaped = "Item Grenade Duct Taped";

		public const string GrenadeExplosive = "Item Grenade Explosive";

		public const string GrenadeHuman = "Item Grenade Human";

		public const string GrenadeShockwave = "Item Grenade Shockwave";

		public const string GrenadeStun = "Item Grenade Stun";

		public const string GunHandgun = "Item Gun Handgun";

		public const string GunLaser = "Item Gun Laser";

		public const string GunShockwave = "Item Gun Shockwave";

		public const string GunShotgun = "Item Gun Shotgun";

		public const string GunStun = "Item Gun Stun";

		public const string GunTranq = "Item Gun Tranq";

		public const string HealthPackLarge = "Item Health Pack Large";

		public const string HealthPackMedium = "Item Health Pack Medium";

		public const string HealthPackSmall = "Item Health Pack Small";

		public const string MeleeBaseballBat = "Item Melee Baseball Bat";

		public const string MeleeFryingPan = "Item Melee Frying Pan";

		public const string MeleeInflatableHammer = "Item Melee Inflatable Hammer";

		public const string MeleeSledgeHammer = "Item Melee Sledge Hammer";

		public const string MeleeStunBaton = "Item Melee Stun Baton";

		public const string MeleeSword = "Item Melee Sword";

		public const string StaffTorque = "Item Staff Torque";

		public const string StaffVoid = "Item Staff Void";

		public const string StaffZeroGravity = "Item Staff Zero Gravity";

		public const string MineExplosive = "Item Mine Explosive";

		public const string MineShockwave = "Item Mine Shockwave";

		public const string MineStun = "Item Mine Stun";

		public const string OrbZeroGravity = "Item Orb Zero Gravity";

		public const string PhaseBridge = "Item Phase Bridge";

		public const string PowerCrystal = "Item Power Crystal";

		public const string RubberDuck = "Item Rubber Duck";

		public const string ReviveItem = "Item ReviveItem";

		public const string LeafBlower = "Item Leaf Blower";

		public const string WalkieTalkieBox = "Item WalkieTalkieBox";

		public const string UpgradeDeathHeadBattery = "Item Upgrade Death Head Battery";

		public const string UpgradeMapPlayerCount = "Item Upgrade Map Player Count";

		public const string UpgradePlayerCrouchRest = "Item Upgrade Player Crouch Rest";

		public const string UpgradePlayerEnergy = "Item Upgrade Player Energy";

		public const string UpgradePlayerExtraJump = "Item Upgrade Player Extra Jump";

		public const string UpgradePlayerGrabRange = "Item Upgrade Player Grab Range";

		public const string UpgradePlayerGrabStrength = "Item Upgrade Player Grab Strength";

		public const string UpgradePlayerHealth = "Item Upgrade Player Health";

		public const string UpgradePlayerSprintSpeed = "Item Upgrade Player Sprint Speed";

		public const string UpgradePlayerTumbleClimb = "Item Upgrade Player Tumble Climb";

		public const string UpgradePlayerTumbleLaunch = "Item Upgrade Player Tumble Launch";

		public const string UpgradePlayerTumbleWings = "Item Upgrade Player Tumble Wings";

		public const string ValuableTracker = "Item Valuable Tracker";

		public static readonly string[] All = new string[59]
		{
			"Item Cart Cannon", "Item Cart Laser", "Item Cart Medium", "Item Cart Small", "Item Vehicle Semiscooter", "Item Vehicle Semiscooter Small", "Item Drone Battery", "Item Drone Feather", "Item Drone Indestructible", "Item Drone Torque",
			"Item Drone Zero Gravity", "Item Duck Bucket", "Item Extraction Tracker", "Item Grenade Duct Taped", "Item Grenade Explosive", "Item Grenade Human", "Item Grenade Shockwave", "Item Grenade Stun", "Item Gun Handgun", "Item Gun Laser",
			"Item Gun Shockwave", "Item Gun Shotgun", "Item Gun Stun", "Item Gun Tranq", "Item Health Pack Large", "Item Health Pack Medium", "Item Health Pack Small", "Item Melee Baseball Bat", "Item Melee Frying Pan", "Item Melee Inflatable Hammer",
			"Item Melee Sledge Hammer", "Item Melee Stun Baton", "Item Melee Sword", "Item Staff Torque", "Item Staff Void", "Item Staff Zero Gravity", "Item Mine Explosive", "Item Mine Shockwave", "Item Mine Stun", "Item Orb Zero Gravity",
			"Item Phase Bridge", "Item Power Crystal", "Item Rubber Duck", "Item ReviveItem", "Item Leaf Blower", "Item WalkieTalkieBox", "Item Upgrade Death Head Battery", "Item Upgrade Map Player Count", "Item Upgrade Player Crouch Rest", "Item Upgrade Player Energy",
			"Item Upgrade Player Extra Jump", "Item Upgrade Player Grab Range", "Item Upgrade Player Grab Strength", "Item Upgrade Player Health", "Item Upgrade Player Sprint Speed", "Item Upgrade Player Tumble Climb", "Item Upgrade Player Tumble Launch", "Item Upgrade Player Tumble Wings", "Item Valuable Tracker"
		};
	}
}
namespace EnemyDrops.Configuration
{
	internal static class ConfigurationController
	{
		private static ConfigFile? configFile;

		private static ConfigEntry<int>? maxDropsPerLevelEntry;

		private static ConfigEntry<bool>? preserveItemsBetweenLevelsEntry;

		private static ConfigEntry<int>? maxPreservedItemsEntry;

		private static ConfigEntry<bool>? enableColorModificationEntry;

		private static ConfigEntry<float>? colorMultiplierREntry;

		private static ConfigEntry<float>? colorMultiplierGEntry;

		private static ConfigEntry<float>? colorMultiplierBEntry;

		private static ConfigEntry<float>? colorAddEntry;

		private static ConfigEntry<bool>? enableDropAuraEntry;

		private static ConfigEntry<float>? auraIntensityEntry;

		private static ConfigEntry<float>? auraRangeEntry;

		internal static int MaxDropsPerLevel => maxDropsPerLevelEntry?.Value ?? 200;

		internal static bool PreserveItemsBetweenLevels => preserveItemsBetweenLevelsEntry?.Value ?? false;

		internal static int MaxPreservedItems => maxPreservedItemsEntry?.Value ?? 10;

		internal static bool EnableColorModification => enableColorModificationEntry?.Value ?? false;

		internal static float ColorMultiplierR => colorMultiplierREntry?.Value ?? 0.55f;

		internal static float ColorMultiplierG => colorMultiplierGEntry?.Value ?? 0.55f;

		internal static float ColorMultiplierB => colorMultiplierBEntry?.Value ?? 0.55f;

		internal static float ColorAdd => colorAddEntry?.Value ?? 0.05f;

		internal static bool EnableDropAura => enableDropAuraEntry?.Value ?? true;

		internal static float AuraIntensity => auraIntensityEntry?.Value ?? 0.8f;

		internal static float AuraRange => auraRangeEntry?.Value ?? 3.5f;

		internal static void Initialize(ConfigFile config, ManualLogSource logger)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Expected O, but got Unknown
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Expected O, but got Unknown
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Expected O, but got Unknown
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Expected O, but got Unknown
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Expected O, but got Unknown
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Expected O, but got Unknown
			if (config == null)
			{
				throw new ArgumentNullException("config");
			}
			if (logger == null)
			{
				throw new ArgumentNullException("logger");
			}
			configFile = config;
			maxDropsPerLevelEntry = configFile.Bind<int>("General", "MaxDropsPerLevel", 200, new ConfigDescription("Maximum number of items that can drop each level.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000), Array.Empty<object>()));
			preserveItemsBetweenLevelsEntry = configFile.Bind<bool>("General", "PreserveItemsBetweenLevels", false, new ConfigDescription("Allow items obtained from enemy drops and secured in the truck or inventory to persist across levels.", (AcceptableValueBase)null, Array.Empty<object>()));
			maxPreservedItemsEntry = configFile.Bind<int>("General", "MaxPreservedItems", 10, new ConfigDescription("Maximum number of enemy-dropped items that can be preserved simultaneously across levels.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			enableColorModificationEntry = configFile.Bind<bool>("Visuals", "EnableColorModification", false, new ConfigDescription("Whether items dropped by enemies have their materials modified with a color multiplier and additive offset.", (AcceptableValueBase)null, Array.Empty<object>()));
			colorMultiplierREntry = configFile.Bind<float>("Visuals", "ColorMultiplierR", 0.55f, new ConfigDescription("Red channel multiplier applied to material color (preserves texture details).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			colorMultiplierGEntry = configFile.Bind<float>("Visuals", "ColorMultiplierG", 0.55f, new ConfigDescription("Green channel multiplier applied to material color (preserves texture details).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			colorMultiplierBEntry = configFile.Bind<float>("Visuals", "ColorMultiplierB", 0.55f, new ConfigDescription("Blue channel multiplier applied to material color (preserves texture details).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			colorAddEntry = configFile.Bind<float>("Visuals", "ColorAdd", 0.05f, new ConfigDescription("Additive brightness offset applied to material color.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 1f), Array.Empty<object>()));
			enableDropAuraEntry = configFile.Bind<bool>("Visuals", "EnableDropAura", true, new ConfigDescription("Whether items dropped by enemies emit a reddish light aura centered on the item.", (AcceptableValueBase)null, Array.Empty<object>()));
			auraIntensityEntry = configFile.Bind<float>("Visuals", "AuraIntensity", 0.8f, new ConfigDescription("Intensity of the reddish light aura emitted by enemy drops.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f), Array.Empty<object>()));
			auraRangeEntry = configFile.Bind<float>("Visuals", "AuraRange", 3.5f, new ConfigDescription("Range in meters of the reddish light aura emitted by enemy drops.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 10f), Array.Empty<object>()));
			ItemDropTables.InitializeConfig(configFile);
			configFile.Save();
			ItemDropTables.LogWeights(logger);
			logger.LogInfo((object)$"EnemyDrops: Configuration initialized. MaxDropsPerLevel={MaxDropsPerLevel}, PreserveItemsBetweenLevels={PreserveItemsBetweenLevels}, MaxPreservedItems={MaxPreservedItems}, EnableColorModification={EnableColorModification}, EnableDropAura={EnableDropAura}, AuraIntensity={AuraIntensity}, AuraRange={AuraRange}");
		}

		internal static void Reload(ManualLogSource logger)
		{
			if (configFile == null)
			{
				logger.LogWarning((object)"EnemyDrops: Configuration reload requested before initialization.");
				return;
			}
			try
			{
				configFile.Reload();
				ItemDropTables.InitializeConfig(configFile);
				configFile.Save();
				ItemDropTables.LogWeights(logger);
				logger.LogInfo((object)$"EnemyDrops: Configuration reloaded. MaxDropsPerLevel={MaxDropsPerLevel}, PreserveItemsBetweenLevels={PreserveItemsBetweenLevels}, MaxPreservedItems={MaxPreservedItems}, EnableColorModification={EnableColorModification}, EnableDropAura={EnableDropAura}, AuraIntensity={AuraIntensity}, AuraRange={AuraRange}");
			}
			catch (Exception arg)
			{
				logger.LogError((object)$"EnemyDrops: Failed to reload configuration: {arg}");
			}
		}
	}
	internal sealed class DropTableConfigMatrix
	{
		internal const int DropWeightMin = 0;

		internal const int DropWeightMax = 12;

		private readonly Dictionary<string, ConfigEntry<int>> entriesDifficulty1 = new Dictionary<string, ConfigEntry<int>>(StringComparer.OrdinalIgnoreCase);

		private readonly Dictionary<string, ConfigEntry<int>> entriesDifficulty2 = new Dictionary<string, ConfigEntry<int>>(StringComparer.OrdinalIgnoreCase);

		private readonly Dictionary<string, ConfigEntry<int>> entriesDifficulty3 = new Dictionary<string, ConfigEntry<int>>(StringComparer.OrdinalIgnoreCase);

		private readonly IReadOnlyList<WeightedKey> weightsDifficulty1;

		private readonly IReadOnlyList<WeightedKey> weightsDifficulty2;

		private readonly IReadOnlyList<WeightedKey> weightsDifficulty3;

		public DropTableConfigMatrix(ConfigFile config, IReadOnlyList<WeightedKey> defaultsDifficulty1, IReadOnlyList<WeightedKey> defaultsDifficulty2, IReadOnlyList<WeightedKey> defaultsDifficulty3)
		{
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Expected O, but got Unknown
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Expected O, but got Unknown
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Expected O, but got Unknown
			if (config == null)
			{
				throw new ArgumentNullException("config");
			}
			if (defaultsDifficulty1 == null)
			{
				throw new ArgumentNullException("defaultsDifficulty1");
			}
			if (defaultsDifficulty2 == null)
			{
				throw new ArgumentNullException("defaultsDifficulty2");
			}
			if (defaultsDifficulty3 == null)
			{
				throw new ArgumentNullException("defaultsDifficulty3");
			}
			Dictionary<string, float> dictionary = ToMap(defaultsDifficulty1);
			Dictionary<string, float> dictionary2 = ToMap(defaultsDifficulty2);
			Dictionary<string, float> dictionary3 = ToMap(defaultsDifficulty3);
			AcceptableValueRange<int> val = new AcceptableValueRange<int>(0, 12);
			string[] all = ItemKeys.All;
			foreach (string text in all)
			{
				float value;
				int num = Clamp((int)Math.Round(dictionary.TryGetValue(text, out value) ? value : 0f), 0, 12);
				float value2;
				int num2 = Clamp((int)Math.Round(dictionary2.TryGetValue(text, out value2) ? value2 : 0f), 0, 12);
				float value3;
				int num3 = Clamp((int)Math.Round(dictionary3.TryGetValue(text, out value3) ? value3 : 0f), 0, 12);
				entriesDifficulty1[text] = config.Bind<int>("Easy Monsters (Elsa for example)", text, num, new ConfigDescription($"Weight for \"{text}\" on easy monsters. (range {0}..{12})", (AcceptableValueBase)(object)val, Array.Empty<object>()));
				entriesDifficulty2[text] = config.Bind<int>("Med. Monsters (Chef for example)", text, num2, new ConfigDescription($"Weight for \"{text}\" on medium monsters. (range {0}..{12})", (AcceptableValueBase)(object)val, Array.Empty<object>()));
				entriesDifficulty3[text] = config.Bind<int>("Hard Monsters (Robe for example)", text, num3, new ConfigDescription($"Weight for \"{text}\" on hard monsters. (range {0}..{12})", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			}
			weightsDifficulty1 = BuildWeights(entriesDifficulty1);
			weightsDifficulty2 = BuildWeights(entriesDifficulty2);
			weightsDifficulty3 = BuildWeights(entriesDifficulty3);
		}

		public IReadOnlyList<WeightedKey> Get(Difficulty difficulty)
		{
			//IL_0000: 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_0005: Invalid comparison between Unknown and I4
			if ((int)difficulty != 0)
			{
				if ((int)difficulty == 1)
				{
					return weightsDifficulty2;
				}
				return weightsDifficulty3;
			}
			return weightsDifficulty1;
		}

		private static Dictionary<string, float> ToMap(IReadOnlyList<WeightedKey> list)
		{
			Dictionary<string, float> dictionary = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase);
			for (int i = 0; i < list.Count; i++)
			{
				dictionary[list[i].Key] = list[i].Weight;
			}
			return dictionary;
		}

		private static IReadOnlyList<WeightedKey> BuildWeights(Dictionary<string, ConfigEntry<int>> byKey)
		{
			WeightedKey[] array = new WeightedKey[ItemKeys.All.Length];
			for (int i = 0; i < ItemKeys.All.Length; i++)
			{
				string key = ItemKeys.All[i];
				int num = Clamp(byKey[key].Value, 0, 12);
				array[i] = new WeightedKey(key, num);
			}
			return array;
		}

		private static int Clamp(int value, int min, int max)
		{
			if (value >= min)
			{
				if (value <= max)
				{
					return value;
				}
				return max;
			}
			return min;
		}
	}
}