Decompiled source of VanillaNPC v1.1.0

plugins/VanillaNPC.dll

Decompiled 9 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FjordFolk.Bandits;
using FjordFolk.Beggar;
using FjordFolk.Fisher;
using FjordFolk.Guards;
using FjordFolk.Recruiters;
using FjordFolk.Tavern;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("VanillaNPC")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("VanillaNPC")]
[assembly: AssemblyTitle("VanillaNPC")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FjordFolk
{
	internal static class Loc
	{
		private const string Prefix = "fjordfolk_";

		private static readonly string[] Languages = new string[2] { "English", "Russian" };

		public static void Register()
		{
			string[] languages = Languages;
			for (int i = 0; i < languages.Length; i++)
			{
				string text = languages[i];
				string text2 = "FjordFolk.Localization." + text + ".txt";
				using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text2);
				if (stream == null)
				{
					FjordFolkPlugin.Log.LogError((object)("embedded " + text2 + " not found"));
					continue;
				}
				using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8);
				Dictionary<string, string> dictionary = Parse(streamReader.ReadToEnd());
				LocalizationManager.Instance.GetLocalization().AddTranslation(ref text, dictionary);
			}
		}

		public static string Token(string key)
		{
			return "$fjordfolk_" + key;
		}

		public static string T(string key)
		{
			if (Localization.instance == null)
			{
				return key;
			}
			return Localization.instance.Localize(Token(key));
		}

		public static string T(string key, params object[] args)
		{
			return string.Format(T(key), args);
		}

		private static Dictionary<string, string> Parse(string text)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			string[] array = text.Split('\n');
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim().TrimStart('\ufeff');
				if (text2.Length != 0 && !text2.StartsWith("#"))
				{
					int num = text2.IndexOf('=');
					if (num > 0)
					{
						string text3 = text2.Substring(0, num).Trim();
						string value = text2.Substring(num + 1).Trim().Replace("\\n", "\n");
						dictionary["fjordfolk_" + text3] = value;
					}
				}
			}
			return dictionary;
		}
	}
	public class NpcActor : MonoBehaviour, Hoverable, Interactable
	{
		public int m_presetId;

		[NonSerialized]
		public bool m_portrait;

		[NonSerialized]
		public string m_poseOverride;

		private static readonly int s_appearanceVersion = StringExtensionMethods.GetStableHashCode("fjordfolk_appearance_v1");

		private ZNetView m_nview;

		private VisEquipment m_vis;

		private FisherWorkplace m_work;

		private BeggarBehaviour m_beggar;

		private RecruiterCamp m_camp;

		private CraftingStation m_station;

		private Innkeeper m_inn;

		private Drunkard m_drunk;

		private NpcPreset m_preset;

		private NpcEmotes m_emotes;

		private void Awake()
		{
			FjordFolkPlugin.Guard("NpcActor.Awake", delegate
			{
				m_nview = ((Component)this).GetComponent<ZNetView>();
				m_vis = ((Component)this).GetComponent<VisEquipment>();
				m_work = ((Component)this).GetComponent<FisherWorkplace>();
				m_beggar = ((Component)this).GetComponent<BeggarBehaviour>();
				m_camp = ((Component)this).GetComponent<RecruiterCamp>();
				m_station = ((Component)this).GetComponent<CraftingStation>();
				m_inn = ((Component)this).GetComponent<Innkeeper>();
				m_drunk = ((Component)this).GetComponent<Drunkard>();
				m_preset = NpcPresets.Get(m_presetId);
				if ((Object)(object)m_vis == (Object)null || m_preset == null)
				{
					FjordFolkPlugin.Log.LogWarning((object)$"{((Object)this).name}: missing VisEquipment or preset {m_presetId}");
				}
				else
				{
					ZDO val = (((Object)(object)m_nview != (Object)null) ? m_nview.GetZDO() : null);
					if (val == null)
					{
						DressGhost(m_preset);
					}
					else if (m_nview.IsOwner() && !val.GetBool(s_appearanceVersion, false))
					{
						WriteAppearance(val, m_preset);
						val.Set(s_appearanceVersion, true);
					}
				}
			});
		}

		private void Start()
		{
			FjordFolkPlugin.Guard("NpcActor.Start", delegate
			{
				Animator componentInChildren = ((Component)this).GetComponentInChildren<Animator>();
				if (!((Object)(object)componentInChildren == (Object)null) && m_preset != null)
				{
					m_emotes = new NpcEmotes(componentInChildren);
					m_emotes.SkipWakeup();
					if (!m_portrait)
					{
						ApplyPose();
					}
				}
			});
		}

		private void WriteAppearance(ZDO zdo, NpcPreset p)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			zdo.Set(ZDOVars.s_modelIndex, p.Model, false);
			zdo.Set(ZDOVars.s_skinColor, p.SkinColor);
			zdo.Set(ZDOVars.s_hairColor, p.HairColor);
			zdo.Set(ZDOVars.s_hairItem, ItemHash(HairName(p)), false);
			zdo.Set(ZDOVars.s_beardItem, ItemHash(BeardName(p)), false);
			zdo.Set(ZDOVars.s_chestItem, ItemHash(p.Chest), false);
			zdo.Set(ZDOVars.s_legItem, ItemHash(p.Legs), false);
			zdo.Set(ZDOVars.s_helmetItem, ItemHash(p.Helmet), false);
			zdo.Set(ZDOVars.s_shoulderItem, ItemHash(p.Shoulder), false);
			zdo.Set(ZDOVars.s_rightItem, ItemHash(p.RightItem), false);
			zdo.Set(ZDOVars.s_leftItem, ItemHash(p.LeftItem), false);
		}

		private void DressGhost(NpcPreset p)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			m_vis.m_modelIndex = p.Model;
			m_vis.m_skinColor = p.SkinColor;
			m_vis.m_hairColor = p.HairColor;
			m_vis.m_hairItem = ItemHash(HairName(p));
			m_vis.m_beardItem = ItemHash(BeardName(p));
			m_vis.m_chestItem = ItemHash(p.Chest);
			m_vis.m_legItem = ItemHash(p.Legs);
			m_vis.m_helmetItem = ItemHash(p.Helmet);
			m_vis.m_shoulderItem = ItemHash(p.Shoulder);
			m_vis.m_rightItem = ItemHash(p.RightItem);
			m_vis.m_leftItem = ItemHash(p.LeftItem);
		}

		private static string HairName(NpcPreset p)
		{
			return Customization("Hair", p.HairIndex);
		}

		private static string BeardName(NpcPreset p)
		{
			return Customization("Beard", p.BeardIndex);
		}

		internal static string Customization(string prefix, int index)
		{
			if (index <= 0 || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return "";
			}
			List<string> list = (from i in ObjectDB.instance.GetAllItems((ItemType)10, prefix)
				where (Object)(object)i != (Object)null && !((Object)i).name.EndsWith("None")
				select ((Object)i).name into n
				orderby n.Length, n
				select n).ToList();
			if (list.Count != 0)
			{
				return list[Mathf.Clamp(index, 1, list.Count) - 1];
			}
			return "";
		}

		private int ItemHash(string itemName)
		{
			if (string.IsNullOrEmpty(itemName))
			{
				return 0;
			}
			if ((Object)(object)ObjectDB.instance != (Object)null && (Object)(object)ObjectDB.instance.GetItemPrefab(itemName) == (Object)null)
			{
				FjordFolkPlugin.Log.LogWarning((object)(((Object)this).name + ": item '" + itemName + "' does not exist, slot left empty"));
				return 0;
			}
			return StringExtensionMethods.GetStableHashCode(itemName);
		}

		private void ApplyPose()
		{
			if (m_emotes != null && m_preset != null)
			{
				((MonoBehaviour)this).CancelInvoke("ApplyPose");
				string text = ((!string.IsNullOrEmpty(m_poseOverride)) ? m_poseOverride : m_preset.Pose);
				if (string.IsNullOrEmpty(text))
				{
					m_emotes.StopAll();
				}
				else if (m_emotes.Play(text) == "missing")
				{
					FjordFolkPlugin.Log.LogWarning((object)(((Object)this).name + ": pose '" + text + "' not in animator"));
				}
			}
		}

		public void PlayGestureLocal(string emote, float returnAfter = 3.5f)
		{
			if (m_emotes != null && !string.IsNullOrEmpty(emote))
			{
				((MonoBehaviour)this).CancelInvoke("ApplyPose");
				m_emotes.Play(emote);
				if (returnAfter > 0f)
				{
					((MonoBehaviour)this).Invoke("ApplyPose", returnAfter);
				}
			}
		}

		public void ReturnToPose()
		{
			ApplyPose();
		}

		public string GetHoverName()
		{
			if (m_preset == null)
			{
				return "";
			}
			return m_preset.Name;
		}

		public string GetHoverText()
		{
			if (m_preset == null)
			{
				return "";
			}
			if ((Object)(object)m_work != (Object)null && m_work.IsLive)
			{
				return m_work.HoverText(m_preset.Name);
			}
			if ((Object)(object)m_beggar != (Object)null && m_beggar.IsLive)
			{
				return m_beggar.HoverText(m_preset.Name);
			}
			if ((Object)(object)m_camp != (Object)null && (Object)(object)m_nview != (Object)null && m_nview.IsValid())
			{
				return m_camp.HoverText(m_preset.Name);
			}
			if ((Object)(object)m_inn != (Object)null && (Object)(object)m_nview != (Object)null && m_nview.IsValid())
			{
				return m_inn.HoverText(m_preset.Name);
			}
			if ((Object)(object)m_drunk != (Object)null && (Object)(object)m_nview != (Object)null && m_nview.IsValid())
			{
				return m_drunk.HoverText(m_preset.Name);
			}
			return m_preset.Name;
		}

		public float GetHoverOffset()
		{
			return 0f;
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			if (hold || m_preset == null)
			{
				return false;
			}
			FjordFolkPlugin.Guard("NpcActor.Interact", delegate
			{
				if ((Object)(object)m_work != (Object)null)
				{
					if (m_work.IsLive && !FisherPanel.JustClosed)
					{
						FisherPanel.Open(m_work);
					}
				}
				else if ((Object)(object)m_beggar != (Object)null)
				{
					m_beggar.GiveCoin(user);
				}
				else if ((Object)(object)m_inn != (Object)null)
				{
					m_inn.OpenShop(user);
				}
				else if ((Object)(object)m_drunk != (Object)null)
				{
					m_drunk.Interact(user);
				}
				else if ((Object)(object)m_station != (Object)null)
				{
					m_station.Interact(user, false, alt);
				}
			});
			return true;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			if ((Object)(object)m_beggar == (Object)null || !m_beggar.IsLive || !BeggarBehaviour.IsCoin(item))
			{
				return false;
			}
			FjordFolkPlugin.Guard("NpcActor.UseItem", delegate
			{
				m_beggar.GiveCoin(user);
			});
			return true;
		}

		public void Say(string text)
		{
			//IL_000b: 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)
			Chat.instance.SetNpcText(((Component)this).gameObject, Vector3.up * 2.1f, 25f, 6f, "", text, false);
		}
	}
	internal sealed class NpcDialogue
	{
		private const string EmbeddedPrefix = "FjordFolk.Dialogue.";

		private static readonly string[] FallbackLanguages = new string[2] { "English", "Russian" };

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

		private static readonly Random s_random = new Random();

		private readonly Dictionary<string, List<string>> m_sections;

		private readonly Dictionary<string, Queue<string>> m_bags = new Dictionary<string, Queue<string>>();

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

		public string Source { get; }

		private NpcDialogue(Dictionary<string, List<string>> sections, string source)
		{
			m_sections = sections;
			Source = source;
		}

		public static NpcDialogue For(string dialogueId)
		{
			string text = ((Localization.instance != null) ? Localization.instance.GetSelectedLanguage() : "English");
			string key = dialogueId + "|" + text;
			if (s_cache.TryGetValue(key, out var value))
			{
				return value;
			}
			NpcDialogue npcDialogue = Load(dialogueId, text);
			s_cache[key] = npcDialogue;
			FjordFolkPlugin.Log.LogDebug((object)("dialogue '" + dialogueId + "' for " + text + ": " + npcDialogue.Source + ", " + $"{npcDialogue.m_sections.Count} sections, {Total(npcDialogue.m_sections)} lines"));
			return npcDialogue;
		}

		public bool Has(string section)
		{
			if (m_sections.TryGetValue(section, out var value))
			{
				return value.Count > 0;
			}
			return false;
		}

		public string Pick(string section)
		{
			if (!Has(section))
			{
				return null;
			}
			if (!m_bags.TryGetValue(section, out var value) || value.Count == 0)
			{
				value = Refill(section);
				m_bags[section] = value;
			}
			string text = value.Dequeue();
			m_lastPicked[section] = text;
			return text;
		}

		private Queue<string> Refill(string section)
		{
			List<string> list = new List<string>(m_sections[section]);
			for (int num = list.Count - 1; num > 0; num--)
			{
				int num2 = s_random.Next(num + 1);
				List<string> list2 = list;
				int index = num;
				List<string> list3 = list;
				int index2 = num2;
				string value = list[num2];
				string value2 = list[num];
				list2[index] = value;
				list3[index2] = value2;
			}
			if (list.Count > 1 && m_lastPicked.TryGetValue(section, out var value3) && list[0] == value3)
			{
				List<string> list3 = list;
				List<string> list2 = list;
				int index2 = list.Count - 1;
				string value2 = list[list.Count - 1];
				string value = list[0];
				list3[0] = value2;
				list2[index2] = value;
			}
			return new Queue<string>(list);
		}

		private static NpcDialogue Load(string dialogueId, string language)
		{
			List<string> list = new List<string> { language };
			string[] fallbackLanguages = FallbackLanguages;
			foreach (string item in fallbackLanguages)
			{
				if (!list.Contains(item))
				{
					list.Add(item);
				}
			}
			foreach (string item2 in list)
			{
				string text = dialogueId + "." + item2 + ".txt";
				string text2 = Path.Combine(Paths.ConfigPath, "VanillaNPC", "dialogue", text);
				if (File.Exists(text2))
				{
					return new NpcDialogue(Parse(File.ReadAllText(text2, Encoding.UTF8)), "override " + text2);
				}
				using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("FjordFolk.Dialogue." + text);
				if (stream == null)
				{
					continue;
				}
				using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8);
				string source = ((item2 == language) ? ("embedded " + text) : ("embedded " + text + " (no " + language + " translation)"));
				return new NpcDialogue(Parse(streamReader.ReadToEnd()), source);
			}
			FjordFolkPlugin.Log.LogWarning((object)("no dialogue file for '" + dialogueId + "' in any language"));
			return new NpcDialogue(new Dictionary<string, List<string>>(), "none");
		}

		private static Dictionary<string, List<string>> Parse(string text)
		{
			Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);
			List<string> value = null;
			string[] array = text.Split('\n');
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim().TrimStart('\ufeff');
				if (text2.Length == 0 || text2.StartsWith("#"))
				{
					continue;
				}
				if (text2.StartsWith("[") && text2.EndsWith("]"))
				{
					string key = text2.Substring(1, text2.Length - 2).Trim();
					if (!dictionary.TryGetValue(key, out value))
					{
						value = (dictionary[key] = new List<string>());
					}
				}
				else
				{
					value?.Add(text2);
				}
			}
			return dictionary;
		}

		private static int Total(Dictionary<string, List<string>> sections)
		{
			int num = 0;
			foreach (List<string> value in sections.Values)
			{
				num += value.Count;
			}
			return num;
		}
	}
	internal sealed class NpcEmotes
	{
		private static bool s_parametersLogged;

		private readonly Animator m_animator;

		private readonly Dictionary<string, AnimatorControllerParameter> m_params = new Dictionary<string, AnimatorControllerParameter>();

		private string m_activeLoop;

		public NpcEmotes(Animator animator)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			m_animator = animator;
			AnimatorControllerParameter[] parameters = animator.parameters;
			foreach (AnimatorControllerParameter val in parameters)
			{
				m_params[val.name.ToLowerInvariant()] = val;
			}
			if (!s_parametersLogged)
			{
				s_parametersLogged = true;
				List<string> list = new List<string>();
				parameters = animator.parameters;
				foreach (AnimatorControllerParameter val2 in parameters)
				{
					list.Add($"{val2.name}:{val2.type}");
				}
				FjordFolkPlugin.Log.LogDebug((object)string.Format("animator parameters ({0}): {1}", list.Count, string.Join(", ", list)));
			}
		}

		public void SkipWakeup()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			if (m_params.TryGetValue("wakeup", out var value) && (int)value.type == 4)
			{
				m_animator.SetBool(value.name, false);
			}
		}

		public string Play(string emote)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Invalid comparison between Unknown and I4
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Invalid comparison between Unknown and I4
			string key = (emote.StartsWith("attach_", StringComparison.OrdinalIgnoreCase) ? emote.ToLowerInvariant() : ("emote_" + emote.ToLowerInvariant()));
			if (!m_params.TryGetValue(key, out var value))
			{
				return "missing";
			}
			StopLoop();
			if (m_params.TryGetValue("emote_stop", out var value2))
			{
				m_animator.ResetTrigger(value2.name);
			}
			AnimatorControllerParameterType type = value.type;
			if ((int)type != 4)
			{
				if ((int)type == 9)
				{
					m_animator.SetTrigger(value.name);
					return "once";
				}
				return "missing";
			}
			m_animator.SetBool(value.name, true);
			m_activeLoop = value.name;
			return "loop";
		}

		public void StopAll()
		{
			StopLoop();
			if (m_params.TryGetValue("emote_stop", out var value))
			{
				m_animator.SetTrigger(value.name);
			}
		}

		private void StopLoop()
		{
			if (!string.IsNullOrEmpty(m_activeLoop))
			{
				m_animator.SetBool(m_activeLoop, false);
				m_activeLoop = null;
				if (m_params.TryGetValue("emote_stop", out var value))
				{
					m_animator.SetTrigger(value.name);
				}
			}
		}
	}
	public class NpcGreeter : MonoBehaviour
	{
		public string m_dialogueId = "";

		public float m_greetRange = 5f;

		public float m_byeRange = 9f;

		public string m_gesture = "wave";

		public bool m_holdGesture;

		private const float CheckInterval = 0.25f;

		private const float QuickReturnWindow = 120f;

		private const float PestWindow = 150f;

		private const int PestVisits = 2;

		private const float ShortVisit = 6f;

		private ZNetView m_nview;

		private NpcActor m_actor;

		private bool m_near;

		private float m_nearSince;

		private float m_leftAt = -9999f;

		private readonly List<float> m_visits = new List<float>();

		private float m_nextCheck;

		private string m_pending;

		private float m_pendingAt;

		private void Awake()
		{
			m_nview = ((Component)this).GetComponent<ZNetView>();
			m_actor = ((Component)this).GetComponent<NpcActor>();
		}

		private void Update()
		{
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid() || string.IsNullOrEmpty(m_dialogueId))
			{
				return;
			}
			if (m_pending != null && Time.time >= m_pendingAt)
			{
				string action = m_pending;
				m_pending = null;
				FjordFolkPlugin.Guard("NpcGreeter." + action, delegate
				{
					Perform(action);
				});
			}
			if (!(Time.time < m_nextCheck))
			{
				m_nextCheck = Time.time + 0.25f;
				FjordFolkPlugin.Guard("NpcGreeter.Update", CheckPlayer);
			}
		}

		private void CheckPlayer()
		{
			//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)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead())
			{
				return;
			}
			float num = Vector3.Distance(((Component)localPlayer).transform.position, ((Component)this).transform.position);
			if (!m_near && num < m_greetRange)
			{
				m_near = true;
				m_nearSince = Time.time;
				Schedule("greet", Random.Range(0.35f, 1.1f));
			}
			else if (m_near && num > m_byeRange)
			{
				m_near = false;
				if (m_pending == "greet")
				{
					m_pending = null;
					return;
				}
				m_leftAt = Time.time;
				Schedule("bye", Random.Range(0.2f, 0.7f));
			}
		}

		private void Schedule(string action, float delay)
		{
			m_pending = action;
			m_pendingAt = Time.time + delay;
		}

		private void Perform(string action)
		{
			NpcDialogue dialogue = NpcDialogue.For(m_dialogueId);
			if (action == "greet")
			{
				Greet(dialogue);
			}
			else
			{
				Goodbye(dialogue);
			}
		}

		private void Greet(NpcDialogue dialogue)
		{
			m_visits.RemoveAll((float t) => Time.time - t > 150f);
			int count = m_visits.Count;
			m_visits.Add(Time.time);
			string text = ((count >= 2) ? "greet_pest" : ((!(Time.time - m_leftAt < 120f)) ? (Lore(dialogue) ?? Situational("greet", "greet_first", dialogue)) : "greet_again"));
			bool flag = text == "greet_pest";
			bool num = flag || m_holdGesture || Random.value < 0.85f;
			bool flag2 = !string.IsNullOrEmpty(m_gesture) && (m_holdGesture || (!flag && Random.value < 0.8f));
			if (flag2)
			{
				m_actor?.PlayGestureLocal(m_gesture, m_holdGesture ? 0f : 3.5f);
			}
			string text2 = (num ? (dialogue.Pick(text) ?? dialogue.Pick("greet_first")) : null);
			if (text2 != null)
			{
				m_actor?.Say(text2);
			}
			Report("greet", text, flag2, text2);
		}

		private void Goodbye(NpcDialogue dialogue)
		{
			if (m_holdGesture)
			{
				m_actor?.ReturnToPose();
			}
			string section = ((Time.time - m_nearSince < 6f && Random.value < 0.7f) ? "bye_short" : Situational("bye", "bye", dialogue));
			string text = ((Random.value < 0.7f) ? (dialogue.Pick(section) ?? dialogue.Pick("bye")) : null);
			if (text != null)
			{
				m_actor?.Say(text);
			}
			Report("bye", section, gestured: false, text);
		}

		private static string Lore(NpcDialogue dialogue)
		{
			if (dialogue.Has("greet_brother") && BeggarLore.MetRecently && Random.value < 0.5f)
			{
				return "greet_brother";
			}
			if (dialogue.Has("greet_hired") && Random.value < 0.35f && FisherRules.FishermanExists())
			{
				return "greet_hired";
			}
			return null;
		}

		private static string Situational(string prefix, string plain, NpcDialogue dialogue)
		{
			EnvMan instance = EnvMan.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return plain;
			}
			float dayFraction = instance.GetDayFraction();
			return Try("rain", EnvMan.IsWet(), 0.45f) ?? Try("night", EnvMan.IsNight(), 0.4f) ?? Try("morning", dayFraction > 0.22f && dayFraction < 0.38f, 0.35f) ?? Try("evening", dayFraction > 0.62f && dayFraction < 0.76f, 0.35f) ?? plain;
			string Try(string suffix, bool when, float chance)
			{
				string text = prefix + "_" + suffix;
				if (!when || !dialogue.Has(text) || !(Random.value < chance))
				{
					return null;
				}
				return text;
			}
		}

		private void Report(string action, string section, bool gestured, string line)
		{
			string text = ((line == null) ? "(silent)" : ("\"" + line + "\""));
			FjordFolkPlugin.Log.LogDebug((object)(m_dialogueId + " " + action + ": [" + section + "]" + (gestured ? (" +" + m_gesture) : "") + " " + text));
		}
	}
	internal sealed class NpcIcons : MonoBehaviour
	{
		private static readonly List<string> s_prefabs = new List<string>();

		private static bool s_started;

		internal static bool Staging { get; private set; }

		public static void Add(string prefabName)
		{
			if (!s_prefabs.Contains(prefabName))
			{
				s_prefabs.Add(prefabName);
			}
		}

		private void Update()
		{
			if (!s_started && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)ZNetScene.instance == (Object)null) && !((Object)(object)ObjectDB.instance == (Object)null))
			{
				s_started = true;
				((MonoBehaviour)this).StartCoroutine(RenderAll());
			}
		}

		private IEnumerator RenderAll()
		{
			yield return (object)new WaitForSeconds(3f);
			int rendered = 0;
			foreach (string s_prefab in s_prefabs)
			{
				GameObject prefab = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(s_prefab) : null);
				Piece piece = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Piece>() : null);
				if ((Object)(object)piece == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
				{
					continue;
				}
				GameObject stage = null;
				Staging = true;
				FjordFolkPlugin.Guard("NpcIcons.Stage", delegate
				{
					stage = Stage(prefab);
				});
				Staging = false;
				if ((Object)(object)stage == (Object)null)
				{
					continue;
				}
				yield return (object)new WaitForSeconds(1.5f);
				Staging = true;
				FjordFolkPlugin.Guard("NpcIcons.Render", delegate
				{
					//IL_000b: Unknown result type (might be due to invalid IL or missing references)
					//IL_0010: Unknown result type (might be due to invalid IL or missing references)
					//IL_001b: Unknown result type (might be due to invalid IL or missing references)
					//IL_0026: Unknown result type (might be due to invalid IL or missing references)
					//IL_0036: Unknown result type (might be due to invalid IL or missing references)
					//IL_0040: Unknown result type (might be due to invalid IL or missing references)
					//IL_004c: Expected O, but got Unknown
					//IL_0057: Unknown result type (might be due to invalid IL or missing references)
					//IL_005c: Unknown result type (might be due to invalid IL or missing references)
					Sprite val = RenderManager.Instance.Render(new RenderRequest(stage)
					{
						Width = 128,
						Height = 128,
						Rotation = Quaternion.Euler(8f, -30f, 0f),
						UseCache = false
					});
					if (!((Object)(object)val == (Object)null))
					{
						Rect rect = val.rect;
						if (!(((Rect)(ref rect)).width <= 1f))
						{
							piece.m_icon = val;
							int num = rendered;
							rendered = num + 1;
						}
					}
				});
				Staging = false;
				Object.Destroy((Object)(object)stage);
			}
			FjordFolkPlugin.Log.LogDebug((object)$"NPC icons rendered: {rendered} of {s_prefabs.Count}");
		}

		private static GameObject Stage(GameObject prefab)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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)
			Vector3 val = ((Component)Player.m_localPlayer).transform.position + new Vector3(0f, 600f, 0f);
			ZNetView.m_forceDisableInit = true;
			GameObject val2;
			try
			{
				val2 = Object.Instantiate<GameObject>(prefab, val, Quaternion.identity);
			}
			finally
			{
				ZNetView.m_forceDisableInit = false;
			}
			NpcActor component = val2.GetComponent<NpcActor>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_portrait = true;
			}
			Collider[] componentsInChildren = val2.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].enabled = false;
			}
			Animator[] componentsInChildren2 = val2.GetComponentsInChildren<Animator>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				componentsInChildren2[i].cullingMode = (AnimatorCullingMode)0;
			}
			return val2;
		}
	}
	internal static class NpcPieces
	{
		private static readonly HashSet<string> KeepTypes = new HashSet<string>
		{
			"Transform", "ZNetView", "VisEquipment", "Animator", "SkinnedMeshRenderer", "MeshRenderer", "MeshFilter", "LODGroup", "CapsuleCollider", "SphereCollider",
			"BoxCollider", "MeshCollider", "MagicaCloth", "MagicaCapsuleCollider", "MagicaSphereCollider", "MagicaPlaneCollider"
		};

		public static void RegisterAll()
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab("Player");
			if ((Object)(object)prefab == (Object)null)
			{
				FjordFolkPlugin.Log.LogError((object)"vanilla 'Player' prefab not found, nothing registered");
				return;
			}
			FisherPieces.Register(prefab);
			BeggarPieces.Register(prefab);
			GuardPieces.Register(prefab);
			RecruiterPieces.Register(prefab);
			TavernPieces.Register(prefab);
			BanditPieces.Register(prefab);
		}

		internal static GameObject BuildNpc(GameObject player, string prefabName, int presetId)
		{
			GameObject val = PrefabManager.Instance.CreateClonedPrefab(prefabName, player);
			Strip(val);
			ZNetView component = val.GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null)
			{
				FjordFolkPlugin.Log.LogError((object)(prefabName + ": ZNetView lost during strip"));
				return null;
			}
			component.m_persistent = true;
			val.AddComponent<NpcActor>().m_presetId = presetId;
			NpcPreset npcPreset = NpcPresets.Get(presetId);
			if (npcPreset != null && !string.IsNullOrEmpty(npcPreset.DialogueId))
			{
				NpcGreeter npcGreeter = val.AddComponent<NpcGreeter>();
				npcGreeter.m_dialogueId = npcPreset.DialogueId;
				npcGreeter.m_gesture = npcPreset.Greet;
				npcGreeter.m_holdGesture = npcPreset.HoldGreet;
			}
			if ((Object)(object)val.GetComponent<Piece>() == (Object)null)
			{
				val.AddComponent<Piece>();
			}
			return val;
		}

		internal static void AddToHammer(GameObject prefab, string nameToken, string descriptionToken, string iconItem, RequirementConfig[] requirements)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			if (!((Object)(object)prefab == (Object)null))
			{
				PieceConfig val = new PieceConfig
				{
					Name = nameToken,
					Description = descriptionToken,
					PieceTable = "Hammer",
					Category = "Misc",
					Icon = IconOf(iconItem),
					Requirements = requirements
				};
				PieceManager.Instance.AddPiece(new CustomPiece(prefab, false, val));
				NpcIcons.Add(((Object)prefab).name);
				FjordFolkPlugin.Log.LogDebug((object)("registered " + ((Object)prefab).name));
			}
		}

		private static void Strip(GameObject prefab)
		{
			for (int i = 0; i < 10; i++)
			{
				List<Component> list = (from c in prefab.GetComponentsInChildren<Component>(true)
					where (Object)(object)c != (Object)null && !KeepTypes.Contains(((object)c).GetType().Name)
					orderby (!(c is MonoBehaviour)) ? 1 : 0
					select c).ToList();
				if (list.Count == 0)
				{
					break;
				}
				foreach (Component item in list)
				{
					Object.DestroyImmediate((Object)(object)item);
				}
				int num = prefab.GetComponentsInChildren<Component>(true).Count((Component c) => (Object)(object)c != (Object)null && !KeepTypes.Contains(((object)c).GetType().Name));
				if (num == list.Count)
				{
					FjordFolkPlugin.Log.LogWarning((object)$"{((Object)prefab).name}: {num} components could not be removed");
					break;
				}
			}
			int num2 = LayerMask.NameToLayer("piece");
			Collider[] componentsInChildren = prefab.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if (val.isTrigger)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
				else if (num2 >= 0)
				{
					((Component)val).gameObject.layer = num2;
				}
			}
		}

		internal static Sprite IconOf(string itemName)
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(itemName);
			Sprite[] array = ((!((Object)(object)prefab != (Object)null)) ? null : prefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_icons);
			if (array == null || array.Length == 0)
			{
				return null;
			}
			return array[0];
		}
	}
	internal sealed class NpcPreset
	{
		public int Id;

		public string NameKey;

		public int Model;

		public Vector3 SkinColor;

		public Vector3 HairColor;

		public int HairIndex;

		public int BeardIndex;

		public string Chest = "";

		public string Legs = "";

		public string Helmet = "";

		public string Shoulder = "";

		public string RightItem = "";

		public string LeftItem = "";

		public string Pose = "";

		public string Greet = "";

		public bool HoldGreet;

		public string DialogueId = "";

		public string Name => Loc.T(NameKey);
	}
	internal static class NpcPresets
	{
		public const int FishermanId = 1;

		public const int BeggarId = 2;

		public const int RecruiterId = 3;

		public const int RecruiterGuardLeftId = 4;

		public const int RecruiterGuardRightId = 5;

		public const int InnkeeperId = 6;

		public const int DrunkardId = 7;

		public const int RegularBodvarId = 8;

		public const int RegularHjaltiId = 9;

		private static readonly NpcPreset[] All = new NpcPreset[9]
		{
			new NpcPreset
			{
				Id = 1,
				NameKey = "knut_name",
				Model = 0,
				SkinColor = new Vector3(0.85f, 0.72f, 0.6f),
				HairColor = new Vector3(0.62f, 0.28f, 0.12f),
				HairIndex = 9,
				BeardIndex = 2,
				Chest = "ArmorRagsChest",
				Legs = "ArmorRagsLegs",
				Helmet = "HelmetFishingHat",
				RightItem = "FishingRod",
				Pose = "sit",
				Greet = "wave",
				DialogueId = "fisher"
			},
			new NpcPreset
			{
				Id = 2,
				NameKey = "ulv_name",
				Model = 0,
				SkinColor = new Vector3(0.85f, 0.72f, 0.6f),
				HairColor = new Vector3(0.45f, 0.34f, 0.22f),
				HairIndex = 8,
				BeardIndex = 10,
				Chest = "ArmorRagsChest",
				Legs = "ArmorRagsLegs",
				Helmet = "HelmetSweatBand",
				Pose = "sit",
				Greet = "cower",
				HoldGreet = true,
				DialogueId = "beggar"
			},
			new NpcPreset
			{
				Id = 3,
				NameKey = "hrodgeir_name",
				Model = 0,
				SkinColor = new Vector3(0.85f, 0.72f, 0.6f),
				HairColor = new Vector3(0.62f, 0.28f, 0.12f),
				HairIndex = 7,
				BeardIndex = 12,
				Chest = "ArmorTunic6",
				Legs = "ArmorLeatherLegs",
				Shoulder = "CapeLox",
				Helmet = "HelmetHat1",
				Greet = "comehere",
				DialogueId = "recruiter"
			},
			new NpcPreset
			{
				Id = 4,
				NameKey = "recruiter_guard_name",
				Model = 0,
				SkinColor = new Vector3(0.85f, 0.72f, 0.6f),
				HairColor = new Vector3(0.45f, 0.34f, 0.22f),
				HairIndex = 9,
				BeardIndex = 8,
				Chest = "ArmorBronzeChest",
				Legs = "ArmorBronzeLegs",
				Shoulder = "CapeLinen",
				Helmet = "HelmetBronze",
				RightItem = "SpearBronze",
				LeftItem = "ShieldBronzeBuckler"
			},
			new NpcPreset
			{
				Id = 5,
				NameKey = "recruiter_guard_name",
				Model = 0,
				SkinColor = new Vector3(0.85f, 0.72f, 0.6f),
				HairColor = new Vector3(0.45f, 0.34f, 0.22f),
				HairIndex = 9,
				BeardIndex = 8,
				Chest = "ArmorBronzeChest",
				Legs = "ArmorBronzeLegs",
				Shoulder = "CapeLinen",
				Helmet = "HelmetBronze",
				RightItem = "SpearBronze",
				LeftItem = "ShieldBronzeBuckler"
			},
			new NpcPreset
			{
				Id = 6,
				NameKey = "innkeeper_name",
				Model = 0,
				SkinColor = new Vector3(0.85f, 0.72f, 0.6f),
				HairColor = new Vector3(0.62f, 0.28f, 0.12f),
				HairIndex = 6,
				BeardIndex = 12,
				Chest = "ArmorDeepNorthMediumChest",
				Legs = "ArmorDeepNorthMediumlegs",
				RightItem = "Tankard",
				Greet = "toast",
				DialogueId = "innkeeper"
			},
			new NpcPreset
			{
				Id = 7,
				NameKey = "drunkard_name",
				Model = 0,
				SkinColor = new Vector3(0.85f, 0.72f, 0.6f),
				HairColor = new Vector3(0.45f, 0.34f, 0.22f),
				HairIndex = 11,
				BeardIndex = 5,
				Chest = "ArmorTunic3",
				Legs = "ArmorRagsLegs",
				Helmet = "HelmetMidsummerCrown",
				RightItem = "Tankard_dvergr",
				Greet = "laugh",
				DialogueId = "drunkard"
			},
			new NpcPreset
			{
				Id = 8,
				NameKey = "regular_bodvar_name",
				Model = 0,
				SkinColor = new Vector3(0.85f, 0.72f, 0.6f),
				HairColor = new Vector3(0.2f, 0.14f, 0.1f),
				HairIndex = 3,
				BeardIndex = 8,
				Chest = "ArmorTunic5",
				Legs = "ArmorTrollLeatherLegs",
				Shoulder = "CapeLinen",
				Helmet = "HelmetHat8",
				RightItem = "Tankard",
				Greet = "toast"
			},
			new NpcPreset
			{
				Id = 9,
				NameKey = "regular_hjalti_name",
				Model = 0,
				SkinColor = new Vector3(0.85f, 0.72f, 0.6f),
				HairColor = new Vector3(0.45f, 0.34f, 0.22f),
				HairIndex = 6,
				BeardIndex = 6,
				Chest = "ArmorTunic8",
				Legs = "ArmorLeatherLegs",
				Shoulder = "CapeFeather",
				Helmet = "HelmetHat2",
				RightItem = "Tankard",
				Greet = "toast"
			}
		};

		public static NpcPreset Get(int id)
		{
			NpcPreset[] all = All;
			foreach (NpcPreset npcPreset in all)
			{
				if (npcPreset.Id == id)
				{
					return npcPreset;
				}
			}
			return null;
		}
	}
	internal static class PieceKit
	{
		public static readonly HashSet<string> Scenery = new HashSet<string> { "Transform", "MeshRenderer", "MeshFilter", "SkinnedMeshRenderer", "Cloth", "LODGroup", "BoxCollider", "CapsuleCollider", "SphereCollider", "MeshCollider" };

		public static readonly HashSet<string> Decor = new HashSet<string>(Scenery) { "Light", "LightFlicker", "LightLod", "ParticleSystem", "ParticleSystemRenderer" };

		public static void ShowUndamaged(GameObject go)
		{
			WearNTear[] componentsInChildren = go.GetComponentsInChildren<WearNTear>(true);
			foreach (WearNTear val in componentsInChildren)
			{
				if ((Object)(object)val.m_worn != (Object)null && (Object)(object)val.m_worn != (Object)(object)val.m_new)
				{
					val.m_worn.SetActive(false);
				}
				if ((Object)(object)val.m_broken != (Object)null && (Object)(object)val.m_broken != (Object)(object)val.m_new)
				{
					val.m_broken.SetActive(false);
				}
				if ((Object)(object)val.m_new != (Object)null)
				{
					val.m_new.SetActive(true);
				}
			}
		}

		public static void StripTo(GameObject go, HashSet<string> keep)
		{
			for (int i = 0; i < 10; i++)
			{
				List<Component> list = (from c in go.GetComponentsInChildren<Component>(true)
					where (Object)(object)c != (Object)null && !keep.Contains(((object)c).GetType().Name)
					orderby (!(c is MonoBehaviour)) ? 1 : 0
					select c).ToList();
				if (list.Count == 0)
				{
					break;
				}
				foreach (Component item in list)
				{
					Object.DestroyImmediate((Object)(object)item);
				}
			}
		}

		public static void KeepSolidColliders(GameObject go, int layer = -1)
		{
			Collider[] componentsInChildren = go.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if (val.isTrigger)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
				else if (layer >= 0)
				{
					((Component)val).gameObject.layer = layer;
				}
			}
		}

		public static void RemoveColliders(GameObject go)
		{
			Collider[] componentsInChildren = go.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
		}

		public static Bounds ActiveBounds(Transform root, Transform space)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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_00a0: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = default(Bounds);
			bool any = false;
			Matrix4x4 worldToLocalMatrix = space.worldToLocalMatrix;
			MeshFilter[] componentsInChildren = ((Component)root).GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val in componentsInChildren)
			{
				if (IsSwitchedOn(((Component)val).transform, root) && (Object)(object)((Component)val).GetComponent<Renderer>() != (Object)null)
				{
					Encapsulate(ref bounds, ref any, val.sharedMesh, worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix);
				}
			}
			SkinnedMeshRenderer[] componentsInChildren2 = ((Component)root).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val2 in componentsInChildren2)
			{
				if (IsSwitchedOn(((Component)val2).transform, root))
				{
					Encapsulate(ref bounds, ref any, val2.sharedMesh, worldToLocalMatrix * ((Component)val2).transform.localToWorldMatrix);
				}
			}
			return bounds;
		}

		public static Bounds ColliderBounds(Transform root, Transform space)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = default(Bounds);
			bool any = false;
			Matrix4x4 worldToLocalMatrix = space.worldToLocalMatrix;
			Collider[] componentsInChildren = ((Component)root).GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if (val.isTrigger || !IsSwitchedOn(((Component)val).transform, root))
				{
					continue;
				}
				Matrix4x4 matrix = worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix;
				Collider val2 = val;
				BoxCollider val3 = (BoxCollider)(object)((val2 is BoxCollider) ? val2 : null);
				if (val3 == null)
				{
					MeshCollider val4 = (MeshCollider)(object)((val2 is MeshCollider) ? val2 : null);
					if (val4 == null)
					{
						SphereCollider val5 = (SphereCollider)(object)((val2 is SphereCollider) ? val2 : null);
						if (val5 == null)
						{
							CapsuleCollider val6 = (CapsuleCollider)(object)((val2 is CapsuleCollider) ? val2 : null);
							if (val6 != null)
							{
								Vector3 val7 = Vector3.one * val6.radius * 2f;
								((Vector3)(ref val7))[val6.direction] = Mathf.Max(val6.height, val6.radius * 2f);
								EncapsulateBox(ref bounds, ref any, new Bounds(val6.center, val7), matrix);
							}
						}
						else
						{
							EncapsulateBox(ref bounds, ref any, new Bounds(val5.center, Vector3.one * val5.radius * 2f), matrix);
						}
					}
					else if ((Object)(object)val4.sharedMesh != (Object)null)
					{
						EncapsulateBox(ref bounds, ref any, val4.sharedMesh.bounds, matrix);
					}
				}
				else
				{
					EncapsulateBox(ref bounds, ref any, new Bounds(val3.center, val3.size), matrix);
				}
			}
			return bounds;
		}

		private static bool IsSwitchedOn(Transform t, Transform root)
		{
			Transform val = t;
			while ((Object)(object)val != (Object)null)
			{
				if (!((Component)val).gameObject.activeSelf)
				{
					return false;
				}
				if ((Object)(object)val == (Object)(object)root)
				{
					return true;
				}
				val = val.parent;
			}
			return true;
		}

		private static void Encapsulate(ref Bounds bounds, ref bool any, Mesh mesh, Matrix4x4 matrix)
		{
			//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)
			if ((Object)(object)mesh != (Object)null)
			{
				EncapsulateBox(ref bounds, ref any, mesh.bounds, matrix);
			}
		}

		private static void EncapsulateBox(ref Bounds bounds, ref bool any, Bounds b, Matrix4x4 matrix)
		{
			//IL_001e: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_0070: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < 8; i++)
			{
				Vector3 val = ((Matrix4x4)(ref matrix)).MultiplyPoint3x4(new Vector3(((i & 1) == 0) ? ((Bounds)(ref b)).min.x : ((Bounds)(ref b)).max.x, ((i & 2) == 0) ? ((Bounds)(ref b)).min.y : ((Bounds)(ref b)).max.y, ((i & 4) == 0) ? ((Bounds)(ref b)).min.z : ((Bounds)(ref b)).max.z));
				if (!any)
				{
					bounds = new Bounds(val, Vector3.zero);
					any = true;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(val);
				}
			}
		}

		public static string Describe(GameObject go)
		{
			return string.Join(", ", from c in go.GetComponentsInChildren<Component>(true)
				where (Object)(object)c != (Object)null && !(c is Transform)
				group c by ((object)c).GetType().Name into g
				orderby g.Key
				select (g.Count() <= 1) ? g.Key : $"{g.Key} x{g.Count()}");
		}

		public static List<RequirementConfig> CostOf(string pieceName)
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(pieceName);
			return ((prefab != null) ? prefab.GetComponent<Piece>() : null)?.m_resources?.Where((Requirement r) => (Object)(object)r?.m_resItem != (Object)null && r.m_amount > 0).Select((Func<Requirement, RequirementConfig>)((Requirement r) => new RequirementConfig(((Object)r.m_resItem).name, r.m_amount, 0, true))).ToList() ?? new List<RequirementConfig>();
		}

		public static string BaseName(string name)
		{
			int num = name.IndexOf(" (", StringComparison.Ordinal);
			if (num > 0)
			{
				name = name.Substring(0, num);
			}
			return name.Replace("(Clone)", "").Trim();
		}

		public static string Fmt(Bounds b)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_004b: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			return $"center ({((Bounds)(ref b)).center.x:0.00}, {((Bounds)(ref b)).center.y:0.00}, {((Bounds)(ref b)).center.z:0.00}) size ({((Bounds)(ref b)).size.x:0.00}, {((Bounds)(ref b)).size.y:0.00}, {((Bounds)(ref b)).size.z:0.00})";
		}
	}
	[BepInPlugin("fedorovdgap.vanillanpc", "VanillaNPC", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInIncompatibility("fedorovdgap.fjordfolk")]
	[BepInProcess("valheim.exe")]
	public class FjordFolkPlugin : BaseUnityPlugin
	{
		public const string PluginId = "fedorovdgap.vanillanpc";

		public const string PluginName = "VanillaNPC";

		public const string PluginVersion = "1.1.0";

		public const string FormerPluginId = "fedorovdgap.fjordfolk";

		public const string ConfigFolder = "VanillaNPC";

		internal static ManualLogSource Log;

		private static readonly HashSet<string> s_failedOnce = new HashSet<string>();

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			FisherConfig.Bind(((BaseUnityPlugin)this).Config);
			BeggarConfig.Bind(((BaseUnityPlugin)this).Config);
			GuardConfig.Bind(((BaseUnityPlugin)this).Config);
			Guard("Loc.Register", Loc.Register);
			Guard("Harmony", delegate
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				new Harmony("fedorovdgap.vanillanpc").PatchAll(typeof(FjordFolkPlugin).Assembly);
			});
			((Component)this).gameObject.AddComponent<BeggarSpawner>();
			((Component)this).gameObject.AddComponent<GuardFollowService>();
			((Component)this).gameObject.AddComponent<BanditReminders>();
			((Component)this).gameObject.AddComponent<NpcIcons>();
			PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable;
		}

		private void OnVanillaPrefabsAvailable()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable;
			Guard("RegisterAll", NpcPieces.RegisterAll);
		}

		internal static void Guard(string where, Action action)
		{
			try
			{
				action();
			}
			catch (Exception arg)
			{
				if (s_failedOnce.Add(where))
				{
					Log.LogError((object)$"{where} failed (repeats are not logged): {arg}");
				}
			}
		}
	}
	internal static class VanillaUi
	{
		public sealed class Window
		{
			public RectTransform Root;

			public float Width;

			public TMP_Text Title;

			public Image Icon;

			public TMP_Text LevelText;

			public UITooltip LevelTooltip;

			public readonly List<Button> Tabs = new List<Button>();

			public Rect ContentArea;

			public GameObject List;

			public RectTransform ListRoot;

			public float ListSpacing;

			public GameObject Details;

			public Image DetailsIcon;

			public TMP_Text DetailsName;

			public TMP_Text DetailsText;

			public TMP_Text DetailsFooter;

			public readonly List<Tile> Requirements = new List<Tile>();

			public TMP_Text RequirementLevel;

			public UITooltip RequirementLevelTooltip;

			public Button ActionButton;
		}

		public sealed class ListEntry
		{
			public GameObject Root;

			public Image Icon;

			public TMP_Text Name;

			public TMP_Text Badge;

			public GameObject Selected;

			public Button Button;
		}

		public enum TextStyle
		{
			Header,
			Body,
			Big
		}

		public sealed class Slot
		{
			public RectTransform Rect;

			public Image Icon;

			public TMP_Text Amount;

			public GameObject Selected;

			public Button Button;

			public UITooltip Tooltip;

			public void Show(Sprite icon, int amount, bool dim)
			{
				//IL_0050: 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)
				if ((Object)(object)Icon != (Object)null)
				{
					Icon.sprite = icon;
					((Behaviour)Icon).enabled = (Object)(object)icon != (Object)null;
					((Graphic)Icon).color = (Color)(dim ? new Color(1f, 1f, 1f, 0.45f) : Color.white);
				}
				if ((Object)(object)Amount != (Object)null)
				{
					Amount.text = ((amount > 0) ? amount.ToString() : "");
					((Component)Amount).gameObject.SetActive(amount > 0);
				}
			}
		}

		public sealed class Tile
		{
			public GameObject Root;

			public Image Icon;

			public TMP_Text Name;

			public TMP_Text Amount;

			public UITooltip Tooltip;
		}

		private static readonly HashSet<string> Behaviours = new HashSet<string> { "SkillsDialog", "UIGroupHandler", "UIGamePad", "Localize", "UIInputHandler", "UIDragHandler", "InventoryElement", "ScrollRectEnsureVisible", "EventTrigger" };

		private static readonly HashSet<string> Layouts = new HashSet<string> { "ContentSizeFitter", "LayoutElement", "VerticalLayoutGroup", "HorizontalLayoutGroup", "GridLayoutGroup" };

		public static readonly Color Red = new Color(1f, 0.25f, 0.25f);

		private static GameObject s_holder;

		public static Vector2 ButtonSize => SizeOf((RectTransform)((Component)InventoryGui.instance.m_takeAllButton).transform, new Vector2(133f, 40f));

		public static float SlotNaturalSize => SizeOf((RectTransform)InventoryGui.instance.m_playerGrid.m_elementPrefab.transform, new Vector2(64f, 64f)).x;

		public static float SlotSpacing => Mathf.Max(SlotNaturalSize, InventoryGui.instance.m_playerGrid.m_elementSpace);

		public static string MissingPart()
		{
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return "InventoryGui";
			}
			if ((Object)(object)instance.m_crafting == (Object)null || (Object)(object)instance.m_craftingStationName == (Object)null)
			{
				return "crafting panel";
			}
			if ((Object)(object)instance.m_tabCraft == (Object)null || (Object)(object)instance.m_tabUpgrade == (Object)null)
			{
				return "tabs";
			}
			if ((Object)(object)instance.m_recipeListRoot == (Object)null || (Object)(object)instance.m_recipeElementPrefab == (Object)null)
			{
				return "recipe list";
			}
			if ((Object)(object)instance.m_recipeName == (Object)null || (Object)(object)instance.m_recipeDecription == (Object)null || (Object)(object)instance.m_itemCraftType == (Object)null)
			{
				return "description";
			}
			if (instance.m_recipeRequirementList == null || instance.m_recipeRequirementList.Length == 0)
			{
				return "requirements";
			}
			if ((Object)(object)instance.m_craftButton == (Object)null || (Object)(object)instance.m_takeAllButton == (Object)null)
			{
				return "buttons";
			}
			if ((Object)(object)instance.m_playerGrid == (Object)null || (Object)(object)instance.m_playerGrid.m_elementPrefab == (Object)null)
			{
				return "inventory slot";
			}
			return null;
		}

		public static Transform GuiRoot()
		{
			Canvas val = (((Object)(object)InventoryGui.instance != (Object)null) ? ((Component)InventoryGui.instance).GetComponentInParent<Canvas>(true) : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((Component)val.rootCanvas).transform;
		}

		public static Window CreateWindow(Transform parent, string title, IList<string> tabs, Action<int> onTab)
		{
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: 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_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04da: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e4: Expected O, but got Unknown
			//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d0: Expected O, but got Unknown
			//IL_07e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_07fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0807: Unknown result type (might be due to invalid IL or missing references)
			//IL_080f: Unknown result type (might be due to invalid IL or missing references)
			//IL_081b: Unknown result type (might be due to invalid IL or missing references)
			//IL_08d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_08e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_08ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_08f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0861: Unknown result type (might be due to invalid IL or missing references)
			//IL_086b: Expected O, but got Unknown
			//IL_0866: Unknown result type (might be due to invalid IL or missing references)
			//IL_086b: Unknown result type (might be due to invalid IL or missing references)
			//IL_087b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0885: Expected O, but got Unknown
			//IL_0880: Unknown result type (might be due to invalid IL or missing references)
			//IL_0885: Unknown result type (might be due to invalid IL or missing references)
			//IL_08bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_08c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0730: Unknown result type (might be due to invalid IL or missing references)
			//IL_073a: Expected O, but got Unknown
			//IL_0749: Unknown result type (might be due to invalid IL or missing references)
			//IL_0753: Expected O, but got Unknown
			InventoryGui instance = InventoryGui.instance;
			RectTransform source = instance.m_crafting;
			var anon = new
			{
				Title = PathOf((Component)(object)instance.m_craftingStationName),
				Icon = PathOf((Component)(object)instance.m_craftingStationIcon),
				Level = PathOf((Component)(object)instance.m_craftingStationLevelRoot),
				LevelText = PathOf((Component)(object)instance.m_craftingStationLevel),
				Tabs = new string[2]
				{
					PathOf((Component)(object)instance.m_tabCraft),
					PathOf((Component)(object)instance.m_tabUpgrade)
				},
				List = TopOf((Component)(object)instance.m_recipeListRoot),
				ListRoot = PathOf((Component)(object)instance.m_recipeListRoot),
				Details = TopOf((Component)(object)instance.m_recipeName),
				DetailsIcon = PathOf((Component)(object)instance.m_recipeIcon),
				DetailsName = PathOf((Component)(object)instance.m_recipeName),
				DetailsText = PathOf((Component)(object)instance.m_recipeDecription),
				DetailsFooter = PathOf((Component)(object)instance.m_itemCraftType),
				Requirements = instance.m_recipeRequirementList.Select((GameObject r) => (!((Object)(object)r != (Object)null)) ? null : PathFrom((Transform)(object)source, r.transform)).ToArray(),
				RequirementLevel = PathOf((Component)(object)instance.m_minStationLevelText),
				RequirementLevelIcon = PathOf((Component)(object)instance.m_minStationLevelIcon),
				Action = PathOf((Component)(object)instance.m_craftButton),
				Hidden = new string[4]
				{
					PathOf((Component)(object)instance.m_variantButton),
					PathOf((Component)(object)instance.m_qualityPanel),
					PathOf((Component)(object)instance.m_craftProgressPanel),
					PathOf((Component)(object)instance.m_upgradeItemName)?.Split('/').Take(2).Aggregate((string a, string b) => a + "/" + b)
				},
				Removed = new string[2]
				{
					TopOf((Component)(object)instance.m_repairButton),
					TopOf((Component)(object)instance.m_repairPanel)
				}
			};
			Rect rect = source.rect;
			Vector2 size = ((Rect)(ref rect)).size;
			GameObject val = CloneInactive(((Component)source).gameObject);
			((Object)val).name = "fjordfolk_window";
			HashSet<string> hashSet = new HashSet<string>(from p in new string[5] { anon.Title, anon.Icon, anon.Level, anon.List, anon.Details }.Concat(anon.Tabs)
				where !string.IsNullOrEmpty(p)
				select p.Split('/')[0]);
			foreach (Transform item in ((IEnumerable)val.transform).Cast<Transform>().ToList())
			{
				Image component = ((Component)item).GetComponent<Image>();
				Sprite val2 = ((component != null) ? component.sprite : null);
				bool num = (Object)(object)val2 != (Object)null && ((Object)val2).name.Contains("repair");
				bool flag = !((Component)item).gameObject.activeSelf && !hashSet.Contains(((Object)item).name);
				if (num || flag || anon.Removed.Contains(((Object)item).name))
				{
					Object.DestroyImmediate((Object)(object)((Component)item).gameObject);
				}
			}
			foreach (string item2 in new string[14]
			{
				anon.Title, anon.Icon, anon.Level, anon.LevelText, anon.List, anon.ListRoot, anon.Details, anon.DetailsIcon, anon.DetailsName, anon.DetailsText,
				anon.DetailsFooter, anon.RequirementLevel, anon.RequirementLevelIcon, anon.Action
			}.Concat(anon.Tabs).Concat(anon.Requirements))
			{
				SwitchOn(val, item2);
			}
			foreach (string item3 in anon.Hidden.Where((string p) => !string.IsNullOrEmpty(p)))
			{
				Transform obj = val.transform.Find(item3);
				if (obj != null)
				{
					((Component)obj).gameObject.SetActive(false);
				}
			}
			RectTransform val3 = Find<RectTransform>(val, anon.ListRoot);
			if ((Object)(object)val3 != (Object)null)
			{
				foreach (Transform item4 in ((IEnumerable)val3).Cast<Transform>().ToList())
				{
					Object.DestroyImmediate((Object)(object)((Component)item4).gameObject);
				}
			}
			Strip(val);
			Window obj2 = new Window
			{
				Root = (RectTransform)val.transform,
				Width = size.x,
				Title = Find<TMP_Text>(val, anon.Title),
				Icon = Find<Image>(val, anon.Icon),
				LevelText = Find<TMP_Text>(val, anon.LevelText),
				LevelTooltip = Find<UITooltip>(val, anon.Level)
			};
			Transform obj3 = val.transform.Find(anon.List ?? "");
			obj2.List = ((obj3 != null) ? ((Component)obj3).gameObject : null);
			obj2.ListRoot = val3;
			obj2.ListSpacing = ((instance.m_recipeListSpace > 1f) ? instance.m_recipeListSpace : 32f);
			Transform obj4 = val.transform.Find(anon.Details ?? "");
			obj2.Details = ((obj4 != null) ? ((Component)obj4).gameObject : null);
			obj2.DetailsIcon = Find<Image>(val, anon.DetailsIcon);
			obj2.DetailsName = Find<TMP_Text>(val, anon.DetailsName);
			obj2.DetailsText = Find<TMP_Text>(val, anon.DetailsText);
			obj2.DetailsFooter = Find<TMP_Text>(val, anon.DetailsFooter);
			obj2.RequirementLevel = Find<TMP_Text>(val, anon.RequirementLevel);
			obj2.RequirementLevelTooltip = Find<UITooltip>(val, anon.RequirementLevelIcon);
			obj2.ActionButton = Find<Button>(val, anon.Action);
			Window window = obj2;
			string[] requirements = anon.Requirements;
			foreach (string path in requirements)
			{
				RectTransform val4 = Find<RectTransform>(val, path);
				if ((Object)(object)val4 != (Object)null)
				{
					window.Requirements.Add(TileOf(((Component)val4).gameObject));
				}
			}
			if ((Object)(object)window.Title != (Object)null)
			{
				window.Title.text = title;
			}
			if ((Object)(object)window.ActionButton != (Object)null)
			{
				window.ActionButton.onClick = new ButtonClickedEvent();
			}
			for (int num3 = 0; num3 < anon.Tabs.Length; num3++)
			{
				Button val5 = Find<Button>(val, anon.Tabs[num3]);
				if ((Object)(object)val5 == (Object)null)
				{
					continue;
				}
				if (tabs == null || num3 >= tabs.Count)
				{
					((Component)val5).gameObject.SetActive(false);
					continue;
				}
				int index = num3;
				val5.onClick = new ButtonClickedEvent();
				((UnityEvent)val5.onClick).AddListener((UnityAction)delegate
				{
					FjordFolkPlugin.Guard("VanillaUi.Tab", delegate
					{
						onTab(index);
					});
				});
				Transform obj5 = ((Component)val5).transform.Find("Text");
				TMP_Text val6 = ((obj5 != null) ? ((Component)obj5).GetComponent<TMP_Text>() : null) ?? ((Component)val5).GetComponentInChildren<TMP_Text>(true);
				if ((Object)(object)val6 != (Object)null)
				{
					val6.text = tabs[num3];
				}
				window.Tabs.Add(val5);
			}
			RectTransform root = window.Root;
			((Transform)root).SetParent(parent, false);
			Vector2 val7 = default(Vector2);
			((Vector2)(ref val7))..ctor(0.5f, 0.5f);
			root.anchorMax = val7;
			root.anchorMin = val7;
			root.pivot = new Vector2(0.5f, 0.5f);
			root.sizeDelta = size;
			root.anchoredPosition = Vector2.zero;
			((Transform)root).localScale = Vector3.one;
			val.SetActive(true);
			Canvas.ForceUpdateCanvases();
			if ((Object)(object)window.List != (Object)null && (Object)(object)window.Details != (Object)null)
			{
				Rect val8 = FromTopLeft(root, (RectTransform)window.List.transform);
				Rect val9 = FromTopLeft(root, (RectTransform)window.Details.transform);
				window.ContentArea = Rect.MinMaxRect(((Rect)(ref val8)).xMin, Mathf.Min(((Rect)(ref val8)).yMin, ((Rect)(ref val9)).yMin), ((Rect)(ref val9)).xMax, Mathf.Max(((Rect)(ref val8)).yMax, ((Rect)(ref val9)).yMax));
			}
			else
			{
				window.ContentArea = new Rect(10f, 101f, size.x - 20f, size.y - 105f);
			}
			return window;
			string PathOf(Component c)
			{
				if (!((Object)(object)c != (Object)null))
				{
					return null;
				}
				return PathFrom((Transform)(object)source, c.transform);
			}
			string TopOf(Component c)
			{
				string text = PathOf(c);
				if (text == null)
				{
					return null;
				}
				return text.Split('/')[0];
			}
		}

		public static ListEntry AddListEntry(Window window, int index, Action onClick)
		{
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: 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_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Expected O, but got Unknown
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Expected O, but got Unknown
			GameObject val = CloneInactive(InventoryGui.instance.m_recipeElementPrefab);
			((Object)val).name = "fjordfolk_listentry";
			ListEntry obj = new ListEntry
			{
				Root = val
			};
			Transform obj2 = val.transform.Find("icon");
			obj.Icon = ((obj2 != null) ? ((Component)obj2).GetComponent<Image>() : null);
			Transform obj3 = val.transform.Find("name");
			obj.Name = ((obj3 != null) ? ((Component)obj3).GetComponent<TMP_Text>() : null);
			Transform obj4 = val.transform.Find("QualityLevel");
			obj.Badge = ((obj4 != null) ? ((Component)obj4).GetComponent<TMP_Text>() : null);
			Transform obj5 = val.transform.Find("selected");
			obj.Selected = ((obj5 != null) ? ((Component)obj5).gameObject : null);
			obj.Button = val.GetComponent<Button>();
			ListEntry listEntry = obj;
			Transform obj6 = val.transform.Find("Durability");
			if (obj6 != null)
			{
				((Component)obj6).gameObject.SetActive(false);
			}
			GameObject selected = listEntry.Selected;
			if (selected != null)
			{
				selected.SetActive(false);
			}
			Strip(val);
			if ((Object)(object)listEntry.Button != (Object)null)
			{
				listEntry.Button.onClick = new ButtonClickedEvent();
				((UnityEvent)listEntry.Button.onClick).AddListener((UnityAction)delegate
				{
					FjordFolkPlugin.Guard("VanillaUi.ListEntry", onClick.Invoke);
				});
			}
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)window.ListRoot, false);
			val2.anchoredPosition = new Vector2(0f, (float)(-index) * window.ListSpacing);
			val.SetActive(true);
			float num = (float)(index + 1) * window.ListSpacing;
			Rect rect = window.ListRoot.rect;
			if (((Rect)(ref rect)).height < num)
			{
				window.ListRoot.SetSizeWithCurrentAnchors((Axis)1, num);
			}
			return listEntry;
		}

		public static Image Panel(Transform parent, float x, float y, float width, float height)
		{
			//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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			Image component = ((Component)InventoryGui.instance.m_recipeName.transform.parent).GetComponent<Image>();
			GameObject val = new GameObject("fjordfolk_panel", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			Image component2 = val.GetComponent<Image>();
			if ((Object)(object)component != (Object)null)
			{
				component2.sprite = component.sprite;
				component2.type = component.type;
				((Graphic)component2).color = ((Graphic)component).color;
				((Graphic)component2).material = ((Graphic)component).material;
				component2.pixelsPerUnitMultiplier = component.pixelsPerUnitMultiplier;
			}
			else
			{
				((Graphic)component2).color = new Color(0f, 0f, 0f, 0.56f);
			}
			((Graphic)component2).raycastTarget = false;
			Place((RectTransform)val.transform, parent, x, y, new Vector2(width, height));
			return component2;
		}

		public static TMP_Text Text(Transform parent, TextStyle style, string text, float x, float y, float width, float height, TextAlignmentOptions alignment = (TextAlignmentOptions)513, float size = 0f)
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected O, but got Unknown
			InventoryGui instance = InventoryGui.instance;
			GameObject val = CloneInactive(((Component)(style switch
			{
				TextStyle.Big => instance.m_recipeName, 
				TextStyle.Header => instance.m_itemCraftType, 
				_ => instance.m_recipeDecription, 
			})).gameObject);
			((Object)val).name = "fjordfolk_text";
			foreach (Transform item in ((IEnumerable)val.transform).Cast<Transform>().ToList())
			{
				Object.DestroyImmediate((Object)(object)((Component)item).gameObject);
			}
			Strip(val);
			StripLayouts(val, includeChildren: true);
			TMP_Text component = val.GetComponent<TMP_Text>();
			component.text = text;
			component.alignment = alignment;
			component.textWrappingMode = (TextWrappingModes)1;
			component.overflowMode = (TextOverflowModes)0;
			component.enableAutoSizing = false;
			component.richText = true;
			((Graphic)component).raycastTarget = false;
			component.fontSize = ((size > 0f) ? size : (style switch
			{
				TextStyle.Big => 30f, 
				TextStyle.Header => 20f, 
				_ => 17f, 
			}));
			Place((RectTransform)val.transform, parent, x, y, new Vector2(width, height));
			val.SetActive(true);
			return component;
		}

		public static Button Button(Transform parent, string label, float x, float y, float width, float height, Action onClick)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_00bb: 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_00d1: Expected O, but got Unknown
			GameObject val = CloneInactive(((Component)InventoryGui.instance.m_takeAllButton).gameObject);
			((Object)val).name = "fjordfolk_button";
			Strip(val);
			StripLayouts(val, includeChildren: true);
			Button component = val.GetComponent<Button>();
			component.onClick = new ButtonClickedEvent();
			((UnityEvent)component.onClick).AddListener((UnityAction)delegate
			{
				FjordFolkPlugin.Guard("VanillaUi.Button " + label, onClick.Invoke);
			});
			((Selectable)component).interactable = true;
			Transform obj = val.transform.Find("Text");
			TMP_Text val2 = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null) ?? val.GetComponentInChildren<TMP_Text>(true);
			if ((Object)(object)val2 != (Object)null)
			{
				val2.text = label;
				val2.textWrappingMode = (TextWrappingModes)0;
			}
			Place((RectTransform)val.transform, parent, x, y, new Vector2(width, height));
			val.SetActive(true);
			return component;
		}

		public static void SetButtonLabel(Button button, string label)
		{
			object obj;
			if (!((Object)(object)button != (Object)null))
			{
				obj = null;
			}
			else
			{
				Transform obj2 = ((Component)button).transform.Find("Text");
				obj = ((obj2 != null) ? ((Component)obj2).GetComponent<TMP_Text>() : null) ?? ((Component)button).GetComponentInChildren<TMP_Text>(true);
			}
			TMP_Text val = (TMP_Text)obj;
			if ((Object)(object)val != (Object)null)
			{
				val.text = label;
			}
		}

		public static UITooltip TooltipOf(Component c)
		{
			if (!((Object)(object)c != (Object)null))
			{
				return null;
			}
			return c.GetComponentInChildren<UITooltip>(true);
		}

		public static void SetTooltip(UITooltip tooltip, string topic, string text)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)tooltip != (Object)null)
			{
				tooltip.Set(topic, text, (RectTransform)null, Vector2.zero);
			}
		}

		public static Slot InventorySlot(Transform parent, float x, float y, float size, Action onClick)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Expected O, but got Unknown
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Expected O, but got Unknown
			GameObject val = CloneInactive(InventoryGui.instance.m_playerGrid.m_elementPrefab);
			((Object)val).name = "fjordfolk_slot";
			InventoryElement component = val.GetComponent<InventoryElement>();
			Slot slot = new Slot
			{
				Rect = (RectTransform)val.transform,
				Icon = (((Object)(object)component != (Object)null) ? component.m_icon : null),
				Amount = (((Object)(object)component != (Object)null) ? component.m_amount : null),
				Selected = (((Object)(object)component != (Object)null) ? component.m_selected : null),
				Button = (((Object)(object)component != (Object)null && (Object)(object)component.m_button != (Object)null) ? component.m_button : val.GetComponent<Button>()),
				Tooltip = val.GetComponentInChildren<UITooltip>(true)
			};
			if ((Object)(object)component != (Object)null)
			{
				Component[] array = (Component[])(object)new Component[7]
				{
					(Component)component.m_quality,
					(Component)component.m_equiped,
					(Component)component.m_queued,
					(Component)component.m_noteleport,
					(Component)component.m_food,
					(Component)component.m_durability,
					(Component)component.m_dropFocus
				};
				foreach (Component val2 in array)
				{
					if ((Object)(object)val2 != (Object)null)
					{
						val2.gameObject.SetActive(false);
					}
				}
			}
			Transform obj = val.transform.Find("binding");
			if (obj != null)
			{
				((Component)obj).gameObject.SetActive(false);
			}
			GameObject selected = slot.Selected;
			if (selected != null)
			{
				selected.SetActive(false);
			}
			Strip(val);
			if ((Object)(object)slot.Button != (Object)null)
			{
				slot.Button.onClick = new ButtonClickedEvent();
				if (onClick != null)
				{
					((UnityEvent)slot.Button.onClick).AddListener((UnityAction)delegate
					{
						FjordFolkPlugin.Guard("VanillaUi.Slot", onClick.Invoke);
					});
				}
			}
			float slotNaturalSize = SlotNaturalSize;
			Place(slot.Rect, parent, x, y, new Vector2(slotNaturalSize, slotNaturalSize));
			((Transform)slot.Rect).localScale = Vector3.one * (size / slotNaturalSize);
			val.SetActive(true);
			return slot;
		}

		private static Tile TileOf(GameObject go)
		{
			Tile obj = new Tile
			{
				Root = go
			};
			Transform obj2 = go.transform.Find("res_icon");
			obj.Icon = ((obj2 != null) ? ((Component)obj2).GetComponent<Image>() : null);
			Transform obj3 = go.transform.Find("res_name");
			obj.Name = ((obj3 != null) ? ((Component)obj3).GetComponent<TMP_Text>() : null);
			Transform obj4 = go.transform.Find("res_amount");
			obj.Amount = ((obj4 != null) ? ((Component)obj4).GetComponent<TMP_Text>() : null);
			obj.Tooltip = go.GetComponent<UITooltip>();
			return obj;
		}

		public static void ShowRequirement(Tile tile, Sprite icon, string name, int have, int need, string tooltip)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			Component[] array = (Component[])(object)new Component[3]
			{
				(Component)tile.Icon,
				(Component)tile.Name,
				(Component)tile.Amount
			};
			foreach (Component obj in array)
			{
				if (obj != null)
				{
					obj.gameObject.SetActive(true);
				}
			}
			if ((Object)(object)tile.Icon != (Object)null)
			{
				tile.Icon.sprite = icon;
				((Graphic)tile.Icon).color = Color.white;
			}
			if ((Object)(object)tile.Name != (Object)null)
			{
				tile.Name.text = name;
			}
			if ((Object)(object)tile.Amount != (Object)null)
			{
				tile.Amount.text = $"{have}/{need}";
				((Graphic)tile.Amount).color = ((have >= need) ? Color.white : Red);
			}
			SetTooltip(tile.Tooltip, name, tooltip);
		}

		public static void HideRequirement(Tile tile)
		{
			Component[] array = (Component[])(object)new Component[3]
			{
				(Component)tile.Icon,
				(Component)tile.Name,
				(Component)tile.Amount
			};
			foreach (Component obj in array)
			{
				if (obj != null)
				{
					obj.gameObject.SetActive(false);
				}
			}
			SetTooltip(tile.Tooltip, "", "");
		}

		private static GameObject CloneInactive(GameObject source)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			if ((Object)(object)s_holder == (Object)null)
			{
				s_holder = new GameObject("fjordfolk_ui_holder");
				s_holder.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)s_holder);
			}
			GameObject obj = Object.Instantiate<GameObject>(source, s_holder.transform, false);
			obj.SetActive(true);
			return obj;
		}

		private static void Strip(GameObject go)
		{
			UIGamePad[] componentsInChildren = go.GetComponentsInChildren<UIGamePad>(true);
			foreach (UIGamePad val in componentsInChildren)
			{
				if ((Object)(object)val.m_hint != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val.m_hint);
				}
			}
			foreach (GameObject item in (from b in go.GetComponentsInChildren<MonoBehaviour>(true)
				where (Object)(object)b != (Object)null && ((object)b).GetType().Name == "UIInputHint"
				select ((Component)b).gameObject).Distinct().ToList())
			{
				if ((Object)(object)item != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)item);
				}
			}
			MonoBehaviour[] componentsInChildren2 = go.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val2 in componentsInChildren2)
			{
				if ((Object)(object)val2 != (Object)null && Behaviours.Contains(((object)val2).GetType().Name))
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
			}
		}

		private static void StripLayouts(GameObject go, bool includeChildren)
		{
			Component[] array = (includeChildren ? go.GetComponentsInChildren<Component>(true) : go.GetComponents<Component>());
			foreach (Component val in array)
			{
				if ((Object)(object)val != (Object)null && Layouts.Contains(((object)val).GetType().Name))
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}

		public static void Place(RectTransform rect, Transform parent, float x, float y, Vector2 size)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			((Transform)rect).SetParent(parent, false);
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0f, 1f);
			rect.anchorMax = val;
			rect.anchorMin = val;
			rect.pivot = new Vector2(0f, 1f);
			rect.sizeDelta = size;
			rect.anchoredPosition = new Vector2(x, 0f - y);
			((Transform)rect).localScale = Vector3.one;
		}

		public static RectTransform Group(Transform parent, string name, float x, float y, float width, float height)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0036: Expected O, but got Unknown
			RectTransform val = (RectTransform)new GameObject(name, new Type[1] { typeof(RectTransform) }).transform;
			Place(val, parent, x, y, new Vector2(width, height));
			return val;
		}

		private static Rect FromTopLeft(RectTransform root, RectTransform child)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_0056: 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_0079: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			child.GetWorldCorners(array);
			Rect rect = root.rect;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(float.MaxValue, float.MaxValue);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(float.MinValue, float.MinValue);
			Vector3[] array2 = array;
			Vector2 val5 = default(Vector2);
			foreach (Vector3 val3 in array2)
			{
				Vector3 val4 = ((Transform)root).InverseTransformPoint(val3);
				((Vector2)(ref val5))..ctor(val4.x - ((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMax - val4.y);
				val = Vector2.Min(val, val5);
				val2 = Vector2.Max(val2, val5);
			}
			return Rect.MinMaxRect(val.x, val.y, val2.x, val2.y);
		}

		private static void SwitchOn(GameObject root, string path)
		{
			if (string.IsNullOrEmpty(path))
			{
				return;
			}
			Transform val = root.transform.Find(path);
			Transform val2 = val;
			while ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)root.transform)
			{
				((Component)val2).gameObject.SetActive(true);
				val2 = val2.parent;
			}
			if (!((Object)(object)val == (Object)null))
			{
				Graphic[] components = ((Component)val).GetComponents<Graphic>();
				for (int i = 0; i < components.Length; i++)
				{
					((Behaviour)components[i]).enabled = true;
				}
			}
		}

		private static T Find<T>(GameObject root, string path) where T : Component
		{
			if (string.IsNullOrEmpty(path))
			{
				return default(T);
			}
			Transform val = root.transform.Find(path);
			if (!((Object)(object)val != (Object)null))
			{
				return default(T);
			}
			return ((Component)val).GetComponent<T>();
		}

		private static Vector2 SizeOf(RectTransform rect, Vector2 fallback)
		{
			//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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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_0047: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)rect == (Object)null)
			{
				return fallback;
			}
			Rect rect2 = rect.rect;
			Vector2 val = ((Rect)(ref rect2)).size;
			if (val.x <= 1f || val.y <= 1f)
			{
				val = ((rect.anchorMin == rect.anchorMax) ? rect.sizeDelta : fallback);
			}
			return new Vector2((val.x > 1f) ? val.x : fallback.x, (val.y > 1f) ? val.y : fallback.y);
		}

		private static string PathFrom(Transform root, Transform target)
		{
			if ((Object)(object)target == (Object)null)
			{
				return null;
			}
			List<string> list = new List<string>();
			Transform val = target;
			while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root)
			{
				list.Add(((Object)val).name);
				val = val.parent;
			}
			list.Reverse();
			return string.Join("/", list);
		}
	}
}
namespace FjordFolk.Tavern
{
	public class Drunkard : MonoBehaviour
	{
		public const string DialogueId = "drunkard";

