Decompiled source of Xaltorez Valheim Modpack v1.0.1

plugins/aedenthorn-HuginQuests/HuginQuestFramework.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using QuestFramework;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+0d02688ca05f415d9319b5e85b2635fd3fbeffc8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace HuginQuestFramework;

[BepInPlugin("aedenthorn.HuginQuestFramework", "Hugin Quest Framework", "0.4.2")]
public class BepInExPlugin : BaseUnityPlugin
{
	public enum QuestType
	{
		Fetch,
		Kill,
		Build
	}

	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	public static class ZNetScene_Awake_Patch
	{
		public static void Postfix(StoreGui __instance)
		{
			if (modEnabled.Value)
			{
				GetQuests();
				lastCheckTime = ZNet.instance.GetTimeSeconds();
			}
		}
	}

	[HarmonyPatch(typeof(Character), "RPC_Damage")]
	public static class Character_RPC_Damage_Patch
	{
		public static void Postfix(Character __instance, HitData hit)
		{
			if (modEnabled.Value && !(__instance.GetHealth() > 0f) && !((Object)(object)hit.GetAttacker() != (Object)(object)Player.m_localPlayer))
			{
				AdvanceKillQuests(__instance);
			}
		}
	}

	[HarmonyPatch(typeof(Player), "TryPlacePiece")]
	public static class Player_PlacePiece_Patch
	{
		public static void Postfix(Piece piece, bool __result)
		{
			if (modEnabled.Value && __result)
			{
				AdvanceBuildQuests(piece);
			}
		}
	}

	[HarmonyPatch(typeof(Inventory), "Changed")]
	public static class Inventory_Changed_Patch
	{
		public static void Postfix(Inventory __instance)
		{
			if (modEnabled.Value && Object.op_Implicit((Object)(object)Player.m_localPlayer) && __instance == ((Humanoid)Player.m_localPlayer).GetInventory())
			{
				AdjustFetchQuests();
			}
		}
	}

	[HarmonyPatch(typeof(Menu), "IsVisible")]
	public static class Menu_IsVisible_Patch
	{
		public static bool Prefix(Menu __instance, ref bool __result)
		{
			if (modEnabled.Value)
			{
				Transform questDialogueTransform = BepInExPlugin.questDialogueTransform;
				if (questDialogueTransform != null && ((Component)questDialogueTransform).gameObject.activeSelf)
				{
					__result = true;
					return false;
				}
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Raven), "Say")]
	public static class Raven_Say_Patch
	{
		public static void Prefix(ref string topic, ref string text, bool showName, bool longTimeout, bool large)
		{
			if (!(!modEnabled.Value || showName || longTimeout || large))
			{
				if (finishedQuest != null)
				{
					topic = haveRewardDialogue.Value;
					text = "";
				}
				else if (nextQuest != null)
				{
					topic = haveQuestDialogue.Value;
					text = "";
				}
			}
		}
	}

	[HarmonyPatch(typeof(Raven), "FlyAway")]
	public static class Raven_FlyAway_Patch
	{
		public static bool Prefix()
		{
			return !modEnabled.Value || (Object)(object)questDialogueTransform == (Object)null || !((Component)questDialogueTransform).gameObject.activeSelf;
		}
	}

	[HarmonyPatch(typeof(Raven), "GetBestText")]
	public static class Raven_GetBestText_Patch
	{
		public static bool Prefix(Raven __instance, ref RavenText __result)
		{
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			if (!modEnabled.Value || __instance.m_isMunin || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return true;
			}
			if (finishedQuest == null)
			{
				foreach (QuestData value in QuestFrameworkAPI.GetCurrentQuests().Values)
				{
					if (value.ID.StartsWith(typeof(BepInExPlugin).Namespace) && value.currentStage == "StageTwo")
					{
						finishedQuest = value;
						break;
					}
				}
			}
			if (finishedQuest != null || nextQuest != null)
			{
				__result = new RavenText();
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Raven), "Talk")]
	public static class Raven_Talk_Patch
	{
		public static bool Prefix(Raven __instance, ref RavenText ___m_currentText, ref bool ___m_hasTalked)
		{
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Expected O, but got Unknown
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Expected O, but got Unknown
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Expected O, but got Unknown
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Expected O, but got Unknown
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_036e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0404: Unknown result type (might be due to invalid IL or missing references)
			//IL_040d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0412: Unknown result type (might be due to invalid IL or missing references)
			if (!modEnabled.Value || ___m_currentText == null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return true;
			}
			if (finishedQuest == null)
			{
				foreach (QuestData value in QuestFrameworkAPI.GetCurrentQuests().Values)
				{
					if (value.ID.StartsWith(typeof(BepInExPlugin).Namespace) && value.currentStage == "StageTwo")
					{
						Dbgl("Setting finished quest to " + value.ID);
						finishedQuest = value;
						break;
					}
				}
			}
			if (finishedQuest != null)
			{
				if (finishedQuest.currentStage == "StageTwo")
				{
					FulfillQuest(finishedQuest);
					AccessTools.Method(typeof(Raven), "Say", (Type[])null, (Type[])null).Invoke(__instance, new object[5] { currentText.m_topic, "", false, true, true });
					___m_hasTalked = true;
					return false;
				}
				Dbgl("Finished quest isn't finished");
				finishedQuest = null;
			}
			if (nextQuest != null)
			{
				if ((Object)(object)questDialogueTransform == (Object)null)
				{
					Dbgl("Creating Quest Accept Window");
					questDialogueTransform = Object.Instantiate<Transform>(Menu.instance.m_logoutDialog, Menu.instance.m_logoutDialog.parent.parent);
					((Object)((Component)questDialogueTransform).gameObject).name = "QuestAcceptWindow";
					RectTransform component = ((Component)questDialogueTransform.Find("dialog")).GetComponent<RectTransform>();
					component.anchoredPosition -= new Vector2(0f, 200f);
					Transform val = questDialogueTransform.Find("dialog/Button_yes");
					((Object)val).name = "Button_Decline";
					RectTransform component2 = ((Component)val).GetComponent<RectTransform>();
					component2.anchoredPosition -= new Vector2(0f, 32f);
					((Component)val).GetComponentInChildren<TMP_Text>().text = declineButtonText.Value;
					((Component)val).GetComponent<Button>().onClick = new ButtonClickedEvent();
					((UnityEvent)((Component)val).GetComponent<Button>().onClick).AddListener(new UnityAction(DeclineQuest));
					Transform val2 = questDialogueTransform.Find("dialog/Button_no");
					((Object)val2).name = "Button_Accept";
					RectTransform component3 = ((Component)val2).GetComponent<RectTransform>();
					component3.anchoredPosition -= new Vector2(0f, 32f);
					((Component)val2).GetComponentInChildren<TMP_Text>().text = acceptButtonText.Value;
					((Component)val2).GetComponent<Button>().onClick = new ButtonClickedEvent();
					((UnityEvent)((Component)val2).GetComponent<Button>().onClick).AddListener(new UnityAction(AcceptQuest));
					questDialogueTitleTransform = questDialogueTransform.Find("dialog/Quit");
					((Object)questDialogueTitleTransform).name = "Title";
					RectTransform component4 = ((Component)questDialogueTitleTransform).GetComponent<RectTransform>();
					component4.anchoredPosition += new Vector2(0f, 20f);
					questDialogueSubtitleTransform = Object.Instantiate<Transform>(questDialogueTransform.Find("dialog/Title"), questDialogueTransform.Find("dialog"));
					((Object)questDialogueSubtitleTransform).name = "Subtitle";
					((Graphic)((Component)questDialogueSubtitleTransform).GetComponent<TMP_Text>()).color = Color.white;
					((Component)questDialogueSubtitleTransform).GetComponent<TMP_Text>().fontSize = 16f;
					RectTransform component5 = ((Component)questDialogueSubtitleTransform).GetComponent<RectTransform>();
					Vector2 anchoredPosition = component5.anchoredPosition;
					Rect rect = ((Component)questDialogueTitleTransform).GetComponent<RectTransform>().rect;
					component5.anchoredPosition = anchoredPosition - new Vector2(0f, ((Rect)(ref rect)).height);
				}
				((Component)questDialogueTitleTransform).GetComponent<TMP_Text>().text = nextQuest.name;
				((Component)questDialogueSubtitleTransform).GetComponent<TMP_Text>().text = nextQuest.questStages["StageOne"].name + "\n" + nextQuest.questStages["StageOne"].desc;
				Dbgl("Showing Quest Accept Window");
				((Component)questDialogueTransform).gameObject.SetActive(true);
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Raven), "Update")]
	public static class Raven_Update_Patch
	{
		public static void Prefix(Raven __instance, ref bool ___m_hasTalked, ref RavenText ___m_currentText)
		{
			if (!modEnabled.Value || __instance.m_isMunin || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			if (respondedToQuest)
			{
				Dbgl("Responded to quest");
				AccessTools.Field(typeof(GameCamera), "m_mouseCapture").SetValue(GameCamera.instance, true);
				Cursor.lockState = (CursorLockMode)1;
				Cursor.visible = false;
				respondedToQuest = false;
				___m_hasTalked = true;
				AccessTools.Method(typeof(Raven), "Say", (Type[])null, (Type[])null).Invoke(__instance, new object[5] { currentText.m_topic, currentText.m_text, false, true, true });
				nextQuest = null;
			}
			else if (nextQuest == null && ZNet.instance.GetTimeSeconds() > (double)questCheckInterval.Value + lastCheckTime)
			{
				Dbgl("Checking for quest");
				lastCheckTime = ZNet.instance.GetTimeSeconds();
				if (!QuestFrameworkAPI.GetCurrentQuests().Keys.ToList().Exists((string s) => s.StartsWith(typeof(BepInExPlugin).Namespace)) && Random.value < questChance.Value)
				{
					nextQuest = MakeRandomQuest();
				}
			}
		}
	}

