Decompiled source of ExtractionPointReward v1.0.0

ExtractionPointReward.dll

Decompiled 6 hours 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 ExtractionPointReward.Providers;
using ExtractionPointReward.Tracking;
using ExtractionPointReward.Visuals;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using RepoAPI.Game;
using RepoAPI.Items;
using UnityEngine;

[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("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+0f9a9f4307da8ac7dc1dad914a21f142d0514b43")]
[assembly: AssemblyProduct("ExtractionPointReward")]
[assembly: AssemblyTitle("ExtractionPointReward")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
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 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;
		}
	}
	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();
			}
		}
	}
}
namespace ExtractionPointReward
{
	internal static class ConfigurationController
	{
		public sealed class SlotWeightConfigMatrix
		{
			public const int WeightMin = 0;

			public const int WeightMax = 12;

			public const int TotalSlots = 5;

			private readonly ConfigEntry<bool>[] slotEnabled = new ConfigEntry<bool>[5];

			private readonly Dictionary<string, ConfigEntry<int>>[] slotEntries = new Dictionary<string, ConfigEntry<int>>[5];

			private readonly IReadOnlyList<WeightedKey>[] slotWeights = new IReadOnlyList<WeightedKey>[5];

			public SlotWeightConfigMatrix(ConfigFile config, IReadOnlyList<WeightedKey>[] defaultsPerSlot, bool[] defaultEnabledPerSlot)
			{
				//IL_0183: Unknown result type (might be due to invalid IL or missing references)
				//IL_018d: Expected O, but got Unknown
				if (config == null)
				{
					throw new ArgumentNullException("config");
				}
				if (defaultsPerSlot == null)
				{
					throw new ArgumentNullException("defaultsPerSlot");
				}
				if (defaultEnabledPerSlot == null)
				{
					throw new ArgumentNullException("defaultEnabledPerSlot");
				}
				if (defaultsPerSlot.Length != 5)
				{
					throw new ArgumentException($"defaultsPerSlot must have {5} entries", "defaultsPerSlot");
				}
				if (defaultEnabledPerSlot.Length != 5)
				{
					throw new ArgumentException($"defaultEnabledPerSlot must have {5} entries", "defaultEnabledPerSlot");
				}
				AcceptableValueRange<int> val = new AcceptableValueRange<int>(0, 12);
				string[] allKeys = ItemKeysProvider.AllKeys;
				for (int i = 0; i < 5; i++)
				{
					int num = i + 1;
					string text = $"Slot {num}";
					slotEnabled[i] = config.Bind<bool>(text, "Enabled", defaultEnabledPerSlot[i], $"Enable or disable reward Slot {num}.");
					slotEntries[i] = new Dictionary<string, ConfigEntry<int>>(StringComparer.OrdinalIgnoreCase);
					Dictionary<string, float> dictionary = ToMap(defaultsPerSlot[i]);
					foreach (string text2 in allKeys)
					{
						float value;
						int num2 = Clamp((int)Math.Round(dictionary.TryGetValue(text2, out value) ? value : 0f), 0, 12);
						slotEntries[i][text2] = config.Bind<int>(text, text2, num2, new ConfigDescription($"Weight for \"{text2}\" in slot {num}. (range {0}..{12})", (AcceptableValueBase)(object)val, Array.Empty<object>()));
					}
					slotWeights[i] = BuildWeights(slotEntries[i]);
				}
			}

			public bool IsSlotEnabled(int slot)
			{
				if (slot < 1 || slot > 5)
				{
					return false;
				}
				return slotEnabled[slot - 1].Value;
			}

			public IReadOnlyList<WeightedKey> GetForSlot(int slot)
			{
				if (slot < 1 || slot > 5)
				{
					return slotWeights[0];
				}
				return slotWeights[slot - 1];
			}

			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)
			{
				string[] allKeys = ItemKeysProvider.AllKeys;
				WeightedKey[] array = new WeightedKey[allKeys.Length];
				for (int i = 0; i < allKeys.Length; i++)
				{
					string key = allKeys[i];
					int num = Clamp(byKey[key].Value, 0, 12);
					array[i] = new WeightedKey(key, num);
				}
				return array;
			}

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

		private static ConfigFile? configFile;

		public static ConfigEntry<bool> Enabled { get; private set; }

		public static ConfigEntry<bool> PreserveItemsBetweenLevels { get; private set; }

