Decompiled source of ItemTips v2.2.0

ItemTipsMod.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ETGGUI;
using Gunfiguration;
using Gungeon;
using MonoMod.RuntimeDetour;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using SGUI;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("ItemTipsMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+3c88a2fb9be593e23ea5a411f65742f18f1e0f11")]
[assembly: AssemblyProduct("ItemTipsMod")]
[assembly: AssemblyTitle("ItemTipsMod")]
[assembly: InternalsVisibleTo("ModTests")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ItemTipsMod;

public class AdvancedSynergyCache
{
	public AdvancedSynergyEntry[] SourceEntries;

	public Dictionary<string, SynergyGroup> SynergyKeyIndex;

	public Dictionary<int, List<SynergyGroup>> ItemIndex;

	public AdvancedSynergyCache()
		: this(ArrayHelper<AdvancedSynergyEntry>.Empty)
	{
	}

	public AdvancedSynergyCache(AdvancedSynergyEntry[] sourceEntries)
	{
		SourceEntries = sourceEntries;
		Build();
	}

	private void Build()
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Invalid comparison between Unknown and I4
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Invalid comparison between Unknown and I4
		SynergyKeyIndex = new Dictionary<string, SynergyGroup>();
		ItemIndex = new Dictionary<int, List<SynergyGroup>>();
		AdvancedSynergyEntry[] sourceEntries = SourceEntries;
		foreach (AdvancedSynergyEntry val in sourceEntries)
		{
			if (!string.IsNullOrEmpty(val.NameKey) && (int)val.ActivationStatus != 1 && (int)val.ActivationStatus != 2)
			{
				if (SynergyKeyIndex.TryGetValue(val.NameKey, out var value))
				{
					value.Entries.Add(val);
					continue;
				}
				SynergyKeyIndex[val.NameKey] = new SynergyGroup(val.NameKey)
				{
					Entries = { val }
				};
			}
		}
		foreach (KeyValuePair<string, SynergyGroup> item in SynergyKeyIndex)
		{
			_ = item.Key;
			SynergyGroup value2 = item.Value;
			foreach (AdvancedSynergyEntry entry in value2.Entries)
			{
				AddSynergyEntries(entry.MandatoryGunIDs, value2);
				AddSynergyEntries(entry.MandatoryItemIDs, value2);
				AddSynergyEntries(entry.OptionalGunIDs, value2);
				AddSynergyEntries(entry.OptionalItemIDs, value2);
			}
		}
	}

	private void AddSynergyEntries(List<int> ids, SynergyGroup group)
	{
		if (ids == null)
		{
			return;
		}
		foreach (int id in ids)
		{
			if (ItemIndex.TryGetValue(id, out var value))
			{
				if (!value.Contains(group))
				{
					value.Add(group);
				}
			}
			else
			{
				ItemIndex[id] = new List<SynergyGroup> { group };
			}
		}
	}
}
public class SynergyGroup
{
	public readonly string NameKey;

	public List<AdvancedSynergyEntry> Entries = new List<AdvancedSynergyEntry>();

	public SynergyGroup(string nameKey)
	{
		NameKey = nameKey;
	}

	public bool SynergyIsAvailable(PlayerController p1, PlayerController p2, int additionalID = -1)
	{
		foreach (AdvancedSynergyEntry entry in Entries)
		{
			if (entry.SynergyIsAvailable(p1, p2, additionalID))
			{
				return true;
			}
		}
		return false;
	}
}
public sealed class AmmonomiconEntryCache
{
	private readonly PickupAndSynergyDataCache _dataCache;

	private readonly AdvancedSynergyCache _synergyCache;

	private GungeonSupportedLanguages _currentLanguage;

	private Dictionary<int, string> _entryCache;

	public AmmonomiconEntryCache(AdvancedSynergyCache synergyCache, PickupAndSynergyDataCache dataCache)
	{
		_synergyCache = synergyCache;
		_dataCache = dataCache;
		_entryCache = new Dictionary<int, string>();
	}

	public GungeonSupportedLanguages GetCacheLanguage()
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return _currentLanguage;
	}

	public void SetCacheLanguage(GungeonSupportedLanguages value)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		if (value != _currentLanguage)
		{
			_entryCache = new Dictionary<int, string>();
			_currentLanguage = value;
		}
	}

	public string GetEntry(int pickupId, string origEntry)
	{
		if (pickupId < 0)
		{
			return origEntry;
		}
		if (_entryCache.TryGetValue(pickupId, out var value))
		{
			return value;
		}
		if (!_dataCache.Pickups.TryGetValue(pickupId, out var value2))
		{
			value2 = null;
		}
		PickupObject byId = PickupObjectDatabase.GetById(pickupId);
		string text = GenerateAmmonomiconText(byId, value2);
		string text2 = (origEntry + "\n" + text).Trim();
		_entryCache[pickupId] = text2;
		return text2;
	}

	private string GenerateAmmonomiconText(PickupObject pickup, ItemData item)
	{
		StringBuilder builder = new StringBuilder();
		builder.AppendLine("----------");
		TipBuilder.AppendQualityDescriptor(pickup, delegate(string line)
		{
			builder.AppendLine(line);
		});
		TipBuilder.AppendActiveCooldownType(pickup, delegate(string line)
		{
			builder.AppendLine(line);
		});
		if (item != null)
		{
			builder.AppendLine(item.Notes);
		}
		TipBuilder.AppendModifiers(pickup, delegate(StatType stat, string line)
		{
			builder.AppendLine(line);
		});
		HashSet<string> hashSet = new HashSet<string>();
		if (_synergyCache.ItemIndex.TryGetValue(pickup.PickupObjectId, out var value) && value.Count > 0)
		{
			builder.AppendLine("Synergies:");
			foreach (SynergyGroup item2 in value)
			{
				string synergyString = StringTableManager.GetSynergyString(item2.NameKey, -1);
				if (hashSet.Add(synergyString))
				{
					string text = (item2.SynergyIsAvailable(GameManager.Instance.PrimaryPlayer, GameManager.Instance.SecondaryPlayer) ? "*" : "");
					if (_dataCache.Synergies.TryGetValue(item2.NameKey, out var value2))
					{
						builder.AppendLine(" - " + text + synergyString + text + ": " + value2.Effect);
					}
					else
					{
						builder.AppendLine(" - " + text + synergyString + text);
					}
				}
			}
		}
		if (item != null && item.Synergies.Length != 0)
		{
			if (hashSet.Count == 0)
			{
				builder.AppendLine("Synergies:");
			}
			SynergyData[] synergies = item.Synergies;
			foreach (SynergyData synergyData in synergies)
			{
				string localizedSynergyName = synergyData.GetLocalizedSynergyName();
				if (hashSet.Add(localizedSynergyName))
				{
					string effect = synergyData.Effect;
					string text2 = (synergyData.InternalWouldGetSynergy() ? "*" : "");
					if (!string.IsNullOrEmpty(effect))
					{
						builder.AppendLine(" - " + text2 + localizedSynergyName + text2 + ": " + effect);
					}
					else
					{
						builder.AppendLine(" - " + text2 + localizedSynergyName + text2);
					}
				}
			}
		}
		return builder.ToString();
	}
}
internal static class ArrayHelper<T>
{
	public static T[] Empty { get; } = new T[0];

}
internal class CooldownLabelBehavior : MonoBehaviour
{
	public static CooldownLabelBehavior Instance;

	public PlayerCooldownLabelCollection labelCollection;

	public bool forceUpdate;

	public bool forceInitialize;

	public void UpdateLabelPostion()
	{
		PlayerCooldownLabelData[] cooldownLabelData = labelCollection.cooldownLabelData;
		for (int i = 0; i < cooldownLabelData.Length; i++)
		{
			cooldownLabelData[i].UpdateLabelPostion();
		}
	}

	public void SetVisible(bool visible)
	{
		labelCollection.ForEach(delegate(PlayerCooldownLabelData c)
		{
			((dfControl)c.cooldownLabel).IsVisible = visible;
		});
	}

	private void Start()
	{
		try
		{
			labelCollection = new PlayerCooldownLabelCollection();
			GameManager.Instance.OnNewLevelFullyLoaded += OnNewLevelFullyLoaded;
			Instance = this;
		}
		catch (Exception arg)
		{
			StaticLogger.LogDebug("Error in CooldownLabelBehavior.Start: {0}", arg);
		}
	}

	private void OnNewLevelFullyLoaded()
	{
		try
		{
			labelCollection.Clear();
			forceInitialize = true;
			forceUpdate = true;
		}
		catch (Exception arg)
		{
			StaticLogger.LogDebug("Error in CooldownLabelBehavior.OnNewLevelFullyLoaded: {0}", arg);
		}
	}

