Decompiled source of LGHEpicLootv2 v0.0.4

plugins/EpicLoot-UnityLib.dll

Decompiled 4 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("EpicLoot-UnityLib")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Randy Knapp Mods")]
[assembly: AssemblyProduct("EpicLoot-UnityLib")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("fb508e8d-0c64-4ec6-b746-f668f510296f")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace EpicLoot_UnityLib
{
	public class AugmentUI : EnchantingTableUIPanelBase
	{
		public delegate List<InventoryItemListElement> GetAugmentableItemsDelegate();

		public delegate List<Tuple<string, bool>> GetAugmentableEffectsDelegate(ItemData item);

		public delegate string GetAvailableEffectsDelegate(ItemData item, int augmentIndex);

		public delegate List<InventoryItemListElement> GetAugmentCostDelegate(ItemData item, int augmentIndex);

		public delegate GameObject AugmentItemDelegate(ItemData item, int augmentIndex);

		public Text AvailableEffectsText;

		public Text AvailableEffectsHeader;

		public Scrollbar AvailableEffectsScrollbar;

		public List<Toggle> AugmentSelectors;

		[Header("Cost")]
		public Text CostLabel;

		public MultiSelectItemList CostList;

		public static GetAugmentableItemsDelegate GetAugmentableItems;

		public static GetAugmentableEffectsDelegate GetAugmentableEffects;

		public static GetAvailableEffectsDelegate GetAvailableEffects;

		public static GetAugmentCostDelegate GetAugmentCost;

		public static AugmentItemDelegate AugmentItem;

		private int _augmentIndex;

		private GameObject _choiceDialog;

		public override void Awake()
		{
			base.Awake();
			for (int i = 0; i < AugmentSelectors.Count; i++)
			{
				((UnityEvent<bool>)(object)AugmentSelectors[i].onValueChanged).AddListener((UnityAction<bool>)OnAugmentSelectorToggled);
			}
		}

		[UsedImplicitly]
		public void OnEnable()
		{
			_augmentIndex = -1;
			foreach (Toggle augmentSelector in AugmentSelectors)
			{
				augmentSelector.isOn = false;
			}
			if ((Object)(object)AvailableEffectsHeader != (Object)null)
			{
				int num = 2;
				Tuple<float, float> featureCurrentValue = EnchantingTableUI.instance.SourceTable.GetFeatureCurrentValue(EnchantingFeature.Augment);
				if (!float.IsNaN(featureCurrentValue.Item1))
				{
					num = (int)featureCurrentValue.Item1;
				}
				string text = ((num > 2) ? "<color=#EAA800>" : "");
				string text2 = ((num > 2) ? "</color>" : "");
				AvailableEffectsHeader.text = Localization.instance.Localize("$mod_epicloot_augment_availableeffects " + text + "($mod_epicloot_augment_choices)" + text2, new string[1] { num.ToString() });
			}
			OnAugmentIndexChanged();
			List<InventoryItemListElement> source = GetAugmentableItems();
			AvailableItems.SetItems(source.Cast<IListElement>().ToList());
			DeselectAll();
		}

		public override void Update()
		{
			base.Update();
			if (!_locked && ZInput.IsGamepadActive())
			{
				if (ZInput.GetButtonDown("JoyButtonY"))
				{
					int num = AugmentSelectors.Count((Toggle x) => ((Behaviour)x).isActiveAndEnabled);
					int index = (_augmentIndex + 1) % num;
					AugmentSelectors[index].isOn = true;
					ZInput.ResetButtonStatus("JoyButtonY");
				}
				if ((Object)(object)AvailableEffectsScrollbar != (Object)null)
				{
					float joyRightStickY = ZInput.GetJoyRightStickY();
					if (Mathf.Abs(joyRightStickY) > 0.5f)
					{
						AvailableEffectsScrollbar.value = Mathf.Clamp01(AvailableEffectsScrollbar.value + joyRightStickY * -0.1f);
					}
				}
			}
			if (!((Object)(object)_choiceDialog != (Object)null) || _choiceDialog.activeSelf)
			{
				return;
			}
			Unlock();
			Object.Destroy((Object)(object)_choiceDialog);
			_choiceDialog = null;
			Cancel();
			AvailableItems.ForeachElement(delegate(int i, MultiSelectItemListElement e)
			{
				if (e.IsSelected())
				{
					e.SetItem(e.GetListElement());
					e.Refresh();
				}
			});
			RefreshAugmentSelectors();
			OnAugmentIndexChanged();
		}

		public void OnAugmentSelectorToggled(bool isOn)
		{
			if (isOn)
			{
				for (int i = 0; i < AugmentSelectors.Count; i++)
				{
					if (AugmentSelectors[i].isOn)
					{
						SelectAugmentIndex(i);
						break;
					}
				}
			}
			else if (!AugmentSelectors.Any((Toggle x) => x.isOn))
			{
				SelectAugmentIndex(-1);
			}
		}

		public void SelectAugmentIndex(int index)
		{
			if (index != _augmentIndex)
			{
				_augmentIndex = index;
				OnAugmentIndexChanged();
			}
		}

		public void OnAugmentIndexChanged()
		{
			Tuple<InventoryItemListElement, int> singleSelectedItem = AvailableItems.GetSingleSelectedItem<InventoryItemListElement>();
			if (singleSelectedItem?.Item1.GetItem() == null)
			{
				((Selectable)MainButton).interactable = false;
				AvailableEffectsText.text = "";
				((Behaviour)CostLabel).enabled = false;
				CostList.SetItems(new List<IListElement>());
				_augmentIndex = -1;
				{
					foreach (Toggle augmentSelector in AugmentSelectors)
					{
						augmentSelector.isOn = false;
					}
					return;
				}
			}
			if (_augmentIndex < 0)
			{
				AvailableEffectsText.text = string.Empty;
				((Behaviour)CostLabel).enabled = false;
				CostList.SetItems(new List<IListElement>());
				((Selectable)MainButton).interactable = false;
				return;
			}
			ItemData item = singleSelectedItem.Item1.GetItem();
			string text = GetAvailableEffects(item, _augmentIndex);
			AvailableEffectsText.text = text;
			ScrollEnchantInfoToTop();
			((Behaviour)CostLabel).enabled = true;
			List<InventoryItemListElement> list = GetAugmentCost(item, _augmentIndex);
			CostList.SetItems(list.Cast<IListElement>().ToList());
			Tuple<float, float> featureCurrentValue = EnchantingTableUI.instance.SourceTable.GetFeatureCurrentValue(EnchantingFeature.Augment);
			float num = (float.IsNaN(featureCurrentValue.Item2) ? 0f : featureCurrentValue.Item2);
			if (num > 0f)
			{
				CostLabel.text = Localization.instance.Localize($"$mod_epicloot_augmentcost <color=#EAA800>(-{num}% $item_coins!)</color>");
			}
			else
			{
				CostLabel.text = Localization.instance.Localize("$mod_epicloot_augmentcost");
			}
			bool flag = EnchantingTableUIPanelBase.LocalPlayerCanAffordCost(list);
			bool flag2 = EnchantingTableUI.instance.SourceTable.IsFeatureUnlocked(EnchantingFeature.Augment);
			((Selectable)MainButton).interactable = flag2 && flag && _augmentIndex >= 0;
		}

		private void ScrollEnchantInfoToTop()
		{
			AvailableEffectsScrollbar.value = 1f;
		}

		protected override void DoMainAction()
		{
			Tuple<InventoryItemListElement, int> singleSelectedItem = AvailableItems.GetSingleSelectedItem<InventoryItemListElement>();
			if (singleSelectedItem?.Item1.GetItem() == null)
			{
				Cancel();
				return;
			}
			ItemData item = singleSelectedItem.Item1.GetItem();
			List<InventoryItemListElement> list = GetAugmentCost(item, _augmentIndex);
			Player localPlayer = Player.m_localPlayer;
			if (!localPlayer.NoCostCheat())
			{
				if (!EnchantingTableUIPanelBase.LocalPlayerCanAffordCost(list))
				{
					Debug.LogError((object)"[Augment Item] ERROR: Tried to augment item but could not afford the cost. This should not happen!");
					return;
				}
				Inventory inventory = ((Humanoid)localPlayer).GetInventory();
				foreach (InventoryItemListElement item3 in list)
				{
					ItemData item2 = item3.GetItem();
					inventory.RemoveItem(item2.m_shared.m_name, item2.m_stack, -1, true);
				}
			}
			if ((Object)(object)_choiceDialog != (Object)null)
			{
				Object.Destroy((Object)(object)_choiceDialog);
			}
			_choiceDialog = AugmentItem(item, _augmentIndex);
			Lock();
		}

		protected override void OnSelectedItemsChanged()
		{
			ItemData val = AvailableItems.GetSingleSelectedItem<InventoryItemListElement>()?.Item1.GetItem();
			List<Tuple<string, bool>> list = GetAugmentableEffects(val);
			if (list.Count > AugmentSelectors.Count)
			{
				Debug.LogError((object)$"[Epic Loot] ERROR: Too many magic effects to show! (Max: {AugmentSelectors.Count})");
			}
			for (int i = 0; i < AugmentSelectors.Count; i++)
			{
				Toggle val2 = AugmentSelectors[i];
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				val2.SetIsOnWithoutNotify(i == 0);
				((Component)val2).gameObject.SetActive(val != null && i < list.Count);
				if (((Component)val2).gameObject.activeSelf)
				{
					Text componentInChildren = ((Component)val2).GetComponentInChildren<Text>();
					if ((Object)(object)componentInChildren != (Object)null)
					{
						componentInChildren.text = list[i].Item1;
						((Selectable)val2).interactable = list[i].Item2;
					}
				}
			}
			if (val == null)
			{
				AvailableEffectsText.text = string.Empty;
			}
			_augmentIndex = 0;
			OnAugmentIndexChanged();
		}

		private void RefreshAugmentSelectors()
		{
			ItemData val = AvailableItems.GetSingleSelectedItem<InventoryItemListElement>()?.Item1.GetItem();
			List<Tuple<string, bool>> list = GetAugmentableEffects(val);
			for (int i = 0; i < AugmentSelectors.Count; i++)
			{
				Toggle val2 = AugmentSelectors[i];
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				val2.SetIsOnWithoutNotify(i == _augmentIndex);
				((Component)val2).gameObject.SetActive(val != null && i < list.Count);
				if (((Component)val2).gameObject.activeSelf)
				{
					Text componentInChildren = ((Component)val2).GetComponentInChildren<Text>();
					if ((Object)(object)componentInChildren != (Object)null)
					{
						componentInChildren.text = list[i].Item1;
						((Selectable)val2).interactable = list[i].Item2;
					}
				}
			}
		}

		public override bool CanCancel()
		{
			if (!base.CanCancel())
			{
				if ((Object)(object)_choiceDialog != (Object)null)
				{
					return _choiceDialog.activeSelf;
				}
				return false;
			}
			return true;
		}

		public override void Cancel()
		{
			base.Cancel();
			OnAugmentIndexChanged();
		}

		public override void Lock()
		{
			base.Lock();
			foreach (Toggle augmentSelector in AugmentSelectors)
			{
				((Selectable)augmentSelector).interactable = false;
			}
		}

		public override void Unlock()
		{
			base.Unlock();
			foreach (Toggle augmentSelector in AugmentSelectors)
			{
				((Selectable)augmentSelector).interactable = true;
			}
		}

		public override void DeselectAll()
		{
			AvailableItems.DeselectAll();
		}
	}
	[RequireComponent(typeof(CanvasGroup))]
	public class EnchantBonus : MonoBehaviour
	{
		public float Delay = 1f;

		public float FadeTime = 1f;

		private CanvasGroup _group;

		private Coroutine _coroutine;

		public void Awake()
		{
			_group = ((Component)this).GetComponent<CanvasGroup>();
			_group.alpha = 0f;
		}

		public void OnEnable()
		{
			_group.alpha = 0f;
		}

		public void OnDestroy()
		{
			if (_coroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_coroutine);
			}
		}

		public IEnumerator FadeOut()
		{
			yield return (object)new WaitForSeconds(Delay);
			while (_group.alpha > 0f)
			{
				CanvasGroup group = _group;
				group.alpha -= Time.deltaTime * (1f / FadeTime);
				yield return null;
			}
		}

		public void Show()
		{
			if (_coroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_coroutine);
			}
			_group.alpha = 1f;
			_coroutine = ((MonoBehaviour)this).StartCoroutine(FadeOut());
		}
	}
	public class FeatureStatus : MonoBehaviour
	{
		public delegate void MakeFeatureUnlockTooltipDelegate(GameObject obj);

		public delegate bool UpgradesActiveDelegate(EnchantingFeature feature, out bool featureActive);

		public EnchantingFeature Feature;

		public Transform UnlockedContainer;

		public Transform LockedContainer;

		public GameObject UnlockedLabel;

		public Image[] Stars;

		public Text ManyStarsLabel;

		public UITooltip Tooltip;

		public static MakeFeatureUnlockTooltipDelegate MakeFeatureUnlockTooltip;

		public static UpgradesActiveDelegate UpgradesActive;

		public void Awake()
		{
			if ((Object)(object)Tooltip != (Object)null)
			{
				MakeFeatureUnlockTooltip(((Component)Tooltip).gameObject);
			}
		}

		public void OnEnable()
		{
			if ((Object)(object)EnchantingTableUI.instance != (Object)null && (Object)(object)EnchantingTableUI.instance.SourceTable != (Object)null)
			{
				EnchantingTableUI.instance.SourceTable.OnFeatureLevelChanged += OnFeatureLevelChanged;
			}
			Refresh();
		}

		public void OnDisable()
		{
			if ((Object)(object)EnchantingTableUI.instance != (Object)null && (Object)(object)EnchantingTableUI.instance.SourceTable != (Object)null)
			{
				EnchantingTableUI.instance.SourceTable.OnFeatureLevelChanged -= OnFeatureLevelChanged;
			}
		}

		public void SetFeature(EnchantingFeature feature)
		{
			if (Feature != feature)
			{
				Feature = feature;
				Refresh();
			}
		}

		public void Refresh()
		{
			if ((Object)(object)EnchantingTableUI.instance == (Object)null || (Object)(object)EnchantingTableUI.instance.SourceTable == (Object)null)
			{
				return;
			}
			if (!EnchantingTableUI.instance.SourceTable.IsFeatureAvailable(Feature))
			{
				if ((Object)(object)UnlockedContainer != (Object)null)
				{
					((Component)UnlockedContainer).gameObject.SetActive(false);
				}
				if ((Object)(object)LockedContainer != (Object)null)
				{
					((Component)LockedContainer).gameObject.SetActive(false);
				}
				return;
			}
			bool featureActive;
			if (EnchantingTableUI.instance.SourceTable.IsFeatureLocked(Feature))
			{
				if ((Object)(object)UnlockedContainer != (Object)null)
				{
					((Component)UnlockedContainer).gameObject.SetActive(false);
				}
				if ((Object)(object)LockedContainer != (Object)null)
				{
					((Component)LockedContainer).gameObject.SetActive(true);
				}
			}
			else
			{
				if ((Object)(object)UnlockedContainer != (Object)null)
				{
					((Component)UnlockedContainer).gameObject.SetActive(true);
				}
				if ((Object)(object)LockedContainer != (Object)null)
				{
					((Component)LockedContainer).gameObject.SetActive(false);
				}
				int featureLevel = EnchantingTableUI.instance.SourceTable.GetFeatureLevel(Feature);
				if (featureLevel > Stars.Length)
				{
					for (int i = 0; i < Stars.Length; i++)
					{
						((Behaviour)Stars[i]).enabled = i == 0;
					}
					if ((Object)(object)ManyStarsLabel != (Object)null)
					{
						((Behaviour)ManyStarsLabel).enabled = true;
						ManyStarsLabel.text = $"×{featureLevel}";
					}
				}
				else
				{
					for (int j = 0; j < Stars.Length; j++)
					{
						((Component)Stars[j]).gameObject.SetActive(featureLevel > j && UpgradesActive(Feature, out featureActive));
					}
					if ((Object)(object)ManyStarsLabel != (Object)null)
					{
						((Behaviour)ManyStarsLabel).enabled = false;
					}
				}
				if ((Object)(object)UnlockedLabel != (Object)null)
				{
					UnlockedLabel.SetActive(featureLevel == 0);
				}
			}
			if ((Object)(object)Tooltip != (Object)null && UpgradesActive(Feature, out featureActive))
			{
				Tooltip.m_topic = Localization.instance.Localize(EnchantingTableUpgrades.GetFeatureName(Feature));
				StringBuilder stringBuilder = new StringBuilder();
				bool num = EnchantingTableUI.instance.SourceTable.IsFeatureLocked(Feature);
				int featureLevel2 = EnchantingTableUI.instance.SourceTable.GetFeatureLevel(Feature);
				int featureMaxLevel = EnchantingTableUpgrades.GetFeatureMaxLevel(Feature);
				if (num)
				{
					stringBuilder.AppendLine(Localization.instance.Localize("$mod_epicloot_currentlevel: <color=#AD1616><b>$mod_epicloot_featurelocked</b></color>"));
				}
				else if (featureLevel2 == 0)
				{
					stringBuilder.AppendLine(Localization.instance.Localize($"$mod_epicloot_currentlevel: <color=#1AACEF><b>$mod_epicloot_featureunlocked</b></color> / {featureMaxLevel}"));
				}
				else
				{
					stringBuilder.AppendLine(Localization.instance.Localize($"$mod_epicloot_currentlevel: <color=#EAA800><b>{featureLevel2}</b></color> / {featureMaxLevel}"));
				}
				if (!num && featureLevel2 > 0)
				{
					string featureUpgradeLevelDescription = EnchantingTableUpgrades.GetFeatureUpgradeLevelDescription(EnchantingTableUI.instance.SourceTable, Feature, featureLevel2);
					stringBuilder.AppendLine("<color=#EAA800>" + featureUpgradeLevelDescription + "</color>");
				}
				stringBuilder.AppendLine();
				stringBuilder.AppendLine(Localization.instance.Localize(EnchantingTableUpgrades.GetFeatureDescription(Feature)));
				Tooltip.m_text = Localization.instance.Localize(stringBuilder.ToString());
			}
		}

		private void OnFeatureLevelChanged(EnchantingFeature feature, int _)
		{
			if (((Behaviour)this).isActiveAndEnabled && feature == Feature)
			{
				Refresh();
			}
		}
	}
	public class DisenchantUI : EnchantingTableUIPanelBase
	{
		public delegate List<InventoryItemListElement> GetDisenchantItemsDelegate();

		public delegate List<InventoryItemListElement> GetDisenchantCostDelegate(ItemData item);

		public delegate List<InventoryItemListElement> DisenchantItemDelegate(ItemData item);

		public Text CostLabel;

		public MultiSelectItemList CostList;

		public EnchantBonus BonusPanel;

		public static GetDisenchantItemsDelegate GetDisenchantItems;

		public static GetDisenchantCostDelegate GetDisenchantCost;

		public static DisenchantItemDelegate DisenchantItem;

		[UsedImplicitly]
		public void OnEnable()
		{
			List<InventoryItemListElement> source = GetDisenchantItems();
			AvailableItems.SetItems(source.Cast<IListElement>().ToList());
			AvailableItems.DeselectAll();
		}

		protected override void DoMainAction()
		{
			Cancel();
			Tuple<IListElement, int> singleSelectedItem = AvailableItems.GetSingleSelectedItem<IListElement>();
			if (singleSelectedItem?.Item1.GetItem() == null)
			{
				return;
			}
			ItemData item = singleSelectedItem.Item1.GetItem();
			List<InventoryItemListElement> list = GetDisenchantCost(item);
			if (!EnchantingTableUIPanelBase.LocalPlayerCanAffordCost(list))
			{
				return;
			}
			Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory();
			foreach (InventoryItemListElement item3 in list)
			{
				ItemData item2 = item3.GetItem();
				inventory.RemoveItem(item2.m_shared.m_name, item2.m_stack, -1, true);
			}
			List<InventoryItemListElement> list2 = DisenchantItem(item);
			if (list2.Count > 0)
			{
				EnchantingTableUI.instance.PlayEnchantBonusSFX();
				BonusPanel.Show();
				EnchantingTableUIPanelBase.GiveItemsToPlayer(list2);
			}
			RefreshAvailableItems();
		}

		public void RefreshAvailableItems()
		{
			List<InventoryItemListElement> source = GetDisenchantItems();
			AvailableItems.SetItems(source.Cast<IListElement>().ToList());
			AvailableItems.DeselectAll();
			OnSelectedItemsChanged();
		}

		protected override void OnSelectedItemsChanged()
		{
			Tuple<InventoryItemListElement, int> singleSelectedItem = AvailableItems.GetSingleSelectedItem<InventoryItemListElement>();
			if (singleSelectedItem != null)
			{
				((Behaviour)CostLabel).enabled = true;
				List<InventoryItemListElement> list = GetDisenchantCost(singleSelectedItem.Item1.GetItem());
				CostList.SetItems(list.Cast<IListElement>().ToList());
				Tuple<float, float> featureCurrentValue = EnchantingTableUI.instance.SourceTable.GetFeatureCurrentValue(EnchantingFeature.Disenchant);
				int num = ((!float.IsNaN(featureCurrentValue.Item2)) ? ((int)featureCurrentValue.Item2) : 0);
				if (num > 0 && list.Count > 0)
				{
					CostLabel.text = Localization.instance.Localize("$mod_epicloot_disenchantcost <color=#EAA800>($mod_epicloot_disenchantcostreduction)</color>", new string[1] { num.ToString() });
				}
				else
				{
					CostLabel.text = Localization.instance.Localize("$mod_epicloot_disenchantcost");
				}
				bool flag = EnchantingTableUIPanelBase.LocalPlayerCanAffordCost(list);
				bool flag2 = EnchantingTableUI.instance.SourceTable.IsFeatureUnlocked(EnchantingFeature.Disenchant);
				((Selectable)MainButton).interactable = flag2 && flag;
			}
			else
			{
				CostList.SetItems(new List<IListElement>());
				((Behaviour)CostLabel).enabled = false;
				((Selectable)MainButton).interactable = false;
			}
		}

		public override void DeselectAll()
		{
			AvailableItems.DeselectAll();
		}
	}
	public class EnchantingTable : MonoBehaviour, Hoverable, Interactable
	{
		public delegate bool UpgradesActiveDelegate(EnchantingFeature feature, out bool featureActive);

		public const float UseDistance = 2.7f;

		public const string DisplayNameLocID = "mod_epicloot_assets_enchantingtable";

		public const int FeatureUnavailableSentinel = -2;

		public const int FeatureLockedSentinel = -1;

		public const int FeatureLevelOne = 1;

		public GameObject EnchantingUIPrefab;

		public static UpgradesActiveDelegate UpgradesActive;

		private static readonly List<EnchantingFeatureUpgradeRequest> _upgradeRequests = new List<EnchantingFeatureUpgradeRequest>();

		private ZNetView _nview;

		private Player _interactingPlayer;

		public event Action<EnchantingFeature, int> OnFeatureLevelChanged;

		public event Action OnAnyFeatureLevelChanged;

		public bool Interact(Humanoid user, bool repeat, bool alt)
		{
			if (repeat || (Object)(object)user != (Object)(object)Player.m_localPlayer || !InUseDistance(user))
			{
				return false;
			}
			EnchantingTableUI.Show(EnchantingUIPrefab, this);
			_interactingPlayer = Player.m_localPlayer;
			return false;
		}

		public void Awake()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			_nview = ((Component)this).GetComponent<ZNetView>();
			if (!((Object)(object)_nview == (Object)null) && _nview.GetZDO() != null)
			{
				WearNTear component = ((Component)this).GetComponent<WearNTear>();
				if ((Object)(object)component != (Object)null)
				{
					component.m_destroyedEffect.m_effectPrefabs = (EffectData[])(object)new EffectData[2]
					{
						new EffectData
						{
							m_prefab = ZNetScene.instance.GetPrefab("vfx_SawDust")
						},
						new EffectData
						{
							m_prefab = ZNetScene.instance.GetPrefab("sfx_wood_destroyed")
						}
					};
					component.m_hitEffect.m_effectPrefabs = (EffectData[])(object)new EffectData[1]
					{
						new EffectData
						{
							m_prefab = ZNetScene.instance.GetPrefab("vfx_SawDust")
						}
					};
				}
				_nview.Register<ZDOID, int, int>("el.TableUpgradeRequest", (Action<long, ZDOID, int, int>)RPC_TableUpgradeRequest);
				_nview.Register<ZDOID, int, int, bool>("el.TableUpgradeResponse", (Method<ZDOID, int, int, bool>)RPC_TableUpgradeResponse);
				InitFeatureLevels();
			}
		}

		public void RequestTableUpgrade(EnchantingFeature feature, int toLevel, Action<bool> responseCallback)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			ZDOID uid = _nview.GetZDO().m_uid;
			_upgradeRequests.Add(new EnchantingFeatureUpgradeRequest
			{
				TableZDO = uid,
				Feature = feature,
				ToLevel = toLevel,
				ResponseCallback = responseCallback
			});
			_nview.InvokeRPC("el.TableUpgradeRequest", new object[3]
			{
				uid,
				(int)feature,
				toLevel
			});
		}

		private void RPC_TableUpgradeRequest(long sender, ZDOID tableZDO, int featureI, int toLevel)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			if (!_nview.IsOwner())
			{
				return;
			}
			GameObject val = ZNetScene.instance.FindInstance(tableZDO);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			EnchantingTable component = val.GetComponent<EnchantingTable>();
			if (!((Object)(object)component == (Object)null))
			{
				if (component.IsFeatureAvailable((EnchantingFeature)featureI) && toLevel == component.GetFeatureLevel((EnchantingFeature)featureI) + 1)
				{
					component.SetFeatureLevel((EnchantingFeature)featureI, toLevel);
					_nview.InvokeRPC(sender, "el.TableUpgradeResponse", new object[4] { tableZDO, featureI, toLevel, true });
					this.OnFeatureLevelChanged?.Invoke((EnchantingFeature)featureI, toLevel);
					this.OnAnyFeatureLevelChanged?.Invoke();
				}
				else
				{
					_nview.InvokeRPC(sender, "el.TableUpgradeResponse", new object[4] { tableZDO, featureI, toLevel, false });
				}
			}
		}

		private void RPC_TableUpgradeResponse(long sender, ZDOID tableZDO, int featureI, int toLevel, bool success)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			foreach (EnchantingFeatureUpgradeRequest item in _upgradeRequests.ToList())
			{
				if (!(item.TableZDO == tableZDO) || item.Feature != (EnchantingFeature)featureI || item.ToLevel != toLevel)
				{
					continue;
				}
				item.ResponseCallback(success);
				_upgradeRequests.Remove(item);
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					if (toLevel == 0)
					{
						((Character)Player.m_localPlayer).Message((MessageType)2, Localization.instance.Localize("$mod_epicloot_unlockmessage", new string[1] { EnchantingTableUpgrades.GetFeatureName((EnchantingFeature)featureI) }), 0, (Sprite)null);
					}
					else
					{
						((Character)Player.m_localPlayer).Message((MessageType)2, Localization.instance.Localize("$mod_epicloot_upgrademessage", new string[2]
						{
							EnchantingTableUpgrades.GetFeatureName((EnchantingFeature)featureI),
							toLevel.ToString()
						}), 0, (Sprite)null);
					}
				}
			}
		}

		public void Update()
		{
			if ((Object)(object)_interactingPlayer != (Object)null && (Object)(object)EnchantingTableUI.instance != (Object)null && ((Behaviour)EnchantingTableUI.instance).isActiveAndEnabled && !InUseDistance((Humanoid)(object)_interactingPlayer))
			{
				EnchantingTableUI.Hide();
				_interactingPlayer = null;
			}
		}

		public void Refresh()
		{
			this.OnAnyFeatureLevelChanged?.Invoke();
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}

		public bool InUseDistance(Humanoid human)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.Distance(((Component)human).transform.position, ((Component)this).transform.position) < 2.7f;
		}

		public string GetHoverText()
		{
			if (InUseDistance((Humanoid)(object)Player.m_localPlayer))
			{
				return Localization.instance.Localize("$mod_epicloot_assets_enchantingtable\n[<color=yellow><b>$KEY_Use</b></color>] $piece_use");
			}
			return Localization.instance.Localize("<color=#808080ff>$piece_toofar</color>");
		}

		public string GetHoverName()
		{
			return "mod_epicloot_assets_enchantingtable";
		}

		private string FormatFeatureName(string featureName)
		{
			return string.Format("el.et.v1." + featureName);
		}

		private void InitFeatureLevels()
		{
			foreach (EnchantingFeature value in Enum.GetValues(typeof(EnchantingFeature)))
			{
				string featureName = value.ToString();
				if (_nview.GetZDO().GetInt(FormatFeatureName(featureName), -888) == -888)
				{
					_nview.GetZDO().Set(FormatFeatureName(featureName), GetDefaultFeatureLevel(value) + 1);
				}
			}
		}

		private static int GetDefaultFeatureLevel(EnchantingFeature feature)
		{
			if (!UpgradesActive(feature, out var featureActive))
			{
				return 1;
			}
			if (!featureActive)
			{
				return -2;
			}
			if (!EnchantingTableUpgrades.Config.DefaultFeatureLevels.TryGetValue(feature, out var value))
			{
				return -2;
			}
			return value;
		}

		public void Reset()
		{
			foreach (EnchantingFeature value in Enum.GetValues(typeof(EnchantingFeature)))
			{
				SetFeatureLevel(value, GetDefaultFeatureLevel(value));
			}
		}

		public int GetFeatureLevel(EnchantingFeature feature)
		{
			if ((Object)(object)_nview == (Object)null || _nview.GetZDO() == null)
			{
				return -2;
			}
			if (!UpgradesActive(feature, out var featureActive))
			{
				return 1;
			}
			if (!featureActive)
			{
				return -2;
			}
			string featureName = feature.ToString();
			int @int = _nview.GetZDO().GetInt(FormatFeatureName(featureName), -2);
			_ = -2;
			if (@int != -2)
			{
				return @int - 1;
			}
			return -2;
		}

		public void SetFeatureLevel(EnchantingFeature feature, int level)
		{
			if (!((Object)(object)_nview == (Object)null))
			{
				int value;
				if (!UpgradesActive(feature, out var _))
				{
					level = 1;
				}
				else if (level > ((!EnchantingTableUpgrades.Config.MaximumFeatureLevels.TryGetValue(feature, out value)) ? 1 : value))
				{
					return;
				}
				string featureName = feature.ToString();
				_nview.GetZDO().Set(FormatFeatureName(featureName), level + 1);
				this.OnFeatureLevelChanged?.Invoke(feature, level);
				this.OnAnyFeatureLevelChanged?.Invoke();
			}
		}

		public bool IsFeatureAvailable(EnchantingFeature feature)
		{
			return GetFeatureLevel(feature) > -2;
		}

		public bool IsFeatureLocked(EnchantingFeature feature)
		{
			return GetFeatureLevel(feature) == -1;
		}

		public bool IsFeatureUnlocked(EnchantingFeature feature)
		{
			return GetFeatureLevel(feature) > -1;
		}

		public bool IsFeatureMaxLevel(EnchantingFeature feature)
		{
			return GetFeatureLevel(feature) == EnchantingTableUpgrades.GetFeatureMaxLevel(feature);
		}

		public List<InventoryItemListElement> GetFeatureUnlockCost(EnchantingFeature feature)
		{
			if (IsFeatureUnlocked(feature))
			{
				Debug.LogWarning((object)$"[EpicLoot] Warning: tried to get unlock cost for a feature that is already unlocked! ({feature})");
			}
			return EnchantingTableUpgrades.GetUpgradeCost(feature, 0);
		}

		public List<InventoryItemListElement> GetFeatureUpgradeCost(EnchantingFeature feature)
		{
			if (IsFeatureLocked(feature) || !IsFeatureAvailable(feature))
			{
				Debug.LogWarning((object)$"[EpicLoot] Warning: tried to get enchanting feature unlock cost for a feature that is locked or unavailable! ({feature})");
			}
			int featureLevel = GetFeatureLevel(feature);
			return EnchantingTableUpgrades.GetUpgradeCost(feature, featureLevel + 1);
		}

		public Tuple<float, float> GetFeatureValue(EnchantingFeature feature, int level)
		{
			if (!IsFeatureAvailable(feature))
			{
				return new Tuple<float, float>(float.NaN, float.NaN);
			}
			if (level < 0 || level > EnchantingTableUpgrades.GetFeatureMaxLevel(feature))
			{
				return new Tuple<float, float>(float.NaN, float.NaN);
			}
			List<float[]> list = feature switch
			{
				EnchantingFeature.Sacrifice => EnchantingTableUpgrades.Config.UpgradeValues.Sacrifice, 
				EnchantingFeature.ConvertMaterials => EnchantingTableUpgrades.Config.UpgradeValues.ConvertMaterials, 
				EnchantingFeature.Enchant => EnchantingTableUpgrades.Config.UpgradeValues.Enchant, 
				EnchantingFeature.Augment => EnchantingTableUpgrades.Config.UpgradeValues.Augment, 
				EnchantingFeature.Disenchant => EnchantingTableUpgrades.Config.UpgradeValues.Disenchant, 
				EnchantingFeature.Helheim => EnchantingTableUpgrades.Config.UpgradeValues.Helheim, 
				_ => throw new ArgumentOutOfRangeException("feature", feature, null), 
			};
			if (level >= list.Count)
			{
				return new Tuple<float, float>(float.NaN, float.NaN);
			}
			float[] array = list[level];
			if (array.Length == 1)
			{
				return new Tuple<float, float>(array[0], float.NaN);
			}
			if (array.Length >= 2)
			{
				return new Tuple<float, float>(array[0], array[1]);
			}
			return new Tuple<float, float>(float.NaN, float.NaN);
		}

		public Tuple<float, float> GetFeatureCurrentValue(EnchantingFeature feature)
		{
			return GetFeatureValue(feature, GetFeatureLevel(feature));
		}
	}
	public class EnchantingTableUI : MonoBehaviour
	{
		public delegate void AugaFixupDelegate(EnchantingTableUI ui);

		public delegate void TabActivationDelegate(EnchantingTableUI ui);

		public GameObject Root;

		public GameObject Scrim;

		public TabHandler TabHandler;

		public GameObject TabScrim;

		[Header("Content")]
		public EnchantingTableUIPanelBase[] Panels;

		[Header("Audio")]
		public AudioSource Audio;

		public AudioClip TabClickSFX;

		public AudioClip EnchantBonusSFX;

		public static AugaFixupDelegate AugaFixup;

		public static TabActivationDelegate TabActivation;

		private int _hiddenFrames;

		public EnchantingTable SourceTable { get; private set; }

		public static EnchantingTableUI instance { get; set; }

		public void Awake()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			instance = this;
			Localization.instance.Localize(((Component)this).transform);
			GameObject val = GameObject.Find("sfx_gui_button");
			if (Object.op_Implicit((Object)(object)val))
			{
				Audio.outputAudioMixerGroup = val.GetComponent<AudioSource>().outputAudioMixerGroup;
			}
			for (int i = 0; i < TabHandler.m_tabs.Count; i++)
			{
				Tab obj = TabHandler.m_tabs[i];
				obj.m_onClick.AddListener(new UnityAction(PlayTabSelectSFX));
				FeatureStatus component = ((Component)obj.m_button).gameObject.GetComponent<FeatureStatus>();
				if ((Object)(object)component != (Object)null)
				{
					component.SetFeature((EnchantingFeature)i);
				}
			}
			AugaFixup(this);
			TabActivation(this);
		}

		public static void Show(GameObject enchantingUiPrefab, EnchantingTable source)
		{
			if ((Object)(object)instance == (Object)null && (Object)(object)StoreGui.instance != (Object)null)
			{
				Transform parent = ((Component)StoreGui.instance).transform.parent;
				int siblingIndex = ((Component)StoreGui.instance).transform.GetSiblingIndex() + 1;
				Object.Instantiate<GameObject>(enchantingUiPrefab, parent).transform.SetSiblingIndex(siblingIndex);
			}
			if (!((Object)(object)instance == (Object)null))
			{
				instance.SourceTable = source;
				instance.Root.SetActive(true);
				instance.Scrim.SetActive(true);
				instance.SourceTable.Refresh();
				EnchantingTableUIPanelBase[] panels = instance.Panels;
				for (int i = 0; i < panels.Length; i++)
				{
					panels[i].DeselectAll();
				}
			}
		}

		public static void Hide()
		{
			if (!((Object)(object)instance == (Object)null))
			{
				instance.Root.SetActive(false);
				instance.Scrim.SetActive(false);
				instance.SourceTable = null;
			}
		}

		public static bool IsVisible()
		{
			if ((Object)(object)instance != (Object)null)
			{
				if (instance._hiddenFrames > 2)
				{
					if ((Object)(object)instance.Root != (Object)null)
					{
						return instance.Root.activeSelf;
					}
					return false;
				}
				return true;
			}
			return false;
		}

		public static bool IsInTextInput()
		{
			if (!IsVisible())
			{
				return false;
			}
			InputField[] componentsInChildren = instance.Root.GetComponentsInChildren<InputField>(false);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (componentsInChildren[i].isFocused)
				{
					return true;
				}
			}
			return false;
		}

		public void Update()
		{
			if ((Object)(object)Root == (Object)null)
			{
				return;
			}
			if (!Root.activeSelf)
			{
				_hiddenFrames++;
				return;
			}
			_hiddenFrames = 0;
			if (((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()) || Console.IsVisible() || Menu.IsVisible() || ((Object)(object)TextViewer.instance != (Object)null && TextViewer.instance.IsVisible()) || ((Character)Player.m_localPlayer).InCutscene() || (!ZInput.GetButtonDown("JoyButtonB") && !Input.GetKeyDown((KeyCode)27) && !Input.GetKeyDown((KeyCode)9)))
			{
				return;
			}
			ZInput.ResetButtonStatus("JoyButtonB");
			ZInput.ResetButtonStatus("JoyJump");
			bool flag = false;
			EnchantingTableUIPanelBase[] panels = Panels;
			foreach (EnchantingTableUIPanelBase enchantingTableUIPanelBase in panels)
			{
				if (((Behaviour)enchantingTableUIPanelBase).isActiveAndEnabled && enchantingTableUIPanelBase.CanCancel())
				{
					enchantingTableUIPanelBase.Cancel();
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				Hide();
			}
		}

		public static void UpdateTabActivation()
		{
			TabActivation(instance);
		}

		public static void UpdateUpgradeActivation()
		{
			TabActivation(instance);
		}

		public void LockTabs()
		{
			TabScrim.SetActive(true);
		}

		public void UnlockTabs()
		{
			TabScrim.SetActive(false);
		}

		public void PlayTabSelectSFX()
		{
			Audio.PlayOneShot(TabClickSFX);
		}

		public void PlayEnchantBonusSFX()
		{
			Audio.PlayOneShot(EnchantBonusSFX);
		}
	}
	public abstract class EnchantingTableUIPanelBase : MonoBehaviour
	{
		public const float CountdownTime = 0.8f;

		public MultiSelectItemList AvailableItems;

		public Button MainButton;

		public GameObject LevelDisplay;

		public GuiBar ProgressBar;

		public AudioSource Audio;

		public AudioClip ProgressLoopSFX;

		public AudioClip CompleteSFX;

		protected bool _inProgress;

		protected float _countdown;

		protected Text _buttonLabel;

		protected TMP_Text _tmpButtonLabel;

		protected bool _useTMP;

		protected string _defaultButtonLabelText;

		protected bool _locked;

		protected abstract void DoMainAction();

		protected abstract void OnSelectedItemsChanged();

		public virtual void Awake()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			if ((Object)(object)AvailableItems != (Object)null)
			{
				AvailableItems.OnSelectedItemsChanged += OnSelectedItemsChanged;
				AvailableItems.GiveFocus(focused: true, 0);
			}
			if ((Object)(object)MainButton != (Object)null)
			{
				((UnityEvent)MainButton.onClick).AddListener(new UnityAction(OnMainButtonClicked));
				_buttonLabel = ((Component)MainButton).GetComponentInChildren<Text>();
				if ((Object)(object)_buttonLabel == (Object)null)
				{
					_tmpButtonLabel = ((Component)MainButton).GetComponentInChildren<TMP_Text>();
					_useTMP = true;
				}
				_defaultButtonLabelText = (_useTMP ? _tmpButtonLabel.text : _buttonLabel.text);
			}
			GameObject val = GameObject.Find("sfx_gui_button");
			if (Object.op_Implicit((Object)(object)val) && (Object)(object)Audio != (Object)null)
			{
				Audio.outputAudioMixerGroup = val.GetComponent<AudioSource>().outputAudioMixerGroup;
			}
		}

		protected virtual void OnMainButtonClicked()
		{
			if (_inProgress)
			{
				Cancel();
			}
			else
			{
				StartProgress();
			}
		}

		public virtual void DeselectAll()
		{
		}

		public virtual void Update()
		{
			if ((Object)(object)ProgressBar != (Object)null)
			{
				((Component)ProgressBar).gameObject.SetActive(_inProgress);
			}
			if ((Object)(object)LevelDisplay != (Object)null)
			{
				LevelDisplay.gameObject.SetActive(!_inProgress);
			}
			if (!_inProgress)
			{
				return;
			}
			if ((Object)(object)ProgressBar != (Object)null)
			{
				ProgressBar.SetValue(0.8f - _countdown);
			}
			_countdown -= Time.deltaTime;
			if (_countdown < 0f)
			{
				_inProgress = false;
				_countdown = 0f;
				if ((Object)(object)Audio != (Object)null)
				{
					Audio.loop = false;
					Audio.Stop();
				}
				DoMainAction();
				PlayCompleteSFX();
			}
		}

		private void PlayCompleteSFX()
		{
			AudioClip completeAudioClip = GetCompleteAudioClip();
			if ((Object)(object)Audio != (Object)null && (Object)(object)completeAudioClip != (Object)null)
			{
				Audio.PlayOneShot(completeAudioClip);
			}
		}

		protected virtual AudioClip GetCompleteAudioClip()
		{
			return CompleteSFX;
		}

		public virtual void StartProgress()
		{
			if (_useTMP)
			{
				_tmpButtonLabel.text = Localization.instance.Localize("$menu_cancel");
			}
			else
			{
				_buttonLabel.text = Localization.instance.Localize("$menu_cancel");
			}
			_inProgress = true;
			_countdown = 0.8f;
			if ((Object)(object)ProgressBar != (Object)null)
			{
				ProgressBar.SetMaxValue(0.8f);
			}
			if ((Object)(object)Audio != (Object)null)
			{
				Audio.loop = true;
				Audio.clip = ProgressLoopSFX;
				Audio.Play();
			}
			Lock();
		}

		public virtual bool CanCancel()
		{
			return _inProgress;
		}

		public virtual void Cancel()
		{
			if (_useTMP)
			{
				_tmpButtonLabel.text = Localization.instance.Localize(_defaultButtonLabelText);
			}
			else
			{
				_buttonLabel.text = Localization.instance.Localize(_defaultButtonLabelText);
			}
			_inProgress = false;
			_countdown = 0f;
			if ((Object)(object)Audio != (Object)null)
			{
				Audio.loop = false;
				Audio.Stop();
			}
			Unlock();
		}

		public virtual void Lock()
		{
			_locked = true;
			MultiSelectItemList[] componentsInChildren = ((Component)this).GetComponentsInChildren<MultiSelectItemList>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].Lock();
			}
			EnchantingTableUI.instance.LockTabs();
		}

		public virtual void Unlock()
		{
			_locked = false;
			MultiSelectItemList[] componentsInChildren = ((Component)this).GetComponentsInChildren<MultiSelectItemList>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].Unlock();
			}
			EnchantingTableUI.instance.UnlockTabs();
		}

		protected static bool LocalPlayerCanAffordCost(List<InventoryItemListElement> cost)
		{
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer.NoCostCheat())
			{
				return true;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			foreach (InventoryItemListElement item2 in cost)
			{
				ItemData item = item2.GetItem();
				if (inventory.CountItems(item.m_shared.m_name, -1, true) < item.m_stack)
				{
					return false;
				}
			}
			return true;
		}

		protected static void GiveItemsToPlayer(List<InventoryItemListElement> sacrificeProducts)
		{
			//IL_00b2: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			foreach (InventoryItemListElement sacrificeProduct in sacrificeProducts)
			{
				ItemData item = sacrificeProduct.GetItem();
				do
				{
					ItemData val = item.Clone();
					val.m_stack = Mathf.Min(item.m_stack, item.m_shared.m_maxStackSize);
					item.m_stack -= val.m_stack;
					if (inventory.CanAddItem(val, -1))
					{
						inventory.AddItem(val);
						((Character)localPlayer).Message((MessageType)1, "$msg_added " + val.m_shared.m_name, val.m_stack, val.GetIcon());
					}
					else
					{
						ItemDrop val2 = ItemDrop.DropItem(val, val.m_stack, ((Component)localPlayer).transform.position + ((Component)localPlayer).transform.forward + ((Component)localPlayer).transform.up, ((Component)localPlayer).transform.rotation);
						((Component)val2).GetComponent<Rigidbody>().velocity = Vector3.up * 5f;
						((Character)localPlayer).Message((MessageType)1, "$msg_dropped " + val2.m_itemData.m_shared.m_name + " $mod_epicloot_sacrifice_inventoryfullexplanation", val2.m_itemData.m_stack, val2.m_itemData.GetIcon());
					}
				}
				while (item.m_stack > 0);
			}
		}
	}
	public enum EnchantingFeature
	{
		Sacrifice,
		ConvertMaterials,
		Enchant,
		Augment,
		Disenchant,
		Helheim
	}
	[Serializable]
	public class ItemAmount
	{
		public string Item = "";

		public int Amount = 1;
	}
	[Serializable]
	public class EnchantingUpgradeCosts
	{
		public List<List<ItemAmount>> Sacrifice;

		public List<List<ItemAmount>> ConvertMaterials;

		public List<List<ItemAmount>> Enchant;

		public List<List<ItemAmount>> Augment;

		public List<List<ItemAmount>> Disenchant;

		public List<List<ItemAmount>> Helheim;
	}
	[Serializable]
	public class EnchantingFeatureValues
	{
		public List<float[]> Sacrifice;

		public List<float[]> ConvertMaterials;

		public List<float[]> Enchant;

		public List<float[]> Augment;

		public List<float[]> Disenchant;

		public List<float[]> Helheim;
	}
	[Serializable]
	public class EnchantingUpgradesConfig
	{
		public Dictionary<EnchantingFeature, int> DefaultFeatureLevels;

		public Dictionary<EnchantingFeature, int> MaximumFeatureLevels;

		public EnchantingUpgradeCosts UpgradeCosts;

		public EnchantingFeatureValues UpgradeValues;
	}
	public class EnchantingFeatureUpgradeRequest
	{
		public ZDOID TableZDO;

		public EnchantingFeature Feature;

		public int ToLevel;

		public Action<bool> ResponseCallback;
	}
	public static class EnchantingTableUpgrades
	{
		public static EnchantingUpgradesConfig Config;

		public static void InitializeConfig(EnchantingUpgradesConfig config)
		{
			Config = config;
		}

		public static string GetFeatureName(EnchantingFeature feature)
		{
			return (new string[6] { "$mod_epicloot_sacrifice", "$mod_epicloot_convertmaterials", "$mod_epicloot_enchant", "$mod_epicloot_augment", "$mod_epicloot_disenchant", "$mod_epicloot_helheim" })[(int)feature];
		}

		public static string GetFeatureDescription(EnchantingFeature feature)
		{
			return (new string[6] { "$mod_epicloot_featureinfo_sacrifice", "$mod_epicloot_featureinfo_convertmaterials", "$mod_epicloot_featureinfo_enchant", "$mod_epicloot_featureinfo_augment", "$mod_epicloot_featureinfo_disenchant", "$mod_epicloot_featureinfo_helheim" })[(int)feature];
		}

		public static string GetFeatureUpgradeLevelDescription(EnchantingTable table, EnchantingFeature feature, int level)
		{
			string[] array = new string[6] { "$mod_epicloot_featureupgrade_sacrifice", "$mod_epicloot_featureupgrade_convertmaterials", "$mod_epicloot_featureupgrade_enchant", "$mod_epicloot_featureupgrade_augment", "$mod_epicloot_featureupgrade_disenchant", "$mod_epicloot_featureupgrade_helheim" };
			Tuple<float, float> featureValue = table.GetFeatureValue(feature, level);
			return Localization.instance.Localize(array[(int)feature], new string[2]
			{
				featureValue.Item1.ToString("0.#"),
				featureValue.Item2.ToString("0.#")
			});
		}

		public static int GetFeatureMaxLevel(EnchantingFeature feature)
		{
			if (!Config.MaximumFeatureLevels.TryGetValue(feature, out var value))
			{
				return 1;
			}
			return value;
		}

		public static List<InventoryItemListElement> GetUpgradeCost(EnchantingFeature feature, int level)
		{
			List<InventoryItemListElement> list = new List<InventoryItemListElement>();
			List<List<ItemAmount>> list2 = feature switch
			{
				EnchantingFeature.Sacrifice => Config.UpgradeCosts.Sacrifice, 
				EnchantingFeature.ConvertMaterials => Config.UpgradeCosts.ConvertMaterials, 
				EnchantingFeature.Enchant => Config.UpgradeCosts.Enchant, 
				EnchantingFeature.Augment => Config.UpgradeCosts.Augment, 
				EnchantingFeature.Disenchant => Config.UpgradeCosts.Disenchant, 
				EnchantingFeature.Helheim => Config.UpgradeCosts.Helheim, 
				_ => throw new ArgumentOutOfRangeException("feature", feature, null), 
			};
			if (list2 == null)
			{
				return list;
			}
			if (level < 0 || level >= list2.Count)
			{
				Debug.LogWarning((object)$"[EpicLoot] Warning: tried to get enchanting feature upgrade cost for level that does not exist ({feature}, {level})");
				return list;
			}
			List<ItemAmount> list3 = list2[level];
			if (list3 == null)
			{
				return list;
			}
			foreach (ItemAmount item in list3)
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item.Item);
				if ((Object)(object)itemPrefab == (Object)null)
				{
					Debug.LogWarning((object)$"[EpicLoot] Tried to add unknown item ({item.Item}) to upgrade cost for feature ({feature}, {level})");
					continue;
				}
				ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
				if ((Object)(object)component == (Object)null)
				{
					Debug.LogWarning((object)$"[EpicLoot] Tried to add item without ItemDrop ({item.Item}) to upgrade cost for feature ({feature}, {level})");
					continue;
				}
				ItemData val = component.m_itemData.Clone();
				val.m_dropPrefab = itemPrefab;
				val.m_stack = item.Amount;
				list.Add(new InventoryItemListElement
				{
					Item = val
				});
			}
			return list;
		}
	}
	public class EnchantUI : EnchantingTableUIPanelBase
	{
		public delegate List<InventoryItemListElement> GetEnchantableItemsDelegate();

		public delegate string GetEnchantInfoDelegate(ItemData item, MagicRarityUnity rarity);

		public delegate List<InventoryItemListElement> GetEnchantCostDelegate(ItemData item, MagicRarityUnity rarity);

		public delegate GameObject EnchantItemDelegate(ItemData item, MagicRarityUnity rarity);

		public Text EnchantInfo;

		public Scrollbar EnchantInfoScrollbar;

		public List<Toggle> RarityButtons;

		[Header("Cost")]
		public Text CostLabel;

		public MultiSelectItemList CostList;

		public AudioClip[] EnchantCompleteSFX;

		public static GetEnchantableItemsDelegate GetEnchantableItems;

		public static GetEnchantInfoDelegate GetEnchantInfo;

		public static GetEnchantCostDelegate GetEnchantCost;

		public static EnchantItemDelegate EnchantItem;

		private ToggleGroup _toggleGroup;

		private MagicRarityUnity _rarity;

		private GameObject _successDialog;

		public override void Awake()
		{
			base.Awake();
			if (RarityButtons.Count > 0)
			{
				_toggleGroup = RarityButtons[0].group;
				_toggleGroup.EnsureValidState();
			}
			for (int i = 0; i < RarityButtons.Count; i++)
			{
				((UnityEvent<bool>)(object)RarityButtons[i].onValueChanged).AddListener((UnityAction<bool>)delegate(bool isOn)
				{
					if (isOn)
					{
						RefreshRarity();
					}
				});
			}
		}

		[UsedImplicitly]
		public void OnEnable()
		{
			_rarity = MagicRarityUnity.Magic;
			OnRarityChanged();
			RarityButtons[0].isOn = true;
			List<InventoryItemListElement> source = GetEnchantableItems();
			AvailableItems.SetItems(source.Cast<IListElement>().ToList());
		}

		public override void Update()
		{
			base.Update();
			if (!_locked && ZInput.IsGamepadActive())
			{
				if (ZInput.GetButtonDown("JoyButtonY"))
				{
					int index = (int)(_rarity + 1) % RarityButtons.Count;
					RarityButtons[index].isOn = true;
					ZInput.ResetButtonStatus("JoyButtonY");
				}
				if ((Object)(object)EnchantInfoScrollbar != (Object)null)
				{
					float joyRightStickY = ZInput.GetJoyRightStickY();
					if (Mathf.Abs(joyRightStickY) > 0.5f)
					{
						EnchantInfoScrollbar.value = Mathf.Clamp01(EnchantInfoScrollbar.value + joyRightStickY * -0.1f);
					}
				}
			}
			if ((Object)(object)_successDialog != (Object)null && !_successDialog.activeSelf)
			{
				Unlock();
				Object.Destroy((Object)(object)_successDialog);
				_successDialog = null;
			}
		}

		public void RefreshRarity()
		{
			MagicRarityUnity rarity = _rarity;
			for (int i = 0; i < RarityButtons.Count; i++)
			{
				if (RarityButtons[i].isOn)
				{
					_rarity = (MagicRarityUnity)i;
				}
			}
			if (rarity != _rarity)
			{
				OnRarityChanged();
			}
		}

		public void OnRarityChanged()
		{
			Tuple<InventoryItemListElement, int> singleSelectedItem = AvailableItems.GetSingleSelectedItem<InventoryItemListElement>();
			if (singleSelectedItem?.Item1.GetItem() == null)
			{
				((Selectable)MainButton).interactable = false;
				EnchantInfo.text = "";
				((Behaviour)CostLabel).enabled = false;
				CostList.SetItems(new List<IListElement>());
				return;
			}
			ItemData item = singleSelectedItem.Item1.GetItem();
			string text = GetEnchantInfo(item, _rarity);
			EnchantInfo.text = text;
			ScrollEnchantInfoToTop();
			((Behaviour)CostLabel).enabled = true;
			List<InventoryItemListElement> list = GetEnchantCost(item, _rarity);
			CostList.SetItems(list.Cast<IListElement>().ToList());
			bool flag = EnchantingTableUIPanelBase.LocalPlayerCanAffordCost(list);
			bool flag2 = EnchantingTableUI.instance.SourceTable.IsFeatureUnlocked(EnchantingFeature.Enchant);
			((Selectable)MainButton).interactable = flag2 && flag;
		}

		private void ScrollEnchantInfoToTop()
		{
			EnchantInfoScrollbar.value = 1f;
		}

		protected override void DoMainAction()
		{
			Tuple<InventoryItemListElement, int> tuple = AvailableItems.GetSelectedItems<InventoryItemListElement>().FirstOrDefault();
			Cancel();
			if (tuple?.Item1.GetItem() == null)
			{
				return;
			}
			ItemData item = tuple.Item1.GetItem();
			List<InventoryItemListElement> list = GetEnchantCost(item, _rarity);
			Player localPlayer = Player.m_localPlayer;
			if (!localPlayer.NoCostCheat())
			{
				if (!EnchantingTableUIPanelBase.LocalPlayerCanAffordCost(list))
				{
					Debug.LogError((object)"[Enchant Item] ERROR: Tried to enchant item but could not afford the cost. This should not happen!");
					return;
				}
				Inventory inventory = ((Humanoid)localPlayer).GetInventory();
				foreach (InventoryItemListElement item3 in list)
				{
					ItemData item2 = item3.GetItem();
					inventory.RemoveItem(item2.m_shared.m_name, item2.m_stack, -1, true);
				}
			}
			if ((Object)(object)_successDialog != (Object)null)
			{
				Object.Destroy((Object)(object)_successDialog);
			}
			DeselectAll();
			Lock();
			_successDialog = EnchantItem(item, _rarity);
			RefreshAvailableItems();
		}

		protected override AudioClip GetCompleteAudioClip()
		{
			return EnchantCompleteSFX[(int)_rarity];
		}

		public void RefreshAvailableItems()
		{
			List<InventoryItemListElement> source = GetEnchantableItems();
			AvailableItems.SetItems(source.Cast<IListElement>().ToList());
			AvailableItems.DeselectAll();
			OnSelectedItemsChanged();
		}

		protected override void OnSelectedItemsChanged()
		{
			OnRarityChanged();
		}

		public override bool CanCancel()
		{
			if (!base.CanCancel())
			{
				if ((Object)(object)_successDialog != (Object)null)
				{
					return _successDialog.activeSelf;
				}
				return false;
			}
			return true;
		}

		public override void Cancel()
		{
			base.Cancel();
			if ((Object)(object)_successDialog != (Object)null && _successDialog.activeSelf)
			{
				Object.Destroy((Object)(object)_successDialog);
				_successDialog = null;
			}
			OnRarityChanged();
		}

		public override void Lock()
		{
			base.Lock();
			foreach (Toggle rarityButton in RarityButtons)
			{
				((Selectable)rarityButton).interactable = false;
			}
		}

		public override void Unlock()
		{
			base.Unlock();
			foreach (Toggle rarityButton in RarityButtons)
			{
				((Selectable)rarityButton).interactable = true;
			}
		}

		public override void DeselectAll()
		{
			AvailableItems.DeselectAll();
		}
	}
	public class FeatureStatus3D : MonoBehaviour
	{
		public EnchantingTable SourceTable;

		public EnchantingFeature Feature;

		public GameObject UnlockedObject;

		public GameObject[] LevelObjects;

		public void OnEnable()
		{
			SourceTable.OnAnyFeatureLevelChanged += Refresh;
			Refresh();
		}

		public void OnDisable()
		{
			SourceTable.OnAnyFeatureLevelChanged -= Refresh;
		}

		public void Refresh()
		{
			bool flag = SourceTable.IsFeatureAvailable(Feature) && SourceTable.IsFeatureUnlocked(Feature);
			if ((Object)(object)UnlockedObject != (Object)null)
			{
				UnlockedObject.SetActive(flag);
			}
			int featureLevel = SourceTable.GetFeatureLevel(Feature);
			for (int i = 0; i < LevelObjects.Length; i++)
			{
				GameObject val = LevelObjects[i];
				if (!((Object)(object)val == (Object)null))
				{
					val.SetActive(flag && featureLevel == i);
				}
			}
			if (flag && featureLevel >= LevelObjects.Length && (Object)(object)LevelObjects[LevelObjects.Length - 1] != (Object)null)
			{
				LevelObjects[LevelObjects.Length - 1].SetActive(true);
			}
		}
	}
	public interface IListElement
	{
		ItemData GetItem();

		int GetMax();

		string GetDisplayNameSuffix();
	}
	public class InventoryItemListElement : IListElement
	{
		public ItemData Item;

		public ItemData GetItem()
		{
			return Item;
		}

		public int GetMax()
		{
			return Item?.m_stack ?? 0;
		}

		public string GetDisplayNameSuffix()
		{
			return string.Empty;
		}
	}
	public class MultiSelectItemList : MonoBehaviour
	{
		public enum SortMode
		{
			Rarity,
			Name,
			Quantity
		}

		public delegate List<IListElement> SortByRarityDelegate(List<IListElement> items);

		public delegate List<IListElement> SortByNameDelegate(List<IListElement> items);

		public bool Multiselect = true;

		public bool Filterable = true;

		public bool Sortable = true;

		public bool ReadOnly;

		public Transform ListContainer;

		public MultiSelectItemListElement ElementPrefab;

		public Dropdown SortByDropdown;

		public InputField FilterByText;

		public Toggle SelectAllToggle;

		public static SortByRarityDelegate SortByRarity;

		public static SortByNameDelegate SortByName;

		private bool _locked;

		private bool _hasGamepadFocus;

		private ScrollRectEnsureVisible _scrollRectEnsureVisible;

		public event Action OnSelectedItemsChanged;

		public event Action OnItemsChanged;

		public void Awake()
		{
			ScrollRect componentInChildren = ((Component)this).GetComponentInChildren<ScrollRect>();
			_scrollRectEnsureVisible = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).GetComponent<ScrollRectEnsureVisible>() : null);
			if ((Object)(object)SelectAllToggle != (Object)null)
			{
				((UnityEvent<bool>)(object)SelectAllToggle.onValueChanged).AddListener((UnityAction<bool>)OnSelectAllToggled);
			}
			if ((Object)(object)SortByDropdown != (Object)null)
			{
				foreach (OptionData option in SortByDropdown.options)
				{
					option.text = Localization.instance.Localize(option.text);
				}
				((UnityEvent<int>)(object)SortByDropdown.onValueChanged).AddListener((UnityAction<int>)OnSortModeChanged);
			}
			if ((Object)(object)FilterByText != (Object)null)
			{
				((UnityEvent<string>)(object)FilterByText.onValueChanged).AddListener((UnityAction<string>)OnFilterChanged);
			}
			Refresh();
		}

		public void Update()
		{
			if (_locked || !HasGamepadFocus() || !ZInput.IsGamepadActive() || (Object)(object)ListContainer == (Object)null)
			{
				return;
			}
			int childCount = ListContainer.childCount;
			MultiSelectItemListElement focusedElement = GetFocusedElement();
			if ((Object)(object)focusedElement == (Object)null)
			{
				return;
			}
			int siblingIndex = ((Component)focusedElement).transform.GetSiblingIndex();
			GridLayoutGroup component = ((Component)ListContainer).GetComponent<GridLayoutGroup>();
			if ((Object)(object)((Component)ListContainer).GetComponent<VerticalLayoutGroup>() != (Object)null)
			{
				if (siblingIndex > 0 && ZInput.GetButtonDown("JoyLStickUp"))
				{
					focusedElement.GiveFocus(focused: false);
					MultiSelectItemListElement element = GetElement(siblingIndex - 1);
					element.GiveFocus(focused: true);
					CenterOnItem(element);
					ZInput.ResetButtonStatus("JoyLStickUp");
				}
				else if (siblingIndex < childCount - 1 && ZInput.GetButtonDown("JoyLStickDown"))
				{
					focusedElement.GiveFocus(focused: false);
					MultiSelectItemListElement element2 = GetElement(siblingIndex + 1);
					element2.GiveFocus(focused: true);
					CenterOnItem(element2);
					ZInput.ResetButtonStatus("JoyLStickDown");
				}
				else if (ZInput.GetButtonDown("JoyLStickLeft"))
				{
					ZInput.ResetButtonStatus("JoyLStickLeft");
				}
				else if (ZInput.GetButtonDown("JoyLStickRight"))
				{
					ZInput.ResetButtonStatus("JoyLStickRight");
				}
			}
			else if ((Object)(object)component != (Object)null)
			{
				int constraintCount = component.constraintCount;
				if (siblingIndex >= constraintCount && ZInput.GetButtonDown("JoyLStickUp"))
				{
					focusedElement.GiveFocus(focused: false);
					MultiSelectItemListElement element3 = GetElement(siblingIndex - constraintCount);
					element3.GiveFocus(focused: true);
					CenterOnItem(element3);
					ZInput.ResetButtonStatus("JoyLStickUp");
				}
				else if (siblingIndex < childCount - constraintCount && ZInput.GetButtonDown("JoyLStickDown"))
				{
					focusedElement.GiveFocus(focused: false);
					MultiSelectItemListElement element4 = GetElement(siblingIndex + constraintCount);
					element4.GiveFocus(focused: true);
					CenterOnItem(element4);
					ZInput.ResetButtonStatus("JoyLStickDown");
				}
				else if (siblingIndex % constraintCount > 0 && ZInput.GetButtonDown("JoyLStickLeft"))
				{
					focusedElement.GiveFocus(focused: false);
					MultiSelectItemListElement element5 = GetElement(siblingIndex - 1);
					element5.GiveFocus(focused: true);
					CenterOnItem(element5);
					ZInput.ResetButtonStatus("JoyLStickLeft");
				}
				else if (siblingIndex % constraintCount < constraintCount - 1 && siblingIndex < childCount - 1 && ZInput.GetButtonDown("JoyLStickRight"))
				{
					focusedElement.GiveFocus(focused: false);
					MultiSelectItemListElement element6 = GetElement(siblingIndex + 1);
					element6.GiveFocus(focused: true);
					CenterOnItem(element6);
					ZInput.ResetButtonStatus("JoyLStickRight");
				}
			}
			if (Multiselect && (Object)(object)SelectAllToggle != (Object)null && ZInput.GetButtonDown("JoyLStick"))
			{
				SelectAllToggle.isOn = !SelectAllToggle.isOn;
				ZInput.ResetButtonStatus("JoyLStick");
			}
			if (Sortable && (Object)(object)SortByDropdown != (Object)null && ZInput.GetButtonDown("JoyRStick"))
			{
				int value = SortByDropdown.value;
				int count = SortByDropdown.options.Count;
				value = (value + 1) % count;
				SortByDropdown.value = value;
				ZInput.ResetButtonStatus("JoyRStick");
			}
		}

		private void CenterOnItem(MultiSelectItemListElement element)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			if ((Object)(object)_scrollRectEnsureVisible != (Object)null)
			{
				_scrollRectEnsureVisible.CenterOnItem((RectTransform)((Component)element).transform);
			}
		}

		private void OnFilterChanged(string _)
		{
			Refresh();
		}

		public void Refresh()
		{
			RefreshFilter();
			RefreshSelectAllToggle();
		}

		private void RefreshFilter()
		{
			if ((Object)(object)FilterByText != (Object)null && !Filterable && ((Component)FilterByText).gameObject.activeSelf)
			{
				((Component)FilterByText).gameObject.SetActive(false);
			}
			if (!Filterable || (Object)(object)FilterByText == (Object)null)
			{
				return;
			}
			string text = FilterByText.text;
			bool flag = string.IsNullOrEmpty(text) || string.IsNullOrWhiteSpace(text);
			string[] array = (flag ? Array.Empty<string>() : text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
			int childCount = ListContainer.childCount;
			for (int i = 0; i < childCount; i++)
			{
				MultiSelectItemListElement component = ((Component)ListContainer.GetChild(i)).GetComponent<MultiSelectItemListElement>();
				string text2 = component.ItemName.text;
				text2 = new Regex("<[^>]*>").Replace(text2, string.Empty);
				bool active = flag;
				string[] array2 = array;
				foreach (string value in array2)
				{
					if (text2.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						active = true;
						break;
					}
				}
				((Component)component).gameObject.SetActive(active);
			}
		}

		public void RefreshSelectAllToggle()
		{
			if (!((Object)(object)SelectAllToggle != (Object)null))
			{
				return;
			}
			if (!Multiselect && ((Component)SelectAllToggle).gameObject.activeSelf)
			{
				((Component)SelectAllToggle).gameObject.SetActive(false);
				return;
			}
			bool isOnWithoutNotify = true;
			int childCount = ListContainer.childCount;
			for (int i = 0; i < childCount; i++)
			{
				if (!((Component)ListContainer.GetChild(i)).GetComponent<MultiSelectItemListElement>().IsMaxSelected())
				{
					isOnWithoutNotify = false;
				}
			}
			SelectAllToggle.SetIsOnWithoutNotify(isOnWithoutNotify);
		}

		private void OnSelectAllToggled(bool _ = true)
		{
			if ((Object)(object)SelectAllToggle == (Object)null)
			{
				return;
			}
			if (SelectAllToggle.isOn)
			{
				ForeachElement(delegate(int _, MultiSelectItemListElement x)
				{
					x.SelectMaxQuantity(noSound: true);
				});
			}
			else
			{
				ForeachElement(delegate(int _, MultiSelectItemListElement x)
				{
					x.Deselect(noSound: true);
				});
			}
			RefreshSelectAllToggle();
		}

		private void OnSortModeChanged(int sortModeValue)
		{
			if (!Sortable || (Object)(object)SortByDropdown == (Object)null)
			{
				return;
			}
			Dictionary<IListElement, int> currentSelectionAmounts = GetCurrentSelectionAmounts();
			List<IListElement> items = currentSelectionAmounts.Keys.ToList();
			SortMode value = (SortMode)SortByDropdown.value;
			List<IListElement> list = SortItems(value, items);
			for (int i = 0; i < list.Count; i++)
			{
				Transform child = ListContainer.GetChild(i);
				IListElement listElement = list[i];
				MultiSelectItemListElement component = ((Component)child).GetComponent<MultiSelectItemListElement>();
				component.SuppressEvents = true;
				component.SetItem(listElement);
				if (currentSelectionAmounts.TryGetValue(listElement, out var value2))
				{
					component.SelectQuantity(value2, noSound: true);
				}
				component.SuppressEvents = false;
			}
			RefreshSelectAllToggle();
		}

		public Dictionary<IListElement, int> GetCurrentSelectionAmounts()
		{
			Dictionary<IListElement, int> dictionary = new Dictionary<IListElement, int>();
			int childCount = ListContainer.childCount;
			for (int i = 0; i < childCount; i++)
			{
				MultiSelectItemListElement component = ((Component)ListContainer.GetChild(i)).GetComponent<MultiSelectItemListElement>();
				if ((Object)(object)component != (Object)null && component.GetItem() != null)
				{
					dictionary.Add(component.GetListElement(), component.GetSelectedQuantity());
				}
			}
			return dictionary;
		}

		private void MakeEnoughElements(int itemCount)
		{
			int childCount = ListContainer.childCount;
			if (childCount > itemCount)
			{
				for (int num = childCount - 1; num >= itemCount; num--)
				{
					Transform child = ListContainer.GetChild(num);
					((Component)child).GetComponent<MultiSelectItemListElement>().OnSelectionChanged -= OnElementSelectionChanged;
					Object.DestroyImmediate((Object)(object)((Component)child).gameObject);
				}
			}
			else if (childCount < itemCount)
			{
				for (int i = childCount; i < itemCount; i++)
				{
					MultiSelectItemListElement multiSelectItemListElement = Object.Instantiate<MultiSelectItemListElement>(ElementPrefab, ListContainer);
					multiSelectItemListElement.SuppressEvents = true;
					multiSelectItemListElement.OnSelectionChanged += OnElementSelectionChanged;
				}
			}
		}

		public void SetItems(List<IListElement> items)
		{
			int count = items.Count;
			Dictionary<IListElement, int> currentSelectionAmounts = GetCurrentSelectionAmounts();
			MultiSelectItemListElement focusedElement = GetFocusedElement();
			MakeEnoughElements(count);
			List<IListElement> list = items;
			if (Sortable && (Object)(object)SortByDropdown != (Object)null)
			{
				SortMode value = (SortMode)SortByDropdown.value;
				list = SortItems(value, items);
			}
			bool flag = false;
			for (int i = 0; i < count; i++)
			{
				Transform child = ListContainer.GetChild(i);
				IListElement listElement = list[i];
				MultiSelectItemListElement component = ((Component)child).GetComponent<MultiSelectItemListElement>();
				component.SuppressEvents = true;
				component.SetItem(listElement);
				if (currentSelectionAmounts.TryGetValue(listElement, out var value2))
				{
					component.SelectQuantity(value2, noSound: true);
				}
				component.SuppressEvents = false;
				bool flag2 = HasGamepadFocus() && (((Object)(object)focusedElement == (Object)null && i == 0) || (Object)(object)component == (Object)(object)focusedElement);
				component.GiveFocus(flag2);
				if (flag2)
				{
					flag = true;
					CenterOnItem(component);
				}
			}
			if (HasGamepadFocus() && !flag && ListContainer.childCount > 0)
			{
				_hasGamepadFocus = false;
				GiveFocus(focused: true, 0);
				CenterOnItem(GetElement(0));
			}
			this.OnItemsChanged?.Invoke();
			this.OnSelectedItemsChanged?.Invoke();
			RefreshSelectAllToggle();
		}

		private void OnElementSelectionChanged(MultiSelectItemListElement element, bool isSelected, int selectedQuantity)
		{
			if (!Multiselect)
			{
				ForeachElement(delegate(int _, MultiSelectItemListElement x)
				{
					if ((Object)(object)x != (Object)(object)element)
					{
						x.SuppressEvents = true;
						x.Deselect(noSound: true);
						x.SuppressEvents = false;
					}
				});
			}
			this.OnSelectedItemsChanged?.Invoke();
			RefreshSelectAllToggle();
		}

		public List<IListElement> SortItems(SortMode mode, List<IListElement> items)
		{
			switch (mode)
			{
			case SortMode.Rarity:
				if (SortByRarity != null)
				{
					return SortByRarity(items);
				}
				return items.ToList();
			case SortMode.Name:
				if (SortByName != null)
				{
					return SortByName(items);
				}
				return (from x in items
					orderby Localization.instance.Localize(x.GetItem().m_shared.m_name), x.GetItem().m_stack descending
					select x).ToList();
			case SortMode.Quantity:
				return (from x in items
					orderby x.GetItem().m_stack descending, Localization.instance.Localize(x.GetItem().m_shared.m_name)
					select x).ToList();
			default:
				throw new ArgumentOutOfRangeException("mode", mode, null);
			}
		}

		public List<Tuple<T, int>> GetSelectedItems<T>()
		{
			List<Tuple<T, int>> list = new List<Tuple<T, int>>();
			int childCount = ListContainer.childCount;
			for (int i = 0; i < childCount; i++)
			{
				MultiSelectItemListElement component = ((Component)ListContainer.GetChild(i)).GetComponent<MultiSelectItemListElement>();
				int selectedQuantity = component.GetSelectedQuantity();
				if (selectedQuantity > 0)
				{
					list.Add(new Tuple<T, int>((T)component.GetListElement(), selectedQuantity));
				}
			}
			return list;
		}

		public Tuple<T, int> GetSingleSelectedItem<T>()
		{
			int childCount = ListContainer.childCount;
			for (int i = 0; i < childCount; i++)
			{
				MultiSelectItemListElement component = ((Component)ListContainer.GetChild(i)).GetComponent<MultiSelectItemListElement>();
				int selectedQuantity = component.GetSelectedQuantity();
				if (selectedQuantity > 0)
				{
					return new Tuple<T, int>((T)component.GetListElement(), selectedQuantity);
				}
			}
			return null;
		}

		public int GetFirstSelectedIndex()
		{
			int childCount = ListContainer.childCount;
			for (int i = 0; i < childCount; i++)
			{
				if (((Component)ListContainer.GetChild(i)).GetComponent<MultiSelectItemListElement>().GetSelectedQuantity() > 0)
				{
					return i;
				}
			}
			return -1;
		}

		public void Lock()
		{
			_locked = true;
			if ((Object)(object)SortByDropdown != (Object)null)
			{
				((Selectable)SortByDropdown).interactable = false;
			}
			if ((Object)(object)FilterByText != (Object)null)
			{
				((Selectable)FilterByText).interactable = false;
			}
			if ((Object)(object)SelectAllToggle != (Object)null)
			{
				((Selectable)SelectAllToggle).interactable = false;
			}
			ForeachElement(delegate(int _, MultiSelectItemListElement e)
			{
				e.Lock();
			});
		}

		public void Unlock()
		{
			_locked = false;
			if ((Object)(object)SortByDropdown != (Object)null)
			{
				((Selectable)SortByDropdown).interactable = Sortable && !ReadOnly;
			}
			if ((Object)(object)FilterByText != (Object)null)
			{
				((Selectable)FilterByText).interactable = Filterable && !ReadOnly;
			}
			if ((Object)(object)SelectAllToggle != (Object)null)
			{
				((Selectable)SelectAllToggle).interactable = Multiselect && !ReadOnly;
			}
			ForeachElement(delegate(int _, MultiSelectItemListElement e)
			{
				e.Unlock();
			});
		}

		private MultiSelectItemListElement GetElement(int index)
		{
			Transform child = ListContainer.GetChild(index);
			if (!((Object)(object)child == (Object)null))
			{
				return ((Component)child).GetComponent<MultiSelectItemListElement>();
			}
			return null;
		}

		public void ForeachElement(Action<int, MultiSelectItemListElement> func)
		{
			if ((Object)(object)ListContainer == (Object)null)
			{
				return;
			}
			int childCount = ListContainer.childCount;
			for (int i = 0; i < childCount; i++)
			{
				MultiSelectItemListElement element = GetElement(i);
				if ((Object)(object)element != (Object)null)
				{
					func(i, element);
				}
			}
		}

		public void DeselectAll()
		{
			SuppressEvents(suppress: true);
			ForeachElement(delegate(int _, MultiSelectItemListElement e)
			{
				e.Deselect(noSound: true);
			});
			SuppressEvents(suppress: false);
			this.OnSelectedItemsChanged?.Invoke();
			RefreshSelectAllToggle();
		}

		public void SuppressEvents(bool suppress)
		{
			ForeachElement(delegate(int _, MultiSelectItemListElement e)
			{
				e.SuppressEvents = suppress;
			});
		}

		public void GiveFocus(bool focused, int tryFocusIndex)
		{
			if (_hasGamepadFocus == focused)
			{
				return;
			}
			_hasGamepadFocus = focused;
			int focusIndex = (focused ? Mathf.Clamp(tryFocusIndex, 0, ListContainer.childCount - 1) : (-1));
			ForeachElement(delegate(int i, MultiSelectItemListElement e)
			{
				bool flag = i == focusIndex;
				e.GiveFocus(flag);
				if (flag)
				{
					CenterOnItem(e);
				}
			});
		}

		public bool HasGamepadFocus()
		{
			return _hasGamepadFocus;
		}

		public MultiSelectItemListElement GetFocusedElement()
		{
			if ((Object)(object)ListContainer == (Object)null || !ZInput.IsGamepadActive())
			{
				return null;
			}
			int childCount = ListContainer.childCount;
			for (int i = 0; i < childCount; i++)
			{
				Transform child = ListContainer.GetChild(i);
				if (!((Object)(object)child == (Object)null))
				{
					MultiSelectItemListElement component = ((Component)child).GetComponent<MultiSelectItemListElement>();
					if ((Object)(object)component != (Object)null && component.HasGamepadFocus())
					{
						return component;
					}
				}
			}
			return null;
		}

		public int GetItemCount()
		{
			if ((Object)(object)ListContainer == (Object)null)
			{
				return 0;
			}
			int childCount = ListContainer.childCount;
			int num = 0;
			for (int i = 0; i < childCount; i++)
			{
				Transform child = ListContainer.GetChild(i);
				if ((Object)(object)child != (Object)null && ((Component)child).gameObject.activeSelf)
				{
					num++;
				}
			}
			return num;
		}

		public bool IsGrid()
		{
			if ((Object)(object)ListContainer != (Object)null)
			{
				return (Object)(object)((Component)ListContainer).GetComponent<GridLayoutGroup>() != (Object)null;
			}
			return false;
		}

		public void InitWithExistingItems()
		{
			for (int i = 0; i < ListContainer.childCount; i++)
			{
				((Component)ListContainer.GetChild(i)).GetComponent<MultiSelectItemListElement>().OnSelectionChanged += OnElementSelectionChanged;
			}
			DeselectAll();
			this.OnItemsChanged?.Invoke();
			this.OnSelectedItemsChanged?.Invoke();
			RefreshSelectAllToggle();
		}
	}
	public class MultiSelectItemListElement : MonoBehaviour
	{
		public delegate void SetMagicItemDelegate(MultiSelectItemListElement element, ItemData item, UITooltip tooltip);

		public const string TotalQuantityFormat = "/ {0}";

		public const string ReadOnlyQuantityFormat = "{0}";

		public Button MainButton;

		public Toggle SelectedToggle;

		public GameObject SelectedBackground;

		public Text ItemName;

		public Image MagicBG;

		public Image ItemIcon;

		public Text ItemTotalQuantity;

		public InputField ItemSelectedQuantity;

		public Button QuantityUpButton;

		public Button QuantityDownButton;

		public UITooltip Tooltip;

		public bool ReadOnly;

		public bool CheckPlayerInventory;

		public bool NoMax;

		public AudioSource Audio;

		public AudioClip OnClickSFX;

		public GameObject GamepadFocusIndicator;

		[NonSerialized]
		public bool SuppressEvents;

		public static SetMagicItemDelegate SetMagicItem;

		private IListElement _item;

		private int _selectedQuantity;

		private bool _locked;

		private bool _hasGamepadFocus;

		public event Action<MultiSelectItemListElement, bool, int> OnSelectionChanged;

		public void Awake()
		{
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Expected O, but got Unknown
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Expected O, but got Unknown
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Expected O, but got Unknown
			if ((Object)(object)ItemIcon != (Object)null || (Object)(object)MagicBG != (Object)null)
			{
				Material material = ((Graphic)((Component)InventoryGui.instance.m_dragItemPrefab.transform.Find("icon")).GetComponent<Image>()).material;
				if ((Object)(object)material != (Object)null)
				{
					if ((Object)(object)ItemIcon != (Object)null)
					{
						((Graphic)ItemIcon).material = material;
					}
					if ((Object)(object)MagicBG != (Object)null)
					{
						((Graphic)MagicBG).material = material;
					}
				}
			}
			if ((Object)(object)Tooltip != (Object)null)
			{
				GameObject tooltipPrefab = StoreGui.instance.m_listElement.GetComponent<UITooltip>().m_tooltipPrefab;
				Tooltip.m_tooltipPrefab = tooltipPrefab;
			}
			if ((Object)(object)Audio != (Object)null)
			{
				GameObject val = GameObject.Find("sfx_gui_button");
				if ((Object)(object)val != (Object)null)
				{
					Audio.outputAudioMixerGroup = val.GetComponent<AudioSource>().outputAudioMixerGroup;
				}
			}
			if (!ReadOnly)
			{
				if ((Object)(object)MainButton != (Object)null)
				{
					((UnityEvent)MainButton.onClick).AddListener(new UnityAction(OnClicked));
				}
				if ((Object)(object)ItemSelectedQuantity != (Object)null)
				{
					((UnityEvent<string>)(object)ItemSelectedQuantity.onEndEdit).AddListener((UnityAction<string>)OnSelectedAmountChanged);
				}
				if ((Object)(object)SelectedToggle != (Object)null)
				{
					((UnityEvent<bool>)(object)SelectedToggle.onValueChanged).AddListener((UnityAction<bool>)OnSelectedToggleChanged);
				}
				if ((Object)(object)QuantityUpButton != (Object)null)
				{
					((UnityEvent)QuantityUpButton.onClick).AddListener(new UnityAction(OnQuantityUpButtonClicked));
				}
				if ((Object)(object)QuantityDownButton != (Object)null)
				{
					((UnityEvent)QuantityDownButton.onClick).AddListener(new UnityAction(OnQuantityDownButtonClicked));
				}
			}
			Refresh();
		}

		public void Update()
		{
			if (!_locked && ZInput.IsGamepadActive() && HasGamepadFocus() && !ReadOnly)
			{
				if (ZInput.GetButtonDown("JoyButtonA"))
				{
					OnClicked();
					ZInput.ResetButtonStatus("JoyButtonA");
				}
				else if (ZInput.GetButtonDown("JoyDPadUp"))
				{
					SelectQuantity(_selectedQuantity + 1, noSound: false);
					ZInput.ResetButtonStatus("JoyDPadUp");
				}
				else if (ZInput.GetButtonDown("JoyDPadDown"))
				{
					SelectQuantity(_selectedQuantity - 1, noSound: false);
					ZInput.ResetButtonStatus("JoyDPadDown");
				}
				else if (ZInput.GetButtonDown("JoyDPadLeft"))
				{
					ZInput.ResetButtonStatus("JoyDPadLeft");
				}
				else if (ZInput.GetButtonDown("JoyDPadRight"))
				{
					ZInput.ResetButtonStatus("JoyDPadRight");
				}
			}
			RefreshGamepadFocusIndicator();
		}

		private void OnClicked()
		{
			if (IsSelected())
			{
				Deselect(noSound: false);
			}
			else
			{
				SelectMaxQuantity(noSound: false);
			}
		}

		public void SelectMaxQuantity(bool noSound)
		{
			int quantity = ((NoMax || _item == null) ? 1 : (_item?.GetItem()?.m_stack).GetValueOrDefault());
			SelectQuantity(quantity, noSound);
		}

		public bool IsSelected()
		{
			return _selectedQuantity > 0;
		}

		public bool IsMaxSelected()
		{
			if (_item != null)
			{
				return _selectedQuantity >= _item.GetItem().m_stack;
			}
			return _selectedQuantity > 0;
		}

		private void OnSelectedAmountChanged(string typedInAmount)
		{
			if (!int.TryParse(typedInAmount, out var result))
			{
				Deselect(noSound: false);
			}
			else
			{
				SelectQuantity(result, noSound: false);
			}
		}

		private void OnSelectedToggleChanged(bool _)
		{
			if (SelectedToggle.isOn)
			{
				SelectMaxQuantity(noSound: true);
			}
			else
			{
				Deselect(noSound: true);
			}
		}

		private void OnQuantityUpButtonClicked()
		{
			SelectQuantity(_selectedQuantity + 1, noSound: false);
		}

		private void OnQuantityDownButtonClicked()
		{
			SelectQuantity(_selectedQuantity - 1, noSound: false);
		}

		public void SetItem(IListElement item)
		{
			bool num = _item == item;
			_item = item;
			if (_item?.GetItem() == null)
			{
				if ((Object)(object)MagicBG != (Object)null)
				{
					((Behaviour)MagicBG).enabled = false;
				}
				if ((Object)(object)ItemIcon != (Object)null)
				{
					ItemIcon.sprite = null;
				}
				if ((Object)(object)ItemName != (Object)null)
				{
					ItemName.text = "<no item>";
				}
				if ((Object)(object)Tooltip != (Object)null)
				{
					Tooltip.m_topic = string.Empty;
					Tooltip.m_text = string.Empty;
				}
			}
			else
			{
				if (SetMagicItem != null)
				{
					SetMagicItem(this, _item.GetItem(), Tooltip);
				}
				else
				{
					if ((Object)(object)MagicBG != (Object)null)
					{
						((Behaviour)MagicBG).enabled = false;
					}
					if ((Object)(object)ItemIcon != (Object)null)
					{
						ItemIcon.sprite = _item.GetItem().GetIcon();
					}
					if ((Object)(object)ItemName != (Object)null)
					{
						ItemName.text = Localization.instance.Localize(_item.GetItem().m_shared.m_name);
					}
					if ((Object)(object)Tooltip != (Object)null)
					{
						Tooltip.m_topic = Localization.instance.Localize(_item.GetItem().m_shared.m_name);
						Tooltip.m_text = Localization.instance.Localize(_item.GetItem().GetTooltip());
					}
				}
				if ((Object)(object)ItemName != (Object)null)
				{
					Text itemName = ItemName;
					itemName.text += _item.GetDisplayNameSuffix();
				}
			}
			if (!num)
			{
				Deselect(noSound: true);
			}
			RefreshGamepadFocusIndicator();
		}

		public void Deselect(bool noSound)
		{
			SelectQuantity(0, noSound);
		}

		public void SelectQuantity(int quantity, bool noSound)
		{
			int selectedQuantity = _selectedQuantity;
			if (_item == null)
			{
				_selectedQuantity = quantity;
			}
			else if (NoMax)
			{
				_selectedQuantity = Mathf.Clamp(quantity, 0, 999);
			}
			else if (_item.GetItem().m_shared.m_maxStackSize == 1)
			{
				_selectedQuantity = Mathf.Clamp(quantity, 0, 1);
			}
			else
			{
				_selectedQuantity = Mathf.Clamp(quantity, 0, _item.GetItem().m_stack);
			}
			if (!SuppressEvents && selectedQuantity != _selectedQuantity)
			{
				this.OnSelectionChanged?.Invoke(this, IsSelected(), _selectedQuantity);
			}
			if ((Object)(object)Audio != (Object)null && !ReadOnly && !noSound && selectedQuantity != _selectedQuantity)
			{
				Audio.PlayOneShot(OnClickSFX);
			}
			Refresh();
		}

		public void Refresh()
		{
			RefreshGamepadFocusIndicator();
			bool flag = _item != null && _item.GetItem().m_shared.m_maxStackSize > 1;
			if ((Object)(object)MainButton != (Object)null)
			{
				((Selectable)MainButton).interactable = !_locked;
			}
			if ((Object)(object)SelectedToggle != (Object)null)
			{
				((Selectable)SelectedToggle).interactable = !_locked;
				((Component)SelectedToggle).gameObject.SetActive(!ReadOnly);
				SelectedToggle.SetIsOnWithoutNotify(_selectedQuantity > 0);
			}
			if ((Object)(object)ItemSelectedQuantity != (Object)null)
			{
				((Selectable)ItemSelectedQuantity).interactable = !_locked;
				((Component)ItemSelectedQuantity).gameObject.SetActive(!ReadOnly && flag);
				ItemSelectedQuantity.text = _selectedQuantity.ToString();
			}
			if ((Object)(object)ItemTotalQuantity != (Object)null && _item != null)
			{
				((Component)ItemTotalQuantity).gameObject.SetActive(ReadOnly || flag);
				string text = string.Format(ReadOnly ? "{0}" : "/ {0}", _item.GetMax());
				if (CheckPlayerInventory && ((Humanoid)Player.m_localPlayer).GetInventory().CountItems(_item.GetItem().m_shared.m_name, -1, true) < _item.GetItem().m_stack)
				{
					text = "<color=red>" + text + "</color>";
				}
				ItemTotalQuantity.text = text;
			}
			if ((Object)(object)QuantityUpButton != (Object)null)
			{
				((Selectable)QuantityUpButton).interactable = !_locked;
				((Component)QuantityUpButton).gameObject.SetActive(!ReadOnly && flag);
			}
			if ((Object)(object)QuantityDownButton != (Object)null)
			{
				((Selectable)QuantityDownButton).interactable = !_locked;
				((Component)QuantityDownButton).gameObject.SetActive(!ReadOnly && flag);
			}
			if ((Object)(object)SelectedBackground != (Object)null)
			{
				SelectedBackground.SetActive(!ReadOnly && _selectedQuantity > 0);
			}
			Localization.instance.Localize(((Component)this).transform);
		}

		public ItemData GetItem()
		{
			return _item.GetItem();
		}

		public IListElement GetListElement()
		{
			return _item;
		}

		public int GetSelectedQuantity()
		{
			return _selectedQuantity;
		}

		public void Lock()
		{
			_locked = true;
			Refresh();
		}

		public void Unlock()
		{
			_locked = false;
			Refresh();
		}

		public void GiveFocus(bool focused)
		{
			_hasGamepadFocus = focused;
			RefreshGamepadFocusIndicator();
		}

		private void RefreshGamepadFocusIndicator()
		{
			if (!((Object)(object)GamepadFocusIndicator == (Object)null))
			{
				GamepadFocusIndicator.SetActive(ZInput.IsGamepadActive() && _hasGamepadFocus);
			}
		}

		public bool HasGamepadFocus()
		{
			return _hasGamepadFocus;
		}
	}
	public class MultiSelectListFocusController : MonoBehaviour
	{
		public List<MultiSelectItemList> Lists = new List<MultiSelectItemList>();

		public GameObject[] SortHints;

		public GameObject[] SelectAllHints;

		public GameObject[] SelectHints;

		private int _focusedListIndex;

		private bool _gamepadWasEnabled;

		public void OnEnable()
		{
			_focusedListIndex = 0;
			for (int i = 0; i < Lists.Count; i++)
			{
				Lists[i].GiveFocus(i == _focusedListIndex, 0);
			}
			RefreshHints();
		}

		public void Update()
		{
			if (Lists.Count == 0)
			{
				return;
			}
			MultiSelectItemList multiSelectItemList = Lists[_focusedListIndex];
			int num = 0;
			int itemCount = multiSelectItemList.GetItemCount();
			while (itemCount == 0)
			{
				multiSelectItemList.GiveFocus(focused: false, 0);
				_focusedListIndex = (_focusedListIndex + 1) % Lists.Count;
				multiSelectItemList = Lists[_focusedListIndex];
				itemCount = multiSelectItemList.GetItemCount();
				if (multiSelectItemList.GetItemCount() > 0)
				{
					multiSelectItemList.GiveFocus(focused: true, 0);
					RefreshHints();
					break;
				}
				num++;
				if (num >= Lists.Count)
				{
					return;
				}
			}
			if (ZInput.IsGamepadActive())
			{
				int num2 = _focusedListIndex;
				if (ZInput.GetButtonDown("JoyTabLeft"))
				{
					num2 = Mathf.Max(_focusedListIndex - 1, 0);
					ZInput.ResetButtonStatus("JoyTabLeft");
				}
				else if (ZInput.GetButtonDown("JoyTabRight"))
				{
					num2 = Mathf.Min(_focusedListIndex + 1, Lists.Count - 1);
					ZInput.ResetButtonStatus("JoyTabRight");
				}
				if (num2 != _focusedListIndex)
				{
					int num3 = num2 - _focusedListIndex;
					if (Lists[num2].GetItemCount() == 0)
					{
						num2 = (num2 + num3 + Lists.Count) % Lists.Count;
					}
					if (Lists[num2].GetItemCount() == 0)
					{
						num2 = _focusedListIndex;
					}
				}
				FocusList(num2);
			}
			if (_gamepadWasEnabled != ZInput.IsGamepadActive())
			{
				RefreshHints();
			}
			_gamepadWasEnabled = ZInput.IsGamepadActive();
		}

		public void FocusList(int newFocusedIndex)
		{
			MultiSelectItemListElement focusedElement = Lists[_focusedListIndex].GetFocusedElement();
			int num = (((Object)(object)focusedElement != (Object)null) ? ((Component)focusedElement).transform.GetSiblingIndex() : (-1));
			if (newFocusedIndex != _focusedListIndex && newFocusedIndex >= 0 && newFocusedIndex < Lists.Count)
			{
				_focusedListIndex = newFocusedIndex;
				for (int i = 0; i < Lists.Count; i++)
				{
					bool flag = Lists[i].IsGrid();
					Lists[i].GiveFocus(i == _focusedListIndex, (!flag) ? num : 0);
				}
				RefreshHints();
			}
		}

		private void RefreshHints()
		{
			if (((Behaviour)this).isActiveAndEnabled && ZInput.IsGamepadActive() && Lists.Count != 0)
			{
				MultiSelectItemList multiSelectItemList = Lists[_focusedListIndex];
				GameObject[] sortHints = SortHints;
				for (int i = 0; i < sortHints.Length; i++)
				{
					sortHints[i].SetActive(multiSelectItemList.Sortable && (Object)(object)multiSelectItemList.SortByDropdown != (Object)null && ((Behaviour)multiSelectItemList.SortByDropdown).isActiveAndEnabled);
				}
				sortHints = SelectAllHints;
				for (int i = 0; i < sortHints.Length; i++)
				{
					sortHints[i].SetActive(multiSelectItemList.Multiselect && (Object)(object)multiSelectItemList.SelectAllToggle != (Object)null && ((Behaviour)multiSelectItemList.SelectAllToggle).isActiveAndEnabled);
				}
				sortHints = SelectHints;
				for (int i = 0; i < sortHints.Length; i++)
				{
					sortHints[i].SetActive(!multiSelectItemList.ReadOnly && (Object)(object)multiSelectItemList.GetFocusedElement() != (Object)null);
				}
			}
		}
	}
	[RequireComponent(typeof(Toggle))]
	public class PlaySoundOnChecked : MonoBehaviour
	{
		public AudioSource Audio;

		public AudioClip SFX;

		private Toggle _toggle;

		public void Awake()
		{
			_toggle = ((Component)this).GetComponent<Toggle>();
			((UnityEvent<bool>)(object)_toggle.onValueChanged).AddListener((UnityAction<bool>)OnToggleChanged);
		}

		public void OnDestroy()
		{
			((UnityEvent<bool>)(object)_toggle.onValueChanged).RemoveListener((UnityAction<bool>)OnToggleChanged);
		}

		private void OnToggleChanged(bool _)
		{
			if ((Object)(object)Audio != (Object)null && (Object)(object)SFX != (Object)null && _toggle.isOn)
			{
				Audio.PlayOneShot(SFX);
			}
		}
	}
	public enum MaterialConversionMode
	{
		Upgrade,
		Convert,
		Junk
	}
	public class ConversionRecipeCostUnity
	{
		public ItemData Item;

		public int Amount;
	}
	public class ConversionRecipeUnity : IListElement
	{
		public ItemData Product;

		public int Amount;

		public List<ConversionRecipeCostUnity> Cost;

		public ItemData GetItem()
		{
			return Product;
		}

		public string GetDisplayNameSuffix()
		{
			if (Amount <= 1)
			{
				return string.Empty;
			}
			return $" x{Amount}";
		}

		public int GetMax()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return 0;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			int num = int.MaxValue;
			foreach (ConversionRecipeCostUnity item in Cost)
			{
				int num2 = Mathf.FloorToInt((float)inventory.CountItems(item.Item.m_shared.m_name, -1, true) / (float)item.Amount);
				num = Mathf.Min(num, num2);
			}
			return num;
		}
	}
	public class ConvertUI : EnchantingTableUIPanelBase
	{
		public delegate List<ConversionRecipeUnity> GetConversionRecipesDelegate(int mode);

		public MultiSelectItemList Products;

		public List<Toggle> ModeButtons;

		[Header("Cost")]
		public Text CostLabel;

		public MultiSelectItemList CostList;

		public static GetConversionRecipesDelegate GetConversionRecipes;

		private Text _progressLabel;

		private ToggleGroup _toggleGroup;

		private MaterialConversionMode _mode;

		public override void Awake()
		{
			base.Awake();
			_progressLabel = ((Component)ProgressBar).gameObject.GetComponentInChildren<Text>();
			if (ModeButtons.Count > 0)
			{
				_toggleGroup = ModeButtons[0].group;
				_toggleGroup.EnsureValidState();
			}
			for (int i = 0; i < ModeButtons.Count; i++)
			{
				((UnityEvent<bool>)(object)ModeButtons[i].onValueChanged).AddListener((UnityAction<bool>)delegate(bool isOn)
				{
					if (isOn)
					{
						RefreshMode();
					}
				});
			}
		}

		[UsedImplicitly]
		public void OnEnable()
		{
			_mode = MaterialConversionMode.Upgrade;
			RefreshMode();
			List<ConversionRecipeUnity> source = GetConversionRecipes((int)_mode);
			AvailableItems.SetItems(source.Cast<IListElement>().ToList());
		}

		public override void Update()
		{
			base.Update();
			if (!_locked && ZInput.IsGamepadActive() && ZInput.GetButtonDown("JoyButtonY"))
			{
				int index = (int)(_mode + 1) % ModeButtons.Count;
				ModeButtons[index].isOn = true;
				ZInput.ResetButtonStatus("JoyButtonY");
			}
		}

		public void RefreshMode()
		{
			MaterialConversionMode mode = _mode;
			for (int i = 0; i < ModeButtons.Count; i++)
			{
				if (ModeButtons[i].isOn)
				{
					_mode = (MaterialConversionMode)i;
				}
			}
			if (mode != _mode)
			{
				OnModeChanged();
			}
		}

		public void OnModeChanged()
		{
			DeselectAll();
			RefreshAvailableItems();
			switch (_mode)
			{
			case MaterialConversionMode.Upgrade:
				CostLabel.text = Localization.instance.Localize("$mod_epicloot_upgradecost");
				_progressLabel.text = Localization.instance.Localize("$mod_epicloot_upgradeprogress");
				if (_useTMP)
				{
					_tmpButtonLabel.text = Localization.instance.Localize("$mod_epicloot_upgrade");
				}
				else
				{
					_buttonLabel.text = Localization.instance.Localize("$mod_epicloot_upgrade");
				}
				break;
			case MaterialConversionMode.Convert:
				CostLabel.text = Localization.instance.Localize("$mod_epicloot_convertcost");
				_progressLabel.text = Localization.instance.Localize("$mod_epicloot_convertprogress");
				if (_useTMP)
				{
					_tmpButtonLabel.text = Localization.instance.Localize("$mod_epicloot_convert");
				}
				else
				{
					_buttonLabel.text = Localization.instance.Localize("$mod_epicloot_convert");
				}
				break;
			case MaterialConversionMode.Junk:
				CostLabel.text = Localization.instance.Localize("$mod_epicloot_junkcost");
				_progressLabel.text = Localization.instance.Localize("$mod_epicloot_junkprogress");
				if (_useTMP)
				{
					_tmpButtonLabel.text = Localization.instance.Localize("$mod_epicloot_junk");
				}
				else
				{
					_buttonLabel.text = Localization.instance.Localize("$mod_epicloot_junk");
				}
				break;
			default:
				throw new ArgumentOutOfRangeException();
			}
		}

		protected override void DoMainAction()
		{
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			List<Tuple<ConversionRecipeUnity, int>> selectedItems = AvailableItems.GetSelectedItems<ConversionRecipeUnity>();
			List<InventoryItemListElement> conversionProducts = GetConversionProducts(selectedItems);
			List<InventoryItemListElement> conversionCost = GetConversionCost(selectedItems);
			Cancel();
			Player localPlayer = Player.m_localPlayer;
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			foreach (InventoryItemListElement item3 in conversionCost)
			{
				ItemData item = item3.GetItem();
				inventory.RemoveItem(item.m_shared.m_name, item.m_stack, -1, true);
			}
			foreach (InventoryItemListElement item4 in conversionProducts)
			{
				ItemData item2 = item4.GetItem();
				if (inventory.CanAddItem(item2, -1))
				{
					inventory.AddItem(item2);
					((Character)localPlayer).Message((MessageType)1, "$msg_added " + item2.m_shared.m_name, item2.m_stack, item2.GetIcon());
				}
				else
				{
					ItemDrop val = ItemDrop.DropItem(item2, item2.m_stack, ((Component)localPlayer).transform.position + ((Component)localPlayer).transform.forward + ((Component)localPlayer).transform.up, ((Component)localPlayer).transform.rotation);
					((Component)val).GetComponent<Rigidbody>().velocity = Vector3.up * 5f;
					((Character)localPlayer).Message((MessageType)1, "$msg_dropped " + val.m_itemData.m_shared.m_name + " $mod_epicloot_sacrifice_inventoryfullexplanation", val.m_itemData.m_stack, val.m_itemData.GetIcon());
				}
			}
			DeselectAll();
			RefreshAvailableItems();
		}

		public static List<InventoryItemListElement> GetConversionProducts(List<Tuple<ConversionRecipeUnity, int>> selectedRecipes)
		{
			Dictionary<string, ItemData> dictionary = new Dictionary<string, ItemData>();
			foreach (Tuple<ConversionRecipeUnity, int> selectedRecipe in selectedRecipes)
			{
				ConversionRecipeUnity item = selectedRecipe.Item1;
				int item2 = selectedRecipe.Item2;
				if (dictionary.TryGetValue(item.Product.m_shared.m_name, out var value))
				{
					ItemData obj = value;
					obj.m_stack += item.Amount * item2;
				}
				else
				{
					value = item.Product.Clone();
					value.m_stack = item.Amount * item2;
					dictionary.Add(value.m_shared.m_name, value);
				}
			}
			return (from x in dictionary.Values
				orderby Localization.instance.Localize(x.m_shared.m_name)
				select new InventoryItemListElement
				{
					Item = x
				}).ToList();
		}

		public static List<InventoryItemListElement> GetConversionCost(List<Tuple<ConversionRecipeUnity, int>> selectedRecipes)
		{
			Dictionary<string, ItemData> dictionary = new Dictionary<string, ItemData>();
			foreach (Tuple<ConversionRecipeUnity, int> selectedRecipe in selectedRecipes)
			{
				ConversionRecipeUnity item = selectedRecipe.Item1;
				int item2 = selectedRecipe.Item2;
				foreach (ConversionRecipeCostUnity item3 in item.Cost)
				{
					if (dictionary.TryGetValue(item3.Item.m_shared.m_name, out var value))
					{
						ItemData obj = value;
						obj.m_stack += item3.Amount * item2;
					}
					else
					{
						value = item3.Item.Clone();
						value.m_stack = item3.Amount * item2;
						dictionary.Add(value.m_shared.m_name, value);
					}
				}
			}
			return (from x in dictionary.Values
				orderby Localization.instance.Localize(x.m_shared.m_name)
				select new InventoryItemListElement
				{
					Item = x
				}).ToList();
		}

		public void RefreshAvailableItems()
		{
			List<ConversionRecipeUnity> source = GetConversionRecipes((int)_mode);
			AvailableItems.SetItems(source.Cast<IListElement>().ToList());
			AvailableItems.DeselectAll();
			OnSelectedItemsChanged();
		}

		protected override void OnSelectedItemsChanged()
		{
			List<Tuple<ConversionRecipeUnity, int>> selectedItems = AvailableItems.GetSelectedItems<ConversionRecipeUnity>();
			List<InventoryItemListElement> conversionProducts = GetConversionProducts(selectedItems);
			Products.SetItems(conversionProducts.Cast<IListElement>().ToList());
			List<InventoryItemListElement> conversionCost = GetConversionCost(selectedItems);
			CostList.SetItems(conversionCost.Cast<IListElement>().ToList());
			Tuple<float, float> featureValue = EnchantingTableUI.instance.SourceTable.GetFeatureValue(EnchantingFeature.ConvertMaterials, 0);
			Tuple<float, float> featureCurrentValue = EnchantingTableUI.instance.SourceTable.GetFeatureCurrentValue(EnchantingFeature.ConvertMaterials);
			bool flag = false;
			if (_mode == MaterialConversionMode.Upgrade)
			{
				if (featureCurrentValue.Item1 < featureValue.Item1 && conversionProducts.Any((InventoryItemListElement x) => x.Item.m_shared.m_ammoType.EndsWith("MagicCraftingMaterial")))
				{
					flag = true;
				}
				if (featureCurrentValue.Item2 < featureValue.Item2 && conversionProducts.Any((InventoryItemListElement x) => x.Item.m_shared.m_ammoType.EndsWith("Runestone")))
				{
					flag = true;
				}
				if (flag && conversionCost.Count > 0)
				{
					CostLabel.text = Localization.instance.Localize("<color=#EAA800>($mod_epicloot_bonus)</color> $mod_epicloot_upgradecost");
				}
				else
				{
					CostLabel.text = Localization.instance.Localize("$mod_epicloot_upgradecost");
				}
			}
			bool flag2 = EnchantingTableUIPanelBase.LocalPlayerCanAffordCost(conversionCost);
			bool flag3 = EnchantingTableUI.instance.SourceTable.IsFeatureUnlocked(EnchantingFeat

plugins/EpicLootGoblinsMerged.dll

Decompiled 4 months ago
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Numerics;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Runtime.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Configuration;
using System.Runtime.Serialization.Diagnostics;
using System.Runtime.Serialization.Diagnostics.Application;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Json;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;
using System.Xml.Serialization;
using System.Xml.XPath;
using AdventureBackpacks.API;
using Auga;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using EpicLoot.BaseEL;
using EpicLoot.BaseEL.Abilities;
using EpicLoot.BaseEL.Adventure;
using EpicLoot.BaseEL.Adventure.Feature;
using EpicLoot.BaseEL.Common;
using EpicLoot.BaseEL.Crafting;
using EpicLoot.BaseEL.CraftingV2;
using EpicLoot.BaseEL.Data;
using EpicLoot.BaseEL.GatedItemType;
using EpicLoot.BaseEL.Healing;
using EpicLoot.BaseEL.LegendarySystem;
using EpicLoot.BaseEL.LootBeams;
using EpicLoot.BaseEL.MagicItemEffects;
using EpicLoot.BaseEL.Patching;
using EpicLoot.Skill;
using EpicLoot_UnityLib;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Bson;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Linq.JsonPath;
using Newtonsoft.Json.Schema;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Utilities;
using ServerSync;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("EpicLoot")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("EpicLoot")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace EpicLoot
{
	[BepInPlugin("com.lootgoblinsheim.epicloot", "LGH.EpicLoot", "0.0.4")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal class EpicLoot : BaseUnityPlugin
	{
		public const string PluginGUID = "com.lootgoblinsheim.epicloot";

		public const string PluginName = "LGH.EpicLoot";

		public const string PluginVersion = "0.0.4";

		public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization();

		private EpicLootBase _epicLootBase;

		private void Awake()
		{
			Logger.LogInfo((object)"EpicLoot has landed");
			_epicLootBase = new EpicLootBase();
			_epicLootBase.Awake(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			Enchanting.AddEnchantingSkill();
		}

		private void Start()
		{
			_epicLootBase.Start();
		}

		private void Update()
		{
			_epicLootBase.Update();
		}

		private void OnDestroy()
		{
			_epicLootBase.OnDestroy();
		}
	}
}
namespace EpicLoot.Skill
{
	public static class Enchanting
	{
		public enum OperationType
		{
			Enchant,
			Disenchant,
			Augment,
			Convert,
			Sacrifice
		}

		public static EnchantingSkillConfig Config;

		public static SkillType SkillType;

		public static void AddEnchantingSkill()
		{
			//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_0033: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_0078: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = PrefabManager.Instance.GetPrefab("RunestoneMythic");
			if ((Object)(object)prefab == (Object)null)
			{
				Logger.LogError((object)"RunestoneMythic prefab not exists");
			}
			SkillConfig val = new SkillConfig
			{
				Name = "$mod_epicloot_skill_name",
				Description = "$mod_epicloot_skill_description",
				Identifier = "mod_epicloot_skill_enchanting",
				Icon = prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_icons[0],
				IncreaseStep = 1f
			};
			SkillType = SkillManager.Instance.AddSkill(val);
			Logger.LogInfo((object)$"Added skill {SkillType}");
		}

		public static void InitSkillConfig(EnchantingSkillConfig config)
		{
			Config = config;
		}

		public static float GetEnchantingSkillLevel()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return ((Character)Player.m_localPlayer).GetSkillLevel(SkillType);
		}

		public static void SuccessfulOperation(int targetRarity, OperationType operationType)
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			float num = 1f;
			switch (operationType)
			{
			case OperationType.Enchant:
				num = Config.SuccessEnchantSkillMultiplier;
				break;
			case OperationType.Disenchant:
				num = Config.SuccessDisenchantSkillMultiplier;
				break;
			case OperationType.Augment:
				num = Config.SuccessAugmentationSkillMultiplier;
				break;
			case OperationType.Convert:
				num = Config.SuccessConvertSkillMultiplier;
				break;
			case OperationType.Sacrifice:
				num = Config.SuccessSacrificeSkillMultiplier;
				break;
			}
			float num2 = num * ((float)targetRarity + 1f);
			Logger.LogInfo((object)$"Raising Enchanting: {num2}; multiplier: {num}; targetRarity: {targetRarity}");
			((Character)Player.m_localPlayer).RaiseSkill(SkillType, num2);
		}

		public static MagicItemEffectDefinition.ValueDef GetSkillCappedValueDef(MagicItemEffectDefinition.ValueDef original, ItemRarity rarity)
		{
			if (original == null || Mathf.Approximately(original.MinValue, original.MaxValue))
			{
				return original;
			}
			float enchantingSkillLevel = GetEnchantingSkillLevel();
			int num = Config.EnchantLevels[(int)rarity];
			int num2 = 100 - num;
			float num3 = (original.MaxValue - original.MinValue) / 2f;
			float num4 = (enchantingSkillLevel - (float)num) / (float)num2;
			float num5 = num3 * num4;
			return new MagicItemEffectDefinition.ValueDef
			{
				MinValue = original.MinValue + num5,
				MaxValue = original.MinValue + num3 + num5,
				Increment = original.Increment
			};
		}

		public static bool AugmentAvailableForPlayerSkill(MagicItem magicItem)
		{
			float enchantingSkillLevel = GetEnchantingSkillLevel();
			ItemRarity rarity = magicItem.Rarity;
			return enchantingSkillLevel >= (float)Config.EnchantLevels[(int)rarity];
		}
	}
	[Serializable]
	public class EnchantingSkillConfig
	{
		public List<int> EnchantLevels = new List<int>();

		public float SuccessEnchantSkillMultiplier = 1f;

		public float SuccessDisenchantSkillMultiplier = 1f;

		public float SuccessAugmentationSkillMultiplier = 1f;

		public float SuccessConvertSkillMultiplier = 1f;

		public float SuccessSacrificeSkillMultiplier = 1f;
	}
}
namespace EpicLoot.BaseEL
{
	public class Assets
	{
		public AssetBundle AssetBundle;

		public Sprite EquippedSprite;

		public Sprite AugaEquippedSprite;

		public Sprite GenericSetItemSprite;

		public Sprite AugaSetItemSprite;

		public Sprite GenericItemBgSprite;

		public Sprite AugaItemBgSprite;

		public GameObject[] MagicItemLootBeamPrefabs = (GameObject[])(object)new GameObject[5];

		public readonly Dictionary<string, GameObject[]> CraftingMaterialPrefabs = new Dictionary<string, GameObject[]>();

		public Sprite SmallButtonEnchantOverlay;

		public AudioClip[] MagicItemDropSFX = (AudioClip[])(object)new AudioClip[5];

		public AudioClip ItemLoopSFX;

		public AudioClip AugmentItemSFX;

		public GameObject MerchantPanel;

		public Sprite MapIconTreasureMap;

		public Sprite MapIconBounty;

		public AudioClip AbandonBountySFX;

		public AudioClip DoubleJumpSFX;

		public GameObject DebugTextPrefab;

		public GameObject AbilityBar;

		public GameObject WelcomMessagePrefab;
	}
	[HarmonyPatch]
	public static class Attack_Patch
	{
		public static Attack ActiveAttack;

		[HarmonyPatch(typeof(Attack), "DoMeleeAttack")]
		[HarmonyPrefix]
		[HarmonyPriority(0)]
		public static void Attack_DoMeleeAttack_Prefix(Attack __instance)
		{
			ActiveAttack = __instance;
		}

		[HarmonyPatch(typeof(Attack), "DoMeleeAttack")]
		[HarmonyPostfix]
		public static void Attack_DoMeleeAttack_Postfix()
		{
			ActiveAttack = null;
		}
	}
	public enum BossDropMode
	{
		Default,
		OnePerPlayerOnServer,
		OnePerPlayerNearBoss
	}
	public static class EpicLootDropsHelper
	{
		public static bool InstantDropsEnabled { get; set; }
	}
	[HarmonyPatch(typeof(CharacterDrop), "OnDeath")]
	public static class CharacterDrop_OnDeath_Patch
	{
		public static void Postfix(CharacterDrop __instance)
		{
			if (EpicLootDropsHelper.InstantDropsEnabled)
			{
				EpicLootBase.OnCharacterDeath(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Ragdoll), "Setup")]
	public static class Ragdoll_Setup_Patch
	{
		public static void Postfix(Ragdoll __instance, CharacterDrop characterDrop)
		{
			if (!((Object)(object)characterDrop == (Object)null) && !((Object)(object)characterDrop.m_character == (Object)null) && !characterDrop.m_character.IsPlayer() && EpicLootBase.CanCharacterDropLoot(characterDrop.m_character))
			{
				EpicLootDropsHelper.InstantDropsEnabled = false;
				string characterCleanName = EpicLootBase.GetCharacterCleanName(characterDrop.m_character);
				int level = characterDrop.m_character.GetLevel();
				__instance.m_nview.m_zdo.Set("characterName", characterCleanName);
				__instance.m_nview.m_zdo.Set("level", level);
			}
		}
	}
	[HarmonyPatch(typeof(Ragdoll), "SpawnLoot")]
	public static class Ragdoll_SpawnLoot_Patch
	{
		public static void Postfix(Ragdoll __instance, Vector3 center)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			string @string = __instance.m_nview.m_zdo.GetString("characterName", "");
			int @int = __instance.m_nview.m_zdo.GetInt("level", 0);
			if (!string.IsNullOrEmpty(@string))
			{
				EpicLootBase.OnCharacterDeath(@string, @int, center + Vector3.up * 0.75f);
			}
		}
	}
	[HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")]
	public static class CharacterDrop_GenerateDropList_DropsEnabled
	{
		[HarmonyPriority(800)]
		[HarmonyBefore(new string[] { "org.bepinex.plugins.creaturelevelcontrol" })]
		public static void Postfix(CharacterDrop __instance)
		{
			EpicLootDropsHelper.InstantDropsEnabled = __instance.m_dropsEnabled;
		}
	}
	[HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")]
	public static class CharacterDrop_GenerateDropList_Patch
	{
		public static void Prefix(CharacterDrop __instance)
		{
			if (!((Object)(object)__instance.m_character != (Object)null) || !__instance.m_character.IsBoss() || EpicLootBase.GetBossTrophyDropMode() == BossDropMode.Default)
			{
				return;
			}
			foreach (Drop drop in __instance.m_drops)
			{
				if (!((Object)(object)drop.m_prefab == (Object)null) && ((((Object)drop.m_prefab).name.Equals("Wishbone") && EpicLootBase.GetBossWishboneDropMode() != 0) || (((Object)drop.m_prefab).name.Equals("CryptKey") && EpicLootBase.GetBossCryptKeyDropMode() != 0)) && drop.m_onePerPlayer)
				{
					drop.m_onePerPlayer = false;
				}
			}
		}

		public static void Postfix(CharacterDrop __instance, ref List<KeyValuePair<GameObject, int>> __result)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Invalid comparison between Unknown and I4
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)__instance.m_character != (Object)null) || !__instance.m_character.IsBoss() || EpicLootBase.GetBossTrophyDropMode() == BossDropMode.Default)
			{
				return;
			}
			for (int i = 0; i < __result.Count; i++)
			{
				GameObject key = __result[i].Key;
				ItemDrop component = key.GetComponent<ItemDrop>();
				if (!((Object)(object)component == (Object)null) && component.m_itemData != null && ((int)component.m_itemData.m_shared.m_itemType == 13 || ((Object)key).name.Equals("Wishbone") || ((Object)key).name.Equals("CryptKey")))
				{
					List<PlayerInfo> playerList = ZNet.instance.GetPlayerList();
					int num = EpicLootBase.GetBossTrophyDropMode() switch
					{
						BossDropMode.OnePerPlayerOnServer => playerList.Count, 
						BossDropMode.OnePerPlayerNearBoss => Math.Max(Player.GetPlayersInRangeXZ(((Component)__instance.m_character).transform.position, EpicLootBase.GetBossTrophyDropPlayerRange()), playerList.Count((PlayerInfo x) => Vector3.Distance(x.m_position, ((Component)__instance.m_character).transform.position) <= EpicLootBase.GetBossTrophyDropPlayerRange())), 
						_ => 1, 
					};
					EpicLootBase.Log($"Dropping trophies: {num} (mode={EpicLootBase.GetBossTrophyDropMode()})");
					__result[i] = new KeyValuePair<GameObject, int>(key, num);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Container), "AddDefaultItems")]
	public static class Container_AddDefaultItems_Patch
	{
		public static void Postfix(Container __instance)
		{
			//IL_0064: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.m_piece == (Object)null)
			{
				return;
			}
			string text = ((Object)__instance.m_piece).name.Replace("(Clone)", "").Trim();
			List<LootTable> lootTable = LootRoller.GetLootTable(text);
			if (lootTable == null || lootTable.Count <= 0)
			{
				return;
			}
			List<ItemData> list = LootRoller.RollLootTable(lootTable, 1, ((Object)__instance.m_piece).name, ((Component)__instance).transform.position);
			object arg = list.Count;
			Vector3 position = ((Component)__instance).transform.position;
			EpicLootBase.Log(string.Format("Rolling on loot table: {0}, spawned {1} items at drop point({2}).", text, arg, ((Vector3)(ref position)).ToString("0")));
			foreach (ItemData item in list)
			{
				__instance.m_inventory.AddItem(item);
				EpicLootBase.Log("  - " + item.m_shared.m_name + (item.IsMagic() ? (": " + string.Join(", ", item.GetMagicItem().Effects.Select((MagicItemEffect x) => x.EffectType.ToString()))) : ""));
			}
		}
	}
	[HarmonyPatch(typeof(Hud), "Awake")]
	public static class Hud_Awake_Patch
	{
		public static void Postfix(Hud __instance)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			((GameObject)Object.Instantiate((Object)(object)EpicLootBase.Assets.DebugTextPrefab, __instance.m_rootObject.transform, false)).AddComponent<DebugText>();
		}
	}
	public class DebugText : MonoBehaviour
	{
		public Text Label;

		private static DebugText _instance;

		public void Awake()
		{
			_instance = this;
			Label = ((Component)this).GetComponentInChildren<Text>();
			((Component)this).gameObject.SetActive(false);
		}

		public void OnDestroy()
		{
			_instance = null;
		}

		public static void SetText(string s)
		{
			_instance.Label.text = s;
		}
	}
	public class EpicLootBase
	{
		public const string PluginId = "randyknapp.mods.epicloot";

		public const string DisplayName = "Epic Loot";

		public const string Version = "0.9.37";

		private readonly ConfigSync _configSync = new ConfigSync("randyknapp.mods.epicloot")
		{
			DisplayName = "Epic Loot",
			CurrentVersion = "0.9.37",
			MinimumRequiredVersion = "0.9.35"
		};

		private static ConfigEntry<string> _setItemColor;

		private static ConfigEntry<string> _magicRarityColor;

		private static ConfigEntry<string> _rareRarityColor;

		private static ConfigEntry<string> _epicRarityColor;

		private static ConfigEntry<string> _legendaryRarityColor;

		private static ConfigEntry<int> _magicMaterialIconColor;

		private static ConfigEntry<int> _rareMaterialIconColor;

		private static ConfigEntry<int> _epicMaterialIconColor;

		private static ConfigEntry<int> _legendaryMaterialIconColor;

		public static ConfigEntry<bool> UseScrollingCraftDescription;

		public static ConfigEntry<bool> TransferMagicItemToCrafts;

		public static ConfigEntry<CraftingTabStyle> CraftingTabStyle;

		private static ConfigEntry<bool> _loggingEnabled;

		private static ConfigEntry<LogLevel> _logLevel;

		public static ConfigEntry<bool> UseGeneratedMagicItemNames;

		private static ConfigEntry<GatedItemTypeMode> _gatedItemTypeModeConfig;

		public static ConfigEntry<GatedBountyMode> BossBountyMode;

		private static ConfigEntry<BossDropMode> _bossTrophyDropMode;

		private static ConfigEntry<float> _bossTrophyDropPlayerRange;

		private static ConfigEntry<int> _andvaranautRange;

		public static ConfigEntry<bool> ShowEquippedAndHotbarItemsInSacrificeTab;

		private static ConfigEntry<bool> _adventureModeEnabled;

		private static ConfigEntry<bool> _serverConfigLocked;

		public static readonly ConfigEntry<string>[] AbilityKeyCodes = new ConfigEntry<string>[3];

		public static ConfigEntry<TextAnchor> AbilityBarAnchor;

		public static ConfigEntry<Vector2> AbilityBarPosition;

		public static ConfigEntry<TextAnchor> AbilityBarLayoutAlignment;

		public static ConfigEntry<float> AbilityBarIconSpacing;

		public static ConfigEntry<float> SetItemDropChance;

		public static ConfigEntry<float> GlobalDropRateModifier;

		public static ConfigEntry<float> ItemsToMaterialsDropRatio;

		public static ConfigEntry<bool> AlwaysShowWelcomeMessage;

		public static ConfigEntry<bool> OutputPatchedConfigFiles;

		public static ConfigEntry<bool> EnchantingTableUpgradesActive;

		public static ConfigEntry<bool> EnableLimitedBountiesInProgress;

		public static ConfigEntry<int> MaxInProgressBounties;

		public static ConfigEntry<EnchantingTabs> EnchantingTableActivatedTabs;

		public static Dictionary<string, CustomSyncedValue<string>> SyncedJsonFiles = new Dictionary<string, CustomSyncedValue<string>>();

		public static Dictionary<string, ConfigValue<string>> NonSyncedJsonFiles = new Dictionary<string, ConfigValue<string>>();

		public static readonly List<ItemType> AllowedMagicItemTypes = new List<ItemType>
		{
			(ItemType)6,
			(ItemType)7,
			(ItemType)11,
			(ItemType)17,
			(ItemType)18,
			(ItemType)4,
			(ItemType)3,
			(ItemType)14,
			(ItemType)22,
			(ItemType)5,
			(ItemType)19,
			(ItemType)15
		};

		public static readonly Dictionary<string, string> MagicItemColors = new Dictionary<string, string>
		{
			{ "Red", "#ff4545" },
			{ "Orange", "#ffac59" },
			{ "Yellow", "#ffff75" },
			{ "Green", "#80fa70" },
			{ "Teal", "#18e7a9" },
			{ "Blue", "#00abff" },
			{ "Indigo", "#709bba" },
			{ "Purple", "#d078ff" },
			{ "Pink", "#ff63d6" },
			{ "Gray", "#dbcadb" }
		};

		public static readonly Assets Assets = new Assets();

		public static readonly List<GameObject> RegisteredPrefabs = new List<GameObject>();

		public static readonly List<GameObject> RegisteredItemPrefabs = new List<GameObject>();

		public static readonly Dictionary<GameObject, PieceDef> RegisteredPieces = new Dictionary<GameObject, PieceDef>();

		private static readonly Dictionary<string, Action<ItemDrop>> _customItemSetupActions = new Dictionary<string, Action<ItemDrop>>();

		private static readonly Dictionary<string, Object> _assetCache = new Dictionary<string, Object>();

		public static bool AlwaysDropCheat = false;

		public const PinType BountyPinType = 800;

		public const PinType TreasureMapPinType = 801;

		public static bool HasAuga;

		public static bool HasAdventureBackpacks;

		public static bool AugaTooltipNoTextBoxes;

		private static EpicLootBase _instance;

		private Harmony _harmony;

		private float _worldLuckFactor;

		private static ConfigEntry<BossDropMode> _bossCryptKeyDropMode;

		private static ConfigEntry<float> _bossCryptKeyDropPlayerRange;

		private static ConfigEntry<BossDropMode> _bossWishboneDropMode;

		private static ConfigEntry<float> _bossWishboneDropPlayerRange;

		private ConfigFile Config;

		private ManualLogSource Logger;

		private float _lastUpdate;

		public static event Action AbilitiesInitialized;

		public static event Action LootTableLoaded;

		public void Awake(ConfigFile config, ManualLogSource logSource)
		{
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Expected O, but got Unknown
			//IL_04bc: Unknown result type (might be due to invalid IL or missing references)
			Config = config;
			Logger = logSource;
			_instance = this;
			_magicRarityColor = Config.Bind<string>("Item Colors", "Magic Rarity Color", "Blue", "The color of Magic rarity items, the lowest magic item tier. (Optional, use an HTML hex color starting with # to have a custom color.) Available options: Red, Orange, Yellow, Green, Teal, Blue, Indigo, Purple, Pink, Gray");
			_magicMaterialIconColor = Config.Bind<int>("Item Colors", "Magic Crafting Material Icon Index", 5, "Indicates the color of the icon used for magic crafting materials. A number between 0 and 9. Available options: 0=Red, 1=Orange, 2=Yellow, 3=Green, 4=Teal, 5=Blue, 6=Indigo, 7=Purple, 8=Pink, 9=Gray");
			_rareRarityColor = Config.Bind<string>("Item Colors", "Rare Rarity Color", "Yellow", "The color of Rare rarity items, the second magic item tier. (Optional, use an HTML hex color starting with # to have a custom color.) Available options: Red, Orange, Yellow, Green, Teal, Blue, Indigo, Purple, Pink, Gray");
			_rareMaterialIconColor = Config.Bind<int>("Item Colors", "Rare Crafting Material Icon Index", 2, "Indicates the color of the icon used for rare crafting materials. A number between 0 and 9. Available options: 0=Red, 1=Orange, 2=Yellow, 3=Green, 4=Teal, 5=Blue, 6=Indigo, 7=Purple, 8=Pink, 9=Gray");
			_epicRarityColor = Config.Bind<string>("Item Colors", "Epic Rarity Color", "Purple", "The color of Epic rarity items, the third magic item tier. (Optional, use an HTML hex color starting with # to have a custom color.) Available options: Red, Orange, Yellow, Green, Teal, Blue, Indigo, Purple, Pink, Gray");
			_epicMaterialIconColor = Config.Bind<int>("Item Colors", "Epic Crafting Material Icon Index", 7, "Indicates the color of the icon used for epic crafting materials. A number between 0 and 9. Available options: 0=Red, 1=Orange, 2=Yellow, 3=Green, 4=Teal, 5=Blue, 6=Indigo, 7=Purple, 8=Pink, 9=Gray");
			_legendaryRarityColor = Config.Bind<string>("Item Colors", "Legendary Rarity Color", "Teal", "The color of Legendary rarity items, the highest magic item tier. (Optional, use an HTML hex color starting with # to have a custom color.) Available options: Red, Orange, Yellow, Green, Teal, Blue, Indigo, Purple, Pink, Gray");
			_legendaryMaterialIconColor = Config.Bind<int>("Item Colors", "Legendary Crafting Material Icon Index", 4, "Indicates the color of the icon used for legendary crafting materials. A number between 0 and 9. Available options: 0=Red, 1=Orange, 2=Yellow, 3=Green, 4=Teal, 5=Blue, 6=Indigo, 7=Purple, 8=Pink, 9=Gray");
			_setItemColor = Config.Bind<string>("Item Colors", "Set Item Color", "#26ffff", "The color of set item text and the set item icon. Use a hex color, default is cyan");
			UseScrollingCraftDescription = Config.Bind<bool>("Crafting UI", "Use Scrolling Craft Description", true, "Changes the item description in the crafting panel to scroll instead of scale when it gets too long for the space.");
			CraftingTabStyle = Config.Bind<CraftingTabStyle>("Crafting UI", "Crafting Tab Style", global::EpicLoot.BaseEL.Crafting.CraftingTabStyle.HorizontalSquish, "Sets the layout style for crafting tabs, if you've got too many. Horizontal is the vanilla method, but might overlap other mods or run off the screen. HorizontalSquish makes the buttons narrower, works okay with 6 or 7 buttons. Vertical puts the tabs in a column to the left the crafting window. Angled tries to make more room at the top of the crafting panel by angling the tabs, works okay with 6 or 7 tabs.");
			ShowEquippedAndHotbarItemsInSacrificeTab = Config.Bind<bool>("Crafting UI", "ShowEquippedAndHotbarItemsInSacrificeTab", false, "If set to false, hides the items that are equipped or on your hotbar in the Sacrifice items list.");
			_loggingEnabled = Config.Bind<bool>("Logging", "Logging Enabled", false, "Enable logging");
			_logLevel = Config.Bind<LogLevel>("Logging", "Log Level", LogLevel.Info, "Only log messages of the selected level or higher");
			UseGeneratedMagicItemNames = Config.Bind<bool>("General", "Use Generated Magic Item Names", true, "If true, magic items uses special, randomly generated names based on their rarity, type, and magic effects.");
			_gatedItemTypeModeConfig = SyncedConfig("Balance", "Item Drop Limits", GatedItemTypeMode.BossKillUnlocksCurrentBiomeItems, "Sets how the drop system limits what item types can drop. Unlimited: no limits, exactly what's in the loot table will drop. BossKillUnlocksCurrentBiomeItems: items will drop for the current biome if the that biome's boss has been killed (Leather gear will drop once Eikthyr is killed). BossKillUnlocksNextBiomeItems: items will only drop for the current biome if the previous biome's boss is killed (Bronze gear will drop once Eikthyr is killed). PlayerMustKnowRecipe: (local world only) the item can drop if the player can craft it. PlayerMustHaveCraftedItem: (local world only) the item can drop if the player has already crafted it or otherwise picked it up. If an item type cannot drop, it will downgrade to an item of the same type and skill that the player has unlocked (i.e. swords will stay swords) according to iteminfo.json.");
			BossBountyMode = SyncedConfig("Balance", "Gated Bounty Mode", GatedBountyMode.Unlimited, "Sets whether available bounties are ungated or gated by boss kills.");
			_bossTrophyDropMode = SyncedConfig("Balance", "Boss Trophy Drop Mode", BossDropMode.OnePerPlayerNearBoss, "Sets bosses to drop a number of trophies equal to the number of players. Optionally set it to only include players within a certain distance, use 'Boss Trophy Drop Player Range' to set the range.");
			_bossTrophyDropPlayerRange = SyncedConfig("Balance", "Boss Trophy Drop Player Range", 100f, "Sets the range that bosses check when dropping multiple trophies using the OnePerPlayerNearBoss drop mode.");
			_bossCryptKeyDropMode = SyncedConfig("Balance", "Crypt Key Drop Mode", BossDropMode.OnePerPlayerNearBoss, "Sets bosses to drop a number of crypt keys equal to the number of players. Optionally set it to only include players within a certain distance, use 'Crypt Key Drop Player Range' to set the range.");
			_bossCryptKeyDropPlayerRange = SyncedConfig("Balance", "Crypt Key Drop Player Range", 100f, "Sets the range that bosses check when dropping multiple crypt keys using the OnePerPlayerNearBoss drop mode.");
			_bossWishboneDropMode = SyncedConfig("Balance", "Wishbone Drop Mode", BossDropMode.OnePerPlayerNearBoss, "Sets bosses to drop a number of wishbones equal to the number of players. Optionally set it to only include players within a certain distance, use 'Crypt Key Drop Player Range' to set the range.");
			_bossWishboneDropPlayerRange = SyncedConfig("Balance", "Wishbone Drop Player Range", 100f, "Sets the range that bosses check when dropping multiple wishbones using the OnePerPlayerNearBoss drop mode.");
			_adventureModeEnabled = SyncedConfig("Balance", "Adventure Mode Enabled", value: true, "Set to true to enable all the adventure mode features: secret stash, gambling, treasure maps, and bounties. Set to false to disable. This will not actually remove active treasure maps or bounties from your save.");
			_andvaranautRange = SyncedConfig("Balance", "Andvaranaut Range", 20, "Sets the range that Andvaranaut will locate a treasure chest.");
			_serverConfigLocked = SyncedConfig("Config Sync", "Lock Config", value: false, new ConfigDescription("[Server Only] The configuration is locked and may not be changed by clients once it has been synced from the server. Only valid for server config, will have no effect on clients.", (AcceptableValueBase)null, Array.Empty<object>()));
			SetItemDropChance = SyncedConfig("Balance", "Set Item Drop Chance", 0.15f, "The percent chance that a legendary item will be a set item. Min = 0, Max = 1");
			GlobalDropRateModifier = SyncedConfig("Balance", "Global Drop Rate Modifier", 1f, "A global percentage that modifies how likely items are to drop. 1 = Exactly what is in the loot tables will drop. 0 = Nothing will drop. 2 = The number of items in the drop table are twice as likely to drop (note, this doesn't double the number of items dropped, just doubles the relative chance for them to drop). Min = 0, Max = 4");
			ItemsToMaterialsDropRatio = SyncedConfig("Balance", "Items To Materials Drop Ratio", 0f, "Sets the chance that item drops are instead dropped as magic crafting materials. 0 = all items, no materials. 1 = all materials, no items. Values between 0 and 1 change the ratio of items to materials that drop. At 0.5, half of everything that drops would be items and the other half would be materials. Min = 0, Max = 1");
			TransferMagicItemToCrafts = SyncedConfig("Balance", "Transfer Enchants to Crafted Items", value: false, "When enchanted items are used as ingredients in recipes, transfer the highest enchant to the newly crafted item. Default: False.");
			AlwaysShowWelcomeMessage = Config.Bind<bool>("Debug", "AlwaysShowWelcomeMessage", false, "Just a debug flag for testing the welcome message, do not use.");
			OutputPatchedConfigFiles = Config.Bind<bool>("Debug", "OutputPatchedConfigFiles", false, "Just a debug flag for testing the patching system, do not use.");
			AbilityKeyCodes[0] = Config.Bind<string>("Abilities", "Ability Hotkey 1", "g", "Hotkey for Ability Slot 1.");
			AbilityKeyCodes[1] = Config.Bind<string>("Abilities", "Ability Hotkey 2", "h", "Hotkey for Ability Slot 2.");
			AbilityKeyCodes[2] = Config.Bind<string>("Abilities", "Ability Hotkey 3", "j", "Hotkey for Ability Slot 3.");
			AbilityBarAnchor = Config.Bind<TextAnchor>("Abilities", "Ability Bar Anchor", (TextAnchor)6, "The point on the HUD to anchor the ability bar. Changing this also changes the pivot of the ability bar to that corner. For reference: the ability bar size is 208 by 64.");
			AbilityBarPosition = Config.Bind<Vector2>("Abilities", "Ability Bar Position", new Vector2(150f, 170f), "The position offset from the Ability Bar Anchor at which to place the ability bar.");
			AbilityBarLayoutAlignment = Config.Bind<TextAnchor>("Abilities", "Ability Bar Layout Alignment", (TextAnchor)6, "The Ability Bar is a Horizontal Layout Group. This value indicates how the elements inside are aligned. Choices with 'Center' in them will keep the items centered on the bar, even if there are fewer than the maximum allowed. 'Left' will be left aligned, and similar for 'Right'.");
			AbilityBarIconSpacing = Config.Bind<float>("Abilities", "Ability Bar Icon Spacing", 8f, "The number of units between the icons on the ability bar.");
			EnchantingTableUpgradesActive = SyncedConfig("Enchanting Table", "Upgrades Active", value: true, "Toggles Enchanting Table Upgrade Capabilities. If false, enchanting table features will be unlocked set to Level 1");
			EnchantingTableActivatedTabs = SyncedConfig("Enchanting Table", "Table Features Active", EnchantingTabs.Sacrifice | EnchantingTabs.ConvertMaterials | EnchantingTabs.Enchant | EnchantingTabs.Augment | EnchantingTabs.Disenchant | EnchantingTabs.Upgrade, "Toggles Enchanting Table Feature on and off completely.");
			EnableLimitedBountiesInProgress = SyncedConfig("Bounty Management", "Enable Bounty Limit", value: false, "Toggles limiting bounties. Players unable to purchase if enabled and maximum bounty in-progress count is met");
			MaxInProgressBounties = SyncedConfig("Bounty Management", "Max Bounties Per Player", 5, "Max amount of in-progress bounties allowed per player.");
			_configSync.AddLockingConfigEntry<bool>(_serverConfigLocked);
			EIDFLegacy.CheckForExtendedItemFrameworkLoaded(_instance);
			EnchantingTableUpgradesActive.SettingChanged += delegate
			{
				EnchantingTableUI.UpdateUpgradeActivation();
			};
			EnchantingTableActivatedTabs.SettingChanged += delegate
			{
				EnchantingTableUI.UpdateTabActivation();
			};
			HasAdventureBackpacks = ABAPI.IsLoaded();
			LoadPatches();
			InitializeConfig();
			InitializeAbilities();
			PrintInfo();
			LoadAssets();
			EnchantingUIController.Initialize();
			_harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "randyknapp.mods.epicloot");
			EpicLootBase.LootTableLoaded?.Invoke();
		}

		public void Start()
		{
			HasAuga = API.IsLoaded();
			if (HasAuga)
			{
				API.ComplexTooltip_AddItemTooltipCreatedListener(ExtendAugaTooltipForMagicItem);
				API.ComplexTooltip_AddItemStatPreprocessor(AugaTooltipPreprocessor.PreprocessTooltipStat);
			}
		}

		public static void ExtendAugaTooltipForMagicItem(GameObject complexTooltip, ItemData item)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			API.ComplexTooltip_SetTopic(complexTooltip, Localization.instance.Localize(item.GetDecoratedName()));
			MagicItem magicItem;
			bool flag = item.IsMagic(out magicItem);
			bool flag2 = true;
			Transform val = complexTooltip.transform.Find("Tooltip/IconHeader/IconBkg/Item");
			if ((Object)(object)val == (Object)null)
			{
				val = complexTooltip.transform.Find("InventoryElement/icon");
				flag2 = false;
			}
			RectTransform val2 = null;
			if ((Object)(object)val != (Object)null)
			{
				Image component = ((Component)val).GetComponent<Image>();
				val2 = (RectTransform)((Component)val).transform.Find("magicItem");
				if ((Object)(object)val2 == (Object)null)
				{
					GameObject gameObject = ((Component)Object.Instantiate<Image>(component, flag2 ? ((Component)val).transform : ((Component)val).transform.parent)).gameObject;
					((Object)gameObject).name = "magicItem";
					gameObject.SetActive(true);
					val2 = (RectTransform)gameObject.transform;
					val2.anchorMin = Vector2.zero;
					val2.anchorMax = new Vector2(1f, 1f);
					val2.sizeDelta = Vector2.zero;
					val2.pivot = new Vector2(0.5f, 0.5f);
					val2.anchoredPosition = Vector2.zero;
					Image component2 = ((Component)val2).GetComponent<Image>();
					((Graphic)component2).color = Color.white;
					((Graphic)component2).raycastTarget = false;
					component2.sprite = GetMagicItemBgSprite();
					if (!flag2)
					{
						((Transform)val2).SetSiblingIndex(0);
					}
				}
			}
			if ((Object)(object)val2 != (Object)null)
			{
				((Component)val2).gameObject.SetActive(flag);
			}
			if (item.IsMagicCraftingMaterial())
			{
				ItemRarity craftingMaterialRarity = item.GetCraftingMaterialRarity();
				API.ComplexTooltip_SetIcon(complexTooltip, item.m_shared.m_icons[GetRarityIconIndex(craftingMaterialRarity)]);
			}
			if (!flag)
			{
				return;
			}
			string colorString = magicItem.GetColorString();
			string itemTypeName = magicItem.GetItemTypeName(item.Extended());
			if ((Object)(object)val2 != (Object)null)
			{
				((Graphic)((Component)val2).GetComponent<Image>()).color = item.GetRarityColor();
			}
			API.ComplexTooltip_SetIcon(complexTooltip, item.GetIcon());
			string text = ((!item.IsLegendarySetItem()) ? ("<color=" + colorString + ">" + magicItem.GetRarityDisplay() + " " + itemTypeName + "</color>") : ("<color=" + GetSetItemColor() + ">$mod_epicloot_legendarysetlabel</color>, " + itemTypeName + "\n"));
			try
			{
				API.ComplexTooltip_SetSubtitle(complexTooltip, Localization.instance.Localize(text));
			}
			catch (Exception)
			{
				API.ComplexTooltip_SetSubtitle(complexTooltip, text);
			}
			if (!AugaTooltipNoTextBoxes && !((Object)complexTooltip).name.Contains("InventoryTooltip"))
			{
				API.ComplexTooltip_AddDivider(complexTooltip);
				string tooltip = magicItem.GetTooltip();
				GameObject tooltipTextBoxGO = API.ComplexTooltip_AddTwoColumnTextBox(complexTooltip);
				tooltip = tooltip.Replace("\n\n", "");
				API.TooltipTextBox_AddLine(tooltipTextBoxGO, tooltip);
				if (magicItem.IsLegendarySetItem())
				{
					API.TooltipTextBox_AddLine(API.ComplexTooltip_AddTwoColumnTextBox(complexTooltip), item.GetSetTooltip());
				}
				try
				{
					API.ComplexTooltip_SetDescription(complexTooltip, Localization.instance.Localize(item.GetDescription()));
				}
				catch (Exception)
				{
					API.ComplexTooltip_SetDescription(complexTooltip, item.GetDescription());
				}
			}
		}

		private ConfigEntry<T> SyncedConfig<T>(string group, string configName, T value, string description, bool synchronizedSetting = true)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			return SyncedConfig(group, configName, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting);
		}

		private ConfigEntry<T> SyncedConfig<T>(string group, string configName, T value, ConfigDescription description, bool synchronizedSetting = true)
		{
			ConfigEntry<T> val = Config.Bind<T>(group, configName, value, description);
			_configSync.AddConfigEntry<T>(val).SynchronizedConfig = synchronizedSetting;
			return val;
		}

		public static void LoadPatches()
		{
			FilePatching.LoadAllPatches();
		}

		private static void LoadTranslations(IDictionary<string, object> translations)
		{
			if (translations == null)
			{
				LogErrorForce("Could not parse translations.json!");
				return;
			}
			foreach (KeyValuePair<string, string> item in Localization.instance.m_translations.Where((KeyValuePair<string, string> instanceMTranslation) => instanceMTranslation.Key.StartsWith("mod_epicloot_")).ToList())
			{
				Localization.instance.m_translations.Remove(item.Key);
			}
			foreach (KeyValuePair<string, object> translation in translations)
			{
				Localization.instance.AddWord(translation.Key, translation.Value.ToString());
			}
		}

		public static ConfigFile GetConfigObject()
		{
			return _instance.Config;
		}

		public static void InitializeConfig()
		{
			LoadJsonFile<IDictionary<string, object>>("translations.json", LoadTranslations, ConfigType.Nonsynced);
			LoadJsonFile<LootConfig>("loottables.json", LootRoller.Initialize, ConfigType.Synced);
			LoadJsonFile<MagicItemEffectsList>("magiceffects.json", MagicItemEffectDefinitions.Initialize, ConfigType.Synced);
			LoadJsonFile<ItemInfoConfig>("iteminfo.json", GatedItemTypeHelper.Initialize, ConfigType.Synced);
			LoadJsonFile<RecipesConfig>("recipes.json", RecipesHelper.Initialize, ConfigType.Synced);
			LoadJsonFile<EnchantingCostsConfig>("enchantcosts.json", EnchantCostsHelper.Initialize, ConfigType.Synced);
			LoadJsonFile<ItemNameConfig>("itemnames.json", MagicItemNames.Initialize, ConfigType.Synced);
			LoadJsonFile<AdventureDataConfig>("adventuredata.json", AdventureDataManager.Initialize, ConfigType.Synced);
			LoadJsonFile<LegendaryItemConfig>("legendaries.json", UniqueLegendaryHelper.Initialize, ConfigType.Synced);
			LoadJsonFile<AbilityConfig>("abilities.json", AbilityDefinitions.Initialize, ConfigType.Synced);
			LoadJsonFile<MaterialConversionsConfig>("materialconversions.json", MaterialConversions.Initialize, ConfigType.Synced);
			LoadJsonFile("enchantingupgrades.json", (Action<EnchantingUpgradesConfig>)EnchantingTableUpgrades.InitializeConfig, ConfigType.Synced, update: false);
			LoadJsonFile<EnchantingSkillConfig>("enchantingskill.json", Enchanting.InitSkillConfig, ConfigType.Synced);
			WatchNewPatchConfig();
		}

		public static void WatchNewPatchConfig()
		{
			Log("Watching For Files");
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(FilePatching.PatchesDirPath, "*.json");
			fileSystemWatcher.Created += ConsumeNewPatchFile;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
			static void ConsumeNewPatchFile(object s, FileSystemEventArgs e)
			{
				if (e.ChangeType == WatcherChangeTypes.Created)
				{
					FileInfo fileInfo = new FileInfo(e.FullPath);
					if (fileInfo.Exists)
					{
						FilePatching.ProcessPatchFile(fileInfo);
						string sourceFile = fileInfo.Name;
						string[] array = (from u in FilePatching.PatchesPerFile.Values.SelectMany((List<Patch> l) => l).ToList()
							where u.SourceFile.Equals(sourceFile)
							select u into p
							select p.TargetFile).Distinct().ToArray();
						foreach (string text in array)
						{
							if (SyncedJsonFiles.ContainsKey(text))
							{
								SyncedJsonFiles[text].AssignLocalValue(LoadJsonText(text));
							}
							else
							{
								NonSyncedJsonFiles[text].AssignValue(LoadJsonText(text));
							}
							AddPatchFileWatcher(text, sourceFile);
						}
					}
				}
			}
		}

		private static void InitializeAbilities()
		{
			MagicEffectType.Initialize();
			EpicLootBase.AbilitiesInitialized?.Invoke();
		}

		public static void Log(string message)
		{
			if (_loggingEnabled.Value && _logLevel.Value <= LogLevel.Info)
			{
				_instance.Logger.LogInfo((object)message);
			}
		}

		public static void LogWarning(string message)
		{
			if (_loggingEnabled.Value && _logLevel.Value <= LogLevel.Warning)
			{
				_instance.Logger.LogWarning((object)message);
			}
		}

		public static void LogError(string message)
		{
			if (_loggingEnabled.Value && _logLevel.Value <= LogLevel.Error)
			{
				_instance.Logger.LogError((object)message);
			}
		}

		public static void LogWarningForce(string message)
		{
			_instance.Logger.LogWarning((object)message);
		}

		public static void LogErrorForce(string message)
		{
			_instance.Logger.LogError((object)message);
		}

		public void Update()
		{
			if (Time.time - _lastUpdate > 0.05f)
			{
				_lastUpdate = Time.time;
				EnchantingUIController.RefreshEnchantRarityButtons();
			}
		}

		private void LoadAssets()
		{
			AssetBundle val = AssetUtils.LoadAssetBundleFromResources("epicloot");
			Assets.AssetBundle = val;
			Assets.EquippedSprite = val.LoadAsset<Sprite>("Equipped");
			Assets.AugaEquippedSprite = val.LoadAsset<Sprite>("AugaEquipped");
			Assets.GenericSetItemSprite = val.LoadAsset<Sprite>("GenericSetItemMarker");
			Assets.AugaSetItemSprite = val.LoadAsset<Sprite>("AugaSetItem");
			Assets.GenericItemBgSprite = val.LoadAsset<Sprite>("GenericItemBg");
			Assets.AugaItemBgSprite = val.LoadAsset<Sprite>("AugaItemBG");
			Assets.SmallButtonEnchantOverlay = val.LoadAsset<Sprite>("SmallButtonEnchantOverlay");
			Assets.MagicItemLootBeamPrefabs[0] = val.LoadAsset<GameObject>("MagicLootBeam");
			Assets.MagicItemLootBeamPrefabs[1] = val.LoadAsset<GameObject>("RareLootBeam");
			Assets.MagicItemLootBeamPrefabs[2] = val.LoadAsset<GameObject>("EpicLootBeam");
			Assets.MagicItemLootBeamPrefabs[3] = val.LoadAsset<GameObject>("LegendaryLootBeam");
			Assets.MagicItemLootBeamPrefabs[4] = val.LoadAsset<GameObject>("MythicLootBeam");
			Assets.MagicItemDropSFX[0] = val.LoadAsset<AudioClip>("MagicItemDrop");
			Assets.MagicItemDropSFX[1] = val.LoadAsset<AudioClip>("RareItemDrop");
			Assets.MagicItemDropSFX[2] = val.LoadAsset<AudioClip>("EpicItemDrop");
			Assets.MagicItemDropSFX[3] = val.LoadAsset<AudioClip>("LegendaryItemDrop");
			Assets.MagicItemDropSFX[4] = val.LoadAsset<AudioClip>("MythicItemDrop");
			Assets.ItemLoopSFX = val.LoadAsset<AudioClip>("ItemLoop");
			Assets.AugmentItemSFX = val.LoadAsset<AudioClip>("AugmentItem");
			Assets.MerchantPanel = val.LoadAsset<GameObject>("MerchantPanel");
			Assets.MapIconTreasureMap = val.LoadAsset<Sprite>("TreasureMapIcon");
			Assets.MapIconBounty = val.LoadAsset<Sprite>("MapIconBounty");
			Assets.AbandonBountySFX = val.LoadAsset<AudioClip>("AbandonBounty");
			Assets.DoubleJumpSFX = val.LoadAsset<AudioClip>("DoubleJump");
			Assets.DebugTextPrefab = val.LoadAsset<GameObject>("DebugText");
			Assets.AbilityBar = val.LoadAsset<GameObject>("AbilityBar");
			Assets.WelcomMessagePrefab = val.LoadAsset<GameObject>("WelcomeMessage");
			LoadCraftingMaterialAssets(val, "Runestone");
			LoadCraftingMaterialAssets(val, "Shard");
			LoadCraftingMaterialAssets(val, "Dust");
			LoadCraftingMaterialAssets(val, "Reagent");
			LoadCraftingMaterialAssets(val, "Essence");
			LoadBuildPiece(val, "piece_enchanter", new PieceDef
			{
				Table = "_HammerPieceTable",
				CraftingStation = "piece_workbench",
				Resources = new List<RecipeRequirementConfig>
				{
					new RecipeRequirementConfig
					{
						item = "Stone",
						amount = 10
					},
					new RecipeRequirementConfig
					{
						item = "SurtlingCore",
						amount = 3
					},
					new RecipeRequirementConfig
					{
						item = "Copper",
						amount = 3
					}
				}
			});
			LoadBuildPiece(val, "piece_augmenter", new PieceDef
			{
				Table = "_HammerPieceTable",
				CraftingStation = "piece_workbench",
				Resources = new List<RecipeRequirementConfig>
				{
					new RecipeRequirementConfig
					{
						item = "Obsidian",
						amount = 10
					},
					new RecipeRequirementConfig
					{
						item = "Crystal",
						amount = 3
					},
					new RecipeRequirementConfig
					{
						item = "Bronze",
						amount = 3
					}
				}
			});
			LoadBuildPiece(val, "piece_enchantingtable", new PieceDef
			{
				Table = "_HammerPieceTable",
				CraftingStation = "piece_workbench",
				Resources = new List<RecipeRequirementConfig>
				{
					new RecipeRequirementConfig
					{
						item = "FineWood",
						amount = 10
					},
					new RecipeRequirementConfig
					{
						item = "SurtlingCore",
						amount = 1
					}
				}
			});
			LoadItem(val, "LeatherBelt");
			LoadItem(val, "SilverRing");
			LoadItem(val, "GoldRubyRing");
			LoadItem(val, "Andvaranaut", SetupAndvaranaut);
			LoadItem(val, "ForestToken");
			LoadItem(val, "IronBountyToken");
			LoadItem(val, "GoldBountyToken");
			LoadAllZNetAssets(val);
		}

		public static T LoadAsset<T>(string assetName) where T : Object
		{
			try
			{
				if (_assetCache.ContainsKey(assetName))
				{
					return (T)(object)_assetCache[assetName];
				}
				T val = Assets.AssetBundle.LoadAsset<T>(assetName);
				_assetCache.Add(assetName, (Object)(object)val);
				return val;
			}
			catch (Exception ex)
			{
				LogErrorForce("Error loading asset (" + assetName + "): " + ex.Message);
				return default(T);
			}
		}

		private static void LoadItem(AssetBundle assetBundle, string assetName, Action<ItemDrop> customSetupAction = null)
		{
			bool forceDisableInit = ZNetView.m_forceDisableInit;
			ZNetView.m_forceDisableInit = true;
			GameObject val = assetBundle.LoadAsset<GameObject>(assetName);
			ZNetView.m_forceDisableInit = forceDisableInit;
			RegisteredItemPrefabs.Add(val);
			RegisteredPrefabs.Add(val);
			if (customSetupAction != null)
			{
				_customItemSetupActions.Add(((Object)val).name, customSetupAction);
			}
		}

		private static void LoadBuildPiece(AssetBundle assetBundle, string assetName, PieceDef pieceDef)
		{
			GameObject val = assetBundle.LoadAsset<GameObject>(assetName);
			RegisteredPieces.Add(val, pieceDef);
			RegisteredPrefabs.Add(val);
		}

		private static void LoadCraftingMaterialAssets(AssetBundle assetBundle, string type)
		{
			GameObject[] array = (GameObject[])(object)new GameObject[5];
			foreach (ItemRarity value in Enum.GetValues(typeof(ItemRarity)))
			{
				string text = $"{type}{value}";
				GameObject val = assetBundle.LoadAsset<GameObject>(text);
				if ((Object)(object)val == (Object)null)
				{
					LogErrorForce("Tried to load asset " + text + " but it does not exist in the asset bundle!");
					continue;
				}
				array[(int)value] = val;
				RegisteredPrefabs.Add(val);
				RegisteredItemPrefabs.Add(val);
			}
			Assets.CraftingMaterialPrefabs.Add(type, array);
		}

		private void LoadAllZNetAssets(AssetBundle assetBundle)
		{
			Object[] array = assetBundle.LoadAllAssets();
			foreach (Object val in array)
			{
				GameObject val2 = (GameObject)(object)((val is GameObject) ? val : null);
				if (val2 != null && (Object)(object)val2.GetComponent<ZNetView>() != (Object)null)
				{
					if (!_assetCache.ContainsKey(val.name))
					{
						_assetCache.Add(val.name, (Object)(object)val2);
					}
					if (!RegisteredPrefabs.Contains(val2))
					{
						RegisteredPrefabs.Add(val2);
					}
				}
			}
		}

		public void OnDestroy()
		{
			_instance = null;
		}

		public static void TryRegisterPrefabs(ZNetScene zNetScene)
		{
			if ((Object)(object)zNetScene == (Object)null || zNetScene.m_prefabs == null || zNetScene.m_prefabs.Count <= 0)
			{
				return;
			}
			foreach (GameObject registeredPrefab in RegisteredPrefabs)
			{
				if (!zNetScene.m_prefabs.Contains(registeredPrefab))
				{
					zNetScene.m_prefabs.Add(registeredPrefab);
				}
			}
		}

		public static void TryRegisterPieces(List<PieceTable> pieceTables, List<CraftingStation> craftingStations)
		{
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Expected O, but got Unknown
			foreach (KeyValuePair<GameObject, PieceDef> registeredPiece in RegisteredPieces)
			{
				GameObject key = registeredPiece.Key;
				if ((Object)(object)key == (Object)null)
				{
					LogError("Tried to register piece but prefab was null!");
					continue;
				}
				PieceDef pieceDef = registeredPiece.Value;
				if (pieceDef == null)
				{
					LogError($"Tried to register piece ({key}) but pieceDef was null!");
					continue;
				}
				Piece component = key.GetComponent<Piece>();
				if ((Object)(object)component == (Object)null)
				{
					LogError($"Tried to register piece ({key}) but Piece component was missing!");
					continue;
				}
				PieceTable val = pieceTables.Find((PieceTable x) => ((Object)x).name == pieceDef.Table);
				if ((Object)(object)val == (Object)null)
				{
					LogError(string.Format("Tried to register piece ({0}) but could not find piece table ({1}) (pieceTables({2})= {3})!", key, pieceDef.Table, pieceTables.Count, string.Join(", ", pieceTables.Select((PieceTable x) => ((Object)x).name))));
				}
				else
				{
					if (val.m_pieces.Contains(key))
					{
						continue;
					}
					val.m_pieces.Add(key);
					CraftingStation craftingStation = craftingStations.Find((CraftingStation x) => ((Object)x).name == pieceDef.CraftingStation);
					component.m_craftingStation = craftingStation;
					List<Requirement> list = new List<Requirement>();
					foreach (RecipeRequirementConfig resource in pieceDef.Resources)
					{
						GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(resource.item);
						list.Add(new Requirement
						{
							m_resItem = itemPrefab.GetComponent<ItemDrop>(),
							m_amount = resource.amount
						});
					}
					component.m_resources = list.ToArray();
					StationExtension component2 = key.GetComponent<StationExtension>();
					if ((Object)(object)component2 != (Object)null && !string.IsNullOrEmpty(pieceDef.ExtendStation))
					{
						GameObject val2 = val.m_pieces.Find((GameObject x) => ((Object)x).name == pieceDef.ExtendStation);
						if ((Object)(object)val2 != (Object)null)
						{
							CraftingStation component3 = val2.GetComponent<CraftingStation>();
							component2.m_craftingStation = component3;
						}
						GameObject val3 = val.m_pieces.Find((GameObject x) => (Object)(object)x.GetComponent<StationExtension>() != (Object)null);
						if ((Object)(object)val3 != (Object)null)
						{
							StationExtension component4 = val3.GetComponent<StationExtension>();
							Piece component5 = val3.GetComponent<Piece>();
							component2.m_connectionPrefab = component4.m_connectionPrefab;
							component.m_placeEffect.m_effectPrefabs = component5.m_placeEffect.m_effectPrefabs.ToArray();
						}
						continue;
					}
					GameObject val4 = ((IEnumerable<GameObject>)val.m_pieces).FirstOrDefault((Func<GameObject, bool>)((GameObject x) => ((Object)x).name == "piece_workshop"));
					if ((Object)(object)val4 != (Object)null)
					{
						Piece component6 = val4.GetComponent<Piece>();
						if (component6 != null)
						{
							component.m_placeEffect.m_effectPrefabs = component6.m_placeEffect.m_effectPrefabs.ToArray();
						}
					}
				}
			}
		}

		public static bool IsObjectDBReady()
		{
			if ((Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items.Count != 0)
			{
				return (Object)(object)ObjectDB.instance.GetItemPrefab("Amber") != (Object)null;
			}
			return false;
		}

		public static void TryRegisterItems()
		{
			if (!IsObjectDBReady())
			{
				return;
			}
			foreach (GameObject registeredItemPrefab in RegisteredItemPrefabs)
			{
				ItemDrop component = registeredItemPrefab.GetComponent<ItemDrop>();
				if ((Object)(object)component != (Object)null && (component.m_itemData.IsMagicCraftingMaterial() || component.m_itemData.IsRunestone()))
				{
					ItemRarity rarity = component.m_itemData.GetRarity();
					if (component.m_itemData.IsMagicCraftingMaterial())
					{
						component.m_itemData.m_variant = GetRarityIconIndex(rarity);
					}
				}
			}
			foreach (GameObject registeredItemPrefab2 in RegisteredItemPrefabs)
			{
				if ((Object)(object)registeredItemPrefab2.GetComponent<ItemDrop>() != (Object)null && (Object)(object)ObjectDB.instance.GetItemPrefab(StringExtensionMethods.GetStableHashCode(((Object)registeredItemPrefab2).name)) == (Object)null)
				{
					ObjectDB.instance.m_items.Add(registeredItemPrefab2);
				}
			}
			foreach (GameObject registeredItemPrefab3 in RegisteredItemPrefabs)
			{
				ItemDrop component2 = registeredItemPrefab3.GetComponent<ItemDrop>();
				if ((Object)(object)component2 != (Object)null && _customItemSetupActions.TryGetValue(((Object)registeredItemPrefab3).name, out var value))
				{
					value?.Invoke(component2);
				}
			}
			ObjectDB.instance.UpdateItemHashes();
			List<PieceTable> list = new List<PieceTable>();
			foreach (GameObject item in ObjectDB.instance.m_items)
			{
				ItemDrop component3 = item.GetComponent<ItemDrop>();
				if ((Object)(object)component3 == (Object)null)
				{
					LogError($"An item without an ItemDrop ({item}) exists in ObjectDB.instance.m_items! Don't do this!");
					continue;
				}
				ItemData itemData = component3.m_itemData;
				if (itemData != null && (Object)(object)itemData.m_shared.m_buildPieces != (Object)null && !list.Contains(itemData.m_shared.m_buildPieces))
				{
					list.Add(itemData.m_shared.m_buildPieces);
				}
			}
			List<CraftingStation> list2 = new List<CraftingStation>();
			foreach (PieceTable item2 in list)
			{
				list2.AddRange(from x in item2.m_pieces
					where (Object)(object)x.GetComponent<CraftingStation>() != (Object)null
					select x.GetComponent<CraftingStation>());
			}
			TryRegisterPieces(list, list2);
			SetupStatusEffects();
		}

		public static void TryRegisterRecipes()
		{
			if (IsObjectDBReady())
			{
				RecipesHelper.SetupRecipes();
			}
		}

		private static void SetupAndvaranaut(ItemDrop prefab)
		{
			ItemData itemData = prefab.m_itemData;
			ItemData itemData2 = ObjectDB.instance.GetItemPrefab("Wishbone").GetComponent<ItemDrop>().m_itemData;
			StatusEffect equipStatusEffect = itemData2.m_shared.m_equipStatusEffect;
			SE_CustomFinder sE_CustomFinder = ScriptableObject.CreateInstance<SE_CustomFinder>();
			Utils.CopyFields(equipStatusEffect, sE_CustomFinder, typeof(SE_Finder));
			((Object)sE_CustomFinder).name = "CustomWishboneFinder";
			SE_CustomFinder sE_CustomFinder2 = ScriptableObject.CreateInstance<SE_CustomFinder>();
			Utils.CopyFields(sE_CustomFinder, sE_CustomFinder2, typeof(SE_CustomFinder));
			((Object)sE_CustomFinder2).name = "Andvaranaut";
			((StatusEffect)sE_CustomFinder2).m_name = "$mod_epicloot_item_andvaranaut";
			((StatusEffect)sE_CustomFinder2).m_icon = itemData.GetIcon();
			((StatusEffect)sE_CustomFinder2).m_tooltip = "$mod_epicloot_item_andvaranaut_tooltip";
			((StatusEffect)sE_CustomFinder2).m_startMessage = "$mod_epicloot_item_andvaranaut_startmsg";
			sE_CustomFinder2.RequiredComponentTypes = new List<Type> { typeof(TreasureMapChest) };
			sE_CustomFinder.DisallowedComponentTypes = new List<Type> { typeof(TreasureMapChest) };
			ObjectDB.instance.m_StatusEffects.Remove(equipStatusEffect);
			ObjectDB.instance.m_StatusEffects.Add((StatusEffect)(object)sE_CustomFinder2);
			ObjectDB.instance.m_StatusEffects.Add((StatusEffect)(object)sE_CustomFinder);
			itemData.m_shared.m_equipStatusEffect = (StatusEffect)(object)sE_CustomFinder2;
			itemData2.m_shared.m_equipStatusEffect = (StatusEffect)(object)sE_CustomFinder;
			MagicItem magicItem = new MagicItem
			{
				Rarity = ItemRarity.Epic,
				TypeNameOverride = "$mod_epicloot_item_andvaranaut_type"
			};
			magicItem.Effects.Add(new MagicItemEffect(MagicEffectType.Andvaranaut));
			prefab.m_itemData.SaveMagicItem(magicItem);
		}

		private static void SetupStatusEffects()
		{
			StatusEffect statusEffect = ObjectDB.instance.GetStatusEffect("Lightning".GetHashCode());
			SE_Paralyzed sE_Paralyzed = ScriptableObject.CreateInstance<SE_Paralyzed>();
			Utils.CopyFields(statusEffect, sE_Paralyzed, typeof(StatusEffect));
			((Object)sE_Paralyzed).name = "Paralyze";
			((StatusEffect)sE_Paralyzed).m_name = "mod_epicloot_se_paralyze";
			ObjectDB.instance.m_StatusEffects.Add((StatusEffect)(object)sE_Paralyzed);
		}

		public static void LoadJsonFile<T>(string filename, Action<T> onFileLoad, ConfigType configType, bool update = false) where T : class
		{
			string text = LoadJsonText(filename);
			if (!update)
			{
				if (configType == ConfigType.Synced)
				{
					SyncedJsonFiles.Add(filename, new CustomSyncedValue<string>(_instance._configSync, filename, text));
				}
				else
				{
					NonSyncedJsonFiles.Add(filename, new ConfigValue<string>(filename, text));
				}
			}
			if (configType == ConfigType.Synced)
			{
				SyncedJsonFiles[filename].ValueChanged += Process;
			}
			else
			{
				NonSyncedJsonFiles[filename].ValueChanged += Process;
			}
			Process();
			if (text == null)
			{
				return;
			}
			string assetPath = GetAssetPath(filename);
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Path.GetDirectoryName(assetPath), Path.GetFileName(assetPath));
			fileSystemWatcher.Changed += ConsumeConfigFileEvent;
			fileSystemWatcher.Created += ConsumeConfigFileEvent;
			fileSystemWatcher.Renamed += ConsumeConfigFileEvent;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
			for (int i = 0; i < FilePatching.PatchesPerFile.Where((KeyValuePair<string, List<Patch>> y) => y.Key.Equals(filename)).ToList().Count; i++)
			{
				List<string> list = FilePatching.PatchesPerFile.Where((KeyValuePair<string, List<Patch>> y) => y.Key.Equals(filename)).ToList()[i].Value.Select((Patch p) => p.SourceFile).Distinct().ToList();
				for (int j = 0; j < list.Count; j++)
				{
					string patchFile = list[j];
					AddPatchFileWatcher(filename, patchFile);
				}
			}
			void ConsumeConfigFileEvent(object s, FileSystemEventArgs e)
			{
				if (configType == ConfigType.Synced)
				{
					SyncedJsonFiles[filename].AssignLocalValue(LoadJsonText(filename));
				}
				else
				{
					NonSyncedJsonFiles[filename].AssignValue(LoadJsonText(filename));
				}
			}
			void Process()
			{
				T obj;
				try
				{
					obj = ((configType != 0) ? (string.IsNullOrEmpty(NonSyncedJsonFiles[filename].Value) ? null : JsonConvert.DeserializeObject<T>(NonSyncedJsonFiles[filename].Value)) : (string.IsNullOrEmpty(SyncedJsonFiles[filename].Value) ? null : JsonConvert.DeserializeObject<T>(SyncedJsonFiles[filename].Value)));
				}
				catch (Exception)
				{
					LogErrorForce("Could not parse file '" + filename + "'! Errors in JSON!");
					throw;
				}
				onFileLoad(obj);
			}
		}

		private static void AddPatchFileWatcher(string fileName, string patchFile)
		{
			string fullPatchFilename = Path.Combine(FilePatching.PatchesDirPath, patchFile);
			Log("[AddPatchFileWatcher] Full Patch File Name = " + fullPatchFilename);
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Path.GetDirectoryName(fullPatchFilename), Path.GetFileName(fullPatchFilename));
			fileSystemWatcher.Changed += ConsumePatchFileEvent;
			fileSystemWatcher.Deleted += ConsumePatchFileEvent;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
			void ConsumePatchFileEvent(object s, FileSystemEventArgs e)
			{
				FileInfo fileInfo = null;
				switch (e.ChangeType)
				{
				case WatcherChangeTypes.Deleted:
					Debug.Log((object)"Function Deleted");
					FilePatching.RemoveFilePatches(fileName, patchFile);
					break;
				case WatcherChangeTypes.Changed:
					Debug.Log((object)"Function Changed");
					FilePatching.RemoveFilePatches(fileName, patchFile);
					fileInfo = new FileInfo(fullPatchFilename);
					break;
				}
				if (fileInfo != null && fileInfo.Exists)
				{
					FilePatching.ProcessPatchFile(fileInfo);
				}
				SyncedJsonFiles[fileName].AssignLocalValue(LoadJsonText(fileName));
			}
		}

		public static string LoadJsonText(string filename)
		{
			string assetPath = GetAssetPath(filename);
			if (string.IsNullOrEmpty(assetPath))
			{
				return null;
			}
			string text = File.ReadAllText(assetPath);
			string text2 = FilePatching.ProcessConfigFile(filename, text);
			if (OutputPatchedConfigFiles.Value && text != text2)
			{
				File.WriteAllText(Path.Combine(Paths.ConfigPath, "EpicLoot", filename.Replace(".json", "_patched.json")), text2);
			}
			return text2;
		}

		public static string GenerateAssetPathAtAssembly(string assetName)
		{
			return Path.Combine(Path.GetDirectoryName(typeof(EpicLootBase).Assembly.Location) ?? string.Empty, assetName);
		}

		public static string GetAssetPath(string assetName)
		{
			string text = Path.Combine(Paths.PluginPath, "EpicLoot", assetName);
			if (!File.Exists(text))
			{
				text = GenerateAssetPathAtAssembly(assetName);
				if (!File.Exists(text))
				{
					LogErrorForce("Could not find asset (" + assetName + ")");
					return null;
				}
			}
			return text;
		}

		public static bool CanBeMagicItem(ItemData item)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if (item != null && IsPlayerItem(item) && Nonstackable(item) && IsNotRestrictedItem(item))
			{
				return AllowedMagicItemTypes.Contains(item.m_shared.m_itemType);
			}
			return false;
		}

		public static Sprite GetMagicItemBgSprite()
		{
			if (!HasAuga)
			{
				return Assets.GenericItemBgSprite;
			}
			return Assets.AugaItemBgSprite;
		}

		public static Sprite GetEquippedSprite()
		{
			if (!HasAuga)
			{
				return Assets.EquippedSprite;
			}
			return Assets.AugaEquippedSprite;
		}

		public static Sprite GetSetItemSprite()
		{
			if (!HasAuga)
			{
				return Assets.GenericSetItemSprite;
			}
			return Assets.AugaSetItemSprite;
		}

		public static string GetMagicEffectPip(bool hasBeenAugmented)
		{
			if (!HasAuga)
			{
				if (!hasBeenAugmented)
				{
					return "◆";
				}
				return "◇";
			}
			if (!hasBeenAugmented)
			{
				return "♦";
			}
			return "♢";
		}

		private static bool IsNotRestrictedItem(ItemData item)
		{
			if ((Object)(object)item.m_dropPrefab != (Object)null && LootRoller.Config.RestrictedItems.Contains(((Object)item.m_dropPrefab).name))
			{
				return false;
			}
			return !LootRoller.Config.RestrictedItems.Contains(item.m_shared.m_name);
		}

		private static bool Nonstackable(ItemData item)
		{
			return item.m_shared.m_maxStackSize == 1;
		}

		private static bool IsPlayerItem(ItemData item)
		{
			return item.m_shared.m_icons.Length != 0;
		}

		public static string GetCharacterCleanName(Character character)
		{
			return ((Object)character).name.Replace("(Clone)", "").Trim();
		}

		public static void OnCharacterDeath(CharacterDrop characterDrop)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (CanCharacterDropLoot(characterDrop.m_character))
			{
				string characterCleanName = GetCharacterCleanName(characterDrop.m_character);
				int level = characterDrop.m_character.GetLevel();
				Vector3 dropPoint = characterDrop.m_character.GetCenterPoint() + ((Component)characterDrop).transform.TransformVector(characterDrop.m_spawnOffset);
				OnCharacterDeath(characterCleanName, level, dropPoint);
			}
		}

		public static bool CanCharacterDropLoot(Character character)
		{
			if ((Object)(object)character != (Object)null)
			{
				return !character.IsTamed();
			}
			return false;
		}

		public static void OnCharacterDeath(string characterName, int level, Vector3 dropPoint)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			List<LootTable> lootTable = LootRoller.GetLootTable(characterName);
			if (lootTable != null && lootTable.Count > 0)
			{
				List<GameObject> list = LootRoller.RollLootTableAndSpawnObjects(lootTable, level, characterName, dropPoint);
				Log($"Rolling on loot table: {characterName} (lvl {level}), spawned {list.Count} items at drop point({dropPoint}).");
				DropItems(list, dropPoint);
				{
					foreach (GameObject item in list)
					{
						ItemData itemData = item.GetComponent<ItemDrop>().m_itemData;
						MagicItem magicItem = itemData.GetMagicItem();
						if (magicItem != null)
						{
							Log(string.Format("  - {0} <{1}>: {2}", itemData.m_shared.m_name, item.transform.position, string.Join(", ", magicItem.Effects.Select((MagicItemEffect x) => x.EffectType.ToString()))));
						}
					}
					return;
				}
			}
			Log($"Could not find loot table for: {characterName} (lvl {level})");
		}

		public static void DropItems(List<GameObject> loot, Vector3 centerPos, float dropHemisphereRadius = 0.5f)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_0078: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: 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)
			foreach (GameObject item in loot)
			{
				Vector3 val = Random.insideUnitSphere * dropHemisphereRadius;
				val.y = Mathf.Abs(val.y);
				item.transform.position = centerPos + val;
				item.transform.rotation = Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f);
				Rigidbody component = item.GetComponent<Rigidbody>();
				if ((Object)(object)component != (Object)null)
				{
					Vector3 insideUnitSphere = Random.insideUnitSphere;
					if ((double)insideUnitSphere.y < 0.0)
					{
						insideUnitSphere.y = 0f - insideUnitSphere.y;
					}
					component.AddForce(insideUnitSphere * 5f, (ForceMode)2);
				}
			}
		}

		private void PrintInfo()
		{
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Invalid comparison between Unknown and I4
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Invalid comparison between Unknown and I4
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Invalid comparison between Unknown and I4
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Invalid comparison between Unknown and I4
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Invalid comparison between Unknown and I4
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Invalid comparison between Unknown and I4
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			if (!Directory.Exists("C:\\Users\\rknapp\\Documents\\GitHub\\ValheimMods\\EpicLoot"))
			{
				return;
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("# EpicLoot Data v0.9.37");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("*Author: RandyKnapp*");
			stringBuilder.AppendLine("*Source: [Github](https://github.com/RandyKnapp/ValheimMods/tree/main/EpicLoot)*");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("# Magic Effect Count Weights Per Rarity");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("Each time a **MagicItem** is rolled a number of **MagicItemEffects** are added based on its **Rarity**. The percent chance to roll each number of effects is found on the following table. These values are hardcoded.");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("The raw weight value is shown first, followed by the calculated percentage chance in parentheses.");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("|Rarity|1|2|3|4|5|6|");
			stringBuilder.AppendLine("|--|--|--|--|--|--|--|");
			stringBuilder.AppendLine(GetMagicEffectCountTableLine(ItemRarity.Magic));
			stringBuilder.AppendLine(GetMagicEffectCountTableLine(ItemRarity.Rare));
			stringBuilder.AppendLine(GetMagicEffectCountTableLine(ItemRarity.Epic));
			stringBuilder.AppendLine(GetMagicEffectCountTableLine(ItemRarity.Legendary));
			stringBuilder.AppendLine();
			List<ItemRarity> list = new List<ItemRarity>();
			foreach (ItemRarity value3 in Enum.GetValues(typeof(ItemRarity)))
			{
				list.Add(value3);
			}
			List<SkillType> list2 = new List<SkillType>();
			foreach (SkillType value4 in Enum.GetValues(typeof(SkillType)))
			{
				if ((int)value4 != 0 && (int)value4 != 13 && (int)value4 != 100 && (int)value4 != 101 && (int)value4 != 102 && (int)value4 != 103 && (int)value4 != 999)
				{
					list2.Add(value4);
				}
			}
			stringBuilder.AppendLine("# MagicItemEffect List");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("The following lists all the built-in **MagicItemEffects**. MagicItemEffects are defined in `magiceffects.json` and are parsed and added to `MagicItemEffectDefinitions` on Awake. EpicLoot uses an string for the types of magic effects. You can add your own new types using your own identifiers.");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("Listen to the event `MagicItemEffectDefinitions.OnSetupMagicItemEffectDefinitions` (which gets called in `EpicLoot.Awake`) to add your own using instances of MagicItemEffectDefinition.");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("  * **Display Text:** This text appears in the tooltip for the magic item, with {0:?} replaced with the rolled value for the effect, formatted using the shown C# string format.");
			stringBuilder.AppendLine("  * **Requirements:** A set of requirements.");
			stringBuilder.AppendLine("    * **Flags:** A set of predefined flags to check certain weapon properties. The list of flags is: `NoRoll, ExclusiveSelf, ItemHasPhysicalDamage, ItemHasElementalDamage, ItemUsesDurability, ItemHasNegativeMovementSpeedModifier, ItemHasBlockPower, ItemHasNoParryPower, ItemHasParryPower, ItemHasArmor, ItemHasBackstabBonus, ItemUsesStaminaOnAttack`");
			stringBuilder.AppendLine("    * **ExclusiveEffectTypes:** This effect may not be rolled on an item that has already rolled on of these effects");
			stringBuilder.AppendLine("    * **AllowedItemTypes:** This effect may only be rolled on items of a the types in this list. When this list is empty, this is usually done because this is a special effect type added programmatically  or currently not allowed to roll. Options are: `" + string.Join(", ", AllowedMagicItemTypes) + "`");
			stringBuilder.AppendLine("    * **ExcludedItemTypes:** This effect may only be rolled on items that are not one of the types on this list.");
			stringBuilder.AppendLine("    * **AllowedRarities:** This effect may only be rolled on an item of one of these rarities. Options are: `" + string.Join(", ", list) + "`");
			stringBuilder.AppendLine("    * **ExcludedRarities:** This effect may only be rolled on an item that is not of one of these rarities.");
			stringBuilder.AppendLine("    * **AllowedSkillTypes:** This effect may only be rolled on an item that uses one of these skill types. Options are: `" + string.Join(", ", list2) + "`");
			stringBuilder.AppendLine("    * **ExcludedSkillTypes:** This effect may only be rolled on an item that does not use one of these skill types.");
			stringBuilder.AppendLine("    * **AllowedItemNames:** This effect may only be rolled on an item with one of these names. Use the unlocalized shared name, i.e.: `$item_sword_iron`");
			stringBuilder.AppendLine("    * **ExcludedItemNames:** This effect may only be rolled on an item that does not have one of these names.");
			stringBuilder.AppendLine("    * **CustomFlags:** A set of any arbitrary strings for future use");
			stringBuilder.AppendLine("  * **Value Per Rarity:** This effect may only be rolled on items of a rarity included in this table. The value is rolled using a linear distribution between Min and Max and divisible by the Increment.");
			stringBuilder.AppendLine();
			foreach (KeyValuePair<string, MagicItemEffectDefinition> allDefinition in MagicItemEffectDefinitions.AllDefinitions)
			{
				MagicItemEffectDefinition value = allDefinition.Value;
				stringBuilder.AppendLine("## " + value.Type);
				stringBuilder.AppendLine();
				stringBuilder.AppendLine("> **Display Text:** " + Localization.instance.Localize(value.DisplayText));
				stringBuilder.AppendLine("> ");
				if (value.Prefixes.Count > 0)
				{
					stringBuilder.AppendLine("> **Prefixes:** " + Localization.instance.Localize(string.Join(", ", value.Prefixes)));
				}
				if (value.Suffixes.Count > 0)
				{
					stringBuilder.AppendLine("> **Suffixes:** " + Localization.instance.Localize(string.Join(", ", value.Suffixes)));
				}
				if (value.Prefixes.Count > 0 || value.Suffixes.Count > 0)
				{
					stringBuilder.AppendLine("> ");
				}
				List<string> allowedItemTypes = value.GetAllowedItemTypes();
				stringBuilder.AppendLine("> **Allowed Item Types:** " + ((allowedItemTypes.Count == 0) ? "*None*" : string.Join(", ", allowedItemTypes)));
				stringBuilder.AppendLine("> ");
				stringBuilder.AppendLine("> **Requirements:**");
				stringBuilder.Append(value.Requirements);
				if (value.HasRarityValues())
				{
					stringBuilder.AppendLine("> ");
					stringBuilder.AppendLine("> **Value Per Rarity:**");
					stringBuilder.AppendLine("> ");
					stringBuilder.AppendLine("> |Rarity|Min|Max|Increment|");
					stringBuilder.AppendLine("> |--|--|--|--|");
					if (value.ValuesPerRarity.Magic != null)
					{
						MagicItemEffectDefinition.ValueDef magic = value.ValuesPerRarity.Magic;
						stringBuilder.AppendLine($"> |Magic|{magic.MinValue}|{magic.MaxValue}|{magic.Increment}|");
					}
					if (value.ValuesPerRarity.Rare != null)
					{
						MagicItemEffectDefinition.ValueDef rare = value.ValuesPerRarity.Rare;
						stringBuilder.AppendLine($"> |Rare|{rare.MinValue}|{rare.MaxValue}|{rare.Increment}|");
					}
					if (value.ValuesPerRarity.Epic != null)
					{
						MagicItemEffectDefinition.ValueDef epic = value.ValuesPerRarity.Epic;
						stringBuilder.AppendLine($"> |Epic|{epic.MinValue}|{epic.MaxValue}|{epic.Increment}|");
					}
					if (value.ValuesPerRarity.Legendary != null)
					{
						MagicItemEffectDefinition.ValueDef legendary = value.ValuesPerRarity.Legendary;
						stringBuilder.AppendLine($"> |Legendary|{legendary.MinValue}|{legendary.MaxValue}|{legendary.Increment}|");
					}
				}
				if (!string.IsNullOrEmpty(value.Comment))
				{
					stringBuilder.AppendLine("> ");
					stringBuilder.AppendLine("> ***Notes:*** *" + value.Comment + "*");
				}
				stringBuilder.AppendLine();
			}
			stringBuilder.AppendLine("# Item Sets");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("Sets of loot drop data that can be referenced in the loot tables");
			foreach (KeyValuePair<string, LootItemSet> itemSet in LootRoller.ItemSets)
			{
				LootItemSet value2 = itemSet.Value;
				stringBuilder.AppendLine("## " + itemSet.Key);
				stringBuilder.AppendLine();
				WriteLootList(stringBuilder, 0, value2.Loot);
				stringBuilder.AppendLine();
			}
			stringBuilder.AppendLine("# Loot Tables");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("A list of every built-in loot table from the mod. The name of the loot table is the object name followed by a number signifying the level of the object.");
			foreach (KeyValuePair<string, List<LootTable>> lootTable in LootRoller.LootTables)
			{
				foreach (LootTable item in lootTable.Value)
				{
					stringBuilder.AppendLine("## " + lootTable.Key);
					stringBuilder.AppendLine();
					WriteLootTableDrops(stringBuilder, item);
					WriteLootTableItems(stringBuilder, item);
					stringBuilder.AppendLine();
				}
			}
			File.WriteAllText(Path.Combine("C:\\Users\\rknapp\\Documents\\GitHub\\ValheimMods\\EpicLoot", "info.md"), stringBuilder.ToString());
		}

		private static void WriteLootTableDrops(StringBuilder t, LootTable lootTable)
		{
			int num = ((lootTable.LeveledLoot != null && lootTable.LeveledLoot.Count > 0) ? lootTable.LeveledLoot.Max((LeveledLootDef x) => x.Level) : 0);
			int num2 = Mathf.Max(3, num);
			for (int i = 0; i < num2; i++)
			{
				int num3 = i + 1;
				List<KeyValuePair<int, float>> dropsForLevel = LootRoller.GetDropsForLevel(lootTable, num3, useNextHighestIfNotPresent: false);
				if (dropsForLevel == null || dropsForLevel.Count == 0)
				{
					continue;
				}
				float num4 = dropsForLevel.Sum((KeyValuePair<int, float> x) => x.Value);
				if (num4 > 0f)
				{
					t.AppendLine($"> | Drops (lvl {num3}) | Weight (Chance) |");
					t.AppendLine("> | -- | -- |");
					foreach (KeyValuePair<int, float> item in dropsForLevel)
					{
						int key = item.Key;
						float value = item.Value;
						float num5 = value / num4 * 100f;
						t.AppendLine($"> | {key} | {value} ({num5:0.#}%) |");
					}
				}
				t.AppendLine();
			}
		}

		private static void WriteLootTableItems(StringBuilder t, LootTable lootTable)
		{
			int num = ((lootTable.LeveledLoot != null && lootTable.LeveledLoot.Count > 0) ? lootTable.LeveledLoot.Max((LeveledLootDef x) => x.Level) : 0);
			int num2 = Mathf.Max(3, num);
			for (int i = 0; i < num2; i++)
			{
				int level = i + 1;
				LootDrop[] lootForLevel = LootRoller.GetLootForLevel(lootTable, level, useNextHighestIfNotPresent: false);
				if (!ArrayUtils.IsNullOrEmpty(lootForLevel))
				{
					WriteLootList(t, level, lootForLevel);
				}
			}
		}

		private static void WriteLootList(StringBuilder t, int level, LootDrop[] lootList)
		{
			string text = ((level > 0) ? $" (lvl {level})" : "");
			t.AppendLine("> | Items" + text + " | Weight (Chance) | Magic | Rare | Epic | Legendary |");
			t.AppendLine("> | -- | -- | -- | -- | -- | -- |");
			float num = lootList.Sum((LootDrop x) => x.Weight);
			foreach (LootDrop lootDrop in lootList)
			{
				float num2 = lootDrop.Weight / num * 100f;
				if (lootDrop.Rarity == null || lootDrop.Rarity.Length == 0)
				{
					t.AppendLine($"> | {lootDrop.Item} | {lootDrop.Weight} ({num2:0.#}%) | 1 (100%) | 0 (0%) | 0 (0%) | 0 (0%) |");
					continue;
				}
				float num3 = lootDrop.Rarity.Sum();
				float[] array = new float[4]
				{
					lootDrop.Rarity[0] / num3 * 100f,
					lootDrop.Rarity[1] / num3 * 100f,
					lootDrop.Rarity[2] / num3 * 100f,
					lootDrop.Rarity[3] / num3 * 100f
				};
				t.AppendLine($"> | {lootDrop.Item} | {lootDrop.Weight} ({num2:0.#}%) " + $"| {lootDrop.Rarity[0]} ({array[0]:0.#}%) " + $"| {lootDrop.Rarity[1]} ({array[1]:0.#}%) " + $"| {lootDrop.Rarity[2]:0.#} ({array[2]:0.#}%) " + $"| {lootDrop.Rarity[3]} ({array[3]:0.#}%) |");
			}
			t.AppendLine();
		}

		private static string GetMagicEffectCountTableLine(ItemRarity rarity)
		{
			List<KeyValuePair<int, float>> effectCountsPerRarity = LootRoller.GetEffectCountsPerRarity(rarity, useEnchantingUpgrades: false);
			float num = effectCountsPerRarity.Sum((KeyValuePair<int, float> x) => x.Value);
			string text = $"|{rarity}|";
			for (int j = 1; j <= 6; j++)
			{
				string text2 = " ";
				int i1 = j;
				if (effectCountsPerRarity.TryFind((KeyValuePair<int, float> x) => x.Key == i1, out var result))
				{
					float value = result.Value;
					float num2 = value / num * 100f;
					text2 = $"{value} ({num2:0.#}%)";
				}
				text = text + text2 + "|";
			}
			return text;
		}

		public static string GetSetItemColor()
		{
			return _setItemColor.Value;
		}

		public static string GetRarityDisplayName(ItemRarity rarity)
		{
			return rarity switch
			{
				ItemRarity.Magic => "$mod_epicloot_magic", 
				ItemRarity.Rare => "$mod_epicloot_rare", 
				ItemRarity.Epic => "$mod_epicloot_epic", 
				ItemRarity.Legendary => "$mod_epicloot_legendary", 
				ItemRarity.Mythic => "$mod_epicloot_mythic", 
				_ => "<non magic>", 
			};
		}

		public static string GetRarityColor(ItemRarity rarity)
		{
			return rarity switch
			{
				ItemRarity.Magic => GetColor(_magicRarityColor.Value), 
				ItemRarity.Rare => GetColor(_rareRarityColor.Value), 
				ItemRarity.Epic => GetColor(_epicRarityColor.Value), 
				ItemRarity.Legendary => GetColor(_legendaryRarityColor.Value), 
				ItemRarity.Mythic => GetColor("Orange"), 
				_ => "#FFFFFF", 
			};
		}

		public static Color GetRarityColorARGB(ItemRarity rarity)
		{
			//IL_0015: 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)
			Color result = default(Color);
			if (!ColorUtility.TryParseHtmlString(GetRarityColor(rarity), ref result))
			{
				return Color.white;
			}
			return result;
		}

		private static string GetColor(string configValue)
		{
			if (configValue.StartsWith("#"))
			{
				return configValue;
			}
			if (MagicItemColors.TryGetValue(configValue, out var value))
			{
				return value;
			}
			return "#000000";
		}

		public static int GetRarityIconIndex(ItemRarity rarity)
		{
			return rarity switch
			{
				ItemRarity.Magic => Mathf.Clamp(_magicMaterialIconColor.Value, 0, 9), 
				ItemRarity.Rare => Mathf.Clamp(_rareMaterialIconColor.Value, 0, 9), 
				ItemRarity.Epic => Mathf.Clamp(_epicMaterialIconColor.Value, 0, 9), 
				ItemRarity.Legendary => Mathf.Clamp(_legendaryMaterialIconColor.Value, 0, 9), 
				ItemRarity.Mythic => 1, 
				_ => throw new ArgumentOutOfRangeException("rarity", rarity, null), 
			};
		}

		public static AudioClip GetMagicItemDropSFX(ItemRarity rarity)
		{
			return Assets.MagicItemDropSFX[(int)rarity];
		}

		public static GatedItemTypeMode GetGatedItemTypeMode()
		{
			return _gatedItemTypeModeConfig.Value;
		}

		public static BossDropMode GetBossTrophyDropMode()
		{
			return _bossTrophyDropMode.Value;
		}

		public static float GetBossTrophyDropPlayerRange()
		{
			return _bossTrophyDropPlayerRange.Value;
		}

		public static float GetBossCryptKeyPlayerRange()
		{
			return _bossCryptKeyDropPlayerRange.Value;
		}

		public static BossDropMode GetBossCryptKeyDropMode()
		{
			return _bossCryptKeyDropMode.Value;
		}

		public static BossDropMode GetBossWishboneDropMode()
		{
			return _bossWishboneDropMode.Value;
		}

		public static float GetBossWishboneDropPlayerRange()
		{
			return _bossWishboneDropPlayerRange.Value;
		}

		public static int GetAndvaranautRange()
		{
			return _andvaranautRange.Value;
		}

		public static bool IsAdventureModeEnabled()
		{
			return _adventureModeEnabled.Value;
		}

		private static void GenerateTranslations()
		{
			string text = LoadJsonText("magiceffects.json");
			MagicItemEffectsList? magicItemEffectsList = JsonConvert.DeserializeObject<MagicItemEffectsList>(text);
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (MagicItemEffectDefinition magicItemEffect in magicItemEffectsList.MagicItemEffects)
			{
				if (string.IsNullOrEmpty(magicItemEffect.Description))
				{
					magicItemEffect.Description = magicItemEffect.DisplayText.Replace("display", "desc");
					text = text.Replace("\"DisplayText\" : \"" + magicItemEffect.DisplayText + "\"", "\"DisplayText\" : \"" + magicItemEffect.DisplayText + "\",\n      \"Description\" : \"" + magicItemEffect.Description + "\"");
					dictionary.Add(magicItemEffect.Description, "");
				}
			}
			File.WriteAllText(GenerateAssetPathAtAssembly("magiceffects_translated.json"), text);
			string path = GenerateAssetPathAtAssembly("new_translations.json");
			string contents = "{\n" + string.Join("\n", dictionary.Select((KeyValuePair<string, string> x) => "  \"" + x.Key + "\": \"" + x.Value + "\",")) + "\n}";
			File.WriteAllText(path, contents);
		}

		private static string Clean(string name)
		{
			return name.Replace("'", "").Replace(",", "").Trim()
				.Replace(" ", "_")
				.ToLowerInvariant();
		}

		private static void ReplaceValueList(List<string> values, string field, string label, MagicItemEffectDefinition effectDef, Dictionary<string, string> translations, ref string magicEffectsJson)
		{
			List<string> list = new List<string>();
			for (int i = 0; i < values.Count; i++)
			{
				string text = values[i];
				string text2;
				if (text.StartsWith("$"))
				{
					text2 = text;
				}
				else
				{
					text2 = GetId(effectDef, $"{field}{i + 1}");
					AddTranslation(translations, text2, text);
				}
				list.Add(text2);
			}
			if (list.Count > 0)
			{
				string original = "\"" + label + "\": [ " + string.Join(", ", values.Select((string x) => "\"" + x + "\"")) + " ]";
				string locId = "\"" + label + "\": [\n        " + string.Join(",\n        ", list.Select((string x) => (!x.StartsWith("$")) ? ("\"$" + x + "\"") : ("\"" + x + "\""))) + "\n      ]";
				magicEffectsJson = ReplaceTranslation(magicEffectsJson, original, locId);
			}
		}

		private static string GetId(MagicItemEffectDefinition effectDef, string field)
		{
			return "mod_epicloot_me_" + effectDef.Type.ToLowerInvariant() + "_" + field.ToLowerInvariant();
		}

		private static void AddTranslation(Dictionary<string, string> translations, string key, string value)
		{
			translations.Add(key, value);
		}

		private static string ReplaceTranslation(string jsonFile, string original, string locId)
		{
			return jsonFile.Replace(original, locId);
		}

		private static string SetupTranslation(MagicItemEffectDefinition effectDef, string value, string field, string replaceFormat, Dictionary<string, string> translations, string jsonFile)
		{
			if (string.IsNullOrEmpty(value) || value.StartsWith("$"))
			{
				return jsonFile;
			}
			string id = GetId(effectDef, field);
			AddTranslation(translations, id, value);
			return ReplaceTranslation(jsonFile, string.Format(replaceFormat, value), string.Format(replaceFormat, "$" + id));
		}

		public static float GetWorldLuckFactor()
		{
			return _instance._worldLuckFactor;
		}

		public static void SetWorldLuckFactor(float luckFactor)
		{
			_instance._worldLuckFactor = luckFactor;
		}
	}
	public static class EpicLootAuga
	{
		public static Button ReplaceButton(Button button, bool icon = false, bool keepListeners = false)
		{
			return ReplaceButtonInternal(API.MediumButton_Create(((Component)button).transform.parent, ((Object)button).name, string.Empty), button, icon, keepListeners);
		}

		public static Button ReplaceButtonFancy(Button button, bool icon = false, bool keepListeners = false)
		{
			return ReplaceButtonInternal(API.FancyButton_Create(((Component)button).transform.parent, ((Object)button).name, string.Empty), button, icon, keepListeners);
		}

		private static Button ReplaceButtonInternal(Button newButton, Button button, bool icon, bool keepListeners)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_0077: 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_0083: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: 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_00c7: Expected O, but got Unknown
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			if (icon)
			{
				Object.Destroy((Object)(object)((Component)((Component)newButton).GetComponentInChildren<TMP_Text>()).gameObject);
				((Object)Object.Instantiate<Transform>(((Component)button).transform.Find("Icon"), ((Component)newButton).transform)).name = "Icon";
			}
			else
			{
				string text = ((Component)button).GetComponentInChildren<Text>().text;
				((Component)newButton).GetComponentInChildren<TMP_Text>().text = text;
			}
			RectTransform val = (RectTransform)((Component)button).transform;
			RectTransform val2 = (RectTransform)((Component)newButton).transform;
			val2.anchorMin = val.anchorMin;
			val2.anchorMax = val.anchorMax;
			val2.pivot = val.pivot;
			val2.anchoredPosition = val.anchoredPosition;
			Rect rect = val.rect;
			val2.SetSizeWithCurrentAnchors((Axis)0, ((Rect)(ref rect)).width);
			if (keepListeners)
			{
				newButton.onClick = button.onClick;
				button.onClick = new ButtonClickedEvent();
			}
			UIGamePad component = ((Component)button).GetComponent<UIGamePad>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.m_hint != (Object)null)
			{
				component.m_hint.transform.SetParent(((Component)newButton).transform);
				UIGamePad obj = ((Component)newButton).gameObject.AddComponent<UIGamePad>();
				obj.m_keyCode = component.m_keyCode;
				obj.m_zinputKey = component.m_zinputKey;
				obj.m_hint = component.m_hint;
				obj.m_blockingElements = component.m_blockingElements.ToList();
			}
			Object.DestroyImmediate((Object)(object)((Component)button).gameObject);
			return newButton;
		}

		public static void MakeSimpleTooltip(GameObject obj)
		{
			API.Tooltip_MakeSimpleTooltip(obj);
		}

		public static void ReplaceBackground(GameObject obj, bool withCornerDecoration)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			Object.Destroy((Object)(object)obj.GetComponent<Image>());
			RectTransform val = (RectTransform)API.Panel_Create(obj.transform, Vector2.one, "AugaBackground", withCornerDecoration).transform;
			((Transform)val).SetSiblingIndex(0);
			val.anchorMin = Vector2.zero;
			val.anchorMax = Vector2.one;
			val.pivot = new Vector2(0.5f, 0.5f);
			val.sizeDelta = new Vector2(40f, 40f);
		}

		public static void FixItemBG(GameObject obj)
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			Transform val = obj.transform.Find("MagicBG");
			if ((Object)(object)val != (Object)null)
			{
				Image component = ((Component)val).GetComponent<Image>();
				if ((Object)(object)component != (Object)null)
				{
					component.sprite = EpicLootBase.GetMagicItemBgSprite();
				}
			}
			bool flag = false;
			Transform val2 = obj.transform.Find("ItemBG");
			Image val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<Image>() : null);
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = obj.GetComponent<Image>();
			}
			if ((Object)(object)val3 != (Object)null)
			{
				val3.sprite = API.GetItemBackgroundSprite();
				((Graphic)val3).color = new Color(0f, 0f, 0f, 0.5f);
				flag = true;
			}
			if (!flag)
			{
				Transform val4 = obj.transform.Find("Icon");
				if ((Object)(object)val4 != (Object)null)
				{
					Transform obj2 = Object.Instantiate<Transform>(val4, val4.parent);
					obj2.SetSiblingIndex(2);
					Image component2 = ((Component)obj2).GetComponent<Image>();
					component2.sprite = API.GetItemBackgroundSprite();
					((Graphic)component2).color = new Color(0f, 0f, 0f, 0.5f);
				}
			}
		}

		public static void FixListElementColors(GameObject obj)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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)
			Transform val = obj.transform.Find("Selected");
			if ((Object)(object)val != (Object)null)
			{
				Image component = ((Component)val).GetComponent<Image>();
				if ((Object)(object)component != (Object)null)
				{
					Color color = default(Color);
					ColorUtility.TryParseHtmlString(API.Blue, ref color);
					((Graphic)component).color = color;
				}
			}
			Transform val2 = obj.transform.Find("Background");
			if ((Object)(object)val2 != (Object)null)
			{
				Image component2 = ((Component)val2).GetComponent<Image>();
				if ((Object)(object)component2 != (Object)null)
				{
					((Graphic)component2).color = new Color(0f, 0f, 0f, 0.5f);
				}
			}
			Button component3 = obj.GetComponent<Button>();
			if ((Object)(object)component3 != (Object)null)
			{
				((Selectable)component3).colors = ColorBlock.defaultColorBlock;
			}
		}

		public static void FixFonts(GameObject obj)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			TMP_Text[] componentsInChildren = obj.GetComponentsInChildren<TMP_Text>(true);
			Color color = default(Color);
			Color color2 = default(Color);
			foreach (TMP_Text val in componentsInChildren)
			{
				if (((Object)val.font).name == "Norsebold")
				{
					ColorUtility.TryParseHtmlString(API.Brown1, ref color);
					((Graphic)val).color = color;
					val.text = Localization.instance.Localize(val.text).ToUpperInvariant();
				}
				if (((Object)val).name == "Count" || ((Object)val).name == "RewardLabel" || ((Object)val).name.EndsWith("Count"))
				{
					ColorUtility.TryParseHtmlString(API.BrightGold, ref color2);
					((Graphic)val).color = color2;
				}
				val.text = val.text.Replace("<color=yellow>", "<color=" + API.BrightGold + ">");
			}
		}

		public static Button ReplaceVerticalLargeTab(Button button)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due