		public static ConfigEntry<int> MaxPreservedItems { get; private set; }

		public static SlotWeightConfigMatrix SlotWeights { get; private set; }

		public static ConfigEntry<bool> EnableColorModification { get; private set; }

		public static ConfigEntry<float> ColorMultiplierR { get; private set; }

		public static ConfigEntry<float> ColorMultiplierG { get; private set; }

		public static ConfigEntry<float> ColorMultiplierB { get; private set; }

		public static ConfigEntry<float> ColorAdd { get; private set; }

		public static ConfigEntry<bool> EnableRewardAura { get; private set; }

		public static ConfigEntry<float> AuraColorR { get; private set; }

		public static ConfigEntry<float> AuraColorG { get; private set; }

		public static ConfigEntry<float> AuraColorB { get; private set; }

		public static ConfigEntry<float> AuraIntensity { get; private set; }

		public static ConfigEntry<float> AuraRange { get; private set; }

		internal static void Initialize(ConfigFile config)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Expected O, but got Unknown
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Expected O, but got Unknown
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Expected O, but got Unknown
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Expected O, but got Unknown
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Expected O, but got Unknown
			configFile = config ?? throw new ArgumentNullException("config");
			Enabled = configFile.Bind<bool>("General", "Enabled", true, "Enable or disable this mod.");
			PreserveItemsBetweenLevels = configFile.Bind<bool>("General", "PreserveItemsBetweenLevels", false, "Allow items obtained from extraction point rewards and secured in the truck or inventory to persist across levels.");
			MaxPreservedItems = configFile.Bind<int>("General", "MaxPreservedItems", 10, new ConfigDescription("Maximum number of extraction-rewarded items that can be preserved simultaneously across levels.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			EnableColorModification = configFile.Bind<bool>("Visuals", "EnableColorModification", false, "Whether items spawned as extraction rewards have their materials modified with a color multiplier and additive offset.");
			ColorMultiplierR = configFile.Bind<float>("Visuals", "ColorMultiplierR", 0.65f, new ConfigDescription("Red channel multiplier applied to material color (preserves texture details).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			ColorMultiplierG = configFile.Bind<float>("Visuals", "ColorMultiplierG", 0.9f, new ConfigDescription("Green channel multiplier applied to material color (preserves texture details).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			ColorMultiplierB = configFile.Bind<float>("Visuals", "ColorMultiplierB", 1f, new ConfigDescription("Blue channel multiplier applied to material color (preserves texture details).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			ColorAdd = 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>()));
			EnableRewardAura = configFile.Bind<bool>("Visuals", "EnableRewardAura", true, "Whether items spawned as extraction rewards emit a luminous light aura centered on the item.");
			AuraColorR = configFile.Bind<float>("Visuals", "AuraColorR", 0.15f, new ConfigDescription("Red channel of the reward aura light color.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			AuraColorG = configFile.Bind<float>("Visuals", "AuraColorG", 0.85f, new ConfigDescription("Green channel of the reward aura light color.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			AuraColorB = configFile.Bind<float>("Visuals", "AuraColorB", 1f, new ConfigDescription("Blue channel of the reward aura light color.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			AuraIntensity = configFile.Bind<float>("Visuals", "AuraIntensity", 0.8f, new ConfigDescription("Intensity of the light aura emitted by extraction rewards.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f), Array.Empty<object>()));
			AuraRange = configFile.Bind<float>("Visuals", "AuraRange", 3.5f, new ConfigDescription("Range in meters of the light aura emitted by extraction rewards.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 10f), Array.Empty<object>()));
			IReadOnlyList<WeightedKey>[] defaultsPerSlot = BuildDefaultWeightsPerSlot();
			bool[] defaultEnabledPerSlot = BuildDefaultEnabledPerSlot();
			SlotWeights = new SlotWeightConfigMatrix(configFile, defaultsPerSlot, defaultEnabledPerSlot);
			configFile.Save();
		}

		internal static void Reload()
		{
			if (configFile != null)
			{
				configFile.Reload();
				IReadOnlyList<WeightedKey>[] defaultsPerSlot = BuildDefaultWeightsPerSlot();
				bool[] defaultEnabledPerSlot = BuildDefaultEnabledPerSlot();
				SlotWeights = new SlotWeightConfigMatrix(configFile, defaultsPerSlot, defaultEnabledPerSlot);
				configFile.Save();
			}
		}

		private static IReadOnlyList<WeightedKey>[] BuildDefaultWeightsPerSlot()
		{
			IReadOnlyList<WeightedKey>[] array = new IReadOnlyList<WeightedKey>[5]
			{
				CreateHealthPackOnlyDefaults(),
				null,
				null,
				null,
				null
			};
			for (int i = 1; i < 5; i++)
			{
				array[i] = CreateBalancedDefaults();
			}
			return array;
		}

		private static bool[] BuildDefaultEnabledPerSlot()
		{
			bool[] array = new bool[5] { true, true, false, false, false };
			for (int i = 2; i < 5; i++)
			{
				array[i] = false;
			}
			return array;
		}

		private static IReadOnlyList<WeightedKey> CreateHealthPackOnlyDefaults()
		{
			string[] allKeys = ItemKeysProvider.AllKeys;
			WeightedKey[] array = new WeightedKey[allKeys.Length];
			for (int i = 0; i < allKeys.Length; i++)
			{
				string text = allKeys[i];
				array[i] = new WeightedKey(text, text switch
				{
					"Item Health Pack Small" => 10f, 
					"Item Health Pack Medium" => 6f, 
					"Item Health Pack Large" => 3f, 
					_ => 0f, 
				});
			}
			return array;
		}

		private static IReadOnlyList<WeightedKey> CreateBalancedDefaults()
		{
			string[] allKeys = ItemKeysProvider.AllKeys;
			WeightedKey[] array = new WeightedKey[allKeys.Length];
			for (int i = 0; i < allKeys.Length; i++)
			{
				string key = allKeys[i];
				array[i] = new WeightedKey(key, GetDefaultWeightForKey(key));
			}
			return array;
		}

		private static float GetDefaultWeightForKey(string key)
		{
			if (key.StartsWith("Item Upgrade", StringComparison.OrdinalIgnoreCase))
			{
				return 1f;
			}
			switch (key)
			{
			case "Item Power Crystal":
				return 0f;
			case "Item Grenade Human":
			case "Item Grenade Duct Taped":
			case "Item Grenade Shockwave":
			case "Item Grenade Explosive":
			case "Item Health Pack Small":
			case "Item Grenade Stun":
			case "Item Mine Explosive":
			case "Item Mine Shockwave":
			case "Item Mine Stun":
				return 10f;
			case "Item Health Pack Medium":
			case "Item Extraction Tracker":
			case "Item Valuable Tracker":
			case "Item Duck Bucket":
				return 6f;
			case "Item Gun Shockwave":
			case "Item Drone Battery":
			case "Item Drone Feather":
			case "Item Staff Zero Gravity":
			case "Item Health Pack Large":
			case "Item Phase Bridge":
			case "Item Drone Torque":
			case "Item Gun Tranq":
			case "Item Melee Frying Pan":
			case "Item Melee Sword":
			case "Item Gun Handgun":
			case "Item Leaf Blower":
			case "Item Rubber Duck":
			case "Item Cart Small":
			case "Item Vehicle Semiscooter":
			case "Item Melee Inflatable Hammer":
			case "Item Gun Stun":
			case "Item Vehicle Semiscooter Small":
				return 3f;
			case "Item Melee Baseball Bat":
			case "Item Drone Zero Gravity":
			case "Item Staff Torque":
			case "Item Gun Laser":
			case "Item Orb Zero Gravity":
			case "Item Melee Stun Baton":
			case "Item Gun Shotgun":
			case "Item Cart Cannon":
			case "Item Cart Medium":
			case "Item ReviveItem":
			case "Item Staff Void":
			case "Item Cart Laser":
			case "Item Melee Sledge Hammer":
			case "Item Drone Indestructible":
			case "Item WalkieTalkieBox":
				return 2f;
			default:
				return 1f;
			}
		}
	}
	[BepInPlugin("com.osmar.ExtractionPointReward", "ExtractionPointReward", "1.0.0")]
	public class ExtractionPointRewardPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.osmar.ExtractionPointReward";

		public const string PluginName = "ExtractionPointReward";

		public const string PluginVersion = "1.0.0";

		internal Harmony? Harmony { get; private set; }

		internal static ManualLogSource Logger { get; private set; }

		private void Awake()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			((Component)this).transform.parent = null;
			((Object)this).hideFlags = (HideFlags)61;
			ConfigurationController.Initialize(((BaseUnityPlugin)this).Config);
			Harmony = new Harmony("com.osmar.ExtractionPointReward");
			Harmony.PatchAll();
			Logger.LogInfo((object)"ExtractionPointReward 1.0.0 loaded!");
		}

		internal void Unpatch()
		{
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}
namespace ExtractionPointReward.Visuals
{
	internal sealed class RewardItemVisuals : MonoBehaviour
	{
		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.Value)
			{
				ApplyMaterialColorModification();
			}
			if (ConfigurationController.EnableRewardAura.Value)
			{
				SetupAuraLight();
			}
			else if ((Object)(object)auraLight != (Object)null && ((Behaviour)auraLight).enabled)
			{
				((Behaviour)auraLight).enabled = false;
			}
			visualsApplied = true;
		}

		private void ApplyMaterialColorModification()
		{
			//IL_00ad: 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)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			float value = ConfigurationController.ColorMultiplierR.Value;
			float value2 = ConfigurationController.ColorMultiplierG.Value;
			float value3 = ConfigurationController.ColorMultiplierB.Value;
			float value4 = ConfigurationController.ColorAdd.Value;
			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 * value + value4), Mathf.Clamp01(val3.g * value2 + value4), Mathf.Clamp01(val3.b * value3 + value4), 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 * value), Mathf.Clamp01(color.g * value2), Mathf.Clamp01(color.b * value3), color.a);
							val2.SetColor("_EmissionColor", val5);
						}
						flag = true;
					}
				}
				if (flag)
				{
					val.materials = materials;
					num++;
				}
			}
			if (!visualsApplied)
			{
				ExtractionPointRewardPlugin.Logger.LogInfo((object)$"RewardItemVisuals: Applied material color modification (mult=[{value:F2},{value2:F2},{value3:F2}], add={value4: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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: 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("RewardItem_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;
			Color auraBaseColor = GetAuraBaseColor();
			auraLight = auraLightObject.AddComponent<Light>();
			auraLight.type = (LightType)2;
			auraLight.color = auraBaseColor;
			auraLight.range = ConfigurationController.AuraRange.Value;
			auraLight.intensity = ConfigurationController.AuraIntensity.Value;
			auraLight.shadows = (LightShadows)0;
			auraLight.renderMode = (LightRenderMode)1;
			auraLight.cullingMask = -1;
			((Behaviour)auraLight).enabled = true;
			ExtractionPointRewardPlugin.Logger.LogInfo((object)$"RewardItemVisuals: Attached centered aura light at local offset {val} on '{((Object)((Component)this).gameObject).name}'.");
		}

		private void Update()
		{
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)auraLight == (Object)null) && ConfigurationController.EnableRewardAura.Value)
			{
				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;
					Color auraBaseColor = GetAuraBaseColor();
					Color val = default(Color);
					((Color)(ref val))..ctor(auraBaseColor.r * 0.75f, auraBaseColor.g * 0.75f, auraBaseColor.b * 0.75f);
					auraLight.color = Color.Lerp(val, auraBaseColor, num2);
					auraLight.intensity = ConfigurationController.AuraIntensity.Value * (0.85f + 0.3f * num2);
					auraLight.range = ConfigurationController.AuraRange.Value;
				}
			}
		}

		private static Color GetAuraBaseColor()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			return new Color(Mathf.Clamp01(ConfigurationController.AuraColorR.Value), Mathf.Clamp01(ConfigurationController.AuraColorG.Value), Mathf.Clamp01(ConfigurationController.AuraColorB.Value));
		}

		private void OnDestroy()
		{
			if ((Object)(object)auraLightObject != (Object)null)
			{
				Object.Destroy((Object)(object)auraLightObject);
			}
		}
	}
}
namespace ExtractionPointReward.Tracking
{
	internal static class RewardInstanceTracker
	{
		private const string PreservedStatsKey = "extractionRewardPreserved";

