Decompiled source of SakeysMyKvastur v1.0.7

BepInEx/plugins/Sakey's My Kvastur/Sakey's My Kvastur.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("Sakey's My Kvastur")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Sakey's My Kvastur")]
[assembly: AssemblyTitle("Sakey's My Kvastur")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SakeysMyKvastur;

[BepInPlugin("com.sakey.my.kvastur", "Sakeys My Kvastur", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
	public const string PluginGUID = "com.sakey.my.kvastur";

	public const string PluginName = "Sakeys My Kvastur";

	public const string PluginVersion = "1.0.0";

	public const string CONTRACT_PREFAB = "SakeysMyKvasturContract";

	public const string KVASTUR_PREFAB = "SakeysMyKvastur";

	public const string VANILLA_KVASTUR_PREFAB = "BogWitchKvastur";

	public const string BROKEN_BROOM_PREFAB = "SakeysMyKvastur_BrokenBroom";

	public const string BROKEN_BROOM_NAME = "$SakeysMyKvastur_BrokenBroomName";

	public const string BROKEN_BROOM_DESC = "$SakeysMyKvastur_BrokenBroomDesc";

	public const string TROPHY_PREFAB = "TrophyKvastur";

	public const string BOGWITCH_PREFAB = "BogWitch";

	public const string CONTRACT_NAME = "$SakeysMyKvastur_Name";

	public const string CONTRACT_DESC = "$SakeysMyKvastur_Desc";

	public const string TRADE_TEXT = "$SakeysMyKvastur_Trade";

	public const string MENU_TRADE = "$SakeysMyKvastur_MenuTrade";

	public const string MENU_FOLLOW = "$SakeysMyKvastur_MenuFollow";

	public const string MENU_STAY = "$SakeysMyKvastur_MenuStay";

	public const string MENU_RETRIEVE = "$SakeysMyKvastur_MenuRetrieve";

	public const string COMMAND_FOLLOW_STAY = "$SakeysMyKvastur_CommandFollowStay";

	public const string COMMAND_FOLLOW = "$SakeysMyKvastur_CommandFollow";

	public const string COMMAND_STAY = "$SakeysMyKvastur_CommandStay";

	public const string COMMAND_RETRIEVE = "$SakeysMyKvastur_CommandRetrieve";

	public const string COMMAND_RENAME = "$SakeysMyKvastur_CommandRename";

	public const string COMMAND_SWEEP = "$SakeysMyKvastur_CommandSweep";

	public const string COMMAND_FOREST = "$SakeysMyKvastur_CommandForest";

	public const string COMMAND_MEADOWS = "$SakeysMyKvastur_CommandMeadows";

	public const string COMMAND_SWAMP = "$SakeysMyKvastur_CommandSwamp";

	public const string COMMAND_KVASTUR = "$SakeysMyKvastur_CommandKvastur";

	public const string FOLLOW_ON = "$SakeysMyKvastur_FollowOn";

	public const string FOLLOW_OFF = "$SakeysMyKvastur_FollowOff";

	public const string STAY_TEXT = "$SakeysMyKvastur_Stay";

	public const string RETRIEVED_TEXT = "$SakeysMyKvastur_Retrieved";

	public const string RENAME_TITLE = "$SakeysMyKvastur_RenameTitle";

	public const string RENAMED_TEXT = "$SakeysMyKvastur_Renamed";

	public const string NOT_OWNER = "$SakeysMyKvastur_NotOwner";

	public const string NO_KVASTUR = "$SakeysMyKvastur_NoKvastur";

	public const string INVENTORY_FULL = "$SakeysMyKvastur_InventoryFull";

	public const string NOT_ENOUGH_ITEM = "$SakeysMyKvastur_NotEnoughItem";

	public const string SOLD_TEXT = "$SakeysMyKvastur_Sold";

	public const string ALREADY_OWNED = "$SakeysMyKvastur_AlreadyOwned";

	public const string DEATH_TEXT = "$SakeysMyKvastur_Death";

	internal static ConfigEntry<int> ContractPrice;

	internal static ConfigEntry<float> PatrolRadius;

	internal static ConfigEntry<float> ReturnDistance;

	internal static ConfigEntry<bool> EnableBlackForestShop;

	internal static ConfigEntry<bool> EnableMeadowsShop;

	internal static ConfigEntry<bool> EnableSwampShop;

	internal static ConfigEntry<KeyboardShortcut> CommandKey;

	internal static ConfigFile ConfigInstance;

	private Harmony harmony;

	private int GetKvasturDefaultPrice(string prefabName)
	{
		switch (prefabName)
		{
		case "Sap":
			return 1;
		case "SurtlingCore":
			return 10;
		case "MoltenCore":
			return 20;
		case "Bloodbag":
			return 10;
		case "Entrails":
			return 10;
		case "MushroomMagecap":
			return 10;
		case "AncientSeed":
			return 20;
		case "Iron":
			return 10;
		case "DvergrNeedle":
			return 500;
		case "FlametalNew":
			return 150;
		case "GemstoneBlue":
		case "GemstoneRed":
		case "GemstoneGreen":
			return 200;
		case "BlackCore":
			return 600;
		case "FrostCore":
			return 1000;
		case "Gold":
			return 1000;
		default:
			return 10;
		}
	}

	private static void OnContractPriceChanged(object sender, EventArgs e)
	{
		if (ContractPrice == null)
		{
			return;
		}
		int num = Mathf.Max(0, ContractPrice.Value);
		try
		{
			Trader[] array = Object.FindObjectsOfType<Trader>();
			foreach (Trader val in array)
			{
				if ((Object)(object)val == (Object)null || val.m_items == null)
				{
					continue;
				}
				foreach (TradeItem item in val.m_items)
				{
					if (item != null && !((Object)(object)item.m_prefab == (Object)null) && string.Equals(((Object)((Component)item.m_prefab).gameObject).name.Replace("(Clone)", "").Trim(), "SakeysMyKvasturContract", StringComparison.OrdinalIgnoreCase))
					{
						item.m_price = num;
					}
				}
			}
		}
		catch (Exception ex)
		{
			Logger.LogWarning((object)("Failed to refresh Kvastur contract price: " + ex.Message));
		}
		Logger.LogInfo((object)$"Kvastur contract price changed to {num}.");
	}

	private void Awake()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		SetupConfig();
		SetupLocalization();
		harmony = new Harmony("com.sakey.my.kvastur");
		harmony.PatchAll();
		PrefabManager.OnVanillaPrefabsAvailable += RegisterKvasturCreature;
		PrefabManager.OnVanillaPrefabsAvailable += RegisterContractItem;
		PrefabManager.OnVanillaPrefabsAvailable += RegisterBrokenBroomItem;
		Logger.LogInfo((object)"Sakeys My Kvastur 1.0.0 loaded.");
	}

	private void SetupConfig()
	{
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		ConfigInstance = ((BaseUnityPlugin)this).Config;
		ContractPrice = ((BaseUnityPlugin)this).Config.Bind<int>("General", "ContractPrice", 1000, "Price of the Kvastur contract at the Bog Witch.");
		ContractPrice.SettingChanged += OnContractPriceChanged;
		PatrolRadius = ((BaseUnityPlugin)this).Config.Bind<float>("AI", "PatrolRadius", 10f, "Normal roaming radius around Kvastur's home position.");
		ReturnDistance = ((BaseUnityPlugin)this).Config.Bind<float>("AI", "ReturnDistance", 20f, "Distance from home before Kvastur returns.");
		EnableBlackForestShop = ((BaseUnityPlugin)this).Config.Bind<bool>("Shop - Black Forest", "EnableBlackForestShop", false, "Add the Black Forest (Haldor) shop to the F4 selection cycle.");
		EnableMeadowsShop = ((BaseUnityPlugin)this).Config.Bind<bool>("Shop - Meadows", "EnableMeadowsShop", false, "Add the Meadows (Hildir) shop to the F4 selection cycle.");
		EnableSwampShop = ((BaseUnityPlugin)this).Config.Bind<bool>("Shop - Swamp", "EnableSwampShop", true, "Add the Swamp (Bog Witch) shop to the F4 selection cycle.");
		CommandKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "CommandKey", new KeyboardShortcut((KeyCode)285, Array.Empty<KeyCode>()), "Kvastur command selection key. F4 cycles through enabled commands and shops. Press Use/E near your Kvastur to execute. Default: F4.");
	}

	private void SetupLocalization()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		CustomLocalization val = new CustomLocalization();
		string text = "English";
		val.AddTranslation(ref text, new Dictionary<string, string>
		{
			{ "SakeysMyKvastur_Name", "My Kvastur" },
			{ "SakeysMyKvastur_Desc", "While it sweeps, it can also use magic to place orders with the Bog Witch. You may keep several, but only one can be magically active at a time. If it breaks, it becomes just an ordinary broom. Take good care of it." },
			{ "SakeysMyKvastur_BrokenBroomName", "Ordinary Broom" },
			{ "SakeysMyKvastur_BrokenBroomDesc", "Just an ordinary broom now. Let’s fix it up." },
			{ "SakeysMyKvastur_MenuTrade", "Trade" },
			{ "SakeysMyKvastur_MenuFollow", "Follow" },
			{ "SakeysMyKvastur_MenuStay", "Stay" },
			{ "SakeysMyKvastur_MenuRetrieve", "Retrieve" },
			{ "SakeysMyKvastur_CommandFollowStay", "My Kvastur: Follow / Stay" },
			{ "SakeysMyKvastur_CommandFollow", "My Kvastur: Follow" },
			{ "SakeysMyKvastur_CommandStay", "My Kvastur: Stay" },
			{ "SakeysMyKvastur_CommandRetrieve", "My Kvastur: Retrieve" },
			{ "SakeysMyKvastur_CommandRename", "My Kvastur: Rename" },
			{ "SakeysMyKvastur_CommandSweep", "My Kvastur: Sweep" },
			{ "SakeysMyKvastur_CommandForest", "Black Forest Magic Shop" },
			{ "SakeysMyKvastur_CommandMeadows", "Meadows Magic Shop" },
			{ "SakeysMyKvastur_CommandSwamp", "Swamp Magic Shop" },
			{ "SakeysMyKvastur_CommandKvastur", "Kvastur Shop" },
			{ "SakeysMyKvastur_Trade", "Trade" },
			{ "SakeysMyKvastur_FollowOn", "My Kvastur will follow you." },
			{ "SakeysMyKvastur_FollowOff", "My Kvastur will stay here." },
			{ "SakeysMyKvastur_Stay", "My Kvastur will stay here." },
			{ "SakeysMyKvastur_Retrieved", "The Kvastur was stored in your inventory." },
			{ "SakeysMyKvastur_RenameTitle", "Rename Kvastur" },
			{ "SakeysMyKvastur_Renamed", "The Kvastur's name has been changed." },
			{ "SakeysMyKvastur_NotOwner", "This Kvastur does not belong to you." },
			{ "SakeysMyKvastur_NoKvastur", "You do not have a Kvastur nearby." },
			{ "SakeysMyKvastur_InventoryFull", "Your inventory is full." },
			{ "SakeysMyKvastur_NotEnoughItem", "You do not have that item." },
			{ "SakeysMyKvastur_Sold", "Sold for" },
			{ "SakeysMyKvastur_AlreadyOwned", "You already have a magical Kvastur. This broom remains as a spare." },
			{ "SakeysMyKvastur_Death", "Your Kvastur was destroyed and its magic was lost. Use a spare broom to make a new contract." },
			{ "SakeysMyKvastur_Talk1", "Hmm." },
			{ "SakeysMyKvastur_Talk2", "What do you need?" },
			{ "SakeysMyKvastur_Greet", "Come closer." },
			{ "SakeysMyKvastur_Goodbye", "Until next time." },
			{ "SakeysMyKvastur_StartTrade", "Take a look." },
			{ "SakeysMyKvastur_Buy", "It’s here!" },
			{ "SakeysMyKvastur_Delivered", "It’s here!" },
			{ "SakeysMyKvastur_Sell", "I can use that." },
			{ "SakeysMyKvastur_SellButton", "Sell" },
			{ "SakeysMyKvastur_FollowLabel", "Follow" },
			{ "SakeysMyKvastur_StayLabel", "Stay" },
			{ "SakeysMyKvastur_RetrieveLabel", "Retrieve Contract" }
		});
		text = "Japanese";
		val.AddTranslation(ref text, new Dictionary<string, string>
		{
			{ "SakeysMyKvastur_Name", "ボグウィッチのほうき" },
			{ "SakeysMyKvastur_Desc", "魔法のほうき。魔法の力でアイテムをお取り寄せしてくれる。魔女から授かったものなので、怒らせてはいけない。壊れたらただのほうきになる。大事に使おう。" },
			{ "SakeysMyKvastur_BrokenBroomName", "ただのほうき" },
			{ "SakeysMyKvastur_BrokenBroomDesc", "ただのほうきになってしまった。修理してあげよう。" },
			{ "SakeysMyKvastur_Trade", "取引" },
			{ "SakeysMyKvastur_FollowOn", "ボグウィッチのほうきはついてきます。" },
			{ "SakeysMyKvastur_FollowOff", "ボグウィッチのほうきはここに留まります。" },
			{ "SakeysMyKvastur_Stay", "ボグウィッチのほうきはここに留まります。" },
			{ "SakeysMyKvastur_Retrieved", "クヴァシルを荷物に収納しました。" },
			{ "SakeysMyKvastur_CommandSweep", "ボグウィッチのほうき:お掃除" },
			{ "SakeysMyKvastur_CommandForest", "森の魔法通販" },
			{ "SakeysMyKvastur_CommandMeadows", "草原の魔法通販" },
			{ "SakeysMyKvastur_CommandSwamp", "沼の魔法通販" },
			{ "SakeysMyKvastur_CommandKvastur", "クヴァシルのお取り寄せ" },
			{ "SakeysMyKvastur_NotOwner", "このクヴァシルはあなたのものではありません。" },
			{ "SakeysMyKvastur_NoKvastur", "近くにあなたのクヴァシルはいません。" },
			{ "SakeysMyKvastur_InventoryFull", "インベントリがいっぱいです。" },
			{ "SakeysMyKvastur_NotEnoughItem", "そのアイテムを持っていません。" },
			{ "SakeysMyKvastur_Sold", "売却しました:" },
			{ "SakeysMyKvastur_AlreadyOwned", "すでに魔法のクヴァシルを持っています。このほうきは予備として残ります。" },
			{ "SakeysMyKvastur_Death", "クヴァシルが壊れ、魔力を失いました。予備のほうきがあれば、もう一度契約できます。" },
			{ "SakeysMyKvastur_MenuTrade", "取引" },
			{ "SakeysMyKvastur_MenuFollow", "ついてくる" },
			{ "SakeysMyKvastur_MenuStay", "待機" },
			{ "SakeysMyKvastur_MenuRetrieve", "回収" },
			{ "SakeysMyKvastur_CommandFollowStay", "ボグウィッチのほうき:追従/待機" },
			{ "SakeysMyKvastur_CommandFollow", "ボグウィッチのほうき:追従" },
			{ "SakeysMyKvastur_CommandStay", "ボグウィッチのほうき:待機" },
			{ "SakeysMyKvastur_CommandRetrieve", "ボグウィッチのほうき:回収" },
			{ "SakeysMyKvastur_CommandRename", "クヴァシル:名前変更" },
			{ "SakeysMyKvastur_RenameTitle", "クヴァシルの名前" },
			{ "SakeysMyKvastur_Renamed", "クヴァシルの名前を変更しました。" },
			{ "SakeysMyKvastur_Talk1", "ふむ。" },
			{ "SakeysMyKvastur_Talk2", "何か用か?" },
			{ "SakeysMyKvastur_Greet", "近くへどうぞ。" },
			{ "SakeysMyKvastur_Goodbye", "また会おう。" },
			{ "SakeysMyKvastur_StartTrade", "見ていってくれ。" },
			{ "SakeysMyKvastur_Buy", "届いたよ" },
			{ "SakeysMyKvastur_Delivered", "届いたよ" },
			{ "SakeysMyKvastur_Sell", "これは使えそうだ。" },
			{ "SakeysMyKvastur_SellButton", "売る" },
			{ "SakeysMyKvastur_FollowLabel", "追従" },
			{ "SakeysMyKvastur_StayLabel", "待機" },
			{ "SakeysMyKvastur_RetrieveLabel", "荷物に収納" }
		});
		LocalizationManager.Instance.AddLocalization(val);
	}

	private void RegisterKvasturCreature()
	{
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Expected O, but got Unknown
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((Object)(object)PrefabManager.Instance.GetPrefab("BogWitchKvastur") == (Object)null)
			{
				Logger.LogError((object)"Base Kvastur prefab 'BogWitchKvastur' was not found.");
				return;
			}
			if ((Object)(object)PrefabManager.Instance.GetPrefab("SakeysMyKvastur") != (Object)null)
			{
				Logger.LogInfo((object)"Custom Kvastur prefab 'SakeysMyKvastur' is already registered.");
				return;
			}
			GameObject val = PrefabManager.Instance.CreateClonedPrefab("SakeysMyKvastur", "BogWitchKvastur");
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogError((object)"Failed to clone 'BogWitchKvastur' into 'SakeysMyKvastur'.");
				return;
			}
			CustomPrefab val2 = new CustomPrefab(val, true);
			Humanoid component = val.GetComponent<Humanoid>();
			if ((Object)(object)component != (Object)null)
			{
				((Character)component).m_name = "$SakeysMyKvastur_Name";
				((Character)component).m_faction = (Faction)0;
			}
			MonsterAI component2 = val.GetComponent<MonsterAI>();
			if ((Object)(object)component2 != (Object)null)
			{
				((BaseAI)component2).m_idleSound = null;
				((BaseAI)component2).m_idleSoundChance = 0f;
				((BaseAI)component2).m_idleSoundInterval = 0f;
			}
			Character component3 = val.GetComponent<Character>();
			if ((Object)(object)component3 != (Object)null)
			{
				component3.m_faction = (Faction)0;
			}
			RemoveKvasturTrophyDrop(val);
			if ((Object)(object)val.GetComponent<KvasturCompanion>() == (Object)null)
			{
				val.AddComponent<KvasturCompanion>();
			}
			if ((Object)(object)val.GetComponent<KvasturInteractable>() == (Object)null)
			{
				val.AddComponent<KvasturInteractable>();
			}
			PrefabManager.Instance.AddPrefab(val2);
			try
			{
				PrefabManager.Instance.RegisterToZNetScene(val);
			}
			catch (Exception ex)
			{
				Logger.LogDebug((object)("Kvastur current ZNetScene registration skipped/failed: " + ex.Message));
			}
			Logger.LogInfo((object)"Registered custom Kvastur prefab 'SakeysMyKvastur' as a separate clone of 'BogWitchKvastur'. No vanilla Kvastur was modified.");
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"Kvastur prefab registration failed: {arg}");
		}
		PrefabManager.OnVanillaPrefabsAvailable -= RegisterKvasturCreature;
	}

	private void RemoveKvasturTrophyDrop(GameObject prefab)
	{
		try
		{
			CharacterDrop component = prefab.GetComponent<CharacterDrop>();
			if (!((Object)(object)component == (Object)null) && component.m_drops != null)
			{
				component.m_drops.Clear();
			}
		}
		catch (Exception ex)
		{
			Logger.LogWarning((object)("Failed to remove Kvastur Trophy drop: " + ex.Message));
		}
	}

	private void ConfigureKvasturDeathDrop()
	{
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Expected O, but got Unknown
		try
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab("SakeysMyKvastur");
			if (!((Object)(object)prefab == (Object)null))
			{
				CharacterDrop val = prefab.GetComponent<CharacterDrop>();
				if ((Object)(object)val == (Object)null)
				{
					val = prefab.AddComponent<CharacterDrop>();
				}
				GameObject val2 = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("SakeysMyKvastur_BrokenBroom") : null);
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = PrefabManager.Instance.GetPrefab("SakeysMyKvastur_BrokenBroom");
				}
				if ((Object)(object)val2 == (Object)null)
				{
					Logger.LogWarning((object)"Broken broom prefab was not available while configuring Kvastur drops.");
					return;
				}
				val.m_drops.Clear();
				val.m_drops.Add(new Drop
				{
					m_prefab = val2,
					m_amountMin = 1,
					m_amountMax = 1,
					m_chance = 1f,
					m_onePerPlayer = false,
					m_levelMultiplier = false
				});
				Logger.LogInfo((object)"Configured My Kvastur death drop: 1x Broken Broom only.");
			}
		}
		catch (Exception arg)
		{
			Logger.LogWarning((object)$"Failed to configure Kvastur death drop: {arg}");
		}
	}

	private void RegisterContractItem()
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Expected O, but got Unknown
		//IL_0066: 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_007b: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			CustomItem val = new CustomItem("SakeysMyKvasturContract", "TrophyKvastur");
			ItemDrop itemDrop = val.ItemDrop;
			if ((Object)(object)itemDrop == (Object)null)
			{
				Logger.LogError((object)"Kvastur contract ItemDrop could not be created.");
				return;
			}
			itemDrop.m_itemData.m_shared.m_name = "$SakeysMyKvastur_Name";
			itemDrop.m_itemData.m_shared.m_description = "$SakeysMyKvastur_Desc";
			itemDrop.m_itemData.m_shared.m_itemType = (ItemType)16;
			itemDrop.m_itemData.m_shared.m_trophyPos = Vector2Int.zero;
			itemDrop.m_itemData.m_shared.m_questItem = false;
			itemDrop.m_itemData.m_shared.m_maxStackSize = 1;
			itemDrop.m_itemData.m_dropPrefab = val.ItemPrefab;
			if ((Object)(object)val.ItemPrefab.GetComponent<KvasturContractDrop>() == (Object)null)
			{
				val.ItemPrefab.AddComponent<KvasturContractDrop>();
			}
			if (!ItemManager.Instance.AddItem(val))
			{
				Logger.LogError((object)"Failed to register Kvastur contract.");
			}
			else
			{
				Logger.LogInfo((object)"Kvastur contract registered.");
			}
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"Kvastur contract registration failed: {arg}");
		}
		PrefabManager.OnVanillaPrefabsAvailable -= RegisterContractItem;
	}

	private void RegisterBrokenBroomItem()
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Expected O, but got Unknown
		//IL_0066: 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_007b: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			CustomItem val = new CustomItem("SakeysMyKvastur_BrokenBroom", "TrophyKvastur");
			ItemDrop itemDrop = val.ItemDrop;
			if ((Object)(object)itemDrop == (Object)null)
			{
				Logger.LogError((object)"Broken broom ItemDrop could not be created.");
				return;
			}
			itemDrop.m_itemData.m_shared.m_name = "$SakeysMyKvastur_BrokenBroomName";
			itemDrop.m_itemData.m_shared.m_description = "$SakeysMyKvastur_BrokenBroomDesc";
			itemDrop.m_itemData.m_shared.m_itemType = (ItemType)16;
			itemDrop.m_itemData.m_shared.m_trophyPos = Vector2Int.zero;
			itemDrop.m_itemData.m_shared.m_questItem = false;
			itemDrop.m_itemData.m_shared.m_maxStackSize = 20;
			itemDrop.m_itemData.m_dropPrefab = val.ItemPrefab;
			if (!ItemManager.Instance.AddItem(val))
			{
				Logger.LogError((object)"Failed to register broken broom item.");
			}
			else
			{
				Logger.LogInfo((object)"Broken broom item registered.");
				RegisterRepairRecipe();
				ConfigureKvasturDeathDrop();
			}
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"Broken broom registration failed: {arg}");
		}
		PrefabManager.OnVanillaPrefabsAvailable -= RegisterBrokenBroomItem;
	}

	private void RegisterRepairRecipe()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Expected O, but got Unknown
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Expected O, but got Unknown
		try
		{
			RecipeConfig val = new RecipeConfig
			{
				Name = "SakeysMyKvastur_Repair",
				Item = "SakeysMyKvasturContract",
				Amount = 1,
				CraftingStation = "piece_workbench",
				MinStationLevel = 1
			};
			val.AddRequirement("SakeysMyKvastur_BrokenBroom", 1, 0);
			val.AddRequirement("MeadEitrMinor", 1, 0);
			val.AddRequirement("LeatherScraps", 10, 0);
			val.AddRequirement("FineWood", 10, 0);
			bool flag = ItemManager.Instance.AddRecipe(new CustomRecipe(val));
			Logger.LogInfo((object)$"Kvastur repair recipe registered: {flag}");
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"Kvastur repair recipe registration failed: {arg}");
		}
	}

	private void OnDestroy()
	{
		PrefabManager.OnVanillaPrefabsAvailable -= RegisterKvasturCreature;
		PrefabManager.OnVanillaPrefabsAvailable -= RegisterContractItem;
		PrefabManager.OnVanillaPrefabsAvailable -= RegisterBrokenBroomItem;
		Harmony obj = harmony;
		if (obj != null)
		{
			obj.UnpatchSelf();
		}
	}
}
public class KvasturContractDrop : MonoBehaviour
{
	private bool processed;