	private void Update()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Invalid comparison between Unknown and I4
		try
		{
			if ((int)GameManager.Instance.CurrentLevelOverrideState == 1)
			{
				return;
			}
			if (GameManager.Instance.IsLoadingLevel)
			{
				forceUpdate = true;
				forceInitialize = true;
				return;
			}
			if (!GameUIRoot.Instance.IsCoreUIVisible())
			{
				forceUpdate = true;
				return;
			}
			if (forceInitialize)
			{
				labelCollection.Initialize(GameManager.Instance.AllPlayers.Length);
				forceInitialize = false;
			}
			for (int i = 0; i < GameManager.Instance.AllPlayers.Length; i++)
			{
				try
				{
					PlayerController player = GameManager.Instance.AllPlayers[i];
					PlayerCooldownLabelData playerCooldownLabelData = labelCollection[i];
					if (playerCooldownLabelData.UpdateBoundState(player) | forceUpdate)
					{
						forceUpdate = false;
						playerCooldownLabelData.UpdateLabelState();
					}
				}
				catch (Exception ex)
				{
					StaticLogger.LogDebug("Error updating cooldown label for player {0}: {1}", i, ex);
				}
			}
		}
		catch (Exception arg)
		{
			StaticLogger.LogDebug("Error in Cooldown behavior Update: {0}", arg);
		}
	}
}
internal class PlayerCooldownLabelCollection
{
	private static Func<GameUIRoot, int, GameUIItemController> GetPlayerItemController = GetPlayerItemControllerDelegate();

	public PlayerCooldownLabelData[] cooldownLabelData;

	public PlayerCooldownLabelData this[int index] => cooldownLabelData[index];

	public void ForEach(Action<PlayerCooldownLabelData> action)
	{
		if (cooldownLabelData != null)
		{
			PlayerCooldownLabelData[] array = cooldownLabelData;
			foreach (PlayerCooldownLabelData obj in array)
			{
				action(obj);
			}
		}
	}

	public void Initialize(int playerCount)
	{
		StaticLogger.LogDebug("Initializing PlayerCooldownLabelCollection, playerCount: {0}", playerCount);
		cooldownLabelData = new PlayerCooldownLabelData[playerCount];
		for (int i = 0; i < playerCount; i++)
		{
			PlayerCooldownLabelData playerCooldownLabelData = new PlayerCooldownLabelData
			{
				itemController = GetPlayerItemController?.Invoke(GameUIRoot.Instance, i)
			};
			dfLabel val = ((dfControl)((Component)playerCooldownLabelData.itemController).GetComponent<dfPanel>()).AddControl<dfLabel>();
			val.TextScale = 2f;
			val.AutoSize = true;
			((dfControl)val).IsVisible = false;
			playerCooldownLabelData.cooldownLabel = val;
			if (playerCooldownLabelData.itemController.IsRightAligned)
			{
				playerCooldownLabelData.BaseRelativeX = 525;
				playerCooldownLabelData.BaseRelativeX = 510;
			}
			else
			{
				playerCooldownLabelData.BaseRelativeX = 150;
				playerCooldownLabelData.BaseRelativeY = 510;
			}
			playerCooldownLabelData.UpdateLabelPostion();
			cooldownLabelData[i] = playerCooldownLabelData;
		}
	}

	public void Clear()
	{
		if (cooldownLabelData != null)
		{
			PlayerCooldownLabelData[] array = cooldownLabelData;
			for (int i = 0; i < array.Length; i++)
			{
				array[i].Destroy();
			}
			cooldownLabelData = null;
		}
	}

	private static Func<GameUIRoot, int, GameUIItemController> GetPlayerItemControllerDelegate()
	{
		MethodInfo method = typeof(GameUIRoot).GetMethod("GetItemControllerForPlayerID", BindingFlags.Instance | BindingFlags.NonPublic);
		if ((object)method != null)
		{
			Delegate @delegate = Delegate.CreateDelegate(typeof(Func<GameUIRoot, int, GameUIItemController>), method);
			Func<GameUIRoot, int, GameUIItemController> f = (Func<GameUIRoot, int, GameUIItemController>)@delegate;
			return (GameUIRoot r, int i) => (r?.itemControllers == null) ? null : f(r, i);
		}
		StaticLogger.LogDebug("Could not find GetItemControllerForPlayerID");
		return (GameUIRoot r, int i) => null;
	}
}
internal class PlayerCooldownLabelData
{
	public GameUIItemController itemController;

	public dfLabel cooldownLabel;

	public PlayerItem lastItem;

	public bool isGhost;

	public int BaseRelativeX;

	public int BaseRelativeY;

	public int AdditionalOffsetPx = 2;

	public dfAnchorStyle Anchor = (dfAnchorStyle)6;

	public dfPivotPoint Pivot = (dfPivotPoint)6;

	public int lastActiveCount = -1;

	public float lastCooldown;

	public bool showDecimal;

	public bool UpdateBoundState(PlayerController player)
	{
		bool result = false;
		if (player.IsGhost != isGhost)
		{
			isGhost = player.IsGhost;
			result = true;
		}
		if ((Object)(object)player.CurrentItem != (Object)(object)lastItem)
		{
			lastItem = player.CurrentItem;
			result = true;
		}
		if (Object.op_Implicit((Object)(object)lastItem))
		{
			showDecimal = false;
			float num;
			if (lastItem.CurrentRoomCooldown > 0)
			{
				num = lastItem.CurrentRoomCooldown;
			}
			else if (lastItem.CurrentDamageCooldown > 0f)
			{
				num = (int)lastItem.CurrentDamageCooldown;
			}
			else if (lastItem.CurrentTimeCooldown > 0f)
			{
				showDecimal = true;
				num = lastItem.CurrentTimeCooldown;
			}
			else
			{
				num = 0f;
			}
			if (num != lastCooldown)
			{
				lastCooldown = num;
				result = true;
			}
		}
		if (lastActiveCount != player.activeItems.Count)
		{
			lastActiveCount = player.activeItems.Count;
			result = true;
		}
		return result;
	}

	public void UpdateLabelState()
	{
		if (!Object.op_Implicit((Object)(object)lastItem) || lastCooldown == 0f || isGhost)
		{
			((dfControl)cooldownLabel).IsVisible = false;
			return;
		}
		((dfControl)cooldownLabel).IsVisible = true;
		string text = (showDecimal ? "0.0" : "0");
		cooldownLabel.Text = lastCooldown.ToString(text);
		UpdateLabelPostion();
	}

	public void UpdateLabelPostion()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: 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)
		((dfControl)cooldownLabel).Anchor = Anchor;
		((dfControl)cooldownLabel).Pivot = Pivot;
		((dfControl)cooldownLabel).RelativePosition = new Vector3((float)BaseRelativeX, (float)BaseRelativeY);
		float num = (float)AdditionalOffsetPx * Pixelator.Instance.CurrentTileScale * (float)itemController.AdditionalItemBoxSprites.Count;
		if (itemController.IsRightAligned)
		{
			num = 0f - num;
		}
		((dfControl)cooldownLabel).RelativePosition = new Vector3((float)BaseRelativeX + num, (float)BaseRelativeY);
	}

	public void Destroy()
	{
		if (Object.op_Implicit((Object)(object)cooldownLabel))
		{
			Object.Destroy((Object)(object)cooldownLabel);
		}
	}
}
internal static class DebugHelper
{
	internal struct ElapsedHelper : IDisposable
	{
		public readonly string Label;

		public readonly long StartTimestamp;

		public ElapsedHelper(string label, long startTimestamp)
		{
			Label = label;
			StartTimestamp = startTimestamp;
		}

		public void Dispose()
		{
			float num = Stopwatch.GetTimestamp() - StartTimestamp;
			if (num <= 0f)
			{
				StaticLogger.LogDebug(Label + " Elapsed: 0 ms");
				return;
			}
			float num2 = num / (float)Stopwatch.Frequency * 1000f;
			StaticLogger.LogDebug($"{Label} Elapsed: {num2} ms");
		}
	}

	public static void AddDebugCommands(ItemTipsModule module)
	{
	}

	public static ElapsedHelper LogElapsed(string label)
	{
		return new ElapsedHelper(label, Stopwatch.GetTimestamp());
	}
}
public class ExternalDataCache
{
	public Dictionary<string, ExternalPickupData> Pickups = new Dictionary<string, ExternalPickupData>();

	public Dictionary<string, ExternalSynergyData> Synergies = new Dictionary<string, ExternalSynergyData>();
}
public class ExternalDataSet
{
	public ExternalMetadata Metadata;

	public Dictionary<string, ExternalPickupData> Items;

	public Dictionary<string, ExternalSynergyData> Synergies;
}
public class ExternalPickupData
{
	public string Name;

	public string Notes;

	[JsonIgnore]
	public ExternalMetadata SourceMetadata;
}
public class ExternalSynergyData
{
	public string Name;

	public string Notes;

	[JsonIgnore]
	public ExternalMetadata SourceMetadata;
}
public class ExternalMetadata
{
	public string Name;

	public string Version;

	public string Url;
}
internal static class HookHelper
{
	public static Hook CreateHook(Type sourceType, string sourceMethodName, object newReceiver, string hookMethodName)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Expected O, but got Unknown
		MethodInfo? method = sourceType.GetMethod(sourceMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		Delegate @delegate = ReflectionHelper.CreateInstanceDelegate(newReceiver, hookMethodName);
		return new Hook((MethodBase)method, @delegate);
	}
}
public class InternalDataSet
{
	public ItemData[] Items = ArrayHelper<ItemData>.Empty;

	public SynergyData[] Synergies = ArrayHelper<SynergyData>.Empty;
}
public class SynergyData
{
	public string Key;

	public PartsList OtherParts;

	public string Name;

	public string Effect;

	public SourceMetadata SourceMetadata;