		private static readonly HashSet<string> rewardInstances = new HashSet<string>();

		internal static void MarkReward(GameObject go)
		{
			if (Object.op_Implicit((Object)(object)go))
			{
				if (!Object.op_Implicit((Object)(object)go.GetComponent<RewardItemTag>()))
				{
					go.AddComponent<RewardItemTag>();
				}
				if (!Object.op_Implicit((Object)(object)go.GetComponent<RewardItemVisuals>()))
				{
					go.AddComponent<RewardItemVisuals>();
				}
				ItemAttributes component = go.GetComponent<ItemAttributes>();
				if ((Object)(object)component != (Object)null && !string.IsNullOrEmpty(component.instanceName))
				{
					RegisterInstance(component.instanceName);
				}
			}
		}

		internal static void RegisterInstance(string instanceName)
		{
			if (!string.IsNullOrEmpty(instanceName) && rewardInstances.Add(instanceName))
			{
				ExtractionPointRewardPlugin.Logger.LogDebug((object)("ExtractionPointReward: Registered reward instance '" + instanceName + "'."));
			}
		}

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

		internal static void ProcessSceneSwitch(bool gameOver, bool leaveGame)
		{
			if (gameOver || leaveGame)
			{
				if (gameOver)
				{
					ItemPreservation.ResetCounts("extractionRewardPreserved");
				}
				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)
			{
				ExtractionPointRewardPlugin.Logger.LogWarning((object)"ExtractionPointReward: StatsManager tables are null; cannot process scene switch.");
				ClearForNewLevel();
				return;
			}
			bool value = ConfigurationController.PreserveItemsBetweenLevels.Value;
			int value2 = ConfigurationController.MaxPreservedItems.Value;
			int num = GetTotalPreservedCount();
			RewardItemTag[] array = Object.FindObjectsOfType<RewardItemTag>();
			HashSet<string> hashSet = new HashSet<string>();
			if (value && array != null)
			{
				foreach (RewardItemTag rewardItemTag in array)
				{
					if (!Object.op_Implicit((Object)(object)rewardItemTag))
					{
						continue;
					}
					ItemAttributes component = ((Component)rewardItemTag).GetComponent<ItemAttributes>();
					if (!Object.op_Implicit((Object)(object)component) || !ItemPreservation.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 >= value2)
					{
						ExtractionPointRewardPlugin.Logger.LogInfo((object)$"ExtractionPointReward: Item '{baseItemName}' ({instanceName}) is secured, but MaxPreservedItems limit ({value2}) has been reached. Item will not persist.");
					}
					else if (ItemPreservation.TryPreserveSecuredItem(component, out baseItemName))
					{
						ItemPreservation.RecordCount("extractionRewardPreserved", baseItemName);
						num++;
						if (!string.IsNullOrEmpty(instanceName))
						{
							hashSet.Add(instanceName);
						}
						ExtractionPointRewardPlugin.Logger.LogInfo((object)$"ExtractionPointReward: Preserved item '{baseItemName}' ({instanceName}) into truck/next level. Total preserved: {num}/{value2}");
					}
				}
			}
			List<string> list = new List<string>(rewardInstances);
			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($"ExtractionPointReward: Cleaned up {list2.Count} non-preserved reward instance(s) from item + itemStatBattery:");
				for (int k = 0; k < list2.Count; k++)
				{
					stringBuilder.AppendLine("  " + list2[k]);
				}
				ExtractionPointRewardPlugin.Logger.LogDebug((object)stringBuilder.ToString());
			}
			ClearForNewLevel();
		}

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

