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(List 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 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 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 modEnabled; public static ConfigEntry nexusID; public static ConfigEntry showHUD; public static ConfigEntry toggleHUDKey; public static ConfigEntry toggleHUDKeyOnPress; public static ConfigEntry hudUseOSFont; public static ConfigEntry hudUseShadow; public static ConfigEntry hudFontColor; public static ConfigEntry hudShadowColor; public static ConfigEntry hudShadowOffset; public static ConfigEntry hudFontSize; public static ConfigEntry toggleHUDKeyMod; public static ConfigEntry toggleClockKey; public static ConfigEntry hudFontName; public static ConfigEntry hudTemplate; public static ConfigEntry questNameTemplate; public static ConfigEntry questDescTemplate; public static ConfigEntry stageNameTemplate; public static ConfigEntry stageDescTemplate; public static ConfigEntry objectiveNameTemplate; public static ConfigEntry objectiveDescTemplate; public static ConfigEntry hudLocationString; public static ConfigEntry 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("General", "Enabled", true, "Enable this mod"); nexusID = ((BaseUnityPlugin)this).Config.Bind("General", "NexusID", 1583, "Nexus mod ID for updates"); showHUD = ((BaseUnityPlugin)this).Config.Bind("Options", "ShowHUD", true, "Show the quest HUD"); toggleHUDKey = ((BaseUnityPlugin)this).Config.Bind("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("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("Options", "HudLocationString", "80%,50%", "Location on the screen to show the HUD (x,y) or (x%,y%)"); hudUseOSFont = ((BaseUnityPlugin)this).Config.Bind("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("Display", "HUDUseShadow", false, "Add a shadow behind the HUD text"); hudShadowOffset = ((BaseUnityPlugin)this).Config.Bind("Display", "HUDShadowOffset", 2, "Shadow offset in pixels"); hudFontName = ((BaseUnityPlugin)this).Config.Bind("Display", "HUDFontName", "AveriaSerifLibre-Bold", "Name of the font to use"); hudFontSize = ((BaseUnityPlugin)this).Config.Bind("Display", "HUDFontSize", 24, "Font size of HUD display"); hudFontColor = ((BaseUnityPlugin)this).Config.Bind("Display", "HUDFontColor", Color.white, "Font color for the HUD"); hudShadowColor = ((BaseUnityPlugin)this).Config.Bind("Display", "HUDShadowColor", Color.black, "Color for the shadow"); toggleHUDKeyOnPress = ((BaseUnityPlugin)this).Config.Bind("Display", "ToggleHUDKeyOnPress", false, "If true, limit HUD display to when the hotkey is down"); hudTemplate = ((BaseUnityPlugin)this).Config.Bind("Text", "hudTemplate", "Current Quests:\n\n{quests}", "Quest list template. {quests} is replaced by the quest list."); questNameTemplate = ((BaseUnityPlugin)this).Config.Bind("Text", "QuestNameTemplate", " {name}", "Quest name template. {name} is replaced by the quest name"); questDescTemplate = ((BaseUnityPlugin)this).Config.Bind("Text", "QuestDescTemplate", " {desc}", "Quest desc template. {desc} is replaced by the quest description."); stageNameTemplate = ((BaseUnityPlugin)this).Config.Bind("Text", "StageNameTemplate", " {name}", "Quest stage name template. {name} is replaced by the stage name."); stageDescTemplate = ((BaseUnityPlugin)this).Config.Bind("Text", "StageDescTemplate", " {desc}", "Quest stage desc template. {desc} is replaced by the stage description."); objectiveNameTemplate = ((BaseUnityPlugin)this).Config.Bind("Text", "ObjectiveNameTemplate", " {name}", "Stage objective name template. {name} is replaced by the objective name."); objectiveDescTemplate = ((BaseUnityPlugin)this).Config.Bind("Text", "ObjectiveDescTemplate", " {desc}", "Stage objective desc template. {desc} is replaced by the objective description."); hudTextAlignment = ((BaseUnityPlugin)this).Config.Bind("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()); } } 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 list = new List(); 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 list = new List(); 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 list2 = new List(); 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 list3 = new List(); foreach (QuestObjective value in questStage.objectives.Values) { if (!value.completed) { List list4 = new List(); 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[] 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 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 questDict = new Dictionary(); } [Serializable] public class QuestData { public string name = ""; public string desc = ""; public string ID = ""; public string currentStage = ""; public Dictionary data = new Dictionary(); public Dictionary questStages = new Dictionary(); } [Serializable] public class QuestStage { public string name = ""; public string desc = ""; public string ID = ""; public Dictionary data = new Dictionary(); public Dictionary objectives = new Dictionary(); } [Serializable] public class QuestObjective { public string name = ""; public string desc = ""; public string ID = ""; public Dictionary data = new Dictionary(); public bool completed = false; }