	[HarmonyPatch(typeof(Terminal), "InputText")]
	public static class InputText_Patch
	{
		public static bool Prefix(Terminal __instance)
		{
			if (!modEnabled.Value)
			{
				return true;
			}
			string text = ((TMP_InputField)__instance.m_input).text;
			if (text.ToLower().Equals(typeof(BepInExPlugin).Namespace.ToLower() + " reset"))
			{
				((BaseUnityPlugin)context).Config.Reload();
				((BaseUnityPlugin)context).Config.Save();
				__instance.AddString(text);
				__instance.AddString(((BaseUnityPlugin)context).Info.Metadata.Name + " config reloaded");
				return false;
			}
			return true;
		}
	}

	public static readonly bool isDebug = true;

	public static ConfigEntry<string> modKey;

	public static ConfigEntry<bool> modEnabled;

	public static ConfigEntry<int> nexusID;

	public static ConfigEntry<int> maxQuests;

	public static ConfigEntry<float> questCheckInterval;

	public static ConfigEntry<float> questChance;

	public static ConfigEntry<float> randomFetchQuestWeight;

	public static ConfigEntry<float> randomKillQuestWeight;

	public static ConfigEntry<float> randomBuildQuestWeight;

	public static ConfigEntry<float> randomFetchRewardMult;

	public static ConfigEntry<float> randomKillRewardMult;

	public static ConfigEntry<float> randomBuildRewardMult;

	public static ConfigEntry<int> randomWorthlessItemValue;

	public static ConfigEntry<int> minAmount;

	public static ConfigEntry<int> maxAmount;

	public static ConfigEntry<int> maxReward;

	public static ConfigEntry<float> rewardFluctuation;

	public static ConfigEntry<bool> allowUnknownFetchMaterials;

	public static ConfigEntry<string> randomFetchQuestName;

	public static ConfigEntry<string> randomKillQuestName;

	public static ConfigEntry<string> randomBuildQuestName;

	public static ConfigEntry<string> randomFetchQuestObjectiveName;

	public static ConfigEntry<string> randomKillQuestObjectiveName;

	public static ConfigEntry<string> randomBuildQuestObjectiveName;

	public static ConfigEntry<string> randomQuestRewardText;

	public static ConfigEntry<string> randomQuestProgressText;

	public static ConfigEntry<string> questDeclinedDialogue;

	public static ConfigEntry<string> questAcceptedDialogue;

	public static ConfigEntry<string> noRoomDialogue;

	public static ConfigEntry<string> completedDialogue;

	public static ConfigEntry<string> haveRewardDialogue;

	public static ConfigEntry<string> haveQuestDialogue;

	public static ConfigEntry<string> declineButtonText;

	public static ConfigEntry<string> acceptButtonText;

	public static ConfigEntry<string> questNameString;

	public static ConfigEntry<string> questDescString;

	public static ConfigEntry<string> returnString;

	public static ConfigEntry<string> returnDescString;

	public static ConfigEntry<string> startString;

	public static ConfigEntry<string> completeString;

	public static ConfigEntry<string> killQuestString;

	public static ConfigEntry<string> fetchQuestString;

	public static BepInExPlugin context;

	public static double lastCheckTime = 0.0;

	public static RavenText currentText = new RavenText();

	public static bool showQuestAcceptWindow;

	public static bool respondedToQuest = false;

	public static QuestData nextQuest;

	public static QuestData finishedQuest;

	public static GUIStyle titleStyle;

	public static GUIStyle subTitleStyle;

	public static GUIStyle descStyle;

	public static float windowWidth = 400f;

	public static float windowHeight = 300f;

	public static int windowID = 1890175404;

	public static Transform questDialogueTransform;

	public static Transform questDialogueSubtitleTransform;

	public static Transform questDialogueTitleTransform;

	public static Dictionary<string, HuginQuestData> huginQuestDict = new Dictionary<string, HuginQuestData>();

	public static List<GameObject> possibleKillList = new List<GameObject>();

	public static List<GameObjectReward> possibleFetchList = new List<GameObjectReward>();

	public static List<GameObjectReward> possibleBuildList = new List<GameObjectReward>();

	public static void Dbgl(string str = "", bool pref = true)
	{
		if (isDebug)
		{
			Debug.Log((object)((pref ? (typeof(BepInExPlugin).Namespace + " ") : "") + str));
		}
	}