		internal static void Reset()
		{
			ExtractionPointRewardPlugin.Logger.LogDebug((object)$"ExtractionPointReward: Resetting preserved reward count (was {GetTotalPreservedCount()}).");
			ItemPreservation.ResetCounts("extractionRewardPreserved");
			ClearForNewLevel();
		}

		internal static void ClearForNewLevel()
		{
			if (rewardInstances.Count > 0)
			{
				ExtractionPointRewardPlugin.Logger.LogDebug((object)$"ExtractionPointReward: Clearing reward-instance tracker ({rewardInstances.Count} entries).");
			}
			rewardInstances.Clear();
		}
	}
	internal sealed class RewardItemTag : MonoBehaviour
	{
	}
}
namespace ExtractionPointReward.Providers
{
	internal class RandomItemProvider
	{
		private readonly WeightedKeyTable?[] tables = new WeightedKeyTable[5];

		private static int TotalSlots => 5;

		public RandomItemProvider()
		{
			RebuildTables();
		}

		public void RebuildTables()
		{
			if (ConfigurationController.SlotWeights == null)
			{
				throw new InvalidOperationException("ConfigurationController.SlotWeights is not initialized.");
			}
			for (int i = 0; i < TotalSlots; i++)
			{
				int num = i + 1;
				if (!ConfigurationController.SlotWeights.IsSlotEnabled(num))
				{
					tables[i] = null;
					continue;
				}
				IReadOnlyList<WeightedKey> forSlot = ConfigurationController.SlotWeights.GetForSlot(num);
				if (!forSlot.Any((WeightedKey e) => e.Weight > 0f))
				{
					tables[i] = null;
					ExtractionPointRewardPlugin.Logger.LogDebug((object)$"RandomItemProvider: Slot {num} has all-zero weights — any spawn requests for this slot will be skipped.");
				}
				else
				{
					tables[i] = new WeightedKeyTable(forSlot);
				}
			}
		}

