Decompiled source of Errands v0.1.0

Errands.dll

Decompiled 4 days 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.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Errands")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+b95ca039d613e039ad41b0788bf72a402f6d746a")]
[assembly: AssemblyProduct("Errands")]
[assembly: AssemblyTitle("Errands")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 Errands
{
	public class SpawnCommand : ConsoleCommand
	{
		public override string Name => "errands_spawn";

		public override string Help => "Spawn an errand dvergr in front of you";

		public override bool IsCheat => true;

		public override void Run(string[] args)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_0051: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (Object.op_Implicit((Object)(object)localPlayer))
			{
				Vector3 lookDir = ((Character)localPlayer).GetLookDir();
				lookDir.y = 0f;
				Vector3 val = ((Component)localPlayer).transform.position + ((Vector3)(ref lookDir)).normalized * 2.5f;
				Quaternion rot = Quaternion.LookRotation(-lookDir);
				GameObject val2 = Placement.Spawn(val, rot, WorldGenerator.instance.GetBiome(val));
				Console.instance.Print(Object.op_Implicit((Object)(object)val2) ? $"Dvergr spawned at {val2.transform.position}" : "Failed: prefab not found");
			}
		}
	}
	public class LocationsCommand : ConsoleCommand
	{
		public override string Name => "errands_locations";

		public override string Help => "List vanilla location names by biome (optionally filter by biome name)";

		public override void Run(string[] args)
		{
			string text = ((args.Length != 0) ? args[0].ToLowerInvariant() : null);
			SortedDictionary<string, List<string>> sortedDictionary = new SortedDictionary<string, List<string>>();
			foreach (ZoneLocation location in ZoneSystem.instance.m_locations)
			{
				if (!location.m_enable)
				{
					continue;
				}
				string text2 = ((object)Unsafe.As<Biome, Biome>(ref location.m_biome)/*cast due to .constrained prefix*/).ToString();
				if (text == null || text2.ToLowerInvariant().Contains(text))
				{
					if (!sortedDictionary.TryGetValue(text2, out var value))
					{
						value = (sortedDictionary[text2] = new List<string>());
					}
					value.Add($"{location.m_prefabName} x{location.m_quantity}");
				}
			}
			foreach (KeyValuePair<string, List<string>> item in sortedDictionary)
			{
				string text3 = "[" + item.Key + "] " + string.Join(", ", item.Value.OrderBy((string s) => s));
				Console.instance.Print(text3);
				ZLog.Log((object)("Errands locations " + text3));
			}
			Console.instance.Print("Also written to LogOutput.log");
		}
	}
	public class TexDumpCommand : ConsoleCommand
	{
		public override string Name => "errands_texdump";

		public override string Help => "Dump the dvergr's textures to PNG next to Errands.dll";

		public override void Run(string[] args)
		{
			GameObject prefab = ZNetScene.instance.GetPrefab("ErrandsDvergr");
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				Console.instance.Print("Prefab missing");
				return;
			}
			string directoryName = Path.GetDirectoryName(typeof(ErrandsPlugin).Assembly.Location);
			foreach (string item in Tinting.Dump(prefab, directoryName))
			{
				Console.instance.Print(item);
			}
		}
	}
	public class RepCommand : ConsoleCommand
	{
		public override string Name => "errands_rep";

		public override string Help => "Set standing: errands_rep <biome> <amount>";

		public override bool IsCheat => true;

		public override void Run(string[] args)
		{
			//IL_002f: 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)
			if (args.Length < 2 || !Enum.TryParse<Biome>(args[0], ignoreCase: true, out Biome result) || !int.TryParse(args[1], out var result2))
			{
				Console.instance.Print("errands_rep <Meadows|BlackForest|Swamp|Mountain|Plains|Mistlands|AshLands> <amount>");
				return;
			}
			Journal.SetRep(result, result2);
			Console.instance.Print($"{result} standing = {result2} ({Shop.TierTag(result2)})");
		}
	}
	public class DoneCommand : ConsoleCommand
	{
		public override string Name => "errands_done";

		public override string Help => "Mark your held errands as complete";

		public override bool IsCheat => true;

		public override void Run(string[] args)
		{
			Journal.CompleteAll();
			Console.instance.Print("Errands marked done; talk to the dvergr.");
		}
	}
	public class KitCommand : ConsoleCommand
	{
		public override string Name => "errands_kit";

		public override string Help => "Test kit: errands_kit <biome|all>";

		public override bool IsCheat => true;

		public override void Run(string[] args)
		{
			//IL_0059: 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)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || args.Length < 1)
			{
				Console.instance.Print("errands_kit <Meadows|BlackForest|Swamp|Mountain|Plains|Mistlands|AshLands|all>");
				return;
			}
			List<Biome> list = new List<Biome>();
			if (args[0].ToLowerInvariant() == "all")
			{
				list.AddRange(Biomes.All);
			}
			else
			{
				if (!Enum.TryParse<Biome>(args[0], ignoreCase: true, out Biome result))
				{
					Console.instance.Print("Unknown biome " + args[0]);
					return;
				}
				list.Add(result);
			}
			int num = 0;
			foreach (Biome item in list)
			{
				foreach (string item2 in Uniques.All(item))
				{
					Give(localPlayer, item2, 1, 1);
					num++;
				}
				if (Object.op_Implicit((Object)(object)ObjectDB.instance.GetItemPrefab(Rewards.ChestPrefab(item))))
				{
					Give(localPlayer, Rewards.ChestPrefab(item), 3, 3);
				}
				Journal.SetRep(item, 80);
			}
			Give(localPlayer, "ErrandsMark", 100, 1);
			Console.instance.Print($"{num} uniques, chests, 100 marks; standing set to Kin. Bag full? Check your feet.");
		}

		private static void Give(Player player, string prefab, int amount, int quality)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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)
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefab);
			if (!Object.op_Implicit((Object)(object)itemPrefab))
			{
				Console.instance.Print("missing " + prefab);
			}
			else if (((Humanoid)player).GetInventory().AddItem(prefab, amount, quality, 0, 0L, "", false, false) == null)
			{
				ItemData obj = itemPrefab.GetComponent<ItemDrop>().m_itemData.Clone();
				obj.m_quality = quality;
				ItemDrop.DropItem(obj, amount, ((Component)player).transform.position + ((Component)player).transform.forward + Vector3.up, Quaternion.identity);
			}
		}
	}
	public class Dvergr : MonoBehaviour
	{
		public const string BiomeKey = "errands_biome";

		public const string SettledKey = "errands_settled";

		public const string IdKey = "errands_id";

		private ZNetView m_nview;

		private Trader m_trader;

		private bool m_settled;

		private bool m_deciding;

		public Biome Biome { get; private set; }

		public int Id { get; private set; }

		public string Name
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)m_trader))
				{
					return "Dvergr";
				}
				return m_trader.m_name;
			}
		}

		public List<Shop.Shelf> Shelves { get; private set; }

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

		private void Start()
		{
			//IL_0038: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected I4, but got Unknown
			if (!Object.op_Implicit((Object)(object)m_nview) || !m_nview.IsValid())
			{
				return;
			}
			Biome = (Biome)m_nview.GetZDO().GetInt("errands_biome", 0);
			if ((int)Biome == 0)
			{
				Biome = WorldGenerator.instance.GetBiome(((Component)this).transform.position);
				if (m_nview.IsOwner())
				{
					m_nview.GetZDO().Set("errands_biome", (int)Biome);
				}
			}
			Id = m_nview.GetZDO().GetInt("errands_id", 0);
			if (Id == 0)
			{
				Id = Random.Range(1, int.MaxValue);
				m_nview.ClaimOwnership();
				m_nview.GetZDO().Set("errands_id", Id);
			}
			m_settled = m_nview.GetZDO().GetBool("errands_settled", false);
			Dress();
		}

		private void Update()
		{
			if (!m_settled && Object.op_Implicit((Object)(object)m_nview) && m_nview.IsValid())
			{
				m_nview.ClaimOwnership();
				Settle();
				m_settled = true;
				m_nview.GetZDO().Set("errands_settled", true);
			}
		}

		public static void SetBiome(GameObject go, Biome biome, int id)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected I4, but got Unknown
			ZNetView component = go.GetComponent<ZNetView>();
			if (Object.op_Implicit((Object)(object)component) && component.GetZDO() != null)
			{
				component.GetZDO().Set("errands_biome", (int)biome);
				component.GetZDO().Set("errands_id", id);
			}
		}

		private void Settle()
		{
			//IL_0042: 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_006f: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			int mask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain" });
			Vector3 position = ((Component)this).transform.position;
			Collider[] componentsInChildren = ((Component)this).GetComponentsInChildren<Collider>(true);
			Collider[] array = componentsInChildren;
			for (int i = 0; i < array.Length; i++)
			{
				array[i].enabled = false;
			}
			try
			{
				RaycastHit val = default(RaycastHit);
				foreach (Vector3 item in Candidates(position))
				{
					if (Physics.Raycast(item + Vector3.up * 3f, Vector3.down, ref val, 6f, mask) && !(Mathf.Abs(((RaycastHit)(ref val)).point.y - position.y) > 2.5f))
					{
						Vector3 val2 = ((RaycastHit)(ref val)).point + Vector3.up * 0.3f;
						if (!Physics.CheckCapsule(val2, val2 + Vector3.up * 1.4f, 0.35f, mask, (QueryTriggerInteraction)1))
						{
							((Component)this).transform.position = ((RaycastHit)(ref val)).point;
							m_nview.GetZDO().SetPosition(((RaycastHit)(ref val)).point);
							break;
						}
					}
				}
			}
			finally
			{
				array = componentsInChildren;
				for (int i = 0; i < array.Length; i++)
				{
					array[i].enabled = true;
				}
			}
		}

		private static IEnumerable<Vector3> Candidates(Vector3 origin)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			yield return origin;
			for (float r = 1.2f; r <= 5f; r += 1.2f)
			{
				for (int i = 0; i < 12; i++)
				{
					float num = (float)i * (float)Math.PI * 2f / 12f;
					yield return origin + new Vector3(Mathf.Cos(num) * r, 0f, Mathf.Sin(num) * r);
				}
			}
		}

		private void Dress()
		{
			//IL_001d: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			m_trader.m_name = Biomes.DvergrName(Id);
			Lines.Fill(m_trader, Biome);
			Shelves = Shop.Stock(m_trader, Biome);
			Tinting.Apply(((Component)this).gameObject, Biome);
		}

		public void OpenWares()
		{
			if (!((Object)(object)StoreGui.instance == (Object)null))
			{
				Popup.CloseAll();
				if (!StoreGui.IsVisible())
				{
					Say(Lines.Wares);
					StoreGui.instance.Show(m_trader);
				}
			}
		}

		public void TapOrHold()
		{
			if (!m_deciding)
			{
				((MonoBehaviour)this).StartCoroutine(Decide());
			}
		}

		private IEnumerator Decide()
		{
			m_deciding = true;
			float t = 0f;
			while (ZInput.GetButton("Use") || ZInput.GetButton("JoyUse"))
			{
				t += Time.deltaTime;
				if (t >= 0.35f)
				{
					m_deciding = false;
					OpenWares();
					yield break;
				}
				yield return null;
			}
			m_deciding = false;
			Interact();
		}

		public void Interact()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			List<Errand> list = Journal.Active().FindAll((Errand e) => e.Biome == Biome && Journal.Complete(e));
			foreach (Errand item in list)
			{
				Journal.HandIn(item, Biome);
			}
			Errand errand = Journal.TodaysOffer(this);
			if (errand == null)
			{
				Say(Lines.NoErrands);
				return;
			}
			if (Journal.Taken(Id, errand.Day))
			{
				Say((list.Count > 0) ? Lines.HandIn : Lines.Tomorrow);
				return;
			}
			if (Journal.Full)
			{
				Say(Lines.HandsFull);
				return;
			}
			Say((list.Count > 0) ? Lines.HandIn : Lines.Offer);
			OfferDialog.Show(this, errand);
		}

		public void Say(List<string> lines)
		{
			//IL_000b: 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)
			Chat.instance.SetNpcText(((Component)this).gameObject, Vector3.up * m_trader.m_dialogHeight, 20f, m_trader.m_hideDialogDelay, "", Lines.Pick(lines), false);
			Animator componentInChildren = ((Component)this).GetComponentInChildren<Animator>();
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				componentInChildren.SetTrigger("Talk");
			}
		}
	}
	[HarmonyPatch(typeof(Trader), "Interact")]
	internal static class Trader_Interact_Patch
	{
		private static bool Prefix(Trader __instance, bool hold, ref bool __result)
		{
			Dvergr component = ((Component)__instance).GetComponent<Dvergr>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return true;
			}
			__result = false;
			if (!hold)
			{
				component.TapOrHold();
			}
			return false;
		}
	}
	public static class Lines
	{
		public static readonly List<string> Greet = new List<string> { "Hm. Another one of Odin's strays.", "Mind the roof. It was better before the trolls.", "You're tall. They're all tall.", "Sit if you must. Don't touch anything." };

		public static readonly List<string> Talk = new List<string> { "The old ones built this. We only keep it standing.", "There's work, if you want it. There's always work.", "Ten thousand years and the roof still leaks.", "The forest remembers everything. So do I.", "Don't ask about the Mistlands." };

		public static readonly List<string> Goodbye = new List<string> { "Mind the roof.", "Don't die. The paperwork is endless.", "Come back when you've done something useful." };

		public static readonly List<string> NoErrands = new List<string> { "Nothing for you here. Nothing for anyone here.", "No work. Just weather." };

		public static readonly List<string> Offer = new List<string> { "There's work, if you want it.", "I need a thing done. You look like you have hands.", "Odin's strays are good for one thing. Fetching." };

		public static readonly List<string> HandIn = new List<string> { "Hm. Not bad. For a tall one.", "Good. Now I owe you, and I hate that.", "That's that, then. Sit. Don't touch anything." };

		public static readonly List<string> Tomorrow = new List<string> { "You have my errand. Find another of us, or come back tomorrow.", "One a day from me. The others may be softer." };

		public static readonly List<string> Wares = new List<string> { "Marks only. I don't want your coins.", "Look, don't touch. Then pay, then touch.", "Kin get the good shelf. You're not kin." };

		public static readonly List<string> HandsFull = new List<string> { "Your hands are full. Finish something.", "Five errands and you want a sixth? Go away." };

		public static string Pick(List<string> list)
		{
			return list[Random.Range(0, list.Count)];
		}

		public static void Fill(Trader t, Biome biome)
		{
			t.m_randomGreets = Greet;
			t.m_randomTalk = Talk;
			t.m_randomGoodbye = Goodbye;
			t.m_randomStartTrade = NoErrands;
			t.m_randomBuy = Talk;
			t.m_randomSell = Talk;
			t.m_randomGiveItemNo = Talk;
			t.m_randomUseItemAlreadyRecieved = Talk;
		}
	}
	public abstract class Popup : MonoBehaviour
	{
		private static readonly List<Popup> s_open = new List<Popup>();

		protected readonly List<GameObject> m_rows = new List<GameObject>();

		protected static readonly Vector2 Top = new Vector2(0.5f, 1f);

		protected static readonly Vector2 Bottom = new Vector2(0.5f, 0f);

		public static bool AnyOpen => s_open.Count > 0;

		protected void Show()
		{
			if (!s_open.Contains(this))
			{
				s_open.Add(this);
			}
			((Component)this).gameObject.SetActive(true);
		}

		public void Hide()
		{
			s_open.Remove(this);
			((Component)this).gameObject.SetActive(false);
		}

		public static void CloseAll()
		{
			Popup[] array = s_open.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				array[i].Hide();
			}
		}

		private void Update()
		{
			if (ZInput.GetKeyDown((KeyCode)27, true))
			{
				OnEscape();
			}
			Tick();
		}

		protected virtual void OnEscape()
		{
			Hide();
		}

		protected virtual void Tick()
		{
		}

		protected void Clear()
		{
			foreach (GameObject row in m_rows)
			{
				Object.Destroy((Object)(object)row);
			}
			m_rows.Clear();
		}

		protected GameObject Text(string s, float x, float y, int size, Color colour, bool bold, float width, TextAnchor align, Vector2? anchor = null)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = (Vector2)(((??)anchor) ?? Top);
			GameObject val2 = GUIManager.Instance.CreateText(s, ((Component)this).transform, val, val, new Vector2(x, y), bold ? GUIManager.Instance.AveriaSerifBold : GUIManager.Instance.AveriaSerif, size, colour, true, Color.black, width, 36f, false);
			Text component = val2.GetComponent<Text>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.alignment = align;
			}
			m_rows.Add(val2);
			return val2;
		}

		protected Button Button(string label, float x, float y, float w, float h, Vector2? anchor = null)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = (Vector2)(((??)anchor) ?? Top);
			GameObject val2 = GUIManager.Instance.CreateButton(label, ((Component)this).transform, val, val, new Vector2(x, y), w, h);
			m_rows.Add(val2);
			return val2.GetComponent<Button>();
		}

		protected static T Make<T>(string name, float w, float h, Vector2 anchor, Vector2 pos) where T : Popup
		{
			//IL_000f: 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_0011: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, anchor, anchor, pos, w, h, false);
			((Object)obj).name = name;
			obj.SetActive(false);
			return obj.AddComponent<T>();
		}
	}
	public class OfferDialog : Popup
	{
		private static OfferDialog s_instance;

		private const float W = 520f;

		private const float H = 160f;

		private Dvergr m_dvergr;

		public static void Show(Dvergr dvergr, Errand offer)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)s_instance))
			{
				s_instance = Popup.Make<OfferDialog>("ErrandsOffer", 520f, 160f, new Vector2(0.5f, 0f), new Vector2(0f, 190f));
			}
			s_instance.Fill(dvergr, offer);
			s_instance.Show();
		}

		private void Fill(Dvergr dvergr, Errand offer)
		{
			//IL_0039: 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_007b: 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)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Expected O, but got Unknown
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Expected O, but got Unknown
			Clear();
			m_dvergr = dvergr;
			Text(dvergr.Name, 0f, -20f, 18, GUIManager.Instance.ValheimOrange, bold: true, 480f, (TextAnchor)4);
			Text(JournalPanel.StandingLine(dvergr.Biome), 0f, -42f, 13, new Color(0.85f, 0.85f, 0.85f), bold: false, 480f, (TextAnchor)4);
			Text(offer.Title + Stars(offer.Tier), 0f, -68f, 20, Color.white, bold: false, 480f, (TextAnchor)4);
			((UnityEvent)Button("Accept", -150f, -118f, 130f, 40f).onClick).AddListener((UnityAction)delegate
			{
				Journal.Accept(offer);
				Hide();
			});
			((UnityEvent)Button("Decline", 0f, -118f, 130f, 40f).onClick).AddListener(new UnityAction(base.Hide));
			((UnityEvent)Button("Wares", 150f, -118f, 130f, 40f).onClick).AddListener(new UnityAction(dvergr.OpenWares));
		}

		public static string Stars(int tier)
		{
			return "  <color=#f0c040>" + new string('★', tier) + "</color>";
		}
	}
	public class JournalPanel : Popup
	{
		private static JournalPanel s_instance;

		private const float W = 560f;

		private const float Row = 44f;

		public static bool IsOpen
		{
			get
			{
				if (Object.op_Implicit((Object)(object)s_instance))
				{
					return ((Component)s_instance).gameObject.activeSelf;
				}
				return false;
			}
		}

		public static string StandingLine(Biome b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			int num = Journal.Rep(b);
			return $"Standing: {Biomes.Label(b)} - {num} ({Shop.TierTag(num)})";
		}

		public static void Toggle()
		{
			//IL_0051: 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)
			if (IsOpen)
			{
				s_instance.Hide();
				return;
			}
			float h = 170f + 44f * (float)Mathf.Max(1, ErrandsPlugin.MaxErrands.Value);
			if (!Object.op_Implicit((Object)(object)s_instance))
			{
				s_instance = Popup.Make<JournalPanel>("ErrandsJournal", 560f, h, new Vector2(0.5f, 0.5f), Vector2.zero);
			}
			s_instance.Fill();
			s_instance.Show();
		}

		private void Fill()
		{
			//IL_0042: 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_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Expected O, but got Unknown
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Expected O, but got Unknown
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			Clear();
			List<Errand> list = Journal.Active();
			Text($"Errands  {list.Count}/{ErrandsPlugin.MaxErrands.Value}", 0f, -24f, 22, GUIManager.Instance.ValheimOrange, bold: true, 520f, (TextAnchor)4);
			float num = -68f;
			if (list.Count == 0)
			{
				Text("No errands. The dvergr keep to the ruins.", 0f, num, 16, Color.grey, bold: false, 520f, (TextAnchor)4);
				num -= 44f;
			}
			foreach (Errand item in list)
			{
				bool flag = Journal.Complete(item);
				Text($"{item.Title}{OfferDialog.Stars(item.Tier)}   {Journal.Progress(item)}/{item.Need}   ({Biomes.Label(item.Biome)})", -45f, num, 17, (Color)(flag ? new Color(0.6f, 1f, 0.6f) : Color.white), bold: false, 410f, (TextAnchor)3);
				Button obj = Button("Drop", 220f, num, 70f, 34f);
				Errand captured = item;
				((UnityEvent)obj.onClick).AddListener((UnityAction)delegate
				{
					Journal.Abandon(captured);
					Fill();
				});
				num -= 44f;
			}
			Biome currentBiome = Player.m_localPlayer.GetCurrentBiome();
			if (Array.IndexOf(Biomes.All, currentBiome) >= 0)
			{
				Text(StandingLine(currentBiome), 0f, 72f, 15, new Color(0.85f, 0.85f, 0.85f), bold: false, 520f, (TextAnchor)4, Popup.Bottom);
			}
			((UnityEvent)Button("Close", 0f, 34f, 140f, 40f, Popup.Bottom).onClick).AddListener(new UnityAction(base.Hide));
		}
	}
	[HarmonyPatch(typeof(StoreGui), "IsVisible")]
	internal static class StoreGui_IsVisible_Patch
	{
		private static void Postfix(ref bool __result)
		{
			if (Popup.AnyOpen)
			{
				__result = true;
			}
		}
	}
	public class JournalKey : MonoBehaviour
	{
		private void Update()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && !Console.IsVisible() && !Menu.IsVisible() && !InventoryGui.IsVisible() && !TextInput.IsVisible() && (!Object.op_Implicit((Object)(object)Chat.instance) || !Chat.instance.HasFocus()) && ZInput.GetKeyDown(ErrandsPlugin.JournalKeyCode, true))
			{
				JournalPanel.Toggle();
			}
		}
	}
	public enum Verb
	{
		Kill,
		Gather,
		Craft
	}
	public class ErrandDef
	{
		public Verb Verb;

		public string[] Prefabs;

		public int Min;

		public int Max;

		public int Tier;

		public string[] Keys;

		public string Display;

		public ErrandDef(Verb verb, string prefabs, int min, int max, int tier)
		{
			Verb = verb;
			Prefabs = prefabs.Split(new char[1] { '/' });
			Min = min;
			Max = max;
			Tier = tier;
		}
	}
	public class Errand
	{
		public Biome Biome;

		public int Day;

		public Verb Verb;

		public string[] Keys;

		public string Display;

		public int Need;

		public int Have;

		public int Tier;

		public long Owner;

		public int Giver;

		public string GiverName = "";

		public string Id => $"{(int)Biome}:{Day}:{Owner}:{Giver}";

		public string VerbWord
		{
			get
			{
				if (Verb != Verb.Kill)
				{
					if (Verb != Verb.Gather)
					{
						return "Craft";
					}
					return "Bring";
				}
				return "Kill";
			}
		}

		public string Title => $"{VerbWord} {Need} {Localization.instance.Localize(Display)}";

		public string Serialize()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected I4, but got Unknown
			return string.Join("|", (int)Biome, Day, (int)Verb, string.Join("+", Keys), Display, Need, Have, Tier, Owner, Giver, GiverName);
		}

		public static Errand Parse(string line)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			string[] array = line.Split(new char[1] { '|' });
			if (array.Length < 8)
			{
				return null;
			}
			Errand errand = new Errand();
			errand.Biome = (Biome)int.Parse(array[0]);
			errand.Day = int.Parse(array[1]);
			errand.Verb = (Verb)int.Parse(array[2]);
			errand.Keys = array[3].Split(new char[1] { '+' });
			errand.Display = array[4];
			errand.Need = int.Parse(array[5]);
			errand.Have = int.Parse(array[6]);
			errand.Tier = int.Parse(array[7]);
			errand.Owner = ((array.Length > 8 && long.TryParse(array[8], out var result)) ? result : 0);
			errand.Giver = ((array.Length > 9 && int.TryParse(array[9], out var result2)) ? result2 : 0);
			errand.GiverName = ((array.Length > 10) ? array[10] : "");
			return errand;
		}
	}
	public static class Tables
	{
		private static readonly Dictionary<Biome, List<ErrandDef>> s_defs = new Dictionary<Biome, List<ErrandDef>>
		{
			[(Biome)1] = new List<ErrandDef>
			{
				new ErrandDef(Verb.Kill, "Deer", 8, 12, 1),
				new ErrandDef(Verb.Kill, "Boar", 8, 12, 1),
				new ErrandDef(Verb.Kill, "Neck", 8, 12, 1),
				new ErrandDef(Verb.Kill, "Greyling", 10, 15, 1),
				new ErrandDef(Verb.Gather, "Wood", 40, 60, 1),
				new ErrandDef(Verb.Gather, "Stone", 30, 50, 1),
				new ErrandDef(Verb.Gather, "Flint", 15, 25, 1),
				new ErrandDef(Verb.Gather, "Raspberry", 20, 30, 1),
				new ErrandDef(Verb.Gather, "Mushroom", 15, 20, 1),
				new ErrandDef(Verb.Gather, "DeerHide", 6, 10, 2),
				new ErrandDef(Verb.Gather, "Feathers", 10, 20, 2),
				new ErrandDef(Verb.Craft, "ArrowFlint", 40, 60, 1),
				new ErrandDef(Verb.Craft, "Torch", 6, 10, 1)
			},
			[(Biome)8] = new List<ErrandDef>
			{
				new ErrandDef(Verb.Kill, "Greydwarf/Greydwarf_Elite/Greydwarf_Shaman", 12, 20, 1),
				new ErrandDef(Verb.Kill, "Skeleton/Skeleton_Poison", 10, 15, 1),
				new ErrandDef(Verb.Kill, "Troll", 1, 2, 3),
				new ErrandDef(Verb.Gather, "CopperOre", 15, 25, 2),
				new ErrandDef(Verb.Gather, "TinOre", 10, 20, 2),
				new ErrandDef(Verb.Gather, "FineWood", 30, 40, 1),
				new ErrandDef(Verb.Gather, "RoundLog", 30, 40, 1),
				new ErrandDef(Verb.Gather, "Thistle", 8, 12, 1),
				new ErrandDef(Verb.Gather, "Blueberries", 20, 30, 1),
				new ErrandDef(Verb.Gather, "Resin", 20, 30, 1),
				new ErrandDef(Verb.Gather, "SurtlingCore", 3, 5, 3),
				new ErrandDef(Verb.Gather, "GreydwarfEye", 10, 20, 1),
				new ErrandDef(Verb.Craft, "Bronze", 6, 10, 2),
				new ErrandDef(Verb.Craft, "ArrowFire", 20, 40, 1),
				new ErrandDef(Verb.Craft, "BronzeNails", 40, 60, 2)
			},
			[(Biome)2] = new List<ErrandDef>
			{
				new ErrandDef(Verb.Kill, "Draugr/Draugr_Elite/Draugr_Ranged", 10, 15, 1),
				new ErrandDef(Verb.Kill, "Blob/BlobElite", 6, 10, 1),
				new ErrandDef(Verb.Kill, "Leech", 6, 10, 1),
				new ErrandDef(Verb.Kill, "Surtling", 5, 8, 2),
				new ErrandDef(Verb.Kill, "Wraith", 1, 2, 3),
				new ErrandDef(Verb.Kill, "Abomination", 1, 1, 3),
				new ErrandDef(Verb.Gather, "IronScrap", 15, 25, 2),
				new ErrandDef(Verb.Gather, "Guck", 8, 12, 1),
				new ErrandDef(Verb.Gather, "Bloodbag", 6, 10, 1),
				new ErrandDef(Verb.Gather, "Entrails", 6, 10, 1),
				new ErrandDef(Verb.Gather, "Ooze", 8, 12, 1),
				new ErrandDef(Verb.Gather, "AncientSeed", 2, 3, 3),
				new ErrandDef(Verb.Craft, "IronNails", 40, 60, 2),
				new ErrandDef(Verb.Craft, "ArrowIron", 20, 40, 2),
				new ErrandDef(Verb.Craft, "MeadBasePoisonResist", 2, 3, 1)
			},
			[(Biome)4] = new List<ErrandDef>
			{
				new ErrandDef(Verb.Kill, "Wolf", 6, 10, 1),
				new ErrandDef(Verb.Kill, "Hatchling", 4, 6, 2),
				new ErrandDef(Verb.Kill, "Fenring/Fenring_Cultist", 2, 3, 3),
				new ErrandDef(Verb.Kill, "StoneGolem", 1, 1, 3),
				new ErrandDef(Verb.Kill, "Ulv", 6, 10, 2),
				new ErrandDef(Verb.Gather, "SilverOre", 15, 25, 2),
				new ErrandDef(Verb.Gather, "Obsidian", 15, 25, 1),
				new ErrandDef(Verb.Gather, "FreezeGland", 6, 10, 1),
				new ErrandDef(Verb.Gather, "WolfPelt", 4, 6, 2),
				new ErrandDef(Verb.Gather, "Crystal", 3, 5, 3),
				new ErrandDef(Verb.Gather, "WolfMeat", 6, 10, 1),
				new ErrandDef(Verb.Craft, "ArrowObsidian", 40, 60, 2),
				new ErrandDef(Verb.Craft, "MeadBaseFrostResist", 2, 3, 1),
				new ErrandDef(Verb.Craft, "WolfJerky", 4, 8, 1)
			},
			[(Biome)16] = new List<ErrandDef>
			{
				new ErrandDef(Verb.Kill, "Goblin/GoblinArcher/GoblinShaman", 10, 15, 1),
				new ErrandDef(Verb.Kill, "GoblinBrute", 2, 3, 3),
				new ErrandDef(Verb.Kill, "Deathsquito", 6, 10, 1),
				new ErrandDef(Verb.Kill, "Lox", 2, 3, 2),
				new ErrandDef(Verb.Kill, "BlobTar", 4, 6, 2),
				new ErrandDef(Verb.Gather, "BlackMetalScrap", 15, 25, 2),
				new ErrandDef(Verb.Gather, "Barley", 20, 30, 1),
				new ErrandDef(Verb.Gather, "Flax", 20, 30, 1),
				new ErrandDef(Verb.Gather, "Cloudberry", 20, 30, 1),
				new ErrandDef(Verb.Gather, "LoxMeat", 4, 6, 2),
				new ErrandDef(Verb.Gather, "Needle", 6, 10, 1),
				new ErrandDef(Verb.Gather, "Tar", 8, 12, 2),
				new ErrandDef(Verb.Craft, "ArrowNeedle", 40, 60, 2),
				new ErrandDef(Verb.Craft, "BreadDough", 6, 10, 1)
			},
			[(Biome)512] = new List<ErrandDef>
			{
				new ErrandDef(Verb.Kill, "Seeker/SeekerBrood", 10, 15, 1),
				new ErrandDef(Verb.Kill, "SeekerBrute", 1, 2, 3),
				new ErrandDef(Verb.Kill, "Tick", 8, 12, 1),
				new ErrandDef(Verb.Kill, "Gjall", 1, 1, 3),
				new ErrandDef(Verb.Kill, "Hare", 4, 6, 1),
				new ErrandDef(Verb.Gather, "BlackMarble", 20, 30, 1),
				new ErrandDef(Verb.Gather, "Sap", 10, 15, 1),
				new ErrandDef(Verb.Gather, "YggdrasilWood", 20, 30, 1),
				new ErrandDef(Verb.Gather, "Softtissue", 8, 12, 2),
				new ErrandDef(Verb.Gather, "Carapace", 8, 12, 2),
				new ErrandDef(Verb.Gather, "Mandible", 2, 3, 3),
				new ErrandDef(Verb.Gather, "MushroomJotunPuffs", 8, 12, 1),
				new ErrandDef(Verb.Craft, "ArrowCarapace", 40, 60, 2),
				new ErrandDef(Verb.Craft, "YggdrasilPorridge", 4, 6, 1)
			},
			[(Biome)32] = new List<ErrandDef>
			{
				new ErrandDef(Verb.Kill, "Charred_Melee/Charred_Archer/Charred_Mage/Charred_Twitcher", 10, 15, 1),
				new ErrandDef(Verb.Kill, "Morgen", 1, 1, 3),
				new ErrandDef(Verb.Kill, "Volture", 4, 6, 1),
				new ErrandDef(Verb.Kill, "Asksvin", 2, 3, 2),
				new ErrandDef(Verb.Kill, "FallenValkyrie", 1, 1, 3),
				new ErrandDef(Verb.Gather, "Grausten", 20, 30, 1),
				new ErrandDef(Verb.Gather, "Blackwood", 20, 30, 1),
				new ErrandDef(Verb.Gather, "FlametalOreNew", 8, 12, 2),
				new ErrandDef(Verb.Gather, "CharredBone", 10, 20, 1),
				new ErrandDef(Verb.Gather, "AskHide", 4, 6, 2)
			}
		};

		private static bool s_resolved;

		public static void Resolve()
		{
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			if (s_resolved || !Object.op_Implicit((Object)(object)ObjectDB.instance) || !Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				return;
			}
			foreach (KeyValuePair<Biome, List<ErrandDef>> s_def in s_defs)
			{
				for (int num = s_def.Value.Count - 1; num >= 0; num--)
				{
					ErrandDef errandDef = s_def.Value[num];
					List<string> list = new List<string>();
					string[] prefabs = errandDef.Prefabs;
					foreach (string text in prefabs)
					{
						if (errandDef.Verb == Verb.Kill)
						{
							GameObject prefab = ZNetScene.instance.GetPrefab(text);
							Character val = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<Character>() : null);
							if (Object.op_Implicit((Object)(object)val))
							{
								list.Add(text);
								if (errandDef.Display == null)
								{
									errandDef.Display = val.m_name;
								}
							}
							continue;
						}
						GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text);
						ItemDrop val2 = (Object.op_Implicit((Object)(object)itemPrefab) ? itemPrefab.GetComponent<ItemDrop>() : null);
						if (Object.op_Implicit((Object)(object)val2))
						{
							list.Add(val2.m_itemData.m_shared.m_name);
							if (errandDef.Display == null)
							{
								errandDef.Display = val2.m_itemData.m_shared.m_name;
							}
						}
					}
					if (list.Count == 0)
					{
						Logger.LogWarning((object)string.Format("Errands: no such prefab {0} for {1}; errand dropped", string.Join("/", errandDef.Prefabs), s_def.Key));
						s_def.Value.RemoveAt(num);
					}
					else
					{
						errandDef.Keys = list.ToArray();
					}
				}
			}
			s_resolved = true;
		}

		public static Errand Offer(Biome biome, long playerId, int day, int giver, string giverName)
		{
			//IL_000a: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			Resolve();
			if (!s_defs.TryGetValue(biome, out var value) || value.Count == 0)
			{
				return null;
			}
			Random random = new Random((int)(playerId * 31 + (long)biome * 7919 + day * 104729 + (long)giver * 65537L));
			ErrandDef errandDef = value[random.Next(value.Count)];
			return new Errand
			{
				Biome = biome,
				Day = day,
				Verb = errandDef.Verb,
				Keys = errandDef.Keys,
				Display = errandDef.Display,
				Need = random.Next(errandDef.Min, errandDef.Max + 1),
				Have = 0,
				Tier = errandDef.Tier,
				Owner = playerId,
				Giver = giver,
				GiverName = giverName
			};
		}
	}
	[BepInPlugin("games.loxley.errands", "Errands", "0.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class ErrandsPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "games.loxley.errands";

		public const string PluginName = "Errands";

		public const string PluginVersion = "0.1.0";

		public const string DvergrPrefab = "ErrandsDvergr";

		public static ConfigEntry<float> RuinChance;

		public static ConfigEntry<float> KeyHue;

		public static ConfigEntry<float> KeyTolerance;

		public static ConfigEntry<float> KeyMinSaturation;

		public static ConfigEntry<int> MaxErrands;

		public static ConfigEntry<float> RealHours;

		public static ConfigEntry<int> RepPerTier;

		public static ConfigEntry<float> PartyRange;

		public static ConfigEntry<string> JournalKey;

		public static ConfigEntry<bool> ShowTracker;

		public static ConfigEntry<float> TrackerX;

		public static ConfigEntry<float> TrackerY;

		public static KeyCode JournalKeyCode = (KeyCode)106;

		public static readonly Dictionary<Biome, ConfigEntry<string>> Ruins = new Dictionary<Biome, ConfigEntry<string>>();

		public static readonly Dictionary<Biome, ConfigEntry<string>> Tints = new Dictionary<Biome, ConfigEntry<string>>();

		private unsafe void Awake()
		{
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			RuinChance = ((BaseUnityPlugin)this).Config.Bind<float>("Placement", "RuinChance", 0.25f, "Chance that a listed ruin has a dvergr in it. Decided once per ruin from the world seed, so everyone sees the same ones.");
			MaxErrands = ((BaseUnityPlugin)this).Config.Bind<int>("Errands", "MaxErrands", 5, "How many errands you can hold at once.");
			RealHours = ((BaseUnityPlugin)this).Config.Bind<float>("Errands", "RealHours", 0f, "0: each dvergr offers one errand per in-game day. Above 0: one per this many real hours instead.");
			RepPerTier = ((BaseUnityPlugin)this).Config.Bind<int>("Errands", "RepPerTier", 10, "Standing gained per errand star.");
			PartyRange = ((BaseUnityPlugin)this).Config.Bind<float>("Errands", "PartyRange", 30f, "Players within this many metres share kill credit, and receive a copy of any errand one of them accepts.");
			JournalKey = ((BaseUnityPlugin)this).Config.Bind<string>("Errands", "JournalKey", "J", "Key that opens your errand book anywhere (a UnityEngine.KeyCode name).");
			if (Enum.TryParse<KeyCode>(JournalKey.Value, ignoreCase: true, out KeyCode result))
			{
				JournalKeyCode = result;
			}
			ShowTracker = ((BaseUnityPlugin)this).Config.Bind<bool>("Tracker", "Show", true, "Show the errand tracker on the HUD while you hold at least one.");
			TrackerX = ((BaseUnityPlugin)this).Config.Bind<float>("Tracker", "X", 24f, "Tracker inset from the right edge of the screen.");
			TrackerY = ((BaseUnityPlugin)this).Config.Bind<float>("Tracker", "Y", 300f, "Tracker inset from the top of the screen (below the minimap).");
			KeyHue = ((BaseUnityPlugin)this).Config.Bind<float>("Tint", "KeyHue", 0.505f, "Hue (0-1) of the cloth on Haldor's texture. Only pixels near this hue are recoloured; skin and gold are left alone.");
			KeyTolerance = ((BaseUnityPlugin)this).Config.Bind<float>("Tint", "KeyTolerance", 0.03f, "How far from KeyHue a pixel may be and still count as cloth.");
			KeyMinSaturation = ((BaseUnityPlugin)this).Config.Bind<float>("Tint", "KeyMinSaturation", 0.45f, "Greys below this saturation are never recoloured.");
			Biome[] all = Biomes.All;
			for (int i = 0; i < all.Length; i++)
			{
				Biome val = all[i];
				Ruins[val] = ((BaseUnityPlugin)this).Config.Bind<string>("Placement", ((object)(*(Biome*)(&val))/*cast due to .constrained prefix*/).ToString() + "Ruins", Biomes.DefaultRuins(val), "Comma-separated vanilla location names a dvergr may shelter in. `errands_locations` in the console lists what your game has.");
				Tints[val] = ((BaseUnityPlugin)this).Config.Bind<string>("Dvergr", ((object)(*(Biome*)(&val))/*cast due to .constrained prefix*/).ToString() + "Tint", Biomes.DefaultTint(val), "hue,saturation,value shift applied to the cloth pixels of the dvergr's texture. Hue is 0-1 around the wheel.");
			}
			PrefabManager.OnVanillaPrefabsAvailable += AddPrefab;
			PrefabManager.OnPrefabsRegistered += Tables.Resolve;
			((Component)this).gameObject.AddComponent<JournalKey>();
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new SpawnCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new LocationsCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new TexDumpCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RepCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new DoneCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new KitCommand());
			new Harmony("games.loxley.errands").PatchAll();
		}

		private void AddPrefab()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			GameObject val = PrefabManager.Instance.CreateClonedPrefab("ErrandsDvergr", "Haldor");
			if (!Object.op_Implicit((Object)(object)val))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Haldor prefab not found; no dvergr for you.");
				return;
			}
			Trader component = val.GetComponent<Trader>();
			component.m_items.Clear();
			component.m_useItems.Clear();
			component.m_randomTalkConditionals.Clear();
			component.m_name = "Dvergr";
			val.AddComponent<Dvergr>();
			PrefabManager.Instance.AddPrefab(new CustomPrefab(val, false));
			Rewards.AddItems();
			Uniques.AddItems();
			PrefabManager.OnVanillaPrefabsAvailable -= AddPrefab;
		}
	}
	public static class Biomes
	{
		public static readonly Biome[] All;

		private static readonly string[] s_names;

		public static string DvergrName(int id)
		{
			return s_names[(uint)id % (uint)s_names.Length];
		}

		public static string DefaultTint(Biome b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected I4, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Invalid comparison between Unknown and I4
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Invalid comparison between Unknown and I4
			if ((int)b <= 16)
			{
				switch (b - 1)
				{
				default:
					if ((int)b != 8)
					{
						if ((int)b != 16)
						{
							break;
						}
						return "-0.35,0.1,0.1";
					}
					return "0.2,0,-0.1";
				case 0:
					return "0,0,0";
				case 1:
					return "-0.15,-0.2,-0.15";
				case 3:
					return "0.1,-0.3,0.25";
				case 2:
					break;
				}
			}
			else
			{
				if ((int)b == 32)
				{
					return "0.5,0.2,0";
				}
				if ((int)b == 64)
				{
					return "0.15,-0.5,0.3";
				}
				if ((int)b == 512)
				{
					return "0.3,0,-0.05";
				}
			}
			return "0,0,0";
		}

		public static string DefaultRuins(Biome b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Invalid comparison between Unknown and I4
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected I4, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Invalid comparison between Unknown and I4
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Invalid comparison between Unknown and I4
			if ((int)b <= 8)
			{
				switch (b - 1)
				{
				default:
					if ((int)b != 8)
					{
						break;
					}
					return "Ruin1,Ruin2,StoneTowerRuins03,StoneTowerRuins07,StoneTowerRuins08,StoneTowerRuins09,StoneTowerRuins10,StoneHouse3,StoneHouse4";
				case 0:
					return "WoodHouse1,WoodHouse2,WoodHouse3,WoodHouse4,WoodHouse5,WoodHouse6,WoodHouse7,WoodHouse8,WoodHouse9,WoodHouse10,WoodHouse11,WoodHouse12,WoodHouse13,WoodFarm1,WoodVillage1";
				case 1:
					return "SwampHut1,SwampHut2,SwampHut3,SwampHut4,SwampHut5,SwampRuin1,SwampRuin2";
				case 3:
					return "StoneTowerRuins04,StoneTowerRuins05,AbandonedLogCabin02,AbandonedLogCabin03,AbandonedLogCabin04";
				case 2:
					break;
				}
			}
			else
			{
				if ((int)b == 16)
				{
					return "StoneTower1,StoneTower3,Ruin3,StoneHenge1,StoneHenge2,StoneHenge3,StoneHenge4,StoneHenge5,StoneHenge6";
				}
				if ((int)b == 32)
				{
					return "CharredRuins1,CharredRuins2,CharredRuins3,CharredRuins4,CharredTowerRuins1,CharredTowerRuins2,CharredTowerRuins3";
				}
				if ((int)b == 512)
				{
					return "Mistlands_GuardTower1_ruined_new,Mistlands_GuardTower3_ruined_new,Mistlands_Excavation1,Mistlands_Excavation2,Mistlands_Excavation3,Mistlands_Statue1,Mistlands_Statue2";
				}
			}
			return "";
		}

		public static HashSet<string> RuinSet(Biome b)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			HashSet<string> hashSet = new HashSet<string>();
			if (!ErrandsPlugin.Ruins.TryGetValue(b, out var value))
			{
				return hashSet;
			}
			string[] array = value.Value.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length > 0)
				{
					hashSet.Add(text);
				}
			}
			return hashSet;
		}

		public unsafe static string Label(Biome b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			if ((int)b != 8)
			{
				if ((int)b != 32)
				{
					if ((int)b == 64)
					{
						return "Deep North";
					}
					return ((object)(*(Biome*)(&b))/*cast due to .constrained prefix*/).ToString();
				}
				return "Ashlands";
			}
			return "Black Forest";
		}

		static Biomes()
		{
			Biome[] array = new Biome[8];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			All = (Biome[])(object)array;
			s_names = new string[70]
			{
				"Alvíss", "Dvalinn", "Nár", "Frosti", "Bömburr", "Regin", "Brokkr", "Nori", "Andvari", "Austri",
				"Vestri", "Norðri", "Suðri", "Bifurr", "Bafurr", "Nóri", "Án", "Ánarr", "Óinn", "Mjöðvitnir",
				"Vígr", "Gandálfr", "Vindálfr", "Þorinn", "Þrór", "Vitr", "Litr", "Nýr", "Nýráðr", "Rekkr",
				"Ráðsviðr", "Fíli", "Kíli", "Fundinn", "Náli", "Hepti", "Víli", "Hannar", "Svíurr", "Billingr",
				"Brúni", "Bíldr", "Buri", "Frár", "Hornbori", "Frægr", "Lóni", "Aurvangr", "Jari", "Eikinskjaldi",
				"Draupnir", "Dólgþrasir", "Hár", "Haugspori", "Hlévangr", "Glói", "Dóri", "Óri", "Dúfr", "Skirfir",
				"Virfir", "Skáfiðr", "Ái", "Álfr", "Yngvi", "Fjalarr", "Finnr", "Ginnarr", "Sindri", "Eitri"
			};
		}
	}
	public static class Journal
	{
		[HarmonyPatch(typeof(Player), "OnInventoryChanged")]
		private static class AnnounceGather
		{
			private static void Postfix(Player __instance)
			{
				if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
				{
					OnInventoryChanged();
				}
			}
		}

		[HarmonyPatch(typeof(Player), "Awake")]
		private static class RegisterKillRpc
		{
			private static void Postfix(Player __instance)
			{
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				component.Register<string>("Errands_Kill", (Action<long, string>)delegate(long sender, string prefab)
				{
					if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
					{
						OnKill(prefab);
					}
				});
				component.Register<string, string>("Errands_Share", (Action<long, string, string>)delegate(long sender, string from, string line)
				{
					if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
					{
						OnShared(from, line);
					}
				});
			}
		}

		[HarmonyPatch(typeof(Character), "OnDeath")]
		private static class CreditKill
		{
			private static void Prefix(Character __instance, HitData ___m_lastHit)
			{
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				if (__instance.IsPlayer() || __instance.IsTamed())
				{
					return;
				}
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner())
				{
					return;
				}
				Character obj = ((___m_lastHit != null) ? ___m_lastHit.GetAttacker() : null);
				Player val = (Player)(object)((obj is Player) ? obj : null);
				if (val == null)
				{
					return;
				}
				string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject);
				List<Player> list = NearbyPlayers(((Component)__instance).transform.position);
				if (!list.Contains(val))
				{
					list.Add(val);
				}
				foreach (Player item in list)
				{
					ZNetView component2 = ((Component)item).GetComponent<ZNetView>();
					if (Object.op_Implicit((Object)(object)component2) && component2.IsValid())
					{
						component2.InvokeRPC("Errands_Kill", new object[1] { prefabName });
					}
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
		private static class CountCraft
		{
			private static void Prefix(Player player, Recipe ___m_craftRecipe, ItemData ___m_craftUpgradeItem, out KeyValuePair<string, int> __state)
			{
				__state = default(KeyValuePair<string, int>);
				if (!((Object)(object)___m_craftRecipe == (Object)null) && ___m_craftUpgradeItem == null && Object.op_Implicit((Object)(object)player))
				{
					string name = ___m_craftRecipe.m_item.m_itemData.m_shared.m_name;
					__state = new KeyValuePair<string, int>(name, ((Humanoid)player).GetInventory().CountItems(name, -1, true));
				}
			}

			private static void Postfix(Player player, KeyValuePair<string, int> __state)
			{
				if (__state.Key != null && Object.op_Implicit((Object)(object)player) && !((Object)(object)player != (Object)(object)Player.m_localPlayer))
				{
					int num = ((Humanoid)player).GetInventory().CountItems(__state.Key, -1, true) - __state.Value;
					if (num > 0)
					{
						OnCraft(__state.Key, num);
					}
				}
			}
		}

		private const string ActiveKey = "errands.active";

		private const string TakenKey = "errands.taken";

		private const string RepPrefix = "errands.rep.";

		private const string KillRpc = "Errands_Kill";

		private const string ShareRpc = "Errands_Share";

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

		private static Player P => Player.m_localPlayer;

		public static bool Full => Active().Count >= ErrandsPlugin.MaxErrands.Value;

		public static int Today()
		{
			float value = ErrandsPlugin.RealHours.Value;
			if (value > 0f)
			{
				return (int)((double)DateTime.UtcNow.Ticks / (36000000000.0 * (double)value));
			}
			if (!Object.op_Implicit((Object)(object)EnvMan.instance))
			{
				return 0;
			}
			return EnvMan.instance.GetDay();
		}

		public static List<Errand> Active()
		{
			List<Errand> list = new List<Errand>();
			if (!Object.op_Implicit((Object)(object)P) || !P.m_customData.TryGetValue("errands.active", out var value) || string.IsNullOrEmpty(value))
			{
				return list;
			}
			string[] array = value.Split(new char[1] { '\n' });
			for (int i = 0; i < array.Length; i++)
			{
				Errand errand = Errand.Parse(array[i]);
				if (errand != null)
				{
					list.Add(errand);
				}
			}
			return list;
		}

		private static void Save(List<Errand> list)
		{
			if (Object.op_Implicit((Object)(object)P))
			{
				P.m_customData["errands.active"] = string.Join("\n", list.Select((Errand e) => e.Serialize()));
			}
		}

		public static bool Taken(int giver, int day)
		{
			if (Object.op_Implicit((Object)(object)P) && P.m_customData.TryGetValue("errands.taken", out var value))
			{
				return value.Split(new char[1] { ';' }).Contains($"{giver}:{day}");
			}
			return false;
		}

		private static void MarkTaken(int giver, int day)
		{
			List<string> keep = new List<string> { $"{giver}:{day}" };
			if (P.m_customData.TryGetValue("errands.taken", out var value))
			{
				keep.AddRange(from k in value.Split(new char[1] { ';' })
					where k.EndsWith(":" + day) && !keep.Contains(k)
					select k);
			}
			P.m_customData["errands.taken"] = string.Join(";", keep);
		}

		public static int Rep(Biome biome)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected I4, but got Unknown
			if (!Object.op_Implicit((Object)(object)P) || !P.m_customData.TryGetValue("errands.rep." + (int)biome, out var value) || !int.TryParse(value, out var result))
			{
				return 0;
			}
			return result;
		}

		private static void AddRep(Biome biome, int amount)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			SetRep(biome, Rep(biome) + amount);
		}

		public static void SetRep(Biome biome, int value)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected I4, but got Unknown
			if (Object.op_Implicit((Object)(object)P))
			{
				P.m_customData["errands.rep." + (int)biome] = value.ToString();
			}
		}

		public static Errand TodaysOffer(Dvergr d)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)P))
			{
				return null;
			}
			return Tables.Offer(d.Biome, P.GetPlayerID(), Today(), d.Id, d.Name);
		}

		public static bool Accept(Errand offer)
		{
			if (!Object.op_Implicit((Object)(object)P) || offer == null || Full || Taken(offer.Giver, offer.Day))
			{
				return false;
			}
			List<Errand> list = Active();
			list.Add(offer);
			Save(list);
			MarkTaken(offer.Giver, offer.Day);
			((Character)P).Message((MessageType)2, "Errand taken: " + offer.Title, 0, (Sprite)null, false);
			Share(offer);
			return true;
		}

		private static void Share(Errand e)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			string text = e.Serialize();
			foreach (Player item in NearbyPlayers(((Component)P).transform.position))
			{
				if (!((Object)(object)item == (Object)(object)P))
				{
					ZNetView component = ((Component)item).GetComponent<ZNetView>();
					if (Object.op_Implicit((Object)(object)component) && component.IsValid())
					{
						component.InvokeRPC("Errands_Share", new object[2]
						{
							P.GetPlayerName(),
							text
						});
					}
				}
			}
		}

		private static void OnShared(string from, string line)
		{
			Errand e = Errand.Parse(line);
			if (e == null || !Object.op_Implicit((Object)(object)P))
			{
				return;
			}
			List<Errand> list = Active();
			if (!list.Exists((Errand x) => x.Id == e.Id))
			{
				if (list.Count >= ErrandsPlugin.MaxErrands.Value)
				{
					((Character)P).Message((MessageType)2, from + " took an errand but your hands are full", 0, (Sprite)null, false);
					return;
				}
				e.Have = 0;
				list.Add(e);
				Save(list);
				((Character)P).Message((MessageType)2, from + " shares an errand: " + e.Title, 0, (Sprite)null, false);
			}
		}

		public static List<Player> NearbyPlayers(Vector3 pos)
		{
			//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)
			float r = ErrandsPlugin.PartyRange.Value;
			return Player.GetAllPlayers().FindAll((Player p) => Object.op_Implicit((Object)(object)p) && Vector3.Distance(((Component)p).transform.position, pos) <= r);
		}

		public static int Progress(Errand e)
		{
			if (e.Verb != Verb.Gather || !Object.op_Implicit((Object)(object)P))
			{
				return Mathf.Min(e.Have, e.Need);
			}
			int num = 0;
			string[] keys = e.Keys;
			foreach (string text in keys)
			{
				num += ((Humanoid)P).GetInventory().CountItems(text, -1, true);
			}
			return Mathf.Min(num, e.Need);
		}

		public static bool Complete(Errand e)
		{
			return Progress(e) >= e.Need;
		}

		public static void Abandon(Errand e)
		{
			List<Errand> list = Active();
			list.RemoveAll((Errand x) => x.Id == e.Id);
			Save(list);
		}

		public static bool HandIn(Errand e, Biome at)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)P) || e.Biome != at || !Complete(e))
			{
				return false;
			}
			if (e.Verb == Verb.Gather)
			{
				int num = e.Need;
				string[] keys = e.Keys;
				foreach (string text in keys)
				{
					int num2 = Mathf.Min(num, ((Humanoid)P).GetInventory().CountItems(text, -1, true));
					if (num2 > 0)
					{
						((Humanoid)P).GetInventory().RemoveItem(text, num2, -1, true);
						num -= num2;
					}
				}
			}
			Abandon(e);
			int num3 = e.Tier * ErrandsPlugin.RepPerTier.Value;
			AddRep(e.Biome, num3);
			int num4 = Rep(e.Biome);
			((Character)P).Message((MessageType)2, $"Errand done. {Biomes.Label(e.Biome)} standing +{num3}  ({Shop.TierTag(num4)} {num4})", 0, (Sprite)null, false);
			Rewards.Grant(P, e);
			return true;
		}

		private static void Bump(Func<Errand, bool> matches, int amount)
		{
			List<Errand> list = Active();
			bool flag = false;
			foreach (Errand item in list)
			{
				if (item.Verb != Verb.Gather && item.Have < item.Need && matches(item))
				{
					item.Have = Mathf.Min(item.Need, item.Have + amount);
					flag = true;
					((Character)P).Message((MessageType)1, $"{item.Title}  {item.Have}/{item.Need}", 0, (Sprite)null, false);
				}
			}
			if (flag)
			{
				Save(list);
			}
		}

		public static void CompleteAll()
		{
			List<Errand> list = Active();
			foreach (Errand item in list)
			{
				item.Have = item.Need;
			}
			Save(list);
		}

		public static void OnKill(string prefab)
		{
			Bump((Errand e) => e.Verb == Verb.Kill && e.Keys.Contains(prefab), 1);
		}

		public static void OnCraft(string sharedName, int count)
		{
			Bump((Errand e) => e.Verb == Verb.Craft && e.Keys.Contains(sharedName), count);
		}

		public static void OnInventoryChanged()
		{
			foreach (Errand item in Active())
			{
				if (item.Verb == Verb.Gather)
				{
					int num = Progress(item);
					s_lastShown.TryGetValue(item.Id, out var value);
					if (num > value)
					{
						((Character)P).Message((MessageType)1, $"{item.Title}  {num}/{item.Need}", 0, (Sprite)null, false);
					}
					s_lastShown[item.Id] = num;
				}
			}
		}
	}
	[HarmonyPatch(typeof(ZoneSystem), "SpawnLocation")]
	internal static class ZoneSystem_SpawnLocation_Patch
	{
		private static void Postfix(ZoneLocation location, int seed, Vector3 pos, Quaternion rot, SpawnMode mode, List<GameObject> spawnedGhostObjects)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0013: 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_004d: 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_004f: 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_0053: Invalid comparison between Unknown and I4
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if (((int)mode == 0 || (int)mode == 2) && location != null)
			{
				Biome biome = WorldGenerator.instance.GetBiome(pos);
				if (Biomes.RuinSet(biome).Contains(location.m_prefabName) && !(new Random(seed ^ 0x45524E44).NextDouble() >= (double)ErrandsPlugin.RuinChance.Value))
				{
					Placement.Spawn(pos, rot, biome, (int)mode == 2, spawnedGhostObjects, seed);
					ZLog.Log((object)$"Errands: dvergr placed in {location.m_prefabName} at {pos}");
				}
			}
		}
	}
	public static class Placement
	{
		public static GameObject Spawn(Vector3 pos, Quaternion rot, Biome biome, bool ghost = false, List<GameObject> ghostList = null, int seed = 0)
		{
			//IL_002b: 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_0040: 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)
			GameObject prefab = ZNetScene.instance.GetPrefab("ErrandsDvergr");
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				ZLog.LogWarning((object)"Errands: dvergr prefab missing from ZNetScene");
				return null;
			}
			pos.y = ZoneSystem.instance.GetGroundHeight(pos);
			if (ghost)
			{
				ZNetView.StartGhostInit();
			}
			GameObject val = Object.Instantiate<GameObject>(prefab, pos, rot);
			int id = ((seed != 0) ? new Random(seed).Next(1, int.MaxValue) : Random.Range(1, int.MaxValue));
			Dvergr.SetBiome(val, biome, id);
			if (ghost)
			{
				ghostList?.Add(val);
				ZNetView.FinishGhostInit();
			}
			return val;
		}
	}
	public static class Rewards
	{
		private class Loot
		{
			public (string prefab, int min, int max)[] Materials;

			public string[] Meads;
		}

		[HarmonyPatch(typeof(Humanoid), "UseItem")]
		private static class UseChest
		{
			private static bool Prefix(Humanoid __instance, ItemData item)
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				Player val = (Player)(object)((__instance is Player) ? __instance : null);
				if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer || item == null)
				{
					return true;
				}
				if ((int)BiomeOf(item) == 0)
				{
					return true;
				}
				Open(val, item);
				return false;
			}
		}

		public const string MarkPrefab = "ErrandsMark";

		public const string ChestPrefix = "ErrandsChest_";

		public const string MarkName = "Dvergr Mark";

		private static readonly int[] s_marksPerTier = new int[4] { 0, 2, 4, 6 };

		private static readonly float[] s_uniqueChance = new float[4] { 0f, 0.08f, 0.15f, 0.3f };

		private static readonly Dictionary<Biome, Loot> s_loot = new Dictionary<Biome, Loot>
		{
			[(Biome)1] = new Loot
			{
				Materials = new(string, int, int)[5]
				{
					("LeatherScraps", 8, 15),
					("DeerHide", 4, 8),
					("Flint", 8, 15),
					("Resin", 10, 20),
					("Feathers", 8, 15)
				},
				Meads = new string[2] { "MeadHealthMinor", "MeadStaminaMinor" }
			},
			[(Biome)8] = new Loot
			{
				Materials = new(string, int, int)[5]
				{
					("CopperOre", 6, 12),
					("TinOre", 4, 8),
					("FineWood", 15, 25),
					("SurtlingCore", 2, 4),
					("Coal", 10, 20)
				},
				Meads = new string[3] { "MeadHealthMinor", "MeadStaminaMinor", "MeadTasty" }
			},
			[(Biome)2] = new Loot
			{
				Materials = new(string, int, int)[5]
				{
					("IronScrap", 6, 12),
					("Guck", 5, 10),
					("Bloodbag", 4, 8),
					("Chain", 1, 2),
					("Ooze", 5, 10)
				},
				Meads = new string[2] { "MeadPoisonResist", "MeadHealthMedium" }
			},
			[(Biome)4] = new Loot
			{
				Materials = new(string, int, int)[5]
				{
					("SilverOre", 6, 12),
					("Obsidian", 10, 20),
					("WolfPelt", 3, 5),
					("FreezeGland", 4, 8),
					("Crystal", 1, 3)
				},
				Meads = new string[3] { "MeadFrostResist", "MeadHealthMedium", "MeadStaminaMedium" }
			},
			[(Biome)16] = new Loot
			{
				Materials = new(string, int, int)[5]
				{
					("BlackMetalScrap", 6, 12),
					("Barley", 10, 20),
					("Flax", 10, 20),
					("Needle", 5, 10),
					("Tar", 5, 10)
				},
				Meads = new string[3] { "MeadHealthMedium", "MeadStaminaMedium", "MeadStaminaLingering" }
			},
			[(Biome)512] = new Loot
			{
				Materials = new(string, int, int)[5]
				{
					("BlackMarble", 10, 20),
					("Sap", 6, 12),
					("Softtissue", 5, 10),
					("Carapace", 5, 10),
					("Eitr", 2, 4)
				},
				Meads = new string[3] { "MeadEitrMinor", "MeadHealthMajor", "MeadStaminaLingering" }
			},
			[(Biome)32] = new Loot
			{
				Materials = new(string, int, int)[4]
				{
					("Grausten", 10, 20),
					("Blackwood", 10, 20),
					("FlametalOreNew", 3, 6),
					("CharredBone", 8, 15)
				},
				Meads = new string[3] { "MeadHealthMajor", "MeadStaminaLingering", "MeadEitrMinor" }
			}
		};

		private static readonly Dictionary<Biome, Color> s_chestTint = new Dictionary<Biome, Color>
		{
			[(Biome)1] = new Color(0.75f, 1f, 0.75f),
			[(Biome)8] = new Color(0.65f, 0.65f, 1f),
			[(Biome)2] = new Color(0.6f, 0.8f, 0.5f),
			[(Biome)4] = new Color(0.85f, 0.95f, 1f),
			[(Biome)16] = new Color(1f, 0.9f, 0.55f),
			[(Biome)512] = new Color(0.85f, 0.65f, 1f),
			[(Biome)32] = new Color(1f, 0.55f, 0.45f),
			[(Biome)64] = new Color(0.9f, 0.95f, 1f)
		};

		public unsafe static string ChestPrefab(Biome b)
		{
			return "ErrandsChest_" + ((object)(*(Biome*)(&b))/*cast due to .constrained prefix*/).ToString();
		}

		public static void AddItems()
		{
			//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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_007d: 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_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Expected O, but got Unknown
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Expected O, but got Unknown
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			CustomItem val = new CustomItem("ErrandsMark", "Coins", new ItemConfig
			{
				Name = "Dvergr Mark",
				Description = "A dvergr weight of silver. Haldor won't take it; the dvergr take nothing else."
			});
			SharedData shared = val.ItemDrop.m_itemData.m_shared;
			shared.m_maxStackSize = 999;
			shared.m_weight = 0f;
			Color c = default(Color);
			((Color)(ref c))..ctor(0.8f, 0.85f, 1f);
			Tint.Apply(val.ItemPrefab, new Color(0.6f, 0.65f, 0.8f));
			if (shared.m_icons.Length != 0 && Object.op_Implicit((Object)(object)shared.m_icons[0]))
			{
				shared.m_icons = (Sprite[])(object)new Sprite[1] { Tint.Sprite(shared.m_icons[0], c, desaturate: true) };
			}
			ItemManager.Instance.AddItem(val);
			GameObject prefab = PrefabManager.Instance.GetPrefab("piece_chest_wood");
			Sprite val2 = ((!Object.op_Implicit((Object)(object)prefab)) ? null : prefab.GetComponent<Piece>()?.m_icon);
			Biome[] all = Biomes.All;
			foreach (Biome val3 in all)
			{
				if (s_loot.ContainsKey(val3))
				{
					CustomItem val4 = new CustomItem(ChestPrefab(val3), "Coins", new ItemConfig
					{
						Name = Biomes.Label(val3) + " Dvergr Chest",
						Description = "Sealed with a dvergr's mark. Use it to see what they thought you were worth."
					});
					SharedData shared2 = val4.ItemDrop.m_itemData.m_shared;
					shared2.m_maxStackSize = 20;
					shared2.m_maxQuality = 3;
					shared2.m_weight = 2f;
					if (Object.op_Implicit((Object)(object)val2))
					{
						shared2.m_icons = (Sprite[])(object)new Sprite[1] { Tint.Sprite(val2, s_chestTint[val3]) };
					}
					ChestModel.Build(val4.ItemPrefab, s_chestTint[val3]);
					ItemManager.Instance.AddItem(val4);
				}
			}
		}

		public static void Grant(Player player, Errand e)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Clamp(e.Tier, 1, 3);
			Give(player, "ErrandsMark", 3 * num, 1);
			Give(player, ChestPrefab(e.Biome), 1, num);
		}

		public static void Open(Player player, ItemData chest)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			Biome val = BiomeOf(chest);
			if ((int)val == 0 || !s_loot.TryGetValue(val, out var value))
			{
				return;
			}
			int num = Mathf.Clamp(chest.m_quality, 1, 3);
			((Humanoid)player).GetInventory().RemoveItem(chest, 1);
			List<string> list = new List<string>();
			Give(player, "ErrandsMark", s_marksPerTier[num], 1, list);
			List<(string, int, int)> list2 = new List<(string, int, int)>(value.Materials);
			for (int i = 0; i < 2; i++)
			{
				if (list2.Count <= 0)
				{
					break;
				}
				(string, int, int) item = list2[Random.Range(0, list2.Count)];
				list2.Remove(item);
				Give(player, item.Item1, Random.Range(item.Item2, item.Item3 + 1), 1, list);
			}
			if (num >= 3 && value.Meads.Length != 0)
			{
				Give(player, value.Meads[Random.Range(0, value.Meads.Length)], 1, 1, list);
			}
			string text = ((Random.value < s_uniqueChance[num]) ? Uniques.RollChestUnique(player, val) : null);
			if (text != null)
			{
				Give(player, text, 1, 1, list);
				((Character)player).Message((MessageType)2, "The dvergr left you " + Uniques.DisplayName(text), 0, (Sprite)null, false);
			}
			((Character)player).Message((MessageType)1, "Chest: " + string.Join(", ", list), 0, (Sprite)null, false);
		}

		private static Biome BiomeOf(ItemData item)
		{
			//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_004e: Unknown result type (might be due to invalid IL or missing references)
			Biome[] all = Biomes.All;
			foreach (Biome val in all)
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(ChestPrefab(val));
				if (Object.op_Implicit((Object)(object)itemPrefab) && itemPrefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_name == item.m_shared.m_name)
				{
					return val;
				}
			}
			return (Biome)0;
		}

		private static void Give(Player player, string prefab, int amount, int quality, List<string> got = null)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			if (amount <= 0)
			{
				return;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefab);
			if (!Object.op_Implicit((Object)(object)itemPrefab))
			{
				Logger.LogWarning((object)("Errands: reward prefab " + prefab + " missing"));
				return;
			}
			ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
			int num = Mathf.Max(1, component.m_itemData.m_shared.m_maxStackSize);
			int num2 = amount;
			while (num2 > 0)
			{
				int num3 = Mathf.Min(num2, num);
				if (((Humanoid)player).GetInventory().AddItem(prefab, num3, quality, 0, 0L, "", false, false) == null)
				{
					Vector3 val = ((Component)player).transform.position + ((Component)player).transform.forward * 0.5f + Vector3.up;
					ItemData obj = component.m_itemData.Clone();
					obj.m_quality = quality;
					ItemDrop.DropItem(obj, num3, val, Quaternion.identity);
				}
				num2 -= num3;
			}
			got?.Add($"{amount} {Localization.instance.Localize(component.m_itemData.m_shared.m_name)}");
		}
	}
	public static class ChestModel
	{
		public static void Build(GameObject prefab, Color tint)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_0062: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			//IL_0091: 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)
			//IL_00bb: Expected O, but got Unknown
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].enabled = false;
			}
			Material m = MaterialOf("piece_chest_wood");
			GameObject val = new GameObject("chest");
			val.transform.SetParent(prefab.transform, false);
			val.layer = prefab.layer;
			Part(val, new Vector3(0f, 0.12f, 0f), new Vector3(0.45f, 0.24f, 0.3f), m, tint);
			Part(val, new Vector3(0f, 0.28f, 0f), new Vector3(0.47f, 0.08f, 0.32f), m, tint * 0.8f);
		}

		private static void Part(GameObject parent, Vector3 pos, Vector3 scale, Material m, Color tint)
		{
			//IL_0029: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3);
			Object.DestroyImmediate((Object)(object)obj.GetComponent<Collider>());
			obj.transform.SetParent(parent.transform, false);
			obj.transform.localPosition = pos;
			obj.transform.localScale = scale;
			obj.layer = parent.layer;
			MeshRenderer component = obj.GetComponent<MeshRenderer>();
			if (Object.op_Implicit((Object)(object)m))
			{
				Material val = new Material(m);
				if (val.HasProperty("_Color"))
				{
					val.color = tint;
				}
				((Renderer)component).sharedMaterial = val;
			}
		}

		private static Material MaterialOf(string prefabName)
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(prefabName);
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				return null;
			}
			MeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<MeshRenderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Material[] sharedMaterials = ((Renderer)componentsInChildren[i]).sharedMaterials;
				foreach (Material val in sharedMaterials)
				{
					if (Object.op_Implicit((Object)(object)val) && !((Object)val.shader).name.Contains("Snow") && !((Object)val).name.ToLower().Contains("snow") && Object.op_Implicit((Object)(object)val.mainTexture))
					{
						return val;
					}
				}
			}
			return null;
		}
	}
	public static class Tint
	{
		public static void Apply(GameObject prefab, Color c)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				Material[] sharedMaterials = val.sharedMaterials;
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					if (Object.op_Implicit((Object)(object)sharedMaterials[j]))
					{
						Material val2 = new Material(sharedMaterials[j]);
						if (val2.HasProperty("_Color"))
						{
							val2.color = c;
						}
						sharedMaterials[j] = val2;
					}
				}
				val.sharedMaterials = sharedMaterials;
			}
		}

		public static Sprite Sprite(Sprite src, Color c, bool desaturate = false)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Rect textureRect = src.textureRect;
				RenderTexture temporary = RenderTexture.GetTemporary(((Texture)src.texture).width, ((Texture)src.texture).height, 0, (RenderTextureFormat)0);
				RenderTexture active = RenderTexture.active;
				Graphics.Blit((Texture)(object)src.texture, temporary);
				RenderTexture.active = temporary;
				int num = (int)((Rect)(ref textureRect)).width;
				int num2 = (int)((Rect)(ref textureRect)).height;
				Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false);
				val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)num, (float)num2), 0, 0);
				Texture2D val2 = new Texture2D(num, num2, (TextureFormat)4, false);
				val2.ReadPixels(new Rect(((Rect)(ref textureRect)).x, (float)((Texture)src.texture).height - ((Rect)(ref textureRect)).y - (float)num2, (float)num, (float)num2), 0, 0);
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
				float num3 = Alpha(val);
				float num4 = Alpha(val2);
				if (num3 <= 0f && num4 <= 0f)
				{
					return src;
				}
				Texture2D val3 = ((num3 >= num4) ? val : val2);
				Color[] pixels = val3.GetPixels();
				for (int i = 0; i < pixels.Length; i++)
				{
					Color val4 = pixels[i];
					if (desaturate)
					{
						float num5 = val4.r * 0.3f + val4.g * 0.59f + val4.b * 0.11f;
						((Color)(ref val4))..ctor(num5, num5, num5, val4.a);
					}
					pixels[i] = new Color(val4.r * c.r, val4.g * c.g, val4.b * c.b, val4.a);
				}
				val3.SetPixels(pixels);
				val3.Apply();
				return Sprite.Create(val3, new Rect(0f, 0f, (float)num, (float)num2), new Vector2(0.5f, 0.5f), src.pixelsPerUnit);
			}
			catch
			{
				return src;
			}
			static float Alpha(Texture2D t)
			{
				//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_001a: Unknown result type (might be due to invalid IL or missing references)
				float num6 = 0f;
				Color[] pixels2 = t.GetPixels();
				foreach (Color val5 in pixels2)
				{
					num6 += val5.a;
				}
				return num6;
			}
		}
	}
	public static class Shop
	{
		public class Shelf
		{
			public TradeItem Item;

			public int Rep;
		}

		[HarmonyPatch(typeof(Trader), "GetAvailableItems")]
		private static class FilterByStanding
		{
			private static bool Prefix(Trader __instance, ref List<TradeItem> __result)
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				Dvergr component = ((Component)__instance).GetComponent<Dvergr>();
				if (!Object.op_Implicit((Object)(object)component) || component.Shelves == null)
				{
					return true;
				}
				int num = Journal.Rep(component.Biome);
				__result = new List<TradeItem>();
				foreach (Shelf shelf in component.Shelves)
				{
					if (shelf.Rep <= num && (string.IsNullOrEmpty(shelf.Item.m_buyKey) || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || !((Humanoid)Player.m_localPlayer).HaveUniqueKey(shelf.Item.m_buyKey)))
					{
						__result.Add(shelf.Item);
					}
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(StoreGui), "Show")]
		private static class SwapCurrency
		{
			private static ItemDrop s_coins;

			public static ItemDrop Coins => s_coins;

			private static void Prefix(StoreGui __instance, Trader trader)
			{
				if ((Object)(object)s_coins == (Object)null)
				{
					s_coins = __instance.m_coinPrefab;
				}
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("ErrandsMark");
				__instance.m_coinPrefab = ((Object.op_Implicit((Object)(object)trader) && Object.op_Implicit((Object)(object)((Component)trader).GetComponent<Dvergr>()) && Object.op_Implicit((Object)(object)itemPrefab)) ? itemPrefab.GetComponent<ItemDrop>() : s_coins);
			}
		}

		[HarmonyPatch(typeof(StoreGui), "FillList")]
		private static class SwapCoinIcons
		{
			private static void Postfix(StoreGui __instance, Trader ___m_trader)
			{
				ItemDrop coins = SwapCurrency.Coins;
				GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab("ErrandsMark") : null);
				if (!Object.op_Implicit((Object)(object)coins) || !Object.op_Implicit((Object)(object)val))
				{
					return;
				}
				Sprite val2 = coins.m_itemData.m_shared.m_icons[0];
				Sprite val3 = val.GetComponent<ItemDrop>().m_itemData.m_shared.m_icons[0];
				bool flag = Object.op_Implicit((Object)(object)___m_trader) && Object.op_Implicit((Object)(object)((Component)___m_trader).GetComponent<Dvergr>());
				if (Object.op_Implicit((Object)(object)__instance.m_sellButton))
				{
					((Component)((Component)__instance.m_sellButton).transform.parent).gameObject.SetActive(!flag);
				}
				Image[] componentsInChildren = __instance.m_rootPanel.GetComponentsInChildren<Image>(true);
				foreach (Image val4 in componentsInChildren)
				{
					if (!Object.op_Implicit((Object)(object)val4.sprite))
					{
						continue;
					}
					if ((Object)(object)val4.sprite == (Object)(object)val2)
					{
						if (flag)
						{
							val4.sprite = val3;
						}
					}
					else if ((Object)(object)val4.sprite == (Object)(object)val3)
					{
						if (!flag)
						{
							val4.sprite = val2;
						}
					}
					else if (((Object)val4.sprite).name == "coin_32" && flag)
					{
						val4.sprite = val3;
					}
				}
			}
		}

		[HarmonyPatch(typeof(StoreGui), "GetSellableItem")]
		private static class NoSelling
		{
			private static bool Prefix(Trader ___m_trader, ref ItemData __result)
			{
				if (!Object.op_Implicit((Object)(object)___m_trader) || !Object.op_Implicit((Object)(object)((Component)___m_trader).GetComponent<Dvergr>()))
				{
					return true;
				}
				__result = null;
				return false;
			}
		}

		[HarmonyPatch(typeof(Trader), "GetHoverText")]
		private static class HoverText
		{
			private static bool Prefix(Trader __instance, ref string __result)
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				Dvergr component = ((Component)__instance).GetComponent<Dvergr>();
				if (!Object.op_Implicit((Object)(object)component))
				{
					return true;
				}
				__result = Localization.instance.Localize(__instance.m_name + "  (" + TierTag(Journal.Rep(component.Biome)) + ")\n[<color=yellow><b>$KEY_Use</b></color>] Talk\n[<color=yellow><b>Hold $KEY_Use</b></color>] Wares");
				return false;
			}
		}

		public const int GuestRep = 30;

		public const int KinRep = 80;

		private static readonly Dictionary<Biome, (string prefab, int stack, int price)[]> s_goods = new Dictionary<Biome, (string, int, int)[]>
		{
			[(Biome)1] = new(string, int, int)[3]
			{
				("LeatherScraps", 20, 3),
				("DeerHide", 10, 4),
				("MeadHealthMinor", 3, 2)
			},
			[(Biome)8] = new(string, int, int)[3]
			{
				("Bronze", 5, 6),
				("SurtlingCore", 5, 5),
				("MeadStaminaMinor", 3, 2)
			},
			[(Biome)2] = new(string, int, int)[3]
			{
				("Iron", 5, 6),
				("Chain", 3, 4),
				("MeadPoisonResist", 3, 3)
			},
			[(Biome)4] = new(string, int, int)[3]
			{
				("Silver", 5, 6),
				("Crystal", 4, 5),
				("MeadFrostResist", 3, 3)
			},
			[(Biome)16] = new(string, int, int)[3]
			{
				("BlackMetal", 5, 6),
				("Tar", 10, 4),
				("MeadStaminaMedium", 3, 3)
			},
			[(Biome)512] = new(string, int, int)[3]
			{
				("Eitr", 3, 6),
				("Sap", 10, 4),
				("MeadEitrMinor", 3, 3)
			},
			[(Biome)32] = new(string, int, int)[3]
			{
				("FlametalNew", 3, 6),
				("Grausten", 20, 4),
				("MeadHealthMajor", 3, 4)
			}
		};

		public static string TierName(int rep)
		{
			if (rep < 80)
			{
				if (rep < 30)
				{
					return "Outsider";
				}
				return "Guest";
			}
			return "Kin";
		}

		public static string TierColour(int rep)
		{
			if (rep < 80)
			{
				if (rep < 30)
				{
					return "#9a9a9a";
				}
				return "#e0b04a";
			}
			return "#7fd97f";
		}

		public static string TierTag(int rep)
		{
			return "<color=" + TierColour(rep) + ">" + TierName(rep) + "</color>";
		}

		public static List<Shelf> Stock(Trader trader, Biome biome)
		{
			//IL_0012: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			List<Shelf> list = new List<Shelf>();
			trader.m_items = new List<TradeItem>();
			Add(list, Rewards.ChestPrefab(biome), 1, 8, 0);
			if (s_goods.TryGetValue(biome, out (string, int, int)[] value))
			{
				(string, int, int)[] array = value;
				for (int i = 0; i < array.Length; i++)
				{
					var (prefab, stack, price) = array[i];
					Add(list, prefab, stack, price, 30);
				}
			}
			List<string> list2 = Uniques.VendorUniques(biome);
			if (list2.Count > 0)
			{
				Add(list, list2[0], 1, 25, 30, once: true);
			}
			if (list2.Count > 1)
			{
				Add(list, list2[1], 1, 50, 80, once: true);
			}
			foreach (Shelf item in list)
			{
				trader.m_items.Add(item.Item);
			}
			return list;
		}

		private static void Add(List<Shelf> shelves, string prefab, int stack, int price, int rep, bool once = false)
		{
			//IL_005a: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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)
			//IL_00c1: Expected O, but got Unknown
			GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(prefab) : null);
			ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<ItemDrop>() : null);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				Logger.LogWarning((object)("Errands: shop item " + prefab + " missing"));
				return;
			}
			shelves.Add(new Shelf
			{
				Rep = rep,
				Item = new TradeItem
				{
					m_prefab = val2,
					m_stack = stack,
					m_price = price,
					m_buyKey = (once ? ("errands_bought_" + prefab) : ""),
					m_tooltip = "",
					m_name = "",
					m_requiredGlobalKey = "",
					m_incrementKey = ""
				}
			});
		}
	}
	public static class Tinting
	{
		private static readonly Dictionary<string, Texture2D> s_cache = new Dictionary<string, Texture2D>();

		private static bool? s_flipped;

		public static void Apply(GameObject go, Biome biome)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			if (!TryParse(ErrandsPlugin.Tints.TryGetValue(biome, out var value) ? value.Value : "", out var h, out var sat, out var v) || (h == 0f && sat == 0f && v == 0f))
			{
				return;
			}
			Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (val is ParticleSystemRenderer)
				{
					continue;
				}
				Material[] materials = val.materials;
				foreach (Material val2 in materials)
				{
					if (!Object.op_Implicit((Object)(object)val2))
					{
						continue;
					}
					Texture mainTexture = val2.mainTexture;
					Texture2D val3 = (Texture2D)(object)((mainTexture is Texture2D) ? mainTexture : null);
					if (val3 != null)
					{
						Texture2D val4 = Recolour(biome, val3, h, sat, v);
						if (Object.op_Implicit((Object)(object)val4))
						{
							val2.mainTexture = (Texture)(object)val4;
						}
					}
				}
			}
		}

		private unsafe static Texture2D Recolour(Biome biome, Texture2D src, float dh, float ds, float dv)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			string key = ((Object)src).name + "|" + ((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString();
			if (s_cache.TryGetValue(key, out var value))
			{
				return value;
			}
			Texture2D val = ReadBack(src);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			float value2 = ErrandsPlugin.KeyHue.Value;
			float value3 = ErrandsPlugin.KeyTolerance.Value;
			float value4 = ErrandsPlugin.KeyMinSaturation.Value;
			Color[] pixels = val.GetPixels();
			int num = 0;
			float num2 = default(float);
			float num3 = default(float);
			float num4 = default(float);
			for (int i = 0; i < pixels.Length; i++)
			{
				Color.RGBToHSV(pixels[i], ref num2, ref num3, ref num4);
				if (!(num3 < value4) && !(HueDistance(num2, value2) > value3))
				{
					Color val2 = Color.HSVToRGB(Mathf.Repeat(num2 + dh, 1f), Mathf.Clamp01(num3 + ds), Mathf.Clamp01(num4 + dv));
					val2.a = pixels[i].a;
					pixels[i] = val2;
					num++;
				}
			}
			val.SetPixels(pixels);
			val.Apply(tr