	public bool InternalWouldGetSynergy()
	{
		if (OtherParts?.Parts == null)
		{
			return false;
		}
		bool result = false;
		PlayerController[] allPlayers = GameManager.Instance.AllPlayers;
		foreach (PlayerController val in allPlayers)
		{
			int num = 0;
			int[] parts = OtherParts.Parts;
			for (int j = 0; j < parts.Length; j++)
			{
				PickupObject byId = PickupObjectDatabase.GetById(parts[j]);
				if (byId != null && val.HasPickupID(byId.PickupObjectId))
				{
					num++;
				}
				if (OtherParts.PartOperand == PartOperand.One && num > 0)
				{
					break;
				}
			}
			if (OtherParts.PartOperand == PartOperand.One || OtherParts.PartOperand == PartOperand.OneOrMore)
			{
				if (num > 0)
				{
					result = true;
				}
			}
			else if (OtherParts.PartOperand == PartOperand.All && num == OtherParts.Parts.Length)
			{
				result = true;
			}
		}
		return result;
	}
}
public class PartsList
{
	private PartOperand? _operand;

	public string Operand;

	public int[] Parts;

	public PartOperand PartOperand
	{
		get
		{
			if (!_operand.HasValue)
			{
				if (string.IsNullOrEmpty(Operand))
				{
					_operand = PartOperand.Unknown;
				}
				else if (string.Equals(Operand, "one+", StringComparison.OrdinalIgnoreCase))
				{
					_operand = PartOperand.OneOrMore;
				}
				else
				{
					try
					{
						_operand = (PartOperand)Enum.Parse(typeof(PartOperand), Operand, ignoreCase: true);
					}
					catch (Exception)
					{
						_operand = PartOperand.Unknown;
					}
				}
			}
			return _operand.GetValueOrDefault();
		}
	}
}
public enum PartOperand
{
	Unknown,
	One,
	OneOrMore,
	All
}
public class ItemData
{
	public string Name;

	public int? Id;

	public int[] Ids;

	public string Notes;

	public SynergyData[] Synergies = ArrayHelper<SynergyData>.Empty;

	public SourceMetadata SourceMetadata;
}
public class SourceMetadata
{
	public string Name;

	public string Url;

	public string Version;

	public static readonly SourceMetadata InternalSource = new SourceMetadata
	{
		Name = "internal"
	};

	public override string ToString()
	{
		return "SourceMetadata:" + Name;
	}
}
internal static class ItemTipsConfig
{
	public static class ConfigKeys
	{
		public static readonly string HorizontalPosition = "HorizontalPosition";

		public static readonly string VerticalPosition = "VerticalPosition";

		public static readonly string TipsEnabled = "TipsEnabled";

		public static readonly string AmmonomiconEnabled = "AmmonomiconEnabled";
	}

	internal static Gunfig _Gunfig = null;

	public static readonly float DefaultHorizontalPosition = 0.01f;

	public static readonly float DefaultVerticalPosition = 0.2f;

	public static readonly string DefaultItem = "Default";

	public static bool TipsEnabled = true;

	public static bool AmmonomiconEnabled = true;

	public static float HorizontalPosition = DefaultHorizontalPosition;

	public static float VerticalPosition = DefaultVerticalPosition;

	internal static void Init()
	{
		_Gunfig = Gunfig.Get("ItemTips");
		CreateItemTipsMenu(_Gunfig);
		TipsEnabled = _Gunfig.Enabled(ConfigKeys.TipsEnabled);
		AmmonomiconEnabled = _Gunfig.Enabled(ConfigKeys.AmmonomiconEnabled);
		HorizontalPosition = TryGetFloatOrDefault(_Gunfig, ConfigKeys.HorizontalPosition, DefaultHorizontalPosition);
		VerticalPosition = TryGetFloatOrDefault(_Gunfig, ConfigKeys.VerticalPosition, DefaultVerticalPosition);
		StaticLogger.LogDebug($"{ConfigKeys.TipsEnabled}={TipsEnabled}");
		StaticLogger.LogDebug($"{ConfigKeys.AmmonomiconEnabled}={AmmonomiconEnabled}");
		StaticLogger.LogDebug($"{ConfigKeys.HorizontalPosition}={HorizontalPosition}");
		StaticLogger.LogDebug($"{ConfigKeys.VerticalPosition}={VerticalPosition}");
	}

	private static void CreateItemTipsMenu(Gunfig gunfig)
	{
		gunfig.AddToggle(ConfigKeys.TipsEnabled, true, "Tips", (Action<string, string>)delegate(string key, string value)
		{
			TipsEnabled = value == "1";
			StaticLogger.LogDebug($"Config Update {ConfigKeys.TipsEnabled}={TipsEnabled}");
		}, (Update)1);
		gunfig.AddToggle(ConfigKeys.AmmonomiconEnabled, true, "Extended Ammonomicon", (Action<string, string>)delegate(string key, string value)
		{
			AmmonomiconEnabled = value == "1";
			StaticLogger.LogDebug($"Config Update {ConfigKeys.AmmonomiconEnabled}={AmmonomiconEnabled}");
		}, (Update)1);
		List<string> list = new List<string> { DefaultItem };
		list.AddRange(from i in Enumerable.Range(0, 101)
			select ((float)i / 100f).ToString("0.00"));
		gunfig.AddScrollBox(ConfigKeys.HorizontalPosition, list, "Horizontal Position", (Action<string, string>)UpdateFloatCallback, (List<string>)null, (Update)1);
		gunfig.AddScrollBox(ConfigKeys.VerticalPosition, list, "Vertical Position", (Action<string, string>)UpdateFloatCallback, (List<string>)null, (Update)1);
	}

	private static void UpdateFloatCallback(string key, string newValue)
	{
		if (key == ConfigKeys.HorizontalPosition)
		{
			float result;
			if (newValue == DefaultItem)
			{
				HorizontalPosition = DefaultHorizontalPosition;
			}
			else if (float.TryParse(newValue, out result))
			{
				HorizontalPosition = result;
			}
			StaticLogger.LogDebug($"Config Update {ConfigKeys.HorizontalPosition}={HorizontalPosition}");
		}
		else if (key == ConfigKeys.VerticalPosition)
		{
			if (newValue == DefaultItem)
			{
				VerticalPosition = DefaultVerticalPosition;
			}
			if (float.TryParse(newValue, out var result2))
			{
				VerticalPosition = result2;
			}
			StaticLogger.LogDebug($"Config Update {ConfigKeys.VerticalPosition}={VerticalPosition}");
		}
	}

	private static float TryGetFloatOrDefault(Gunfig gunfig, string key, float defaultValue)
	{
		string text = gunfig.Value(key);
		if (text == null)
		{
			return defaultValue;
		}
		if (text == DefaultItem)
		{
			return defaultValue;
		}
		if (float.TryParse(text, out var result))
		{
			return result;
		}
		return defaultValue;
	}
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("glorfindel.etg.itemtips", "ItemTips", "2.2.0")]
public class ItemTipsModule : BaseUnityPlugin
{
	public const string GUID = "glorfindel.etg.itemtips";

	public const string NAME = "ItemTips";

	public const string VERSION = "2.2.0";

	private const string DefaultSynergyHighlightColor = "32C23A";

	private const string DefaultCoolnessHighlightColor = "7ACAD6";

	private const string DefaultCurseHighlightColor = "745AC7";

	private static readonly Color LabelBackgroundColor = new Color(0f, 0f, 0f, 0.5f);

	public ConfigEntry<string> ExternalDataPathConfig;

	private bool _lateStartCalled;

	private Settings _currentSettings;

	private Font _gameFont;

	private Label _infoLabel;

	private NearItemOfInterestModifier _modifier;

	private HashSet<int> _specialItemIds;

	private PickupAndSynergyDataCache _tipCache;

	private AmmonomiconEntryCache _ammonomiconCache;

	private AdvancedSynergyCache _synergyCache;

	private TipSource? _lastTipSource;

	private PlayerControllerObserver _observer;

	public ItemTipsModule()
	{
		_tipCache = new PickupAndSynergyDataCache();
		_currentSettings = new Settings();
		_synergyCache = new AdvancedSynergyCache();
		_ammonomiconCache = new AmmonomiconEntryCache(_synergyCache, _tipCache);
		_specialItemIds = new HashSet<int> { 224, 120, 73, 85, 78, 600, 67 };
	}

	public PickupAndSynergyDataCache GetDataCache()
	{
		return _tipCache;
	}

	public AdvancedSynergyCache GetSynergyCache()
	{
		return _synergyCache;
	}

	public void CheckForSynergyManagerChanges()
	{
		if (_synergyCache.SourceEntries != GameManager.Instance.SynergyManager.synergies)
		{
			StaticLogger.LogDebug("Detected changed source synergies. Reloading...");
			_synergyCache = new AdvancedSynergyCache(GameManager.Instance.SynergyManager.synergies);
			_ammonomiconCache = new AmmonomiconEntryCache(_synergyCache, _tipCache);
		}
	}

	public void Awake()
	{
		ExternalDataPathConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Data", "External Data Path", "", "Optional path to directory with external data files. Separate multiple directories with ';'.");
	}

	public void Start()
	{
		ETGModMainBehaviour.WaitForGameManagerStart((Action<GameManager>)GmStart);
	}