		public string? GetRandomKeyForSlot(int slot)
		{
			if (slot < 1 || slot > TotalSlots)
			{
				throw new ArgumentOutOfRangeException("slot", $"Slot must be 1..{TotalSlots}");
			}
			return (tables[slot - 1] ?? throw new InvalidOperationException($"No positive weights configured or slot disabled for slot {slot}.")).GetRandomKey();
		}

		public bool TrySpawnRandomItemForSlot(int slot, Vector3 position, Quaternion rotation, out GameObject? spawned, float upwardOffset = 0.15f)
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			spawned = null;
			if (slot < 1 || slot > TotalSlots)
			{
				throw new ArgumentOutOfRangeException("slot", $"Slot must be 1..{TotalSlots}");
			}
			if (!ConfigurationController.SlotWeights.IsSlotEnabled(slot))
			{
				ExtractionPointRewardPlugin.Logger.LogDebug((object)$"RandomItemProvider: Slot {slot} is disabled — skipping spawn.");
				return false;
			}
			WeightedKeyTable weightedKeyTable = tables[slot - 1];
			if (weightedKeyTable == null)
			{
				ExtractionPointRewardPlugin.Logger.LogWarning((object)$"RandomItemProvider: Slot {slot} has no positive weights configured — skipping spawn.");
				return false;
			}
			string randomKey = weightedKeyTable.GetRandomKey();
			if (string.IsNullOrEmpty(randomKey))
			{
				ExtractionPointRewardPlugin.Logger.LogWarning((object)"RandomItemProvider: Selected empty key.");
				return false;
			}
			if (ItemProvider.TrySpawnByKey(randomKey, position, rotation, out spawned, upwardOffset))
			{
				if ((Object)(object)spawned != (Object)null)
				{
					RewardInstanceTracker.MarkReward(spawned);
				}
				return true;
			}
			return false;
		}
	}
	internal sealed class WeightedKeyTable
	{
		public List<WeightedKey> Entries { get; }

		public float TotalWeight => Entries.Sum((WeightedKey e) => e.Weight);

		public WeightedKeyTable(IEnumerable<WeightedKey> entries)
		{
			if (entries == null)
			{
				throw new ArgumentNullException("entries");
			}
			Entries = entries.Where((WeightedKey e) => e != null).ToList();
		}

		public string? GetRandomKey()
		{
			if (Entries.Count == 0 || TotalWeight <= 0f)
			{
				return null;
			}
			string text = null;
			float num = Random.value * TotalWeight;
			float num2 = 0f;
			foreach (WeightedKey entry in Entries)
			{
				num2 += entry.Weight;
				if (num <= num2)
				{
					text = entry.Key;
					break;
				}
			}
			return text ?? Entries[Entries.Count - 1].Key;
		}
	}
}
namespace ExtractionPointReward.Patches
{
	[HarmonyPatch(typeof(EnemyDirector), "Start")]
	internal static class EnemyDirector_Start_Patch
	{
		private static void Postfix()
		{
			if (SemiFunc.RunIsLevel())
			{
				ConfigurationController.Reload();
				ExtractionPoint_StateComplete_Patch.Reset();
			}
		}
	}
	[HarmonyPatch(typeof(ExtractionPoint), "StateComplete")]
	internal static class ExtractionPoint_StateComplete_Patch
	{
		private static readonly HashSet<int> spawnedInstanceIds = new HashSet<int>();

