Decompiled source of SafehouseProgressionModeCode Beta v0.1.6

NGA.SHPlibs.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using Atlas;
using BepInEx;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using NGA.ItemShop;
using Sodalite.Api;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyCompany("NGA")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Persistent player progression! Raid, stash loot, and deploy with seemless scene/loadout saving.")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("NGA.SHPlibs")]
[assembly: AssemblyTitle("BepInEx Plugin Title")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.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;
		}
	}
}
public class BaseViewModel
{
	public event Action Changed;

	protected void NotifyListeners()
	{
		this.Changed?.Invoke();
	}

	public virtual void Initialize()
	{
	}

	public virtual void Dispose()
	{
	}
}
public class ViewModelRegistry : MonoBehaviour
{
	private static ViewModelRegistry _instance;

	private readonly Dictionary<Type, object> _map = new Dictionary<Type, object>();

	private void Awake()
	{
		if ((Object)(object)_instance != (Object)null && (Object)(object)_instance != (Object)(object)this)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		_instance = this;
		Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
	}

	private static void EnsureInstance()
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Expected O, but got Unknown
		if (!((Object)(object)_instance != (Object)null))
		{
			GameObject val = new GameObject("ViewModelRegistry");
			_instance = val.AddComponent<ViewModelRegistry>();
			Object.DontDestroyOnLoad((Object)(object)val);
		}
	}

	public static T Get<T>() where T : BaseViewModel, new()
	{
		EnsureInstance();
		Type typeFromHandle = typeof(T);
		if (!_instance._map.TryGetValue(typeFromHandle, out var value))
		{
			T val = new T();
			val.Initialize();
			_instance._map[typeFromHandle] = val;
			value = val;
		}
		return (T)value;
	}

	public static void Prewarm<T>() where T : BaseViewModel, new()
	{
		Get<T>();
	}

	public static void Ensure()
	{
		EnsureInstance();
	}

	public static void Register<T>(T instance) where T : BaseViewModel
	{
		EnsureInstance();
		_instance._map[typeof(T)] = instance;
	}

	public static void DisposeAll()
	{
		EnsureInstance();
		foreach (KeyValuePair<Type, object> item in _instance._map)
		{
			((BaseViewModel)item.Value).Dispose();
		}
		_instance._map.Clear();
	}
}
public class UIElementAnimator
{
	public static IEnumerator AnimateRoutine(Transform rect, Transform targetTransform, float duration)
	{
		Vector3 startPos = rect.position;
		Quaternion startRot = rect.rotation;
		Vector3 targetPos = targetTransform.position;
		Quaternion targetRot = targetTransform.rotation;
		float t = 0f;
		while (t < duration)
		{
			t += Time.deltaTime;
			float lerpT = Mathf.Clamp01(t / duration);
			rect.position = Vector3.Lerp(startPos, targetPos, lerpT);
			rect.rotation = Quaternion.Lerp(startRot, targetRot, lerpT);
			yield return null;
		}
		rect.position = targetPos;
		rect.rotation = targetRot;
	}
}
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 NGA
{
	public static class BankUtils
	{
		public const string BITTIES_SYMBOL = "₿";

		public const string SPADES_SYMBOL = "♠";

		public const string BITTIES_COLOR = "yellow";

		public const string SPADES_COLOR = "lightblue";

		public static string BITTIES_SYMBOL_COLORED = "<color=yellow>₿</color>";

		public static string SPADES_SYMBOL_COLORED = "<color=lightblue>♠</color>";

		private static readonly CultureInfo Invariant = CultureInfo.InvariantCulture;

		public static string FormatAmount(int amount)
		{
			return amount.ToString("N0", Invariant);
		}

		public static string FormatBitties(int amount, bool bold = true)
		{
			string text = FormatAmount(amount);
			string text2 = "<color=yellow>₿</color>" + text;
			return bold ? ("<b>" + text2 + "</b>") : text2;
		}

		public static string FormatBitties(float amount, bool bold = true)
		{
			string text = amount.ToString("N2", Invariant).TrimEnd(new char[1] { '0' }).TrimEnd(new char[1] { Invariant.NumberFormat.NumberDecimalSeparator[0] });
			string text2 = "<color=yellow>₿</color>" + text;
			return bold ? ("<b>" + text2 + "</b>") : text2;
		}

		public static string FormatSpades(int amount, bool bold = true)
		{
			string text = FormatAmount(amount);
			string text2 = "<color=lightblue>♠</color>" + text;
			return bold ? ("<b>" + text2 + "</b>") : text2;
		}

		public static string FormatBoth(int bitties, int spades)
		{
			return FormatBitties(bitties) + "   " + FormatSpades(spades);
		}
	}
	public class BankViewModel : BaseViewModel
	{
		public static BankViewModel Instance => ViewModelRegistry.Get<BankViewModel>();

		private bool IsAnyProfileActive()
		{
			return SHGM.saveState.currentProfile != null;
		}

		public bool ProcessTransaction(ShBank.TransactionRecord record)
		{
			if (!IsAnyProfileActive())
			{
				Debug.LogWarning((object)"Try buy: No current profile found");
				return false;
			}
			bool flag = SHGM.saveState.currentProfile.bank.ProcessTransaction(record, forceDecrement: false);
			if (flag)
			{
				NotifyListeners();
			}
			return flag;
		}

		public int GetSpades()
		{
			if (!IsAnyProfileActive())
			{
				return 0;
			}
			return SHGM.saveState.currentProfile.bank.playerSpades;
		}

		public void AddSpades(int amount)
		{
			if (!IsAnyProfileActive())
			{
				Debug.LogWarning((object)"Spades: No current profile found");
			}
			else if (amount != 0)
			{
				SHGM.saveState.currentProfile.bank.IncrementSpades(amount);
				NotifyListeners();
			}
		}

		public bool TrySpendSpades(int amount)
		{
			if (!IsAnyProfileActive())
			{
				Debug.LogWarning((object)"Spades: No current profile found");
				return false;
			}
			bool flag = SHGM.saveState.currentProfile.bank.TryDecrementSpades(amount);
			if (flag)
			{
				NotifyListeners();
			}
			return flag;
		}

		public void ForceSpendSpades(int amount)
		{
			if (!IsAnyProfileActive())
			{
				Debug.LogWarning((object)"Spades: No current profile found");
				return;
			}
			SHGM.saveState.currentProfile.bank.ForceDecrementSpades(amount);
			NotifyListeners();
		}
	}
	[Serializable]
	public class ShBank
	{
		[Serializable]
		public class TransactionRecord
		{
			public int amount;

			public string description;

			public TransactionRecord(int amount, string description)
			{
				this.amount = amount;
				this.description = description;
			}
		}

		public int playerBalance;

		public List<TransactionRecord> transactions;

		public int playerSpades;

		public ShBank()
		{
			playerBalance = 0;
			transactions = new List<TransactionRecord>();
			playerSpades = 0;
		}

		public bool TryDecrementPlyBalance(int amount)
		{
			if (playerBalance >= amount)
			{
				playerBalance -= amount;
				return true;
			}
			return false;
		}

		public void ForceDecrementPlyBalance(int amount)
		{
			playerBalance -= amount;
		}

		public void IncrementPlyBalance(int amount)
		{
			playerBalance += amount;
		}

		public bool ProcessTransaction(TransactionRecord transaction, bool forceDecrement)
		{
			if (transaction.amount < 0)
			{
				if (forceDecrement)
				{
					ForceDecrementPlyBalance(-transaction.amount);
				}
				else if (!TryDecrementPlyBalance(-transaction.amount))
				{
					return false;
				}
			}
			else
			{
				IncrementPlyBalance(transaction.amount);
			}
			transactions.Insert(0, transaction);
			return true;
		}

		public bool TryDecrementSpades(int amount)
		{
			if (playerSpades >= amount)
			{
				playerSpades -= amount;
				return true;
			}
			return false;
		}

		public void ForceDecrementSpades(int amount)
		{
			playerSpades -= amount;
		}

		public void IncrementSpades(int amount)
		{
			playerSpades += amount;
		}
	}
	public class GiftMate : MonoBehaviour
	{
		public int refreshRate = 30;

		public float timeSinceRefresh = 0f;

		public int selectedIx = 0;

		public void Start()
		{
			drawGifts();
		}

		public void Update()
		{
			timeSinceRefresh += Time.deltaTime;
			if (timeSinceRefresh >= (float)refreshRate)
			{
				timeSinceRefresh = 0f;
				drawGifts();
			}
		}

		private void drawGifts()
		{
			SHGM.saveState.currentProfile.giftsList.giftsQueue.ForEach(delegate
			{
			});
		}

		public void BTN_SpawnSelected()
		{
			ShGiftsList giftsList = SHGM.saveState.currentProfile.giftsList;
			if (selectedIx >= 0 && selectedIx < giftsList.giftsQueue.Count)
			{
				giftsList.giftsQueue[selectedIx].idsToSpawn.ForEach(delegate
				{
				});
				giftsList.RemoveGift(giftsList.giftsQueue[selectedIx]);
				drawGifts();
			}
		}
	}
	[Serializable]
	public class ShGift
	{
		public string tinyMessage;

		public List<string> idsToSpawn;

		public ShGift(string tinyMessage, List<string> idsToSpawn)
		{
			this.tinyMessage = tinyMessage;
			this.idsToSpawn = idsToSpawn;
		}
	}
	[Serializable]
	public class ShGiftsList
	{
		public List<ShGift> giftsQueue;

		public ShGiftsList()
		{
			giftsQueue = new List<ShGift>();
		}

		public void AddGift(ShGift g)
		{
			giftsQueue.Add(g);
		}

		public void RemoveGift(ShGift g)
		{
			giftsQueue.Remove(g);
		}
	}
	[Serializable]
	public class BaseItemData
	{
		public float Price;

		public List<string> Tags = new List<string>();

		public string ObjectID { get; protected set; }

		public BaseItemData(string objectId, float price)
		{
			ObjectID = objectId;
			Price = price;
		}

		public override string ToString()
		{
			return string.Format("[Base Item Data] ID: {0}, Price: {1:C}, Tags: {2}", ObjectID, Price, string.Join(", ", Tags.ToArray()));
		}
	}
	[Serializable]
	public class GunData : BaseItemData
	{
		public GunData(string objectId, float price)
			: base(objectId, price)
		{
		}
	}
	public class ItemExtractedFeatures
	{
		public string Family;

		public ObjectCategory Category;

		public bool IsModContent;

		public float Mass;

		public int MagazineCapacity;

		public bool RequiresPicatinnySight;

		public OTagEra TagEra;

		public OTagSet TagSet;

		public OTagFirearmSize TagFirearmSize;

		public OTagFirearmAction TagFirearmAction;

		public OTagFirearmRoundPower TagFirearmRoundPower;

		public OTagFirearmCountryOfOrigin TagFirearmCountryOfOrigin;

		public int TagFirearmFirstYear;

		public OTagFirearmMount TagAttachmentMount;

		public OTagAttachmentFeature TagAttachmentFeature;

		public OTagMeleeStyle TagMeleeStyle;

		public OTagMeleeHandedness TagMeleeHandedness;

		public OTagPowerupType TagPowerupType;

		public OTagThrownType TagThrownType;

		public OTagThrownDamageType TagThrownDamageType;

		public List<OTagFirearmFiringMode> TagFirearmFiringModes;

		public List<OTagFirearmFeedOption> TagFirearmFeedOption;

		public List<OTagFirearmMount> TagFirearmMounts;

		public FireArmMagazineType MagazineType;

		public FireArmClipType ClipType;

		public bool UsesRoundTypeFlag;

		public FireArmRoundType RoundType;

		public List<string> CompatibleMagazines;

		public List<string> CompatibleClips;

		public List<string> CompatibleSpeedLoaders;

		public List<string> CompatibleSingleRounds;

		public List<string> BespokeAttachments;

		public List<string> RequiredSecondaryPieces;

		public int CreditCost;
	}
	internal static class ItemFeatureExtractor
	{
		internal static void TryEnrichFromFvrObject(ItemIndexRecord rec)
		{
			if (rec != null && !string.IsNullOrEmpty(rec.ItemID))
			{
				if (!IM.OD.TryGetValue(rec.ItemID, out var value) || (Object)(object)value == (Object)null)
				{
					rec.FvrObject = null;
					return;
				}
				rec.FvrObject = value;
				Extract(rec, value);
			}
		}

		private static void Extract(ItemIndexRecord rec, FVRObject fvr)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: 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_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: 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)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			rec.StringTags.Clear();
			rec.TagTokenSet.Clear();
			ItemExtractedFeatures itemExtractedFeatures = new ItemExtractedFeatures();
			itemExtractedFeatures.Family = fvr.Family;
			itemExtractedFeatures.Category = fvr.Category;
			itemExtractedFeatures.IsModContent = fvr.IsModContent;
			itemExtractedFeatures.Mass = fvr.Mass;
			itemExtractedFeatures.MagazineCapacity = fvr.MagazineCapacity;
			itemExtractedFeatures.RequiresPicatinnySight = fvr.RequiresPicatinnySight;
			itemExtractedFeatures.TagEra = fvr.TagEra;
			itemExtractedFeatures.TagSet = fvr.TagSet;
			itemExtractedFeatures.TagFirearmSize = fvr.TagFirearmSize;
			itemExtractedFeatures.TagFirearmAction = fvr.TagFirearmAction;
			itemExtractedFeatures.TagFirearmRoundPower = fvr.TagFirearmRoundPower;
			itemExtractedFeatures.TagFirearmCountryOfOrigin = fvr.TagFirearmCountryOfOrigin;
			itemExtractedFeatures.TagFirearmFirstYear = fvr.TagFirearmFirstYear;
			itemExtractedFeatures.TagAttachmentMount = fvr.TagAttachmentMount;
			itemExtractedFeatures.TagAttachmentFeature = fvr.TagAttachmentFeature;
			itemExtractedFeatures.TagMeleeStyle = fvr.TagMeleeStyle;
			itemExtractedFeatures.TagMeleeHandedness = fvr.TagMeleeHandedness;
			itemExtractedFeatures.TagPowerupType = fvr.TagPowerupType;
			itemExtractedFeatures.TagThrownType = fvr.TagThrownType;
			itemExtractedFeatures.TagThrownDamageType = fvr.TagThrownDamageType;
			itemExtractedFeatures.TagFirearmFiringModes = ((fvr.TagFirearmFiringModes != null) ? new List<OTagFirearmFiringMode>(fvr.TagFirearmFiringModes) : null);
			itemExtractedFeatures.TagFirearmFeedOption = ((fvr.TagFirearmFeedOption != null) ? new List<OTagFirearmFeedOption>(fvr.TagFirearmFeedOption) : null);
			itemExtractedFeatures.TagFirearmMounts = ((fvr.TagFirearmMounts != null) ? new List<OTagFirearmMount>(fvr.TagFirearmMounts) : null);
			itemExtractedFeatures.MagazineType = fvr.MagazineType;
			itemExtractedFeatures.ClipType = fvr.ClipType;
			itemExtractedFeatures.UsesRoundTypeFlag = fvr.UsesRoundTypeFlag;
			itemExtractedFeatures.RoundType = fvr.RoundType;
			itemExtractedFeatures.CreditCost = fvr.CreditCost;
			itemExtractedFeatures.CompatibleMagazines = ExtractIds(fvr.CompatibleMagazines);
			itemExtractedFeatures.CompatibleClips = ExtractIds(fvr.CompatibleClips);
			itemExtractedFeatures.CompatibleSpeedLoaders = ExtractIds(fvr.CompatibleSpeedLoaders);
			itemExtractedFeatures.CompatibleSingleRounds = ExtractIds(fvr.CompatibleSingleRounds);
			itemExtractedFeatures.BespokeAttachments = ExtractIds(fvr.BespokeAttachments);
			itemExtractedFeatures.RequiredSecondaryPieces = ExtractIds(fvr.RequiredSecondaryPieces);
			rec.Features = itemExtractedFeatures;
			AddEnumTag(rec, "Era", itemExtractedFeatures.TagEra);
			AddEnumTag(rec, "Set", itemExtractedFeatures.TagSet);
			AddEnumTag(rec, "FirearmSize", itemExtractedFeatures.TagFirearmSize);
			AddEnumTag(rec, "FirearmAction", itemExtractedFeatures.TagFirearmAction);
			AddEnumTag(rec, "FirearmRoundPower", itemExtractedFeatures.TagFirearmRoundPower);
			AddEnumTag(rec, "Country", itemExtractedFeatures.TagFirearmCountryOfOrigin);
			AddEnumTag(rec, "AttachmentMount", itemExtractedFeatures.TagAttachmentMount);
			AddEnumTag(rec, "AttachmentFeature", itemExtractedFeatures.TagAttachmentFeature);
			AddEnumTag(rec, "MeleeStyle", itemExtractedFeatures.TagMeleeStyle);
			AddEnumTag(rec, "MeleeHandedness", itemExtractedFeatures.TagMeleeHandedness);
			AddEnumTag(rec, "PowerupType", itemExtractedFeatures.TagPowerupType);
			AddEnumTag(rec, "ThrownType", itemExtractedFeatures.TagThrownType);
			AddEnumTag(rec, "ThrownDamage", itemExtractedFeatures.TagThrownDamageType);
			if (itemExtractedFeatures.TagFirearmFirstYear > 0)
			{
				AddStringTag(rec, "Year_" + itemExtractedFeatures.TagFirearmFirstYear);
			}
			if (itemExtractedFeatures.TagFirearmFiringModes != null)
			{
				for (int i = 0; i < itemExtractedFeatures.TagFirearmFiringModes.Count; i++)
				{
					AddEnumTag(rec, "FiringMode", itemExtractedFeatures.TagFirearmFiringModes[i]);
				}
			}
			if (itemExtractedFeatures.TagFirearmFeedOption != null)
			{
				for (int j = 0; j < itemExtractedFeatures.TagFirearmFeedOption.Count; j++)
				{
					AddEnumTag(rec, "FeedOption", itemExtractedFeatures.TagFirearmFeedOption[j]);
				}
			}
			if (itemExtractedFeatures.TagFirearmMounts != null)
			{
				for (int k = 0; k < itemExtractedFeatures.TagFirearmMounts.Count; k++)
				{
					AddEnumTag(rec, "FirearmMount", itemExtractedFeatures.TagFirearmMounts[k]);
				}
			}
			AddStringTag(rec, "RoundType_" + ((object)(FireArmRoundType)(ref itemExtractedFeatures.RoundType)).ToString());
			AddStringTag(rec, "MagazineType_" + ((object)(FireArmMagazineType)(ref itemExtractedFeatures.MagazineType)).ToString());
			AddStringTag(rec, "ClipType_" + ((object)(FireArmClipType)(ref itemExtractedFeatures.ClipType)).ToString());
			AddStringTag(rec, "AttachmentMount_" + ((object)(OTagFirearmMount)(ref itemExtractedFeatures.TagAttachmentMount)).ToString());
			if (rec.Data != null)
			{
				rec.Data.Tags.Clear();
				rec.Data.Tags.AddRange(rec.StringTags);
			}
		}

		private static List<string> ExtractIds(List<FVRObject> objs)
		{
			if (objs == null || objs.Count == 0)
			{
				return null;
			}
			List<string> list = new List<string>(objs.Count);
			for (int i = 0; i < objs.Count; i++)
			{
				FVRObject val = objs[i];
				if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(val.ItemID))
				{
					list.Add(val.ItemID);
				}
			}
			return list;
		}

		private static void AddEnumTag(ItemIndexRecord rec, string prefix, object enumValue)
		{
			if (enumValue != null)
			{
				string text = enumValue.ToString();
				if (!string.Equals(text, "None", StringComparison.OrdinalIgnoreCase))
				{
					AddStringTag(rec, prefix + "_" + text);
				}
			}
		}

		private static void AddStringTag(ItemIndexRecord rec, string tag)
		{
			if (!string.IsNullOrEmpty(tag))
			{
				string text = tag.Trim();
				if (text.Length != 0)
				{
					rec.StringTags.Add(text);
					rec.TagTokenSet.Add(ItemToken.StableToken(text));
				}
			}
		}
	}
	public static class ItemIndex
	{
		[Serializable]
		public sealed class FilterRequest
		{
			public string ItemID;

			public string Family;

			public ObjectCategory? Category;

			public OTagEra? TagEra;

			public OTagSet? TagSet;

			public OTagFirearmSize? TagFirearmSize;

			public OTagFirearmAction? TagFirearmAction;

			public OTagFirearmRoundPower? TagFirearmRoundPower;

			public OTagFirearmCountryOfOrigin? TagFirearmCountryOfOrigin;

			public OTagFirearmMount? TagAttachmentMount;

			public OTagAttachmentFeature? TagAttachmentFeature;

			public OTagMeleeStyle? TagMeleeStyle;

			public OTagMeleeHandedness? TagMeleeHandedness;

			public OTagPowerupType? TagPowerupType;

			public OTagThrownType? TagThrownType;

			public OTagThrownDamageType? TagThrownDamageType;

			public int? FirearmFirstYearMin;

			public int? FirearmFirstYearMax;

			public float? MassMin;

			public float? MassMax;

			public FireArmRoundType? RoundType;

			public FireArmMagazineType? MagazineType;

			public FireArmClipType? ClipType;

			public List<OTagFirearmFiringMode> RequireAnyFiringModes;

			public List<OTagFirearmFeedOption> RequireAnyFeedOptions;

			public List<OTagFirearmMount> RequireAnyFirearmMounts;

			public List<string> RequireAllStringTags;

			public List<string> RequireAnyStringTags;

			public bool? IsModContent;

			public int MaxResults = 100;
		}

		public struct SimilarityResult
		{
			public string ItemID;

			public float Score;

			public BaseItemData Data;
		}

		public static void Clear()
		{
			ItemIndexStore.Clear();
		}

		public static void AddOrUpdateItem(BaseItemData item)
		{
			if (item != null && !string.IsNullOrEmpty(item.ObjectID))
			{
				ItemIndexRecord orCreate = ItemIndexStore.GetOrCreate(item.ObjectID);
				orCreate.Data = item;
				ItemFeatureExtractor.TryEnrichFromFvrObject(orCreate);
				ItemIndexStore.Commit(orCreate);
			}
		}

		public static void AddOrUpdateItem(string itemId)
		{
			if (!string.IsNullOrEmpty(itemId))
			{
				ItemIndexRecord orCreate = ItemIndexStore.GetOrCreate(itemId);
				if (orCreate.Data == null)
				{
					orCreate.Data = new BaseItemData(itemId, 0f);
				}
				ItemFeatureExtractor.TryEnrichFromFvrObject(orCreate);
				ItemIndexStore.Commit(orCreate);
			}
		}

		public static void AddItems(List<string> objectIds)
		{
			if (objectIds != null)
			{
				for (int i = 0; i < objectIds.Count; i++)
				{
					AddOrUpdateItem(objectIds[i]);
				}
			}
		}

		public static void AddItems(List<BaseItemData> items)
		{
			if (items != null)
			{
				for (int i = 0; i < items.Count; i++)
				{
					AddOrUpdateItem(items[i]);
				}
			}
		}

		public static void EnsureIndexed(string itemId)
		{
			if (!string.IsNullOrEmpty(itemId) && !ItemIndexStore.Contains(itemId))
			{
				AddOrUpdateItem(new BaseItemData(itemId, 0f));
			}
		}

		public static ItemExtractedFeatures GetItemFeatures(string itemId)
		{
			if (string.IsNullOrEmpty(itemId))
			{
				return null;
			}
			ItemIndexStore.TryGet(itemId, out var rec);
			return rec?.Features;
		}

		public static List<BaseItemData> Query(FilterRequest request)
		{
			return ItemQueryEngine.Query(request);
		}

		public static List<SimilarityResult> FindNearestNeighbors(string seedItemId, int k = 10)
		{
			return ItemSimilarityEngine.FindNearestNeighbors(seedItemId, k);
		}

		public static float PredictPrice(string seedItemId, int k = 5)
		{
			return ItemSimilarityEngine.PredictPrice(seedItemId, k);
		}

		public static List<BaseItemData> FindByItemId(string itemId)
		{
			if (string.IsNullOrEmpty(itemId))
			{
				return new List<BaseItemData>(0);
			}
			return Query(new FilterRequest
			{
				ItemID = itemId,
				MaxResults = 1
			});
		}

		public static List<BaseItemData> FindByCategory(ObjectCategory category, int maxResults = 100)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return Query(new FilterRequest
			{
				Category = category,
				MaxResults = maxResults
			});
		}

		public static List<BaseItemData> FindByFamily(string family, int maxResults = 100)
		{
			return Query(new FilterRequest
			{
				Family = family,
				MaxResults = maxResults
			});
		}

		public static List<BaseItemData> FindByEra(OTagEra era, int maxResults = 100)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return Query(new FilterRequest
			{
				TagEra = era,
				MaxResults = maxResults
			});
		}

		public static List<BaseItemData> FindBySet(OTagSet set, int maxResults = 100)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return Query(new FilterRequest
			{
				TagSet = set,
				MaxResults = maxResults
			});
		}

		public static List<BaseItemData> FindByRoundType(FireArmRoundType roundType, int maxResults = 100)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return Query(new FilterRequest
			{
				RoundType = roundType,
				MaxResults = maxResults
			});
		}

		public static List<BaseItemData> FindByMagazineType(FireArmMagazineType magazineType, int maxResults = 100)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return Query(new FilterRequest
			{
				MagazineType = magazineType,
				MaxResults = maxResults
			});
		}

		public static List<BaseItemData> FindByClipType(FireArmClipType clipType, int maxResults = 100)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return Query(new FilterRequest
			{
				ClipType = clipType,
				MaxResults = maxResults
			});
		}

		public static List<BaseItemData> FindByFirstYearRange(int minInclusive, int maxInclusive, int maxResults = 100)
		{
			return Query(new FilterRequest
			{
				FirearmFirstYearMin = minInclusive,
				FirearmFirstYearMax = maxInclusive,
				MaxResults = maxResults
			});
		}

		public static List<BaseItemData> FindByTagsAll(int maxResults, params string[] tags)
		{
			FilterRequest filterRequest = new FilterRequest
			{
				MaxResults = maxResults,
				RequireAllStringTags = new List<string>()
			};
			if (tags != null)
			{
				for (int i = 0; i < tags.Length; i++)
				{
					if (!string.IsNullOrEmpty(tags[i]))
					{
						filterRequest.RequireAllStringTags.Add(tags[i]);
					}
				}
			}
			if (filterRequest.RequireAllStringTags.Count == 0)
			{
				filterRequest.RequireAllStringTags = null;
			}
			return Query(filterRequest);
		}

		public static List<BaseItemData> FindByTagsAny(int maxResults, params string[] tags)
		{
			FilterRequest filterRequest = new FilterRequest
			{
				MaxResults = maxResults,
				RequireAnyStringTags = new List<string>()
			};
			if (tags != null)
			{
				for (int i = 0; i < tags.Length; i++)
				{
					if (!string.IsNullOrEmpty(tags[i]))
					{
						filterRequest.RequireAnyStringTags.Add(tags[i]);
					}
				}
			}
			if (filterRequest.RequireAnyStringTags.Count == 0)
			{
				filterRequest.RequireAnyStringTags = null;
			}
			return Query(filterRequest);
		}

		public static List<BaseItemData> FindByAnyFiringMode(int maxResults, params OTagFirearmFiringMode[] modes)
		{
			FilterRequest filterRequest = new FilterRequest
			{
				MaxResults = maxResults,
				RequireAnyFiringModes = new List<OTagFirearmFiringMode>()
			};
			if (modes != null)
			{
				for (int i = 0; i < modes.Length; i++)
				{
					filterRequest.RequireAnyFiringModes.Add(modes[i]);
				}
			}
			if (filterRequest.RequireAnyFiringModes.Count == 0)
			{
				filterRequest.RequireAnyFiringModes = null;
			}
			return Query(filterRequest);
		}

		public static HashSet<string> GetIdsByCategoryCopy(ObjectCategory category)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			HashSet<string> byCategory = ItemIndexStore.GetByCategory(category);
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			foreach (string item in byCategory)
			{
				hashSet.Add(item);
			}
			return hashSet;
		}

		public static HashSet<string> GetIdsByFamilyCopy(string family)
		{
			HashSet<string> byFamily = ItemIndexStore.GetByFamily(family);
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			foreach (string item in byFamily)
			{
				hashSet.Add(item);
			}
			return hashSet;
		}

		public static HashSet<string> GetIdsByStringTagCopy(string tag)
		{
			int tok = ItemToken.StableToken(tag);
			HashSet<string> byTagToken = ItemIndexStore.GetByTagToken(tok);
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			foreach (string item in byTagToken)
			{
				hashSet.Add(item);
			}
			return hashSet;
		}

		public static bool TryGetIndexedPrice(string itemId, out float price)
		{
			price = 0f;
			if (string.IsNullOrEmpty(itemId))
			{
				return false;
			}
			if (!ItemIndexStore.TryGet(itemId, out var rec))
			{
				return false;
			}
			if (rec.Data == null)
			{
				return false;
			}
			price = rec.Data.Price;
			return true;
		}

		public static void OverrideIndexedPrice(string itemId, float newPrice)
		{
			if (!string.IsNullOrEmpty(itemId))
			{
				ItemIndexRecord orCreate = ItemIndexStore.GetOrCreate(itemId);
				if (orCreate.Data == null)
				{
					orCreate.Data = new BaseItemData(itemId, newPrice);
					ItemIndexStore.Commit(orCreate);
				}
				else
				{
					orCreate.Data.Price = newPrice;
					ItemIndexStore.Commit(orCreate);
				}
			}
		}
	}
	internal sealed class ItemIndexRecord
	{
		public string ItemID;

		public BaseItemData Data;

		public FVRObject FvrObject;

		public ItemExtractedFeatures Features;

		public readonly List<string> StringTags = new List<string>(32);

		public readonly HashSet<int> TagTokenSet = new HashSet<int>();
	}
	internal static class ItemIndexStore
	{
		private static readonly Dictionary<string, ItemIndexRecord> _recordsById = new Dictionary<string, ItemIndexRecord>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<ObjectCategory, HashSet<string>> _byCategory = new Dictionary<ObjectCategory, HashSet<string>>();

		private static readonly Dictionary<string, HashSet<string>> _byFamily = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<int, HashSet<string>> _byTagToken = new Dictionary<int, HashSet<string>>();

		internal static void Clear()
		{
			_recordsById.Clear();
			_byCategory.Clear();
			_byFamily.Clear();
			_byTagToken.Clear();
		}

		internal static bool Contains(string itemId)
		{
			return _recordsById.ContainsKey(itemId);
		}

		internal static bool TryGet(string itemId, out ItemIndexRecord rec)
		{
			return _recordsById.TryGetValue(itemId, out rec);
		}

		internal static ItemIndexRecord GetOrCreate(string itemId)
		{
			if (_recordsById.TryGetValue(itemId, out var value))
			{
				return value;
			}
			value = new ItemIndexRecord
			{
				ItemID = itemId
			};
			_recordsById[itemId] = value;
			return value;
		}

		internal static void Commit(ItemIndexRecord rec)
		{
			_recordsById[rec.ItemID] = rec;
			ReindexAppendOnly(rec);
		}

		internal static IEnumerable<KeyValuePair<string, ItemIndexRecord>> EnumerateAll()
		{
			return _recordsById;
		}

		internal static HashSet<string> GetAllIds()
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			foreach (KeyValuePair<string, ItemIndexRecord> item in _recordsById)
			{
				hashSet.Add(item.Key);
			}
			return hashSet;
		}

		internal static HashSet<string> GetByCategory(ObjectCategory cat)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			HashSet<string> value;
			return _byCategory.TryGetValue(cat, out value) ? value : new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		}

		internal static HashSet<string> GetByFamily(string family)
		{
			if (string.IsNullOrEmpty(family))
			{
				return new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			}
			HashSet<string> value;
			return _byFamily.TryGetValue(family, out value) ? value : new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		}

		internal static HashSet<string> GetByTagToken(int tok)
		{
			HashSet<string> value;
			return _byTagToken.TryGetValue(tok, out value) ? value : new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		}

		internal static HashSet<string> IntersectCandidates(HashSet<string> current, HashSet<string> next)
		{
			if (current == null)
			{
				HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
				foreach (string item in next)
				{
					hashSet.Add(item);
				}
				return hashSet;
			}
			if (current.Count == 0)
			{
				return current;
			}
			List<string> list = new List<string>();
			foreach (string item2 in current)
			{
				if (!next.Contains(item2))
				{
					list.Add(item2);
				}
			}
			for (int i = 0; i < list.Count; i++)
			{
				current.Remove(list[i]);
			}
			return current;
		}

		private static void ReindexAppendOnly(ItemIndexRecord rec)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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)
			if (rec == null)
			{
				return;
			}
			ItemExtractedFeatures features = rec.Features;
			string itemID = rec.ItemID;
			if (string.IsNullOrEmpty(itemID))
			{
				return;
			}
			if (features != null)
			{
				ObjectCategory category = features.Category;
				if (!_byCategory.TryGetValue(category, out var value))
				{
					value = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
					_byCategory[category] = value;
				}
				value.Add(itemID);
			}
			string text = features?.Family;
			if (!string.IsNullOrEmpty(text))
			{
				if (!_byFamily.TryGetValue(text, out var value2))
				{
					value2 = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
					_byFamily[text] = value2;
				}
				value2.Add(itemID);
			}
			HashSet<int> tagTokenSet = rec.TagTokenSet;
			if (tagTokenSet == null)
			{
				return;
			}
			foreach (int item in tagTokenSet)
			{
				if (!_byTagToken.TryGetValue(item, out var value3))
				{
					value3 = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
					_byTagToken[item] = value3;
				}
				value3.Add(itemID);
			}
		}
	}
	internal static class ItemQueryEngine
	{
		internal static List<BaseItemData> Query(ItemIndex.FilterRequest request)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (request == null)
			{
				return new List<BaseItemData>(0);
			}
			HashSet<string> hashSet = null;
			if (request.Category.HasValue)
			{
				hashSet = ItemIndexStore.IntersectCandidates(hashSet, ItemIndexStore.GetByCategory(request.Category.Value));
			}
			if (!string.IsNullOrEmpty(request.Family))
			{
				hashSet = ItemIndexStore.IntersectCandidates(hashSet, ItemIndexStore.GetByFamily(request.Family));
			}
			if (request.RequireAllStringTags != null && request.RequireAllStringTags.Count > 0)
			{
				for (int i = 0; i < request.RequireAllStringTags.Count; i++)
				{
					int tok = ItemToken.StableToken(request.RequireAllStringTags[i]);
					hashSet = ItemIndexStore.IntersectCandidates(hashSet, ItemIndexStore.GetByTagToken(tok));
					if (hashSet != null && hashSet.Count == 0)
					{
						break;
					}
				}
			}
			if (hashSet == null)
			{
				hashSet = ItemIndexStore.GetAllIds();
			}
			List<BaseItemData> list = new List<BaseItemData>(Math.Max(0, request.MaxResults));
			foreach (string item in hashSet)
			{
				if (ItemIndexStore.TryGet(item, out var rec) && Matches(request, rec))
				{
					if (rec.Data != null)
					{
						list.Add(rec.Data);
					}
					if (list.Count >= request.MaxResults)
					{
						break;
					}
				}
			}
			return list;
		}

		private static bool Matches(ItemIndex.FilterRequest req, ItemIndexRecord rec)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: 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_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0438: Unknown result type (might be due to invalid IL or missing references)
			//IL_043e: Unknown result type (might be due to invalid IL or missing references)
			//IL_046b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0471: Unknown result type (might be due to invalid IL or missing references)
			//IL_049e: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a4: Unknown result type (might be due to invalid IL or missing references)
			ItemExtractedFeatures features = rec.Features;
			if (!string.IsNullOrEmpty(req.ItemID) && !string.Equals(req.ItemID, rec.ItemID, StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			if (!string.IsNullOrEmpty(req.Family) && !string.Equals(req.Family, features.Family, StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			if (req.Category.HasValue && req.Category.Value != features.Category)
			{
				return false;
			}
			if (req.IsModContent.HasValue && req.IsModContent.Value != features.IsModContent)
			{
				return false;
			}
			if (req.TagEra.HasValue && req.TagEra.Value != features.TagEra)
			{
				return false;
			}
			if (req.TagSet.HasValue && req.TagSet.Value != features.TagSet)
			{
				return false;
			}
			if (req.TagFirearmSize.HasValue && req.TagFirearmSize.Value != features.TagFirearmSize)
			{
				return false;
			}
			if (req.TagFirearmAction.HasValue && req.TagFirearmAction.Value != features.TagFirearmAction)
			{
				return false;
			}
			if (req.TagFirearmRoundPower.HasValue && req.TagFirearmRoundPower.Value != features.TagFirearmRoundPower)
			{
				return false;
			}
			if (req.TagFirearmCountryOfOrigin.HasValue && req.TagFirearmCountryOfOrigin.Value != features.TagFirearmCountryOfOrigin)
			{
				return false;
			}
			if (req.TagAttachmentMount.HasValue && req.TagAttachmentMount.Value != features.TagAttachmentMount)
			{
				return false;
			}
			if (req.TagAttachmentFeature.HasValue && req.TagAttachmentFeature.Value != features.TagAttachmentFeature)
			{
				return false;
			}
			if (req.TagMeleeStyle.HasValue && req.TagMeleeStyle.Value != features.TagMeleeStyle)
			{
				return false;
			}
			if (req.TagMeleeHandedness.HasValue && req.TagMeleeHandedness.Value != features.TagMeleeHandedness)
			{
				return false;
			}
			if (req.TagPowerupType.HasValue && req.TagPowerupType.Value != features.TagPowerupType)
			{
				return false;
			}
			if (req.TagThrownType.HasValue && req.TagThrownType.Value != features.TagThrownType)
			{
				return false;
			}
			if (req.TagThrownDamageType.HasValue && req.TagThrownDamageType.Value != features.TagThrownDamageType)
			{
				return false;
			}
			if (req.FirearmFirstYearMin.HasValue && features.TagFirearmFirstYear < req.FirearmFirstYearMin.Value)
			{
				return false;
			}
			if (req.FirearmFirstYearMax.HasValue && features.TagFirearmFirstYear > req.FirearmFirstYearMax.Value)
			{
				return false;
			}
			if (req.MassMin.HasValue && features.Mass < req.MassMin.Value)
			{
				return false;
			}
			if (req.MassMax.HasValue && features.Mass > req.MassMax.Value)
			{
				return false;
			}
			if (req.RoundType.HasValue && req.RoundType.Value != features.RoundType)
			{
				return false;
			}
			if (req.MagazineType.HasValue && req.MagazineType.Value != features.MagazineType)
			{
				return false;
			}
			if (req.ClipType.HasValue && req.ClipType.Value != features.ClipType)
			{
				return false;
			}
			if (req.RequireAnyFiringModes != null && req.RequireAnyFiringModes.Count > 0)
			{
				if (features.TagFirearmFiringModes == null || features.TagFirearmFiringModes.Count == 0)
				{
					return false;
				}
				if (!OverlapsAny(req.RequireAnyFiringModes, features.TagFirearmFiringModes))
				{
					return false;
				}
			}
			if (req.RequireAnyFeedOptions != null && req.RequireAnyFeedOptions.Count > 0)
			{
				if (features.TagFirearmFeedOption == null || features.TagFirearmFeedOption.Count == 0)
				{
					return false;
				}
				if (!OverlapsAny(req.RequireAnyFeedOptions, features.TagFirearmFeedOption))
				{
					return false;
				}
			}
			if (req.RequireAnyFirearmMounts != null && req.RequireAnyFirearmMounts.Count > 0)
			{
				if (features.TagFirearmMounts == null || features.TagFirearmMounts.Count == 0)
				{
					return false;
				}
				if (!OverlapsAny(req.RequireAnyFirearmMounts, features.TagFirearmMounts))
				{
					return false;
				}
			}
			if (req.RequireAnyStringTags != null && req.RequireAnyStringTags.Count > 0)
			{
				bool flag = false;
				for (int i = 0; i < req.RequireAnyStringTags.Count; i++)
				{
					int item = ItemToken.StableToken(req.RequireAnyStringTags[i]);
					if (rec.TagTokenSet.Contains(item))
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					return false;
				}
			}
			if (req.RequireAllStringTags != null && req.RequireAllStringTags.Count > 0)
			{
				for (int j = 0; j < req.RequireAllStringTags.Count; j++)
				{
					int item2 = ItemToken.StableToken(req.RequireAllStringTags[j]);
					if (!rec.TagTokenSet.Contains(item2))
					{
						return false;
					}
				}
			}
			return true;
		}

		private static bool OverlapsAny<T>(List<T> requiredAny, List<T> actual)
		{
			for (int i = 0; i < requiredAny.Count; i++)
			{
				T x = requiredAny[i];
				for (int j = 0; j < actual.Count; j++)
				{
					if (EqualityComparer<T>.Default.Equals(x, actual[j]))
					{
						return true;
					}
				}
			}
			return false;
		}
	}
	internal static class ItemSimilarityEngine
	{
		internal static List<ItemIndex.SimilarityResult> FindNearestNeighbors(string seedItemId, int k)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(seedItemId))
			{
				return new List<ItemIndex.SimilarityResult>(0);
			}
			if (!ItemIndexStore.TryGet(seedItemId, out var rec))
			{
				ItemIndex.EnsureIndexed(seedItemId);
				if (!ItemIndexStore.TryGet(seedItemId, out rec))
				{
					return new List<ItemIndex.SimilarityResult>(0);
				}
			}
			ItemSimilarityProfile profile = GetProfile(rec);
			HashSet<string> hashSet = null;
			if (profile.RequireSameCategory)
			{
				hashSet = ItemIndexStore.IntersectCandidates(hashSet, ItemIndexStore.GetByCategory(rec.Features.Category));
			}
			if ((Object)(object)rec.FvrObject != (Object)null)
			{
				if (profile.RequireSameRoundTypeForFirearms)
				{
					hashSet = ItemIndexStore.IntersectCandidates(hashSet, ItemIndexStore.GetByTagToken(ItemToken.StableToken("RoundType_" + ((object)(FireArmRoundType)(ref rec.Features.RoundType)).ToString())));
				}
				if (profile.RequireSameAttachmentMountForAttachments)
				{
					hashSet = ItemIndexStore.IntersectCandidates(hashSet, ItemIndexStore.GetByTagToken(ItemToken.StableToken("AttachmentMount_" + ((object)(OTagFirearmMount)(ref rec.Features.TagAttachmentMount)).ToString())));
				}
			}
			if (hashSet == null)
			{
				hashSet = ItemIndexStore.GetAllIds();
			}
			List<ItemIndex.SimilarityResult> list = new List<ItemIndex.SimilarityResult>(Mathf.Min(Mathf.Max(8, k * 8), hashSet.Count));
			foreach (string item in hashSet)
			{
				if (!string.Equals(item, seedItemId, StringComparison.OrdinalIgnoreCase) && ItemIndexStore.TryGet(item, out var rec2))
				{
					float num = ScoreSimilarity(rec, rec2, profile);
					if (!(num <= 0f))
					{
						list.Add(new ItemIndex.SimilarityResult
						{
							ItemID = item,
							Score = num,
							Data = rec2.Data
						});
					}
				}
			}
			list.Sort((ItemIndex.SimilarityResult a, ItemIndex.SimilarityResult b) => b.Score.CompareTo(a.Score));
			if (k < 1)
			{
				k = 1;
			}
			if (list.Count > k)
			{
				list.RemoveRange(k, list.Count - k);
			}
			return list;
		}

		internal static float PredictPrice(string seedItemId, int k = 3)
		{
			List<ItemIndex.SimilarityResult> list = FindNearestNeighbors(seedItemId, Mathf.Max(1, k * 3));
			float num = 0f;
			int num2 = 0;
			for (int i = 0; i < list.Count; i++)
			{
				BaseItemData data = list[i].Data;
				if (data != null && !(data.Price <= 0f))
				{
					num += data.Price;
					num2++;
					if (num2 >= k)
					{
						break;
					}
				}
			}
			return (num2 == 0) ? 0f : (num / (float)num2);
		}

		private static ItemSimilarityProfile GetProfile(ItemIndexRecord seed)
		{
			return ItemSimilarityPolicy.Default;
		}

		private static float ScoreSimilarity(ItemIndexRecord a, ItemIndexRecord b, ItemSimilarityProfile p)
		{
			//IL_000d: 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_007d: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			if (a.Features.Category == b.Features.Category)
			{
				num += p.WeightCategory;
			}
			if (!string.IsNullOrEmpty(a.Features.Family) && string.Equals(a.Features.Family, b.Features.Family, StringComparison.OrdinalIgnoreCase))
			{
				num += p.WeightFamily;
			}
			if (((object)(OTagEra)(ref a.Features.TagEra)).Equals((object?)b.Features.TagEra))
			{
				num += p.WeightEra;
			}
			if (((object)(OTagSet)(ref a.Features.TagSet)).Equals((object?)b.Features.TagSet))
			{
				num += p.WeightSet;
			}
			if (((object)(OTagFirearmAction)(ref a.Features.TagFirearmAction)).Equals((object?)b.Features.TagFirearmAction))
			{
				num += p.WeightAction;
			}
			if (((object)(OTagFirearmSize)(ref a.Features.TagFirearmSize)).Equals((object?)b.Features.TagFirearmSize))
			{
				num += p.WeightSize;
			}
			if (((object)(OTagFirearmRoundPower)(ref a.Features.TagFirearmRoundPower)).Equals((object?)b.Features.TagFirearmRoundPower))
			{
				num += p.WeightRoundPower;
			}
			if (((object)(OTagFirearmCountryOfOrigin)(ref a.Features.TagFirearmCountryOfOrigin)).Equals((object?)b.Features.TagFirearmCountryOfOrigin))
			{
				num += p.WeightCountry;
			}
			if (((object)(OTagFirearmMount)(ref a.Features.TagAttachmentMount)).Equals((object?)b.Features.TagAttachmentMount))
			{
				num += p.WeightAttachmentMount;
			}
			if (((object)(FireArmRoundType)(ref a.Features.RoundType)).Equals((object?)b.Features.RoundType))
			{
				num += p.WeightRoundType;
			}
			if (a.Features.TagFirearmFirstYear > 0 && b.Features.TagFirearmFirstYear > 0)
			{
				int num2 = Mathf.Abs(a.Features.TagFirearmFirstYear - b.Features.TagFirearmFirstYear);
				float num3 = 1f / (1f + (float)num2 / Mathf.Max(1f, p.FirstYearScale));
				num += num3 * p.WeightFirstYear;
			}
			num += OverlapScore(a.Features.TagFirearmFiringModes, b.Features.TagFirearmFiringModes) * p.WeightFiringModes;
			num += OverlapScore(a.Features.TagFirearmFeedOption, b.Features.TagFirearmFeedOption) * p.WeightFeedOptions;
			num += OverlapScore(a.Features.TagFirearmMounts, b.Features.TagFirearmMounts) * p.WeightMounts;
			num += CompatibilityOverlapScore(a.Features, b.Features) * p.WeightCompatibility;
			if (a.TagTokenSet.Count > 0 && b.TagTokenSet.Count > 0)
			{
				int num4 = 0;
				if (a.TagTokenSet.Count <= b.TagTokenSet.Count)
				{
					foreach (int item in a.TagTokenSet)
					{
						if (b.TagTokenSet.Contains(item))
						{
							num4++;
						}
					}
				}
				else
				{
					foreach (int item2 in b.TagTokenSet)
					{
						if (a.TagTokenSet.Contains(item2))
						{
							num4++;
						}
					}
				}
				int num5 = Mathf.Max(1, Mathf.Min(a.TagTokenSet.Count, b.TagTokenSet.Count));
				float num6 = (float)num4 / (float)num5;
				num += num6 * p.WeightStringTags;
			}
			return num;
		}

		private static float OverlapScore<T>(List<T> a, List<T> b)
		{
			if (a == null || b == null)
			{
				return 0f;
			}
			if (a.Count == 0 || b.Count == 0)
			{
				return 0f;
			}
			int num = 0;
			for (int i = 0; i < a.Count; i++)
			{
				T x = a[i];
				for (int j = 0; j < b.Count; j++)
				{
					if (EqualityComparer<T>.Default.Equals(x, b[j]))
					{
						num++;
						break;
					}
				}
			}
			int num2 = Mathf.Max(1, Mathf.Min(a.Count, b.Count));
			return (float)num / (float)num2;
		}

		private static float CompatibilityOverlapScore(ItemExtractedFeatures a, ItemExtractedFeatures b)
		{
			int num = 0;
			int denom = 0;
			num += OverlapCount(a.CompatibleMagazines, b.CompatibleMagazines, ref denom);
			num += OverlapCount(a.CompatibleClips, b.CompatibleClips, ref denom);
			num += OverlapCount(a.CompatibleSpeedLoaders, b.CompatibleSpeedLoaders, ref denom);
			num += OverlapCount(a.CompatibleSingleRounds, b.CompatibleSingleRounds, ref denom);
			num += OverlapCount(a.BespokeAttachments, b.BespokeAttachments, ref denom);
			return (denom <= 0) ? 0f : ((float)num / (float)denom);
		}

		private static int OverlapCount(List<string> a, List<string> b, ref int denom)
		{
			if (a == null || b == null)
			{
				return 0;
			}
			if (a.Count == 0 || b.Count == 0)
			{
				return 0;
			}
			denom += Mathf.Max(1, Mathf.Min(a.Count, b.Count));
			int num = 0;
			for (int i = 0; i < a.Count; i++)
			{
				string a2 = a[i];
				for (int j = 0; j < b.Count; j++)
				{
					if (string.Equals(a2, b[j], StringComparison.OrdinalIgnoreCase))
					{
						num++;
						break;
					}
				}
			}
			return num;
		}
	}
	internal sealed class ItemSimilarityProfile
	{
		public bool RequireSameCategory = true;

		public bool RequireSameRoundTypeForFirearms = false;

		public bool RequireSameAttachmentMountForAttachments = false;

		public float WeightCategory = 5f;

		public float WeightFamily = 4f;

		public float WeightSet = 4f;

		public float WeightRoundPower = 3f;

		public float WeightRoundType = 3f;

		public float WeightFirstYear = 2f;

		public float FirstYearScale = 25f;

		public float WeightEra = 2f;

		public float WeightStringTags = 2f;

		public float WeightAction = 2f;

		public float WeightFiringModes = 2f;

		public float WeightCountry = 1f;

		public float WeightFeedOptions = 1f;

		public float WeightMounts = 1f;

		public float WeightCompatibility = 0f;

		public float WeightAttachmentMount = 0f;

		public float WeightSize = 0f;
	}
	internal static class ItemSimilarityPolicy
	{
		internal static readonly ItemSimilarityProfile Default = new ItemSimilarityProfile();
	}
	internal static class ItemToken
	{
		internal static int StableToken(string s)
		{
			if (s == null)
			{
				return 0;
			}
			int num = 23;
			for (int i = 0; i < s.Length; i++)
			{
				char c = char.ToLowerInvariant(s[i]);
				num = num * 31 + c;
			}
			return num;
		}
	}
	public static class CsvItemPriceLoader
	{
		public static List<BaseItemData> LoadBaseItems(string relativePath)
		{
			List<BaseItemData> list = new List<BaseItemData>();
			string text = Path.Combine(ShFileIoHandler.GetPluginModFolder(), relativePath);
			if (!File.Exists(text))
			{
				Debug.LogError((object)("CSV Load Error: File not found at path: " + text));
				return list;
			}
			int num = 0;
			try
			{
				string[] array = File.ReadAllLines(text);
				string[] array2 = array;
				foreach (string text2 in array2)
				{
					num++;
					string text3 = text2.Trim();
					if (string.IsNullOrEmpty(text3))
					{
						continue;
					}
					string[] array3 = text3.Split(new char[1] { ',' });
					if (array3.Length < 2)
					{
						Debug.LogWarning((object)$"CSV Parsing Warning on line {num}: Skipping malformed line.");
						continue;
					}
					string text4 = array3[0].Trim();
					float result;
					if (string.IsNullOrEmpty(text4))
					{
						Debug.LogWarning((object)$"CSV Parsing Warning on line {num}: Empty ObjectID. Skipping.");
					}
					else if (!float.TryParse(array3[1].Trim(), NumberStyles.Any, CultureInfo.InvariantCulture, out result))
					{
						Debug.LogError((object)$"CSV Parsing Error on line {num}: Could not parse Price as float: '{array3[1]}'");
					}
					else
					{
						list.Add(new BaseItemData(text4, result));
					}
				}
				Debug.Log((object)$"Successfully loaded {list.Count} items from CSV '{relativePath}'.");
			}
			catch (Exception ex)
			{
				Debug.LogError((object)$"CRITICAL CSV LOAD FAILURE for '{relativePath}' on line {num}: {ex.Message}");
				list.Clear();
			}
			return list;
		}
	}
	public static class ItemPricesManager
	{
		private static readonly Dictionary<string, float> _priceCache = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase);

		public static float CHEAPEND_SELL_PRICE = 0.1f;

		public static float SELL_DISCOUNT = 0.95f;

		public static List<ObjectCategory> sellCheapenedCategories = new List<ObjectCategory>
		{
			(ObjectCategory)2,
			(ObjectCategory)4,
			(ObjectCategory)3,
			(ObjectCategory)8,
			(ObjectCategory)64
		};

		public static void LoadAndApplyCsvPrices()
		{
			_priceCache.Clear();
			ApplyCsv("Attachment.csv");
			ApplyCsv("Attachment2Temp.csv");
			ApplyCsv("Cartridge.csv");
			ApplyCsv("Clip.csv");
			ApplyCsv("Magazine.csv");
			ApplyCsv("MeatFortress.csv");
			ApplyCsv("Melee.csv");
			ApplyCsv("Misc.csv");
			ApplyCsv("Pistol.csv");
			ApplyCsv("Shotgun.csv");
			ApplyCsv("SMG_Rifle.csv");
			ApplyCsv("Speedloader.csv");
			ApplyCsv("Support.csv");
		}

		private static void ApplyCsv(string relativePath)
		{
			List<BaseItemData> list = CsvItemPriceLoader.LoadBaseItems(relativePath);
			if (list == null || list.Count == 0)
			{
				return;
			}
			for (int i = 0; i < list.Count; i++)
			{
				BaseItemData baseItemData = list[i];
				if (baseItemData != null && !string.IsNullOrEmpty(baseItemData.ObjectID))
				{
					ItemIndex.EnsureIndexed(baseItemData.ObjectID);
					ItemIndex.OverrideIndexedPrice(baseItemData.ObjectID, baseItemData.Price);
					_priceCache[baseItemData.ObjectID] = baseItemData.Price;
				}
			}
		}

		public static float GetPrice(string objectId, int k = 3)
		{
			if (string.IsNullOrEmpty(objectId))
			{
				Debug.LogError((object)"GetPrice called with null or empty objectId.");
				return 0f;
			}
			if (_priceCache.TryGetValue(objectId, out var value))
			{
				return value;
			}
			if (ItemIndex.TryGetIndexedPrice(objectId, out var price) && price > 0f)
			{
				_priceCache[objectId] = price;
				return price;
			}
			float num = ItemIndex.PredictPrice(objectId, Mathf.Max(1, k));
			_priceCache[objectId] = num;
			return num;
		}

		public static float GetSellPrice(string objectId)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			ItemExtractedFeatures itemFeatures = ItemIndex.GetItemFeatures(objectId);
			if (sellCheapenedCategories.Contains(itemFeatures.Category))
			{
				return CHEAPEND_SELL_PRICE;
			}
			float price = GetPrice(objectId);
			return price * SELL_DISCOUNT;
		}

		public static void ClearCache()
		{
			_priceCache.Clear();
		}
	}
	[Serializable]
	public class ShLoadout
	{
		public string displayName;

		public string uid;

		public string fullFileName;

		public string lastUsedorSaved;

		public bool IsOfficialExtract;

		private ShLoadout(string displayName, bool isOfficialExtract)
		{
			uid = Guid.NewGuid().ToString();
			this.displayName = displayName;
			fullFileName = "";
			lastUsedorSaved = ShTimeCalculator.dateTimeToString(DateTime.UtcNow);
			IsOfficialExtract = isOfficialExtract;
		}

		internal static ShLoadout Create(string displayName, bool isOfficialExtract)
		{
			return new ShLoadout(displayName, isOfficialExtract);
		}

		public void UpdateLastSavedTime()
		{
			lastUsedorSaved = ShTimeCalculator.dateTimeToString(DateTime.UtcNow);
		}

		public void ChangeDisplayName(string newname)
		{
			displayName = newname;
		}
	}
	public static class ShLoadoutFactory
	{
		private const string DEFAULT_NAME = "Unnamed Loadout";

		private const string DEFAULT_EXTRACT_NAME = "Extracted Loadout";

		public static ShLoadout CreateDefault()
		{
			return ShLoadout.Create("Unnamed Loadout", isOfficialExtract: false);
		}

		public static ShLoadout CreateNamed(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				name = "Unnamed Loadout";
			}
			return ShLoadout.Create(name, isOfficialExtract: false);
		}

		public static ShLoadout CreateOfficialExtract()
		{
			return ShLoadout.Create("Extracted Loadout", isOfficialExtract: true);
		}
	}
	[Serializable]
	public class ShLoadoutRack
	{
		public List<ShLoadout> loadouts;

		public ShLoadoutRack()
		{
			Init();
		}

		public void Init()
		{
			if (loadouts == null)
			{
				loadouts = new List<ShLoadout>();
			}
		}

		public ShLoadout CreateEmptyLoadout()
		{
			if (loadouts == null)
			{
				loadouts = new List<ShLoadout>();
			}
			int num = 0;
			foreach (ShLoadout loadout in loadouts)
			{
				if (loadout != null && !loadout.IsOfficialExtract)
				{
					num++;
				}
			}
			int num2 = num + 1;
			string name = $"Loadout {num2}";
			ShLoadout shLoadout = ShLoadoutFactory.CreateNamed(name);
			loadouts.Add(shLoadout);
			return shLoadout;
		}

		public ShLoadout EnsureExtractionLoadout()
		{
			List<ShLoadout> list = new List<ShLoadout>();
			foreach (ShLoadout loadout in loadouts)
			{
				if (loadout != null && loadout.IsOfficialExtract)
				{
					list.Add(loadout);
				}
			}
			if (list.Count == 0)
			{
				ShLoadout shLoadout = ShLoadoutFactory.CreateOfficialExtract();
				loadouts.Add(shLoadout);
				return shLoadout;
			}
			if (list.Count == 1)
			{
				return list[0];
			}
			ShLoadout shLoadout2 = list[0];
			DateTime dateTime = ShTimeCalculator.stringToDateTime(shLoadout2.lastUsedorSaved);
			for (int i = 1; i < list.Count; i++)
			{
				DateTime dateTime2 = ShTimeCalculator.stringToDateTime(list[i].lastUsedorSaved);
				if (dateTime2 > dateTime)
				{
					shLoadout2 = list[i];
					dateTime = dateTime2;
				}
			}
			for (int num = loadouts.Count - 1; num >= 0; num--)
			{
				ShLoadout shLoadout3 = loadouts[num];
				if (shLoadout3 != null && shLoadout3.IsOfficialExtract && shLoadout3 != shLoadout2)
				{
					loadouts.RemoveAt(num);
				}
			}
			return shLoadout2;
		}

		public ShLoadout GetLoadout(string uid)
		{
			foreach (ShLoadout loadout in loadouts)
			{
				if (loadout.uid == uid)
				{
					return loadout;
				}
			}
			return null;
		}

		public void ConsumeLoadout(string uid)
		{
			for (int num = loadouts.Count - 1; num >= 0; num--)
			{
				ShLoadout shLoadout = loadouts[num];
				if (shLoadout != null && shLoadout.uid == uid)
				{
					loadouts.RemoveAt(num);
					break;
				}
			}
		}

		public List<ShLoadout> listLoadoutsSortedByUpdateTime()
		{
			ShLoadout item = EnsureExtractionLoadout();
			loadouts.Sort(delegate(ShLoadout a, ShLoadout b)
			{
				if (a == null && b == null)
				{
					return 0;
				}
				if (a == null)
				{
					return 1;
				}
				if (b == null)
				{
					return -1;
				}
				DateTime value = ShTimeCalculator.stringToDateTime(a.lastUsedorSaved);
				return ShTimeCalculator.stringToDateTime(b.lastUsedorSaved).CompareTo(value);
			});
			for (int num = loadouts.Count - 1; num >= 0; num--)
			{
				ShLoadout shLoadout = loadouts[num];
				if (shLoadout != null && shLoadout.IsOfficialExtract)
				{
					loadouts.RemoveAt(num);
				}
			}
			loadouts.Insert(0, item);
			return loadouts;
		}

		public List<ShLoadout> ListLoadoutsUnsorted()
		{
			ShLoadout item = EnsureExtractionLoadout();
			for (int num = loadouts.Count - 1; num >= 0; num--)
			{
				ShLoadout shLoadout = loadouts[num];
				if (shLoadout != null && shLoadout.IsOfficialExtract)
				{
					loadouts.RemoveAt(num);
				}
			}
			loadouts.Insert(0, item);
			return loadouts;
		}
	}
	public static class ShLoadoutsVault
	{
		private const string LOADOUTS_FOLDER = "Loadouts";

		private const string EXTR_LOADY_FILE = "ExtractionLoady.json";

		private const string LOADY_EXT = "_.json";

		public static string GetVaultProfileRoot(string profileUid)
		{
			return Path.Combine(Path.Combine(ShFileIoHandler.GetH3SaveFolder(), ShFileIoHandler.rootSaveFolder), profileUid);
		}

		public static string GetLoadoutsFolder(string profileUid)
		{
			return Path.Combine(GetVaultProfileRoot(profileUid), "Loadouts");
		}

		public static string GetExtractionLoadyFile(string profileUid)
		{
			return Path.Combine(GetLoadoutsFolder(profileUid), "ExtractionLoady.json");
		}

		public static string GetLoadyFileFromUid(string profileUid, string loadyUid)
		{
			return Path.Combine(GetLoadoutsFolder(profileUid), loadyUid + "_.json");
		}

		public static bool TrySaveExtractionLoady(string profileUid, out string error)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			error = null;
			VaultFile vf = new VaultFile();
			if (!TryScanCurrentLoadout(out vf, out error))
			{
				error = "[TrySaveExtractionLoady] Scanning quickbelt failed.";
				return false;
			}
			string extractionLoadyFile = GetExtractionLoadyFile(profileUid);
			ShFileIoHandler.EnsureFile(extractionLoadyFile);
			if (!ShFileIoHandler.TrySaveJson(vf, extractionLoadyFile, out error))
			{
				error = "[TrySaveExtractionLoady] Failed to save w error: " + error;
				return false;
			}
			return true;
		}

		public static VaultFile TryGetExtractionLoadyVault(string profileUid, out string error)
		{
			string extractionLoadyFile = GetExtractionLoadyFile(profileUid);
			ShFileIoHandler.EnsureFile(extractionLoadyFile);
			if (!ShFileIoHandler.TryLoadJson<VaultFile>(extractionLoadyFile, out VaultFile obj, out error))
			{
				if (error == "File was empty")
				{
					return null;
				}
				error = "[TryGetExtractionLoady]: Failed to parse json w: " + error + " on file " + extractionLoadyFile;
				return null;
			}
			return obj;
		}

		public static bool TryLoadExtractionLoady(string profileUid, out string error)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			string extractionLoadyFile = GetExtractionLoadyFile(profileUid);
			ShFileIoHandler.EnsureDirectory(Path.GetDirectoryName(extractionLoadyFile));
			if (!ShFileIoHandler.TryLoadJson<VaultFile>(extractionLoadyFile, out VaultFile obj, out error))
			{
				error = "[TryLoadExtractionLoady]: Failed to parse json w: " + error + " on file " + extractionLoadyFile;
				return false;
			}
			Transform transform = ((Component)GM.CurrentPlayerBody).transform;
			return VaultSystem.SpawnObjects((VaultFileType)2, obj, ref error, transform, Vector3.zero);
		}

		public static bool TryClearExtractionLoadyFile(string profileUid, out string error)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			VaultFile obj = new VaultFile();
			string extractionLoadyFile = GetExtractionLoadyFile(profileUid);
			ShFileIoHandler.EnsureDirectory(Path.GetDirectoryName(extractionLoadyFile));
			if (!ShFileIoHandler.TrySaveJson(obj, extractionLoadyFile, out error))
			{
				Debug.LogError((object)("[TrySaveExtractionLoady] Failed to save w error: " + error));
				return false;
			}
			return true;
		}

		public static bool TrySaveCustomLoady(string profileUid, string loadyUid, out string fullFileName, out string error)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			error = null;
			fullFileName = null;
			VaultFile vf = new VaultFile();
			if (!TryScanCurrentLoadout(out vf, out error))
			{
				Debug.LogError((object)"[TrySaveCustomLoady] Scanning quickbelt failed.");
				return false;
			}
			string loadyFileFromUid = GetLoadyFileFromUid(profileUid, loadyUid);
			ShFileIoHandler.EnsureDirectory(Path.GetDirectoryName(loadyFileFromUid));
			if (!ShFileIoHandler.TrySaveJson(vf, loadyFileFromUid, out error))
			{
				Debug.LogError((object)("[TrySaveCustomLoady] Failed to save w error: " + error));
				return false;
			}
			fullFileName = loadyFileFromUid;
			return true;
		}

		public static VaultFile TryGetCustomLoadyFile(string profileUid, string loadyUid, out string error)
		{
			string loadyFileFromUid = GetLoadyFileFromUid(profileUid, loadyUid);
			ShFileIoHandler.EnsureDirectory(Path.GetDirectoryName(loadyFileFromUid));
			if (!ShFileIoHandler.TryLoadJson<VaultFile>(loadyFileFromUid, out VaultFile obj, out error))
			{
				error = "[TryGetCustomLoadyFile]: Failed to parse json w: " + error + " on file " + loadyFileFromUid;
				return null;
			}
			return obj;
		}

		public static bool TryLoadCustomLoady(string profileUid, string loadyUid, out string error)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			string loadyFileFromUid = GetLoadyFileFromUid(profileUid, loadyUid);
			ShFileIoHandler.EnsureDirectory(Path.GetDirectoryName(loadyFileFromUid));
			if (!ShFileIoHandler.TryLoadJson<VaultFile>(loadyFileFromUid, out VaultFile obj, out error))
			{
				error = "[TryLoadCustomLoady]: Failed to parse json w: " + error + " on file " + loadyFileFromUid;
				return false;
			}
			Transform transform = ((Component)GM.CurrentPlayerBody).transform;
			return VaultSystem.SpawnObjects((VaultFileType)2, obj, ref error, transform, Vector3.zero);
		}

		public static bool TryDeleteCustomLoady(string profileUid, string loadyUid, out string error)
		{
			error = null;
			string loadyFileFromUid = GetLoadyFileFromUid(profileUid, loadyUid);
			ShFileIoHandler.EnsureDirectory(Path.GetDirectoryName(loadyFileFromUid));
			try
			{
				if (File.Exists(loadyFileFromUid))
				{
					File.Delete(loadyFileFromUid);
				}
				return true;
			}
			catch (Exception ex)
			{
				error = ex.Message;
				Debug.LogError((object)("[TryDeleteCustomLoady]: Failed to delete w: " + error + " on file " + loadyFileFromUid));
				return false;
			}
		}

		public static bool TryDeleteExtractionLoady(string profileUid, out string error)
		{
			error = null;
			string extractionLoadyFile = GetExtractionLoadyFile(profileUid);
			try
			{
				if (File.Exists(extractionLoadyFile))
				{
					File.Delete(extractionLoadyFile);
				}
				return true;
			}
			catch (Exception ex)
			{
				error = ex.Message;
				Debug.LogError((object)("[TryDeleteExtractionLoady]: Failed to delete w: " + error + " on file " + extractionLoadyFile));
				return false;
			}
		}

		private static bool TryScanCurrentLoadout(out VaultFile vf, out string error)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			vf = new VaultFile();
			error = null;
			if (!VaultSystem.FindAndScanObjectsInQuickbelt(vf))
			{
				error = "Loady scan failed.";
				return false;
			}
			return true;
		}
	}
	public class LootCalculator
	{
		public static List<string> GetOrderedItemsIDs(List<ObjectCategory> orderedCategories)
		{
			int count = orderedCategories?.Count ?? 0;
			List<string> result = NewBlankResultList(count);
			Dictionary<int, string> firearmAtIndex = new Dictionary<int, string>();
			string lastFirearmId = string.Empty;
			PlaceFirearms(orderedCategories, result, firearmAtIndex, ref lastFirearmId);
			FillNonFirearms(orderedCategories, result, firearmAtIndex, ref lastFirearmId);
			return result;
		}

		private static List<string> NewBlankResultList(int count)
		{
			List<string> list = new List<string>(count);
			for (int i = 0; i < count; i++)
			{
				list.Add(string.Empty);
			}
			return list;
		}

		private static void PlaceFirearms(List<ObjectCategory> cats, List<string> result, Dictionary<int, string> firearmAtIndex, ref string lastFirearmId)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Invalid comparison between Unknown and I4
			for (int i = 0; i < cats.Count; i++)
			{
				ObjectCategory val = cats[i];
				if (!IsAnyCategory(val) && (int)val == 1)
				{
					FVRObject obj = PickRandomFromCategory((ObjectCategory)1);
					string text2 = (result[i] = ToItemId(obj));
					if (!string.IsNullOrEmpty(text2))
					{
						firearmAtIndex[i] = text2;
						lastFirearmId = text2;
					}
				}
			}
		}

		private static void FillNonFirearms(List<ObjectCategory> cats, List<string> result, Dictionary<int, string> firearmAtIndex, ref string lastFirearmId)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Invalid comparison between Unknown and I4
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < cats.Count; i++)
			{
				if (!string.IsNullOrEmpty(result[i]))
				{
					continue;
				}
				ObjectCategory cat = cats[i];
				cat = ResolveAnyCategory(cat);
				if (IsAmmoCategory(cat))
				{
					result[i] = GetAmmoItemId(i, cats.Count, firearmAtIndex, ref lastFirearmId);
				}
				else if ((int)cat == 1)
				{
					FVRObject obj = PickRandomFromCategory((ObjectCategory)1);
					result[i] = ToItemId(obj);
					if (!string.IsNullOrEmpty(result[i]))
					{
						lastFirearmId = result[i];
					}
				}
				else
				{
					result[i] = ToItemId(PickRandomFromCategory(cat));
				}
			}
		}

		private static bool IsAnyCategory(ObjectCategory cat)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			return (int)cat == 0;
		}

		private static ObjectCategory ResolveAnyCategory(ObjectCategory cat)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: 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)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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)
			if (!IsAnyCategory(cat))
			{
				return cat;
			}
			Dictionary<ObjectCategory, List<FVRObject>> odicTagCategory = ManagerSingleton<IM>.Instance.odicTagCategory;
			if (odicTagCategory == null || odicTagCategory.Count == 0)
			{
				return (ObjectCategory)0;
			}
			List<ObjectCategory> list = new List<ObjectCategory>(odicTagCategory.Keys);
			list.Remove((ObjectCategory)0);
			return list[Random.Range(0, list.Count)];
		}

		private static bool IsAmmoCategory(ObjectCategory cat)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			return (int)cat == 2 || (int)cat == 6 || (int)cat == 3 || (int)cat == 4;
		}

		private static string GetAmmoItemId(int index, int totalCount, Dictionary<int, string> firearmAtIndex, ref string lastFirearmId)
		{
			string text = ((!string.IsNullOrEmpty(lastFirearmId)) ? lastFirearmId : FindWeaponAhead(index, totalCount, firearmAtIndex));
			if (!string.IsNullOrEmpty(text))
			{
				FVRObject val = IM.OD[text];
				FVRObject randomAmmoObject = IM.OD[text].GetRandomAmmoObject(val, (List<OTagEra>)null, -1, -1, (List<OTagSet>)null);
				string text2 = ToItemId(randomAmmoObject);
				if (!string.IsNullOrEmpty(text2))
				{
					return text2;
				}
			}
			return ToItemId(PickRandomFromCategory((ObjectCategory)2));
		}

		private static string FindWeaponAhead(int idx, int totalCount, Dictionary<int, string> firearmAtIndex)
		{
			for (int i = idx + 1; i < totalCount; i++)
			{
				if (firearmAtIndex.TryGetValue(i, out var value))
				{
					return value;
				}
			}
			return string.Empty;
		}

		private static FVRObject PickRandomFromCategory(ObjectCategory cat)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<ObjectCategory, List<FVRObject>> odicTagCategory = ManagerSingleton<IM>.Instance.odicTagCategory;
			if (odicTagCategory == null)
			{
				Debug.LogError((object)"PickRandomFromCategory: failed get odicTagCategory at all");
				return null;
			}
			if (!odicTagCategory.TryGetValue(cat, out var value) || value == null || value.Count == 0)
			{
				Debug.LogError((object)("PickRandomFromCategory: failed get category " + ((object)(ObjectCategory)(ref cat)).ToString()));
				return null;
			}
			return value[Random.Range(0, value.Count)];
		}

		private static string ToItemId(FVRObject obj)
		{
			if ((Object)(object)obj == (Object)null)
			{
				Debug.LogError((object)"ToItemId: obj in put is null");
				return string.Empty;
			}
			try
			{
				if (!string.IsNullOrEmpty(obj.ItemID))
				{
					return obj.ItemID;
				}
			}
			catch
			{
				Debug.LogError((object)"ToItemId: ItemID is not present in the object");
				return string.Empty;
			}
			return string.Empty;
		}
	}
	public class ShowLootUiOnInteract : MonoBehaviour
	{
		private bool ready = false;

		private SosigLink slink;

		private SLinkLootController controller;

		public void Init(SosigLink Slink, SLinkLootController Controller)
		{
			ready = true;
			slink = Slink;
			controller = Controller;
		}

		private void Update()
		{
			if (ready)
			{
				controller.SetUiActive(((FVRInteractiveObject)slink.O).IsHeld);
			}
		}
	}
	public class SLinkLootController : MonoBehaviour
	{
		private Canvas canvas;

		private List<SpawnOnGrab> grabbies;

		public void Awake()
		{
			FindUiVariables();
		}

		private void FindUiVariables()
		{
			canvas = ((Component)((Component)this).transform).GetComponent<Canvas>();
			grabbies = new List<SpawnOnGrab>(((Component)this).GetComponentsInChildren<SpawnOnGrab>());
		}

		public static void AttachToSosig(Sosig theSosig)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: 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_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Component)theSosig).transform.Find("Sosig_Torso");
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogError((object)"AttachToSosig: could not find Sosig_Torso");
				return;
			}
			GameObject val2 = ShSpawnItems.SpawnItemFromID("NGA_torsoLootUi");
			if ((Object)(object)val2 == (Object)null)
			{
				Debug.LogError((object)"AttachToSosig: SpawnItemFromOD returned null for torso");
				return;
			}
			val2.transform.SetParent(val);
			val2.transform.localPosition = Vector3.zero;
			val2.transform.localRotation = Quaternion.identity;
			val2.transform.localScale = new Vector3(0.007f, 0.007f, 0.007f);
			SLinkLootController component = val2.GetComponent<SLinkLootController>();
			component.EnableLooting(theSosig);
			if ((Object)(object)component == (Object)null)
			{
				Debug.LogError((object)"AttachToSosig: torso UI prefab has no SLinkLootController");
				return;
			}
			ShowLootUiOnInteract showLootUiOnInteract = ((Component)val).gameObject.AddComponent<ShowLootUiOnInteract>();
			showLootUiOnInteract.Init(((Component)val).GetComponent<SosigLink>(), component);
			Transform val3 = val.Find("UpperLink");
			if ((Object)(object)val3 == (Object)null)
			{
				Debug.LogError((object)"AttachToSosig: could not find Upper link");
				return;
			}
			GameObject val4 = ShSpawnItems.SpawnItemFromID("NGA_waistLootUi");
			if ((Object)(object)val4 == (Object)null)
			{
				Debug.LogError((object)"AttachToSosig: SpawnItemFromOD returned null for waist");
				return;
			}
			val4.transform.SetParent(val3);
			val4.transform.localPosition = Vector3.zero;
			val4.transform.localRotation = Quaternion.identity;
			val4.transform.localScale = new Vector3(0.007f, 0.007f, 0.007f);
			SLinkLootController component2 = val4.GetComponent<SLinkLootController>();
			component2.EnableLooting(theSosig);
			if ((Object)(object)component2 == (Object)null)
			{
				Debug.LogError((object)"AttachToSosig: torso UI prefab has no SLinkLootController");
				return;
			}
			ShowLootUiOnInteract showLootUiOnInteract2 = ((Component)val3).gameObject.AddComponent<ShowLootUiOnInteract>();
			showLootUiOnInteract2.Init(((Component)val3).GetComponent<SosigLink>(), component2);
		}

		public void EnableLooting(Sosig killedSosig)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			List<ObjectCategory> list = new List<ObjectCategory>(grabbies.Count);
			foreach (SpawnOnGrab grabby in grabbies)
			{
				list.Add(grabby.itemType);
			}
			List<string> orderedItemsIDs = LootCalculator.GetOrderedItemsIDs(list);
			for (int i = 0; i < grabbies.Count; i++)
			{
				grabbies[i].SetItem(orderedItemsIDs[i]);
			}
			SetUiActive(value: false);
		}

		public void SetUiActive(bool value)
		{
			((Behaviour)canvas).enabled = value;
		}
	}
	public class SpawnOnGrab : FVRInteractiveObject
	{
		private RawImage backgroundImage;

		private RawImage itemImage;

		private readonly HashSet<FVRPhysicalObject> _inside = new HashSet<FVRPhysicalObject>();

		private readonly HashSet<FVRPhysicalObject> _waitingRelease = new HashSet<FVRPhysicalObject>();

		private Collider collectionTrigger;

		private bool destroyCollectedObject = true;

		public Color defaultColor = Color32.op_Implicit(new Color32((byte)86, (byte)70, (byte)70, (byte)128));

		public Color hoveredColor = Color32.op_Implicit(new Color32((byte)161, (byte)161, (byte)55, byte.MaxValue));

		private static readonly List<FVRPhysicalObject> _toProcess = new List<FVRPhysicalObject>(32);

		[Header("Spawner params")]
		public ObjectCategory itemType = (ObjectCategory)(-1);

		public string itemID;

		[Tooltip("How many objects can be taken from this spawner before it runs out")]
		public int currObjectCapacity;

		private FVRObject fob;

		private AnvilCallback<GameObject> itemLoader;

		protected override void Awake()
		{
			((FVRInteractiveObject)this).Awake();
			FindUiVariables();
			if (!string.IsNullOrEmpty(itemID) && IM.OD.ContainsKey(itemID))
			{
				itemLoader = ((AnvilAsset)IM.OD[itemID]).GetGameObjectAsync();
			}
			if (!string.IsNullOrEmpty(itemID))
			{
				itemLoader = ((AnvilAsset)IM.OD[itemID]).GetGameObjectAsync();
			}
		}

		private void FindUiVariables()
		{
			backgroundImage = ((Component)((Component)this).transform).GetComponent<RawImage>();
			itemImage = ((Component)((Component)this).transform.Find("ItemImage")).GetComponent<RawImage>();
			collectionTrigger = ((Component)this).GetComponent<Collider>();
		}

		public void Redraw()
		{
			if (!IM.HasSpawnedID(fob.SpawnedFromId))
			{
				Debug.LogWarning((object)("SpawnedID not exist for: " + fob.ItemID));
			}
			if (currObjectCapacity > 0 && IM.HasSpawnedID(fob.SpawnedFromId))
			{
				((Behaviour)itemImage).enabled = true;
				itemImage.texture = (Texture)(object)IM.GetSpawnerID(fob.SpawnedFromId).Sprite.texture;
			}
			else
			{
				((Behaviour)itemImage).enabled = true;
			}
		}

		public override void BeginInteraction(FVRViveHand hand)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			if (currObjectCapacity >= 1)
			{
				((FVRInteractiveObject)this).BeginInteraction(hand);
				if (!((AnvilCallbackBase)itemLoader).IsCompleted)
				{
					((AnvilCallbackBase)itemLoader).CompleteNow();
				}
				FVRPhysicalObject component = Object.Instantiate<GameObject>(itemLoader.Result, ((Component)hand).transform.position, ((Component)hand).transform.rotation).GetComponent<FVRPhysicalObject>();
				if ((Object)(object)component != (Object)null)
				{
					hand.ForceSetInteractable((FVRInteractiveObject)(object)component);
					((FVRInteractiveObject)component).BeginInteraction(hand);
				}
				RemoveItem();
			}
		}

		public void RemoveItem()
		{
			if (currObjectCapacity >= 1)
			{
				currObjectCapacity--;
				if (currObjectCapacity < 1)
				{
					((Behaviour)itemImage).enabled = false;
				}
			}
		}

		public void AddItem(string ID, int objectAmount = 1)
		{
			if (string.IsNullOrEmpty(ID) || objectAmount < 1)
			{
				Debug.LogWarning((object)"SpawnOnGrab.AddItem: You tried to give me an empty item id or negative or zero objectAmount. Nice try.");
			}
			else if (!string.IsNullOrEmpty(itemID) && currObjectCapacity > 0)
			{
				Debug.LogWarning((object)("SpawnOnGrab.AddItem: I cant add an item if there are some already present: " + itemID + " for " + currObjectCapacity));
			}
			else if (ID == itemID)
			{
				currObjectCapacity += objectAmount;
				Redraw();
			}
			else
			{
				SetItem(ID, objectAmount);
			}
		}

		public void SetItem(string ID, int objectCapacity = 1)
		{
			if (string.IsNullOrEmpty(ID))
			{
				Debug.LogError((object)"SpawnOnGrab was given an empty or null id");
				return;
			}
			if (!IM.OD.ContainsKey(ID))
			{
				Debug.LogError((object)("SpawnOnGrab was given key that's not present in IM.OD: " + ID));
				return;
			}
			itemID = ID;
			fob = IM.OD[itemID];
			itemLoader = ((AnvilAsset)fob).GetGameObjectAsync();
			currObjectCapacity = objectCapacity;
			Redraw();
		}

		private void OnTriggerEnter(Collider other)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)other == (Object)null)
			{
				return;
			}
			((Graphic)backgroundImage).color = hoveredColor;
			FVRPhysicalObject componentInParent = ((Component)other).GetComponentInParent<FVRPhysicalObject>();
			if (!((Object)(object)componentInParent == (Object)null))
			{
				_inside.Add(componentInParent);
				if (((FVRInteractiveObject)componentInParent).IsHeld)
				{
					_waitingRelease.Add(componentInParent);
				}
			}
		}

		private void OnTriggerExit(Collider other)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)other == (Object)null))
			{
				((Graphic)backgroundImage).color = defaultColor;
				FVRPhysicalObject componentInParent = ((Component)other).GetComponentInParent<FVRPhysicalObject>();
				if (!((Object)(object)componentInParent == (Object)null))
				{
					_inside.Remove(componentInParent);
					_waitingRelease.Remove(componentInParent);
				}
			}
		}

		private void Update()
		{
			if (_inside.Count == 0)
			{
				return;
			}
			_toProcess.Clear();
			foreach (FVRPhysicalObject item in _inside)
			{
				if ((Object)(object)item != (Object)null)
				{
					_toProcess.Add(item);
				}
			}
			foreach (FVRPhysicalObject item2 in _toProcess)
			{
				if ((Object)(object)item2 == (Object)null)
				{
					continue;
				}
				if (((FVRInteractiveObject)item2).IsHeld)
				{
					_waitingRelease.Add(item2);
				}
				else
				{
					if (!_waitingRelease.Contains(item2))
					{
						continue;
					}
					FVRObject objectWrapper = item2.ObjectWrapper;
					if ((Object)(object)objectWrapper != (Object)null)
					{
						AddItem(objectWrapper.ItemID);
						if (destroyCollectedObject && (Object)(object)((Component)item2).gameObject != (Object)null)
						{
							Object.Destroy((Object)(object)((Component)item2).gameObject);
						}
					}
					_waitingRelease.Remove(item2);
					_inside.Remove(item2);
				}
			}
		}
	}
	[BepInPlugin("NGA.SafehouseProgressionMPatchy", "SafehouseProgressionMPatchy", "0.0.1")]
	[BepInDependency("nrgill28.Sodalite", "1.4.1")]
	[BepInProcess("h3vr.exe")]
	public class SafehouseProgressionMPatchy : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(GM))]
		[HarmonyPatch("Awake")]
		public class SH_GM_Initializer
		{
			private static void Postfix(GM __instance)
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Expected O, but got Unknown
				if ((Object)(object)SHGM.Instance == (Object)null)
				{
					GameObject val = new GameObject("SH_GM");
					val.AddComponent<SHGM>();
					Object.DontDestroyOnLoad((Object)(object)val);
				}
				SceneTravelManager.Ensure();
			}
		}

		[HarmonyPatch(typeof(FVRSceneSettings))]
		[HarmonyPatch("LoadDefaultSceneRoutine")]
		private class FVRSceneSettingsLoadDefaultSceneRoutineHook
		{
			private static bool Prefix(FVRSceneSettings __instance)
			{
				if (SceneTravelManager.Instance._pending.HasValue)
				{
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(TNH_Manager), "HoldPointCompleted")]
		private class HoldPointManagerCompleted
		{
			private static void Postfix(TNH_Manager __instance)
			{
				BankViewModel.Instance.AddSpades(2);
			}
		}

		[HarmonyPatch(typeof(TNH_Manager))]
		[HarmonyPatch("SetPhase_Completed")]
		private class HoldPointManagerSetPhase_Completed
		{
			private static void Postfix(TNH_Manager __instance)
			{
				BankViewModel.Instance.AddSpades(5);
			}
		}

		[HarmonyPatch(typeof(TNH_Manager))]
		[HarmonyPatch("SetPhase_Dead")]
		private class HoldPointManagerSetPhase_Dead
		{
			private static void Postfix(TNH_Manager __instance)
			{
				GM.CurrentPlayerBody.WipeQuickbeltContents();
			}
		}

		[HarmonyPatch(typeof(Sosig), "Configure")]
		private class SosigLootAttach
		{
			private static void Postfix(Sosig __instance)
			{
			}
		}

		[HarmonyPatch(typeof(FVRWristMenu2))]
		[HarmonyPatch("Awake")]
		private class WristMenuAwakeHook
		{
			private static void Postfix(FVRWristMenu2 __instance)
			{
				if ((Object)(object)__instance == (Object)null)
				{
					Logger.LogMessage((object)"FVRWristMenu2 is null!?");
				}
				try
				{
					FVRWristMenuSection_Safehouse2 fVRWristMenuSection_Safehouse = AddWristMenuSection(__instance);
				}
				catch (Exception ex)
				{
					Debug.LogError((object)("[AddWristMenuSection] Failed with error: " + ex.Message));
				}
			}
		}

		public class SwapIconHandler : MonoBehaviour
		{
			private FVRWristMenuSectionButton b;

			private bool swapped;

			private void Awake()
			{
				b = ((Component)this).GetComponent<FVRWristMenuSectionButton>();
			}

			private void Update()
			{
				//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
				//IL_0247: Unknown result type (might be due to invalid IL or missing references)
				//IL_024e: Expected O, but got Unknown
				//IL_0286: Unknown result type (might be due to invalid IL or missing references)
				//IL_029d: Unknown result type (might be due to invalid IL or missing references)
				//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
				//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
				//IL_021f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0224: Unknown result type (might be due to invalid IL or missing references)
				//IL_022d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0237: Unknown result type (might be due to invalid IL or missing references)
				//IL_023c: Unknown result type (might be due to invalid IL or missing references)
				if (swapped)
				{
					return;
				}
				if ((Object)(object)b == (Object)null)
				{
					b = ((Component)this).GetComponent<FVRWristMenuSectionButton>();
				}
				else
				{
					if ((Object)(object)b.ButtonText == (Object)null || !(b.ButtonText.text == "SHP3-swap"))
					{
						return;
					}
					swapped = true;
					b.ButtonText.text = "";
					Transform val = ((Component)this).transform.Find("Backing");
					if ((Object)(object)val == (Object)null)
					{
						Debug.LogError((object)"[SwapIconHandler] Could not find child named 'Backing'.");
						return;
					}
					Image component = ((Component)val).GetComponent<Image>();
					if ((Object)(object)component == (Object)null)
					{
						Debug.LogError((object)"[SwapIconHandler] 'Backing' found but it has no Image component.");
						return;
					}
					string text = Path.Combine(ShFileIoHandler.GetPluginModFolder(), "wideIcon.png");
					string text2 = Path.Combine(ShFileIoHandler.GetPluginModFolder(), "redNot.png");
					if (!File.Exists(text) || !File.Exists(text2))
					{
						Debug.LogError((object)("[SwapIconHandler] File not found: " + text));
						return;
					}
					Texture2D val2 = ShFileIoHandler.LoadTextureFromFullPath(text);
					Texture2D val3 = ShFileIoHandler.LoadTextureFromFullPath(text2);
					if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null)
					{
						Debug.LogError((object)"[SwapIconHandler] Loader returned null Texture2D.");
						return;
					}
					Rect val4 = default(Rect);
					((Rect)(ref val4))..ctor(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height);
					Vector2 val5 = default(Vector2);
					((Vector2)(ref val5))..ctor(0.5f, 0.5f);
					Sprite sprite = Sprite.Create(val2, val4, val5);
					component.sprite = sprite;
					if (((Graphic)component).color.a < 1f)
					{
						((Graphic)component).color = new Color(1f, 1f, 1f, 1f);
					}
					FVRPointableButton component2 = ((Component)this).GetComponent<FVRPointableButton>();
					if ((Object)(object)component2 != (Object)null)
					{
						component2.Image = component;
						component2.ColorUnselected = component2.ColorSelected;
						component2.ColorSelected *= 2f;
					}
					GameObject val6 = new GameObject("Notification");
					val6.transform.SetParent(val, false);
					RawImage val7 = val6.AddComponent<RawImage>();
					val7.texture = (Texture)(object)val3;
					RectTransform component3 = val6.GetComponent<RectTransform>();
					component3.anchorMin = new Vector2(1f, 1f);
					component3.anchorMax = new Vector2(1f, 1f);
					component3.pivot = new Vector2(1f, 1f);
					component3.anchoredPosition = Vector2.zero;
					component3.sizeDelta = new Vector2(100f, 100f);
				}
			}
		}

		public class FVRWristMenuSection_Safehouse2 : FVRWristMenuSection
		{
			public override void Enable()
			{
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				GameObject val = ShSpawnItems.SpawnItemFromID("NGA_sp3Hud");
				val.transform.Rotate(0f, -90f, 0f, (Space)1);
				((Component)this).gameObject.SetActive(false);
				base.Menu.SectionSet.SetSelectedButton(-1);
			}
		}

		internal static ManualLogSource Logger { get; private set; }

		private void Awake()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			Harmony val = new Harmony("NGA.SafehouseProgressionMPatchy");
			Logger.LogMessage((object)"New harmony");
			SetUpConfigFields();
			Logger.LogMessage((object)"Setted the fields");
			val.PatchAll();
			Logger.LogMessage((object)"Hello, world! Sent from NGA.SafehouseProgressionMPatchy");
		}

		private void SetUpConfigFields()
		{
		}

		public static FVRWristMenuSection_Safehouse2 AddWristMenuSection(FVRWristMenu2 wristMenu)
		{
			//IL_0035: 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_00ac: 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_00cf: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Expected O, but got Unknown
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Expected O, but got Unknown
			FVRWristMenuSection val = wristMenu.Sections.First((FVRWristMenuSection x) => (object)((object)x).GetType() == typeof(FVRWristMenuSection_Spawn));
			Transform transform = ((Component)val).transform;
			FVRWristMenuSection val2 = Object.Instantiate<FVRWristMenuSection>(val, transform.position, transform.rotation, transform.parent);
			GameObject gameObject = ((Component)val2).gameObject;
			GameObject gameObject2 = ((Component)gameObject.transform.parent).gameObject;
			Object.Destroy((Object)(object)val2);
			Image component = gameObject.GetComponent<Image>();
			if ((Object)(object)component != (Object)null)
			{
				string pluginModFolder = ShFileIoHandler.GetPluginModFolder();
				string absolutePath = Path.Combine(pluginModFolder, "icon.png");
				Texture2D val3 = ShFileIoHandler.LoadTextureFromFullPath(absolutePath);
				RectTransform rectTransform = ((Graphic)component).rectTransform;
				Vector2 sizeDelta = rectTransform.sizeDelta;
				Sprite sprite = Sprite.Create(val3, new Rect(0f, 0f, (float)((Texture)val3).width, (float)((Texture)val3).height), new Vector2(0.5f, 0.5f));
				component.sprite = sprite;
				rectTransform.sizeDelta = sizeDelta;
			}
			else
			{
				Logger.LogError((object)"No Image component found in my Section.");
			}
			FVRWristMenuSection_Safehouse2 fVRWristMenuSection_Safehouse = gameObject.AddComponent<FVRWristMenuSection_Safehouse2>();
			((FVRWristMenuSection)fVRWristMenuSection_Safeho