	private void Start()
	{
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		if (processed)
		{
			return;
		}
		processed = true;
		if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
		{
			return;
		}
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			Logger.LogWarning((object)"Kvastur contract dropped, but local player was not found.");
		}
		else if ((Object)(object)KvasturCompanion.FindOwned(localPlayer.GetPlayerID()) != (Object)null)
		{
			((Character)localPlayer).Message((MessageType)2, "$SakeysMyKvastur_AlreadyOwned", 0, (Sprite)null, false);
			Logger.LogInfo((object)"Player already owns a Kvastur; spare contract was left untouched.");
		}
		else if (SpawnKvastur(((Component)this).transform.position, localPlayer))
		{
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				ZNetScene.instance.Destroy(((Component)this).gameObject);
			}
			else
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}
	}

	private bool SpawnKvastur(Vector3 position, Player owner)
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)owner == (Object)null)
		{
			return false;
		}
		GameObject prefab = PrefabManager.Instance.GetPrefab("SakeysMyKvastur");
		if ((Object)(object)prefab == (Object)null)
		{
			Logger.LogError((object)"Custom Kvastur prefab 'SakeysMyKvastur' was not found. No broom was spawned.");
			return false;
		}
		GameObject val = Object.Instantiate<GameObject>(prefab, position, ((Component)owner).transform.rotation);
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		ZNetView component = val.GetComponent<ZNetView>();
		if ((Object)(object)component == (Object)null || !component.IsValid())
		{
			Logger.LogError((object)"Spawned SakeysMyKvastur has no valid ZNetView.");
			Object.Destroy((Object)(object)val);
			return false;
		}
		ZDO zDO = component.GetZDO();
		if (zDO == null)
		{
			Logger.LogError((object)"Spawned SakeysMyKvastur has no ZDO.");
			Object.Destroy((Object)(object)val);
			return false;
		}
		zDO.Set("SakeysMyKvastur_Owner", owner.GetPlayerID());
		zDO.Set("SakeysMyKvastur_HomeX", position.x);
		zDO.Set("SakeysMyKvastur_HomeY", position.y);
		zDO.Set("SakeysMyKvastur_HomeZ", position.z);
		zDO.Set("SakeysMyKvastur_Follow", false);
		KvasturCompanion kvasturCompanion = val.GetComponent<KvasturCompanion>();
		if ((Object)(object)kvasturCompanion == (Object)null)
		{
			kvasturCompanion = val.AddComponent<KvasturCompanion>();
		}
		kvasturCompanion.Initialize(owner.GetPlayerID(), position);
		KvasturInteractable kvasturInteractable = val.GetComponent<KvasturInteractable>();
		if ((Object)(object)kvasturInteractable == (Object)null)
		{
			kvasturInteractable = val.AddComponent<KvasturInteractable>();
		}
		kvasturInteractable.Initialize();
		Humanoid component2 = val.GetComponent<Humanoid>();
		if ((Object)(object)component2 != (Object)null)
		{
			((Character)component2).m_faction = (Faction)0;
			kvasturCompanion.ApplyCustomName();
		}
		Logger.LogInfo((object)string.Format("Spawned custom {0} at {1} for player {2}. Vanilla {3} was not touched.", "SakeysMyKvastur", position, owner.GetPlayerID(), "BogWitchKvastur"));
		return true;
	}
}
public class KvasturCompanion : MonoBehaviour
{
	public static class KvasturPetEffect
	{
		private static object petEffect;

