Decompiled source of ItemMagnet v0.1.0

ItemMagnet.dll

Decompiled 2 days 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.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("ItemMagnet")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ce1fe04c1e0d3a2923c660dc5676ceccf87de5a5")]
[assembly: AssemblyProduct("ItemMagnet")]
[assembly: AssemblyTitle("ItemMagnet")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace OdinsMissingPatch
{
	[BepInPlugin("rauschekuh.itemmagnet", "Item Magnet", "0.1.0")]
	public class ItemMagnetPlugin : BaseUnityPlugin
	{
		public const string GUID = "rauschekuh.itemmagnet";

		public const string NAME = "Item Magnet";

		public const string VERSION = "0.1.0";

		private static readonly Tweak[] Tweaks = new Tweak[1] { ItemMagnet.Instance };

		private void Awake()
		{
			TweakHost.Start((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, ((BaseUnityPlugin)this).Config, "rauschekuh.itemmagnet", Tweaks, delegate(ConfigFile config)
			{
				Danger.Bind(config, "the item magnet cannot be used.");
			});
		}
	}
	internal static class MovedMarker
	{
		[HarmonyPatch(typeof(ItemDrop), "OnPlayerDrop")]
		[Serves(new Type[] { typeof(ItemMagnet) })]
		private static class MarkPlayerDrop
		{
			private static void Postfix(ItemDrop __instance)
			{
				Mark(__instance);
			}
		}

		[HarmonyPatch(typeof(ItemDrop), "AutoStackItems")]
		[Serves(new Type[] { typeof(ItemMagnet) })]
		private static class KeepMarkWhenMerged
		{
			private static bool Prefix(ItemDrop __instance)
			{
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				if (!ItemMagnet.Instance.On)
				{
					return true;
				}
				ItemData itemData = __instance.m_itemData;
				if (itemData.m_shared.m_maxStackSize <= 1 || itemData.m_stack >= itemData.m_shared.m_maxStackSize || __instance.m_haveAutoStacked)
				{
					return false;
				}
				__instance.m_haveAutoStacked = true;
				if (ItemDrop.s_itemMask == 0)
				{
					ItemDrop.s_itemMask = LayerMask.GetMask(new string[1] { "item" });
				}
				bool flag = false;
				bool flag2 = false;
				Collider[] array = Physics.OverlapSphere(((Component)__instance).transform.position, 4f, ItemDrop.s_itemMask);
				foreach (Collider val in array)
				{
					if (!Object.op_Implicit((Object)(object)val.attachedRigidbody))
					{
						continue;
					}
					ItemDrop component = ((Component)val.attachedRigidbody).GetComponent<ItemDrop>();
					if (!((Object)(object)component == (Object)null) && !((Object)(object)component == (Object)(object)__instance) && component.m_itemData.m_shared.m_autoStack && !((Object)(object)component.m_nview == (Object)null) && component.m_nview.IsValid() && component.m_nview.IsOwner() && !(component.m_itemData.m_shared.m_name != itemData.m_shared.m_name) && component.m_itemData.m_quality == itemData.m_quality)
					{
						int num = itemData.m_shared.m_maxStackSize - itemData.m_stack;
						if (num == 0)
						{
							break;
						}
						if (component.m_itemData.m_stack <= num)
						{
							itemData.m_stack += component.m_itemData.m_stack;
							flag = true;
							flag2 |= IsMoved(component);
							component.m_nview.Destroy();
						}
					}
				}
				if (flag)
				{
					__instance.Save();
				}
				if (flag2)
				{
					Mark(__instance);
				}
				return false;
			}
		}

		internal static readonly int Key = StringExtensionMethods.GetStableHashCode("omp_moved");

		internal static bool IsMoved(ItemDrop item)
		{
			ZDO val = (((Object)(object)item.m_nview != (Object)null && item.m_nview.IsValid()) ? item.m_nview.GetZDO() : null);
			if (val != null)
			{
				return val.GetBool(Key, false);
			}
			return false;
		}

		internal static void Mark(ItemDrop item)
		{
			ZNetView nview = item.m_nview;
			if ((Object)(object)nview != (Object)null && nview.IsValid() && nview.IsOwner())
			{
				nview.GetZDO().Set(Key, true);
			}
		}
	}
	internal sealed class ItemMagnet : Tweak
	{
		[HarmonyPatch(typeof(Player), "Update")]
		private static class Hotkey
		{
			private static void Postfix(Player __instance)
			{
				if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && (Instance.On || Instance.channeling))
				{
					Instance.Tick(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(CharacterAnimEvent), "GPower")]
		private static class HoldPose
		{
			private static bool Prefix(CharacterAnimEvent __instance)
			{
				Character character = __instance.m_character;
				Player val = (Player)(object)((character is Player) ? character : null);
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val != (Object)(object)Player.m_localPlayer))
				{
					return !Instance.TakeGPowerEvent(val);
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Player), "SetControls")]
		private static class StandStill
		{
			private static void Prefix(Player __instance, ref Vector3 movedir, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold, ref bool block, ref bool blockHold, ref bool jump, ref bool crouch, ref bool run, ref bool autoRun, ref bool dodge)
			{
				//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)
				if (Instance.channeling && !((Object)(object)__instance != (Object)(object)Instance.channeler))
				{
					movedir = Vector3.zero;
					attack = (attackHold = (secondaryAttack = (secondaryAttackHold = false)));
					block = (blockHold = (jump = (crouch = (run = (autoRun = (dodge = false))))));
				}
			}
		}

		[HarmonyPatch(typeof(Player), "AutoPickup")]
		private static class PullItems
		{
			private static void Postfix(Player __instance, float dt)
			{
				if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
				{
					Instance.Pull(__instance, dt);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "LateUpdate")]
		private static class FloatPose
		{
			private static void Postfix(Player __instance)
			{
				if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
				{
					Instance.Float(__instance);
				}
			}
		}

		internal static readonly ItemMagnet Instance = new ItemMagnet();

		private const float PullSpeed = 15f;

		private const float ArriveDistance = 1f;

		private const float SettleTime = 4f;

		private const float HoldSpeed = 0.03f;

		private const float PoseTimeout = 3f;

		private const float FxInterval = 2f;

		private const float Lift = 0.35f;

		private const float Bob = 0.06f;

		private const float LiftSpeed = 0.8f;

		private const float SwayDegrees = 5f;

		private const float SwayFadeTime = 1f;

		private ConfigEntry<KeyboardShortcut> hotkey;

		private ConfigEntry<float> baseRadius;

		private ConfigEntry<float> radiusPerSecond;

		private ConfigEntry<float> maxRadius;

		private Player channeler;

		private bool channeling;

		private float channelStart;

		private float swallowPowerUntil;

		private float settleUntil;

		private float lastFx;

		private bool posed;

		private int waiting;

		private readonly List<ItemDrop> pulling = new List<ItemDrop>();

		private readonly HashSet<ItemDrop> pullingSet = new HashSet<ItemDrop>();

		private Transform liftedVisual;

		private Vector3 visualRest;

		private float lift;

		private EffectList activationFx;

		private ObjectDB activationFxSource;

		internal override string Section => "Item Magnet";

		internal override Type[] Uses => new Type[1] { typeof(Danger) };

		protected override string Summary => "Hold a key to pull the items lying around you to your feet, in a ring that grows the longer you hold it. Only out of combat, and an item that was moved once - pulled or dropped by a player - is never pulled again.";

		private float Radius
		{
			get
			{
				if (!channeling)
				{
					return 0f;
				}
				return RadiusAfter(Time.time - channelStart);
			}
		}

		private ItemMagnet()
		{
		}

		protected override void Bind(ConfigFile config)
		{
			//IL_0014: 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_005d: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			hotkey = config.Bind<KeyboardShortcut>(Section, "Hotkey", new KeyboardShortcut((KeyCode)121, Array.Empty<KeyCode>()), "Hold to pull. Let go to stop.");
			baseRadius = config.Bind<float>(Section, "BaseRadius", 10f, new ConfigDescription("Metres. How far the pull reaches after holding the key for one second.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>()));
			radiusPerSecond = config.Bind<float>(Section, "RadiusPerSecond", 5f, new ConfigDescription("Metres the reach grows by for every further second the key is held.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
			maxRadius = config.Bind<float>(Section, "MaxRadius", 60f, new ConfigDescription("Metres. The reach stops growing here. Items much further away than this are often not loaded on your machine at all.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>()));
		}

		private float RadiusAfter(float seconds)
		{
			return Mathf.Clamp(baseRadius.Value + radiusPerSecond.Value * (seconds - 1f), 0f, maxRadius.Value);
		}

		private void Tick(Player player)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)channeler != (Object)null && (Object)(object)channeler != (Object)(object)player)
			{
				Forget();
			}
			if (channeling)
			{
				if (!base.On || !Hotkeys.Held(hotkey.Value) || !CanKeepChanneling(player))
				{
					End(player);
					return;
				}
				Sway(player);
				PlayFx(player);
			}
			else if (base.On && ((Character)player).TakeInput() && Hotkeys.Pressed(hotkey.Value))
			{
				TryStart(player);
			}
		}

		private static bool CanPose(Player player)
		{
			if (!((Character)player).IsDead() && (!((Character)player).InAttack() || ((Humanoid)player).HaveQueuedChain()) && !((Character)player).InDodge() && ((Character)player).CanMove() && !((Character)player).IsKnockedBack() && !((Character)player).IsStaggering() && !((Character)player).InMinorAction() && ((Character)player).IsOnGround() && !((Character)player).IsSwimming() && !((Character)player).IsAttached() && !((Character)player).IsTeleporting())
			{
				return !((Character)player).InPlaceMode();
			}
			return false;
		}

		private void TryStart(Player player)
		{
			if (CanPose(player))
			{
				if (Danger.Near(player))
				{
					((Character)player).Message((MessageType)2, "$omp_magnet_danger", 0, (Sprite)null, false);
					return;
				}
				channeler = player;
				channeling = true;
				channelStart = Time.time;
				swallowPowerUntil = Time.time + 3f;
				lastFx = float.NegativeInfinity;
				posed = false;
				((Character)player).m_zanim.SetTrigger("gpower");
			}
		}

		private bool CanKeepChanneling(Player player)
		{
			if (((Character)player).IsDead() || ((Character)player).IsStaggering() || ((Character)player).IsKnockedBack() || ((Character)player).IsSwimming() || ((Character)player).IsAttached() || ((Character)player).IsTeleporting() || !((Character)player).TakeInput())
			{
				return false;
			}
			if (Danger.Near(player))
			{
				((Character)player).Message((MessageType)2, "$omp_magnet_danger", 0, (Sprite)null, false);
				return false;
			}
			return true;
		}

		private void End(Player player)
		{
			channeling = false;
			settleUntil = Time.time + 4f;
			if ((Object)(object)player != (Object)null && (Object)(object)((Character)player).m_zanim != (Object)null)
			{
				((Character)player).m_zanim.SetSpeed(1f);
			}
		}

		private void Forget()
		{
			channeler = null;
			channeling = false;
			swallowPowerUntil = 0f;
			pulling.Clear();
			pullingSet.Clear();
			liftedVisual = null;
			lift = 0f;
		}

		private bool TakeGPowerEvent(Player player)
		{
			if ((Object)(object)player != (Object)(object)channeler || Time.time > swallowPowerUntil)
			{
				return false;
			}
			swallowPowerUntil = 0f;
			if (channeling)
			{
				posed = true;
				((Character)player).m_zanim.SetSpeed(0.03f);
			}
			return true;
		}

		private void Pull(Player player, float dt)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player != (Object)(object)channeler || (!channeling && pulling.Count == 0))
			{
				return;
			}
			Vector3 position = ((Component)player).transform.position;
			if (channeling)
			{
				Capture(player, position, Radius);
			}
			for (int num = pulling.Count - 1; num >= 0; num--)
			{
				ItemDrop val = pulling[num];
				if ((Object)(object)val == (Object)null || (Object)(object)val.m_nview == (Object)null || !val.m_nview.IsValid() || !val.m_nview.IsOwner() || FlyHome(val, position, dt))
				{
					pullingSet.Remove(val);
					pulling.RemoveAt(num);
				}
			}
			if (channeling && waiting == 0 && pulling.Count == 0 && (posed || Time.time - channelStart > 3f))
			{
				End(player);
			}
			if (!channeling && Time.time > settleUntil)
			{
				pulling.Clear();
				pullingSet.Clear();
			}
		}

		private void Capture(Player player, Vector3 feet, float radius)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//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_0075: Unknown result type (might be due to invalid IL or missing references)
			waiting = 0;
			float num = radius * radius;
			float num2 = maxRadius.Value * maxRadius.Value;
			foreach (ItemDrop s_instance in ItemDrop.s_instances)
			{
				if ((Object)(object)s_instance == (Object)null || pullingSet.Contains(s_instance))
				{
					continue;
				}
				Vector3 offset = ((Component)s_instance).transform.position - feet;
				if (!(((Vector3)(ref offset)).sqrMagnitude > num2) && !(Horizontal(offset) <= 1f) && Pullable(player, s_instance))
				{
					if (((Vector3)(ref offset)).sqrMagnitude > num)
					{
						waiting++;
					}
					else if (!s_instance.m_nview.IsOwner())
					{
						s_instance.RequestOwn();
						waiting++;
					}
					else
					{
						MovedMarker.Mark(s_instance);
						pulling.Add(s_instance);
						pullingSet.Add(s_instance);
					}
				}
			}
		}

		private static bool Pullable(Player player, ItemDrop item)
		{
			if ((Object)(object)item.m_nview != (Object)null && item.m_nview.IsValid() && item.m_autoPickup && !item.IsPiece() && !item.InTar() && !MovedMarker.IsMoved(item))
			{
				return !((Humanoid)player).HaveUniqueKey(item.m_itemData.m_shared.m_name);
			}
			return false;
		}

		private static bool FlyHome(ItemDrop item, Vector3 feet, float dt)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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)
			Vector3 position = ((Component)item).transform.position;
			Vector3 val = feet + Vector3.up * 0.5f - position;
			if (Horizontal(val) <= 1f)
			{
				return true;
			}
			Vector3 val2 = position + Vector3.ClampMagnitude(val, 15f * dt);
			float num = (((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.GetGroundHeight(val2) : val2.y);
			val2.y = Mathf.Max(val2.y, num + 0.3f);
			((Component)item).transform.position = val2;
			Rigidbody body = item.m_body;
			if ((Object)(object)body != (Object)null)
			{
				body.linearVelocity = Vector3.zero;
			}
			return false;
		}

		private static float Horizontal(Vector3 offset)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = new Vector2(offset.x, offset.z);
			return ((Vector2)(ref val)).magnitude;
		}

		private void Sway(Player player)
		{
			//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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)((Character)player).m_eye == (Object)null))
			{
				float num = Mathf.Clamp01((Time.time - channelStart) / 1f);
				float num2 = Mathf.Max(0.05f, 1f - Mathf.Abs(Vector3.Dot(((Character)player).m_eye.forward, Vector3.up)));
				float num3 = Time.deltaTime * Mathf.Cos(Time.realtimeSinceStartup * 0.3f) * 5f * num * num2;
				((Character)player).m_lookYaw = ((Character)player).m_lookYaw * Quaternion.Euler(0f, num3, 0f);
				((Character)player).UpdateEyeRotation();
				((Character)player).m_lookDir = ((Character)player).m_eye.forward;
			}
		}

		private void PlayFx(Player player)
		{
			//IL_002b: 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_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)
			if (!(Time.time - lastFx < 2f))
			{
				lastFx = Time.time;
				EffectList val = ActivationFx();
				if (val != null)
				{
					val.Create(((Character)player).GetCenterPoint(), ((Component)player).transform.rotation, ((Component)player).transform, 1f, -1, default(ZDOID));
				}
			}
		}

		private EffectList ActivationFx()
		{
			ObjectDB instance = ObjectDB.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			if ((Object)(object)activationFxSource != (Object)(object)instance)
			{
				activationFxSource = instance;
				activationFx = null;
				foreach (StatusEffect statusEffect in instance.m_StatusEffects)
				{
					if ((Object)(object)statusEffect != (Object)null && ((Object)statusEffect).name.StartsWith("GP_") && statusEffect.m_startEffects != null && statusEffect.m_startEffects.HasEffects())
					{
						activationFx = statusEffect.m_startEffects;
						break;
					}
				}
			}
			return activationFx;
		}

		private void Float(Player player)
		{
			//IL_00b8: 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_00c8: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player != (Object)(object)channeler)
			{
				return;
			}
			float num = (channeling ? (0.35f + Mathf.Sin(Time.time * 2f) * 0.06f) : 0f);
			if (lift == 0f && num == 0f)
			{
				return;
			}
			Transform val = (((Object)(object)((Character)player).m_visual != (Object)null) ? ((Character)player).m_visual.transform : null);
			if (!((Object)(object)val == (Object)null))
			{
				if ((Object)(object)liftedVisual != (Object)(object)val)
				{
					liftedVisual = val;
					visualRest = val.localPosition;
				}
				lift = Mathf.MoveTowards(lift, num, 0.8f * Time.deltaTime);
				val.localPosition = visualRest + Vector3.up * lift;
				if (lift == 0f)
				{
					liftedVisual = null;
				}
			}
		}
	}
	internal static class Danger
	{
		[HarmonyPatch(typeof(Player), "RPC_OnTargeted")]
		[Serves(new Type[] { typeof(Danger) })]
		private static class NoticeEnragedEnemy
		{
			private static void Postfix(Player __instance, bool alerted)
			{
				if (alerted && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
				{
					lastEnraged = Time.time;
				}
			}
		}

		private const float CheckInterval = 0.25f;

		private const float EnragedMemory = 1.5f;

		internal const string Section = "General";

		internal static ConfigEntry<float> ThreatRadius;

		internal static ConfigEntry<bool> EnragedEnemies;

		internal static ConfigEntry<bool> BossFights;

		private static float lastCheck = float.NegativeInfinity;

		private static bool inDanger;

		private static float lastEnraged = float.NegativeInfinity;

		internal static void Bind(ConfigFile config, string effect)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			ThreatRadius = config.Bind<float>("General", "ThreatRadius", 25f, new ConfigDescription("Metres. A hostile creature closer than this puts you in combat, whether it has noticed you or not: " + effect, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 200f), Array.Empty<object>()));
			EnragedEnemies = config.Bind<bool>("General", "EnragedEnemies", true, "An enemy that has noticed you and is coming for you puts you in combat at any distance, not only inside ThreatRadius. Off means only the radius counts.");
			BossFights = config.Bind<bool>("General", "BossFights", true, "A boss health bar on screen puts you in combat, whoever the boss is after and however far away it is.");
		}

		internal static bool Near(Player player)
		{
			if (Time.time - lastCheck < 0.25f)
			{
				return inDanger;
			}
			lastCheck = Time.time;
			inDanger = Enraged() || BossBarShowing() || HostileWithin(player, ThreatRadius.Value);
			return inDanger;
		}

		private static bool Enraged()
		{
			if (EnragedEnemies.Value)
			{
				return Time.time - lastEnraged < 1.5f;
			}
			return false;
		}

		private static bool BossBarShowing()
		{
			if (BossFights.Value && (Object)(object)EnemyHud.instance != (Object)null)
			{
				return EnemyHud.instance.ShowingBossHud();
			}
			return false;
		}

		private static bool HostileWithin(Player player, float radius)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)player).transform.position;
			float num = radius * radius;
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (!((Object)(object)allCharacter == (Object)null) && !((Object)(object)allCharacter == (Object)(object)player) && !allCharacter.IsDead() && BaseAI.IsEnemy((Character)(object)player, allCharacter))
				{
					Vector3 val = ((Component)allCharacter).transform.position - position;
					if (((Vector3)(ref val)).sqrMagnitude <= num)
					{
						return true;
					}
				}
			}
			return false;
		}
	}
	internal static class FavoriteMark
	{
		internal const string Key = "OMP_Favorite";

		internal static bool IsSet(ItemData item)
		{
			if (item != null && item.m_customData != null && item.m_customData.TryGetValue("OMP_Favorite", out var value))
			{
				return value == "1";
			}
			return false;
		}
	}
	internal static class Hotkeys
	{
		internal static bool Pressed(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !ZInput.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey, false))
			{
				return false;
			}
			return ModifiersHeld(shortcut);
		}

		internal static bool Held(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !ZInput.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey, false))
			{
				return false;
			}
			return ModifiersHeld(shortcut);
		}

		internal static string Describe(params KeyboardShortcut[] chord)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			for (int i = 0; i < chord.Length; i++)
			{
				KeyboardShortcut val = chord[i];
				if ((int)((KeyboardShortcut)(ref val)).MainKey == 0)
				{
					continue;
				}
				foreach (KeyCode modifier in ((KeyboardShortcut)(ref val)).Modifiers)
				{
					list.Add(KeyName(modifier));
				}
				list.Add(KeyName(((KeyboardShortcut)(ref val)).MainKey));
			}
			return string.Join(" + ", list.ToArray());
		}

		private unsafe static string KeyName(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			string text = ZInput.KeyCodeToDisplayName(key);
			if (!string.IsNullOrEmpty(text) && !text.StartsWith("$"))
			{
				return text;
			}
			return ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString();
		}

		private static bool ModifiersHeld(KeyboardShortcut shortcut)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
			{
				if (!ZInput.GetKey(modifier, false))
				{
					return false;
				}
			}
			return true;
		}
	}
	internal static class LegacyConfig
	{
		private const string OldFile = "rauschekuh.odinsmissingpatch.cfg";

		internal static HashSet<string> Sections(string path)
		{
			HashSet<string> hashSet = new HashSet<string>();
			try
			{
				if (File.Exists(path))
				{
					foreach (ConfigDefinition key in Read(path).Keys)
					{
						hashSet.Add(key.Section);
					}
				}
			}
			catch (Exception ex)
			{
				TweakHost.Log.LogWarning((object)("could not read " + path + ": " + ex.Message));
			}
			return hashSet;
		}

		internal static void Import(ConfigFile config, HashSet<string> known)
		{
			try
			{
				string path = Path.Combine(Paths.ConfigPath, "rauschekuh.odinsmissingpatch.cfg");
				if (!File.Exists(path))
				{
					return;
				}
				Dictionary<ConfigDefinition, string> dictionary = Read(path);
				int num = 0;
				foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in config)
				{
					if (!known.Contains(item.Key.Section) && dictionary.TryGetValue(item.Key, out var value))
					{
						item.Value.SetSerializedValue(value);
						num++;
					}
				}
				if (num > 0)
				{
					config.Save();
					TweakHost.Log.LogInfo((object)("took " + num + " setting(s) over from rauschekuh.odinsmissingpatch.cfg"));
				}
			}
			catch (Exception ex)
			{
				TweakHost.Log.LogWarning((object)("could not read the settings of rauschekuh.odinsmissingpatch.cfg: " + ex.Message));
			}
		}

		private static Dictionary<ConfigDefinition, string> Read(string path)
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Expected O, but got Unknown
			Dictionary<ConfigDefinition, string> dictionary = new Dictionary<ConfigDefinition, string>();
			string text = "";
			string[] array = File.ReadAllLines(path);
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (text2.Length == 0 || text2.StartsWith("#"))
				{
					continue;
				}
				if (text2.StartsWith("[") && text2.EndsWith("]"))
				{
					text = text2.Substring(1, text2.Length - 2);
					continue;
				}
				int num = text2.IndexOf('=');
				if (num > 0 && text.Length > 0)
				{
					dictionary[new ConfigDefinition(text, text2.Substring(0, num).Trim())] = text2.Substring(num + 1).Trim();
				}
			}
			return dictionary;
		}
	}
	internal static class Palette
	{
		internal static readonly Color Gold = new Color(1f, 0.8f, 0.3f, 1f);

		internal static readonly Color ChestYellow = new Color(1f, 0.84f, 0.3f, 1f);

		internal const string ChestYellowTag = "<color=#ffd64d>";
	}
	[AttributeUsage(AttributeTargets.Class)]
	internal sealed class ServesAttribute : Attribute
	{
		internal readonly Type[] Tweaks;

		public bool Optional { get; set; }

		public ServesAttribute(params Type[] tweaks)
		{
			Tweaks = tweaks;
		}
	}
	[AttributeUsage(AttributeTargets.Class)]
	internal sealed class AlwaysAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class)]
	internal sealed class LoadHookAttribute : Attribute
	{
	}
	internal static class Patcher
	{
		private sealed class PatchClass
		{
			internal Type Type;

			internal Tweak[] Serves;

			internal bool Optional;

			internal bool LoadHook;

			internal bool Applied;

			internal bool Failed;
		}

		private static readonly List<PatchClass> classes = new List<PatchClass>();

		private static Harmony harmony;

		private static ManualLogSource log;

		internal static void Map(IList<Tweak> tweaks, ManualLogSource logSource)
		{
			log = logSource;
			Dictionary<Type, Tweak> byType = tweaks.ToDictionary((Tweak t) => t.GetType());
			Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(Assembly.GetExecutingAssembly());
			foreach (Type type in typesFromAssembly)
			{
				if (!type.IsDefined(typeof(HarmonyPatch), inherit: false))
				{
					continue;
				}
				Tweak[] array = Owners(type, byType);
				if (array != null)
				{
					classes.Add(new PatchClass
					{
						Type = type,
						Serves = array,
						Optional = type.GetCustomAttributes(typeof(ServesAttribute), inherit: false).Cast<ServesAttribute>().Any((ServesAttribute s) => s.Optional),
						LoadHook = type.IsDefined(typeof(LoadHookAttribute), inherit: false)
					});
				}
			}
		}

		private static Tweak[] Owners(Type type, Dictionary<Type, Tweak> byType)
		{
			if (type.IsDefined(typeof(AlwaysAttribute), inherit: false))
			{
				return new Tweak[0];
			}
			ServesAttribute servesAttribute = (ServesAttribute)type.GetCustomAttributes(typeof(ServesAttribute), inherit: false).FirstOrDefault();
			if (servesAttribute != null)
			{
				List<Tweak> list = new List<Tweak>();
				Type[] tweaks = servesAttribute.Tweaks;
				foreach (Type tweak in tweaks)
				{
					if (byType.TryGetValue(tweak, out var value))
					{
						list.Add(value);
						continue;
					}
					if (typeof(Tweak).IsAssignableFrom(tweak))
					{
						log.LogWarning((object)(type.FullName + " serves " + tweak.Name + ", which is not in the Tweaks list"));
						continue;
					}
					list.AddRange(byType.Values.Where((Tweak t) => t.Uses.Contains(tweak)));
				}
				if (list.Count <= 0)
				{
					return null;
				}
				return list.Distinct().ToArray();
			}
			Type declaringType = type.DeclaringType;
			while (declaringType != null)
			{
				if (byType.TryGetValue(declaringType, out var value2))
				{
					return new Tweak[1] { value2 };
				}
				declaringType = declaringType.DeclaringType;
			}
			log.LogWarning((object)(type.FullName + " belongs to no tweak and names none, so it is always applied"));
			return new Tweak[0];
		}

		internal static bool AnyServedOn(Type patchClass)
		{
			foreach (PatchClass @class in classes)
			{
				if (@class.Type != patchClass)
				{
					continue;
				}
				Tweak[] serves = @class.Serves;
				for (int i = 0; i < serves.Length; i++)
				{
					if (serves[i].On)
					{
						return true;
					}
				}
				return false;
			}
			return false;
		}

		internal static bool MayNeedRestart(Tweak tweak)
		{
			return classes.Any((PatchClass c) => c.LoadHook && c.Serves.Contains(tweak));
		}

		internal static void Apply(Harmony instance, IList<Tweak> tweaks)
		{
			harmony = instance;
			foreach (PatchClass @class in classes)
			{
				if (@class.Serves.Length == 0 || @class.Serves.Any((Tweak t) => t.Wanted && !t.Broken))
				{
					TryApply(@class);
				}
			}
			foreach (Tweak tweak in tweaks)
			{
				if (tweak.Wanted && !tweak.Broken)
				{
					GoLive(tweak);
				}
				tweak.Enabled.SettingChanged += delegate
				{
					SwitchedOn(tweak);
				};
			}
		}

		private static void SwitchedOn(Tweak tweak)
		{
			if (!tweak.Wanted || tweak.Patched || tweak.Broken)
			{
				return;
			}
			List<PatchClass> list = classes.Where((PatchClass c) => c.Serves.Contains(tweak) && !c.Applied && !c.Failed).ToList();
			if (list.Any((PatchClass c) => c.LoadHook))
			{
				log.LogInfo((object)(tweak.Section + " was off at launch and takes effect at the next start of the game"));
				return;
			}
			foreach (PatchClass item in list)
			{
				TryApply(item);
			}
			if (!tweak.Broken)
			{
				GoLive(tweak);
				log.LogInfo((object)(tweak.Section + " switched on"));
			}
		}

		private static void GoLive(Tweak tweak)
		{
			tweak.Patched = true;
			tweak.Refresh();
		}

		private static void TryApply(PatchClass patch)
		{
			try
			{
				harmony.CreateClassProcessor(patch.Type).Patch();
				patch.Applied = true;
			}
			catch (Exception ex)
			{
				patch.Failed = true;
				Unpatch(patch);
				string message = (ex.InnerException ?? ex).Message;
				if (patch.Serves.Length == 0 || patch.Optional)
				{
					log.LogError((object)(patch.Type.FullName + " could not be patched, carrying on without it: " + message));
					return;
				}
				Tweak[] serves = patch.Serves;
				for (int i = 0; i < serves.Length; i++)
				{
					Break(serves[i], patch.Type, message);
				}
			}
		}

		private static void Break(Tweak tweak, Type failed, string cause)
		{
			if (tweak.Broken)
			{
				return;
			}
			tweak.Broken = true;
			tweak.Patched = false;
			log.LogError((object)(tweak.Section + " is switched off: " + failed.FullName + " could not be patched, most likely because a game update changed it. " + cause));
			foreach (PatchClass @class in classes)
			{
				if (@class.Applied && @class.Serves.Contains(tweak) && !@class.Serves.Any((Tweak t) => !t.Broken && (t.Patched || t.Wanted)))
				{
					Unpatch(@class);
					@class.Applied = false;
				}
			}
			tweak.Refresh();
		}

		private static void Unpatch(PatchClass patch)
		{
			try
			{
				foreach (MethodBase item in harmony.GetPatchedMethods().ToList())
				{
					Patches patchInfo = Harmony.GetPatchInfo(item);
					if (patchInfo == null)
					{
						continue;
					}
					foreach (Patch item2 in patchInfo.Prefixes.Concat(patchInfo.Postfixes).Concat(patchInfo.Transpilers).Concat(patchInfo.Finalizers)
						.Concat(patchInfo.ILManipulators)
						.ToList())
					{
						if (item2.owner == harmony.Id && item2.PatchMethod.DeclaringType == patch.Type)
						{
							harmony.Unpatch(item, item2.PatchMethod);
						}
					}
				}
			}
			catch (Exception ex)
			{
				log.LogError((object)("could not take out " + patch.Type.FullName + ": " + ex.Message));
			}
		}
	}
	internal static class Translations
	{
		[HarmonyPatch(typeof(Localization), "SetupLanguage")]
		[Always]
		private static class Load
		{
			private static void Postfix(Localization __instance, string language)
			{
				if (__instance == null || !Read() || !Reader())
				{
					return;
				}
				object obj = null;
				try
				{
					obj = textAsset.Invoke(new object[1] { csv });
					loadCsv.Invoke(__instance, new object[2]
					{
						obj,
						Has(language) ? language : "English"
					});
					Revision++;
				}
				catch (Exception ex)
				{
					TweakHost.Log.LogWarning((object)("could not load translations.csv: " + ex.Message));
				}
				finally
				{
					Object val = (Object)((obj is Object) ? obj : null);
					if (val != (Object)null)
					{
						Object.Destroy(val);
					}
				}
			}
		}

		private const string FileName = "translations.csv";

		private const string Fallback = "English";

		private static string csv;

		private static string[] languages;

		private static ConstructorInfo textAsset;

		private static MethodInfo loadCsv;

		private static bool looked;

		internal static int Revision { get; private set; }

		private static bool Read()
		{
			if (languages != null)
			{
				return csv != null;
			}
			languages = new string[0];
			try
			{
				string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "translations.csv");
				if (!File.Exists(text))
				{
					TweakHost.Log.LogDebug((object)("no translations.csv beside the DLL: " + text));
					return false;
				}
				csv = File.ReadAllText(text);
				using (StringReader stringReader = new StringReader(csv))
				{
					string text2 = stringReader.ReadLine();
					languages = ((text2 != null) ? text2.Split(new char[1] { ',' }) : new string[0]);
				}
				for (int i = 0; i < languages.Length; i++)
				{
					languages[i] = languages[i].Trim().Trim(new char[1] { '"' });
				}
			}
			catch (Exception ex)
			{
				csv = null;
				TweakHost.Log.LogWarning((object)("could not read translations.csv: " + ex.Message));
			}
			return csv != null;
		}

		private static bool Has(string language)
		{
			string[] array = languages;
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] == language)
				{
					return true;
				}
			}
			return false;
		}

		private static bool Reader()
		{
			if (looked)
			{
				if (loadCsv != null)
				{
					return textAsset != null;
				}
				return false;
			}
			looked = true;
			Type type = Type.GetType("UnityEngine.TextAsset, UnityEngine.CoreModule");
			if (type != null)
			{
				textAsset = type.GetConstructor(new Type[1] { typeof(string) });
				loadCsv = typeof(Localization).GetMethod("LoadCSV", new Type[2]
				{
					type,
					typeof(string)
				});
			}
			if (loadCsv == null || textAsset == null)
			{
				TweakHost.Log.LogWarning((object)"Localization.LoadCSV not found; the mod's words stay untranslated");
				return false;
			}
			return true;
		}
	}
	internal abstract class Tweak
	{
		private const float MinMultiplier = 0.1f;

		private const float MaxMultiplier = 20f;

		private const string RestartNote = " If it was off when the game started, switching it on may only take effect after a restart.";

		private ConfigEntry<bool> enabled;

		private readonly List<Action> settingHandlers = new List<Action>();

		internal abstract string Section { get; }

		protected abstract string Summary { get; }

		internal virtual Type[] Uses => Type.EmptyTypes;

		internal bool On
		{
			get
			{
				if (Patched)
				{
					return Wanted;
				}
				return false;
			}
		}

		internal bool Wanted
		{
			get
			{
				if (enabled != null)
				{
					return enabled.Value;
				}
				return false;
			}
		}

		internal ConfigEntry<bool> Enabled => enabled;

		internal bool Patched { get; set; }

		internal bool Broken { get; set; }

		protected virtual void Bind(ConfigFile config)
		{
		}

		internal void Setup(ConfigFile config, bool mayNeedRestart)
		{
			enabled = config.Bind<bool>(Section, "Enabled", true, Summary + (mayNeedRestart ? " If it was off when the game started, switching it on may only take effect after a restart." : ""));
			Bind(config);
		}

		internal void Refresh()
		{
			foreach (Action settingHandler in settingHandlers)
			{
				settingHandler();
			}
		}

		protected ConfigEntry<float> BindMultiplier(ConfigFile config, string key, float value, string description)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			return config.Bind<float>(Section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 20f), Array.Empty<object>()));
		}

		protected ConfigEntry<string> BindList(ConfigFile config, string key, string value, string description, Action<List<string>> apply)
		{
			ConfigEntry<string> entry = config.Bind<string>(Section, key, value, description);
			entry.SettingChanged += delegate
			{
				apply(Items(entry.Value));
			};
			apply(Items(entry.Value));
			return entry;
		}

		internal static List<string> Items(string list)
		{
			List<string> list2 = new List<string>();
			string[] array = (list ?? "").Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length > 0)
				{
					list2.Add(text);
				}
			}
			return list2;
		}

		protected void OnSettingChanged(ConfigFile config, Action handler)
		{
			settingHandlers.Add(handler);
			config.SettingChanged += delegate(object sender, SettingChangedEventArgs args)
			{
				if (args.ChangedSetting.Definition.Section == Section)
				{
					handler();
				}
			};
		}
	}
	internal static class TweakHost
	{
		internal static ManualLogSource Log;

		internal static BaseUnityPlugin Plugin;

		internal static void Start(BaseUnityPlugin plugin, ManualLogSource logger, ConfigFile config, string guid, Tweak[] tweaks, Action<ConfigFile> bindShared = null)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			Plugin = plugin;
			Log = logger;
			HashSet<string> known = LegacyConfig.Sections(config.ConfigFilePath);
			bindShared?.Invoke(config);
			Patcher.Map(tweaks, logger);
			foreach (Tweak tweak in tweaks)
			{
				tweak.Setup(config, Patcher.MayNeedRestart(tweak));
			}
			LegacyConfig.Import(config, known);
			Patcher.Apply(new Harmony(guid), tweaks);
			string text = string.Join(", ", (from t in tweaks
				where t.On
				select t.Section).ToArray());
			logger.LogInfo((object)((text.Length > 0) ? ("tweaks on: " + text) : "every tweak is switched off"));
		}
	}
	internal static class UiAssets
	{
		private static readonly Dictionary<string, Sprite> icons = new Dictionary<string, Sprite>();

		private static MethodInfo loadImage;

		internal static Sprite Icon(string name)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0069: 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)
			if (icons.TryGetValue(name, out var value))
			{
				return value;
			}
			value = null;
			try
			{
				string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
				string text = IconPath(directoryName, name);
				if (text != null)
				{
					Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
					if (LoadPng(val, File.ReadAllBytes(text)))
					{
						((Texture)val).filterMode = (FilterMode)1;
						value = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
					}
				}
				else
				{
					TweakHost.Log.LogWarning((object)("icon missing: " + name + ".png, looked in " + Path.Combine(directoryName, "icons") + " and " + directoryName));
				}
			}
			catch (Exception ex)
			{
				TweakHost.Log.LogWarning((object)("could not load icon " + name + ": " + ex.Message));
			}
			icons[name] = value;
			return value;
		}

		private static string IconPath(string dir, string name)
		{
			string path = name + ".png";
			string[] array = new string[2]
			{
				Path.Combine(Path.Combine(dir, "icons"), path),
				Path.Combine(dir, path)
			};
			foreach (string text in array)
			{
				if (File.Exists(text))
				{
					return text;
				}
			}
			return null;
		}

		private static bool LoadPng(Texture2D texture, byte[] png)
		{
			if (loadImage == null)
			{
				Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule");
				loadImage = ((type != null) ? type.GetMethod("LoadImage", new Type[2]
				{
					typeof(Texture2D),
					typeof(byte[])
				}) : null);
				if (loadImage == null)
				{
					TweakHost.Log.LogWarning((object)"ImageConversion.LoadImage not found; icons stay blank");
					return false;
				}
			}
			return (bool)loadImage.Invoke(null, new object[2] { texture, png });
		}

		internal static GameObject TooltipPrefab(InventoryGui gui)
		{
			InventoryGrid playerGrid = gui.m_playerGrid;
			GameObject val = (((Object)(object)playerGrid != (Object)null) ? playerGrid.m_elementPrefab : null);
			InventoryElement val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<InventoryElement>() : null);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2.m_tooltip != (Object)null && (Object)(object)val2.m_tooltip.m_tooltipPrefab != (Object)null)
			{
				return val2.m_tooltip.m_tooltipPrefab;
			}
			UITooltip[] componentsInChildren = ((Component)gui).GetComponentsInChildren<UITooltip>(true);
			foreach (UITooltip val3 in componentsInChildren)
			{
				if ((Object)(object)val3.m_tooltipPrefab != (Object)null)
				{
					return val3.m_tooltipPrefab;
				}
			}
			return null;
		}
	}
}