	public void GmStart(GameManager gm)
	{
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			StaticLogger.Source = ((BaseUnityPlugin)this).Logger;
			StaticLogger.LogDebug("Loading Config");
			ItemTipsConfig.Init();
			StaticLogger.LogDebug("Initializing UI");
			_infoLabel = new Label();
			_modifier = new NearItemOfInterestModifier();
			SGUIRoot.Main.Children.Add((SElement)(object)_infoLabel);
			((SElement)_infoLabel).Background = LabelBackgroundColor;
			((SElement)_infoLabel).OnUpdateStyle = delegate(SElement elem)
			{
				elem.Font = LoadFont();
				((Label)(object)elem).Reposition(ItemTipsConfig.HorizontalPosition, ItemTipsConfig.VerticalPosition);
			};
			((SElement)_infoLabel).With.Add((SModifier)(object)_modifier);
			StaticLogger.LogDebug("Loading internal data");
			Stopwatch stopwatch = Stopwatch.StartNew();
			_tipCache = Loader.LoadItemData();
			_synergyCache = new AdvancedSynergyCache(GameManager.Instance.SynergyManager.synergies);
			_ammonomiconCache = new AmmonomiconEntryCache(_synergyCache, _tipCache);
			stopwatch.Stop();
			StaticLogger.LogDebug($"Loaded {_tipCache.Pickups.Count} items in {stopwatch.ElapsedMilliseconds} ms");
			SetupHoooks();
			_observer = ((Component)ETGModMainBehaviour.Instance).gameObject.AddComponent<PlayerControllerObserver>();
			PlayerControllerObserver observer = _observer;
			observer.EnteredCombat = (Action)Delegate.Combine(observer.EnteredCombat, new Action(OnEnteredCombat));
			((Component)ETGModMainBehaviour.Instance).gameObject.AddComponent<SynergyManagerMonitorBehaviour>().ItemTips = this;
			((Component)ETGModMainBehaviour.Instance).gameObject.AddComponent<CooldownLabelBehavior>();
			StaticLogger.LogDebug("Defining commands");
			ETGModConsole.Commands.AddGroup("itemtips", (Action<string[]>)delegate
			{
				HelpCommand(ArrayHelper<string>.Empty);
			});
			ConsoleCommandGroup group = ETGModConsole.Commands.GetGroup("itemtips");
			group.AddUnit("help", (Action<string[]>)HelpCommand);
			group.AddUnit("reload", (Action<string[]>)ReloadCommand);
			group.AddUnit("generate", (Action<string[]>)GenerateSampleCommand);
			DebugHelper.AddDebugCommands(this);
			ETGModConsole.Log((object)"ItemTips v2.2.0 loaded", false);
		}
		catch (Exception arg)
		{
			StaticLogger.LogError(string.Format("ItemTips v{0} Error: {1}", "2.2.0", arg));
			ETGModConsole.Log((object)string.Format("ItemTips v{0} Error: {1}", "2.2.0", arg), false);
		}
	}

	private void SetupHoooks()
	{
		StaticLogger.LogDebug("Generating hooks");
		HookHelper.CreateHook(typeof(Gun), "OnEnteredRange", this, "GunOnEnteredRangeHook");
		HookHelper.CreateHook(typeof(Gun), "OnExitRange", this, "GunOnExitRangeHook");
		HookHelper.CreateHook(typeof(Gun), "Pickup", this, "GunPickupHook");
		HookHelper.CreateHook(typeof(PassiveItem), "OnEnteredRange", this, "PassiveItemOnEnteredRangeHook");
		HookHelper.CreateHook(typeof(PassiveItem), "OnExitRange", this, "PassiveItemOnExitRangeHook");
		HookHelper.CreateHook(typeof(PassiveItem), "Pickup", this, "PassiveItemPickupHook");
		HookHelper.CreateHook(typeof(GungeonMapItem), "Pickup", this, "PassiveItemPickupHook");
		HookHelper.CreateHook(typeof(PlayerItem), "OnEnteredRange", this, "ActiveItemOnEnteredRangeHook");
		HookHelper.CreateHook(typeof(PlayerItem), "OnExitRange", this, "ActiveItemOnExitRangeHook");
		HookHelper.CreateHook(typeof(PlayerItem), "Pickup", this, "ActiveItemPickupHook");
		HookHelper.CreateHook(typeof(ShopItemController), "OnEnteredRange", this, "ShopItemOnEnteredRangeHook");
		HookHelper.CreateHook(typeof(ShopItemController), "OnExitRange", this, "ShopItemOnExitRangeHook");
		HookHelper.CreateHook(typeof(ShopItemController), "Interact", this, "ShopItemInteractHook");
		HookHelper.CreateHook(typeof(RewardPedestal), "OnEnteredRange", this, "RewardPedestalOnEnteredRangeHook");
		HookHelper.CreateHook(typeof(RewardPedestal), "OnExitRange", this, "RewardPedestalOnExitRangeHook");
		HookHelper.CreateHook(typeof(RewardPedestal), "Interact", this, "RewardPedestalInteractHook");
		HookHelper.CreateHook(typeof(Chest), "PredictContents", this, "ChestPredictContentsHook");
		HookHelper.CreateHook(typeof(HologramDoer), "HideSprite", this, "HologramDoerHideSpriteHook");
		HookHelper.CreateHook(typeof(PlayerController), "OnGunChanged", this, "OnGunChangedHook");
		HookHelper.CreateHook(typeof(Foyer), "Awake", this, "LateStartAwakeHook");
		HookHelper.CreateHook(typeof(EncounterDatabaseEntry), "GetModifiedLongDescription", this, "GetModifiedLongDescriptionHook");
	}

	private void LateStartAwakeHook(Action<Foyer> orig, Foyer self)
	{
		orig(self);
		if (!_lateStartCalled)
		{
			_lateStartCalled = true;
			try
			{
				ScanExternalData();
				CheckForSynergyManagerChanges();
			}
			catch (Exception arg)
			{
				StaticLogger.LogError($"Error automatically loading external files: {arg}");
			}
		}
	}

	private int ScanExternalData()
	{
		int num = 0;
		Stopwatch stopwatch = Stopwatch.StartNew();
		int num2 = _tipCache.LoadExternalDirectory(Paths.PluginPath);
		StaticLogger.LogDebug($"Finished loading external data in BepInEx path . Loaded {num2} items. Elapsed: {stopwatch.ElapsedMilliseconds} ms");
		num += num2;
		string value = ExternalDataPathConfig.Value;
		if (!string.IsNullOrEmpty(value))
		{
			string[] array = value.Split(new char[1] { ';' });
			foreach (string text in array)
			{
				StaticLogger.LogInfo("Loading external directory: " + text);
				Stopwatch stopwatch2 = Stopwatch.StartNew();
				int num3 = _tipCache.LoadExternalDirectory(text);
				StaticLogger.LogDebug($"Finished loading external data in '{text}'. Loaded {num3} items. Elapsed: {stopwatch2.ElapsedMilliseconds} ms");
				num += num3;
			}
		}
		return num;
	}

	private void HologramDoerHideSpriteHook(Action<HologramDoer, GameObject, bool> orig, HologramDoer self, GameObject gameObject, bool instant)
	{
		if (ItemTipsConfig.TipsEnabled)
		{
			HideTip();
		}
		orig(self, gameObject, instant);
	}

	private void OnEnteredCombat()
	{
		HideTip();
	}

	private string GetModifiedLongDescriptionHook(Func<EncounterDatabaseEntry, string> orig, EncounterDatabaseEntry self)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		string text = orig(self);
		if (ItemTipsConfig.AmmonomiconEnabled)
		{
			try
			{
				_ammonomiconCache.SetCacheLanguage(GameManager.Options.CurrentLanguage);
				int pickupObjectId = self.pickupObjectId;
				return _ammonomiconCache.GetEntry(pickupObjectId, text);
			}
			catch (Exception arg)
			{
				StaticLogger.LogError(string.Format("Error in {0}: {1}", "GetModifiedLongDescriptionHook", arg));
			}
		}
		return text;
	}

	private void HelpCommand(string[] args)
	{
		if (args.Length != 0)
		{
			string text = args[0].ToLowerInvariant();
			switch (text)
			{
			case "reload":
				ETGModConsole.Log((object)"Reloads external item description files", false);
				break;
			case "generate":
				ETGModConsole.Log((object)"Generates a sample external item description file", false);
				break;
			case "help":
				ETGModConsole.Log((object)"Help generates help", false);
				break;
			default:
				ETGModConsole.Log((object)("Unknown command " + text), false);
				break;
			}
		}
		else
		{
			ETGModConsole.Log((object)"ItemTips v2.2.0 command help", false);
			ETGModConsole.Log((object)"itemtips reload - Reload external tip files", false);
			ETGModConsole.Log((object)"itemtips generate - Create sample external tip file", false);
			ETGModConsole.Log((object)"itemtips help [command] - Additional help about the command", false);
		}
	}

	private void GenerateSampleCommand(string[] args)
	{
		char[] separator = new char[1] { ':' };
		string text = null;
		try
		{
			HashSet<string> hashSet = new HashSet<string>(args ?? ArrayHelper<string>.Empty);
			ExternalDataSet externalDataSet = new ExternalDataSet
			{
				Metadata = new ExternalMetadata
				{
					Name = "",
					Url = "",
					Version = ""
				},
				Items = new Dictionary<string, ExternalPickupData>(),
				Synergies = new Dictionary<string, ExternalSynergyData>()
			};
			foreach (KeyValuePair<string, PickupObject> pair in Game.Items.Pairs)
			{
				if (string.IsNullOrEmpty(pair.Key) || _specialItemIds.Contains(pair.Value.PickupObjectId))
				{
					continue;
				}
				string text2 = pair.Key;
				bool flag = false;
				string item;
				if (text2.StartsWith("gungeon:"))
				{
					item = "gungeon";
					if (text2.Contains("_dupe") || (text2.Contains("+") && text2 != "gungeon:+1_bullets"))
					{
						continue;
					}
					text2 = text2.Substring("gungeon:".Length);
					flag = true;
				}
				else
				{
					item = text2.Split(separator)[0];
				}
				string text3 = null;
				if (_tipCache.Pickups.TryGetValue(pair.Value.PickupObjectId, out var value))
				{
					text3 = value.Notes;
				}
				else if (flag)
				{
					continue;
				}
				if (hashSet.Count <= 0 || hashSet.Contains(item))
				{
					externalDataSet.Items[text2] = new ExternalPickupData
					{
						Name = pair.Value.EncounterNameOrDisplayName,
						Notes = (text3 ?? string.Empty)
					};
				}
			}
			foreach (KeyValuePair<string, SynergyGroup> item2 in _synergyCache.SynergyKeyIndex)
			{
				string text4 = null;
				if (_tipCache.Synergies.TryGetValue(item2.Value.NameKey, out var value2))
				{
					text4 = value2.Effect;
					string synergyString = StringTableManager.GetSynergyString(item2.Key, -1);
					externalDataSet.Synergies[item2.Key] = new ExternalSynergyData
					{
						Name = synergyString,
						Notes = (text4 ?? string.Empty)
					};
				}
			}
			string path = Loader.DataFilePrefix + "-sample" + Loader.DataFileExtension;
			text = Path.Combine(Environment.GetEnvironmentVariable("HOME") ?? Environment.GetFolderPath(Environment.SpecialFolder.Personal), path);
			JsonHelper.SerializeToFile(text, externalDataSet);
			long length = new FileInfo(text).Length;
			StaticLogger.LogInfo($"Wrote {length} bytes to to {text}");
			ETGModConsole.Log((object)("Wrote sample file to " + text), false);
		}
		catch (Exception ex)
		{
			if (text != null)
			{
				StaticLogger.LogError($"Error creating sample file: '{text}' {ex}");
				ETGModConsole.Log((object)$"Error creating sample file: '{text}' {ex}", false);
			}
			else
			{
				StaticLogger.LogError($"Error creating sample file: {ex}");
				ETGModConsole.Log((object)$"Error creating sample file: {ex}", false);
			}
		}
	}

	private void ReloadCommand(string[] args)
	{
		int num = ScanExternalData();
		ETGModConsole.Log((object)$"ItemTips reloaded {num} items", false);
	}

	private Font LoadFont()
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Expected O, but got Unknown
		if ((Object)(object)_gameFont == (Object)null)
		{
			dfFont val = (dfFont)GameUIRoot.Instance.Manager.DefaultFont;
			_gameFont = FontConverter.GetFontFromdfFont(val, 2);
		}
		return _gameFont;
	}

	private void GunOnEnteredRangeHook(Action<Gun, PlayerController> orig, Gun self, PlayerController player)
	{
		try
		{
			if (ItemTipsConfig.TipsEnabled)
			{
				ShowTip(TipSource.Gun, ((PickupObject)self).PickupObjectId);
			}
		}
		catch (Exception arg)
		{
			StaticLogger.LogDebug(string.Format("Error in {0}: {1}", "GunOnEnteredRangeHook", arg));
		}
		orig(self, player);
	}

	private void GunOnExitRangeHook(Action<Gun, PlayerController> orig, Gun self, PlayerController player)
	{
		if (ItemTipsConfig.TipsEnabled)
		{
			HideTip();
		}
		orig(self, player);
	}

	private void GunPickupHook(Action<Gun, PlayerController> orig, Gun self, PlayerController player)
	{
		if (ItemTipsConfig.TipsEnabled)
		{
			HideTip();
		}
		orig(self, player);
	}

	private void PassiveItemOnEnteredRangeHook(Action<PassiveItem, PlayerController> orig, PassiveItem self, PlayerController player)
	{
		if (ItemTipsConfig.TipsEnabled)
		{
			ShowTip(TipSource.PassiveItem, ((PickupObject)self).PickupObjectId);
		}
		orig(self, player);
	}

	private void PassiveItemOnExitRangeHook(Action<PassiveItem, PlayerController> orig, PassiveItem self, PlayerController player)
	{
		if (ItemTipsConfig.TipsEnabled)
		{
			HideTip();
		}
		orig(self, player);
	}

	private void PassiveItemPickupHook(Action<PassiveItem, PlayerController> orig, PassiveItem self, PlayerController player)
	{
		if (ItemTipsConfig.TipsEnabled)
		{
			HideTip();
		}
		orig(self, player);
	}

	private void ActiveItemOnEnteredRangeHook(Action<PlayerItem, PlayerController> orig, PlayerItem self, PlayerController player)
	{
		if (ItemTipsConfig.TipsEnabled)
		{
			ShowTip(TipSource.ActiveItem, ((PickupObject)self).PickupObjectId);
		}
		orig(self, player);
	}

	private void ActiveItemOnExitRangeHook(Action<PlayerItem, PlayerController> orig, PlayerItem self, PlayerController player)
	{
		if (ItemTipsConfig.TipsEnabled)
		{
			HideTip();
		}
		orig(self, player);
	}

	private void ActiveItemPickupHook(Action<PlayerItem, PlayerController> orig, PlayerItem self, PlayerController player)
	{
		if (ItemTipsConfig.TipsEnabled)
		{
			HideTip();
		}
		orig(self, player);
	}

	private void ShopItemOnEnteredRangeHook(Action<ShopItemController, PlayerController> orig, ShopItemController self, PlayerController player)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Invalid comparison between Unknown and I4
		if (ItemTipsConfig.TipsEnabled && Object.op_Implicit((Object)(object)self.item))
		{
			int pickupId = (((int)self.CurrencyType != 1) ? self.item.PickupObjectId : (PickupObjectDatabase.GetByEncounterName(self.item.EncounterNameOrDisplayName)?.PickupObjectId ?? (-1)));
			ShowTip(TipSource.ShopItem, pickupId);
		}
		orig(self, player);
	}

	private void ShopItemOnExitRangeHook(Action<ShopItemController, PlayerController> orig, ShopItemController self, PlayerController player)
	{
		if (ItemTipsConfig.TipsEnabled)
		{
			HideTip();
		}
		orig(self, player);
	}

	private void ShopItemInteractHook(Action<ShopItemController, PlayerController> orig, ShopItemController self, PlayerController player)
	{
		if (ItemTipsConfig.TipsEnabled)
		{
			HideTip();
		}
		orig(self, player);
	}

	private void RewardPedestalOnEnteredRangeHook(Action<RewardPedestal, PlayerController> orig, RewardPedestal self, PlayerController player)
	{
		if (ItemTipsConfig.TipsEnabled)
		{
			int pickupId = self.contents?.PickupObjectId ?? (-1);
			ShowTip(TipSource.RewardPedestal, pickupId);
		}
		orig(self, player);
	}

	private void RewardPedestalOnExitRangeHook(Action<RewardPedestal, PlayerController> orig, RewardPedestal self, PlayerController player)
	{
		if (ItemTipsConfig.TipsEnabled)
		{
			HideTip();
		}
		orig(self, player);
	}

	private void RewardPedestalInteractHook(Action<RewardPedestal, PlayerController> orig, RewardPedestal self, PlayerController player)
	{
		if (ItemTipsConfig.TipsEnabled)
		{
			HideTip();
		}
		orig(self, player);
	}

	private List<PickupObject> ChestPredictContentsHook(Func<Chest, PlayerController, List<PickupObject>> orig, Chest self, PlayerController player)
	{
		List<PickupObject> list = orig(self, player);
		if (list.Count > 0 && ItemTipsConfig.TipsEnabled)
		{
			ShowTip(TipSource.ChestPredicted, list[0].PickupObjectId);
		}
		return list;
	}

	private void OnGunChangedHook(Action<PlayerController, Gun, Gun, Gun, Gun, bool> orig, PlayerController self, Gun previous, Gun current, Gun previousSecondary, Gun currentSecondary, bool newGun)
	{
		if (ItemTipsConfig.TipsEnabled && _lastTipSource.GetValueOrDefault() == TipSource.ChestPredicted)
		{
			HideTip();
		}
		orig(self, previous, current, previousSecondary, currentSecondary, newGun);
	}

	private void ShrineOnEnteredRangeHook(Action<AdvancedShrineController, PlayerController> orig, AdvancedShrineController self, PlayerController player)
	{
		orig(self, player);
	}

	private void ShrineOnExitRangeHook(Action<AdvancedShrineController, PlayerController> orig, AdvancedShrineController self, PlayerController player)
	{
		orig(self, player);
	}

	private void ShowTip(TipSource source, int pickupId)
	{
		//IL_0088: 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)
		if (pickupId < 0)
		{
			_modifier.IsNearItem = false;
			_lastTipSource = null;
			return;
		}
		try
		{
			if (_specialItemIds.Contains(pickupId))
			{
				_modifier.IsNearItem = false;
				_lastTipSource = null;
				return;
			}
			PickupObject byId = PickupObjectDatabase.GetById(pickupId);
			if (!_tipCache.Pickups.TryGetValue(pickupId, out var value))
			{
				value = null;
			}
			TextInfo textInfo = GenerateTextInfo(byId, value);
			((SLabel)_infoLabel).Text = textInfo.LabelText;
			((SElement)_infoLabel).Size = textInfo.LabelSize;
			_modifier.IsNearItem = true;
			_lastTipSource = source;
			_infoLabel.Reposition(ItemTipsConfig.HorizontalPosition, ItemTipsConfig.VerticalPosition);
		}
		catch (Exception arg)
		{
			StaticLogger.LogDebug($"ShowTip Error {source} '{pickupId}': {arg}");
		}
	}

	private void HideTip()
	{
		_modifier.IsNearItem = false;
		_lastTipSource = null;
	}

	private TextInfo GenerateTextInfo(PickupObject pickup, ItemData item)
	{
		//IL_036d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0372: Unknown result type (might be due to invalid IL or missing references)
		//IL_0389: Unknown result type (might be due to invalid IL or missing references)
		List<string> lines = new List<string> { pickup.EncounterNameOrDisplayName };
		TipBuilder.AppendQualityDescriptor(pickup, delegate(string line)
		{
			lines.Add(line);
		});
		EncounterDatabaseEntry entry = EncounterDatabase.GetEntry(((BraveBehaviour)pickup).encounterTrackable.EncounterGuid);
		if (entry != null)
		{
			string secondTapeDescriptor = entry.GetSecondTapeDescriptor();
			if (entry.shootStyleInt >= 0)
			{
				lines.Add("Style: " + secondTapeDescriptor);
			}
			else if (entry.isPassiveItem || entry.isPlayerItem)
			{
				lines.Add("Type: " + secondTapeDescriptor);
			}
		}
		TipBuilder.AppendActiveCooldownType(pickup, delegate(string line)
		{
			lines.Add(line);
		});
		if (item != null && !string.IsNullOrEmpty(item.Notes))
		{
			List<string> collection = ConvertStringToFixedWidthLines(item.Notes, _currentSettings.LineWidth);
			lines.AddRange(collection);
		}
		TipBuilder.AppendModifiers(pickup, delegate(StatType stat, string line)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Invalid comparison between Unknown and I4
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			string text3 = null;
			if ((int)stat != 4)
			{
				if ((int)stat == 14)
				{
					text3 = "745AC7";
				}
			}
			else
			{
				text3 = "7ACAD6";
			}
			if (string.IsNullOrEmpty(text3))
			{
				lines.Add(line);
			}
			else
			{
				lines.Add("<color=#" + text3 + ">" + line + "</color>");
			}
		});
		HashSet<string> hashSet = new HashSet<string>();
		if (_synergyCache.ItemIndex.TryGetValue(pickup.PickupObjectId, out var value) && value.Count > 0)
		{
			lines.Add("Synergies:");
			foreach (SynergyGroup item2 in value)
			{
				string synergyString = StringTableManager.GetSynergyString(item2.NameKey, -1);
				if (!hashSet.Add(synergyString))
				{
					continue;
				}
				string text = null;
				bool num = item2.SynergyIsAvailable(GameManager.Instance.PrimaryPlayer, GameManager.Instance.SecondaryPlayer, pickup.PickupObjectId);
				if (num && _tipCache.Synergies.TryGetValue(item2.NameKey, out var value2))
				{
					text = value2.Effect;
				}
				if (num)
				{
					if (!string.IsNullOrEmpty(text))
					{
						lines.Add(" - <color=#32C23A>" + synergyString + "</color>:");
						List<string> collection2 = ConvertStringToFixedWidthLines(text, _currentSettings.LineWidth);
						lines.AddRange(collection2);
					}
					else
					{
						lines.Add(" - <color=#32C23A>" + synergyString + "</color>");
					}
				}
				else
				{
					lines.Add(" - " + synergyString);
				}
			}
		}
		if (item != null && item.Synergies.Length != 0)
		{
			if (hashSet.Count == 0)
			{
				lines.Add("Synergies:");
			}
			SynergyData[] synergies = item.Synergies;
			foreach (SynergyData synergyData in synergies)
			{
				string localizedSynergyName = synergyData.GetLocalizedSynergyName();
				if (!hashSet.Add(localizedSynergyName) || (synergyData.Key != null && hashSet.Contains(synergyData.Key)))
				{
					continue;
				}
				string text2 = null;
				bool num2 = synergyData.InternalWouldGetSynergy();
				if (num2)
				{
					text2 = synergyData.Effect;
				}
				if (num2)
				{
					if (!string.IsNullOrEmpty(text2))
					{
						lines.Add(" - <color=#32C23A>" + localizedSynergyName + "</color>:");
						List<string> collection3 = ConvertStringToFixedWidthLines(text2, _currentSettings.LineWidth);
						lines.AddRange(collection3);
					}
					else
					{
						lines.Add(" - <color=#32C23A>" + localizedSynergyName + "</color>");
					}
				}
				else
				{
					lines.Add(" - " + localizedSynergyName);
				}
			}
		}
		Vector2 size = _currentSettings.GetSize(lines.Count);
		return new TextInfo(string.Join("\n", lines.ToArray()), size);
	}

	private static List<string> ConvertStringToFixedWidthLines(string text, int lineWidth)
	{
		List<string> list = new List<string>();
		if (text.Length < lineWidth)
		{
			list.Add(text);
		}
		else
		{
			string[] array = text.Split();
			StringBuilder stringBuilder = new StringBuilder();
			string[] array2 = array;
			foreach (string text2 in array2)
			{
				if (stringBuilder.Length + text2.Length + 1 >= lineWidth)
				{
					list.Add(stringBuilder.ToString());
					stringBuilder.Length = 0;
					stringBuilder.Append(text2);
					continue;
				}
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append(" ");
				}
				stringBuilder.Append(text2);
			}
			if (stringBuilder.Length > 0)
			{
				list.Add(stringBuilder.ToString());
			}
		}
		return list;
	}
}
public enum ItemType
{
	None,
	Gun,
	Passive,
	Active,
	Synergy
}
internal static class JsonHelper
{
	private static readonly JsonSerializerSettings DefaultSettings = new JsonSerializerSettings
	{
		Formatting = (Formatting)1,
		ContractResolver = (IContractResolver)new CamelCasePropertyNamesContractResolver()
	};