		private static MethodInfo createMethod;

		private static FieldInfo effectPrefabsField;

		public static void Create(Vector3 position, Quaternion rotation)
		{
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (petEffect == null || createMethod == null)
				{
					Initialize();
				}
				if (petEffect == null || createMethod == null || effectPrefabsField == null || !(effectPrefabsField.GetValue(petEffect) is Array { Length: not 0 } array))
				{
					return;
				}
				List<(AudioSource, bool, bool, float)> list = new List<(AudioSource, bool, bool, float)>();
				foreach (object item in array)
				{
					if (item == null)
					{
						continue;
					}
					FieldInfo fieldInfo = AccessTools.Field(item.GetType(), "m_prefab");
					if (fieldInfo == null)
					{
						continue;
					}
					object? value = fieldInfo.GetValue(item);
					GameObject val = (GameObject)((value is GameObject) ? value : null);
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					AudioSource[] componentsInChildren = val.GetComponentsInChildren<AudioSource>(true);
					foreach (AudioSource val2 in componentsInChildren)
					{
						if (!((Object)(object)val2 == (Object)null))
						{
							list.Add((val2, ((Behaviour)val2).enabled, val2.mute, val2.volume));
							val2.mute = true;
							val2.volume = 0f;
						}
					}
				}
				try
				{
					createMethod.Invoke(petEffect, new object[6]
					{
						position,
						rotation,
						null,
						1f,
						-1,
						(object)default(ZDOID)
					});
				}
				finally
				{
					foreach (var item2 in list)
					{
						if (!((Object)(object)item2.Item1 == (Object)null))
						{
							((Behaviour)item2.Item1).enabled = item2.Item2;
							item2.Item1.mute = item2.Item3;
							item2.Item1.volume = item2.Item4;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Logger.LogDebug((object)("Kvastur pet effect failed: " + ex.Message));
			}
		}

		private static void Initialize()
		{
			GameObject val = null;
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				val = ZNetScene.instance.GetPrefab("Boar");
			}
			if ((Object)(object)val == (Object)null)
			{
				val = PrefabManager.Instance.GetPrefab("Boar");
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Component component = val.GetComponent("Tameable");
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			FieldInfo fieldInfo = AccessTools.Field(((object)component).GetType(), "m_petEffect");
			if (fieldInfo == null)
			{
				return;
			}
			petEffect = fieldInfo.GetValue(component);
			if (petEffect != null)
			{
				effectPrefabsField = AccessTools.Field(petEffect.GetType(), "m_effectPrefabs");
				if (!(effectPrefabsField == null))
				{
					createMethod = AccessTools.Method(petEffect.GetType(), "Create", new Type[6]
					{
						typeof(Vector3),
						typeof(Quaternion),
						typeof(Transform),
						typeof(float),
						typeof(int),
						typeof(ZDOID)
					}, (Type[])null);
				}
			}
		}
	}

	private static readonly FieldInfo ZNetSceneInstancesField = AccessTools.Field(typeof(ZNetScene), "m_instances");

	private const string OWNER_KEY = "SakeysMyKvastur_Owner";

	private const string HOME_X_KEY = "SakeysMyKvastur_HomeX";

	private const string HOME_Y_KEY = "SakeysMyKvastur_HomeY";

	private const string HOME_Z_KEY = "SakeysMyKvastur_HomeZ";

	private const string FOLLOW_KEY = "SakeysMyKvastur_Follow";

	private const string ORIGINAL_VANILLA_KEY = "SakeysMyKvastur_OriginalVanilla";

	private const string DEAD_KEY = "SakeysMyKvastur_Dead";

	private const string NAME_KEY = "SakeysMyKvastur_Name";

	private const string PLAYER_NAME_KEY = "SakeysMyKvastur_PlayerName";

	private ZNetView nview;

	private MonsterAI monsterAI;

	private BaseAI baseAI;

	private Humanoid humanoid;

	private Vector3 homePosition;

	private bool initialized;

	private bool trading;

	private bool deathHandled;

	private float nextNetworkDiagnostic;

	private int networkDiagnosticCount;

	private bool destroyLogged;

	private float nextAIUpdate;

	private static readonly MethodInfo MoveToMethod = AccessTools.Method(typeof(BaseAI), "MoveTo", new Type[4]
	{
		typeof(float),
		typeof(Vector3),
		typeof(float),
		typeof(bool)
	}, (Type[])null);

	private static readonly MethodInfo RandomMovementAroundPointMethod = AccessTools.Method(typeof(BaseAI), "RandomMovementArroundPoint", new Type[4]
	{
		typeof(float),
		typeof(Vector3),
		typeof(float),
		typeof(bool)
	}, (Type[])null);

	private static readonly MethodInfo StopMovingMethod = AccessTools.Method(typeof(BaseAI), "StopMoving", Type.EmptyTypes, (Type[])null);

	private void Awake()
	{
		nview = ((Component)this).GetComponent<ZNetView>();
		monsterAI = ((Component)this).GetComponent<MonsterAI>();
		baseAI = ((Component)this).GetComponent<BaseAI>();
		humanoid = ((Component)this).GetComponent<Humanoid>();
		LoadState();
		ApplyCustomName();
		initialized = true;
		Logger.LogInfo((object)($"[Kvastur NET-DIAG] Awake: GO='{((Object)((Component)this).gameObject).name}', active={((Component)this).gameObject.activeInHierarchy}, " + "ZNetView=" + (((Object)(object)nview != (Object)null) ? "OK" : "NULL") + ", " + $"valid={(Object)(object)nview != (Object)null && nview.IsValid()}, " + "ZDO=" + (((Object)(object)nview != (Object)null && nview.GetZDO() != null) ? "OK" : "NULL")));
		nextNetworkDiagnostic = Time.unscaledTime + 1f;
	}

	private void FixedUpdate()
	{
		if (!initialized)
		{
			return;
		}
		if (networkDiagnosticCount < 3 && Time.unscaledTime >= nextNetworkDiagnostic)
		{
			networkDiagnosticCount++;
			LogNetworkDiagnostic($"periodic#{networkDiagnosticCount}");
			nextNetworkDiagnostic = Time.unscaledTime + 5f;
		}
		if (trading)
		{
			if (StoreGui.IsVisible())
			{
				StopKvasturMovement();
				if ((Object)(object)monsterAI != (Object)null)
				{
					monsterAI.SetFollowTarget((GameObject)null);
				}
				return;
			}
			trading = false;
		}
		if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner() && !(Time.time < nextAIUpdate))
		{
			nextAIUpdate = Time.time + 0.1f;
			UpdateAI();
		}
	}

	public void Initialize(long ownerID, Vector3 home)
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		nview = ((Component)this).GetComponent<ZNetView>();
		monsterAI = ((Component)this).GetComponent<MonsterAI>();
		baseAI = ((Component)this).GetComponent<BaseAI>();
		humanoid = ((Component)this).GetComponent<Humanoid>();
		homePosition = home;
		initialized = true;
		if ((Object)(object)nview != (Object)null && nview.IsValid() && nview.IsOwner())
		{
			ZDO zDO = nview.GetZDO();
			zDO.Set("SakeysMyKvastur_Owner", ownerID);
			SaveHome(home);
			zDO.Set("SakeysMyKvastur_Follow", false);
		}
		if ((Object)(object)baseAI != (Object)null)
		{
			baseAI.m_randomMoveRange = Plugin.PatrolRadius.Value;
			baseAI.m_randomMoveInterval = 20f;
		}
		if ((Object)(object)humanoid != (Object)null)
		{
			((Character)humanoid).m_faction = (Faction)0;
		}
	}

	public string GetCustomName()
	{
		string text = string.Empty;
		try
		{
			if ((Object)(object)nview != (Object)null && nview.IsValid())
			{
				ZDO zDO = nview.GetZDO();
				if (zDO != null)
				{
					text = zDO.GetString("SakeysMyKvastur_Name", string.Empty);
				}
			}
		}
		catch
		{
			text = string.Empty;
		}
		if (!string.IsNullOrWhiteSpace(text))
		{
			return text;
		}
		Player val = FindOwner();
		if ((Object)(object)val != (Object)null && val.m_customData != null && val.m_customData.TryGetValue("SakeysMyKvastur_PlayerName", out var value))
		{
			return value ?? string.Empty;
		}
		return string.Empty;
	}

	public void ApplyCustomName()
	{
		if ((Object)(object)humanoid == (Object)null)
		{
			humanoid = ((Component)this).GetComponent<Humanoid>();
		}
		if (!((Object)(object)humanoid == (Object)null))
		{
			string customName = GetCustomName();
			((Character)humanoid).m_name = (string.IsNullOrWhiteSpace(customName) ? "$SakeysMyKvastur_Name" : customName);
		}
	}