		private static readonly object spawnLock = new object();

		private static bool IsModEnabled => ConfigurationController.Enabled.Value;

		internal static void Reset()
		{
			lock (spawnLock)
			{
				spawnedInstanceIds.Clear();
			}
		}

		private static void Prefix(ExtractionPoint __instance)
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer() || !SemiFunc.RunIsLevel() || !IsModEnabled || !IsStateStart(__instance))
			{
				return;
			}
			int instanceID = ((Object)__instance).GetInstanceID();
			lock (spawnLock)
			{
				if (spawnedInstanceIds.Contains(instanceID))
				{
					return;
				}
			}
			AddInstanceId(instanceID);
			if (!SpawnRewards(__instance))
			{
				RemoveInstanceId(instanceID);
			}
		}

		private static bool SpawnRewards(ExtractionPoint extractionPoint)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: 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_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			bool result = false;
			Vector3 spawnPosition = GetSpawnPosition(extractionPoint);
			RandomItemProvider randomItemProvider = new RandomItemProvider();
			randomItemProvider.RebuildTables();
			List<int> list = new List<int>();
			for (int i = 1; i <= 5; i++)
			{
				if (ConfigurationController.SlotWeights.IsSlotEnabled(i))
				{
					list.Add(i);
				}
			}
			ExtractionPointRewardPlugin.Logger.LogDebug((object)$"ExtractionPoint_StateComplete_Patch: Spawning {list.Count} enabled reward slots.");
			for (int j = 0; j < list.Count; j++)
			{
				int num = list[j];
				float num2 = ((float)j - (float)(list.Count - 1) / 2f) * 0.5f;
				Vector3 val = spawnPosition + Vector3.right * num2 + Vector3.up * 0.05f * (float)num;
				try
				{
					if (randomItemProvider.TrySpawnRandomItemForSlot(num, val, Quaternion.identity, out GameObject spawned))
					{
						result = true;
						ExtractionPointRewardPlugin.Logger.LogInfo((object)$"ExtractionPoint_StateComplete_Patch: Spawned '{((Object)spawned).name}' for slot {num} at {val}.");
					}
					else
					{
						ExtractionPointRewardPlugin.Logger.LogWarning((object)$"ExtractionPoint_StateComplete_Patch: Failed to spawn item for slot {num} at {val}.");
					}
				}
				catch (Exception arg)
				{
					ExtractionPointRewardPlugin.Logger.LogError((object)$"ExtractionPoint_StateComplete_Patch: Exception while spawning slot {num}: {arg}");
				}
			}
			return result;
		}

		private static Vector3 GetSpawnPosition(ExtractionPoint extractionPoint)
		{
			//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)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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)
			try
			{
				return ((Object)(object)extractionPoint.surplusSpawnTransform != (Object)null) ? extractionPoint.surplusSpawnTransform.position : ((Component)extractionPoint).transform.position;
			}
			catch
			{
				return ((Component)extractionPoint).transform.position;
			}
		}

		private static bool IsStateStart(ExtractionPoint extractionPoint)
		{
			FieldInfo field = ((object)extractionPoint).GetType().GetField("stateStart", BindingFlags.Instance | BindingFlags.NonPublic);
			if (field == null)
			{
				return false;
			}
			return (bool)field.GetValue(extractionPoint);
		}

		private static void AddInstanceId(int instanceId)
		{
			lock (spawnLock)
			{
				spawnedInstanceIds.Add(instanceId);
			}
		}

		private static void RemoveInstanceId(int instanceId)
		{
			lock (spawnLock)
			{
				spawnedInstanceIds.Remove(instanceId);
			}
		}
	}
	[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<RewardItemTag>()))
			{
				RewardInstanceTracker.RegisterInstance(_name);
			}
		}
	}
	[HarmonyPatch(typeof(SemiFunc), "OnSceneSwitch")]
	internal static class SemiFunc_OnSceneSwitch_Patch
	{
		private static void Prefix(bool _gameOver, bool _leaveGame)
		{
			try
			{
				RewardInstanceTracker.ProcessSceneSwitch(_gameOver, _leaveGame);
			}
			catch (Exception arg)
			{
				ExtractionPointRewardPlugin.Logger.LogError((object)$"SemiFunc_OnSceneSwitch_Patch: Failed to process reward instances on scene switch: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(StatsManager), "ItemRemove")]
	internal static class StatsManager_ItemRemove_Patch
	{
		private static void Postfix(string instanceName)
		{
			try
			{
				RewardInstanceTracker.OnItemRemoved(instanceName);
			}
			catch (Exception arg)
			{
				ExtractionPointRewardPlugin.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
			{
				RewardInstanceTracker.Reset();
			}
			catch (Exception arg)
			{
				ExtractionPointRewardPlugin.Logger.LogError((object)$"StatsManager_RunStartStats_Patch: Failed to reset preserved tracker on RunStartStats: {arg}");
			}
		}
	}
}