	private static readonly JsonSerializer Serializer = JsonSerializer.Create(DefaultSettings);

	public static T DeserializeFromFile<T>(string filePath)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Expected O, but got Unknown
		using StreamReader streamReader = new StreamReader(filePath);
		JsonTextReader val = new JsonTextReader((TextReader)streamReader);
		try
		{
			return Serializer.Deserialize<T>((JsonReader)(object)val);
		}
		finally
		{
			((IDisposable)val)?.Dispose();
		}
	}

	public static T DeserializeFromStream<T>(Stream inputStream)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Expected O, but got Unknown
		using StreamReader streamReader = new StreamReader(inputStream);
		JsonTextReader val = new JsonTextReader((TextReader)streamReader);
		try
		{
			return Serializer.Deserialize<T>((JsonReader)(object)val);
		}
		finally
		{
			((IDisposable)val)?.Dispose();
		}
	}

	public static void SerializeToFile(string filePath, object obj)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Expected O, but got Unknown
		using StreamWriter streamWriter = new StreamWriter(filePath, append: false);
		JsonTextWriter val = new JsonTextWriter((TextWriter)streamWriter);
		try
		{
			Serializer.Serialize((JsonWriter)(object)val, obj);
		}
		finally
		{
			((IDisposable)val)?.Dispose();
		}
	}
}
internal class Label : SLabel
{
	public void Reposition(float leftFraction, float topFraction)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		if (((SElement)this).Root != null)
		{
			((SElement)this).Position.x = ((SElement)this).Root.Size.x * leftFraction;
			((SElement)this).Position.y = ((SElement)this).Root.Size.y * topFraction;
		}
	}
}
public static class Loader
{
	public static bool ThrowIfException = DefaultThrowSetting();