	public bool SetCustomName(string text)
	{
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || !IsOwner(localPlayer))
		{
			return false;
		}
		string text2 = text ?? string.Empty;
		text2 = text2.Trim();
		text2 = new string(text2.Where((char c) => !char.IsControl(c)).ToArray());
		if (text2.Length > 24)
		{
			text2 = text2.Substring(0, 24);
		}
		if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner())
		{
			return false;
		}
		ZDO zDO = nview.GetZDO();
		if (zDO == null)
		{
			return false;
		}
		zDO.Set("SakeysMyKvastur_Name", text2);
		if (localPlayer.m_customData != null)
		{
			if (string.IsNullOrEmpty(text2))
			{
				localPlayer.m_customData.Remove("SakeysMyKvastur_PlayerName");
			}
			else
			{
				localPlayer.m_customData["SakeysMyKvastur_PlayerName"] = text2;
			}
			try
			{
				Game instance = Game.instance;
				if ((Object)(object)instance != (Object)null)
				{
					PlayerProfile playerProfile = instance.GetPlayerProfile();
					if (playerProfile != null)
					{
						playerProfile.SavePlayerData(localPlayer);
					}
				}
			}
			catch (Exception ex)
			{
				Logger.LogDebug((object)("Kvastur custom name player-data save failed: " + ex.Message));
			}
		}
		ApplyCustomName();
		return true;
	}

	private void LogNetworkDiagnostic(string reason)
	{
		try
		{
			ZNetScene instance = ZNetScene.instance;
			bool flag = (Object)(object)instance != (Object)null;
			bool flag2 = (Object)(object)nview != (Object)null;
			bool flag3 = flag2 && nview.IsValid();
			ZDO val = (flag3 ? nview.GetZDO() : null);
			bool flag4 = val != null;
			bool flag5 = false;
			bool flag6 = false;
			string arg = "(unknown)";
			IDictionary<ZDO, ZNetView> dictionary = null;
			if (flag && ZNetSceneInstancesField != null)
			{
				dictionary = ZNetSceneInstancesField.GetValue(instance) as IDictionary<ZDO, ZNetView>;
			}
			if (flag && flag4 && dictionary != null)
			{
				flag5 = dictionary.ContainsKey(val);
				if (dictionary.TryGetValue(val, out var value))
				{
					flag6 = (Object)(object)value == (Object)(object)nview;
				}
				try
				{
					GameObject prefab = instance.GetPrefab(val.GetPrefab());
					arg = (((Object)(object)prefab != (Object)null) ? ((Object)prefab).name : $"(hash:{val.GetPrefab()})");
				}
				catch
				{
					arg = "(prefab lookup failed)";
				}
			}
			Logger.LogInfo((object)("[Kvastur NET-DIAG] " + reason + ": GO='" + (((Object)(object)((Component)this).gameObject != (Object)null) ? ((Object)((Component)this).gameObject).name : "<null>") + "', " + $"GOActive={(Object)(object)((Component)this).gameObject != (Object)null && ((Component)this).gameObject.activeInHierarchy}, " + $"ZNetScene={flag}, ZNetView={flag2}, Valid={flag3}, ZDO={flag4}, " + "instancesField=" + ((ZNetSceneInstancesField != null) ? "OK" : "MISSING") + ", instancesRead=" + ((dictionary != null) ? "OK" : "FAILED") + ", " + $"m_instances.ContainsZDO={flag5}, mappedToThisView={flag6}, " + $"prefab='{arg}', IsOwner={flag3 && nview.IsOwner()}"));
		}
		catch (Exception arg2)
		{
			Logger.LogWarning((object)$"[Kvastur NET-DIAG] {reason}: diagnostic itself failed: {arg2}");
		}
	}

	private void OnDisable()
	{
		LogNetworkDiagnostic("OnDisable");
	}

	private void OnDestroy()
	{
		if (!destroyLogged)
		{
			destroyLogged = true;
			LogNetworkDiagnostic("OnDestroy");
		}
	}

	private void LoadState()
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: 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_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)nview == (Object)null || !nview.IsValid())
		{
			homePosition = ((Component)this).transform.position;
			return;
		}
		ZDO zDO = nview.GetZDO();
		if (zDO == null)
		{
			homePosition = ((Component)this).transform.position;
			return;
		}
		float num = zDO.GetFloat("SakeysMyKvastur_HomeX", ((Component)this).transform.position.x);
		float num2 = zDO.GetFloat("SakeysMyKvastur_HomeY", ((Component)this).transform.position.y);
		float num3 = zDO.GetFloat("SakeysMyKvastur_HomeZ", ((Component)this).transform.position.z);
		homePosition = new Vector3(num, num2, num3);
	}

	private void StopKvasturMovement()
	{
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)baseAI == (Object)null)
		{
			return;
		}
		try
		{
			if (StopMovingMethod != null)
			{
				StopMovingMethod.Invoke(baseAI, null);
			}
			else if (MoveToMethod != null)
			{
				MoveToMethod.Invoke(baseAI, new object[4]
				{
					0.1f,
					((Component)this).transform.position,
					0f,
					false
				});
			}
		}
		catch (Exception ex)
		{
			Logger.LogDebug((object)("Kvastur stop movement failed: " + ex.Message));
		}
	}

	private void UpdateAI()
	{
		if (!((Object)(object)baseAI == (Object)null))
		{
			if (IsFollowing())
			{
				UpdateFollow();
			}
			else
			{
				UpdatePatrol();
			}
		}
	}

	private void UpdateFollow()
	{
		Player val = FindOwner();
		if (!((Object)(object)val == (Object)null) && !((Object)(object)monsterAI == (Object)null))
		{
			baseAI.m_randomMoveRange = 0f;
			monsterAI.SetFollowTarget(((Component)val).gameObject);
		}
	}

	private void UpdatePatrol()
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)baseAI != (Object)null)
		{
			baseAI.m_randomMoveRange = Plugin.PatrolRadius.Value;
		}
		if ((Object)(object)monsterAI != (Object)null)
		{
			monsterAI.SetFollowTarget((GameObject)null);
		}
		if (Vector3.Distance(((Component)this).transform.position, homePosition) > Plugin.ReturnDistance.Value)
		{
			MoveToHome();
		}
		else if (RandomMovementAroundPointMethod != null)
		{
			try
			{
				RandomMovementAroundPointMethod.Invoke(baseAI, new object[4]
				{
					0.5f,
					homePosition,
					Plugin.PatrolRadius.Value,
					false
				});
			}
			catch (Exception ex)
			{
				Logger.LogDebug((object)("Kvastur random movement failed: " + ex.Message));
			}
		}
	}

	private void MoveToHome()
	{
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		if (MoveToMethod == null || (Object)(object)baseAI == (Object)null)
		{
			return;
		}
		try
		{
			MoveToMethod.Invoke(baseAI, new object[4] { 0.5f, homePosition, 2f, true });
		}
		catch (Exception ex)
		{
			Logger.LogDebug((object)("Kvastur return movement failed: " + ex.Message));
		}
	}

	public long GetOwnerID()
	{
		if ((Object)(object)nview == (Object)null || !nview.IsValid())
		{
			return 0L;
		}
		ZDO zDO = nview.GetZDO();
		if (zDO == null)
		{
			return 0L;
		}
		return zDO.GetLong("SakeysMyKvastur_Owner", 0L);
	}

	public bool IsOwner(Player player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return false;
		}
		return GetOwnerID() == player.GetPlayerID();
	}

	public bool IsFollowing()
	{
		if ((Object)(object)nview == (Object)null || !nview.IsValid())
		{
			return false;
		}
		ZDO zDO = nview.GetZDO();
		if (zDO == null)
		{
			return false;
		}
		return zDO.GetBool("SakeysMyKvastur_Follow", false);
	}

	public void StopForCommand()
	{
		StopKvasturMovement();
		if ((Object)(object)monsterAI != (Object)null)
		{
			monsterAI.SetFollowTarget((GameObject)null);
		}
	}

	public void Follow()
	{
		if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner())
		{
			nview.GetZDO().Set("SakeysMyKvastur_Follow", true);
		}
	}

	public void StayHere()
	{
		//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_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner())
		{
			Vector3 position = ((Component)this).transform.position;
			nview.GetZDO().Set("SakeysMyKvastur_Follow", false);
			SaveHome(position);
			homePosition = position;
			if ((Object)(object)monsterAI != (Object)null)
			{
				monsterAI.SetFollowTarget((GameObject)null);
			}
		}
	}

	private void SaveHome(Vector3 position)
	{
		//IL_003f: 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_0061: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner())
		{
			ZDO zDO = nview.GetZDO();
			if (zDO != null)
			{
				zDO.Set("SakeysMyKvastur_HomeX", position.x);
				zDO.Set("SakeysMyKvastur_HomeY", position.y);
				zDO.Set("SakeysMyKvastur_HomeZ", position.z);
			}
		}
	}

	public void BeginTrading()
	{
		trading = true;
		StopKvasturMovement();
		if ((Object)(object)monsterAI != (Object)null)
		{
			monsterAI.SetFollowTarget((GameObject)null);
		}
	}

	public void EndTrading()
	{
		trading = false;
	}

	public bool IsTrading()
	{
		return trading;
	}

	public void HandleDeath()
	{
		if (deathHandled)
		{
			return;
		}
		deathHandled = true;
		Player val = FindOwner();
		if ((Object)(object)nview != (Object)null && nview.IsValid() && nview.IsOwner())
		{
			ZDO zDO = nview.GetZDO();
			if (zDO != null)
			{
				zDO.Set("SakeysMyKvastur_Dead", true);
				zDO.Set("SakeysMyKvastur_Owner", 0L);
				zDO.Set("SakeysMyKvastur_Follow", false);
			}
		}
		if ((Object)(object)val != (Object)null && (Object)(object)val == (Object)(object)Player.m_localPlayer)
		{
			((Character)val).Message((MessageType)2, "$SakeysMyKvastur_Death", 0, (Sprite)null, false);
		}
		Logger.LogInfo((object)"Kvastur companion died; magical ownership cleared.");
	}

	public void Retrieve()
	{
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return;
		}
		if (!IsOwner(localPlayer))
		{
			((Character)localPlayer).Message((MessageType)2, "$SakeysMyKvastur_NotOwner", 0, (Sprite)null, false);
		}
		else
		{
			if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner())
			{
				return;
			}
			GameObject val = ObjectDB.instance.GetItemPrefab("SakeysMyKvasturContract");
			if ((Object)(object)val == (Object)null)
			{
				val = PrefabManager.Instance.GetPrefab("SakeysMyKvasturContract");
			}
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogError((object)"Kvastur contract prefab not found.");
				return;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			if (inventory != null)
			{
				if (!inventory.AddItem(val, 1))
				{
					((Character)localPlayer).Message((MessageType)2, "$SakeysMyKvastur_InventoryFull", 0, (Sprite)null, false);
					return;
				}
				((Character)localPlayer).Message((MessageType)2, "$SakeysMyKvastur_Retrieved", 0, (Sprite)null, false);
				ZNetScene.instance.Destroy(((Component)this).gameObject);
			}
		}
	}

	private Player FindOwner()
	{
		long ownerID = GetOwnerID();
		if (ownerID == 0L)
		{
			return null;
		}
		foreach (Player allPlayer in Player.GetAllPlayers())
		{
			if ((Object)(object)allPlayer != (Object)null && allPlayer.GetPlayerID() == ownerID)
			{
				return allPlayer;
			}
		}
		return null;
	}

	public static KvasturCompanion FindOwned(long ownerID)
	{
		KvasturCompanion[] array = Object.FindObjectsOfType<KvasturCompanion>();
		foreach (KvasturCompanion kvasturCompanion in array)
		{
			if ((Object)(object)kvasturCompanion != (Object)null && kvasturCompanion.GetOwnerID() == ownerID)
			{
				return kvasturCompanion;
			}
		}
		return null;
	}
}
[HarmonyPatch(typeof(Character), "OnDeath")]
public static class KvasturDeathPatch
{
	[HarmonyPrefix]
	private static void Prefix(Character __instance)
	{
		if (!((Object)(object)__instance == (Object)null))
		{
			KvasturCompanion component = ((Component)__instance).GetComponent<KvasturCompanion>();
			if (!((Object)(object)component == (Object)null))
			{
				component.HandleDeath();
			}
		}
	}
}
[HarmonyPatch(typeof(Character), "Message", new Type[]
{
	typeof(MessageType),
	typeof(string),
	typeof(int),
	typeof(Sprite),
	typeof(bool)
})]
public static class KvasturCharacterMessagePatch
{
	[HarmonyPrefix]
	private static bool Prefix(Character __instance)
	{
		if ((Object)(object)__instance == (Object)null)
		{
			return true;
		}
		return (Object)(object)((Component)__instance).GetComponent<KvasturCompanion>() == (Object)null;
	}
}
[HarmonyPatch(typeof(Trader), "Say", new Type[]
{
	typeof(string),
	typeof(string)
})]
public static class KvasturTraderSayStringPatch
{
	[HarmonyPrefix]
	private static bool Prefix(Trader __instance)
	{
		if ((Object)(object)__instance == (Object)null)
		{
			return true;
		}
		return (Object)(object)((Component)__instance).GetComponent<KvasturCompanion>() == (Object)null;
	}
}
[HarmonyPatch(typeof(Trader), "Say", new Type[]
{
	typeof(List<string>),
	typeof(string)
})]
public static class KvasturTraderSayListPatch
{
	[HarmonyPrefix]
	private static bool Prefix(Trader __instance)
	{
		if ((Object)(object)__instance == (Object)null)
		{
			return true;
		}
		return (Object)(object)((Component)__instance).GetComponent<KvasturCompanion>() == (Object)null;
	}
}
[HarmonyPatch(typeof(Trader), "OnBought")]
public static class KvasturBoughtEffectPatch
{
	[HarmonyPostfix]
	private static void Postfix(Trader __instance, TradeItem item)
	{
		if (!((Object)(object)__instance == (Object)null) && item != null && !((Object)(object)item.m_prefab == (Object)null) && !((Object)(object)((Component)__instance).GetComponent<KvasturCompanion>() == (Object)null))
		{
			KvasturPurchaseFeedback kvasturPurchaseFeedback = ((Component)__instance).GetComponent<KvasturPurchaseFeedback>();
			if ((Object)(object)kvasturPurchaseFeedback == (Object)null)
			{
				kvasturPurchaseFeedback = ((Component)__instance).gameObject.AddComponent<KvasturPurchaseFeedback>();
			}
			kvasturPurchaseFeedback.Queue();
		}
	}
}
public class KvasturPurchaseFeedback : MonoBehaviour
{
	private bool queued;