	public void Awake()
	{
		context = this;
		modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable this mod");
		nexusID = ((BaseUnityPlugin)this).Config.Bind<int>("General", "NexusID", 1588, "Nexus mod ID for updates");
		questCheckInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Options", "QuestCheckInterval", 3600f, "Number of game seconds between checking for a new quest (default every game hour).");
		questChance = ((BaseUnityPlugin)this).Config.Bind<float>("Options", "QuestChance", 0.1f, "Chance of a quest being offered on each interval.");
		maxQuests = ((BaseUnityPlugin)this).Config.Bind<int>("Options", "MaxQuests", 1, "Number of quests to allow at once.");
		allowUnknownFetchMaterials = ((BaseUnityPlugin)this).Config.Bind<bool>("Options", "AllowUnknownFetchMaterials", true, "All fetch quests for unknown materials.");
		randomFetchQuestWeight = ((BaseUnityPlugin)this).Config.Bind<float>("Random", "RandomFetchQuestWeight", 1f, "Chance of a random quest being a fetch quest.");
		randomKillQuestWeight = ((BaseUnityPlugin)this).Config.Bind<float>("Random", "RandomKillQuestWeight", 1f, "Chance of a random quest being a kill quest.");
		randomBuildQuestWeight = ((BaseUnityPlugin)this).Config.Bind<float>("Random", "RandomBuildQuestWeight", 1f, "Chance of a random quest being a build quest.");
		randomFetchRewardMult = ((BaseUnityPlugin)this).Config.Bind<float>("Random", "RandomFetchRewardMult", 3f, "Multiple of item cost as reward for random fetch quests.");
		randomKillRewardMult = ((BaseUnityPlugin)this).Config.Bind<float>("Random", "RandomKillRewardMult", 0.2f, "Multiple of creature max health as reward for random kill quests.");
		randomBuildRewardMult = ((BaseUnityPlugin)this).Config.Bind<float>("Random", "RandomBuildRewardMult", 5f, "Multiple of build ingredients cost as reward for random build quests.");
		randomWorthlessItemValue = ((BaseUnityPlugin)this).Config.Bind<int>("Random", "RandomWorthlessItemValue", 1, "Fetch value of items that have no specified value.");
		minAmount = ((BaseUnityPlugin)this).Config.Bind<int>("Options", "MinAmount", 3, "Minimum number of things in quests without specified amounts.");
		maxAmount = ((BaseUnityPlugin)this).Config.Bind<int>("Options", "MaxAmount", 10, "Maximum number of things in quest without specified amounts.");
		rewardFluctuation = ((BaseUnityPlugin)this).Config.Bind<float>("Options", "RewardFluctuation", 0.5f, "Reward can fluctuate by this much fraction.");
		randomFetchQuestName = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "RandomFetchQuestName", "{thing} Collector", "Name of random fetch quests.");
		randomKillQuestName = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "RandomKillQuestName", "{thing} Killer", "Name of random kill quests.");
		randomBuildQuestName = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "RandomBuildQuestName", "{thing} Builder", "Name of random build quests.");
		randomFetchQuestObjectiveName = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "RandomFetchQuestObjectiveName", "Fetch {amount} {thing}", "Objective name of random fetch quests.");
		randomKillQuestObjectiveName = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "RandomKillQuestObjectiveName", "Kill {amount} {thing}", "Objective name of random kill quests.");
		randomBuildQuestObjectiveName = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "RandomBuildQuestObjectiveName", "Build {amount} {thing}", "Objective name of random build quests.");
		randomQuestProgressText = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "RandomQuestProgressText", "Progress {progress}/{amount}", "Progress text of random quests.");
		randomQuestRewardText = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "RandomQuestRewardText", "Hugin will reward you {rewardAmount} {rewardName}", "Progress text of random quests.");
		questAcceptedDialogue = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "QuestAcceptedDialogue", "May you be victorious in your endeavor...", "Hugin's dialogue when accepting a quest.");
		questDeclinedDialogue = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "QuestDeclinedDialogue", "Perhaps next time...", "Hugin's dialogue when declining a quest.");
		noRoomDialogue = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "NoRoomDialogue", "You have no room for your reward...", "Hugin's dialogue if you have no room for your reward.");
		completedDialogue = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "CompletedDialogue", "Well done... until next we meet!", "Hugin's dialogue after completing quest.");
		haveRewardDialogue = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "HaveRewardDialogue", "Come take your reward...", "Hugin's dialogue when there's a completed quest.");
		haveQuestDialogue = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "HaveQuestDialogue", "I have a quest for you...", "Hugin's dialogue when there's a quest.");
		declineButtonText = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "DeclineButtonText", "Decline", "Text for button to decline quest.");
		acceptButtonText = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "AcceptButtonText", "Accept", "Text for button to accept quest.");
		questNameString = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "QuestString", "Hugin's Request", "Main quest header string.");
		returnString = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "ReturnString", "Talk to Hugin.", "Return objective.");
		returnDescString = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "ReturnDescString", "Talk to the raven for your reward.", "Return objective description.");
		startString = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "StartString", "Quest Started.", "HUD message on quest start.");
		completeString = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "CompleteString", "Quest Completed.", "HUD message on quest completion.");
		killQuestString = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "KillQuestString", "Kill Quest", "Kill quest string.");
		fetchQuestString = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "FetchQuestString", "Fetch Quest", "Fetch quest string.");
		if (modEnabled.Value)
		{
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
		}
	}

	public static void GetQuests()
	{
		huginQuestDict.Clear();
		if (Directory.Exists(Path.Combine(AedenthornUtils.GetAssetPath((object)context, true), "Quests")) && Directory.GetFiles(Path.Combine(AedenthornUtils.GetAssetPath((object)context, true), "Quests")).Length != 0)
		{
			List<HuginQuestData> list = new List<HuginQuestData>();
			string[] files = Directory.GetFiles(Path.Combine(AedenthornUtils.GetAssetPath((object)context, true), "Quests"));
			foreach (string text in files)
			{
				try
				{
					list.Add(JsonUtility.FromJson<HuginQuestData>(File.ReadAllText(text)));
				}
				catch (Exception arg)
				{
					try
					{
						string[] array = File.ReadAllLines(text);
						string[] array2 = array;
						foreach (string text2 in array2)
						{
							list.Add(JsonUtility.FromJson<HuginQuestData>(text2));
						}
					}
					catch
					{
						Dbgl($"Error reading quests from {text}:\n\n{arg}");
					}
				}
			}
			if (list.Count > 0)
			{
				for (int k = 0; k < list.Count; k++)
				{
					HuginQuestData huginQuestData = list[k];
					huginQuestData.ID = typeof(BepInExPlugin).Namespace + "_" + huginQuestData.ID;
					if (huginQuestData.amount <= 0)
					{
						huginQuestData.amount = Random.Range(minAmount.Value, maxAmount.Value);
						huginQuestData.rewardAmount *= huginQuestData.amount;
					}
					huginQuestData.rewardAmount = Mathf.RoundToInt((float)huginQuestData.rewardAmount * (1f + (rewardFluctuation.Value * 2f * Random.value - rewardFluctuation.Value)));
					if (huginQuestData.type == QuestType.Fetch)
					{
						try
						{
							huginQuestData.thing = ObjectDB.instance.GetItemPrefab(huginQuestData.thing).GetComponent<ItemDrop>().m_itemData.m_shared.m_name;
						}
						catch
						{
						}
					}
					else if (huginQuestData.type == QuestType.Kill)
					{
						try
						{
							huginQuestData.thing = ZNetScene.instance.GetPrefab(huginQuestData.thing).GetComponent<Character>().m_name;
						}
						catch
						{
						}
					}
					huginQuestDict[huginQuestData.ID] = huginQuestData;
					Dbgl("Added quest " + huginQuestData.ID);
				}
			}
		}
		if (huginQuestDict.Count != 0)
		{
			return;
		}
		possibleKillList = ((Dictionary<int, GameObject>)AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs").GetValue(ZNetScene.instance)).Values.ToList().FindAll((GameObject g) => (Object.op_Implicit((Object)(object)g) && Object.op_Implicit((Object)(object)g.GetComponent<MonsterAI>())) || Object.op_Implicit((Object)(object)g.GetComponent<AnimalAI>()));
		possibleFetchList.Clear();
		List<GameObject> list2 = ObjectDB.instance.m_items.FindAll(delegate(GameObject g)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Invalid comparison between Unknown and I4
			int result;
			if (Object.op_Implicit((Object)(object)g) && Object.op_Implicit((Object)(object)g.GetComponent<ItemDrop>()))
			{
				ItemData itemData = g.GetComponent<ItemDrop>().m_itemData;
				result = ((itemData != null && (int)(itemData.m_shared?.m_itemType).GetValueOrDefault() == 1) ? 1 : 0);
			}
			else
			{
				result = 0;
			}
			return (byte)result != 0;
		});
		foreach (GameObject item in list2)
		{
			int itemValue = GetItemValue(item.GetComponent<ItemDrop>());
			if (itemValue > 0 && (allowUnknownFetchMaterials.Value || AccessTools.FieldRefAccess<Player, HashSet<string>>(Player.m_localPlayer, "m_knownMaterial").Contains(item.GetComponent<ItemDrop>().m_itemData.m_shared.m_name)))
			{
				possibleFetchList.Add(new GameObjectReward(item, itemValue));
			}
		}
		possibleBuildList.Clear();
		GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Hammer");
		ItemDrop val = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null);
		List<GameObject> list3 = new List<GameObject>(val.m_itemData.m_shared.m_buildPieces.m_pieces);
		GameObject itemPrefab2 = ObjectDB.instance.GetItemPrefab("Hoe");
		ItemDrop val2 = ((itemPrefab2 != null) ? itemPrefab2.GetComponent<ItemDrop>() : null);
		list3.AddRange(val2.m_itemData.m_shared.m_buildPieces.m_pieces);
		foreach (GameObject item2 in list3)
		{
			Requirement[] resources = item2.GetComponent<Piece>().m_resources;
			int num = 0;
			Requirement[] array3 = resources;
			foreach (Requirement val3 in array3)
			{
				num += GetItemValue(val3.m_resItem) * val3.m_amount;
			}
			if (num > 0)
			{
				possibleBuildList.Add(new GameObjectReward(item2, num));
			}
		}
		Dbgl($"got {possibleFetchList.Count} possible fetch items, {possibleKillList.Count} possible kill items, and {possibleBuildList.Count} possible build items");
	}

	public static int GetItemValue(ItemDrop itemDrop)
	{
		int num = itemDrop.m_itemData.m_shared.m_value;
		if (Chainloader.PluginInfos.ContainsKey("Menthus.bepinex.plugins.BetterTrader"))
		{
			ConfigDefinition key = Chainloader.PluginInfos["Menthus.bepinex.plugins.BetterTrader"].Instance.Config.Keys.ToList().Find((ConfigDefinition c) => c.Section.StartsWith("C_Items") && c.Section.EndsWith("." + ((Object)itemDrop).name) && c.Key == "Sellable");
			if (key != (ConfigDefinition)null && (bool)Chainloader.PluginInfos["Menthus.bepinex.plugins.BetterTrader"].Instance.Config[key].BoxedValue)
			{
				key = Chainloader.PluginInfos["Menthus.bepinex.plugins.BetterTrader"].Instance.Config.Keys.ToList().Find((ConfigDefinition c) => c.Section == key.Section && c.Key == "Sell Price");
				num = (int)Chainloader.PluginInfos["Menthus.bepinex.plugins.BetterTrader"].Instance.Config[key].BoxedValue;
			}
		}
		if (num <= 0 && randomWorthlessItemValue.Value > 0)
		{
			num = randomWorthlessItemValue.Value;
		}
		return num;
	}

	public static QuestData MakeRandomQuest()
	{
		if (huginQuestDict.Count > 0)
		{
			Dbgl("Making random custom quest");
			int num = Random.Range(0, huginQuestDict.Count);
			return MakeQuestData(huginQuestDict[huginQuestDict.Keys.ToArray()[num]]);
		}
		Dbgl("Making random quest");
		float num2 = Random.value * (randomFetchQuestWeight.Value + randomKillQuestWeight.Value + randomBuildQuestWeight.Value);
		QuestType questType = ((!(num2 <= randomFetchQuestWeight.Value)) ? ((num2 <= randomFetchQuestWeight.Value + randomKillQuestWeight.Value) ? QuestType.Kill : QuestType.Build) : QuestType.Fetch);
		int num3 = Random.Range(minAmount.Value, maxAmount.Value);
		string name;
		string questName;
		string stageName;
		int num4;
		switch (questType)
		{
		case QuestType.Kill:
		{
			GameObject gameObject = possibleKillList[Random.Range(0, possibleKillList.Count)];
			num4 = Mathf.RoundToInt((float)num3 * gameObject.GetComponent<Character>().m_health * randomKillRewardMult.Value);
			name = gameObject.GetComponent<Character>().m_name;
			questName = randomKillQuestName.Value.Replace("{thing}", Localization.instance.Localize(name));
			stageName = randomKillQuestObjectiveName.Value.Replace("{thing}", Localization.instance.Localize(name));
			break;
		}
		case QuestType.Fetch:
		{
			GameObjectReward gameObjectReward2 = possibleFetchList[Random.Range(0, possibleFetchList.Count)];
			GameObject gameObject = gameObjectReward2.gameObject;
			num4 = Mathf.CeilToInt((float)(num3 * gameObjectReward2.reward) * randomFetchRewardMult.Value);
			name = gameObject.GetComponent<ItemDrop>().m_itemData.m_shared.m_name;
			questName = randomFetchQuestName.Value.Replace("{thing}", Localization.instance.Localize(name));
			stageName = randomFetchQuestObjectiveName.Value.Replace("{thing}", Localization.instance.Localize(name));
			break;
		}
		default:
		{
			GameObjectReward gameObjectReward = possibleBuildList[Random.Range(0, possibleBuildList.Count)];
			GameObject gameObject = gameObjectReward.gameObject;
			num4 = Mathf.CeilToInt((float)(num3 * gameObjectReward.reward) * randomBuildRewardMult.Value);
			name = ((Object)gameObject).name;
			questName = randomBuildQuestName.Value.Replace("{thing}", Localization.instance.Localize(gameObject.GetComponent<Piece>().m_name));
			stageName = randomBuildQuestObjectiveName.Value.Replace("{thing}", Localization.instance.Localize(gameObject.GetComponent<Piece>().m_name));
			break;
		}
		}
		num4 = Mathf.RoundToInt((float)num4 * (1f + (rewardFluctuation.Value * 2f * Random.value - rewardFluctuation.Value)));
		int num5 = 0;
		string text = $"{typeof(BepInExPlugin).Namespace}|{questType}|{num3}|{name}|{num4}|{num5}";
		while (QuestFrameworkAPI.IsQuestActive(text))
		{
			text = $"{typeof(BepInExPlugin).Namespace}|{questType}|{num3}|{name}|{num4}|{++num5}";
		}
		HuginQuestData huginQuestData = new HuginQuestData
		{
			questName = questName,
			questDesc = "",
			stageName = stageName,
			stageDesc = randomQuestRewardText.Value.Replace("{rewardName}", "gold coins"),
			objectiveName = randomQuestProgressText.Value,
			objectiveDesc = "",
			type = questType,
			thing = name,
			amount = num3,
			rewardName = "Coins",
			rewardAmount = num4,
			ID = text
		};
		Dbgl($"Created {questType} quest {huginQuestData.ID}");
		return MakeQuestData(huginQuestData);
	}

	public static QuestData MakeQuestData(HuginQuestData fqd)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_022b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0284: Unknown result type (might be due to invalid IL or missing references)
		//IL_028f: Unknown result type (might be due to invalid IL or missing references)
		//IL_029b: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0352: Unknown result type (might be due to invalid IL or missing references)
		//IL_0362: Expected O, but got Unknown
		//IL_036d: Expected O, but got Unknown
		//IL_0374: Unknown result type (might be due to invalid IL or missing references)
		//IL_0379: Unknown result type (might be due to invalid IL or missing references)
		//IL_0384: Unknown result type (might be due to invalid IL or missing references)
		//IL_0390: Unknown result type (might be due to invalid IL or missing references)
		//IL_0395: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c5: Expected O, but got Unknown
		//IL_03d0: Expected O, but got Unknown
		//IL_03d7: Expected O, but got Unknown
		return new QuestData
		{
			name = fqd.questName.Replace("{rewardAmount}", $"{fqd.rewardAmount}").Replace("{amount}", $"{fqd.amount}").Replace("{progress}", "0"),
			desc = fqd.questDesc.Replace("{rewardAmount}", $"{fqd.rewardAmount}").Replace("{amount}", $"{fqd.amount}").Replace("{progress}", "0"),
			ID = fqd.ID,
			currentStage = "StageOne",
			data = new Dictionary<string, object>
			{
				{ "qname", fqd.questName },
				{ "qdesc", fqd.questDesc },
				{ "sname", fqd.stageName },
				{ "sdesc", fqd.stageDesc },
				{ "oname", fqd.objectiveName },
				{ "odesc", fqd.objectiveDesc },
				{ "progress", 0 },
				{ "type", fqd.type },
				{ "thing", fqd.thing },
				{ "amount", fqd.amount },
				{ "rewardAmount", fqd.rewardAmount },
				{ "rewardName", fqd.rewardName }
			},
			questStages = new Dictionary<string, QuestStage>
			{
				{
					"StageOne",
					new QuestStage
					{
						name = fqd.stageName.Replace("{rewardAmount}", $"{fqd.rewardAmount}").Replace("{amount}", $"{fqd.amount}").Replace("{progress}", "0"),
						desc = fqd.stageDesc.Replace("{rewardAmount}", $"{fqd.rewardAmount}").Replace("{amount}", $"{fqd.amount}").Replace("{progress}", "0"),
						ID = "StageOne",
						objectives = new Dictionary<string, QuestObjective> { 
						{
							"ObjectiveOne",
							new QuestObjective
							{
								name = fqd.objectiveName.Replace("{rewardAmount}", $"{fqd.rewardAmount}").Replace("{amount}", $"{fqd.amount}").Replace("{progress}", "0"),
								desc = fqd.objectiveDesc.Replace("{rewardAmount}", $"{fqd.rewardAmount}").Replace("{amount}", $"{fqd.amount}").Replace("{progress}", "0"),
								ID = "ObjectiveOne"
							}
						} }
					}
				},
				{
					"StageTwo",
					new QuestStage
					{
						ID = "StageTwo",
						objectives = new Dictionary<string, QuestObjective> { 
						{
							"ObjectiveOne",
							new QuestObjective
							{
								name = returnString.Value,
								desc = returnDescString.Value,
								ID = "ObjectiveOne"
							}
						} }
					}
				}
			}
		};
	}

	public static void DeclineQuest()
	{
		Dbgl("Declining quest");
		currentText.m_topic = questDeclinedDialogue.Value;
		respondedToQuest = true;
		((Component)questDialogueTransform).gameObject.SetActive(false);
	}

	public static void AcceptQuest()
	{
		Dbgl("Accepting quest");
		currentText.m_topic = questAcceptedDialogue.Value;
		QuestFrameworkAPI.AddQuest(nextQuest, false);
		respondedToQuest = true;
		((Component)questDialogueTransform).gameObject.SetActive(false);
		AdjustFetchQuests();
	}

	public static void AdvanceKillQuests(Character character)
	{
		Dictionary<string, QuestData> currentQuests = QuestFrameworkAPI.GetCurrentQuests();
		string[] array = currentQuests.Keys.ToArray();
		string[] array2 = array;
		foreach (string key in array2)
		{
			QuestData qd = currentQuests[key];
			if (qd.ID.StartsWith(typeof(BepInExPlugin).Namespace) && (QuestType)qd.data["type"] == QuestType.Kill && qd.currentStage == "StageOne" && (string)qd.data["thing"] == character.m_name)
			{
				qd.data["progress"] = (int)qd.data["progress"] + 1;
				UpdateQuestProgress(ref qd);
				if ((int)qd.data["progress"] >= (int)qd.data["amount"])
				{
					qd.currentStage = "StageTwo";
				}
				QuestFrameworkAPI.AddQuest(qd, true);
			}
		}
	}

	public static void AdvanceBuildQuests(Piece piece)
	{
		Dictionary<string, QuestData> currentQuests = QuestFrameworkAPI.GetCurrentQuests();
		string[] array = currentQuests.Keys.ToArray();
		string[] array2 = array;
		foreach (string key in array2)
		{
			QuestData qd = currentQuests[key];
			if (qd.ID.StartsWith(typeof(BepInExPlugin).Namespace) && (QuestType)qd.data["type"] == QuestType.Build && qd.currentStage == "StageOne" && (string)qd.data["thing"] == Utils.GetPrefabName(((Component)piece).gameObject))
			{
				qd.data["progress"] = (int)qd.data["progress"] + 1;
				UpdateQuestProgress(ref qd);
				if ((int)qd.data["progress"] >= (int)qd.data["amount"])
				{
					qd.currentStage = "StageTwo";
				}
				QuestFrameworkAPI.AddQuest(qd, true);
			}
		}
	}

	public static void AdjustFetchQuests()
	{
		Dictionary<string, QuestData> currentQuests = QuestFrameworkAPI.GetCurrentQuests();
		string[] array = currentQuests.Keys.ToArray();
		string[] array2 = array;
		foreach (string key in array2)
		{
			QuestData qd = currentQuests[key];
			if (!qd.ID.StartsWith(typeof(BepInExPlugin).Namespace) || (QuestType)qd.data["type"] != QuestType.Fetch)
			{
				continue;
			}
			int num = ((Humanoid)Player.m_localPlayer).GetInventory().CountItems((string)qd.data["thing"], -1, true);
			if (num == (int)qd.data["progress"])
			{
				continue;
			}
			qd.data["progress"] = num;
			UpdateQuestProgress(ref qd);
			if ((int)qd.data["progress"] >= (int)qd.data["amount"])
			{
				qd.currentStage = "StageTwo";
			}
			else
			{
				qd.currentStage = "StageOne";
				if (finishedQuest != null && finishedQuest.ID == qd.ID)
				{
					finishedQuest = null;
				}
			}
			QuestFrameworkAPI.AddQuest(qd, true);
		}
	}

	public static void UpdateQuestProgress(ref QuestData qd)
	{
		qd.name = ((string)qd.data["qname"]).Replace("{rewardAmount}", string.Format("{0}", qd.data["rewardAmount"])).Replace("{amount}", string.Format("{0}", qd.data["amount"])).Replace("{progress}", string.Format("{0}", qd.data["progress"]));
		qd.desc = ((string)qd.data["qdesc"]).Replace("{rewardAmount}", string.Format("{0}", qd.data["rewardAmount"])).Replace("{amount}", string.Format("{0}", qd.data["amount"])).Replace("{progress}", string.Format("{0}", qd.data["progress"]));
		qd.questStages["StageOne"].name = ((string)qd.data["sname"]).Replace("{rewardAmount}", string.Format("{0}", qd.data["rewardAmount"])).Replace("{amount}", string.Format("{0}", qd.data["amount"])).Replace("{progress}", string.Format("{0}", qd.data["progress"]));
		qd.questStages["StageOne"].desc = ((string)qd.data["sdesc"]).Replace("{rewardAmount}", string.Format("{0}", qd.data["rewardAmount"])).Replace("{amount}", string.Format("{0}", qd.data["amount"])).Replace("{progress}", string.Format("{0}", qd.data["progress"]));
		qd.questStages["StageOne"].objectives["ObjectiveOne"].name = ((string)qd.data["oname"]).Replace("{rewardAmount}", string.Format("{0}", qd.data["rewardAmount"])).Replace("{amount}", string.Format("{0}", qd.data["amount"])).Replace("{progress}", string.Format("{0}", qd.data["progress"]));
		qd.questStages["StageOne"].objectives["ObjectiveOne"].desc = ((string)qd.data["odesc"]).Replace("{rewardAmount}", string.Format("{0}", qd.data["rewardAmount"])).Replace("{amount}", string.Format("{0}", qd.data["amount"])).Replace("{progress}", string.Format("{0}", qd.data["progress"]));
	}

	public static void FulfillQuest(QuestData qd)
	{
		if (qd.currentStage == "StageTwo")
		{
			if ((string)qd.data["rewardName"] == "Gold")
			{
				qd.data["rewardName"] = "Coins";
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab((string)qd.data["rewardName"]);
			ItemDrop val = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				currentText.m_topic = "There is something wrong with your quest...";
				Dbgl(string.Format("Error getting reward {0}", qd.data["rewardName"]));
				return;
			}
			Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory();
			int num = inventory.GetWidth() * inventory.GetHeight() - inventory.GetAllItems().Count;
			int num2 = inventory.FindFreeStackSpace(val.m_itemData.m_shared.m_name, (float)val.m_itemData.m_worldLevel);
			num2 += num * val.m_itemData.m_shared.m_maxStackSize;
			if (num2 < (int)qd.data["rewardAmount"])
			{
				currentText.m_topic = noRoomDialogue.Value;
				Dbgl(string.Format("No room for reward! {0} {1}", num2, (int)qd.data["rewardAmount"]));
				((Character)Player.m_localPlayer).Message((MessageType)2, "No room for reward!", 0, (Sprite)null);
				return;
			}
			if ((QuestType)qd.data["type"] == QuestType.Fetch)
			{
				if (inventory.CountItems((string)qd.data["thing"], -1, true) < (int)qd.data["amount"])
				{
					currentText.m_topic = "It seems you have not completed your quest...";
					Dbgl("not enough to complete quest!");
					if (finishedQuest != null && finishedQuest.ID == qd.ID)
					{
						finishedQuest = null;
					}
					AdjustFetchQuests();
					return;
				}
				inventory.RemoveItem((string)qd.data["thing"], (int)qd.data["amount"], -1, true);
			}
			inventory.AddItem(((Object)((Component)val).gameObject).name, (int)qd.data["rewardAmount"], val.m_itemData.m_quality, val.m_itemData.m_variant, 0L, "", false);
			((Character)Player.m_localPlayer).ShowPickupMessage(val.m_itemData, (int)qd.data["rewardAmount"]);
			((Character)Player.m_localPlayer).Message((MessageType)2, completeString.Value, 0, (Sprite)null);
			QuestFrameworkAPI.RemoveQuest(qd.ID);
			finishedQuest = null;
			currentText.m_topic = completedDialogue.Value;
			Dbgl("Quest " + qd.ID + " completed");
		}
		else
		{
			Dbgl("Quest " + qd.ID + " isn't ready to complete");
		}
	}
}
public class GameObjectReward
{
	public GameObject gameObject;