	public static string DataFilePrefix { get; } = "itemtips";


	public static string DataFileExtension { get; } = ".tip";


	internal static string SearchPattern { get; } = DataFilePrefix + "*" + DataFileExtension;


	public static PickupAndSynergyDataCache LoadItemData()
	{
		PickupAndSynergyDataCache pickupAndSynergyDataCache = new PickupAndSynergyDataCache();
		try
		{
			InternalDataSet internalDataSet = GetInternalDataSet();
			ItemData[] items = internalDataSet.Items;
			foreach (ItemData itemData in items)
			{
				itemData.SourceMetadata = SourceMetadata.InternalSource;
				if (itemData.Id.HasValue)
				{
					pickupAndSynergyDataCache.Pickups[itemData.Id.GetValueOrDefault()] = itemData;
				}
				else if (itemData.Ids != null)
				{
					int[] ids = itemData.Ids;
					foreach (int key in ids)
					{
						pickupAndSynergyDataCache.Pickups[key] = itemData;
					}
				}
				else
				{
					StaticLogger.LogDebug("Could not process item '" + itemData.Name + "' because it does not have an id");
				}
				SynergyData[] synergies = internalDataSet.Synergies;
				foreach (SynergyData synergyData in synergies)
				{
					synergyData.SourceMetadata = SourceMetadata.InternalSource;
					if (synergyData.Key != null && synergyData.Key.StartsWith("#"))
					{
						pickupAndSynergyDataCache.Synergies[synergyData.Key] = synergyData;
					}
					else
					{
						StaticLogger.LogDebug("Could not process item '" + synergyData.Name + "' because it does not have a proper id");
					}
				}
			}
		}
		catch (Exception arg) when (!ThrowIfException)
		{
			StaticLogger.LogInfo($"Error processing item data: {arg}");
		}
		return pickupAndSynergyDataCache;
	}