	public void Queue()
	{
		queued = true;
	}

	private void LateUpdate()
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: 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)
		if (queued)
		{
			queued = false;
			KvasturCompanion component = ((Component)this).GetComponent<KvasturCompanion>();
			if (!((Object)(object)component == (Object)null))
			{
				KvasturCompanion.KvasturPetEffect.Create(((Component)component).transform.position + Vector3.up * 0.5f, ((Component)component).transform.rotation);
			}
		}
	}
}
[HarmonyPatch(typeof(KvasturInteractable), "Interact")]
public static class KvasturControllerCyclePatch
{
	[HarmonyPrefix]
	private static bool Prefix(Humanoid user)
	{
		if ((Object)(object)user == (Object)null || (Object)(object)user != (Object)(object)Player.m_localPlayer)
		{
			return true;
		}
		return !KvasturInputController.SuppressInteractThisFrame();
	}
}
public sealed class KvasturNameReceiver : TextReceiver
{
	private readonly KvasturCompanion companion;

	public KvasturNameReceiver(KvasturCompanion companion)
	{
		this.companion = companion;
	}

	public string GetText()
	{
		if (!((Object)(object)companion != (Object)null))
		{
			return string.Empty;
		}
		return companion.GetCustomName();
	}

	public void SetText(string text)
	{
		if (!((Object)(object)companion == (Object)null) && companion.SetCustomName(text))
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				((Character)localPlayer).Message((MessageType)2, "$SakeysMyKvastur_Renamed", 0, (Sprite)null, false);
			}
		}
	}
}
public class KvasturInteractable : MonoBehaviour, Interactable
{
	private enum ShopCategory
	{
		BlackForest,
		Meadows,
		Swamp,
		Kvastur
	}

	private KvasturCompanion companion;

	private Trader trader;

	private static readonly List<GameObject> temporaryTraderProbeObjects = new List<GameObject>();

	private void Awake()
	{
		Initialize();
	}

	public void Initialize()
	{
		companion = ((Component)this).GetComponent<KvasturCompanion>();
		trader = ((Component)this).GetComponent<Trader>();
		if ((Object)(object)trader == (Object)null)
		{
			trader = ((Component)this).gameObject.AddComponent<Trader>();
		}
		((Behaviour)trader).enabled = false;
		ConfigureTrader();
	}

	private void ConfigureTrader()
	{
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Expected O, but got Unknown
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Expected O, but got Unknown
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Expected O, but got Unknown
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Expected O, but got Unknown
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Expected O, but got Unknown
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Expected O, but got Unknown
		if (!((Object)(object)trader == (Object)null))
		{
			trader.m_name = "$SakeysMyKvastur_Name";
			trader.m_standRange = 3.5f;
			trader.m_greetRange = 7f;
			trader.m_byeRange = 8f;
			trader.m_randomTalkInterval = 18f;
			trader.m_randomTalkFX = new EffectList();
			trader.m_randomGreetFX = new EffectList();
			trader.m_randomGoodbyeFX = new EffectList();
			trader.m_randomStartTradeFX = new EffectList();
			trader.m_randomBuyFX = new EffectList();
			trader.m_randomSellFX = new EffectList();
			trader.m_randomTalk = new List<string>();
			trader.m_randomGreets = new List<string>();
			trader.m_randomGoodbye = new List<string>();
			trader.m_randomStartTrade = new List<string>();
			trader.m_randomBuy = new List<string>();
			trader.m_randomSell = new List<string>();
			trader.m_items = new List<TradeItem>();
			trader.m_useItems = new List<TraderUseItem>();
		}
	}

	public string GetHoverText()
	{
		return LocalizationManager.Instance.GetLocalization().TryTranslate("$SakeysMyKvastur_Name") + "\n[<color=yellow><b>$KEY_Use</b></color>] " + LocalizationManager.Instance.GetLocalization().TryTranslate("$SakeysMyKvastur_Trade");
	}

	public string GetHoverName()
	{
		if ((Object)(object)companion == (Object)null)
		{
			Initialize();
		}
		string text = (((Object)(object)companion != (Object)null) ? companion.GetCustomName() : string.Empty);
		if (!string.IsNullOrWhiteSpace(text))
		{
			return text;
		}
		return LocalizationManager.Instance.GetLocalization().TryTranslate("$SakeysMyKvastur_Name");
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//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_00ac: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)companion == (Object)null || (Object)(object)trader == (Object)null)
		{
			Initialize();
		}
		if (hold || (Object)(object)companion == (Object)null)
		{
			return false;
		}
		if (StoreGui.IsVisible() || InventoryGui.IsVisible() || Menu.IsVisible())
		{
			return false;
		}
		Player val = (Player)(object)((user is Player) ? user : null);
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		if (!companion.IsOwner(val))
		{
			((Character)val).Message((MessageType)2, "$SakeysMyKvastur_NotOwner", 0, (Sprite)null, false);
			return true;
		}
		KvasturCompanion.KvasturPetEffect.Create(((Component)companion).transform.position + Vector3.up * 0.5f, ((Component)companion).transform.rotation);
		Logger.LogInfo((object)$"Kvastur command executed: index={KvasturCommandMenu.SelectedIndex}.");
		KvasturCommandMenu.Execute(companion, val);
		return true;
	}

	private ShopCategory ToShopCategory(KvasturCommandMenu.ShopMode mode)
	{
		return mode switch
		{
			KvasturCommandMenu.ShopMode.BlackForest => ShopCategory.BlackForest, 
			KvasturCommandMenu.ShopMode.Meadows => ShopCategory.Meadows, 
			KvasturCommandMenu.ShopMode.Swamp => ShopCategory.Swamp, 
			_ => ShopCategory.Kvastur, 
		};
	}

	public void OpenTrade(KvasturCommandMenu.ShopMode mode)
	{
		if ((Object)(object)companion == (Object)null || (Object)(object)trader == (Object)null)
		{
			Initialize();
		}
		EnsureTraderItems(ToShopCategory(mode));
		if ((Object)(object)StoreGui.instance == (Object)null || (Object)(object)trader == (Object)null)
		{
			Logger.LogWarning((object)"Kvastur trade UI could not open: StoreGui or Trader is null.");
			return;
		}
		companion.BeginTrading();
		((Behaviour)trader).enabled = false;
		try
		{
			StoreGui.instance.Show(trader);
			Logger.LogInfo((object)"Kvastur trade UI opened.");
		}
		catch (Exception arg)
		{
			((Behaviour)trader).enabled = false;
			companion.EndTrading();
			Logger.LogError((object)$"Kvastur StoreGui.Show failed: {arg}");
		}
	}