	public int reward;

	public GameObjectReward(GameObject go, int value)
	{
		gameObject = go;
		reward = value;
	}
}
[Serializable]
public class HuginQuestData
{
	public string questName = "";

	public string questDesc = "";

	public string stageName = "";

	public string stageDesc = "";

	public string objectiveName = "";

	public string objectiveDesc = "";

	public string ID;

	public BepInExPlugin.QuestType type = BepInExPlugin.QuestType.Fetch;

	public string thing = "";

	public int amount = 0;

	public int rewardAmount = 0;

	public string rewardName = "";
}

plugins/aedenthorn-QuestFramework/QuestFramework.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+0d02688ca05f415d9319b5e85b2635fd3fbeffc8")]
[assembly: AssemblyVersion("1.0.0.0")]
public class AedenthornUtils
{
	public static bool IgnoreKeyPresses(bool extra = false)
	{
		if (!extra)
		{
			int result;
			if (!((Object)(object)ZNetScene.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !Minimap.IsOpen() && !Console.IsVisible() && !TextInput.IsVisible() && !ZNet.instance.InPasswordDialog())
			{
				Chat instance = Chat.instance;
				result = ((instance != null && instance.HasFocus()) ? 1 : 0);
			}
			else
			{
				result = 1;
			}
			return (byte)result != 0;
		}
		int result2;
		if (!((Object)(object)ZNetScene.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !Minimap.IsOpen() && !Console.IsVisible() && !TextInput.IsVisible() && !ZNet.instance.InPasswordDialog())
		{
			Chat instance2 = Chat.instance;
			if ((instance2 == null || !instance2.HasFocus()) && !StoreGui.IsVisible() && !InventoryGui.IsVisible() && !Menu.IsVisible())
			{
				TextViewer instance3 = TextViewer.instance;
				result2 = ((instance3 != null && instance3.IsVisible()) ? 1 : 0);
				goto IL_00d2;
			}
		}
		result2 = 1;
		goto IL_00d2;
		IL_00d2:
		return (byte)result2 != 0;
	}

	public static bool CheckKeyDown(string value)
	{
		try
		{
			string[] array = value.Split(',');
			foreach (string text in array)
			{
				if (Input.GetKeyDown(text.ToLower()))
				{
					return true;
				}
			}
		}
		catch
		{
		}
		return false;
	}

	public static bool CheckKeyUp(string value)
	{
		try
		{
			string[] array = value.Split(',');
			foreach (string text in array)
			{
				if (Input.GetKeyUp(text.ToLower()))
				{
					return true;
				}
			}
		}
		catch
		{
		}
		return false;
	}

	public static bool CheckKeyHeld(string value, bool req = true)
	{
		try
		{
			string[] array = value.Split(',');
			foreach (string text in array)
			{
				if (Input.GetKey(text.ToLower()))
				{
					return true;
				}
			}
		}
		catch
		{
		}
		return !req;
	}

	public static void ShuffleList<T>(List<T> list)
	{
		int num = list.Count;
		while (num > 1)
		{
			num--;
			int index = Random.Range(0, num);
			T value = list[index];
			list[index] = list[num];
			list[num] = value;
		}
	}

	public static string GetAssetPath(object obj, bool create = false)
	{
		return GetAssetPath(obj.GetType().Namespace, create);
	}

	public static string GetAssetPath(string name, bool create = false)
	{
		string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), name);
		if (create && !Directory.Exists(text))
		{
			Directory.CreateDirectory(text);
		}
		return text;
	}

