Decompiled source of PotatoTweaks v1.5.12

plugins/PotatoTweaks.dll

Decompiled 8 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Common;
using EpicLoot;
using EpicLoot.Adventure;
using EpicLoot.Adventure.Feature;
using EpicLoot.Magic.MagicItemEffects;
using EpicLoot.MagicItemEffects;
using EpicLoot.MagicItemEffects.Shards;
using EpicLoot_UnityLib;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using PotatoTweaks.DoubleBed;
using TMPro;
using Unity.Collections;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace PotatoTweaks
{
	internal static class AttackCancel
	{
		[HarmonyPatch(typeof(Attack), "OnAttackTrigger")]
		internal static class SkipCancelled
		{
			[HarmonyPriority(800)]
			private static bool Prefix(Attack __instance)
			{
				QueuedBowRelease.BeforeTrigger(__instance);
				return !IsCancelled(__instance);
			}

			private static void Postfix(Attack __instance, bool __runOriginal)
			{
				if (__runOriginal && !Landed.TryGetValue(__instance, out var _))
				{
					Landed.Add(__instance, Marker);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "Awake")]
		internal static class Register
		{
			private static void Postfix(Player __instance)
			{
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null)
				{
					component.Register<string>("PotatoTweaks_AttackCancel", (Action<long, string>)delegate(long sender, string animation)
					{
						Interrupt(__instance, animation);
					});
				}
			}
		}

		[HarmonyPatch(typeof(Player), "SetControls")]
		internal static class Controls
		{
			private static void Prefix(Player __instance, out bool __state)
			{
				__state = Blocking.Invoke((Character)(object)__instance);
			}

			private static void Postfix(Player __instance, bool __state)
			{
				if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return;
				}
				if (Plugin.AttackCancelEnabled.Value && !__state && Blocking.Invoke((Character)(object)__instance) && CanCancel(__instance))
				{
					Cancel(__instance);
					holdIgnored = true;
				}
				if (holdIgnored)
				{
					if (!AttackHold.Invoke((Character)(object)__instance) && !SecondaryAttackHold.Invoke((Character)(object)__instance))
					{
						holdIgnored = false;
					}
					AttackHold.Invoke((Character)(object)__instance) = false;
					SecondaryAttackHold.Invoke((Character)(object)__instance) = false;
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "StartAttack")]
		internal static class Waiting
		{
			private static bool Prefix(Humanoid __instance, ref bool __result)
			{
				if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || Time.time >= AttackAllowedAt)
				{
					return true;
				}
				__result = false;
				return false;
			}
		}

		private const float BlendSeconds = 0.1f;

		private const float WindupWait = 0.2f;

		private const string Rpc = "PotatoTweaks_AttackCancel";

		private static readonly int AttackTag = ZSyncAnimation.GetHash("attack");

		private static readonly int Movement = Animator.StringToHash("Base Layer.Movement");

		private static readonly int UpperBodyIdle = Animator.StringToHash("upperbody.None");

		private static readonly FieldRef<Character, Animator> CharacterAnimator = AccessTools.FieldRefAccess<Character, Animator>("m_animator");

		private static readonly FieldRef<Character, bool> Blocking = AccessTools.FieldRefAccess<Character, bool>("m_blocking");

		private static readonly FieldRef<Character, bool> AttackHold = AccessTools.FieldRefAccess<Character, bool>("m_attackHold");

		private static readonly FieldRef<Character, bool> SecondaryAttackHold = AccessTools.FieldRefAccess<Character, bool>("m_secondaryAttackHold");

		private static readonly FieldRef<Humanoid, Attack> CurrentAttack = AccessTools.FieldRefAccess<Humanoid, Attack>("m_currentAttack");

		private static readonly FieldRef<Humanoid, Attack> PreviousAttack = AccessTools.FieldRefAccess<Humanoid, Attack>("m_previousAttack");

		private static readonly FieldRef<Player, float> QueuedAttack = AccessTools.FieldRefAccess<Player, float>("m_queuedAttackTimer");

		private static readonly FieldRef<Player, float> QueuedSecondAttack = AccessTools.FieldRefAccess<Player, float>("m_queuedSecondAttackTimer");

		private static readonly FieldRef<Attack, float> AttackTime = AccessTools.FieldRefAccess<Attack, float>("m_time");

		private static readonly ConditionalWeakTable<Attack, object> Landed = new ConditionalWeakTable<Attack, object>();

		private static readonly ConditionalWeakTable<Attack, object> Cancelled = new ConditionalWeakTable<Attack, object>();

		private static readonly object Marker = new object();

		internal static float AttackAllowedAt;

		private static bool holdIgnored;

		internal static bool IsCancelled(Attack attack)
		{
			object value;
			if (attack != null)
			{
				return Cancelled.TryGetValue(attack, out value);
			}
			return false;
		}

		internal static void MarkCancelled(Attack attack)
		{
			if (attack != null && !Cancelled.TryGetValue(attack, out var _))
			{
				Cancelled.Add(attack, Marker);
			}
		}

		private static bool CanCancel(Player player)
		{
			if (CurrentAttack.Invoke((Humanoid)(object)player) != null && ((Character)player).InAttack() && !((Character)player).IsDead() && !((Character)player).InDodge() && !((Character)player).InPlaceMode() && !((Character)player).IsEncumbered() && !((Character)player).InMinorAction())
			{
				return !((Character)player).IsStaggering();
			}
			return false;
		}

		private static void Cancel(Player player)
		{
			Attack val = CurrentAttack.Invoke((Humanoid)(object)player);
			val.Stop();
			MarkCancelled(val);
			QueuedBowRelease.Forget(val);
			PreviousAttack.Invoke((Humanoid)(object)player) = null;
			CurrentAttack.Invoke((Humanoid)(object)player) = null;
			QueuedAttack.Invoke(player) = 0f;
			QueuedSecondAttack.Invoke(player) = 0f;
			AttackAllowedAt = Time.time + (Landed.TryGetValue(val, out var _) ? Remaining(CharacterAnimator.Invoke((Character)(object)player), AttackTime.Invoke(val)) : 0.2f);
			((Component)player).GetComponent<ZNetView>().InvokeRPC(ZNetView.Everybody, "PotatoTweaks_AttackCancel", new object[1] { val.m_attackAnimation ?? "" });
		}

		private static float Remaining(Animator animator, float elapsed)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			float num = 0.2f;
			if (!Object.op_Implicit((Object)(object)animator))
			{
				return num;
			}
			for (int i = 0; i < animator.layerCount; i++)
			{
				AnimatorStateInfo val = State(animator, i);
				float num2 = Mathf.Clamp01(((AnimatorStateInfo)(ref val)).normalizedTime);
				if (((AnimatorStateInfo)(ref val)).tagHash == AttackTag && num2 > 0f)
				{
					num = Mathf.Max(num, (1f - num2) * elapsed / num2);
				}
			}
			return num;
		}

		private static AnimatorStateInfo State(Animator animator, int layer)
		{
			//IL_0013: 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)
			if (!animator.IsInTransition(layer))
			{
				return animator.GetCurrentAnimatorStateInfo(layer);
			}
			return animator.GetNextAnimatorStateInfo(layer);
		}

		private static void Interrupt(Player player, string animation)
		{
			Animator val = CharacterAnimator.Invoke((Character)(object)player);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			if (!string.IsNullOrEmpty(animation))
			{
				foreach (AnimatorControllerParameter item in val.parameters.Where((AnimatorControllerParameter parameter) => (int)parameter.type == 9 && parameter.name.StartsWith(animation)))
				{
					val.ResetTrigger(item.nameHash);
				}
			}
			Blend(val, 0, Movement);
			int layerIndex = val.GetLayerIndex("upperbody");
			if (layerIndex > 0)
			{
				Blend(val, layerIndex, UpperBodyIdle);
			}
		}

		private static void Blend(Animator animator, int layer, int state)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			AnimatorStateInfo val = State(animator, layer);
			if (((AnimatorStateInfo)(ref val)).tagHash == AttackTag && animator.HasState(layer, state))
			{
				animator.CrossFadeInFixedTime(state, 0.1f, layer);
			}
		}
	}
	internal static class CombatEffects
	{
		private enum Source
		{
			None,
			Status,
			CreatureHit,
			Weapon,
			Impact
		}

		[HarmonyPatch]
		internal static class CreatureHits
		{
			private static IEnumerable<MethodBase> TargetMethods()
			{
				yield return AccessTools.Method(typeof(Character), "ApplyDamage", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Character), "RPC_Damage", (Type[])null, (Type[])null);
			}

			private static void Prefix(Character __instance, out Character __state)
			{
				__state = hitCharacter;
				hitCharacter = __instance;
			}

			private static void Finalizer(Character __state)
			{
				hitCharacter = __state;
			}
		}

		[HarmonyPatch(typeof(StatusEffect), "TriggerStartEffects")]
		internal static class StatusStart
		{
			private static void Prefix(StatusEffect __instance, out StatusEffect __state)
			{
				__state = status;
				status = __instance;
			}

			private static void Finalizer(StatusEffect __state)
			{
				status = __state;
			}
		}

		[HarmonyPatch]
		internal static class StatusTick
		{
			private static IEnumerable<MethodBase> TargetMethods()
			{
				yield return AccessTools.Method(typeof(SE_Burning), "UpdateStatusEffect", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(SE_Poison), "UpdateStatusEffect", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(SE_Stats), "UpdateStatusEffect", (Type[])null, (Type[])null);
			}

			private static void Prefix(StatusEffect __instance, out StatusEffect __state)
			{
				__state = status;
				status = __instance;
			}

			private static void Finalizer(StatusEffect __state)
			{
				status = __state;
			}
		}

		[HarmonyPatch]
		internal static class Weapons
		{
			private static IEnumerable<MethodBase> TargetMethods()
			{
				yield return AccessTools.Method(typeof(Attack), "DoMeleeAttack", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Attack), "DoAreaAttack", (Type[])null, (Type[])null);
			}

			private static void Prefix(Attack __instance, out Attack __state)
			{
				__state = attack;
				attack = __instance;
			}

			private static void Finalizer(Attack __state)
			{
				attack = __state;
			}
		}

		[HarmonyPatch(typeof(Projectile), "OnHit")]
		internal static class Projectiles
		{
			private static void Prefix(Projectile __instance, out Projectile __state)
			{
				__state = projectile;
				projectile = __instance;
			}

			private static void Finalizer(Projectile __state)
			{
				projectile = __state;
			}
		}

		[HarmonyPatch(typeof(Aoe), "OnHit")]
		internal static class Areas
		{
			private static void Prefix(Aoe __instance, out Aoe __state)
			{
				__state = area;
				area = __instance;
			}

			private static void Finalizer(Aoe __state)
			{
				area = __state;
			}
		}

		[HarmonyPatch(typeof(EffectList), "Create")]
		internal static class Created
		{
			private static void Postfix(EffectList __instance, GameObject[] __result)
			{
				if (__result == null || __result.Length == 0 || !Active || ((Object)(object)status == (Object)null && !Object.op_Implicit((Object)(object)hitCharacter) && attack == null && !Object.op_Implicit((Object)(object)projectile) && !Object.op_Implicit((Object)(object)area)) || Of(__instance) == Source.None)
				{
					return;
				}
				float num = Mathf.Clamp01(Plugin.DimOpacity.Value);
				float num2 = Mathf.Clamp01(Plugin.DimBrightness.Value);
				float size = Mathf.Clamp(Plugin.DimSize.Value, 0.1f, 1f);
				foreach (GameObject val in __result)
				{
					if (Object.op_Implicit((Object)(object)val))
					{
						ParticleSystem[] componentsInChildren = val.GetComponentsInChildren<ParticleSystem>(true);
						for (int j = 0; j < componentsInChildren.Length; j++)
						{
							Dim(componentsInChildren[j], num, num2, size);
						}
						Light[] componentsInChildren2 = val.GetComponentsInChildren<Light>(true);
						foreach (Light obj in componentsInChildren2)
						{
							obj.intensity *= num * num2;
						}
					}
				}
			}
		}

		[ThreadStatic]
		private static Character hitCharacter;

		[ThreadStatic]
		private static StatusEffect status;

		[ThreadStatic]
		private static Attack attack;

		[ThreadStatic]
		private static Projectile projectile;

		[ThreadStatic]
		private static Aoe area;

		private static readonly FieldRef<Projectile, Character> ProjectileOwner = AccessTools.FieldRefAccess<Projectile, Character>("m_owner");

		private static readonly FieldRef<Aoe, Character> AreaOwner = AccessTools.FieldRefAccess<Aoe, Character>("m_owner");

		private static readonly FieldRef<Attack, Humanoid> Attacker = AccessTools.FieldRefAccess<Attack, Humanoid>("m_character");

		private static readonly Dictionary<Type, FieldInfo> TickFields = new Dictionary<Type, FieldInfo>();

		internal static readonly Type[] Patches = new Type[7]
		{
			typeof(CreatureHits),
			typeof(StatusStart),
			typeof(StatusTick),
			typeof(Weapons),
			typeof(Projectiles),
			typeof(Areas),
			typeof(Created)
		};

		private static bool Active
		{
			get
			{
				if (Plugin.DimEnabled.Value)
				{
					if (!(Plugin.DimOpacity.Value < 0.999f) && !(Plugin.DimBrightness.Value < 0.999f))
					{
						return Plugin.DimSize.Value < 0.999f;
					}
					return true;
				}
				return false;
			}
		}

		private static bool Counts(Character character)
		{
			if (Object.op_Implicit((Object)(object)character))
			{
				if (character.IsPlayer())
				{
					return Plugin.DimOnPlayers.Value;
				}
				return true;
			}
			return false;
		}

		private static EffectList TickEffect(StatusEffect effect)
		{
			Type type = ((object)effect).GetType();
			if (!TickFields.TryGetValue(type, out var value))
			{
				value = (TickFields[type] = AccessTools.Field(type, "m_tickEffect"));
			}
			object? obj = value?.GetValue(effect);
			return (EffectList)((obj is EffectList) ? obj : null);
		}

		private static Source Of(EffectList list)
		{
			if ((Object)(object)status != (Object)null && Counts(status.m_character) && (list == status.m_startEffects || list == TickEffect(status)))
			{
				if (!Plugin.DimStatus.Value)
				{
					return Source.None;
				}
				return Source.Status;
			}
			if (Object.op_Implicit((Object)(object)hitCharacter) && Counts(hitCharacter) && (list == hitCharacter.m_hitEffects || list == hitCharacter.m_critHitEffects || list == hitCharacter.m_backstabHitEffects))
			{
				if (!Plugin.DimCreatureHits.Value)
				{
					return Source.None;
				}
				return Source.CreatureHit;
			}
			if (attack != null && Attacker.Invoke(attack) is Player && (list == attack.m_hitEffect || list == attack.GetWeapon()?.m_shared.m_hitEffect))
			{
				if (!Plugin.DimWeapons.Value)
				{
					return Source.None;
				}
				return Source.Weapon;
			}
			if (Object.op_Implicit((Object)(object)projectile) && ProjectileOwner.Invoke(projectile) is Player && list == projectile.m_hitEffects)
			{
				if (!Plugin.DimImpacts.Value)
				{
					return Source.None;
				}
				return Source.Impact;
			}
			if (Object.op_Implicit((Object)(object)area) && AreaOwner.Invoke(area) is Player && list == area.m_hitEffects)
			{
				if (!Plugin.DimImpacts.Value)
				{
					return Source.None;
				}
				return Source.Impact;
			}
			return Source.None;
		}

		private static void Dim(ParticleSystem system, float opacity, float brightness, float size)
		{
			//IL_0001: 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_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			MainModule main = system.main;
			((MainModule)(ref main)).startColor = Scale(((MainModule)(ref main)).startColor, opacity, brightness);
			((MainModule)(ref main)).startSizeMultiplier = ((MainModule)(ref main)).startSizeMultiplier * size;
		}

		private static Color Scale(Color color, float opacity, float brightness)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			return new Color(color.r * brightness, color.g * brightness, color.b * brightness, color.a * opacity);
		}

		private static Gradient Scale(Gradient gradient, float opacity, float brightness)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			if (gradient == null)
			{
				return null;
			}
			GradientColorKey[] colorKeys = gradient.colorKeys;
			for (int i = 0; i < colorKeys.Length; i++)
			{
				colorKeys[i].color = Scale(colorKeys[i].color, 1f, brightness);
			}
			GradientAlphaKey[] alphaKeys = gradient.alphaKeys;
			for (int j = 0; j < alphaKeys.Length; j++)
			{
				alphaKeys[j].alpha *= opacity;
			}
			Gradient val = new Gradient
			{
				mode = gradient.mode
			};
			val.SetKeys(colorKeys, alphaKeys);
			return val;
		}

		private static MinMaxGradient Scale(MinMaxGradient value, float opacity, float brightness)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected I4, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			ParticleSystemGradientMode mode = ((MinMaxGradient)(ref value)).mode;
			switch ((int)mode)
			{
			case 0:
				return new MinMaxGradient(Scale(((MinMaxGradient)(ref value)).color, opacity, brightness));
			case 2:
				return new MinMaxGradient(Scale(((MinMaxGradient)(ref value)).colorMin, opacity, brightness), Scale(((MinMaxGradient)(ref value)).colorMax, opacity, brightness));
			case 1:
				return new MinMaxGradient(Scale(((MinMaxGradient)(ref value)).gradient, opacity, brightness));
			case 3:
				return new MinMaxGradient(Scale(((MinMaxGradient)(ref value)).gradientMin, opacity, brightness), Scale(((MinMaxGradient)(ref value)).gradientMax, opacity, brightness));
			case 4:
			{
				MinMaxGradient result = default(MinMaxGradient);
				((MinMaxGradient)(ref result))..ctor(Scale(((MinMaxGradient)(ref value)).gradient, opacity, brightness));
				((MinMaxGradient)(ref result)).mode = (ParticleSystemGradientMode)4;
				return result;
			}
			default:
				return value;
			}
		}
	}
	internal static class ComfortHelper
	{
		internal const string OriginalModId = "com.koendertjh.comforthelper";

		internal static readonly Type[] Patches = new Type[2]
		{
			typeof(ComfortTabPatches),
			typeof(RestingMessage)
		};

		internal static void RegisterCommand()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			new ConsoleCommand("comfort", "Your comfort here and the pieces that would raise it (Potato Tweaks)", new ConsoleEvent(ComfortCommand.Run), false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}

		internal static float MaxComfort()
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			Achievement val = null;
			if ((Object)(object)Achievements.m_instance != (Object)null)
			{
				foreach (AchievementList achievementList in Achievements.m_instance.m_achievementLists)
				{
					foreach (Achievement achievement in achievementList.m_achievements)
					{
						if ((Object)(object)achievement != (Object)null && achievement.m_id == "GrindComfort")
						{
							val = achievement;
						}
					}
				}
			}
			Game instance = Game.instance;
			PlayerProfile val2 = ((instance != null) ? instance.GetPlayerProfile() : null);
			if (val2 == null || (Object)(object)val == (Object)null)
			{
				return 0f;
			}
			PlayerStats val3 = val2.m_playerStats[val.m_difficultyRequirement];
			if (val3 == null || !val3.m_stats.TryGetValue((PlayerStatType)132, out var value))
			{
				return 0f;
			}
			return value;
		}
	}
	internal class Suggestion
	{
		public Piece Piece;

		public int Gain;

		public Piece Replaces;
	}
	internal class ComfortReport
	{
		public bool InShelter;

		public int Current;

		public int BestKnown;

		public int Locked;

		public float MaxReached;

		public readonly List<Suggestion> Suggestions = new List<Suggestion>();
	}
	internal static class Comfort
	{
		private const float Radius = 10f;

		private static readonly List<Piece> s_nearby = new List<Piece>();

		private static List<Piece> s_comfortPrefabs;

		private static ZNetScene s_scene;

		private static readonly string[] GroupNames = Enum.GetNames(typeof(ComfortGroup));

		internal static string GroupOf(Piece piece)
		{
			//IL_0001: 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)
			if ((int)piece.m_comfortGroup == 0)
			{
				return piece.m_name;
			}
			return GroupNames[piece.m_comfortGroup];
		}

		internal static Dictionary<string, Piece> BestNearby(Vector3 position)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<string, Piece> dictionary = new Dictionary<string, Piece>();
			Nearby(position, dictionary, null);
			return dictionary;
		}

		internal static void Nearby(Vector3 position, Dictionary<string, Piece> best, HashSet<string> names)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			s_nearby.Clear();
			Piece.GetAllComfortPiecesInRadius(position, 10f, s_nearby);
			foreach (Piece item in s_nearby)
			{
				names?.Add(item.m_name);
				if (best != null)
				{
					string key = GroupOf(item);
					if (!best.TryGetValue(key, out var value) || item.GetComfort() > value.GetComfort())
					{
						best[key] = item;
					}
				}
			}
		}

		internal static ComfortReport Build(Player player)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			ComfortReport comfortReport = new ComfortReport
			{
				InShelter = player.InShelter(),
				Current = SE_Rested.CalculateComfortLevel(player),
				MaxReached = ComfortHelper.MaxComfort()
			};
			Dictionary<string, Piece> dictionary = BestNearby(((Component)player).transform.position);
			Dictionary<string, Piece> dictionary2 = new Dictionary<string, Piece>();
			Dictionary<string, int> dictionary3 = new Dictionary<string, int>();
			foreach (Piece item in ComfortPrefabs())
			{
				string key = GroupOf(item);
				if (!dictionary3.TryGetValue(key, out var value) || item.m_comfort > value)
				{
					dictionary3[key] = item.m_comfort;
				}
				if (player.IsRecipeKnown(item.m_name) && (!dictionary2.TryGetValue(key, out var value2) || item.m_comfort > value2.m_comfort))
				{
					dictionary2[key] = item;
				}
			}
			int num = 0;
			foreach (KeyValuePair<string, Piece> item2 in dictionary2)
			{
				num += item2.Value.m_comfort;
				dictionary.TryGetValue(item2.Key, out var value3);
				int num2 = item2.Value.m_comfort - (((Object)(object)value3 != (Object)null) ? value3.GetComfort() : 0);
				if (num2 > 0)
				{
					comfortReport.Suggestions.Add(new Suggestion
					{
						Piece = item2.Value,
						Gain = num2,
						Replaces = value3
					});
				}
			}
			comfortReport.BestKnown = 2 + num;
			comfortReport.Locked = dictionary3.Sum((KeyValuePair<string, int> p) => p.Value) - num;
			comfortReport.Suggestions.Sort((Suggestion a, Suggestion b) => b.Gain.CompareTo(a.Gain));
			return comfortReport;
		}

		private static List<Piece> ComfortPrefabs()
		{
			if (s_comfortPrefabs != null && (Object)(object)s_scene == (Object)(object)ZNetScene.instance)
			{
				return s_comfortPrefabs;
			}
			s_scene = ZNetScene.instance;
			s_comfortPrefabs = new List<Piece>();
			if ((Object)(object)s_scene == (Object)null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return s_comfortPrefabs;
			}
			HashSet<string> hashSet = new HashSet<string>();
			foreach (GameObject item in ObjectDB.instance.m_items)
			{
				PieceTable val = ((!((Object)(object)item != (Object)null)) ? null : item.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				foreach (GameObject piece in val.m_pieces)
				{
					Piece val2 = (((Object)(object)piece != (Object)null) ? piece.GetComponent<Piece>() : null);
					if ((Object)(object)val2 != (Object)null && val2.m_comfort > 0 && hashSet.Add(val2.m_name))
					{
						s_comfortPrefabs.Add(val2);
					}
				}
			}
			return s_comfortPrefabs;
		}

		internal static string Describe(Suggestion suggestion)
		{
			string arg = Localization.instance.Localize(suggestion.Piece.m_name);
			if (!((Object)(object)suggestion.Replaces == (Object)null))
			{
				return $"+{suggestion.Gain} {arg} (instead of {Localization.instance.Localize(suggestion.Replaces.m_name)})";
			}
			return $"+{suggestion.Gain} {arg}";
		}
	}
	internal static class ComfortGroups
	{
		internal unsafe static string Name(ComfortGroup group)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected I4, but got Unknown
			return (int)group switch
			{
				1 => "Fires", 
				2 => "Beds", 
				3 => "Banners", 
				4 => "Seats", 
				5 => "Tables", 
				6 => "Rugs", 
				7 => "Displays", 
				8 => "Decorations", 
				9 => "Garlands", 
				10 => "Lanterns", 
				11 => "Leisure", 
				0 => "Each counts", 
				_ => ((object)(*(ComfortGroup*)(&group))/*cast due to .constrained prefix*/).ToString(), 
			};
		}
	}
	internal sealed class ComfortPieceList : IPieceList
	{
		private readonly ComfortGroup[] _groups = (ComfortGroup[])Enum.GetValues(typeof(ComfortGroup));

		private readonly List<int> _availableTags = new List<int>();

		public string DisplayName { get; }

		public bool ShowTags => true;

		public bool CanCustomizeTags => false;

		public int TagCount => _availableTags.Count;

		public int TagSeparatorIndex => -1;

		public ComfortPieceList(string displayName)
		{
			DisplayName = displayName;
		}

		public string GetTagDisplayName(int index)
		{
			int num = (int)_groups[_availableTags[index]];
			string text = ComfortGroups.Name((ComfortGroup)num);
			int num2 = NearbyState.GroupComfort((ComfortGroup)num);
			if (num2 <= 0)
			{
				return text;
			}
			return $"<color=#7CFC7C>{text} +{num2}</color>";
		}

		public int GetTagIdByIndex(int index)
		{
			return _availableTags[index];
		}

		public void UpdateAvailableTags(PieceTable pieceTable)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			HashSet<ComfortGroup> hashSet = new HashSet<ComfortGroup>();
			foreach (Piece availablePiece in pieceTable.m_availablePieces)
			{
				if (availablePiece.m_comfort > 0)
				{
					hashSet.Add(availablePiece.m_comfortGroup);
				}
			}
			_availableTags.Clear();
			for (int i = 0; i < _groups.Length; i++)
			{
				if (_groups[i] && hashSet.Contains(_groups[i]))
				{
					_availableTags.Add(i);
				}
			}
			int item = Array.IndexOf(_groups, (ComfortGroup)0);
			if (hashSet.Contains((ComfortGroup)0))
			{
				_availableTags.Add(item);
			}
		}

		public void GetAvailablePiecesWithTag(int tagId, PieceTable pieceTable, IList<Piece> resultOut)
		{
			foreach (Piece item in from p in pieceTable.m_availablePieces
				where p.m_comfort > 0 && (tagId < 0 || tagId >= _groups.Length || (int)p.m_comfortGroup == (int)_groups[tagId])
				orderby p.m_comfort descending
				select p)
			{
				resultOut.Add(item);
			}
		}
	}
	internal static class NearbyState
	{
		private static Dictionary<string, Piece> s_best = new Dictionary<string, Piece>();

		private static HashSet<string> s_names = new HashSet<string>();

		private static Dictionary<string, Piece> s_nextBest = new Dictionary<string, Piece>();

		private static HashSet<string> s_nextNames = new HashSet<string>();

		private static float s_nextUpdate;

		internal static int Version { get; private set; }

		internal static bool Update(Player player, bool force = false)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (!force && Time.time < s_nextUpdate)
			{
				return false;
			}
			s_nextUpdate = Time.time + 1f;
			s_nextBest.Clear();
			s_nextNames.Clear();
			Comfort.Nearby(((Component)player).transform.position, s_nextBest, s_nextNames);
			bool num = !s_nextNames.SetEquals(s_names) || !SameCounting(s_nextBest, s_best);
			Dictionary<string, Piece> dictionary = s_nextBest;
			Dictionary<string, Piece> dictionary2 = s_best;
			s_best = dictionary;
			s_nextBest = dictionary2;
			HashSet<string> hashSet = s_nextNames;
			HashSet<string> hashSet2 = s_names;
			s_names = hashSet;
			s_nextNames = hashSet2;
			if (num)
			{
				Version++;
			}
			return num;
		}

		private static bool SameCounting(Dictionary<string, Piece> a, Dictionary<string, Piece> b)
		{
			if (a.Count != b.Count)
			{
				return false;
			}
			foreach (KeyValuePair<string, Piece> item in a)
			{
				if (!b.TryGetValue(item.Key, out var value) || value.m_name != item.Value.m_name)
				{
					return false;
				}
			}
			return true;
		}

		internal static bool IsHere(Piece piece)
		{
			return s_names.Contains(piece.m_name);
		}

		internal static bool Counts(Piece piece)
		{
			if (s_best.TryGetValue(Comfort.GroupOf(piece), out var value))
			{
				return value.m_name == piece.m_name;
			}
			return false;
		}

		internal static Piece Counting(Piece piece)
		{
			if (!s_best.TryGetValue(Comfort.GroupOf(piece), out var value))
			{
				return null;
			}
			return value;
		}

		internal unsafe static int GroupComfort(ComfortGroup group)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if ((int)group == 0)
			{
				return s_best.Values.Where((Piece p) => (int)p.m_comfortGroup == 0).Sum((Piece p) => p.GetComfort());
			}
			if (!s_best.TryGetValue(((object)(*(ComfortGroup*)(&group))/*cast due to .constrained prefix*/).ToString(), out var value))
			{
				return 0;
			}
			return value.GetComfort();
		}
	}
	[HarmonyPatch]
	internal static class ComfortTabPatches
	{
		private const string CheckName = "PotatoTweaks_ComfortCheck";

		private static readonly Color Green = new Color(0.45f, 0.95f, 0.45f);

		private static readonly Color Grey = new Color(0.62f, 0.62f, 0.62f);

		private static readonly FieldRef<BuildUi, RectTransform> TabContainerRef = AccessTools.FieldRefAccess<BuildUi, RectTransform>("m_tabContainer");

		private static readonly FieldRef<BuildUi, TabHandler> TabHandlerRef = AccessTools.FieldRefAccess<BuildUi, TabHandler>("m_tabHandler");

		private static readonly FieldRef<BuildUi, List<IPieceList>> PieceListsRef = AccessTools.FieldRefAccess<BuildUi, List<IPieceList>>("m_pieceLists");

		private static readonly FieldRef<BuildUi, int> AvailablePieceCountRef = AccessTools.FieldRefAccess<BuildUi, int>("m_availablePieceCount");

		private static readonly FieldRef<BuildUi, int> CurrentPieceListRef = AccessTools.FieldRefAccess<BuildUi, int>("m_currentPieceList");

		private static readonly FieldRef<BuildUi, List<BuildUiPieceButton>> PieceButtonsRef = AccessTools.FieldRefAccess<BuildUi, List<BuildUiPieceButton>>("m_pieceButtons");

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

		private static int s_hoverVersion = -1;

		[HarmonyPrefix]
		[HarmonyPatch(typeof(BuildUi), "Awake")]
		private static void BeforeAwake(BuildUi __instance, out bool __state)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Expected O, but got Unknown
			__state = false;
			if (!Plugin.ComfortTab.Value)
			{
				return;
			}
			RectTransform val = TabContainerRef.Invoke(__instance);
			TabHandler val2 = TabHandlerRef.Invoke(__instance);
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || ((Transform)val).childCount < 2 || val2.m_tabs.Count != ((Transform)val).childCount)
			{
				Plugin.Log.LogWarning((object)"Build menu tabs have an unexpected layout; the Comfort tab is disabled.");
				return;
			}
			RectTransform val3 = (RectTransform)((Transform)val).GetChild(((Transform)val).childCount - 1);
			RectTransform val4 = (RectTransform)((Transform)val).GetChild(((Transform)val).childCount - 2);
			RectTransform val5 = Object.Instantiate<RectTransform>(val3, (Transform)(object)val);
			((Object)val5).name = "PotatoTweaks_ComfortTab";
			if ((Object)(object)((Component)val).GetComponent<LayoutGroup>() == (Object)null)
			{
				val5.anchoredPosition = val3.anchoredPosition + (val3.anchoredPosition - val4.anchoredPosition);
			}
			TMP_Text[] componentsInChildren = ((Component)val5).GetComponentsInChildren<TMP_Text>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].text = Plugin.ComfortTabName.Value;
			}
			Button component = ((Component)val5).GetComponent<Button>();
			component.onClick = new ButtonClickedEvent();
			val2.m_tabs.Add(new Tab
			{
				m_button = component
			});
			__state = true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BuildUi), "Awake")]
		private static void AfterAwake(BuildUi __instance, bool __state)
		{
			if (__state)
			{
				PieceListsRef.Invoke(__instance).Add((IPieceList)(object)new ComfortPieceList(Plugin.ComfortTabName.Value));
			}
		}

		private static bool ComfortTabShown(BuildUi buildUi)
		{
			List<IPieceList> list = PieceListsRef.Invoke(buildUi);
			int num = CurrentPieceListRef.Invoke(buildUi);
			if (num >= 0 && num < list.Count)
			{
				return list[num] is ComfortPieceList;
			}
			return false;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BuildUi), "UpdatePieceButtons")]
		private static void AfterUpdatePieceButtons(BuildUi __instance)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			bool flag = (Object)(object)localPlayer != (Object)null && (ComfortTabShown(__instance) || Plugin.ComfortChecksEverywhere.Value);
			if (flag)
			{
				NearbyState.Update(localPlayer, force: true);
			}
			foreach (BuildUiPieceButton item in PieceButtonsRef.Invoke(__instance))
			{
				Piece piece = item.Piece;
				bool flag2 = flag && (Object)(object)piece != (Object)null && piece.m_comfort > 0 && NearbyState.IsHere(piece);
				Transform val = ((Component)item).transform.Find("PotatoTweaks_ComfortCheck");
				if ((Object)(object)val == (Object)null)
				{
					if (!flag2)
					{
						continue;
					}
					val = CreateCheck(((Component)item).transform);
				}
				((Component)val).gameObject.SetActive(flag2);
				if (flag2)
				{
					Color color = (NearbyState.Counts(piece) ? Green : Grey);
					Image[] componentsInChildren = ((Component)val).GetComponentsInChildren<Image>(true);
					for (int i = 0; i < componentsInChildren.Length; i++)
					{
						((Graphic)componentsInChildren[i]).color = color;
					}
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Hud), "Update")]
		private static void AfterHudUpdate()
		{
			BuildUi val = (((Object)(object)Hud.instance != (Object)null) ? Hud.instance.m_buildUi : null);
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)val == (Object)null) && !((Object)(object)localPlayer == (Object)null) && ((Behaviour)val).isActiveAndEnabled && (ComfortTabShown(val) || Plugin.ComfortChecksEverywhere.Value) && NearbyState.Update(localPlayer))
			{
				AvailablePieceCountRef.Invoke(val) = -1;
			}
		}

		private static Transform CreateCheck(Transform button)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			//IL_00ef: Expected O, but got Unknown
			GameObject val = new GameObject("PotatoTweaks_ComfortCheck", new Type[1] { typeof(RectTransform) });
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent(button, false);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(1f, 1f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(1f, 1f);
			val2.anchoredPosition = new Vector2(-3f, -3f);
			val2.sizeDelta = new Vector2(18f, 16f);
			((Transform)val2).SetAsLastSibling();
			Bar(val2, new Vector2(5f, 6f), new Vector2(9f, 4f), -45f);
			Bar(val2, new Vector2(11f, 8f), new Vector2(15f, 4f), 50f);
			val.SetActive(false);
			return (Transform)val2;
		}

		private static void Bar(RectTransform parent, Vector2 center, Vector2 size, float angle)
		{
			//IL_0032: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_005e: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("bar", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Outline)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)parent, false);
			Vector2 anchorMin = (val2.anchorMax = Vector2.zero);
			val2.anchorMin = anchorMin;
			val2.pivot = new Vector2(0.5f, 0.5f);
			val2.anchoredPosition = center;
			val2.sizeDelta = size;
			((Transform)val2).localRotation = Quaternion.Euler(0f, 0f, angle);
			((Graphic)val.GetComponent<Image>()).raycastTarget = false;
			Outline component = val.GetComponent<Outline>();
			((Shadow)component).effectColor = new Color(0f, 0f, 0f, 0.85f);
			((Shadow)component).effectDistance = new Vector2(1f, -1f);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Hud), "SetupPieceInfo")]
		private static void AfterSetupPieceInfo(Hud __instance, Piece piece)
		{
			Player localPlayer = Player.m_localPlayer;
			if (Plugin.ComfortHoverInfo.Value && !((Object)(object)piece == (Object)null) && piece.m_comfort > 0 && !((Object)(object)localPlayer == (Object)null))
			{
				NearbyState.Update(localPlayer);
				if (s_hoverVersion != NearbyState.Version)
				{
					s_hoverTexts.Clear();
					s_hoverVersion = NearbyState.Version;
				}
				if (!s_hoverTexts.TryGetValue(piece.m_name, out var value))
				{
					value = (s_hoverTexts[piece.m_name] = HoverText(piece));
				}
				TMP_Text pieceDescription = __instance.m_pieceDescription;
				pieceDescription.text += value;
			}
		}

		private static string HoverText(Piece piece)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			Localization instance = Localization.instance;
			string text = $"\n\n<color=#ffb347>Comfort +{piece.m_comfort}</color> ";
			text += (((int)piece.m_comfortGroup == 0) ? "(counts once, next to everything else)" : ("(" + ComfortGroups.Name(piece.m_comfortGroup) + ": only the best one nearby counts)"));
			Piece val = NearbyState.Counting(piece);
			if ((Object)(object)val == (Object)null)
			{
				return text + $"\nNothing like it within 10 m: <color=#7CFC7C>+{piece.m_comfort} here</color>.";
			}
			if (val.m_name == piece.m_name)
			{
				return text + "\n<color=#7CFC7C>Already counts here.</color>";
			}
			if (piece.m_comfort > val.GetComfort())
			{
				return text + $"\n{instance.Localize(val.m_name)} counts here now: <color=#7CFC7C>+{piece.m_comfort - val.GetComfort()} more</color> with this one.";
			}
			return text + "\n" + instance.Localize(val.m_name) + " already counts here; this one adds nothing.";
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateEnvStatusEffects")]
	internal static class RestingMessage
	{
		private static bool s_wasResting;

		private static float s_lastShown = -10000f;

		private static void Postfix(Player __instance)
		{
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			bool flag = ((Character)__instance).GetSEMan().HaveStatusEffect(SEMan.s_statusEffectResting);
			bool num = flag && !s_wasResting;
			s_wasResting = flag;
			if (!num || !Plugin.ComfortRestingMessage.Value || Time.time - s_lastShown < Plugin.ComfortMessageCooldown.Value)
			{
				return;
			}
			s_lastShown = Time.time;
			ComfortReport comfortReport = Comfort.Build(__instance);
			string text = $"Comfort {comfortReport.Current} (best so far {comfortReport.MaxReached:0}, Comfort is King needs 20)";
			if (comfortReport.Suggestions.Count > 0)
			{
				text = text + "\nTo raise it: " + string.Join(", ", comfortReport.Suggestions.Take(Plugin.ComfortSuggestions.Value).Select(Comfort.Describe));
				if (comfortReport.Suggestions.Count > Plugin.ComfortSuggestions.Value)
				{
					text += ", ... (/comfort lists all)";
				}
			}
			((Character)__instance).Message((MessageType)1, text, 0, (Sprite)null, false);
		}
	}
	internal static class ComfortCommand
	{
		internal static void Run(ConsoleEventArgs args)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				Say(args, "Load into a world with a character first.");
				return;
			}
			ComfortReport comfortReport = Comfort.Build(localPlayer);
			Say(args, $"Comfort here {comfortReport.Current}, best so far {comfortReport.MaxReached:0} " + "(Comfort is King needs 20).");
			if (!comfortReport.InShelter)
			{
				Say(args, "  You are not under a roof: pieces only count in a shelter.");
			}
			Say(args, $"  With the pieces you know, the most you can reach is {comfortReport.BestKnown}." + ((comfortReport.Locked > 0) ? $" Pieces you haven't unlocked yet add up to {comfortReport.Locked} more." : ""));
			if (comfortReport.Suggestions.Count == 0)
			{
				Say(args, "  Nothing you know would raise it here.");
				return;
			}
			Say(args, "  Within 10 m, add:");
			foreach (Suggestion suggestion in comfortReport.Suggestions)
			{
				Say(args, "    " + Comfort.Describe(suggestion));
			}
		}

		private static void Say(ConsoleEventArgs args, string text)
		{
			if ((Object)(object)args?.Context != (Object)null)
			{
				args.Context.AddString(text);
			}
			else
			{
				Plugin.Log.LogInfo((object)text);
			}
		}
	}
	internal static class ConfigText
	{
		internal static Dictionary<string, string> Read(string path)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			try
			{
				if (!File.Exists(path))
				{
					return dictionary;
				}
				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)
					{
						dictionary[text + "|" + text2.Substring(0, num).Trim()] = text2.Substring(num + 1).Trim();
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Couldn't read " + Path.GetFileName(path) + ": " + ex.Message));
			}
			return dictionary;
		}

		private static void Set(ConfigEntryBase entry, string value)
		{
			try
			{
				entry.BoxedValue = TomlTypeConverter.ConvertToValue(value, entry.SettingType);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Couldn't copy '" + value + "' into " + entry.Definition.Key + ": " + ex.Message));
			}
		}

		internal static void CarryOver(ConfigFile config, Dictionary<string, string> before, string oldSection, string oldKey, ConfigEntryBase entry)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			string key = entry.Definition.Section + "|" + entry.Definition.Key;
			if (!before.ContainsKey(key) && before.TryGetValue(oldSection + "|" + oldKey, out var value))
			{
				Set(entry, value);
				if (AccessTools.Property(typeof(ConfigFile), "OrphanedEntries")?.GetValue(config) is Dictionary<ConfigDefinition, string> dictionary)
				{
					dictionary.Remove(new ConfigDefinition(oldSection, oldKey));
				}
				config.Save();
			}
		}

		internal static void CopyBool(ConfigFile config, string otherFile, string section, string key, ConfigEntry<bool> entry)
		{
			if (Read(Path.Combine(Paths.ConfigPath, otherFile)).TryGetValue(section + "|" + key, out var value))
			{
				Set((ConfigEntryBase)(object)entry, value);
			}
		}

		private static void Copy(Dictionary<string, string> other, string section, string key, ConfigEntryBase entry)
		{
			if (other.TryGetValue(section + "|" + key, out var value))
			{
				Set(entry, value);
			}
		}

		internal static void ImportDimmer(ConfigFile config)
		{
			Dictionary<string, string> dictionary = Read(Path.Combine(Paths.ConfigPath, "wheeze.valheim.dimmercombatparticleeffects.cfg"));
			if (dictionary.Count != 0)
			{
				Copy(dictionary, "1 - General", "Enabled", (ConfigEntryBase)(object)Plugin.DimEnabled);
				Copy(dictionary, "2 - Strength", "Opacity", (ConfigEntryBase)(object)Plugin.DimOpacity);
				Copy(dictionary, "2 - Strength", "Brightness", (ConfigEntryBase)(object)Plugin.DimBrightness);
				Copy(dictionary, "2 - Strength", "Size", (ConfigEntryBase)(object)Plugin.DimSize);
				Copy(dictionary, "3 - Sources", "Character hit effects", (ConfigEntryBase)(object)Plugin.DimCreatureHits);
				Copy(dictionary, "3 - Sources", "Weapon hit effects", (ConfigEntryBase)(object)Plugin.DimWeapons);
				Copy(dictionary, "3 - Sources", "Projectile hit effects", (ConfigEntryBase)(object)Plugin.DimImpacts);
				Copy(dictionary, "3 - Sources", "Status effect visuals on creatures", (ConfigEntryBase)(object)Plugin.DimStatus);
				Copy(dictionary, "3 - Sources", "Include hits on players", (ConfigEntryBase)(object)Plugin.DimOnPlayers);
				Plugin.Log.LogInfo((object)"Copied the combat effects dimmer settings from Dimmer Combat Particle Effects.");
			}
		}

		internal static void ImportSpearfishing(ConfigFile config)
		{
			Dictionary<string, string> dictionary = Read(Path.Combine(Paths.ConfigPath, "org.bepinex.plugins.spearfishing.cfg"));
			if (dictionary.Count != 0)
			{
				Copy(dictionary, "General", "EnableSpears", (ConfigEntryBase)(object)Plugin.FishSpears);
				Copy(dictionary, "General", "EnableHarpoons", (ConfigEntryBase)(object)Plugin.FishHarpoons);
				Copy(dictionary, "General", "EnableBows", (ConfigEntryBase)(object)Plugin.FishBows);
				Copy(dictionary, "General", "EnableCrossbows", (ConfigEntryBase)(object)Plugin.FishCrossbows);
				Plugin.Log.LogInfo((object)"Copied the spearfishing settings from Spearfishing.");
			}
		}

		internal static void ImportDropMoreLoot(ConfigFile config)
		{
			Dictionary<string, string> other = Read(Path.Combine(Paths.ConfigPath, "TastyChickenLegs.DropMoreLoot.cfg"));
			if (other.Count == 0)
			{
				return;
			}
			if (!Is("Pickup|Disable Loot Settings", fallback: false))
			{
				Copy(other, "Loot", "Multiplier for monster drops", (ConfigEntryBase)(object)Plugin.LootCreatures);
				Copy(other, "Loot", "Multiplier for resources", (ConfigEntryBase)(object)Plugin.LootResources);
				Copy(other, "Loot", "Multiplier for pickable objects", (ConfigEntryBase)(object)Plugin.LootPickables);
				Plugin.LootTrophies.Value = true;
				if (Is("Whitelist|Enable whitelist filter", fallback: false))
				{
					Copy(other, "Whitelist", "White List Itmes", (ConfigEntryBase)(object)Plugin.LootOnly);
				}
			}
			if (Is("Loot|useWeightReduction", fallback: true))
			{
				Copy(other, "Loot", "percentofweight", (ConfigEntryBase)(object)Plugin.ItemWeight);
			}
			if (Is("Stacking|Enable Stacking", fallback: true))
			{
				Copy(other, "Stacking", "Item Stack Multiplier", (ConfigEntryBase)(object)Plugin.ItemStackSize);
			}
			if (Is("Pickup|Enable Pickup Range", fallback: true))
			{
				Copy(other, "Pickup", "Pickup Range", (ConfigEntryBase)(object)Plugin.PickupRangeSetting);
			}
			Copy(other, "Pickup", "Items Float in Water", (ConfigEntryBase)(object)Plugin.ItemsFloat);
			Plugin.Log.LogInfo((object)"Copied the loot and item settings from DropMoreLoot.");
			bool Is(string key, bool fallback)
			{
				if (!other.TryGetValue(key, out var value))
				{
					return fallback;
				}
				return string.Equals(value, "true", StringComparison.OrdinalIgnoreCase);
			}
		}

		internal static void ImportEpicLootAddons(ConfigFile config)
		{
			Dictionary<string, string> other = Read(Path.Combine(Paths.ConfigPath, "digi.valheim.epiclootaddons.cfg"));
			if (other.Count != 0)
			{
				Copy(other, "Epic Loot Storage Materials - General", "Enabled", (ConfigEntryBase)(object)Plugin.ChestMaterialsEnabled);
				Copy(other, "Epic Loot Storage Materials - General", "Range (m)", (ConfigEntryBase)(object)Plugin.ChestMaterialsRange);
				Copy(other, "Epic Loot Storage Materials - General", "Chest trophies in Sacrifice", (ConfigEntryBase)(object)Plugin.ChestTrophies);
				Copy(other, "Epic Loot Storage Materials - General", "Chest shardstones in Sacrifice", (ConfigEntryBase)(object)Plugin.ChestShardstones);
				Copy(other, "Epic Loot Storage Materials - Sacrifice", "Roll double output per item", (ConfigEntryBase)(object)Plugin.SacrificePerItem);
				if (!On("Epic Loot Storage Materials"))
				{
					ConfigEntry<bool> chestMaterialsEnabled = Plugin.ChestMaterialsEnabled;
					bool value = (Plugin.SacrificePerItem.Value = false);
					chestMaterialsEnabled.Value = value;
				}
				Copy(other, "Epic Loot Fixes - Damage stacking", "Damage effects stack", (ConfigEntryBase)(object)Plugin.DamageStacking);
				Copy(other, "Epic Loot Fixes - Double and Triple Shot", "Normal cost", (ConfigEntryBase)(object)Plugin.ShotNormalCost);
				Copy(other, "Epic Loot Fixes - Double and Triple Shot", "Double Magic Shot doubles the summon limit", (ConfigEntryBase)(object)Plugin.ShotSummonLimit);
				Copy(other, "Epic Loot Fixes - Lucky Loot", "Show Lucky Loot message", (ConfigEntryBase)(object)Plugin.LuckyLootMessage);
				Copy(other, "Epic Loot Fixes - Lucky Loot", "Message position", (ConfigEntryBase)(object)Plugin.LuckyLootPosition);
				Copy(other, "Epic Loot Fixes - Lucky Loot", "Lucky Loot on birds", (ConfigEntryBase)(object)Plugin.LuckyLootBirds);
				Copy(other, "Epic Loot Fixes - Performance", "Faster chest loading", (ConfigEntryBase)(object)Plugin.FasterChestLoading);
				Copy(other, "Epic Loot Fixes - Tooltips", "Show eitr cost on enchanted items", (ConfigEntryBase)(object)Plugin.EitrTooltip);
				if (!On("Epic Loot Fixes"))
				{
					ConfigEntry<bool> damageStacking = Plugin.DamageStacking;
					ConfigEntry<bool> shotNormalCost = Plugin.ShotNormalCost;
					ConfigEntry<bool> shotSummonLimit = Plugin.ShotSummonLimit;
					ConfigEntry<bool> luckyLootMessage = Plugin.LuckyLootMessage;
					ConfigEntry<bool> luckyLootBirds = Plugin.LuckyLootBirds;
					ConfigEntry<bool> fasterChestLoading = Plugin.FasterChestLoading;
					bool flag2 = (Plugin.EitrTooltip.Value = false);
					bool flag4 = (fasterChestLoading.Value = flag2);
					bool flag6 = (luckyLootBirds.Value = flag4);
					bool flag8 = (luckyLootMessage.Value = flag6);
					bool flag10 = (shotSummonLimit.Value = flag8);
					bool value = (shotNormalCost.Value = flag10);
					damageStacking.Value = value;
				}
				if (On("Enchant Glow Toggle"))
				{
					Copy(other, "Enchant Glow Toggle - Always", "Hide Glowing aura", (ConfigEntryBase)(object)Plugin.HideGlowing);
					Copy(other, "Enchant Glow Toggle - Always", "Hide all enchantment effects", (ConfigEntryBase)(object)Plugin.HideEnchantEffects);
					Copy(other, "Enchant Glow Toggle - Always", "Hide legendary textures", (ConfigEntryBase)(object)Plugin.HideLegendaryLooks);
				}
				Copy(other, "Shard Exclusivity - General", "Ignore effect exclusions for shards", (ConfigEntryBase)(object)Plugin.ShardsIgnoreClashes);
				if (!On("Shard Exclusivity"))
				{
					Plugin.ShardsIgnoreClashes.Value = false;
				}
				Plugin.Log.LogInfo((object)"Copied the settings from Epic Loot Add-ons.");
			}
			bool On(string part)
			{
				if (other.TryGetValue("0 - Sub-mods|" + part, out var value2))
				{
					return !string.Equals(value2, "false", StringComparison.OrdinalIgnoreCase);
				}
				return true;
			}
		}

		internal static void ImportTrophyAssister(ConfigFile config)
		{
			Dictionary<string, string> dictionary = Read(Path.Combine(Paths.ConfigPath, "com.koendertjh.trophyassister.cfg"));
			if (dictionary.Count != 0)
			{
				Copy(dictionary, "3 - Pity", "Enabled", (ConfigEntryBase)(object)Plugin.TrophyPity);
				if (dictionary.TryGetValue("3 - Pity|Mode", out var value))
				{
					Plugin.TrophyFlatMode.Value = string.Equals(value, "Flat", StringComparison.OrdinalIgnoreCase);
				}
				Copy(dictionary, "3 - Pity", "GrowthPerKill", (ConfigEntryBase)(object)Plugin.TrophyGrowth);
				Copy(dictionary, "3 - Pity", "RareThreshold", (ConfigEntryBase)(object)Plugin.TrophyRareThreshold);
				Copy(dictionary, "3 - Pity", "RareGrowthPerKill", (ConfigEntryBase)(object)Plugin.TrophyRareGrowth);
				Copy(dictionary, "3 - Pity", "FlatBonusPerKill", (ConfigEntryBase)(object)Plugin.TrophyFlatBonus);
				Copy(dictionary, "3 - Pity", "GuaranteeAfterKills", (ConfigEntryBase)(object)Plugin.TrophyGuarantee);
				Copy(dictionary, "3 - Pity", "OnlyCountMyKills", (ConfigEntryBase)(object)Plugin.TrophyOnlyMine);
				Copy(dictionary, "3 - Pity", "ExtraKillsPerStar", (ConfigEntryBase)(object)Plugin.TrophyExtraKillsPerStar);
				if (dictionary.TryGetValue("3 - Pity|StarKillBonus", out var value2) && string.Equals(value2, "false", StringComparison.OrdinalIgnoreCase))
				{
					Plugin.TrophyExtraKillsPerStar.Value = 0;
				}
				Copy(dictionary, "2 - Base boost", "ChanceMultiplier", (ConfigEntryBase)(object)Plugin.TrophyChanceMultiplier);
				Copy(dictionary, "2 - Base boost", "OnlyUncollected", (ConfigEntryBase)(object)Plugin.TrophyOnlyUncollected);
				Copy(dictionary, "4 - Trophy list", "ShowChances", (ConfigEntryBase)(object)Plugin.TrophyShowChances);
				Copy(dictionary, "4 - Trophy list", "ShowMissing", (ConfigEntryBase)(object)Plugin.TrophyShowMissing);
				Copy(dictionary, "4 - Trophy list", "SpoilerFree", (ConfigEntryBase)(object)Plugin.TrophySpoilerFree);
				Copy(dictionary, "4 - Trophy list", "HiddenTrophies", (ConfigEntryBase)(object)Plugin.TrophyHidden);
				Copy(dictionary, "1 - General", "NotifyOnDrop", (ConfigEntryBase)(object)Plugin.TrophyNotify);
				Copy(dictionary, "1 - General", "ShowPityProgress", (ConfigEntryBase)(object)Plugin.TrophyShowProgress);
				Plugin.Log.LogInfo((object)"Copied the trophy settings from TrophyAssister.");
			}
		}
	}
	[HarmonyPatch(typeof(Minimap), "Update")]
	internal static class DeathMarkers
	{
		private const float CheckInterval = 0.25f;

		private const float ConfirmTime = 3f;

		private const float Gap = 6f;

		private static readonly FieldRef<Minimap, List<PinData>> Pins = AccessTools.FieldRefAccess<Minimap, List<PinData>>("m_pins");

		private static readonly List<PinData> Removing = new List<PinData>();

		private static readonly Vector3[] Corners = (Vector3[])(object)new Vector3[4];

		private static Button button;

		private static TMP_Text label;

		private static float nextCheck;

		private static float confirmUntil;

		private static int shown = -1;

		private static void Postfix(Minimap __instance)
		{
			if (!Object.op_Implicit((Object)(object)__instance.m_largeRoot) || !__instance.m_largeRoot.activeInHierarchy)
			{
				confirmUntil = 0f;
			}
			else
			{
				if (Time.unscaledTime < nextCheck)
				{
					return;
				}
				nextCheck = Time.unscaledTime + 0.25f;
				int num = (Plugin.DeathMarkerButton.Value ? Count(__instance) : 0);
				if (num == 0)
				{
					if (Object.op_Implicit((Object)(object)button))
					{
						((Component)button).gameObject.SetActive(false);
					}
				}
				else if (Object.op_Implicit((Object)(object)button) || Create(__instance))
				{
					((Component)button).gameObject.SetActive(true);
					Place(__instance);
					bool flag = Time.unscaledTime < confirmUntil;
					int num2 = (flag ? (-num) : num);
					if (num2 != shown)
					{
						shown = num2;
						label.text = (flag ? $"Click again: remove {num}" : $"Remove death markers ({num})");
					}
				}
			}
		}

		private static int Count(Minimap map)
		{
			List<PinData> list = Pins.Invoke(map);
			int num = 0;
			if (list != null)
			{
				foreach (PinData item in list)
				{
					if (IsDeathMarker(item))
					{
						num++;
					}
				}
			}
			return num;
		}

		private static bool IsDeathMarker(PinData pin)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			if (pin != null && (int)pin.m_type == 4)
			{
				return pin.m_save;
			}
			return false;
		}

		private static bool Create(Minimap map)
		{
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Expected O, but got Unknown
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Expected O, but got Unknown
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			Button val = (Object.op_Implicit((Object)(object)InventoryGui.instance) ? InventoryGui.instance.m_takeAllButton : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, map.m_largeRoot.transform, false);
			((Object)val2).name = "PotatoTweaks_RemoveDeathMarkers";
			UIGamePad[] componentsInChildren = val2.GetComponentsInChildren<UIGamePad>(true);
			foreach (UIGamePad val3 in componentsInChildren)
			{
				if (Object.op_Implicit((Object)(object)val3.m_hint))
				{
					Object.Destroy((Object)(object)val3.m_hint);
				}
				Object.Destroy((Object)(object)val3);
			}
			Localize[] componentsInChildren2 = val2.GetComponentsInChildren<Localize>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.Destroy((Object)(object)componentsInChildren2[i]);
			}
			UITooltip[] componentsInChildren3 = val2.GetComponentsInChildren<UITooltip>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				Object.Destroy((Object)(object)componentsInChildren3[i]);
			}
			(val2.GetComponent<LayoutElement>() ?? val2.AddComponent<LayoutElement>()).ignoreLayout = true;
			button = val2.GetComponent<Button>();
			label = val2.GetComponentInChildren<TMP_Text>(true);
			if (!Object.op_Implicit((Object)(object)button) || !Object.op_Implicit((Object)(object)label))
			{
				Object.Destroy((Object)(object)val2);
				button = null;
				return false;
			}
			button.onClick = new ButtonClickedEvent();
			((UnityEvent)button.onClick).AddListener(new UnityAction(Clicked));
			label.textWrappingMode = (TextWrappingModes)0;
			RectTransform val4 = (RectTransform)val2.transform;
			Vector2 val5 = default(Vector2);
			((Vector2)(ref val5))..ctor(0.5f, 0.5f);
			val4.pivot = val5;
			Vector2 anchorMin = (val4.anchorMax = val5);
			val4.anchorMin = anchorMin;
			val4.sizeDelta = new Vector2(Mathf.Max(val4.sizeDelta.x, 240f), val4.sizeDelta.y);
			shown = -1;
			return true;
		}

		private static void Place(Minimap map)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_001b: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = (RectTransform)map.m_largeRoot.transform;
			RectTransform val2 = (RectTransform)((Component)button).transform;
			RectTransform val3 = (Object.op_Implicit((Object)(object)map.m_selectedIconDeath) ? ((Graphic)map.m_selectedIconDeath).rectTransform : null);
			object obj;
			if (!Object.op_Implicit((Object)(object)val3))
			{
				obj = null;
			}
			else
			{
				Button componentInParent = ((Component)val3).GetComponentInParent<Button>();
				Transform obj2 = ((componentInParent != null) ? ((Component)componentInParent).transform : null);
				obj = ((object)((obj2 is RectTransform) ? obj2 : null)) ?? ((object)val3);
			}
			RectTransform val4 = (RectTransform)obj;
			Rect rect = val.rect;
			Rect rect2 = val2.rect;
			Vector2 size = ((Rect)(ref rect2)).size;
			Vector2 val8 = default(Vector2);
			if (Object.op_Implicit((Object)(object)val4))
			{
				val4.GetWorldCorners(Corners);
				float num = (((Transform)val).InverseTransformPoint(Corners[0]).y + ((Transform)val).InverseTransformPoint(Corners[2]).y) * 0.5f;
				Transform parent = ((Transform)val4).parent;
				RectTransform val5 = (RectTransform)(object)((parent is RectTransform) ? parent : null);
				if (val5 != null && (Object)(object)val5 != (Object)(object)val)
				{
					rect2 = val5.rect;
					if (((Rect)(ref rect2)).width < ((Rect)(ref rect)).width / 3f)
					{
						val5.GetWorldCorners(Corners);
					}
				}
				Vector3 val6 = ((Transform)val).InverseTransformPoint(Corners[0]);
				Vector3 val7 = ((Transform)val).InverseTransformPoint(Corners[2]);
				val8 = (((val6.x + val7.x) * 0.5f > ((Rect)(ref rect)).center.x) ? new Vector2(val6.x - 6f - size.x * 0.5f, num) : new Vector2(val7.x + 6f + size.x * 0.5f, num));
			}
			else
			{
				((Vector2)(ref val8))..ctor(((Rect)(ref rect)).center.x, ((Rect)(ref rect)).yMin + 6f + size.y * 0.5f);
			}
			val8.x = Mathf.Clamp(val8.x, ((Rect)(ref rect)).xMin + size.x * 0.5f, ((Rect)(ref rect)).xMax - size.x * 0.5f);
			val8.y = Mathf.Clamp(val8.y, ((Rect)(ref rect)).yMin + size.y * 0.5f, ((Rect)(ref rect)).yMax - size.y * 0.5f);
			((Transform)val2).localPosition = new Vector3(val8.x, val8.y, 0f);
		}

		private static void Clicked()
		{
			Minimap instance = Minimap.instance;
			if (!Object.op_Implicit((Object)(object)instance))
			{
				return;
			}
			if (Time.unscaledTime >= confirmUntil)
			{
				confirmUntil = Time.unscaledTime + 3f;
				nextCheck = 0f;
				return;
			}
			confirmUntil = 0f;
			nextCheck = 0f;
			Removing.Clear();
			List<PinData> list = Pins.Invoke(instance);
			if (list != null)
			{
				foreach (PinData item in list)
				{
					if (IsDeathMarker(item))
					{
						Removing.Add(item);
					}
				}
			}
			foreach (PinData item2 in Removing)
			{
				instance.RemovePin(item2);
			}
			if (Removing.Count > 0)
			{
				MessageHud instance2 = MessageHud.instance;
				if (instance2 != null)
				{
					instance2.ShowMessage((MessageType)1, (Removing.Count == 1) ? "Removed 1 death marker" : $"Removed {Removing.Count} death markers", 0, (Sprite)null, false, true);
				}
			}
			Removing.Clear();
		}
	}
	internal static class EpicLootAddons
	{
		internal const string OriginalModId = "digi.valheim.epiclootaddons";

		internal const string OriginalModName = "Epic Loot Add-ons";

		private static readonly string[] SeparateMods = new string[8] { "digi.valheim.epiclootstoragematerials", "digi.valheim.epiclootfixes", "digi.valheim.enchantglowtoggle", "digi.valheim.shardexclusivity", "pieter.valheim.epiclootstoragematerials", "pieter.valheim.epiclootfixes", "pieter.valheim.enchantglowtoggle", "pieter.valheim.shardexclusivity" };

		internal static string InstalledOriginal()
		{
			if (Chainloader.PluginInfos.ContainsKey("digi.valheim.epiclootaddons"))
			{
				return "Epic Loot Add-ons";
			}
			string[] separateMods = SeparateMods;
			foreach (string key in separateMods)
			{
				if (Chainloader.PluginInfos.TryGetValue(key, out var value))
				{
					return value.Metadata.Name;
				}
			}
			return null;
		}

		internal static void Enable(Action<Type> patch, Action<string, Action> run)
		{
			run("Enchanting table chests", ChestMaterials.Initialize);
			patch(typeof(ChestMaterials.Track));
			patch(typeof(ChestMaterials.SacrificeList));
			patch(typeof(ChestMaterials.Checkboxes));
			patch(typeof(SacrificeDoubles));
			run("Damage stacking and Double/Triple Shot cost", EffectRules.Initialize);
			patch(typeof(EffectRules.Reloaded));
			patch(typeof(SummonLimit));
			patch(typeof(ShardClashes));
			patch(typeof(LuckyLootMessage));
			patch(typeof(LuckyLootMessage.Register));
			patch(typeof(LuckyBirds));
			patch(typeof(LuckyBirds.Drops));
			patch(typeof(EitrTooltip));
			patch(typeof(FasterChestLoading));
			patch(typeof(FasterChestLoading.Loaded));
			patch(typeof(EnchantLooks.Effects));
			patch(typeof(EnchantLooks.Textures));
			EnchantLooks.Watch();
		}
	}
	internal static class ChestMaterials
	{
		[HarmonyPatch(typeof(Container), "Awake")]
		internal static class Track
		{
			private static void Postfix(Container __instance)
			{
				Known.Add(__instance);
			}
		}

		[HarmonyPatch]
		internal static class SacrificeList
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(AccessTools.TypeByName("EpicLoot.CraftingV2.EnchantingUIController"), "GetSacrificeItems", (Type[])null, (Type[])null);
			}

			private static void Prefix()
			{
				listingSacrifice = true;
			}

			private static void Finalizer()
			{
				listingSacrifice = false;
			}
		}

		[HarmonyPatch(typeof(SacrificeUI), "OnEnable")]
		internal static class Checkboxes
		{
			private static readonly MethodInfo Refresh = AccessTools.Method(typeof(SacrificeUI), "RefreshAvailableItems", (Type[])null, (Type[])null);

			private static void Postfix(SacrificeUI __instance)
			{
				Toggle val = (Object.op_Implicit((Object)(object)((EnchantingTableUIPanelBase)__instance).AvailableItems) ? ((EnchantingTableUIPanelBase)__instance).AvailableItems.SelectAllToggle : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					bool value = Plugin.ChestMaterialsEnabled.Value;
					Add(__instance, val, "PotatoTweaks_ChestTrophies", "Include trophies from chests", 1, Plugin.ChestTrophies, value);
					Add(__instance, val, "PotatoTweaks_ChestShardstones", "Include shardstones from chests", 2, Plugin.ChestShardstones, value);
				}
			}

			private static void Add(SacrificeUI ui, Toggle selectAll, string name, string label, int row, ConfigEntry<bool> setting, bool shown)
			{
				//IL_007f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0086: Expected O, but got Unknown
				//IL_008d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0094: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
				//IL_0102: Expected O, but got Unknown
				Transform parent = ((Component)selectAll).transform.parent;
				Transform val = parent.Find(name);
				if (!shown)
				{
					if (Object.op_Implicit((Object)(object)val))
					{
						((Component)val).gameObject.SetActive(false);
					}
					return;
				}
				Toggle component;
				if (Object.op_Implicit((Object)(object)val))
				{
					((Component)val).gameObject.SetActive(true);
					component = ((Component)val).GetComponent<Toggle>();
				}
				else
				{
					GameObject val2 = Object.Instantiate<GameObject>(((Component)selectAll).gameObject, parent, false);
					((Object)val2).name = name;
					RectTransform val3 = (RectTransform)((Component)selectAll).transform;
					RectTransform val4 = (RectTransform)val2.transform;
					Vector2 anchoredPosition = val3.anchoredPosition;
					float num = row;
					Rect rect = val3.rect;
					val4.anchoredPosition = anchoredPosition + new Vector2(0f, num * (((Rect)(ref rect)).height + 4f));
					Text[] componentsInChildren = val2.GetComponentsInChildren<Text>(true);
					for (int i = 0; i < componentsInChildren.Length; i++)
					{
						componentsInChildren[i].text = label;
					}
					component = val2.GetComponent<Toggle>();
					component.onValueChanged = new ToggleEvent();
					((Selectable)component).interactable = true;
					((UnityEvent<bool>)(object)component.onValueChanged).AddListener((UnityAction<bool>)delegate(bool on)
					{
						setting.Value = on;
						Refresh?.Invoke(ui, null);
					});
				}
				if (Object.op_Implicit((Object)(object)component))
				{
					component.SetIsOnWithoutNotify(setting.Value);
				}
			}
		}

		private const string ProviderId = "potato.tweaks.nearbychests";

		private static readonly List<Container> Known = new List<Container>();

		private static readonly List<Container> Usable = new List<Container>();

		private static int usableFrame = -1;

		private static bool listingSacrifice;

		private static readonly Func<Container, long, bool> CheckAccess = AccessTools.MethodDelegate<Func<Container, long, bool>>(AccessTools.Method(typeof(Container), "CheckAccess", new Type[1] { typeof(long) }, (Type[])null), (object)null, true);

		internal static void Initialize()
		{
			if (!API.RegisterInventoryProvider("potato.tweaks.nearbychests", (Func<List<ItemData>>)ChestItems, (Func<string, int>)CountItem, (Func<string, int, int>)RemoveItem, (Func<ItemData, int, int>)RemoveExactItem))
			{
				throw new Exception("Epic Loot refused the chest provider");
			}
		}

		private static List<Container> Chests()
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			if (usableFrame == Time.frameCount)
			{
				return Usable;
			}
			usableFrame = Time.frameCount;
			Usable.Clear();
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || !Plugin.ChestMaterialsEnabled.Value)
			{
				return Usable;
			}
			Known.RemoveAll((Container chest) => !Object.op_Implicit((Object)(object)chest));
			Vector3 origin = ((Component)localPlayer).transform.position;
			float num = Plugin.ChestMaterialsRange.Value * Plugin.ChestMaterialsRange.Value;
			long playerID = Game.instance.GetPlayerProfile().GetPlayerID();
			foreach (Container item in Known)
			{
				Vector3 val = ((Component)item).transform.position - origin;
				if (((Vector3)(ref val)).sqrMagnitude <= num && CanUse(item, playerID))
				{
					Usable.Add(item);
				}
			}
			Usable.Sort(delegate(Container a, Container b)
			{
				//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)
				//IL_0016: 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_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val2 = ((Component)a).transform.position - origin;
				float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
				val2 = ((Component)b).transform.position - origin;
				return sqrMagnitude.CompareTo(((Vector3)(ref val2)).sqrMagnitude);
			});
			return Usable;
		}

		private static bool CanUse(Container chest, long playerId)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if (!((Behaviour)chest).isActiveAndEnabled || chest.GetInventory() == null || !chest.IsOwner() || chest.IsInUse())
			{
				return false;
			}
			Piece componentInParent = ((Component)chest).GetComponentInParent<Piece>();
			if (!Object.op_Implicit((Object)(object)componentInParent) || !componentInParent.IsPlacedByPlayer() || Object.op_Implicit((Object)(object)chest.m_wagon) || Object.op_Implicit((Object)(object)((Component)chest).GetComponentInParent<Ship>()))
			{
				return false;
			}
			if (chest.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)chest).transform.position, 0f, false, false))
			{
				return false;
			}
			return CheckAccess(chest, playerId);
		}

		private static List<ItemData> ChestItems()
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Invalid comparison between Unknown and I4
			List<ItemData> list = new List<ItemData>();
			if (!listingSacrifice)
			{
				return list;
			}
			bool value = Plugin.ChestTrophies.Value;
			bool value2 = Plugin.ChestShardstones.Value;
			if (!value && !value2)
			{
				return list;
			}
			foreach (Container item in Chests())
			{
				foreach (ItemData allItem in item.GetInventory().GetAllItems())
				{
					if (allItem?.m_shared != null)
					{
						if (value && (int)allItem.m_shared.m_itemType == 13)
						{
							list.Add(allItem);
						}
						else if (value2 && ItemDataExtensions.IsShardStone(allItem))
						{
							list.Add(allItem);
						}
					}
				}
			}
			return list;
		}

		private static int CountItem(string name)
		{
			int num = 0;
			foreach (Container item in Chests())
			{
				num += item.GetInventory().CountItems(name, -1, true);
			}
			return num;
		}

		private static int RemoveItem(string name, int amount)
		{
			int num = 0;
			foreach (Container item in Chests())
			{
				if (num >= amount)
				{
					break;
				}
				Inventory inventory = item.GetInventory();
				int num2 = inventory.CountItems(name, -1, true);
				if (num2 != 0)
				{
					inventory.RemoveItem(name, Mathf.Min(num2, amount - num), -1, true);
					num += num2 - inventory.CountItems(name, -1, true);
				}
			}
			return num;
		}

		private static int RemoveExactItem(ItemData item, int amount)
		{
			if (item == null || amount <= 0)
			{
				return 0;
			}
			foreach (Container item2 in Chests())
			{
				Inventory inventory = item2.GetInventory();
				if (inventory.ContainsItem(item))
				{
					int stack = item.m_stack;
					inventory.RemoveItem(item, Mathf.Min(amount, stack));
					return stack - (inventory.ContainsItem(item) ? item.m_stack : 0);
				}
			}
			return 0;
		}
	}
	[HarmonyPatch(typeof(SacrificeUI), "SacrificeItems")]
	internal static class SacrificeDoubles
	{
		private static readonly MethodInfo ProductsMethod = AccessTools.Method(AccessTools.TypeByName("EpicLoot.CraftingV2.EnchantingUIController"), "GetSacrificeProducts", new Type[1] { typeof(List<Tuple<ItemData, int>>) }, (Type[])null);

		private static readonly MethodInfo FeatureValue = AccessTools.Method(typeof(EnchantingTable), "GetFeatureCurrentValue", (Type[])null, (Type[])null);

		private static Func<List<Tuple<ItemData, int>>, List<InventoryItemListElement>> make;

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			if (ProductsMethod == null)
			{
				throw new Exception("Epic Loot's sacrifice products were not found");
			}
			List<CodeInstruction> list = instructions.ToList();
			int num = list.FindIndex((CodeInstruction i) => CodeInstructionExtensions.Calls(i, ProductsMethod));
			int num2 = list.FindIndex(num + 1, (CodeInstruction i) => CodeInstructionExtensions.Calls(i, FeatureValue));
			if (num < 0 || num2 < 0)
			{
				throw new Exception("Epic Loot's sacrifice code has changed");
			}
			list[num2] = CodeInstructionExtensions.MoveLabelsFrom(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(SacrificeDoubles), "BatchChance", (Type[])null, (Type[])null)), list[num2]);
			list[num] = CodeInstructionExtensions.MoveLabelsFrom(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(SacrificeDoubles), "Products", (Type[])null, (Type[])null)), list[num]);
			list.Insert(num, new CodeInstruction(OpCodes.Ldarg_0, (object)null));
			return list;
		}

		private static Tuple<float, float> BatchChance(EnchantingTable table, EnchantingFeature feature)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.SacrificePerItem.Value)
			{
				return table.GetFeatureCurrentValue(feature);
			}
			return Tuple.Create(float.NaN, float.NaN);
		}

		private static List<InventoryItemListElement> Products(List<Tuple<ItemData, int>> items, SacrificeUI ui)
		{
			if (make == null)
			{
				make = AccessTools.MethodDelegate<Func<List<Tuple<ItemData, int>>, List<InventoryItemListElement>>>(ProductsMethod, (object)null, true);
			}
			EnchantingTable val = (Object.op_Implicit((Object)(object)EnchantingTableUI.instance) ? EnchantingTableUI.instance.SourceTable : null);
			if (!Plugin.SacrificePerItem.Value || !Object.op_Implicit((Object)(object)val))
			{
				return make(items);
			}
			float item = val.GetFeatureCurrentValue((EnchantingFeature)0).Item1;
			float num = (float.IsNaN(item) ? 0f : (item / 100f));
			bool flag = false;
			List<Tuple<ItemData, int>> list = new List<Tuple<ItemData, int>>(items.Count);
			foreach (Tuple<ItemData, int> item2 in items)
			{
				int num2 = 0;
				for (int i = 0; i < item2.Item2; i++)
				{
					if (Random.value < num)
					{
						num2++;
					}
				}
				flag = flag || num2 > 0;
				list.Add(Tuple.Create<ItemData, int>(item2.Item1, item2.Item2 + num2));
			}
			List<InventoryItemListElement> list2 = make(list);
			if (flag && list2.Count > 0)
			{
				EnchantingTableUI.instance.PlayEnchantBonusSFX();
				if (Object.op_Implicit((Object)(object)ui.BonusPanel))
				{
					ui.BonusPanel.Show();
				}
			}
			return list2;
		}
	}
	internal static class EffectRules
	{
		private sealed class Original
		{
			internal List<string> Exclusive;

			internal bool ExclusiveSelf;

			internal float Weight;

			internal bool HadCostScale;

			internal float CostScale;
		}

		[HarmonyPatch(typeof(MagicItemEffectDefinitions), "Initialize")]
		internal static class Reloaded
		{
			private static void Postfix()
			{
				Apply();
			}
		}

		private static readonly HashSet<string> Damage = new HashSet<string>
		{
			"ModifyDamage", "ModifyPhysicalDamage", "ModifyElementalDamage", "ModifyDamageLowHealth", "AddBluntDamage", "AddSlashingDamage", "AddPiercingDamage", "AddFireDamage", "AddFrostDamage", "AddLightningDamage",
			"AddPoisonDamage", "AddSpiritDamage"
		};

		private static readonly HashSet<string> Shots = new HashSet<string> { "DoubleMagicShot", "TripleBowShot" };

		private const string CostScaleKey = "CostScale";

		private static readonly ConditionalWeakTable<MagicItemEffectDefinition, Original> Originals = new ConditionalWeakTable<MagicItemEffectDefinition, Original>();

		internal static void Initialize()
		{
			Plugin.DamageStacking.SettingChanged += delegate
			{
				Apply();
			};
			Plugin.ShotNormalCost.SettingChanged += delegate
			{
				Apply();
			};
			Apply();
		}

		private static void Apply()
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			bool value = Plugin.DamageStacking.Value;
			bool value2 = Plugin.ShotNormalCost.Value;
			foreach (MagicItemEffectDefinition value5 in MagicItemEffectDefinitions.AllDefinitions.Values)
			{
				if (value5 == null || value5.Type == null)
				{
					continue;
				}
				bool flag = Damage.Contains(value5.Type);
				bool flag2 = Shots.Contains(value5.Type);
				if (!flag && !flag2)
				{
					continue;
				}
				if (value5.Requirements == null)
				{
					value5.Requirements = new MagicItemEffectRequirements();
				}
				if (value5.Config == null)
				{
					value5.Config = new Dictionary<string, float>();
				}
				float value4;
				Original value3 = Originals.GetValue(value5, (MagicItemEffectDefinition d) => new Original
				{
					Exclusive = new List<string>(d.Requirements.ExclusiveEffectTypes ?? new List<string>()),
					ExclusiveSelf = d.Requirements.ExclusiveSelf,
					Weight = d.SelectionWeight,
					HadCostScale = d.Config.ContainsKey("CostScale"),
					CostScale = (d.Config.TryGetValue("CostScale", out value4) ? value4 : 0f)
				});
				if (flag)
				{
					value5.Requirements.ExclusiveEffectTypes = (value ? value3.Exclusive.Where((string type) => !Damage.Contains(type)).ToList() : new List<string>(value3.Exclusive));
					value5.Requirements.ExclusiveSelf = value3.ExclusiveSelf && !value;
				}
				if (flag2)
				{
					value5.SelectionWeight = (value ? (value3.Weight * 2f) : value3.Weight);
					if (value2)
					{
						value5.Config["CostScale"] = 0f;
					}
					else if (value3.HadCostScale)
					{
						value5.Config["CostScale"] = value3.CostScale;
					}
					else
					{
						value5.Config.Remove("CostScale");
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(SpawnAbility), "Setup")]
	internal static class SummonLimit
	{
		private static void Prefix(SpawnAbility __instance, ItemData item)
		{
			if (Plugin.ShotSummonLimit.Value && item != null && __instance.m_maxSpawned > 0 && ItemDataExtensions.HasMagicEffect(item, MagicEffectType.DoubleMagicShot, true))
			{
				__instance.m_maxSpawned *= 2;
			}
		}
	}
	[HarmonyPatch]
	internal static class ShardClashes
	{
		private static readonly MethodInfo Check = AccessTools.Method(typeof(MagicItemEffectRequirements), "CheckRequirements", new Type[9]
		{
			typeof(ItemData),
			typeof(MagicItem),
			typeof(RequirementFailure).MakeByRefType(),
			typeof(string).MakeByRefType(),
			typeof(string),
			typeof(bool),
			typeof(bool),
			typeof(bool),
			typeof(bool)
		}, (Type[])null);

		private static IEnumerable<MethodBase> TargetMethods()
		{
			Type manager = AccessTools.TypeByName("EpicLoot.ShardStones.ShardSocketManager");
			yield return AccessTools.Method(manager, "CanSocket", (Type[])null, (Type[])null);
			yield return AccessTools.Method(manager, "CanCoexist", (Type[])null, (Type[])null);
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int found = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (CodeInstructionExtensions.Calls(instruction, Check))
				{
					found++;
					yield return CodeInstructionExtensions.MoveLabelsFrom(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ShardClashes), "CheckForShard", (Type[])null, (Type[])null)), instruction);
				}
				else
				{
					yield return instruction;
				}
			}
			if (found == 0)
			{
				throw new Exception("Epic Loot's socket check has changed");
			}
		}

		private static bool CheckForShard(MagicItemEffectRequirements requirements, ItemData item, MagicItem magicItem, out RequirementFailure failure, out string conflict, string effectType, bool lootRoll, bool augmentRoll, bool runeRoll, bool itemTypeGating)
		{
			List<string> list = null;
			if (Plugin.ShardsIgnoreClashes.Value && !itemTypeGating && requirements.ExclusiveEffectTypes != null && requirements.ExclusiveEffectTypes.Count > 0)
			{
				list = requirements.ExclusiveEffectTypes;
				requirements.ExclusiveEffectTypes = new List<string>();
			}
			try
			{
				return requirements.CheckRequirements(item, magicItem, ref failure, ref conflict, effectType, lootRoll, augmentRoll, runeRoll, itemTypeGating);
			}
			finally
			{
				if (list != null)
				{
					requirements.ExclusiveEffectTypes = list;
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class LuckyLootMessage
	{
		internal sealed class Mark
		{
			internal CharacterDrop Owner;

			internal float Stamp;
		}

		[HarmonyPatch(typeof(Game), "Start")]
		internal static class Register
		{
			private static void Postfix()
			{
				ZRoutedRpc instance = ZRoutedRpc.instance;
				if (instance != null)
				{
					instance.Register<Vector3, string, int, int>("PotatoTweaks_LuckyLoot", (Method<Vector3, string, int, int>)Show);
				}
			}
		}

		private const string Rpc = "PotatoTweaks_LuckyLoot";

		private const float Range = 100f;

		private static readonly Type Lucky = AccessTools.TypeByName("EpicLoot.MagicItemEffects.Shards.LuckyLoot");

		private static readonly FieldRef<CharacterDrop> PendingOwner = AccessTools.StaticFieldRefAccess<CharacterDrop>(AccessTools.Field(Lucky, "_pendingOwner"));

		private static readonly FieldRef<int> PendingRolls = AccessTools.StaticFieldRefAccess<int>(AccessTools.Field(Lucky, "_pendingRolls"));

		private static readonly FieldRef<float> PendingStamp = AccessTools.StaticFieldRefAccess<float>(AccessTools.Field(Lucky, "_pendingStamp"));

		internal static readonly Func<Vector3, float> BestNearbyValue = AccessTools.MethodDelegate<Func<Vector3, float>>(AccessTools.Method(Lucky, "BestNearbyValue", (Type[])null, (Type[])null), (object)null, true);

		private static readonly FieldRef<CharacterDrop, Character> Creature = AccessTools.FieldRefAccess<CharacterDrop, Character>("m_character");

		internal static readonly Func<float, int> Multiplier = AccessTools.MethodDelegate<Func<float, int>>(AccessTools.Method(Lucky, "Multiplier", (Type[])null, (Type[])null), (object)null, true);

		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.Inner(Lucky, "LuckyLoot_CharacterDrop_GenerateDropList_Patch"), "Postfix", (Type[])null, (Type[])null);
		}

		private static void Prefix(out Mark __state)
		{
			__state = new Mark
			{
				Owner = PendingOwner.Invoke(),
				Stamp = PendingStamp.Invoke()
			};
		}

		private static void Postfix(CharacterDrop __0, Mark __state)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)__0) && !((Object)(object)PendingOwner.Invoke() != (Object)(object)__0) && (!((Object)(object)__state.Owner == (Object)(object)__0) || __state.Stamp != PendingStamp.Invoke()))
			{
				Character val = Creature.Invoke(__0);
				if (Object.op_Implicit((Object)(object)val))
				{
					Vector3 position = ((Component)val).transform.position;
					Send(position, val.m_name, Multiplier(BestNearbyValue(position)), PendingRolls.Invoke());
				}
			}
		}

		internal static void Send(Vector3 position, string name, int multiplier, int rolls)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null)
			{
				instance.InvokeRoutedRPC(ZNetView.Everybody, "PotatoTweaks_LuckyLoot", new object[4]
				{
					position,
					name ?? "",
					multiplier,
					rolls
				});
			}
		}

		private static void Show(long sender, Vector3 position, string name, int multiplier, int rolls)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (Plugin.LuckyLootMessage.Value && Object.op_Implicit((Object)(object)localPlayer) && !(Vector3.Distance(((Component)localPlayer).transform.position, position) > 100f))
			{
				StringBuilder stringBuilder = new StringBuilder("Lucky Loot! ").Append((Localization.instance != null) ? Localization.instance.Localize(name) : name).Append(':');
				stringBuilder.Append((multiplier > 1) ? $" {multiplier}x drops" : " more drops");
				if (rolls > 0)
				{
					stringBuilder.Append(string.Format(", +{0} magic item roll{1}", rolls, (rolls == 1) ? "" : "s"));
				}
				((Character)localPlayer).Message(Plugin.LuckyLootPosition.Value, stringBuilder.ToString(), 0, (Sprite)null, false);
			}
		}
	}
	[HarmonyPatch(typeof(DropOnDestroyed), "OnDestroyed")]
	internal static class LuckyBirds
	{
		[HarmonyPatch(typeof(DropTable), "GetDropList", new Type[] { })]
		internal static class Drops
		{
			private static void Postfix(List<GameObject> __result)
			{
				if (multiplier <= 1 || __result == null || __result.Count == 0)
				{
					return;
				}
				List<GameObject> list = __result.Where(delegate(GameObject drop)
				{
					//IL_003c: 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_004c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0051: Unknown result type (might be due to invalid IL or missing references)
					if (Object.op_Implicit((Object)(object)drop))
					{
						ItemDrop component = drop.GetComponent<ItemDrop>();
						if (component == null)
						{
							return true;
						}
						return component.m_itemData?.m_shared?.m_itemType != (ItemType?)13;
					}
					return false;
				}).ToList();
				int num = Mathf.Min(multiplier, Mathf.Max(1, 100 / Mathf.Max(1, list.Count)));
				for (int num2 = 1; num2 < num; num2++)
				{
					__result.AddRange(list);
				}
				multiplier = 0;
			}
		}

		[ThreadStatic]
		private static int multiplier;

		private static void Prefix(DropOnDestroyed __instance)
		{
			//IL_0033: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			multiplier = 0;
			if (!Plugin.LuckyLootBirds.Value || (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponentInParent<RandomFlyingBird>()) && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponentInChildren<RandomFlyingBird>())))
			{
				return;
			}
			Vector3 position = ((Component)__instance).transform.position;
			float num = LuckyLootMessage.BestNearbyValue(position);
			if (!(num <= 0f) && !(Random.value >= num * 0.01f))
			{
				int num2 = LuckyLootMessage.Multiplier(num);
				if (num2 > 1)
				{
					multiplier = num2;
					string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject);
					LuckyLootMessage.Send(position, (prefabName == "Seagal") ? "Seagull" : prefabName, num2, 0);
				}
			}
		}

		private static void Finalizer()
		{
			multiplier = 0;
		}
	}
	[HarmonyPatch(typeof(MagicTooltip), "AddEitrUse")]
	internal static class EitrTooltip
	{
		private static readonly FieldRef<MagicTooltip, ItemData> Item = AccessTools.FieldRefAccess<MagicTooltip, ItemData>("<item>P");

		private static readonly FieldRef<MagicTooltip, MagicItem> Magic = AccessTools.FieldRefAccess<MagicTooltip, MagicItem>("<magicItem>P");

		private static re