	public void OpenRename()
	{
		if ((Object)(object)companion == (Object)null)
		{
			Initialize();
		}
		Player localPlayer = Player.m_localPlayer;
		if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)companion == (Object)null) && companion.IsOwner(localPlayer) && !((Object)(object)TextInput.instance == (Object)null))
		{
			TextInput.instance.RequestText((TextReceiver)(object)new KvasturNameReceiver(companion), LocalizationManager.Instance.GetLocalization().TryTranslate("$SakeysMyKvastur_RenameTitle"), 24);
		}
	}

	public void DoFollow(Player player)
	{
		companion.Follow();
		if ((Object)(object)player != (Object)null)
		{
			((Character)player).Message((MessageType)2, "$SakeysMyKvastur_FollowOn", 0, (Sprite)null, false);
		}
	}

	public void DoStay(Player player)
	{
		companion.StopForCommand();
		companion.StayHere();
		if ((Object)(object)player != (Object)null)
		{
			((Character)player).Message((MessageType)2, "$SakeysMyKvastur_Stay", 0, (Sprite)null, false);
		}
	}

	public void DoRetrieve()
	{
		companion.Retrieve();
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		return false;
	}

	private void EnsureTraderItems(ShopCategory category)
	{
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Expected O, but got Unknown
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Expected O, but got Unknown
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Expected O, but got Unknown
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Expected O, but got Unknown
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Expected O, but got Unknown
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Expected O, but got Unknown
		if (!((Object)(object)trader == (Object)null))
		{
			trader.m_items = new List<TradeItem>();
			switch (category)
			{
			case ShopCategory.BlackForest:
				AddTraderItemsFromSource(trader.m_items, FindTraderPrefab("Haldor"), ShopCategory.BlackForest);
				break;
			case ShopCategory.Meadows:
				AddTraderItemsFromSource(trader.m_items, FindTraderPrefab("Hildir"), ShopCategory.Meadows);
				break;
			case ShopCategory.Swamp:
				AddTraderItemsFromSource(trader.m_items, FindTraderPrefab("BogWitch"), ShopCategory.Swamp);
				AddKvasturContractToShop(trader.m_items, ShopCategory.Swamp);
				break;
			case ShopCategory.Kvastur:
				AddKvasturShopItems(trader.m_items);
				break;
			}
			FindLiveTrader(category switch
			{
				ShopCategory.Meadows => "Hildir", 
				ShopCategory.BlackForest => "Haldor", 
				_ => "BogWitch", 
			});
			trader.m_randomTalkFX = new EffectList();
			trader.m_randomGreetFX = new EffectList();
			trader.m_randomGoodbyeFX = new EffectList();
			trader.m_randomStartTradeFX = new EffectList();
			trader.m_randomBuyFX = new EffectList();
			trader.m_randomSellFX = new EffectList();
			trader.m_name = GetShopDisplayName(category);
		}
	}

	private void AddTraderItemsFromSource(List<TradeItem> target, Trader source, ShopCategory category)
	{
		if (target == null || (Object)(object)source == (Object)null)
		{
			return;
		}
		foreach (TradeItem item in (source.m_items != null) ? new List<TradeItem>(source.m_items) : new List<TradeItem>())
		{
			if (item != null && (!((Object)(object)item.m_prefab == (Object)null) || IsInventoryUpgradeTradeItem(item)) && (!string.Equals(((Object)(object)item.m_prefab != (Object)null) ? ((Object)((Component)item.m_prefab).gameObject).name.Replace("(Clone)", "").Trim() : GetInventoryUpgradeConfigName(item), "SakeysMyKvasturContract", StringComparison.OrdinalIgnoreCase) || category == ShopCategory.Swamp || category == ShopCategory.Kvastur))
			{
				AddSourceShopItem(target, item, category);
			}
		}
		try
		{
			Trader[] array = Object.FindObjectsOfType<Trader>();
			foreach (Trader val in array)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)source)
				{
					continue;
				}
				string a = ((Object)((Component)val).gameObject).name.Replace("(Clone)", "").Trim();
				string b = ((Object)((Component)source).gameObject).name.Replace("(Clone)", "").Trim();
				if (!string.Equals(a, b, StringComparison.OrdinalIgnoreCase) || val.m_items == null)
				{
					continue;
				}
				foreach (TradeItem item2 in new List<TradeItem>(val.m_items))
				{
					if (item2 != null && (!((Object)(object)item2.m_prefab == (Object)null) || IsInventoryUpgradeTradeItem(item2)) && (!string.Equals(((Object)(object)item2.m_prefab != (Object)null) ? ((Object)((Component)item2.m_prefab).gameObject).name.Replace("(Clone)", "").Trim() : GetInventoryUpgradeConfigName(item2), "SakeysMyKvasturContract", StringComparison.OrdinalIgnoreCase) || category == ShopCategory.Swamp || category == ShopCategory.Kvastur))
					{
						AddSourceShopItem(target, item2, category);
					}
				}
			}
		}
		catch (Exception ex)
		{
			Logger.LogDebug((object)$"Failed to read {category} trader m_items: {ex.Message}");
		}
		finally
		{
			CleanupTemporaryTraderProbes();
		}
	}

	private static void CleanupTemporaryTraderProbes()
	{
		if (temporaryTraderProbeObjects.Count == 0)
		{
			return;
		}
		foreach (GameObject temporaryTraderProbeObject in temporaryTraderProbeObjects)
		{
			if ((Object)(object)temporaryTraderProbeObject != (Object)null)
			{
				Object.Destroy((Object)(object)temporaryTraderProbeObject);
			}
		}
		temporaryTraderProbeObjects.Clear();
	}

	private Trader FindLiveTrader(string prefabName)
	{
		if (string.IsNullOrEmpty(prefabName))
		{
			return null;
		}
		try
		{
			Trader[] array = Object.FindObjectsOfType<Trader>();
			foreach (Trader val in array)
			{
				if (!((Object)(object)val == (Object)null) && string.Equals(((Object)((Component)val).gameObject).name.Replace("(Clone)", "").Trim(), prefabName, StringComparison.OrdinalIgnoreCase))
				{
					return val;
				}
			}
		}
		catch
		{
		}
		return null;
	}

	private Trader FindTraderPrefab(string prefabName)
	{
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Expected O, but got Unknown
		if (string.IsNullOrEmpty(prefabName))
		{
			return null;
		}
		try
		{
			Trader[] array = Object.FindObjectsOfType<Trader>();
			foreach (Trader val in array)
			{
				if (!((Object)(object)val == (Object)null) && string.Equals(((Object)((Component)val).gameObject).name.Replace("(Clone)", "").Trim(), prefabName, StringComparison.OrdinalIgnoreCase))
				{
					return val;
				}
			}
		}
		catch
		{
		}
		GameObject val2 = null;
		try
		{
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				val2 = ZNetScene.instance.GetPrefab(prefabName);
			}
		}
		catch
		{
		}
		if ((Object)(object)val2 == (Object)null)
		{
			try
			{
				val2 = PrefabManager.Instance.GetPrefab(prefabName);
			}
			catch
			{
			}
		}
		if ((Object)(object)val2 == (Object)null)
		{
			return null;
		}
		try
		{
			GameObject val3 = new GameObject(prefabName);
			((Object)val3).hideFlags = (HideFlags)61;
			val3.SetActive(false);
			Trader val4 = val3.AddComponent<Trader>();
			Trader component = val2.GetComponent<Trader>();
			val4.m_items = (((Object)(object)component != (Object)null && component.m_items != null) ? new List<TradeItem>(component.m_items) : new List<TradeItem>());
			MethodInfo methodInfo = AccessTools.Method(typeof(Trader), "Start", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				methodInfo.Invoke(val4, null);
			}
			temporaryTraderProbeObjects.Add(val3);
			return val4;
		}
		catch (Exception ex)
		{
			Logger.LogDebug((object)("Kvastur trader probe failed for " + prefabName + ": " + ex.Message));
			return null;
		}
	}

	private bool IsTradeItemAvailable(TradeItem item)
	{
		if (item != null)
		{
			return (Object)(object)item.m_prefab != (Object)null;
		}
		return false;
	}

	private bool IsInventoryUpgradeTradeItem(TradeItem item)
	{
		if (item == null)
		{
			return false;
		}
		string text = item.m_name ?? string.Empty;
		string text2 = item.m_tooltip ?? string.Empty;
		if (text.IndexOf("hud_extrainvslot1", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("hud_extrainvslot2", StringComparison.OrdinalIgnoreCase) < 0 && text2.IndexOf("hud_extrainvslot1", StringComparison.OrdinalIgnoreCase) < 0)
		{
			return text2.IndexOf("hud_extrainvslot2", StringComparison.OrdinalIgnoreCase) >= 0;
		}
		return true;
	}

	private string GetInventoryUpgradeConfigName(TradeItem item)
	{
		string text = item?.m_name ?? string.Empty;
		string text2 = item?.m_tooltip ?? string.Empty;
		if (text.IndexOf("hud_extrainvslot1", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("hud_extrainvslot1", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return "WiderPockets";
		}
		if (text.IndexOf("hud_extrainvslot2", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("hud_extrainvslot2", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return "DeeperPockets";
		}
		return "InventoryUpgrade";
	}

	private void AddSourceShopItem(List<TradeItem> target, TradeItem sourceItem, ShopCategory category)
	{
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: 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_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: 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_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Expected O, but got Unknown
		if (target == null || sourceItem == null)
		{
			return;
		}
		bool flag = IsInventoryUpgradeTradeItem(sourceItem);
		if ((Object)(object)sourceItem.m_prefab == (Object)null && !flag)
		{
			return;
		}
		foreach (TradeItem item in target)
		{
			if (item != null && (((Object)(object)sourceItem.m_prefab != (Object)null && (Object)(object)item.m_prefab == (Object)(object)sourceItem.m_prefab) || (flag && IsInventoryUpgradeTradeItem(item) && string.Equals(GetInventoryUpgradeConfigName(item), GetInventoryUpgradeConfigName(sourceItem), StringComparison.OrdinalIgnoreCase))))
			{
				return;
			}
		}
		string text = (((Object)(object)sourceItem.m_prefab != (Object)null) ? ((Object)((Component)sourceItem.m_prefab).gameObject).name.Replace("(Clone)", "").Trim() : GetInventoryUpgradeConfigName(sourceItem));
		int shopPrice = GetShopPrice(category, text, sourceItem.m_price);
		target.Add(new TradeItem
		{
			m_prefab = sourceItem.m_prefab,
			m_stack = sourceItem.m_stack,
			m_price = Mathf.Max(0, shopPrice),
			m_requiredGlobalKey = string.Empty,
			m_levelUpEffect = sourceItem.m_levelUpEffect,
			m_buyPlayerEffects = (EffectList)(((object)sourceItem.m_buyPlayerEffects) ?? ((object)new EffectList())),
			m_icon = sourceItem.m_icon,
			m_name = (sourceItem.m_name ?? string.Empty),
			m_tooltip = (sourceItem.m_tooltip ?? string.Empty),
			m_buyKey = (sourceItem.m_buyKey ?? string.Empty),
			m_incrementKey = (sourceItem.m_incrementKey ?? string.Empty),
			m_incrementAmount = sourceItem.m_incrementAmount
		});
		Logger.LogInfo((object)($"Kvastur: added {(flag ? text : text)} from {category} shop. " + "prefab=" + (((Object)(object)sourceItem.m_prefab != (Object)null) ? ((Object)((Component)sourceItem.m_prefab).gameObject).name : "<special>") + ", " + $"buyKey={sourceItem.m_buyKey}, incrementKey={sourceItem.m_incrementKey}, incrementAmount={sourceItem.m_incrementAmount}, " + $"price={shopPrice}."));
	}

	private void AddKvasturContractToShop(List<TradeItem> target, ShopCategory category)
	{
		if (target == null)
		{
			return;
		}
		GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("SakeysMyKvasturContract") : null);
		if ((Object)(object)val == (Object)null)
		{
			val = PrefabManager.Instance.GetPrefab("SakeysMyKvasturContract");
		}
		if (!((Object)(object)val == (Object)null))
		{
			ItemDrop component = val.GetComponent<ItemDrop>();
			if (!((Object)(object)component == (Object)null))
			{
				int defaultPrice = ((Plugin.ContractPrice != null) ? Mathf.Max(0, Plugin.ContractPrice.Value) : 1000);
				AddPricedShopItem(target, component, category, defaultPrice);
			}
		}
	}

	private void AddKvasturShopItems(List<TradeItem> target)
	{
		AddKvasturContractToShop(target, ShopCategory.Kvastur);
		string[] array = new string[37]
		{
			"Sap", "SurtlingCore", "MoltenCore", "Bloodbag", "Entrails", "MushroomMagecap", "AncientSeed", "Iron", "DvergrNeedle", "FlametalNew",
			"GemstoneRed", "GemstoneBlue", "GemstoneGreen", "BlackCore", "FrostCore", "Gold", "BarleyWine", "MeadBugRepellent", "MeadBzerker", "MeadEitrLingering",
			"MeadEitrMinor", "MeadFrostResist", "MeadHasty", "MeadHealthLingering", "MeadHealthMajor", "MeadHealthMedium", "MeadHealthMinor", "MeadLightfoot", "MeadPoisonResist", "MeadStaminaLingering",
			"MeadStaminaMedium", "MeadStaminaMinor", "MeadStrength", "MeadSwimmer", "MeadTamer", "MeadTasty", "MeadTrollPheromones"
		};
		foreach (string text in array)
		{
			GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(text) : null);
			if ((Object)(object)val == (Object)null)
			{
				val = PrefabManager.Instance.GetPrefab(text);
			}
			if (!((Object)(object)val == (Object)null))
			{
				ItemDrop component = val.GetComponent<ItemDrop>();
				if (!((Object)(object)component == (Object)null))
				{
					int kvasturDefaultPrice = GetKvasturDefaultPrice(text);
					AddPricedShopItem(target, component, ShopCategory.Kvastur, kvasturDefaultPrice);
				}
			}
		}
	}

	private int GetKvasturDefaultPrice(string prefabName)
	{
		switch (prefabName)
		{
		case "Sap":
			return 1;
		case "SurtlingCore":
			return 10;
		case "MoltenCore":
			return 20;
		case "Bloodbag":
			return 10;
		case "Entrails":
			return 10;
		case "MushroomMagecap":
			return 10;
		case "AncientSeed":
			return 20;
		case "Iron":
			return 10;
		case "DvergrNeedle":
			return 500;
		case "FlametalNew":
			return 150;
		case "GemstoneBlue":
		case "GemstoneRed":
		case "GemstoneGreen":
			return 200;
		case "BlackCore":
			return 600;
		case "FrostCore":
			return 1000;
		case "Gold":
			return 1000;
		default:
			return 10;
		}
	}

	private void AddPricedShopItem(List<TradeItem> target, ItemDrop prefab, ShopCategory category, int defaultPrice)
	{
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: 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_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Expected O, but got Unknown
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: 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)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Expected O, but got Unknown
		if (target == null || (Object)(object)prefab == (Object)null)
		{
			return;
		}
		foreach (TradeItem item in target)
		{
			if (item != null && (Object)(object)item.m_prefab == (Object)(object)prefab)
			{
				return;
			}
		}
		string prefabName = ((Object)((Component)prefab).gameObject).name.Replace("(Clone)", "").Trim();
		int shopPrice = GetShopPrice(category, prefabName, defaultPrice);
		string name = string.Empty;
		string tooltip = string.Empty;
		if (prefab.m_itemData != null && prefab.m_itemData.m_shared != null)
		{
			name = prefab.m_itemData.m_shared.m_name ?? string.Empty;
			tooltip = prefab.m_itemData.m_shared.m_description ?? string.Empty;
		}
		target.Add(new TradeItem
		{
			m_prefab = prefab,
			m_stack = 1,
			m_price = Mathf.Max(0, shopPrice),
			m_requiredGlobalKey = string.Empty,
			m_levelUpEffect = false,
			m_buyPlayerEffects = new EffectList(),
			m_icon = null,
			m_name = name,
			m_tooltip = tooltip,
			m_buyKey = string.Empty,
			m_incrementKey = string.Empty,
			m_incrementAmount = 0
		});
	}

	private int GetShopPrice(ShopCategory category, string prefabName, int defaultPrice)
	{
		return KvasturPriceBridge.GetPrice(category.ToString(), prefabName, defaultPrice);
	}

	private string GetShopDisplayName(ShopCategory category)
	{
		return category switch
		{
			ShopCategory.BlackForest => "$SakeysMyKvastur_CommandForest", 
			ShopCategory.Meadows => "$SakeysMyKvastur_CommandMeadows", 
			ShopCategory.Swamp => "$SakeysMyKvastur_CommandSwamp", 
			_ => "$SakeysMyKvastur_CommandKvastur", 
		};
	}

	private static void CopyTraderEffects(Trader source, Trader target)
	{
		if (!((Object)(object)source == (Object)null) && !((Object)(object)target == (Object)null))
		{
			target.m_randomTalkFX = source.m_randomTalkFX;
			target.m_randomGreetFX = source.m_randomGreetFX;
			target.m_randomGoodbyeFX = source.m_randomGoodbyeFX;
			target.m_randomStartTradeFX = source.m_randomStartTradeFX;
			target.m_randomBuyFX = source.m_randomBuyFX;
			target.m_randomSellFX = source.m_randomSellFX;
		}
	}

	private Trader FindBogWitchTrader()
	{
		Trader[] array = Object.FindObjectsOfType<Trader>();
		foreach (Trader val in array)
		{
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)trader) && string.Equals(((Object)((Component)val).gameObject).name.Replace("(Clone)", "").Trim(), "BogWitch", StringComparison.OrdinalIgnoreCase))
			{
				return val;
			}
		}
		try
		{
			GameObject val2 = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("BogWitch") : null);
			if ((Object)(object)val2 != (Object)null)
			{
				Trader component = val2.GetComponent<Trader>();
				if ((Object)(object)component != (Object)null)
				{
					return component;
				}
			}
		}
		catch (Exception ex)
		{
			Logger.LogDebug((object)("Failed to read Bog Witch prefab trader: " + ex.Message));
		}
		try
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab("BogWitch");
			Trader val3 = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Trader>() : null);
			if ((Object)(object)val3 != (Object)null)
			{
				return val3;
			}
		}
		catch (Exception ex2)
		{
			Logger.LogDebug((object)("Failed to read Bog Witch registered prefab trader: " + ex2.Message));
		}
		return null;
	}
}
[HarmonyPatch(typeof(Trader), "Start")]
public static class BogWitchTraderPatch
{
	[HarmonyPostfix]
	private static void Postfix(Trader __instance)
	{
		//IL_0179: 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_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Expected O, but got Unknown
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ed: 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_0204: Expected O, but got Unknown
		if ((Object)(object)__instance == (Object)null || __instance.m_items == null || !string.Equals((((Object)((Component)__instance).gameObject).name ?? "").Replace("(Clone)", "").Trim(), "BogWitch", StringComparison.OrdinalIgnoreCase))
		{
			return;
		}
		GameObject val = ObjectDB.instance.GetItemPrefab("SakeysMyKvasturContract");
		if ((Object)(object)val == (Object)null)
		{
			val = PrefabManager.Instance.GetPrefab("SakeysMyKvasturContract");
		}
		if ((Object)(object)val == (Object)null)
		{
			Logger.LogWarning((object)"Kvastur contract prefab not ready at Bog Witch Trader.Start.");
			return;
		}
		ItemDrop component = val.GetComponent<ItemDrop>();
		if ((Object)(object)component == (Object)null)
		{
			return;
		}
		if (component.m_itemData != null && component.m_itemData.m_shared != null)
		{
			component.m_itemData.m_shared.m_name = "$SakeysMyKvastur_Name";
			component.m_itemData.m_shared.m_description = "$SakeysMyKvastur_Desc";
		}
		foreach (TradeItem item in __instance.m_items)
		{
			if (item != null && (Object)(object)item.m_prefab == (Object)(object)component)
			{
				return;
			}
		}
		string name = string.Empty;
		string tooltip = string.Empty;
		if (component.m_itemData != null && component.m_itemData.m_shared != null)
		{
			name = component.m_itemData.m_shared.m_name ?? string.Empty;
			tooltip = component.m_itemData.m_shared.m_description ?? string.Empty;
		}
		__instance.m_items.Add(new TradeItem
		{
			m_prefab = component,
			m_price = ((Plugin.ContractPrice != null) ? Mathf.Max(0, Plugin.ContractPrice.Value) : 1000),
			m_stack = 1,
			m_requiredGlobalKey = string.Empty,
			m_levelUpEffect = false,
			m_buyPlayerEffects = new EffectList(),
			m_icon = null,
			m_name = name,
			m_tooltip = tooltip,
			m_buyKey = string.Empty,
			m_incrementKey = string.Empty,
			m_incrementAmount = 0
		});
		Logger.LogInfo((object)"Added Kvastur contract to Bog Witch.");
	}
}
[HarmonyPatch(typeof(Player), "OnSpawned")]
public static class PlayerSpawnPatch
{
	[HarmonyPostfix]
	private static void Postfix(Player __instance)
	{
		if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && (Object)(object)((Component)__instance).GetComponent<KvasturInputController>() == (Object)null)
		{
			((Component)__instance).gameObject.AddComponent<KvasturInputController>();
		}
	}
}
public static class KvasturCommandMenu
{
	public enum ShopMode
	{
		Follow,
		Retrieve,
		Rename,
		BlackForest,
		Meadows,
		Swamp,
		Kvastur
	}