	public static string GetTransformPath(Transform t)
	{
		if (!Object.op_Implicit((Object)(object)t.parent))
		{
			return ((Object)t).name;
		}
		return GetTransformPath(t.parent) + "/" + ((Object)t).name;
	}

	public static byte[] EncodeToPNG(Texture2D texture)
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Expected O, but got Unknown
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Expected O, but got Unknown
		RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)7, (RenderTextureReadWrite)0);
		Graphics.Blit((Texture)(object)texture, temporary);
		RenderTexture active = RenderTexture.active;
		RenderTexture.active = temporary;
		Texture2D val = new Texture2D(((Texture)texture).width, ((Texture)texture).height, (TextureFormat)4, true, false);
		val.ReadPixels(new Rect(0f, 0f, (float)((Texture)temporary).width, (float)((Texture)temporary).height), 0, 0);
		val.Apply();
		RenderTexture.active = active;
		RenderTexture.ReleaseTemporary(temporary);
		Texture2D val2 = new Texture2D(((Texture)texture).width, ((Texture)texture).height);
		val2.SetPixels(val.GetPixels());
		val2.Apply();
		return ImageConversion.EncodeToPNG(val2);
	}
}
namespace QuestFramework;

[BepInPlugin("aedenthorn.QuestFramework", "Quest Framework", "0.3.0")]
public class BepInExPlugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	public static class ZNetScene_Awake_Patch
	{
		public static void Prefix()
		{
			if (modEnabled.Value)
			{
				ApplyConfig();
				LoadQuests(Game.instance.GetPlayerProfile().GetName(), ZNet.instance.GetWorldName());
			}
		}
	}

	[HarmonyPatch(typeof(PlayerProfile), "SavePlayerToDisk")]
	public static class PlayerProfile_SavePlayerToDisk_Patch
	{
		public static void Prefix()
		{
			if (modEnabled.Value && Object.op_Implicit((Object)(object)ZNet.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				SaveQuests(Game.instance.GetPlayerProfile().GetName(), ZNet.instance.GetWorldName());
			}
		}
	}

	[HarmonyPatch(typeof(Terminal), "InputText")]
	public static class InputText_Patch
	{
		public static bool Prefix(Terminal __instance)
		{
			if (!modEnabled.Value)
			{
				return true;
			}
			string text = ((TMP_InputField)__instance.m_input).text;
			if (text.ToLower().Equals(typeof(BepInExPlugin).Namespace.ToLower() + " reset"))
			{
				((BaseUnityPlugin)context).Config.Reload();
				((BaseUnityPlugin)context).Config.Save();
				Game instance = Game.instance;
				object obj;
				if (instance == null)
				{
					obj = null;
				}
				else
				{
					PlayerProfile playerProfile = instance.GetPlayerProfile();
					obj = ((playerProfile != null) ? playerProfile.GetName() : null);
				}
				if (obj != null)
				{
					ZNet instance2 = ZNet.instance;
					if (((instance2 != null) ? instance2.GetWorldName() : null) != null)
					{
						LoadQuests(Game.instance.GetPlayerProfile().GetName(), ZNet.instance.GetWorldName());
					}
				}
				RefreshQuestString();
				__instance.AddString(text);
				__instance.AddString(((BaseUnityPlugin)context).Info.Metadata.Name + " config reloaded");
				return false;
			}
			if (text.ToLower().StartsWith(typeof(BepInExPlugin).Namespace.ToLower() + " end "))
			{
				__instance.AddString(text);
				List<string> list = currentQuests.questDict.Keys.ToList();
				list.Sort();
				string text2 = text.Split(' ')[2];
				if ((list.Contains(text2) && QuestFrameworkAPI.RemoveQuest(text2)) || (int.TryParse(text2, out var result) && list.Count > result && QuestFrameworkAPI.RemoveQuest(list[result])))
				{
					__instance.AddString(((BaseUnityPlugin)context).Info.Metadata.Name + " quest removed");
				}
				else
				{
					__instance.AddString(((BaseUnityPlugin)context).Info.Metadata.Name + " error removing quest");
				}
				return false;
			}
			if (text.ToLower().StartsWith(typeof(BepInExPlugin).Namespace.ToLower() + " clear"))
			{
				__instance.AddString(text);
				currentQuests.questDict.Clear();
				__instance.AddString(((BaseUnityPlugin)context).Info.Metadata.Name + " quests cleared");
				return false;
			}
			if (text.ToLower().StartsWith(typeof(BepInExPlugin).Namespace.ToLower() + " list"))
			{
				__instance.AddString(text);
				List<string> list2 = currentQuests.questDict.Keys.ToList();
				list2.Sort();
				for (int i = 0; i < list2.Count; i++)
				{
					__instance.AddString(i + " " + list2[i]);
				}
				return false;
			}
			return true;
		}
	}

	public static readonly bool isDebug = true;

	public static BepInExPlugin context;

	public static ConfigEntry<bool> modEnabled;

	public static ConfigEntry<int> nexusID;

	public static ConfigEntry<bool> showHUD;

	public static ConfigEntry<string> toggleHUDKey;

	public static ConfigEntry<bool> toggleHUDKeyOnPress;

	public static ConfigEntry<bool> hudUseOSFont;

	public static ConfigEntry<bool> hudUseShadow;

	public static ConfigEntry<Color> hudFontColor;

	public static ConfigEntry<Color> hudShadowColor;

	public static ConfigEntry<int> hudShadowOffset;

	public static ConfigEntry<int> hudFontSize;

	public static ConfigEntry<string> toggleHUDKeyMod;

	public static ConfigEntry<string> toggleClockKey;

	public static ConfigEntry<string> hudFontName;

	public static ConfigEntry<string> hudTemplate;

	public static ConfigEntry<string> questNameTemplate;

	public static ConfigEntry<string> questDescTemplate;

	public static ConfigEntry<string> stageNameTemplate;

	public static ConfigEntry<string> stageDescTemplate;

	public static ConfigEntry<string> objectiveNameTemplate;

	public static ConfigEntry<string> objectiveDescTemplate;

	public static ConfigEntry<string> hudLocationString;

	public static ConfigEntry<TextAnchor> hudTextAlignment;

	public static QuestDataObject currentQuests = new QuestDataObject();

	public static Font hudFont;

	public static GUIStyle style;

	public static GUIStyle style2;

	public static bool configApplied = false;

	public static Vector2 hudPosition;

	public static Rect windowRect;

	public static string newQuestString;

	public static Rect timeRect;

	public static int windowId = 1890175403;

	public static void Dbgl(string str = "", bool pref = true)
	{
		if (isDebug)
		{
			Debug.Log((object)((pref ? (typeof(BepInExPlugin).Namespace + " ") : "") + str));
		}
	}

	public void Awake()
	{
		//IL_018c: 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)
		context = this;
		modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable this mod");
		nexusID = ((BaseUnityPlugin)this).Config.Bind<int>("General", "NexusID", 1583, "Nexus mod ID for updates");
		showHUD = ((BaseUnityPlugin)this).Config.Bind<bool>("Options", "ShowHUD", true, "Show the quest HUD");
		toggleHUDKey = ((BaseUnityPlugin)this).Config.Bind<string>("Options", "ToggleHUDKey", "j", "Key used to toggle the HUD display. Leave blank to disable toggling. Use https://docs.unity3d.com/Manual/ConventionalGameInput.html");
		toggleHUDKeyMod = ((BaseUnityPlugin)this).Config.Bind<string>("Options", "ToggleHUDKeyMod", "", "Extra modifier key used to toggle the HUD display. Leave blank to not require one. Use https://docs.unity3d.com/Manual/ConventionalGameInput.html");
		hudLocationString = ((BaseUnityPlugin)this).Config.Bind<string>("Options", "HudLocationString", "80%,50%", "Location on the screen to show the HUD (x,y) or (x%,y%)");
		hudUseOSFont = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "HUDUseOSFont", false, "Set to true to specify the name of a font from your OS; otherwise limited to fonts in the game resources");
		hudUseShadow = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "HUDUseShadow", false, "Add a shadow behind the HUD text");
		hudShadowOffset = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "HUDShadowOffset", 2, "Shadow offset in pixels");
		hudFontName = ((BaseUnityPlugin)this).Config.Bind<string>("Display", "HUDFontName", "AveriaSerifLibre-Bold", "Name of the font to use");
		hudFontSize = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "HUDFontSize", 24, "Font size of HUD display");
		hudFontColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Display", "HUDFontColor", Color.white, "Font color for the HUD");
		hudShadowColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Display", "HUDShadowColor", Color.black, "Color for the shadow");
		toggleHUDKeyOnPress = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ToggleHUDKeyOnPress", false, "If true, limit HUD display to when the hotkey is down");
		hudTemplate = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "hudTemplate", "<color=#FFB65F><b>Current Quests:</b></color>\n\n{quests}", "Quest list template. {quests} is replaced by the quest list.");
		questNameTemplate = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "QuestNameTemplate", "<size=24>  </size><size=20>{name}</size>", "Quest name template. {name} is replaced by the quest name");
		questDescTemplate = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "QuestDescTemplate", "<size=24>  </size><size=20><i>{desc}</i></size>", "Quest desc template. {desc} is replaced by the quest description.");
		stageNameTemplate = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "StageNameTemplate", "<size=24>    </size><size=18>{name}</size>", "Quest stage name template. {name} is replaced by the stage name.");
		stageDescTemplate = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "StageDescTemplate", "<size=24>    </size><size=18><i>{desc}</i></size>", "Quest stage desc template. {desc} is replaced by the stage description.");
		objectiveNameTemplate = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "ObjectiveNameTemplate", "<size=24>      </size><size=16>{name}</size>", "Stage objective name template. {name} is replaced by the objective name.");
		objectiveDescTemplate = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "ObjectiveDescTemplate", "<size=24>      </size><size=16><i>{desc}</i></size>", "Stage objective desc template. {desc} is replaced by the objective description.");
		hudTextAlignment = ((BaseUnityPlugin)this).Config.Bind<TextAnchor>("Text", "HudTextAlignment", (TextAnchor)3, "HUD display text alignment.");
		Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), MetadataHelper.GetMetadata((object)this).GUID);
	}

	public void Update()
	{
		if (((Behaviour)this).enabled && Object.op_Implicit((Object)(object)Hud.instance) && !toggleHUDKeyOnPress.Value && AedenthornUtils.CheckKeyDown(toggleHUDKey.Value) && AedenthornUtils.CheckKeyHeld(toggleHUDKeyMod.Value, req: false) && !AedenthornUtils.IgnoreKeyPresses(extra: true))
		{
			showHUD.Value = !showHUD.Value;
		}
	}

	public void OnGUI()
	{
		//IL_012b: 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_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: 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_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_022b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0240: Unknown result type (might be due to invalid IL or missing references)
		//IL_024a: Unknown result type (might be due to invalid IL or missing references)
		//IL_024f: Unknown result type (might be due to invalid IL or missing references)
		//IL_025b: Unknown result type (might be due to invalid IL or missing references)
		//IL_026f: Expected O, but got Unknown
		//IL_026a: Unknown result type (might be due to invalid IL or missing references)
		//IL_026f: Unknown result type (might be due to invalid IL or missing references)
		if (Minimap.IsOpen() || Console.IsVisible() || TextInput.IsVisible())
		{
			return;
		}
		ZNet instance = ZNet.instance;
		if (instance != null && instance.InPasswordDialog())
		{
			return;
		}
		Chat instance2 = Chat.instance;
		if ((instance2 != null && instance2.HasFocus()) || StoreGui.IsVisible() || InventoryGui.IsVisible() || Menu.IsVisible())
		{
			return;
		}
		TextViewer instance3 = TextViewer.instance;
		if ((instance3 != null && instance3.IsVisible()) || currentQuests.questDict.Count == 0 || (!showHUD.Value && !toggleHUDKeyOnPress.Value) || (toggleHUDKeyOnPress.Value && (!AedenthornUtils.CheckKeyHeld(toggleHUDKey.Value) || !AedenthornUtils.CheckKeyHeld(toggleHUDKeyMod.Value))))
		{
			return;
		}
		if (modEnabled.Value && configApplied && Object.op_Implicit((Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)Hud.instance))
		{
			float num = 1f;
			style.normal.textColor = new Color(hudFontColor.Value.r, hudFontColor.Value.g, hudFontColor.Value.b, hudFontColor.Value.a * num);
			style2.normal.textColor = new Color(hudShadowColor.Value.r, hudShadowColor.Value.g, hudShadowColor.Value.b, hudShadowColor.Value.a * num);
			if (((!toggleHUDKeyOnPress.Value && showHUD.Value) || (toggleHUDKeyOnPress.Value && AedenthornUtils.CheckKeyHeld(toggleClockKey.Value))) && (bool)AccessTools.Method(typeof(Hud), "IsVisible", (Type[])null, (Type[])null).Invoke(Hud.instance, new object[0]))
			{
				GUI.backgroundColor = Color.clear;
				windowRect = GUILayout.Window(windowId, new Rect(((Rect)(ref windowRect)).position, ((Rect)(ref timeRect)).size), new WindowFunction(WindowBuilder), "", Array.Empty<GUILayoutOption>());
			}
		}
		if (!Input.GetKey((KeyCode)323) && (((Rect)(ref windowRect)).x != hudPosition.x || ((Rect)(ref windowRect)).y != hudPosition.y))
		{
			hudPosition = new Vector2(((Rect)(ref windowRect)).x, ((Rect)(ref windowRect)).y);
			hudLocationString.Value = $"{((Rect)(ref windowRect)).x},{((Rect)(ref windowRect)).y}";
			((BaseUnityPlugin)this).Config.Save();
		}
	}

	public static void RefreshQuestString()
	{
		if (currentQuests.questDict.Count == 0)
		{
			newQuestString = "";
			return;
		}
		string value = hudTemplate.Value;
		List<string> list = new List<string>();
		foreach (QuestData value2 in currentQuests.questDict.Values)
		{
			string item = MakeQuestString(value2);
			list.Add(item);
		}
		newQuestString = value.Replace("{quests}", string.Join("\n\n", list));
		Dbgl("new quest string:\n\n" + newQuestString);
	}

	public static string MakeQuestString(QuestData qd)
	{
		List<string> list = new List<string>();
		if (qd.name.Length > 0)
		{
			list.Add(questNameTemplate.Value.Replace("{name}", qd.name));
		}
		if (qd.desc.Length > 0)
		{
			list.Add(questDescTemplate.Value.Replace("{desc}", qd.desc));
		}
		QuestStage questStage = qd.questStages[qd.currentStage];
		List<string> list2 = new List<string>();
		if (questStage.name.Length > 0)
		{
			list2.Add(stageNameTemplate.Value.Replace("{name}", questStage.name));
		}
		if (questStage.desc.Length > 0)
		{
			list2.Add(stageDescTemplate.Value.Replace("{desc}", questStage.desc));
		}
		List<string> list3 = new List<string>();
		foreach (QuestObjective value in questStage.objectives.Values)
		{
			if (!value.completed)
			{
				List<string> list4 = new List<string>();
				if (value.name.Length > 0)
				{
					list4.Add(objectiveNameTemplate.Value.Replace("{name}", value.name));
				}
				if (value.desc.Length > 0)
				{
					list4.Add(objectiveDescTemplate.Value.Replace("{desc}", value.desc));
				}
				list3.Add(string.Join("\n", list4));
			}
		}
		if (list3.Count > 0)
		{
			list2.AddRange(list3);
		}
		if (list2.Count > 0)
		{
			list.AddRange(list2);
		}
		return string.Join("\n", list);
	}

	public void WindowBuilder(int id)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Expected O, but got Unknown
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		timeRect = GUILayoutUtility.GetRect(new GUIContent(newQuestString), style);
		GUI.DragWindow(timeRect);
		if (hudUseShadow.Value)
		{
			GUI.Label(new Rect(((Rect)(ref timeRect)).position + new Vector2((float)(-hudShadowOffset.Value), (float)hudShadowOffset.Value), ((Rect)(ref timeRect)).size), newQuestString, style2);
		}
		GUI.Label(timeRect, newQuestString, style);
	}

	public static void ApplyConfig()
	{
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: 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)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Expected O, but got Unknown
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01df: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: Expected O, but got Unknown
		string[] array = hudLocationString.Value.Split(',');
		hudPosition = new Vector2(array[0].Trim().EndsWith("%") ? (float.Parse(array[0].Trim().Substring(0, array[0].Trim().Length - 1)) / 100f * (float)Screen.width) : float.Parse(array[0].Trim()), array[1].Trim().EndsWith("%") ? (float.Parse(array[1].Trim().Substring(0, array[1].Trim().Length - 1)) / 100f * (float)Screen.height) : float.Parse(array[1].Trim()));
		windowRect = new Rect(hudPosition, new Vector2(1000f, 100f));
		if (hudUseOSFont.Value)
		{
			hudFont = Font.CreateDynamicFontFromOSFont(hudFontName.Value, hudFontSize.Value);
		}
		else
		{
			Debug.Log((object)"getting fonts");
			Font[] array2 = Resources.FindObjectsOfTypeAll<Font>();
			Font[] array3 = array2;
			foreach (Font val in array3)
			{
				if (((Object)val).name == hudFontName.Value)
				{
					hudFont = val;
					Debug.Log((object)("got font " + ((Object)val).name));
					break;
				}
			}
		}
		style = new GUIStyle
		{
			richText = true,
			fontSize = hudFontSize.Value,
			alignment = hudTextAlignment.Value,
			font = hudFont
		};
		style2 = new GUIStyle
		{
			richText = true,
			fontSize = hudFontSize.Value,
			alignment = hudTextAlignment.Value,
			font = hudFont
		};
		configApplied = true;
	}

	public static void LoadQuests(string player, string world)
	{
		currentQuests.questDict.Clear();
		if (File.Exists(Path.Combine(AedenthornUtils.GetAssetPath(context, create: true), player + "_" + world)))
		{
			using (Stream serializationStream = File.Open(Path.Combine(AedenthornUtils.GetAssetPath(context, create: true), player + "_" + world), FileMode.Open))
			{
				BinaryFormatter binaryFormatter = new BinaryFormatter();
				currentQuests = (QuestDataObject)binaryFormatter.Deserialize(serializationStream);
			}
			RefreshQuestString();
			Dbgl($"Got {currentQuests.questDict.Count} quests for player {player} in world {world}");
		}
	}

	public static void SaveQuests(string player, string world)
	{
		if (currentQuests.questDict.Count == 0 && !File.Exists(Path.Combine(AedenthornUtils.GetAssetPath(context, create: true), player + "_" + world)))
		{
			return;
		}
		using Stream serializationStream = File.Open(Path.Combine(AedenthornUtils.GetAssetPath(context, create: true), player + "_" + world), FileMode.Create);
		BinaryFormatter binaryFormatter = new BinaryFormatter();
		binaryFormatter.Serialize(serializationStream, currentQuests);
		Dbgl("Quests saved for " + player + " in world " + world);
	}
}
public static class QuestFrameworkAPI
{
	public static Dictionary<string, QuestData> GetCurrentQuests()
	{
		return BepInExPlugin.currentQuests.questDict;
	}