		public const int Coins = 400;

		private static readonly (string Boss, string Mead)[] Progress = new(string, string)[8]
		{
			("", "MeadHealthMinor"),
			("defeated_eikthyr", "MeadHealthMinor"),
			("defeated_gdking", "MeadHealthMedium"),
			("defeated_bonemass", "MeadHealthMedium"),
			("defeated_dragon", "MeadHealthMajor"),
			("defeated_goblinking", "MeadHealthMajor"),
			("defeated_queen", "MeadHealthLingering"),
			("defeated_fader", "MeadHealthLingering")
		};

		private NpcActor m_actor;

		private void Awake()
		{
			m_actor = ((Component)this).GetComponent<NpcActor>();
		}

		internal static string WantedMead()
		{
			ZoneSystem instance = ZoneSystem.instance;
			string result = Progress[0].Mead;
			(string, string)[] progress = Progress;
			for (int i = 0; i < progress.Length; i++)
			{
				var (text, text2) = progress[i];
				if (string.IsNullOrEmpty(text) || ((Object)(object)instance != (Object)null && instance.GetGlobalKey(text)))
				{
					result = text2;
				}
			}
			return result;
		}

		private static string MeadName(string prefab)
		{
			object obj;
			if (!((Object)(object)ObjectDB.instance != (Object)null))
			{
				obj = null;
			}
			else
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefab);
				obj = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null);
			}
			ItemDrop val = (ItemDrop)obj;
			if (!((Object)(object)val != (Object)null))
			{
				return prefab;
			}
			return val.m_itemData.m_shared.m_name;
		}

		internal string HoverText(string name)
		{
			string text = name + "\n<color=#c8c8c8>" + Loc.T("drunkard_role") + "</color>\n[<color=yellow><b>$KEY_Use</b></color>] " + Loc.T("drunkard_offer", MeadName(WantedMead()), 400);
			return Localization.instance.Localize(text);
		}

		internal void Interact(Humanoid user)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			Player val = (Player)(object)((user is Player) ? user : null);
			if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			bool anyInWorld;
			TraderLocations.Kind kind;
			Vector3? val2 = TraderLocations.NearestUnfound(((Component)val).transform.position, out kind, out anyInWorld);
			if (!val2.HasValue && !TraderLocations.ClientOnly)
			{
				Say(anyInWorld ? "all_known" : "no_traders");
				return;
			}
			Inventory inventory = ((Humanoid)val).GetInventory();
			string text = WantedMead();
			string text2 = MeadName(text);
			if (inventory.CountItems(text2, -1, true) < 1 || inventory.CountItems(MeadName("Coins"), -1, true) < 400)
			{
				Say("want");
				((Character)val).Message((MessageType)2, Localization.instance.Localize(Loc.T("msg_drunkard_want", text2, 400)), 0, (Sprite)null, false);
				return;
			}
			inventory.RemoveItem(text2, 1, -1, true);
			inventory.RemoveItem(MeadName("Coins"), 400, -1, true);
			m_actor?.PlayGestureLocal("toast");
			if (!val2.HasValue)
			{
				kind = TraderLocations.FirstKindForClient();
				if (kind != null)
				{
					Game.instance.DiscoverClosestLocation(kind.LocationName, ((Component)val).transform.position, Loc.T(kind.NameKey), 3, true, false);
					Say("tell_" + kind.Key);
				}
				FjordFolkPlugin.Log.LogDebug((object)$"drunkard paid ({text} + {400}), asked the server for {kind?.LocationName}");
			}
			else
			{
				Minimap.instance.DiscoverLocation(val2.Value, (PinType)3, Loc.T(kind.NameKey), true);
				Say("tell_" + kind.Key);
				FjordFolkPlugin.Log.LogDebug((object)$"drunkard paid ({text} + {400}), marked {kind.Key} at {val2.Value}");
			}
		}

		private void Say(string section)
		{
			string text = NpcDialogue.For("drunkard").Pick(section);
			if (text != null)
			{
				m_actor?.Say(text);
			}
		}
	}
	internal static class TraderLocations
	{
		internal sealed class Kind
		{
			public string Key;

			public string NameKey;

			public Regex Pattern;

			public string LocationName;

			public List<string> Names = new List<string>();
		}

		private static readonly Kind[] Kinds = new Kind[4]
		{
			new Kind
			{
				Key = "haldor",
				NameKey = "trader_haldor",
				Pattern = new Regex("^Vendor_BlackForest$", RegexOptions.IgnoreCase)
			},
			new Kind
			{
				Key = "hildir",
				NameKey = "trader_hildir",
				Pattern = new Regex("^Hildir_camp$", RegexOptions.IgnoreCase)
			},
			new Kind
			{
				Key = "bogwitch",
				NameKey = "trader_bogwitch",
				Pattern = new Regex("^BogWitch_Camp$", RegexOptions.IgnoreCase)
			},
			new Kind
			{
				Key = "forge",
				NameKey = "trader_forge",
				Pattern = new Regex("^(?!dev).*potential", RegexOptions.IgnoreCase)
			}
		};

		private static ZoneSystem s_resolvedFor;

		public static bool ClientOnly
		{
			get
			{
				if (!((Object)(object)ZoneSystem.instance == (Object)null))
				{
					return ZoneSystem.instance.m_locationInstances.Count == 0;
				}
				return true;
			}
		}

		private static void Resolve()
		{
			if ((Object)(object)s_resolvedFor == (Object)(object)ZoneSystem.instance || (Object)(object)ZoneSystem.instance == (Object)null)
			{
				return;
			}
			s_resolvedFor = ZoneSystem.instance;
			List<string> source = (from l in ZoneSystem.instance.m_locations
				where l != null && !string.IsNullOrEmpty(l.m_prefabName)
				select l.m_prefabName).Distinct().ToList();
			Kind[] kinds = Kinds;
			foreach (Kind kind in kinds)
			{
				kind.Names = source.Where((string n) => kind.Pattern.IsMatch(n)).ToList();
				kind.LocationName = kind.Names.FirstOrDefault();
			}
			FjordFolkPlugin.Log.LogDebug((object)("trader locations: " + string.Join("; ", Kinds.Select((Kind k) => k.Key + " = " + ((k.Names.Count > 0) ? string.Join(", ", k.Names) : "none")))));
			FjordFolkPlugin.Log.LogDebug((object)("locations that might be traders: " + string.Join(", ", source.Where((string n) => Regex.IsMatch(n, "vendor|trader|hildir|witch|forge|potential|idol|merchant", RegexOptions.IgnoreCase)))));
		}

		public static Vector3? NearestUnfound(Vector3 from, out Kind kind, out bool anyInWorld)
		{
			//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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			Resolve();
			kind = null;
			anyInWorld = false;
			if ((Object)(object)ZoneSystem.instance == (Object)null || (Object)(object)Minimap.instance == (Object)null)
			{
				return null;
			}
			Vector3? result = null;
			float num = float.MaxValue;
			foreach (LocationInstance value in ZoneSystem.instance.m_locationInstances.Values)
			{
				string name = value.m_location?.m_prefabName;
				Kind kind2 = ((name != null) ? Kinds.FirstOrDefault((Kind k) => k.Names.Contains(name)) : null);
				if (kind2 == null)
				{
					continue;
				}
				anyInWorld = true;
				Vector3 position = value.m_position;
				if (!Minimap.instance.IsExplored(position) && !HasPinNear(position))
				{
					float num2 = Vector3.Distance(from, position);
					if (num2 < num)
					{
						num = num2;
						result = position;
						kind = kind2;
					}
				}
			}
			return result;
		}

		public static Kind FirstKindForClient()
		{
			Resolve();
			return Kinds.FirstOrDefault((Kind k) => k.LocationName != null && !Minimap.instance.m_pins.Any((PinData p) => p.m_name == Loc.T(k.NameKey)));
		}

		private static bool HasPinNear(Vector3 position)
		{
			//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)
			return Minimap.instance.m_pins.Any(delegate(PinData p)
			{
				//IL_0004: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Invalid comparison between Unknown and I4
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				if (p != null && (int)p.m_type != 4)
				{
					Vector3 val = p.m_pos - position;
					return ((Vector3)(ref val)).sqrMagnitude < 3600f;
				}
				return false;
			});
		}
	}
	public class Innkeeper : MonoBehaviour
	{
		public const string DialogueId = "innkeeper";

		private const float StandRange = 5f;

		private const float SitRange = 8f;

		private const float SitDelay = 2f;

		private ZNetView m_nview;

		private NpcActor m_actor;

		private NpcSeat m_seat;

		private Trader m_trader;

		private float m_nextCheck;

		private float m_sitAt = -1f;

		internal Trader Trader => m_trader;

		private void Awake()
		{
			m_nview = ((Component)this).GetComponent<ZNetView>();
			m_actor = ((Component)this).GetComponent<NpcActor>();
			m_seat = ((Component)this).GetComponent<NpcSeat>();
			m_trader = ((Component)this).GetComponent<Trader>();
		}

		private void Update()
		{
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid() || (Object)(object)m_seat == (Object)null || Time.time < m_nextCheck)
			{
				return;
			}
			m_nextCheck = Time.time + 0.25f;
			FjordFolkPlugin.Guard("Innkeeper.Update", delegate
			{
				//IL_001c: 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)
				Player localPlayer = Player.m_localPlayer;
				float num = (((Object)(object)localPlayer != (Object)null) ? Vector3.Distance(((Component)localPlayer).transform.position, ((Component)this).transform.position) : float.MaxValue);
				bool flag = (Object)(object)StoreGui.instance != (Object)null