	private static readonly List<ShopMode> CurrentModes = new List<ShopMode>();

	public static int SelectedIndex { get; private set; } = -1;

	public static void RebuildModes()
	{
		CurrentModes.Clear();
		CurrentModes.Add(ShopMode.Follow);
		CurrentModes.Add(ShopMode.Retrieve);
		CurrentModes.Add(ShopMode.Rename);
		if (Plugin.EnableBlackForestShop != null && Plugin.EnableBlackForestShop.Value)
		{
			CurrentModes.Add(ShopMode.BlackForest);
		}
		if (Plugin.EnableMeadowsShop != null && Plugin.EnableMeadowsShop.Value)
		{
			CurrentModes.Add(ShopMode.Meadows);
		}
		if (Plugin.EnableSwampShop != null && Plugin.EnableSwampShop.Value)
		{
			CurrentModes.Add(ShopMode.Swamp);
		}
		CurrentModes.Add(ShopMode.Kvastur);
		if (SelectedIndex >= CurrentModes.Count)
		{
			SelectedIndex = 0;
		}
	}

	public static void Cycle()
	{
		RebuildModes();
		SelectedIndex = (SelectedIndex + 1) % CurrentModes.Count;
		ShowSelectedMessage();
	}

	public static void Reset()
	{
		SelectedIndex = -1;
	}

	private static void ShowSelectedMessage()
	{
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return;
		}
		RebuildModes();
		if (CurrentModes.Count == 0)
		{
			return;
		}
		string text = CurrentModes[SelectedIndex] switch
		{
			ShopMode.Follow => "$SakeysMyKvastur_CommandFollow", 
			ShopMode.Retrieve => "$SakeysMyKvastur_CommandRetrieve", 
			ShopMode.Rename => "$SakeysMyKvastur_CommandRename", 
			ShopMode.BlackForest => "$SakeysMyKvastur_CommandForest", 
			ShopMode.Meadows => "$SakeysMyKvastur_CommandMeadows", 
			ShopMode.Swamp => "$SakeysMyKvastur_CommandSwamp", 
			_ => "$SakeysMyKvastur_CommandKvastur", 
		};
		string text2 = text;
		try
		{
			if (LocalizationManager.Instance != null)
			{
				text2 = LocalizationManager.Instance.GetLocalization().TryTranslate(text);
			}
		}
		catch
		{
		}
		((Character)localPlayer).Message((MessageType)2, text2, 0, (Sprite)null, false);
	}

	public static void ExecuteFollow(KvasturCompanion companion, Player player)
	{
		if ((Object)(object)companion == (Object)null || (Object)(object)player == (Object)null)
		{
			return;
		}
		KvasturInteractable component = ((Component)companion).GetComponent<KvasturInteractable>();
		if (!((Object)(object)component == (Object)null))
		{
			if (companion.IsFollowing())
			{
				component.DoStay(player);
			}
			else
			{
				component.DoFollow(player);
			}
		}
	}

	public static void ExecuteRetrieve(KvasturCompanion companion)
	{
		if (!((Object)(object)companion == (Object)null))
		{
			KvasturInteractable component = ((Component)companion).GetComponent<KvasturInteractable>();
			if (!((Object)(object)component == (Object)null))
			{
				component.DoRetrieve();
			}
		}
	}

	public static void ExecuteRename(KvasturCompanion companion)
	{
		if (!((Object)(object)companion == (Object)null))
		{
			KvasturInteractable component = ((Component)companion).GetComponent<KvasturInteractable>();
			if (!((Object)(object)component == (Object)null))
			{
				component.OpenRename();
			}
		}
	}

	public static void ExecuteShop(KvasturCompanion companion, ShopMode mode)
	{
		if (!((Object)(object)companion == (Object)null))
		{
			KvasturInteractable component = ((Component)companion).GetComponent<KvasturInteractable>();
			if (!((Object)(object)component == (Object)null))
			{
				component.OpenTrade(mode);
			}
		}
	}

	public static void Execute(KvasturCompanion companion, Player player)
	{
		if (!((Object)(object)companion == (Object)null) && !((Object)(object)player == (Object)null))
		{
			RebuildModes();
			if (SelectedIndex < 0 || SelectedIndex >= CurrentModes.Count)
			{
				SelectedIndex = 0;
			}
			switch (CurrentModes[SelectedIndex])
			{
			case ShopMode.Follow:
				ExecuteFollow(companion, player);
				break;
			case ShopMode.Retrieve:
				ExecuteRetrieve(companion);
				break;
			case ShopMode.Rename:
				ExecuteRename(companion);
				break;
			default:
				ExecuteShop(companion, CurrentModes[SelectedIndex]);
				break;
			}
		}
	}
}
public class KvasturInputController : MonoBehaviour
{
	private static int suppressInteractFrame = -1;

	public static bool SuppressInteractThisFrame()
	{
		if (suppressInteractFrame == Time.frameCount)
		{
			suppressInteractFrame = -1;
			return true;
		}
		return false;
	}

	private void Update()
	{
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || Console.IsVisible() || Menu.IsVisible())
		{
			return;
		}
		if (ZInput.GetButton("JoyLBumper") && ZInput.GetButtonDown("JoyUse"))
		{
			Character hoverCreature = localPlayer.GetHoverCreature();
			if ((Object)(object)hoverCreature != (Object)null)
			{
				KvasturCompanion component = ((Component)hoverCreature).GetComponent<KvasturCompanion>();
				if ((Object)(object)component != (Object)null && component.IsOwner(localPlayer))
				{
					KvasturCommandMenu.Cycle();
					suppressInteractFrame = Time.frameCount;
				}
			}
		}
		if (WasPressed(Plugin.CommandKey.Value))
		{
			if ((Object)(object)KvasturCompanion.FindOwned(localPlayer.GetPlayerID()) != (Object)null)
			{
				KvasturCommandMenu.Cycle();
			}
			else
			{
				KvasturCommandMenu.Reset();
			}
		}
	}

	private static bool WasPressed(KeyboardShortcut shortcut)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0)
		{
			return false;
		}
		if (!Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey))
		{
			return false;
		}
		foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
		{
			if (!Input.GetKey(modifier))
			{
				return false;
			}
		}
		return true;
	}
}
[HarmonyPatch]
public static class KvasturStoreGuiPatch
{
	private static MethodBase TargetMethod()
	{
		return AccessTools.Method(typeof(StoreGui), "Hide", (Type[])null, (Type[])null);
	}

	private static bool Prepare()
	{
		return TargetMethod() != null;
	}