	public static ExternalDataCache LoadExternalTips(string directory)
	{
		ExternalDataCache externalDataCache = new ExternalDataCache();
		try
		{
			if (Directory.Exists(directory))
			{
				int num = 0;
				string[] files = Directory.GetFiles(directory, SearchPattern, SearchOption.AllDirectories);
				foreach (string text in files)
				{
					try
					{
						num++;
						ProcessJsonFile(externalDataCache, text);
					}
					catch (Exception arg)
					{
						StaticLogger.LogError($"Failed to read external file '{text}': {arg}");
					}
				}
				StaticLogger.LogDebug($"Files processed: {num}");
			}
			else
			{
				StaticLogger.LogDebug("Directory does not exist: " + directory);
			}
		}
		catch (Exception arg2)
		{
			StaticLogger.LogInfo($"Failed to read resource directory '{directory}': {arg2}");
		}
		return externalDataCache;
	}

	internal static InternalDataSet GetInternalDataSet()
	{
		string[] manifestResourceNames = typeof(ItemTipsModule).Assembly.GetManifestResourceNames();
		foreach (string text in manifestResourceNames)
		{
			if (!text.Contains("data.json"))
			{
				continue;
			}
			using Stream inputStream = typeof(ItemTipsModule).Assembly.GetManifestResourceStream(text);
			InternalDataSet internalDataSet = JsonHelper.DeserializeFromStream<InternalDataSet>(inputStream);
			if (internalDataSet != null && internalDataSet.Items != null)
			{
				return internalDataSet;
			}
			StaticLogger.LogDebug("Found stream " + text + " but had no data");
		}
		throw new InvalidOperationException("Could not find internal data set");
	}

	private static void ProcessJsonFile(ExternalDataCache cache, string file)
	{
		StaticLogger.LogInfo("Reading file: " + file);
		using FileStream jsonStream = File.OpenRead(file);
		ProcessJsonFromStream(cache, jsonStream, "file " + file);
	}

	private static void ProcessJsonFromStream(ExternalDataCache cache, Stream jsonStream, string descriptor)
	{
		try
		{
			ExternalDataSet externalDataSet = JsonHelper.DeserializeFromStream<ExternalDataSet>(jsonStream);
			if (externalDataSet.Metadata != null)
			{
				StaticLogger.LogDebug("name:" + externalDataSet.Metadata.Name + ", version:" + externalDataSet.Metadata.Version);
			}
			Dictionary<string, ExternalPickupData> dictionary = externalDataSet?.Items;
			if (dictionary != null && dictionary.Count > 0)
			{
				foreach (KeyValuePair<string, ExternalPickupData> item in dictionary)
				{
					ExternalPickupData value = item.Value;
					value.SourceMetadata = externalDataSet.Metadata;
					if (!string.IsNullOrEmpty(value.Notes) && !value.Notes.EndsWith("."))
					{
						value.Notes += ".";
					}
					cache.Pickups[item.Key] = item.Value;
				}
			}
			Dictionary<string, ExternalSynergyData> dictionary2 = externalDataSet?.Synergies;
			if (dictionary2 != null && dictionary2.Count > 0)
			{
				foreach (KeyValuePair<string, ExternalSynergyData> item2 in dictionary2)
				{
					ExternalSynergyData value2 = item2.Value;
					value2.SourceMetadata = externalDataSet.Metadata;
					if (!string.IsNullOrEmpty(value2.Notes) && !value2.Notes.EndsWith("."))
					{
						value2.Notes += ".";
					}
					cache.Synergies[item2.Key] = item2.Value;
				}
			}
			if (cache.Pickups.Count == 0 && cache.Synergies.Count == 0)
			{
				StaticLogger.LogDebug("Nothing found to load in " + descriptor);
			}
		}
		catch (Exception arg)
		{
			StaticLogger.LogError($"Failed to read json from {descriptor}: {arg}");
		}
	}

	private static bool DefaultThrowSetting()
	{
		return false;
	}
}
internal class NearItemOfInterestModifier : SModifier
{
	public bool IsNearItem;

	public override void Update()
	{
		base.Elem.Enabled = ItemTipsConfig.TipsEnabled;
		if (GameManager.Instance.IsPaused)
		{
			base.Elem.Visible = false;
		}
		else
		{
			base.Elem.Visible = IsNearItem;
		}
	}
}
public class PickupAndSynergyDataCache
{
	public Dictionary<int, ItemData> Pickups = new Dictionary<int, ItemData>();

	public Dictionary<string, SynergyData> Synergies = new Dictionary<string, SynergyData>();

	public int LoadExternalDirectory(string directory)
	{
		int num = 0;
		try
		{
			if (string.IsNullOrEmpty(directory))
			{
				StaticLogger.LogDebug("Skipped loading external files because directory was not set.");
				return 0;
			}
			ExternalDataCache externalDataCache = Loader.LoadExternalTips(directory);
			if (externalDataCache.Pickups.Count == 0 && externalDataCache.Synergies.Count == 0)
			{
				return num;
			}
			int num2 = 0;
			foreach (KeyValuePair<string, ExternalPickupData> pickup in externalDataCache.Pickups)
			{
				string key = pickup.Key;
				ExternalPickupData value = pickup.Value;
				if (string.IsNullOrEmpty(value.Notes))
				{
					StaticLogger.LogDebug("Skipped item: " + key + ", no 'Notes' set.");
					num2++;
					continue;
				}
				if (!Game.Items.ContainsID(key))
				{
					StaticLogger.LogDebug("Skipped item: " + key + ", game has not loaded it.");
					num2++;
					continue;
				}
				PickupObject val = Game.Items[key];
				if (val.PickupObjectId < 0)
				{
					StaticLogger.LogDebug("Skipped item: " + key + ", pickup has not been assigned an id.");
					num2++;
					continue;
				}
				SourceMetadata sourceMetadata = null;
				if (Pickups.TryGetValue(val.PickupObjectId, out var value2))
				{
					if (value2.SourceMetadata == SourceMetadata.InternalSource)
					{
						sourceMetadata = SourceMetadata.InternalSource;
					}
					else if (value.SourceMetadata != null)
					{
						sourceMetadata = new SourceMetadata
						{
							Name = value.SourceMetadata.Name,
							Version = value.SourceMetadata.Version,
							Url = value.SourceMetadata.Url
						};
					}
				}
				else
				{
					sourceMetadata = new SourceMetadata
					{
						Name = value.SourceMetadata.Name,
						Version = value.SourceMetadata.Version,
						Url = value.SourceMetadata.Url
					};
				}
				Pickups[val.PickupObjectId] = new ItemData
				{
					Name = (value.Name ?? key),
					Notes = value.Notes,
					SourceMetadata = sourceMetadata
				};
				num++;
			}
			foreach (KeyValuePair<string, ExternalSynergyData> synergy in externalDataCache.Synergies)
			{
				string key2 = synergy.Key;
				ExternalSynergyData value3 = synergy.Value;
				if (string.IsNullOrEmpty(value3.Notes))
				{
					StaticLogger.LogDebug("Skipped synergy: " + key2 + ", no 'Notes' set.");
					num2++;
					continue;
				}
				SourceMetadata sourceMetadata2 = null;
				if (Synergies.TryGetValue(key2, out var value4))
				{
					if (value4.SourceMetadata == SourceMetadata.InternalSource)
					{
						sourceMetadata2 = SourceMetadata.InternalSource;
					}
					else if (value3.SourceMetadata != null)
					{
						sourceMetadata2 = new SourceMetadata
						{
							Name = value3.SourceMetadata.Name,
							Version = value3.SourceMetadata.Version,
							Url = value3.SourceMetadata.Url
						};
					}
				}
				else
				{
					sourceMetadata2 = new SourceMetadata
					{
						Name = value3.SourceMetadata.Name,
						Version = value3.SourceMetadata.Version,
						Url = value3.SourceMetadata.Url
					};
				}
				Synergies[key2] = new SynergyData
				{
					Name = (value3.Name ?? key2),
					Effect = value3.Notes,
					SourceMetadata = sourceMetadata2
				};
				num++;
			}
			StaticLogger.LogDebug($"Loaded external tips:{num}, skipped:{num2}");
			return num;
		}
		catch (Exception arg)
		{
			StaticLogger.LogError($"Failed to load external data. Error: {arg}");
			return num;
		}
	}
}
public class PlayerControllerObserver : MonoBehaviour
{
	private Func<PlayerController, IPlayerInteractable> getLastInteractable;

	public float TimeBetweenChecks = 1f;

	public Action EnteredCombat;

	public Action ExitedCombat;

