Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Xaltorez Valheim Modpack v1.0.1
plugins/aedenthorn-HuginQuests/HuginQuestFramework.dll
Decompiled 2 days agousing 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 agousing 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; }