Decompiled source of Scavenging Scone v0.2.1

Wilnath.Lootations.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using H3MP;
using H3MP.Networking;
using H3MP.Scripts;
using H3MP.Tracking;
using HarmonyLib;
using MapGenerator;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Sodalite.Api;
using SupplyRaid;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("Wilnath/marbL-")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Library for building containers of randomized items in H3VR.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Wilnath.Lootations")]
[assembly: AssemblyTitle("Lootations")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace Lootations
{
	public class EnableHook : MonoBehaviour
	{
		public GameObject LootObjectOwner;

		public bool Inverted;

		public void Awake()
		{
			LootObject component = LootObjectOwner.GetComponent<LootObject>();
			if ((Object)(object)component == (Object)null)
			{
				Lootations.Logger.LogError((object)"VisibilityHook could not find LootObject.");
				return;
			}
			component.LootObjectTriggered += Triggered;
			component.OnTriggerReset += Reset;
			SetEnabled(visible: true);
		}

		private void Reset()
		{
			SetEnabled(visible: true);
		}

		private void Triggered()
		{
			SetEnabled(visible: false);
		}

		private void SetEnabled(bool visible)
		{
			if (Inverted)
			{
				visible = !visible;
			}
			Renderer component = ((Component)this).GetComponent<Renderer>();
			if ((Object)(object)component != (Object)null)
			{
				component.enabled = visible;
			}
			Collider component2 = ((Component)this).GetComponent<Collider>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.enabled = visible;
			}
		}
	}
	public class EnemySpawn : MonoBehaviour
	{
		private class SpawnParameters
		{
			public int IFF;

			public SosigEnemyID[] pool = (SosigEnemyID[])(object)new SosigEnemyID[1] { (SosigEnemyID)160 };

			public int squadSize = 3;
		}

		public bool UseGlobalSpawnSettings = true;

		public float PlayerDistanceToDespawn = 125f;

		public float PlayerDistanceToSpawn = 100f;

		public float PlayerSpawnGrace = 25f;

		private List<Sosig> spawnedSosigs = new List<Sosig>();

		private bool spawned;

		public void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			if (Utilities.PlayerWithinDistance(((Component)this).transform.position, PlayerSpawnGrace))
			{
				Lootations.Logger.LogDebug((object)"Skipped enemy spawn to grace");
				spawned = true;
			}
		}

		public void Update()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (!spawned && (!Lootations.h3mpEnabled || !Networking.IsClient()) && Utilities.PlayerWithinDistance(((Component)this).transform.position, PlayerDistanceToSpawn))
			{
				Spawn();
				spawned = true;
			}
		}

		private SpawnParameters GetSpawnParameters()
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected I4, but got Unknown
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected I4, but got Unknown
			SpawnParameters spawnParameters = new SpawnParameters();
			if (((Behaviour)SR_Manager.instance).isActiveAndEnabled)
			{
				FactionLevel factionLevel = SR_Manager.GetFactionLevel();
				spawnParameters.IFF = 1;
				spawnParameters.squadSize = Random.Range(factionLevel.squadSizeMin, factionLevel.squadSizeMax);
				spawnParameters.pool = factionLevel.squadPool.sosigEnemyID;
				return spawnParameters;
			}
			if (((Behaviour)GM.TNH_Manager).isActiveAndEnabled)
			{
				List<Patrol> patrols = GM.TNH_Manager.m_curLevel.PatrolChallenge.Patrols;
				Patrol val = patrols[Random.Range(0, patrols.Count)];
				spawnParameters.IFF = 1;
				spawnParameters.squadSize = val.PatrolSize;
				spawnParameters.pool = (SosigEnemyID[])(object)new SosigEnemyID[2]
				{
					(SosigEnemyID)(int)val.EType,
					(SosigEnemyID)(int)val.LType
				};
				return spawnParameters;
			}
			return spawnParameters;
		}

		public void Spawn()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			SpawnParameters spawnParameters = GetSpawnParameters();
			SpawnOptions val = new SpawnOptions
			{
				SpawnActivated = true,
				SpawnState = (SosigOrder)1,
				IFF = spawnParameters.IFF,
				SpawnWithFullAmmo = true,
				EquipmentMode = (EquipmentSlots)7,
				SosigTargetPosition = ((Component)this).transform.position,
				SosigTargetRotation = ((Component)this).transform.eulerAngles
			};
			for (int i = 0; i < spawnParameters.squadSize; i++)
			{
				SosigEnemyID randomSosigIDFromPool = SR_Global.GetRandomSosigIDFromPool(spawnParameters.pool);
				Quaternion val2 = Quaternion.Euler(0f, Random.Range(0f, 360f), 0f);
				if (!Utilities.RandomPointOnNavmesh(((Component)this).transform.position, 0.5f, out var result))
				{
					Lootations.Logger.LogDebug((object)"Could not find spawn position for EnemySpawn sosig");
					continue;
				}
				Sosig val3 = SosigAPI.Spawn(ManagerSingleton<IM>.Instance.odicSosigObjsByID[randomSosigIDFromPool], val, result, val2);
				spawnedSosigs.Add(val3);
				if (((Behaviour)SR_Manager.instance).isActiveAndEnabled)
				{
					foreach (Sosig spawnedSosig in spawnedSosigs)
					{
						spawnedSosig.StateSightRangeMults *= SR_Manager.sosigSightMultiplier;
					}
					SR_Manager.instance.AddCustomSosig(val3, false);
				}
				else if (((Behaviour)GM.TNH_Manager).isActiveAndEnabled)
				{
					GM.TNH_Manager.AddToMiscEnemies(((Component)val3).gameObject);
				}
			}
		}

		public void OnDestroy()
		{
			foreach (Sosig spawnedSosig in spawnedSosigs)
			{
				if (spawnedSosig != null)
				{
					spawnedSosig.KillSosig();
				}
			}
			spawnedSosigs.Clear();
		}

		private void OnDrawGizmosSelected()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			Gizmos.color = Color.red;
			if (UseGlobalSpawnSettings)
			{
				Gizmos.DrawSphere(((Component)this).transform.position, 0.25f);
			}
			else
			{
				Gizmos.DrawSphere(((Component)this).transform.position, PlayerDistanceToSpawn);
			}
		}

		private void OnDrawGizmos()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			Gizmos.color = Color.red;
			Gizmos.DrawSphere(((Component)this).transform.position, 0.1f);
		}
	}
	public static class LootManager
	{
		private static readonly int MAX_SPAWNS;

		private static int LootTriggerCounter;

		public static Dictionary<GameObject, LootSpawnPoint> spawnedLoot;

		private static List<LootObject> LootObjects;

		private static List<LootSpawnPoint> LootSpawns;

		private static List<LootObjectRandomizer> ObjectSpawns;

		private static Dictionary<int, ILootTrigger> LootTriggers;

		private static Dictionary<ILootTrigger, int> LootTriggerIds;

		private static int spawnPointsActivated;

		public static readonly Vector2 MAG_AMOUNT_RANGE;

		public static readonly float Y_SPAWN_INCREMENT;

		static LootManager()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			MAX_SPAWNS = -1;
			LootTriggerCounter = 0;
			spawnedLoot = new Dictionary<GameObject, LootSpawnPoint>();
			LootObjects = new List<LootObject>();
			LootSpawns = new List<LootSpawnPoint>();
			ObjectSpawns = new List<LootObjectRandomizer>();
			LootTriggers = new Dictionary<int, ILootTrigger>();
			LootTriggerIds = new Dictionary<ILootTrigger, int>();
			spawnPointsActivated = 0;
			MAG_AMOUNT_RANGE = new Vector2(2f, 4f);
			Y_SPAWN_INCREMENT = 0.05f;
			SR_Manager.SupplyPointChangeEvent += new SupplyPointChangeDelegate(OnSupplyPointChange);
		}

		public static bool AddLootSpawn(LootSpawnPoint lootable)
		{
			LootSpawns.Add(lootable);
			return true;
		}

		public static void RemoveLootSpawn(LootSpawnPoint lootable)
		{
			if (LootSpawns.Contains(lootable))
			{
				LootSpawns.Remove(lootable);
			}
		}

		public static bool AddLootObject(LootObject obj)
		{
			LootObjects.Add(obj);
			return true;
		}

		public static ILootTrigger GetLootTriggerById(int id)
		{
			if (!LootTriggers.ContainsKey(id))
			{
				return null;
			}
			return LootTriggers[id];
		}

		public static int GetLootTriggerId(ILootTrigger trigger)
		{
			return LootTriggerIds[trigger];
		}

		public static bool AddLootTrigger(ILootTrigger trigger)
		{
			LootTriggers.Add(LootTriggerCounter, trigger);
			LootTriggerIds.Add(trigger, LootTriggerCounter);
			LootTriggerCounter++;
			return true;
		}

		public static bool RemoveLootTrigger(ILootTrigger trigger)
		{
			int key = LootTriggerIds[trigger];
			LootTriggerIds.Remove(trigger);
			LootTriggers.Remove(key);
			return true;
		}

		public static bool RemoveLootObject(LootObject obj)
		{
			if (!LootObjects.Contains(obj))
			{
				return false;
			}
			LootObjects.Remove(obj);
			return true;
		}

		public static bool AddRandomObject(LootObjectRandomizer obj)
		{
			ObjectSpawns.Add(obj);
			return true;
		}

		public static void OnPhysicalObjectPickup(GameObject obj)
		{
			if (Lootations.h3mpEnabled && Networking.IsClient())
			{
				Networking.SendItemGrab(obj);
			}
			if (spawnedLoot.ContainsKey(obj))
			{
				Lootations.Logger.LogDebug((object)"Removed object from tracked spawned loot pool.");
				spawnedLoot[obj].StopTrackingObject(obj);
				spawnedLoot.Remove(obj);
			}
		}

		public static void OnSceneSwitched()
		{
			Lootations.Logger.LogInfo((object)"Removing track of spawned items.");
			spawnedLoot.Clear();
			LootSpawns.Clear();
			LootObjects.Clear();
			ObjectSpawns.Clear();
			LootTriggers.Clear();
			LootTriggerIds.Clear();
			LootTriggerCounter = 0;
		}

		public static void StopTrackingNetworkId(int trackingId)
		{
			Lootations.Logger.LogDebug((object)("Attempting to remove " + trackingId));
			if (Server.objects == null)
			{
				Lootations.Logger.LogError((object)"that stuff is null even");
				return;
			}
			if (trackingId < 0 && trackingId >= Server.objects.Length)
			{
				Lootations.Logger.LogError((object)"Clients.objects does not work like that it turns out");
				return;
			}
			TrackedObjectData val = Server.objects[trackingId];
			if (val == null)
			{
				Lootations.Logger.LogError((object)"stop tracking null check obj");
				return;
			}
			TrackedObject physical = val.physical;
			if ((Object)(object)physical == (Object)null)
			{
				Lootations.Logger.LogError((object)"stop tracking null check physical");
				return;
			}
			GameObject gameObject = ((Component)physical).gameObject;
			if ((Object)(object)gameObject == (Object)null)
			{
				Lootations.Logger.LogError((object)"stop tracking null check gameObj");
			}
			else if (spawnedLoot.ContainsKey(gameObject))
			{
				Lootations.Logger.LogDebug((object)"REMOVED IT!");
				spawnedLoot[gameObject].StopTrackingObject(gameObject);
			}
		}

		private static void ShuffleObjectRandomizers()
		{
			ObjectSpawns = ObjectSpawns.OrderBy((LootObjectRandomizer _) => Random.Range(0, int.MaxValue)).ToList();
		}

		private static void OnSupplyPointChange()
		{
			if (Lootations.h3mpEnabled && Networking.IsConnected())
			{
				if (Networking.IsClient())
				{
					Lootations.Logger.LogDebug((object)"Awaiting reroll of loot as client.");
					return;
				}
				Lootations.Logger.LogDebug((object)"Rolling loot as host.");
				int frameCount = Time.frameCount;
				RerollLoot(frameCount);
				Networking.SendRerollLoot(frameCount);
			}
			else
			{
				Lootations.Logger.LogDebug((object)"Rolling loot as offline.");
				RerollLoot();
			}
		}

		public static void OnTNHLevelSet(int level)
		{
			RerollLoot(Time.frameCount);
		}

		public static void RerollLoot(int seed = -1)
		{
			if (seed == -1)
			{
				seed = Time.frameCount;
			}
			int level = 0;
			if (((Behaviour)SR_Manager.instance).isActiveAndEnabled)
			{
				level = SR_Manager.instance.CurrentCaptures;
			}
			Lootations.Logger.LogDebug((object)("Respawning objects with seed: " + seed));
			Random.InitState(seed);
			spawnPointsActivated = 0;
			ShuffleObjectRandomizers();
			spawnedLoot = new Dictionary<GameObject, LootSpawnPoint>();
			for (int i = 0; i < LootSpawns.Count; i++)
			{
				LootSpawns[i].Reset();
			}
			bool flag = false;
			for (int j = 0; j < ObjectSpawns.Count; j++)
			{
				if (MAX_SPAWNS != -1 && j >= MAX_SPAWNS)
				{
					ManualLogSource logger = Lootations.Logger;
					int mAX_SPAWNS = MAX_SPAWNS;
					logger.LogDebug((object)("Stopping respawn of loot objects, hit config limit of " + mAX_SPAWNS));
					flag = true;
					break;
				}
				if (((Behaviour)MG_Manager.instance).isActiveAndEnabled && MG_Manager.profile.srLootSpawns != 0 && j >= MG_Manager.profile.srLootSpawns)
				{
					Lootations.Logger.LogDebug((object)("Stopping respawn of loot objects, hit MG profile limit of " + MG_Manager.profile.srLootSpawns));
					flag = true;
					break;
				}
				ObjectSpawns[j].RollAndSpawn();
				spawnPointsActivated++;
			}
			if (!flag)
			{
				Lootations.Logger.LogDebug((object)"No limit hit for ObjectRandomizer rerolls.");
			}
			Lootations.Logger.LogDebug((object)("Spawned " + spawnPointsActivated + " objects."));
			for (int k = 0; k < LootObjects.Count; k++)
			{
				LootObjects[k].Reset();
			}
			for (int l = 0; l < LootSpawns.Count; l++)
			{
				LootSpawns[l].SetLevel(level);
			}
		}

		public static Quaternion RandomRotation()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			return Quaternion.Euler(0f, Random.Range(0f, 360f), 0f);
		}
	}
	public class LootObject : MonoBehaviour
	{
		public delegate void TriggerResetDelegate();

		public delegate void LootObjectTriggeredDelegate();

		public GameObject[] LootSpawnPoints;

		private LootSpawnPoint[] spawnPoints;

		public bool OneShot;

		public bool HasResetDistanceGrace = true;

		[HideInInspector]
		public bool Triggered;

		public readonly float PLAYER_PROXIMITY_GRACE_DISTANCE = 25f;

		public event TriggerResetDelegate OnTriggerReset;

		public event LootObjectTriggeredDelegate LootObjectTriggered;

		public static void HookTrigger(GameObject lootObjectOwner, MonoBehaviour trigger)
		{
			LootObject lootObject = ((!((Object)(object)lootObjectOwner == (Object)null)) ? lootObjectOwner.GetComponent<LootObject>() : ((Component)trigger).GetComponent<LootObject>());
			if ((Object)(object)lootObject == (Object)null)
			{
				Lootations.Logger.LogError((object)("Cannot hook loot trigger on object without one: " + ((Object)lootObject).name));
			}
			else if (trigger is ILootTrigger)
			{
				ILootTrigger lootTrigger = trigger as ILootTrigger;
				lootObject.OnTriggerReset += lootTrigger.LootReset;
				lootTrigger.OnTriggered += lootObject.Trigger;
				LootManager.AddLootTrigger(lootTrigger);
			}
		}

		public void Awake()
		{
			if (LootSpawnPoints == null)
			{
				Lootations.Logger.LogWarning((object)"LootTrigger skipped initialization due to missing loot points.");
			}
			spawnPoints = Utilities.GameObjectsToPoints(LootSpawnPoints);
			LootManager.AddLootObject(this);
		}

		public void Trigger(ILootTrigger trigger)
		{
			if (Triggered)
			{
				return;
			}
			Triggered = true;
			this.LootObjectTriggered?.Invoke();
			if (Lootations.h3mpEnabled && Networking.IsConnected())
			{
				Networking.SendTriggerActivated(LootManager.GetLootTriggerId(trigger));
				if (Networking.IsClient())
				{
					return;
				}
			}
			SpawnItemsAtLootSpawns();
		}

		private void SpawnItemsAtLootSpawns()
		{
			LootSpawnPoint[] array = spawnPoints;
			foreach (LootSpawnPoint lootSpawnPoint in array)
			{
				if (lootSpawnPoint == null)
				{
					Lootations.Logger.LogError((object)("Object: " + ((Object)this).name + " contained non loot spawn point!"));
				}
				else
				{
					lootSpawnPoint.Trigger();
				}
			}
		}

		public void Reset()
		{
			if (!OneShot)
			{
				Triggered = false;
				this.OnTriggerReset?.Invoke();
			}
		}

		public void OnDestroy()
		{
			LootManager.RemoveLootObject(this);
		}
	}
	public class LootObjectRandomizer : MonoBehaviour
	{
		public GameObject[] Objects;

		public bool RandomizeRotation;

		private GameObject spawnedObject;

		public readonly float PLAYER_PROXIMITY_GRACE_DISTANCE = 35f;

		public bool ResetGrace = true;

		public void Awake()
		{
			LootManager.AddRandomObject(this);
			if (Objects.Length == 0)
			{
				Lootations.Logger.LogError((object)"LootObjectRandomizer has Objects of length 0.");
			}
		}

		public void Destroy()
		{
			if ((Object)(object)spawnedObject != (Object)null)
			{
				Object.Destroy((Object)(object)spawnedObject);
			}
			spawnedObject = null;
		}

		public void RollAndSpawn()
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			if (Objects.Length == 0)
			{
				Lootations.Logger.LogWarning((object)"ObjectRandomizer told to spawn with objects of length 0.");
				return;
			}
			if ((Object)(object)spawnedObject != (Object)null)
			{
				Object.Destroy((Object)(object)spawnedObject);
			}
			int num = Random.Range(0, Objects.Length);
			spawnedObject = Objects[num];
			if ((Object)(object)spawnedObject == (Object)null)
			{
				Lootations.Logger.LogDebug((object)"ObjectRandomizer rolled null");
				return;
			}
			spawnedObject = Object.Instantiate<GameObject>(spawnedObject, ((Component)this).transform);
			if (RandomizeRotation)
			{
				spawnedObject.transform.Rotate(new Vector3(0f, Random.Range(0f, 360f), 0f));
			}
		}

		private void OnDrawGizmos()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			Gizmos.color = Color.green;
			Gizmos.DrawCube(((Component)this).transform.position + new Vector3(0f, 0.5f, 0f), new Vector3(1f, 1f, 1f));
		}
	}
	public class LootSpawnPoint : MonoBehaviour
	{
		public delegate void LootRolledDelegate(List<string> newLoot);

		public string[] ProgressiveLootTables = new string[5] { "Level 0", "Level 1", "Level 2", "Level 3", "Level 4" };

		public float SpawnRadius = 0.25f;

		[Header("Instance Settings")]
		public bool UseInstanceSettings;

		public float CullDistance = 250f;

		private bool HasSpawnedLoot;

		private bool Culled;

		private float cullDistance = 50f;

		private List<GameObject> spawnedLoot = new List<GameObject>();

		private static readonly float CULL_MIN_TIMER = 0.5f;

		private static readonly float CULL_RANDOM_DELAY_MAX = 2.5f;

		private Coroutine CullUpdateRoutine;

		public List<string> ObjectIds { get; set; } = new List<string>();


		public string TableName { get; set; } = "NONE";


		public event LootRolledDelegate LootRolled;

		private void Awake()
		{
			bool active = LootManager.AddLootSpawn(this);
			((Component)this).gameObject.SetActive(active);
			if (Lootations.CullingEnabled.Value)
			{
				CullUpdateRoutine = ((MonoBehaviour)this).StartCoroutine(CullUpdate());
				if (UseInstanceSettings)
				{
					cullDistance = CullDistance;
				}
				else
				{
					cullDistance = Lootations.ItemCullingDistance.Value;
				}
			}
			if ((Object)(object)SR_Manager.instance != (Object)null)
			{
				SetLevel(SR_Manager.instance.CurrentCaptures);
			}
			else
			{
				SetLevel(0);
			}
		}

		private IEnumerator CullUpdate()
		{
			while (true)
			{
				if (HasSpawnedLoot)
				{
					if (Culled)
					{
						if (Utilities.PlayerWithinDistance(((Component)this).transform.position, cullDistance))
						{
							foreach (GameObject item in spawnedLoot)
							{
								item.SetActive(true);
							}
							Culled = false;
						}
					}
					else if (!Utilities.PlayerWithinDistance(((Component)this).transform.position, cullDistance))
					{
						foreach (GameObject item2 in spawnedLoot)
						{
							item2.SetActive(false);
						}
						Culled = true;
					}
				}
				yield return (object)new WaitForSeconds(CULL_MIN_TIMER + Random.Range(0f, CULL_RANDOM_DELAY_MAX));
			}
		}

		public void StopTrackingObject(GameObject obj)
		{
			if (spawnedLoot.Contains(obj))
			{
				spawnedLoot.Remove(obj);
			}
		}

		public void SetLevel(int level)
		{
			if (ProgressiveLootTables.Length == 0)
			{
				Lootations.Logger.LogWarning((object)"Spawn point has no loot tables at all.");
				return;
			}
			level = Mathf.Clamp(level, 0, ProgressiveLootTables.Length - 1);
			TableName = ProgressiveLootTables[level];
		}

		public void Reset()
		{
			if (Lootations.h3mpEnabled && Networking.IsClient())
			{
				return;
			}
			foreach (GameObject item in spawnedLoot)
			{
				Object.Destroy((Object)(object)item);
			}
			spawnedLoot = new List<GameObject>();
			HasSpawnedLoot = false;
			Culled = false;
		}

		public virtual void Trigger()
		{
			ObjectIds = TableManager.GetTable(TableName).RollObjectId();
			this.LootRolled?.Invoke(ObjectIds);
			((MonoBehaviour)this).StartCoroutine(SpawnLoot());
		}

		private void OnDrawGizmos()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			Gizmos.color = new Color(0f, 0.6f, 0f, 0.5f);
			Gizmos.DrawLine(((Component)this).transform.position, ((Component)this).transform.position + ((Component)this).transform.forward * SpawnRadius);
			Gizmos.color = new Color(0.6f, 0f, 0f, 0.5f);
			Gizmos.DrawLine(((Component)this).transform.position, ((Component)this).transform.position + ((Component)this).transform.forward * -1f * SpawnRadius);
			Gizmos.DrawLine(((Component)this).transform.position, ((Component)this).transform.position + ((Component)this).transform.right * SpawnRadius);
			Gizmos.DrawLine(((Component)this).transform.position, ((Component)this).transform.position + ((Component)this).transform.right * -1f * SpawnRadius);
		}

		private void OnDestroy()
		{
			LootManager.RemoveLootSpawn(this);
			if (CullUpdateRoutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(CullUpdateRoutine);
			}
		}

		public IEnumerator SpawnLoot()
		{
			if (Lootations.h3mpEnabled && Networking.IsClient())
			{
				yield break;
			}
			if (ObjectIds.Count == 0)
			{
				Lootations.Logger.LogWarning((object)"Skipped spawn due to empty lootable.");
				yield break;
			}
			Vector3 val = default(Vector3);
			for (int i = 0; i < ObjectIds.Count; i++)
			{
				string text = ObjectIds[i];
				if (!IM.OD.TryGetValue(text, out var obj))
				{
					Lootations.Logger.LogError((object)("No object found with id '" + text + "'."));
					break;
				}
				Transform transform = ((Component)this).gameObject.transform;
				if ((Object)(object)obj != (Object)null && (int)obj.Category == 1)
				{
					FVRObject mag = ((!FirearmAPI.HasMagazine(obj)) ? obj.CompatibleSingleRounds[0] : FirearmAPI.GetSmallestMagazine(obj, (Func<FVRObject, bool>)null));
					int spawnAmount = Random.Range((int)LootManager.MAG_AMOUNT_RANGE.x, (int)LootManager.MAG_AMOUNT_RANGE.y);
					for (int j = 0; j < spawnAmount; j++)
					{
						AnvilCallback<GameObject> magCallback = ((AnvilAsset)mag).GetGameObjectAsync();
						yield return magCallback;
						((Vector3)(ref val))..ctor(Random.Range(0f - SpawnRadius, SpawnRadius), (float)j * LootManager.Y_SPAWN_INCREMENT, Random.Range(0f - SpawnRadius, SpawnRadius));
						GameObject val2 = Object.Instantiate<GameObject>(magCallback.Result, transform.position + val, transform.rotation * LootManager.RandomRotation());
						LootManager.spawnedLoot.Add(val2, this);
						spawnedLoot.Add(val2);
						val2.SetActive(true);
						yield return null;
					}
				}
				AnvilCallback<GameObject> callback = ((AnvilAsset)obj).GetGameObjectAsync();
				yield return callback;
				HasSpawnedLoot = true;
				GameObject val3 = Object.Instantiate<GameObject>(callback.Result, transform.position, transform.rotation * LootManager.RandomRotation());
				LootManager.spawnedLoot.Add(val3, this);
				spawnedLoot.Add(val3);
				val3.SetActive(true);
				yield return null;
				obj = null;
			}
		}
	}
	public static class Networking
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static CustomPacketHandlerReceivedDelegate <0>__ReceiveClientPacketSync;
		}

		private static readonly string ITEM_GRAB_STRING_ID = "Lootations_ItemGrab";

		private static readonly string REROLL_LOOT_STRING_ID = "Lootations_RerollLoot";

		private static readonly string TRIGGER_ACTIVATED_STRING_ID = "Lootations_TriggerActivated";

		private static Dictionary<string, CustomPacketHandler> packetHandlers = new Dictionary<string, CustomPacketHandler>
		{
			{
				ITEM_GRAB_STRING_ID,
				new CustomPacketHandler(ReceiveItemGrab)
			},
			{
				REROLL_LOOT_STRING_ID,
				new CustomPacketHandler(ReceiveRerollLoot)
			},
			{
				TRIGGER_ACTIVATED_STRING_ID,
				new CustomPacketHandler(ReceiveTriggerActivated)
			}
		};

		private static Dictionary<string, int> packetIds = new Dictionary<string, int>();

		public static void OnSceneSwitched(Scene old_scene, Scene new_scene)
		{
			InitializeNetworking();
		}

		public static void InitializeNetworking()
		{
			if (IsConnected())
			{
				SetupPacketTypes();
			}
		}

		private static void SetupPacketTypes()
		{
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Expected O, but got Unknown
			Lootations.Logger.LogDebug((object)"Setting up packet types.");
			foreach (KeyValuePair<string, CustomPacketHandler> packetHandler in packetHandlers)
			{
				if (!packetIds.ContainsKey(packetHandler.Key))
				{
					Lootations.Logger.LogDebug((object)("Adding handler " + packetHandler.Key + " as default ID"));
					packetIds.Add(packetHandler.Key, -1);
				}
			}
			if (IsHost())
			{
				Lootations.Logger.LogDebug((object)"Setting up packets as host.");
				{
					foreach (KeyValuePair<string, CustomPacketHandler> packetHandler2 in packetHandlers)
					{
						Lootations.Logger.LogDebug((object)("Setting up handler " + packetHandler2.Key));
						if (Mod.registeredCustomPacketIDs.ContainsKey(packetHandler2.Key))
						{
							packetIds[packetHandler2.Key] = Mod.registeredCustomPacketIDs[packetHandler2.Key];
							Lootations.Logger.LogDebug((object)("Handler already existed as id " + packetIds[packetHandler2.Key]));
						}
						else
						{
							packetIds[packetHandler2.Key] = Server.RegisterCustomPacketType(packetHandler2.Key, 0);
							Lootations.Logger.LogDebug((object)("Handler registered as id " + packetIds[packetHandler2.Key]));
						}
						Mod.customPacketHandlers[packetIds[packetHandler2.Key]] = packetHandler2.Value;
					}
					return;
				}
			}
			if (!IsClient())
			{
				return;
			}
			Lootations.Logger.LogDebug((object)"Setting up packets as client.");
			object obj = <>O.<0>__ReceiveClientPacketSync;
			if (obj == null)
			{
				CustomPacketHandlerReceivedDelegate val = ReceiveClientPacketSync;
				<>O.<0>__ReceiveClientPacketSync = val;
				obj = (object)val;
			}
			Mod.CustomPacketHandlerReceived += (CustomPacketHandlerReceivedDelegate)obj;
			foreach (KeyValuePair<string, CustomPacketHandler> packetHandler3 in packetHandlers)
			{
				Lootations.Logger.LogDebug((object)("Processing handler " + packetHandler3.Key.ToString()));
				if (Mod.registeredCustomPacketIDs.ContainsKey(packetHandler3.Key))
				{
					packetIds[packetHandler3.Key] = Mod.registeredCustomPacketIDs[packetHandler3.Key];
					Mod.customPacketHandlers[packetIds[packetHandler3.Key]] = packetHandlers[packetHandler3.Key];
					Lootations.Logger.LogDebug((object)("Handler already registered as id " + packetIds[packetHandler3.Key]));
				}
				else
				{
					Lootations.Logger.LogDebug((object)"Registering the handler as new, awaiting ID from host.");
					ClientSend.RegisterCustomPacketType(packetHandler3.Key);
				}
			}
		}

		public static void ReceiveClientPacketSync(string ID, int index)
		{
			Lootations.Logger.LogDebug((object)("Got ClientPacketSync for HandlerID " + ID + " index: " + index));
			if (packetHandlers.ContainsKey(ID))
			{
				packetIds[ID] = index;
				Mod.customPacketHandlers[index] = packetHandlers[ID];
				Lootations.Logger.LogDebug((object)("Successfully connected handling for packet ID: " + ID));
			}
		}

		public static bool IsConnected()
		{
			if (Lootations.h3mpEnabled)
			{
				return (Object)(object)Mod.managerObject != (Object)null;
			}
			return false;
		}

		public static bool IsClient()
		{
			if (IsConnected())
			{
				return !ThreadManager.host;
			}
			return false;
		}

		public static bool IsHost()
		{
			if (IsConnected())
			{
				return ThreadManager.host;
			}
			return false;
		}

		public static int[] GetPlayerIds()
		{
			int[] array = new int[GameManager.players.Count];
			int num = 0;
			foreach (KeyValuePair<int, PlayerManager> player in GameManager.players)
			{
				array[num] = player.Key;
				num++;
			}
			return array;
		}

		public static Vector3 GetPlayerPosition(int id)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			return ((Component)PlayerData.GetPlayer(id).head).transform.position;
		}

		public static void SendItemGrab(GameObject obj)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			if (!IsClient())
			{
				return;
			}
			if ((Object)(object)obj == (Object)null)
			{
				Lootations.Logger.LogDebug((object)"Obj is, somehow, null");
				return;
			}
			TrackedItem component = obj.GetComponent<TrackedItem>();
			if ((Object)(object)component == (Object)null)
			{
				Lootations.Logger.LogDebug((object)"Obj found but no TrackedItem");
				return;
			}
			TrackedObjectData data = ((TrackedObject)component).data;
			if (data == null)
			{
				Lootations.Logger.LogDebug((object)"Tried to get tracking of object that doesn't have it!");
				return;
			}
			Packet val = new Packet(packetIds[ITEM_GRAB_STRING_ID]);
			val.Write(data.trackedID);
			ClientSend.SendTCPData(val, true);
		}

		public static void ReceiveItemGrab(int clientId, Packet packet)
		{
			Lootations.Logger.LogDebug((object)"Item grab packet received");
			LootManager.StopTrackingNetworkId(packet.ReadInt(true));
		}

		public static void SendRerollLoot(int seed)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			Packet val = new Packet(packetIds[REROLL_LOOT_STRING_ID]);
			val.Write(seed);
			ServerSend.SendTCPDataToAll(val, true);
		}

		public static void ReceiveRerollLoot(int clientId, Packet p)
		{
			int seed = p.ReadInt(true);
			if (IsHost())
			{
				Lootations.Logger.LogInfo((object)"Ignoring reroll loot packet as host.");
			}
			else
			{
				LootManager.RerollLoot(seed);
			}
		}

		public static void SendTriggerActivated(int id)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			Packet val = new Packet(packetIds[TRIGGER_ACTIVATED_STRING_ID]);
			val.Write(id);
			if (IsClient())
			{
				ClientSend.SendTCPData(val, true);
			}
			else
			{
				ServerSend.SendTCPDataToAll(val, true);
			}
		}

		public static void ReceiveTriggerActivated(int clientId, Packet packet)
		{
			ILootTrigger lootTriggerById = LootManager.GetLootTriggerById(packet.ReadInt(true));
			if (lootTriggerById == null)
			{
				Lootations.Logger.LogError((object)"Got packet to trigger non-existing loot trigger!");
			}
			else
			{
				lootTriggerById.Trigger();
			}
		}
	}
	[HarmonyPatch(typeof(FVRPhysicalObject), "BeginInteraction")]
	internal class FVRPhysicalObjectPatch
	{
		private static void Postfix(FVRPhysicalObject __instance)
		{
			LootManager.OnPhysicalObjectPickup(((Component)__instance).gameObject);
		}
	}
	[HarmonyPatch(typeof(IM), "GenerateItemDBs")]
	public class GenerateItemDBsPatch
	{
		public static void Postfix()
		{
			TableManager.Initialize();
		}
	}
	[HarmonyPatch(typeof(TNH_Manager), "SetLevel")]
	public class TNHManagerSetLevelHook
	{
		public static void Postfix(int level)
		{
			Lootations.Logger.LogDebug((object)"TNH SetLevel hook fired");
			LootManager.OnTNHLevelSet(level);
		}
	}
	[BepInProcess("h3vr.exe")]
	[BepInPlugin("Wilnath.Lootations", "Lootations", "1.0.0")]
	public class Lootations : BaseUnityPlugin
	{
		public static bool h3mpEnabled;

		public static ConfigEntry<int> MaxRandomLootObjectSpawns;

		public static ConfigEntry<float> ProximitySpawnDistance;

		public static ConfigEntry<float> ItemCullingDistance;

		public static ConfigEntry<float> SosigSpawnDistance;

		public static ConfigEntry<float> SosigDeSpawnDistance;

		public static ConfigEntry<bool> CullingEnabled;

		public static ConfigEntry<string> DisabledModDrops;

		private static Harmony harmonyInstance;

		public const string Id = "Wilnath.Lootations";

		internal static ManualLogSource Logger { get; private set; }

		public static string Name => "Lootations";

		public static string Version => "1.0.0";

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			harmonyInstance = new Harmony("LootationsHarmonyInstance");
			harmonyInstance.PatchAll();
			SetupConfig();
			h3mpEnabled = Chainloader.PluginInfos.ContainsKey("VIP.TommySoucy.H3MP");
			SceneManager.activeSceneChanged += OnSceneSwitched;
			if (h3mpEnabled)
			{
				Logger.LogDebug((object)"H3MP Detected as enabled");
				HookNetworking();
			}
			else
			{
				Logger.LogDebug((object)"Starting with no H3MP");
			}
		}

		private void HookNetworking()
		{
			SceneManager.activeSceneChanged += Networking.OnSceneSwitched;
		}

		private void OnSceneSwitched(Scene old_scene, Scene new_scene)
		{
			Logger.LogDebug((object)"Scene switch occurred");
			LootManager.OnSceneSwitched();
		}

		private void SetupConfig()
		{
			MaxRandomLootObjectSpawns = ((BaseUnityPlugin)this).Config.Bind<int>("Gameplay", "MaxRandomLootObjectSpawns", 250, "The maximum amount of random loot objects that will spawn per level. -1 to disable");
			DisabledModDrops = ((BaseUnityPlugin)this).Config.Bind<string>("Gameplay", "DisabledModDrops", "", "Plugin names that should count as not being loaded for loot tables. Seperate plugin names with a colon");
			SosigSpawnDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Performance", "SosigSpawnDistance", 75f, "How far away you have to be for sausages to spawn in.");
			SosigDeSpawnDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Performance", "SosigDeSpawnDistance", 150f, "TODO");
			ProximitySpawnDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Performance", "ProximitySpawnDistance", 25f, "Distance until Proximity triggers activate, can be expensive if too far.\nNote: Some proximity triggers override this setting.");
			CullingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Experimental", "Culling", true, "If untouched items are to be disabled after player is set distance away from the loot spawn point.");
			ItemCullingDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Experimental", "ItemCullingDistance", 50f, "The distance at which items are set to be inactive.");
		}
	}
	public class LootTable
	{
		public string Name { get; private set; }

		public string[] Meta { get; set; }

		public List<TableEntry> Entries { get; private set; } = new List<TableEntry>();


		public int TotalWeight { get; set; } = -1;


		public LootTable(string name, TableEntry[] entries)
		{
			foreach (TableEntry entry in entries)
			{
				AddEntry(entry);
			}
			Name = name;
		}

		public void AddEntry(TableEntry entry)
		{
			Entries.Add(entry);
		}

		public List<string> RollObjectId()
		{
			if (TotalWeight == -1)
			{
				CalculateTotalWeight();
			}
			if (TotalWeight == 0)
			{
				Lootations.Logger.LogError((object)("Total weight calculated to be 0 in " + Name));
				return new List<string>();
			}
			int num = Random.Range(1, TotalWeight + 1);
			foreach (TableEntry entry in Entries)
			{
				if (num <= entry.Weight)
				{
					return entry.RollObjectId();
				}
				num -= entry.Weight;
			}
			Lootations.Logger.LogError((object)("Could not roll any ids in " + Name));
			return new List<string>();
		}

		public void CalculateTotalWeight()
		{
			TotalWeight = 0;
			foreach (TableEntry entry in Entries)
			{
				TotalWeight += entry.Weight;
			}
		}
	}
	public interface IValidator
	{
		bool IsValid();
	}
	public class MetaTags
	{
		public List<IValidator> Validators = new List<IValidator>();
	}
	public static class MetaTagsManager
	{
		public static Dictionary<string, Func<string, MetaTags, bool>> keyToMethod = new Dictionary<string, Func<string, MetaTags, bool>> { 
		{
			"ModDependency",
			delegate(string s, MetaTags tags)
			{
				tags.Validators.Add(new ModDependency(s));
				return true;
			}
		} };

		public static MetaTags ParseTableMetaTags(LootTable table)
		{
			string[] meta = table.Meta;
			MetaTags metaTags = new MetaTags();
			string[] array = meta;
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { ':' });
				if (array2.Length != 2)
				{
					Lootations.Logger.LogWarning((object)"Skipping meta tag with ambiguous key:value pair");
					continue;
				}
				string key = array2[0].Trim();
				if (!keyToMethod.ContainsKey(key))
				{
					Lootations.Logger.LogWarning((object)"Skipping meta tag with non-existing meta key");
					continue;
				}
				string arg = array2[1].Trim();
				keyToMethod[key](arg, metaTags);
			}
			return metaTags;
		}
	}
	public class ModDependency : IValidator
	{
		private string _modDependency;

		public ModDependency(string modDependency)
		{
			_modDependency = modDependency;
		}

		public bool IsValid()
		{
			if (Lootations.DisabledModDrops != null && Lootations.DisabledModDrops.Value.Split(new char[1] { ',' }).Contains(_modDependency))
			{
				return false;
			}
			return Chainloader.PluginInfos.ContainsKey(_modDependency);
		}
	}
	public class TableEntry
	{
		public enum TableType
		{
			OBJECT_ID,
			TABLE_REFERENCE,
			TAGS
		}

		public TableType Type { get; set; }

		public int Weight { get; set; }

		public List<string> LootIds { get; set; }

		public static TableEntry ObjectEntry(string objectId, int weight)
		{
			return new TableEntry
			{
				Weight = weight,
				LootIds = new List<string>(1) { objectId },
				Type = TableType.OBJECT_ID
			};
		}

		public static TableEntry TableReference(string tableName, int weight)
		{
			return new TableEntry
			{
				Weight = weight,
				LootIds = new List<string>(1) { tableName },
				Type = TableType.TABLE_REFERENCE
			};
		}

		public List<string> RollObjectId()
		{
			switch (Type)
			{
			case TableType.OBJECT_ID:
				return LootIds;
			case TableType.TABLE_REFERENCE:
				return TableManager.GetTable(LootIds[0]).RollObjectId();
			case TableType.TAGS:
				return new List<string>();
			default:
				Lootations.Logger.LogError((object)"Invalid TableEntry Type. Returning None.");
				return new List<string>();
			}
		}

		private bool IsTagAndValueValid(string tag, string value)
		{
			PropertyInfo property = ((object)IM.OD["BulbBlue"]).GetType().GetProperty(tag.Insert(0, "Tag"));
			if ((object)property == null)
			{
				Lootations.Logger.LogError((object)("Could not find tag with name " + property));
				return false;
			}
			return true;
		}

		private void InitializeTagTable()
		{
			if (Type != TableType.TAGS || LootIds.Count == 0)
			{
				return;
			}
			string[] array = LootIds[0].Split(new char[1] { ':' });
			if (array.Length != 2)
			{
				Lootations.Logger.LogError((object)"Error parsing tags in tag table entry, invalid argument length");
				return;
			}
			string tag = array[0];
			string value = array[1];
			new List<string>();
			IsTagAndValueValid(tag, value);
			foreach (KeyValuePair<string, FVRObject> item in IM.OD)
			{
				_ = item;
			}
		}
	}
	public static class TableManager
	{
		private static Dictionary<string, LootTable> _lootTables;

		private static readonly LootTable NullTable = new LootTable("NONE", new TableEntry[1] { TableEntry.ObjectEntry("NONE", 1) });

		public static void Initialize()
		{
			_lootTables = new Dictionary<string, LootTable>();
			Lootations.Logger.LogInfo((object)"Begun reading loot table files.");
			string[] files = Directory.GetFiles(Paths.PluginPath, "*.lttbl", SearchOption.AllDirectories);
			for (int i = 0; i < files.Length; i++)
			{
				ProcessFile(files[i]);
			}
			ValidateAllTables();
		}

		private static void ValidateAllTables()
		{
			foreach (KeyValuePair<string, LootTable> lootTable in _lootTables)
			{
				RemoveZeroWeightEntries(lootTable.Value);
				ValidateObjectIds(lootTable.Value);
			}
			foreach (KeyValuePair<string, LootTable> lootTable2 in _lootTables)
			{
				lootTable2.Value.CalculateTotalWeight();
			}
			foreach (KeyValuePair<string, LootTable> lootTable3 in _lootTables)
			{
				ValidateReferences(lootTable3.Value);
			}
		}

		private static void RemoveZeroWeightEntries(LootTable table)
		{
			for (int i = 0; i < table.Entries.Count; i++)
			{
				if (table.Entries[i].Weight == 0)
				{
					table.Entries.RemoveAt(i);
					i--;
				}
			}
		}

		private static void ValidateObjectIds(LootTable table)
		{
			for (int i = 0; i < table.Entries.Count; i++)
			{
				if (table.Entries[i].Type == TableEntry.TableType.TABLE_REFERENCE)
				{
					continue;
				}
				List<string> lootIds = table.Entries[i].LootIds;
				for (int j = 0; j < lootIds.Count; j++)
				{
					string text = lootIds[j];
					if (!IM.OD.ContainsKey(text))
					{
						Lootations.Logger.LogDebug((object)("Unknown object id " + text + " in table " + table.Name));
					}
				}
				if (lootIds.Count == 0)
				{
					table.Entries.RemoveAt(i);
					table.CalculateTotalWeight();
					i--;
				}
			}
		}

		private static void ValidateReferences(LootTable table)
		{
			for (int i = 0; i < table.Entries.Count; i++)
			{
				TableEntry tableEntry = table.Entries[i];
				if (tableEntry.Type == TableEntry.TableType.TABLE_REFERENCE)
				{
					if (GetTable(tableEntry.LootIds[0]) == NullTable)
					{
						Lootations.Logger.LogWarning((object)("Reference to non-existant table " + tableEntry.LootIds[0] + " in " + table.Name));
						table.Entries.RemoveAt(i);
						table.CalculateTotalWeight();
						i--;
					}
					else if (GetTable(tableEntry.LootIds[0]).TotalWeight == 0)
					{
						Lootations.Logger.LogDebug((object)("Deleting reference entry to empty table " + tableEntry.LootIds[0] + " in " + table.Name));
						table.Entries.RemoveAt(i);
						table.CalculateTotalWeight();
						i--;
					}
				}
			}
		}

		public static void AddLootTable(LootTable table)
		{
			foreach (IValidator validator in MetaTagsManager.ParseTableMetaTags(table).Validators)
			{
				if (!validator.IsValid())
				{
					Lootations.Logger.LogInfo((object)("Skipping loading table due to failed validator: " + table.Name));
					return;
				}
			}
			if (_lootTables.ContainsKey(table.Name))
			{
				Lootations.Logger.LogInfo((object)("Appending to table " + table.Name));
				LootTable lootTable = _lootTables[table.Name];
				{
					foreach (TableEntry entry in table.Entries)
					{
						lootTable.Entries.Add(entry);
					}
					return;
				}
			}
			for (int i = 0; i < table.Entries.Count; i++)
			{
				TableEntry tableEntry = table.Entries[i];
				if (tableEntry.Weight == 0)
				{
					table.Entries.Remove(tableEntry);
					i--;
				}
			}
			_lootTables.Add(table.Name, table);
		}

		public static LootTable GetTable(string name)
		{
			if (!_lootTables.TryGetValue(name, out var value))
			{
				Lootations.Logger.LogWarning((object)("Attempt to access nonexistant table " + name));
				return NullTable;
			}
			return value;
		}

		private static void ProcessFile(string fileName)
		{
			foreach (LootTable item in JsonConvert.DeserializeObject<List<LootTable>>(File.ReadAllText(fileName)))
			{
				AddLootTable(item);
			}
		}
	}
	public interface ILootTrigger
	{
		public delegate void OnTriggeredDelegate(ILootTrigger trigger);

		event OnTriggeredDelegate OnTriggered;

		void Trigger();

		void LootReset();
	}
	public class LootCardScanTrigger : MonoBehaviour, ILootTrigger
	{
		public GameObject LootObjectOwner;

		public int KeycardTier = 1;

		public event ILootTrigger.OnTriggeredDelegate OnTriggered;

		public void Awake()
		{
			LootObject.HookTrigger(LootObjectOwner, (MonoBehaviour)(object)this);
		}

		private void OnTriggerEnter(Collider other)
		{
			WW_Keycard component = ((Component)other).GetComponent<WW_Keycard>();
			if ((Object)(object)component != (Object)null && component.TierType == KeycardTier)
			{
				Trigger();
			}
		}

		public void Trigger()
		{
			this.OnTriggered?.Invoke(this);
		}

		private void OnDrawGizmos()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			Gizmos.color = new Color(0f, 0.6f, 0f, 0.5f);
		}

		public void LootReset()
		{
		}
	}
	public class LootCoverTrigger : FVRInteractiveObject, ILootTrigger
	{
		public GameObject LootObjectOwner;

		public Transform Root;

		public Transform Hinge;

		private float startAngle;

		public float MinRot;

		public float MaxRot = 45f;

		private bool JustInteracted;

		public event ILootTrigger.OnTriggeredDelegate OnTriggered;

		public override void Awake()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			((FVRInteractiveObject)this).Awake();
			startAngle = ((Component)Hinge).transform.localEulerAngles.z;
			if ((Object)(object)Root == (Object)null || (Object)(object)Hinge == (Object)null)
			{
				Lootations.Logger.LogError((object)"CoverTrigger doesn't have a root or hinge, this is misconfigured!");
				((Component)this).gameObject.SetActive(false);
			}
			else
			{
				LootObject.HookTrigger(LootObjectOwner, (MonoBehaviour)(object)this);
			}
		}

		public void Trigger()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (!JustInteracted)
			{
				((Component)Hinge).transform.localEulerAngles = new Vector3(0f, 0f, MaxRot);
			}
			this.OnTriggered?.Invoke(this);
		}

		public override void BeginInteraction(FVRViveHand hand)
		{
			((FVRInteractiveObject)this).BeginInteraction(hand);
			AudioSource component = ((Component)this).GetComponent<AudioSource>();
			if (component != null)
			{
				component.Play();
			}
			JustInteracted = true;
			Trigger();
			JustInteracted = false;
		}

		public override void UpdateInteraction(FVRViveHand hand)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			((FVRInteractiveObject)this).UpdateInteraction(hand);
			Vector3 val = Root.InverseTransformPoint(((HandInput)(ref hand.Input)).Pos);
			float num = Mathf.Atan2(val.y, val.x) * 57.29578f;
			num = Mathf.Clamp(num, MinRot, MaxRot);
			((Component)Hinge).transform.localEulerAngles = new Vector3(0f, 0f, num);
		}

		public void LootReset()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			((Component)Hinge).transform.localEulerAngles = new Vector3(0f, 0f, startAngle);
		}

		private void OnDrawGizmos()
		{
			//IL_0023: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Root == (Object)null))
			{
				Gizmos.color = new Color(0f, 0.6f, 0f, 0.5f);
				Gizmos.DrawLine(((Component)Root).transform.position, ((Component)Root).transform.position + new Vector3(0f, ((Component)Root).transform.forward.y * Mathf.Sin(MinRot), ((Component)Root).transform.forward.z * Mathf.Cos(MinRot)) * 0.25f);
				Gizmos.DrawLine(((Component)Root).transform.position, ((Component)Root).transform.position + new Vector3(0f, ((Component)Root).transform.forward.y * Mathf.Sin(MaxRot), ((Component)Root).transform.forward.z * Mathf.Cos(MaxRot)) * 0.25f);
			}
		}
	}
	public class LootDamageTrigger : MonoBehaviour, IFVRDamageable, ILootTrigger
	{
		public GameObject LootObjectOwner;

		public DamageClass triggerDamageType = (DamageClass)3;

		public float triggerDamageSize = 10f;

		public event ILootTrigger.OnTriggeredDelegate OnTriggered;

		public void Awake()
		{
			LootObject.HookTrigger(LootObjectOwner, (MonoBehaviour)(object)this);
		}

		void IFVRDamageable.Damage(Damage dam)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (dam.Class == triggerDamageType)
			{
				AudioSource component = ((Component)this).GetComponent<AudioSource>();
				if (component != null)
				{
					component.Play();
				}
				Trigger();
			}
		}

		public void Trigger()
		{
			this.OnTriggered?.Invoke(this);
		}

		public void LootReset()
		{
		}
	}
	public class LootPhysicsTrigger : FVRPhysicalObject, ILootTrigger
	{
		[Header("Loot Trigger")]
		public GameObject LootObjectOwner;

		private Vector3 startingPosition;

		private Quaternion startingRotation;

		private Vector3 startingScale;

		public event ILootTrigger.OnTriggeredDelegate OnTriggered;

		public override void Awake()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			startingPosition = ((Component)this).transform.localPosition;
			startingRotation = ((Component)this).transform.localRotation;
			startingScale = ((Component)this).transform.localScale;
			LootObject.HookTrigger(LootObjectOwner, (MonoBehaviour)(object)this);
		}

		public override void BeginInteraction(FVRViveHand hand)
		{
			((FVRPhysicalObject)this).BeginInteraction(hand);
			Trigger();
		}

		public void Trigger()
		{
			this.OnTriggered?.Invoke(this);
		}

		public void LootReset()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			((Component)this).transform.position = startingPosition;
			((Component)this).transform.rotation = startingRotation;
			((Component)this).transform.localScale = startingScale;
		}
	}
	public class LootProximityTrigger : MonoBehaviour, ILootTrigger
	{
		public GameObject LootObjectOwner;

		[Header("Instance Settings")]
		public bool UseInstanceSettings;

		public float TriggerDistance = 250f;

		private float triggerDistance;

		public event ILootTrigger.OnTriggeredDelegate OnTriggered;

		public void Awake()
		{
			LootObject.HookTrigger(LootObjectOwner, (MonoBehaviour)(object)this);
			if (UseInstanceSettings)
			{
				triggerDistance = TriggerDistance;
			}
			else
			{
				triggerDistance = Lootations.ProximitySpawnDistance.Value;
			}
		}

		public void Trigger()
		{
			this.OnTriggered?.Invoke(this);
		}

		public void LootReset()
		{
		}

		public void Update()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			if (Utilities.PlayerWithinDistance(((Component)this).transform.position, triggerDistance))
			{
				Trigger();
			}
		}
	}
	public class LootSlideTrigger : FVRInteractiveObject, ILootTrigger
	{
		public GameObject LootObjectOwner;

		public GameObject Root;

		public GameObject Hinge;

		public float MaxOffset = 0.25f;

		public event ILootTrigger.OnTriggeredDelegate OnTriggered;

		public override void Awake()
		{
			if ((Object)(object)Root == (Object)null || (Object)(object)Hinge == (Object)null)
			{
				Lootations.Logger.LogError((object)"SlideTrigger doesn't have a root or hinge, this is misconfigured!");
				((Component)this).gameObject.SetActive(false);
			}
			else
			{
				LootObject.HookTrigger(LootObjectOwner, (MonoBehaviour)(object)this);
			}
		}

		public override void BeginInteraction(FVRViveHand hand)
		{
			((FVRInteractiveObject)this).BeginInteraction(hand);
		}

		public void Trigger()
		{
			this.OnTriggered?.Invoke(this);
		}

		public override void UpdateInteraction(FVRViveHand hand)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			((FVRInteractiveObject)this).UpdateInteraction(hand);
			float num = Mathf.Clamp(Root.transform.InverseTransformPoint(((HandInput)(ref hand.Input)).Pos).z, 0f, MaxOffset);
			Hinge.transform.localPosition = new Vector3(0f, 0f, num);
		}

		public void LootReset()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			Hinge.transform.localPosition = new Vector3(0f, 0f, 0f);
		}

		private void OnDrawGizmos()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			Gizmos.color = new Color(0f, 0.6f, 0f, 0.5f);
			Gizmos.DrawLine(Root.transform.position, Root.transform.position + Root.transform.forward * MaxOffset);
		}
	}
	internal static class Utilities
	{
		private static readonly float NAVMESH_QUERY_RANGE = 30f;

		public static LootSpawnPoint[] GameObjectsToPoints(GameObject[] gameObjects)
		{
			if (gameObjects.Length == 0)
			{
				return new LootSpawnPoint[0];
			}
			LootSpawnPoint[] array = new LootSpawnPoint[gameObjects.Length];
			for (int i = 0; i < gameObjects.Length; i++)
			{
				LootSpawnPoint component = gameObjects[i].GetComponent<LootSpawnPoint>();
				if ((Object)(object)component == (Object)null)
				{
					Lootations.Logger.LogError((object)"Object has loot spawn point set without its component");
				}
				else
				{
					array[i] = component;
				}
			}
			return array;
		}

		public static bool FindPointOnNavmesh(Vector3 centre, out Vector3 result)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			NavMeshHit val = default(NavMeshHit);
			if (NavMesh.SamplePosition(centre, ref val, NAVMESH_QUERY_RANGE, -1))
			{
				result = ((NavMeshHit)(ref val)).position;
				return true;
			}
			result = Vector3.zero;
			return false;
		}

		public static bool RandomPointOnNavmesh(Vector3 centre, float range, out Vector3 result)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			NavMeshHit val = default(NavMeshHit);
			for (int i = 0; i < 30; i++)
			{
				if (NavMesh.SamplePosition(centre + Random.insideUnitSphere * range, ref val, 0.5f, -1))
				{
					result = ((NavMeshHit)(ref val)).position;
					return true;
				}
			}
			result = Vector3.zero;
			return false;
		}

		public static string GetRandomInStringArray(string[] arr)
		{
			if (arr.Length == 0)
			{
				return "";
			}
			return arr[Random.Range(0, arr.Length + 1)];
		}

		public static Vector3 GetPlayerPosition()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			return ((Component)GM.CurrentPlayerBody.Head).transform.position;
		}

		public static bool PositionsWithinDistance(Vector3 a, Vector3 b, float distance)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = b - a;
			return ((Vector3)(ref val)).sqrMagnitude < distance * distance;
		}

		public static PlayerData GetPlayer(int i)
		{
			return PlayerData.GetPlayer(i);
		}

		public static bool PlayerWithinDistance(Vector3 a, float distance)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (Lootations.h3mpEnabled && Networking.IsHost())
			{
				int[] playerIds = Networking.GetPlayerIds();
				for (int i = 0; i < playerIds.Length; i++)
				{
					if (PositionsWithinDistance(Networking.GetPlayerPosition(playerIds[i]), a, distance))
					{
						return true;
					}
				}
			}
			return PositionsWithinDistance(GetPlayerPosition(), a, distance);
		}
	}
}