	public static QuestData GetQuestByID(string ID)
	{
		if (!BepInExPlugin.currentQuests.questDict.ContainsKey(ID))
		{
			BepInExPlugin.Dbgl("Quest " + ID + " not active");
			return null;
		}
		return BepInExPlugin.currentQuests.questDict[ID];
	}

	public static bool AddQuest(QuestData qd, bool force = false)
	{
		if (BepInExPlugin.currentQuests.questDict.ContainsKey(qd.ID) && !force)
		{
			BepInExPlugin.Dbgl("Quest " + qd.ID + " already active");
			return false;
		}
		BepInExPlugin.currentQuests.questDict[qd.ID] = qd;
		BepInExPlugin.Dbgl("Quest " + qd.ID + " added");
		BepInExPlugin.RefreshQuestString();
		return true;
	}

	public static bool RemoveQuest(string ID)
	{
		if (!BepInExPlugin.currentQuests.questDict.ContainsKey(ID))
		{
			BepInExPlugin.Dbgl("Quest " + ID + " not active");
			return false;
		}
		BepInExPlugin.currentQuests.questDict.Remove(ID);
		BepInExPlugin.Dbgl("Quest " + ID + " removed");
		BepInExPlugin.RefreshQuestString();
		return true;
	}

	public static bool IsQuestActive(string ID)
	{
		return BepInExPlugin.currentQuests.questDict.ContainsKey(ID);
	}