	[HarmonyPostfix]
	private static void Postfix(StoreGui __instance)
	{
		if ((Object)(object)__instance == (Object)null)
		{
			return;
		}
		Trader value = Traverse.Create((object)__instance).Field("m_trader").GetValue<Trader>();
		if ((Object)(object)value == (Object)null)
		{
			return;
		}
		KvasturCompanion component = ((Component)value).GetComponent<KvasturCompanion>();
		if ((Object)(object)component != (Object)null)
		{
			component.EndTrading();
			Trader component2 = ((Component)value).GetComponent<Trader>();
			if ((Object)(object)component2 != (Object)null)
			{
				((Behaviour)component2).enabled = false;
			}
		}
	}

	public static bool IsKvasturStoreOpen(KvasturCompanion companion)
	{
		if ((Object)(object)companion == (Object)null || (Object)(object)StoreGui.instance == (Object)null)
		{
			return false;
		}
		Trader value = Traverse.Create((object)StoreGui.instance).Field("m_trader").GetValue<Trader>();
		if ((Object)(object)value != (Object)null)
		{
			return (Object)(object)((Component)value).GetComponent<KvasturCompanion>() == (Object)(object)companion;
		}
		return false;
	}
}
[HarmonyPatch(typeof(StoreGui), "BuySelectedItem")]
public static class KvasturContractPurchaseNamePatch
{
	[HarmonyPrefix]
	private static void Prefix(StoreGui __instance)
	{
		if ((Object)(object)__instance == (Object)null)
		{
			return;
		}
		try
		{
			Trader value = Traverse.Create((object)__instance).Field("m_trader").GetValue<Trader>();
			if ((Object)(object)value == (Object)null || (Object)(object)((Component)value).GetComponent<KvasturCompanion>() != (Object)null)
			{
				return;
			}
			TradeItem value2 = Traverse.Create((object)__instance).Field("m_selectedItem").GetValue<TradeItem>();
			if (value2 != null && !((Object)(object)value2.m_prefab == (Object)null) && ((Object)((Component)value2.m_prefab).gameObject).name.Replace("(Clone)", "").Trim().Equals("SakeysMyKvasturContract", StringComparison.OrdinalIgnoreCase))
			{
				ItemData itemData = value2.m_prefab.m_itemData;
				if (itemData != null && itemData.m_shared != null)
				{
					itemData.m_shared.m_name = "$SakeysMyKvastur_Name";
					itemData.m_shared.m_description = "$SakeysMyKvastur_Desc";
					itemData.m_dropPrefab = ((Component)value2.m_prefab).gameObject;
				}
			}
		}
		catch
		{
		}
	}
}
internal sealed class ConfigurationManagerAttributes
{
	public bool? Browsable;

	public bool? HideDefaultButton;

	public bool? IsAdvanced;

	public int? Order;

	public string DispName;

	public string Description;

	public string Category;

	public bool? ReadOnly;
}
internal static class KvasturPriceBridge
{
	public static int GetPrice(string category, string prefabName, int defaultPrice)
	{
		return category switch
		{
			"BlackForest" => KvasturHaldorPrices.Get(prefabName, defaultPrice), 
			"Meadows" => KvasturHildirPrices.Get(prefabName, defaultPrice), 
			"Swamp" => KvasturBogWitchPrices.Get(prefabName, defaultPrice), 
			_ => KvasturShopPrices.Get(prefabName, defaultPrice), 
		};
	}
}
internal abstract class KvasturPricePluginBase : BaseUnityPlugin
{
	protected readonly Dictionary<string, ConfigEntry<int>> Prices = new Dictionary<string, ConfigEntry<int>>(StringComparer.OrdinalIgnoreCase);

	protected ConfigEntry<int> BindPrice(string section, string prefabName, int defaultPrice, string description)
	{
		if (Prices.TryGetValue(prefabName, out var value))
		{
			return value;
		}
		ConfigEntry<int> val = ((BaseUnityPlugin)this).Config.Bind<int>(section, prefabName + "Price", defaultPrice, description);
		Prices[prefabName] = val;
		return val;
	}

	protected int LegacyDefault(string section, string prefabName, int fallback)
	{
		return fallback;
	}

	protected static string CleanPrefabName(GameObject prefab)
	{
		if (!((Object)(object)prefab == (Object)null))
		{
			return ((Object)prefab).name.Replace("(Clone)", "").Trim();
		}
		return string.Empty;
	}
}
[BepInPlugin("com.sakey.my.kvastur.haldorprices", "Sakey's My Kvastur - Haldor Prices", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
internal sealed class KvasturHaldorPrices : KvasturPricePluginBase
{
	private static readonly Dictionary<string, ConfigEntry<int>> Bound = new Dictionary<string, ConfigEntry<int>>(StringComparer.OrdinalIgnoreCase);

	private void Awake()
	{
		PrefabManager.OnVanillaPrefabsAvailable += BindPrices;
	}

	private void BindPrices()
	{
		BindTrader("Haldor", "Shop - Black Forest");
	}

	private void BindTrader(string traderPrefabName, string section)
	{
		GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(traderPrefabName) : null);
		if ((Object)(object)val == (Object)null)
		{
			val = PrefabManager.Instance.GetPrefab(traderPrefabName);
		}
		Trader val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Trader>() : null);
		if ((Object)(object)val2 == (Object)null || val2.m_items == null)
		{
			return;
		}
		foreach (TradeItem item in val2.m_items)
		{
			if (item != null && !((Object)(object)item.m_prefab == (Object)null))
			{
				string text = KvasturPricePluginBase.CleanPrefabName(((Component)item.m_prefab).gameObject);
				if (!Bound.ContainsKey(text))
				{
					Bound[text] = BindPrice(section, text, LegacyDefault(section, text, Mathf.Max(0, item.m_price)), "Haldor purchase price for one item.");
				}
			}
		}
		if (!Bound.ContainsKey("WiderPockets"))
		{
			Bound["WiderPockets"] = BindPrice(section, "WiderPockets", 1000, "Kvastur Black Forest shop price for Wider Pockets.");
		}
		if (!Bound.ContainsKey("DeeperPockets"))
		{
			Bound["DeeperPockets"] = BindPrice(section, "DeeperPockets", 2000, "Kvastur Black Forest shop price for Deeper Pockets.");
		}
	}

	public static int Get(string prefabName, int fallback)
	{
		if (!Bound.TryGetValue(prefabName, out var value))
		{
			return fallback;
		}
		return value.Value;
	}
}
[BepInPlugin("com.sakey.my.kvastur.hildirprices", "Sakey's My Kvastur - Hildir Prices", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
internal sealed class KvasturHildirPrices : KvasturPricePluginBase
{
	private static readonly Dictionary<string, ConfigEntry<int>> Bound = new Dictionary<string, ConfigEntry<int>>(StringComparer.OrdinalIgnoreCase);

	private void Awake()
	{
		PrefabManager.OnVanillaPrefabsAvailable += BindPrices;
	}

	private void BindPrices()
	{
		GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("Hildir") : null);
		if ((Object)(object)val == (Object)null)
		{
			val = PrefabManager.Instance.GetPrefab("Hildir");
		}
		Trader val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Trader>() : null);
		if ((Object)(object)val2 == (Object)null || val2.m_items == null)
		{
			return;
		}
		foreach (TradeItem item in val2.m_items)
		{
			if (item != null && !((Object)(object)item.m_prefab == (Object)null))
			{
				string text = KvasturPricePluginBase.CleanPrefabName(((Component)item.m_prefab).gameObject);
				if (!Bound.ContainsKey(text))
				{
					Bound[text] = BindPrice("Shop - Meadows", text, LegacyDefault("Shop - Meadows", text, Mathf.Max(0, item.m_price)), "Hildir purchase price for one item.");
				}
			}
		}
	}

	public static int Get(string prefabName, int fallback)
	{
		if (!Bound.TryGetValue(prefabName, out var value))
		{
			return fallback;
		}
		return value.Value;
	}
}
[BepInPlugin("com.sakey.my.kvastur.bogwitchprices", "Sakey's My Kvastur - Bog Witch Prices", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
internal sealed class KvasturBogWitchPrices : KvasturPricePluginBase
{
	private static readonly Dictionary<string, ConfigEntry<int>> Bound = new Dictionary<string, ConfigEntry<int>>(StringComparer.OrdinalIgnoreCase);

	private void Awake()
	{
		PrefabManager.OnVanillaPrefabsAvailable += BindPrices;
	}

	private void BindPrices()
	{
		GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("BogWitch") : null);
		if ((Object)(object)val == (Object)null)
		{
			val = PrefabManager.Instance.GetPrefab("BogWitch");
		}
		Trader val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Trader>() : null);
		if ((Object)(object)val2 != (Object)null && val2.m_items != null)
		{
			foreach (TradeItem item in val2.m_items)
			{
				if (item != null && !((Object)(object)item.m_prefab == (Object)null))
				{
					string text = KvasturPricePluginBase.CleanPrefabName(((Component)item.m_prefab).gameObject);
					if (!Bound.ContainsKey(text))
					{
						Bound[text] = BindPrice("Shop - Swamp", text, LegacyDefault("Shop - Swamp", text, Mathf.Max(0, item.m_price)), "Bog Witch purchase price for one item.");
					}
				}
			}
		}
		if (!Bound.ContainsKey("WiderPockets"))
		{
			Bound["WiderPockets"] = BindPrice("Shop - Swamp", "WiderPockets", 1, "Kvastur magic mail-order price for Wider Pockets.");
		}
		if (!Bound.ContainsKey("DeeperPockets"))
		{
			Bound["DeeperPockets"] = BindPrice("Shop - Swamp", "DeeperPockets", 1, "Kvastur magic mail-order price for Deeper Pockets.");
		}
	}

	public static int Get(string prefabName, int fallback)
	{
		if (!Bound.TryGetValue(prefabName, out var value))
		{
			return fallback;
		}
		return value.Value;
	}
}
[BepInPlugin("com.sakey.my.kvastur.kvasturprices", "Sakey's My Kvastur - Kvastur Shop Prices", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
internal sealed class KvasturShopPrices : KvasturPricePluginBase
{
	private static readonly Dictionary<string, ConfigEntry<int>> Bound = new Dictionary<string, ConfigEntry<int>>(StringComparer.OrdinalIgnoreCase);

	private static readonly string[] Prefabs = new string[37]
	{
		"Sap", "SurtlingCore", "MoltenCore", "Bloodbag", "Entrails", "MushroomMagecap", "AncientSeed", "Iron", "DvergrNeedle", "FlametalNew",
		"GemstoneRed", "GemstoneBlue", "GemstoneGreen", "BlackCore", "FrostCore", "Gold", "BarleyWine", "MeadBugRepellent", "MeadBzerker", "MeadEitrLingering",
		"MeadEitrMinor", "MeadFrostResist", "MeadHasty", "MeadHealthLingering", "MeadHealthMajor", "MeadHealthMedium", "MeadHealthMinor", "MeadLightfoot", "MeadPoisonResist", "MeadStaminaLingering",
		"MeadStaminaMedium", "MeadStaminaMinor", "MeadStrength", "MeadSwimmer", "MeadTamer", "MeadTasty", "MeadTrollPheromones"
	};

	private void Awake()
	{
		string[] prefabs = Prefabs;
		foreach (string text in prefabs)
		{
			Bound[text] = BindPrice("Shop - Kvastur", text, LegacyDefault("Shop - Kvastur", text, GetDefault(text)), "Kvastur purchase price for one item.");
		}
	}

	private static int GetDefault(string prefabName)
	{
		switch (prefabName)
		{
		case "Sap":
			return 1;
		case "SurtlingCore":
			return 10;
		case "MoltenCore":
			return 20;
		case "Bloodbag":
			return 10;
		case "Entrails":
			return 10;
		case "MushroomMagecap":
			return 10;
		case "AncientSeed":
			return 20;
		case "Iron":
			return 10;
		case "DvergrNeedle":
			return 500;
		case "FlametalNew":
			return 150;
		case "GemstoneBlue":
		case "GemstoneRed":
		case "GemstoneGreen":
			return 200;
		case "BlackCore":
			return 600;
		case "FrostCore":
			return 1000;
		case "Gold":
			return 1000;
		default:
			return 10;
		}
	}

	public static int Get(string prefabName, int fallback)
	{
		if (!Bound.TryGetValue(prefabName, out var value))
		{
			return fallback;
		}
		return value.Value;
	}
}