	public Action<PlayerController, IPlayerInteractable> LastInteractableChanged;

	private float TimeCounter;

	private bool _currentlyInCombat;

	private IPlayerInteractable _lastInteractable;

	private void Start()
	{
		try
		{
			getLastInteractable = ReflectionHelper.CreatePrivateFieldGetter<PlayerController, IPlayerInteractable>("m_lastInteractionTarget");
		}
		catch (Exception arg)
		{
			StaticLogger.LogInfo($"Cannot inspect player interactions: {arg}");
		}
	}

	private void Update()
	{
		TimeCounter -= Time.deltaTime;
		if (!(TimeCounter <= 0f))
		{
			return;
		}
		TimeCounter = TimeBetweenChecks;
		try
		{
			bool flag = false;
			PlayerController[] allPlayers = GameManager.Instance.AllPlayers;
			foreach (PlayerController val in allPlayers)
			{
				if (val.IsInCombat)
				{
					flag = true;
					break;
				}
				IPlayerInteractable val2 = getLastInteractable(val);
				if (_lastInteractable != val2)
				{
					_lastInteractable = val2;
					LastInteractableChanged?.Invoke(val, _lastInteractable);
					break;
				}
			}
			if (_currentlyInCombat != flag)
			{
				_currentlyInCombat = flag;
				if (flag)
				{
					EnteredCombat?.Invoke();
				}
				else
				{
					ExitedCombat?.Invoke();
				}
			}
		}
		catch (Exception arg)
		{
			StaticLogger.LogDebug($"Error in Update: {arg}");
		}
	}
}
internal delegate void Action<T1, T2, T3, T4, T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
internal delegate void Action<T1, T2, T3, T4, T5, T6>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
internal delegate void Action<T1, T2, T3, T4, T5, T6, T7>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
internal static class ReflectionHelper
{
	private static Type[] ActionDelegateTypes = new Type[8]
	{
		typeof(Action),
		typeof(Action<>),
		typeof(Action<, >),
		typeof(Action<, , >),
		typeof(Action<, , , >),
		typeof(Action<, , , , >),
		typeof(Action<, , , , , >),
		typeof(Action<, , , , , , >)
	};

	private static Type[] FuncDelegateTypes = new Type[5]
	{
		typeof(Func<>),
		typeof(Func<, >),
		typeof(Func<, , >),
		typeof(Func<, , , >),
		typeof(Func<, , , , >)
	};

	public static Func<TTarget, TField> CreatePrivateFieldGetter<TTarget, TField>(string fieldName)
	{
		FieldInfo field = typeof(TTarget).GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
		if ((object)field == null)
		{
			throw new ArgumentException($"Private instance field {fieldName} was not found on {typeof(TTarget)}");
		}
		return (TTarget t) => (TField)field.GetValue(t);
	}

	public static Delegate CreateInstanceDelegate(object source, string name)
	{
		MethodInfo method = source.GetType().GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if ((object)method == null)
		{
			throw new ArgumentException($"Method '{name}' not found on {source.GetType()}");
		}
		Type[] array = (((object)method.ReturnType != typeof(void)) ? FuncDelegateTypes : ActionDelegateTypes);
		ParameterInfo[] parameters = method.GetParameters();
		if (parameters.Length >= array.Length)
		{
			throw new ArgumentException($"Too many parameters for delegate types:{parameters.Length}");
		}
		Type type = array[parameters.Length];
		Type type2;
		if (type.IsGenericType)
		{
			List<Type> list = new List<Type>(parameters.Select((ParameterInfo p) => p.ParameterType));
			if ((object)method.ReturnType == typeof(void))
			{
				type2 = type.MakeGenericType(list.ToArray());
			}
			else
			{
				list.Add(method.ReturnType);
				type2 = type.MakeGenericType(list.ToArray());
			}
		}
		else
		{
			type2 = type;
		}
		return Delegate.CreateDelegate(type2, source, method);
	}
}
public class Settings
{
	public int LineWidth = 40;

	public Vector2 GetSize(int linesHeight)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		return new Vector2(11f * (float)LineWidth, 32f * (float)linesHeight);
	}
}
internal static class StaticLogger
{
	public static ManualLogSource Source;

	public static void LogInfo(string message)
	{
		ManualLogSource source = Source;
		if (source != null)
		{
			source.LogInfo((object)message);
		}
	}

	public static void LogDebug(string message)
	{
		ManualLogSource source = Source;
		if (source != null)
		{
			source.LogDebug((object)message);
		}
	}

	public static void LogDebug<T>(string format, T arg)
	{
		ManualLogSource source = Source;
		if (source != null)
		{
			source.LogDebug((object)string.Format(format, arg));
		}
	}

	public static void LogDebug(string format, params object[] args)
	{
		ManualLogSource source = Source;
		if (source != null)
		{
			source.LogDebug((object)string.Format(format, args));
		}
	}

	public static void LogError(string format, params object[] args)
	{
		ManualLogSource source = Source;
		if (source != null)
		{
			source.LogError((object)string.Format(format, args));
		}
	}
}
internal static class SynergyDataExtensions
{
	public static string GetLocalizedSynergyName(this SynergyData synergy)
	{
		if (synergy.Key == null)
		{
			return synergy.Name;
		}
		string synergyString = StringTableManager.GetSynergyString(synergy.Key, -1);
		if (string.IsNullOrEmpty(synergyString))
		{
			StaticLogger.LogDebug("Did not get localized name for " + synergy.Key);
			return synergy.Key;
		}
		return synergyString;
	}
}
internal class SynergyManagerMonitorBehaviour : MonoBehaviour
{
	public ItemTipsModule ItemTips;

	private void Update()
	{
		if ((Object)(object)ItemTips != (Object)null)
		{
			ItemTips.CheckForSynergyManagerChanges();
		}
	}
}
internal struct TextInfo
{
	public readonly string LabelText;

	public readonly Vector2 LabelSize;

	public TextInfo(string text, Vector2 size)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		LabelText = text;
		LabelSize = size;
	}
}
internal static class TipBuilder
{
	public static void AppendQualityDescriptor(PickupObject pickup, Action<string> appendLine)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Invalid comparison between Unknown and I4
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Invalid comparison between Unknown and I4
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		if ((int)pickup.quality != 0 && (int)pickup.quality != -100 && (int)pickup.quality != -50)
		{
			if (pickup.ItemSpansBaseQualityTiers || pickup.ItemRespectsHeartMagnificence)
			{
				appendLine("Quality: C/B/A");
			}
			else
			{
				appendLine($"Quality: {pickup.quality}");
			}
		}
	}

	public static void AppendActiveCooldownType(PickupObject pickup, Action<string> appendLine)
	{
		PlayerItem val = (PlayerItem)(object)((pickup is PlayerItem) ? pickup : null);
		if (val != null)
		{
			if (val.roomCooldown > 0)
			{
				appendLine("Cooldown: Room");
			}
			else if (val.damageCooldown > 0f)
			{
				appendLine("Cooldown: Damage");
			}
			else if (val.timeCooldown > 0f)
			{
				appendLine("Cooldown: Time");
			}
		}
	}

	public static void AppendModifiers(PickupObject pickup, Action<StatType, string> appendLine)
	{
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Invalid comparison between Unknown and I4
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Invalid comparison between Unknown and I4
		List<StatModifier> list = new List<StatModifier>();
		Gun val = (Gun)(object)((pickup is Gun) ? pickup : null);
		if (val == null)
		{
			BasicStatPickup val2 = (BasicStatPickup)(object)((pickup is BasicStatPickup) ? pickup : null);
			if (val2 == null)
			{
				PassiveItem val3 = (PassiveItem)(object)((pickup is PassiveItem) ? pickup : null);
				if (val3 == null)
				{
					PlayerItem val4 = (PlayerItem)(object)((pickup is PlayerItem) ? pickup : null);
					if (val4 == null)
					{
						StaticLogger.LogDebug("Could not get stat modifiers: " + pickup.EncounterNameOrDisplayName);
						return;
					}
					if (val4.passiveStatModifiers != null)
					{
						list.AddRange(val4.passiveStatModifiers);
					}
				}
				else if (val3.passiveStatModifiers != null)
				{
					list.AddRange(val3.passiveStatModifiers);
				}
			}
			else
			{
				if (((PassiveItem)val2).passiveStatModifiers != null)
				{
					list.AddRange(((PassiveItem)val2).passiveStatModifiers);
				}
				if (val2.modifiers != null)
				{
					list.AddRange(val2.modifiers);
				}
			}
		}
		else if (val.passiveStatModifiers != null)
		{
			list.AddRange(val.passiveStatModifiers);
		}
		if (list.Count <= 0)
		{
			return;
		}
		float num = 0f;
		float num2 = 0f;
		foreach (StatModifier item in list)
		{
			if ((int)item.statToBoost == 14)
			{
				num += item.amount;
			}
			else if ((int)item.statToBoost == 4)
			{
				num2 += item.amount;
			}
		}
		if (num > 0f)
		{
			appendLine((StatType)14, $"Curse: +{num}");
		}
		if (num2 > 0f)
		{
			appendLine((StatType)4, $"Coolness: +{num2}");
		}
	}
}
public enum TipSource
{
	Gun,
	ActiveItem,
	PassiveItem,
	ShopItem,
	RewardPedestal,
	ChestPredicted
}