	public static bool ChangeStage(string questID, string stageID)
	{
		if (!BepInExPlugin.currentQuests.questDict.ContainsKey(questID))
		{
			BepInExPlugin.Dbgl("Quest " + questID + " not active");
			return false;
		}
		if (!BepInExPlugin.currentQuests.questDict[questID].questStages.ContainsKey(stageID))
		{
			BepInExPlugin.Dbgl("Quest does not contain a stage called " + stageID);
			return false;
		}
		BepInExPlugin.currentQuests.questDict[questID].currentStage = stageID;
		BepInExPlugin.Dbgl("Quest " + questID + " stage changed to " + stageID);
		BepInExPlugin.RefreshQuestString();
		return true;
	}

	public static string GetCurrentStage(string questID)
	{
		if (!BepInExPlugin.currentQuests.questDict.ContainsKey(questID))
		{
			BepInExPlugin.Dbgl("Quest " + questID + " not active");
			return null;
		}
		return BepInExPlugin.currentQuests.questDict[questID].currentStage;
	}

	public static string GetQuestString(string questID)
	{
		if (!BepInExPlugin.currentQuests.questDict.ContainsKey(questID))
		{
			BepInExPlugin.Dbgl("Quest " + questID + " not active");
			return null;
		}
		return BepInExPlugin.MakeQuestString(BepInExPlugin.currentQuests.questDict[questID]);
	}

	public static string GetQuestString(QuestData questData)
	{
		return BepInExPlugin.MakeQuestString(questData);
	}
}
[Serializable]
public class QuestDataObject
{
	public Dictionary<string, QuestData> questDict = new Dictionary<string, QuestData>();
}
[Serializable]
public class QuestData
{
	public string name = "";

	public string desc = "";

	public string ID = "";

	public string currentStage = "";

	public Dictionary<string, object> data = new Dictionary<string, object>();

	public Dictionary<string, QuestStage> questStages = new Dictionary<string, QuestStage>();
}
[Serializable]
public class QuestStage
{
	public string name = "";

	public string desc = "";

	public string ID = "";

	public Dictionary<string, object> data = new Dictionary<string, object>();

	public Dictionary<string, QuestObjective> objectives = new Dictionary<string, QuestObjective>();
}
[Serializable]
public class QuestObjective
{
	public string name = "";

	public string desc = "";

	public string ID = "";

	public Dictionary<string, object> data = new Dictionary<string, object>();

	public bool completed = false;
}