Please disclose if your mod was created primarily 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 Simple Quest v4.8.6
plugins/SimpleQuest/SimpleQuest.dll
Decompiled a month agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Jotunn.Entities; using Jotunn.Managers; using Newtonsoft.Json; 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: AssemblyTitle("SimpleQuest")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("SimpleQuest")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("526f6350-8ad0-4fd8-8066-5806b070f058")] [assembly: AssemblyFileVersion("4.8.6.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("4.8.6.0")] namespace SimpleQuest; [BepInPlugin("com.pavel.simplequest", "Simple Quest Pro", "4.8.6")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class SimpleQuestPro : BaseUnityPlugin { [HarmonyPatch(typeof(Character), "ApplyDamage")] private static class UniversalKillPatch { private static void Postfix(Character __instance, HitData hit) { if (!((Object)(object)__instance == (Object)null) && !__instance.IsPlayer() && __instance.GetHealth() <= 0f) { string key = Utils.GetPrefabName(((Component)__instance).gameObject).Trim(); if (!playerKills.ContainsKey(key)) { playerKills[key] = 0; } playerKills[key]++; if ((Object)(object)Instance != (Object)null && (Object)(object)Instance.window != (Object)null && Instance.window.activeSelf) { Instance.UpdateUI(); } } } } [CompilerGenerated] private sealed class <OnClientQuestRequest>d__31 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public long sender; public ZPackage package; public SimpleQuestPro <>4__this; private ZPackage <pkg>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <OnClientQuestRequest>d__31(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <pkg>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (ZNet.instance.IsServer()) { <pkg>5__1 = new ZPackage(); <pkg>5__1.Write(RawServerJson); <>4__this.questSyncRPC.SendPackage(sender, <pkg>5__1); <pkg>5__1 = null; } <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <OnServerQuestReceived>d__32 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public long sender; public ZPackage package; public SimpleQuestPro <>4__this; private string <json>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <OnServerQuestReceived>d__32(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <json>5__1 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <json>5__1 = package.ReadString(); if (!string.IsNullOrEmpty(<json>5__1)) { <>4__this.serverQuests = JsonConvert.DeserializeObject<QuestList>(<json>5__1) ?? <>4__this.serverQuests; if ((Object)(object)<>4__this.window != (Object)null && <>4__this.window.activeSelf) { <>4__this.UpdateUI(); } } <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string ModGUID = "com.pavel.simplequest"; public const string ModName = "Simple Quest Pro"; public const string ModVersion = "4.8.6"; public static SimpleQuestPro Instance; private ConfigEntry<KeyCode> questKey; private QuestList serverQuests = new QuestList(); private HashSet<string> completedQuests = new HashSet<string>(); public static Dictionary<string, int> playerKills = new Dictionary<string, int>(); private int currentIndex = 0; private GameObject window; private Text infoText; private Text pageText; private Text btnText; private Text titleText; private GameObject btnFinish; private Image rewardIcon; private CustomRPC questSyncRPC; private static string RawServerJson = string.Empty; private bool isFirstSpawn = true; private void Awake() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_0094: Expected O, but got Unknown Instance = this; new Harmony("com.pavel.simplequest").PatchAll(); LoadLocalization(); questKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "QuestKey", (KeyCode)108, "Клавиша журнала"); string text = Path.Combine(Paths.ConfigPath, "SimpleQuest"); if (!Directory.Exists(text)) { Directory.CreateDirectory(text); } LoadQuestsLocal(text); questSyncRPC = NetworkManager.Instance.AddRPC("QuestSync", new CoroutineHandler(OnClientQuestRequest), new CoroutineHandler(OnServerQuestReceived)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Simple Quest Pro v4.8.6 готова."); } private void Update() { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null) { isFirstSpawn = true; return; } if (isFirstSpawn) { isFirstSpawn = false; LoadProgress(); LoadQuestsLocal(Path.Combine(Paths.ConfigPath, "SimpleQuest")); if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer()) { questSyncRPC.SendPackage(ZNet.instance.GetServerPeer().m_uid, new ZPackage()); } } if ((Object)(object)window != (Object)null && window.activeSelf && (Input.GetKeyDown((KeyCode)27) || InventoryGui.IsVisible())) { ToggleUI(); } else if (!Chat.instance.HasFocus() && Input.GetKeyDown(questKey.Value)) { ToggleUI(); } } private void ToggleUI() { if ((Object)(object)window == (Object)null) { CreateUI(); } bool flag = !window.activeSelf; if (flag) { UpdateUI(); PlaySfx("sfx_gui_mouse_over"); } else { SaveProgress(); PlaySfx("sfx_gui_mouse_over"); } window.SetActive(flag); GUIManager.BlockInput(flag); Cursor.visible = flag; Cursor.lockState = (CursorLockMode)((!flag) ? 1 : 0); } private void UpdateUI() { if (serverQuests.Quests.Count == 0) { return; } QuestConfig questConfig = serverQuests.Quests[currentIndex]; bool flag = completedQuests.Contains(questConfig.ID); bool flag2 = true; string text = "\n<color=#4d2600>━━━━━━━━━━━━━━━━━━</color>\n"; if (questConfig.Reqs != null) { foreach (QuestRequirement req in questConfig.Reqs) { int itemCount = GetItemCount(req.Prefab); string itemName = GetItemName(req.Prefab); string text2 = ((itemCount >= req.Amount) ? "#006400" : "#8B0000"); text += $"• {itemName}: <color={text2}><b>{itemCount}</b> / {req.Amount}</color>\n"; if (itemCount < req.Amount) { flag2 = false; } } } if (questConfig.KillReqs != null) { foreach (QuestRequirement i in questConfig.KillReqs) { int num = playerKills.Where((KeyValuePair<string, int> x) => x.Key.Equals(i.Prefab.Trim(), StringComparison.OrdinalIgnoreCase)).Sum((KeyValuePair<string, int> x) => x.Value); string text3 = Localization.instance.Localize("$" + i.Prefab.Trim()); string text4 = ((num >= i.Amount) ? "#006400" : "#8B0000"); text += $"• Убить {text3}: <color={text4}><b>{num}</b> / {i.Amount}</color>\n"; if (num < i.Amount) { flag2 = false; } } } titleText.text = "<color=#2b1d0e><b>" + Localization.instance.Localize("$sq_journal") + "</b></color>"; bool flag3 = ((Humanoid)Player.m_localPlayer).GetInventory().GetEmptySlots() > 0; if (flag) { btnText.text = "<color=#555555>" + Localization.instance.Localize("$sq_done") + "</color>"; ((Selectable)btnFinish.GetComponent<Button>()).interactable = false; } else { btnText.text = ((!flag2) ? ("<color=#8B0000>" + Localization.instance.Localize("$sq_not_enough") + "</color>") : ((!flag3) ? ("<color=#8B4513>" + Localization.instance.Localize("$sq_no_space") + "</color>") : ("<color=#006400><b>" + Localization.instance.Localize("$sq_finish") + "</b></color>"))); ((Selectable)btnFinish.GetComponent<Button>()).interactable = flag2 && flag3; } pageText.text = string.Format("{0} {1} / {2}", Localization.instance.Localize("$sq_page"), currentIndex + 1, serverQuests.Quests.Count); if ((Object)(object)rewardIcon != (Object)null) { ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.GetPrefab(questConfig.RewardItem) : null); ItemDrop val2 = ((val != null) ? val.GetComponent<ItemDrop>() : null); if ((Object)(object)val2 != (Object)null) { rewardIcon.sprite = val2.m_itemData.GetIcon(); ((Component)rewardIcon).gameObject.SetActive(true); } else { ((Component)rewardIcon).gameObject.SetActive(false); } } string text5 = $"{GetItemName(questConfig.RewardItem)} x{questConfig.RewardAmount}"; if (questConfig.ExpReward > 0) { text5 += $" | <color=#00008B>+{questConfig.ExpReward} XP</color>"; } infoText.text = "<size=24><color=#4d2600><b>" + questConfig.Title + "</b></color></size>\n<color=#333333><i>" + questConfig.Goal + "</i></color>\n" + text + "\n<color=#4d2600><b>" + Localization.instance.Localize("$sq_reward") + ":</b></color> " + text5; } private void CompleteQuest() { QuestConfig questConfig = serverQuests.Quests[currentIndex]; if (completedQuests.Contains(questConfig.ID)) { return; } Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); if (questConfig.Reqs != null) { foreach (QuestRequirement req in questConfig.Reqs) { if (GetItemCount(req.Prefab) < req.Amount) { return; } } } if (questConfig.KillReqs != null) { foreach (QuestRequirement i in questConfig.KillReqs) { int num = playerKills.Where((KeyValuePair<string, int> x) => x.Key.Equals(i.Prefab.Trim(), StringComparison.OrdinalIgnoreCase)).Sum((KeyValuePair<string, int> x) => x.Value); if (num < i.Amount) { return; } } } if (questConfig.Reqs != null) { foreach (QuestRequirement req2 in questConfig.Reqs) { int num2 = req2.Amount; List<ItemData> list = inventory.GetAllItems().ToList(); for (int num3 = list.Count - 1; num3 >= 0; num3--) { if ((Object)(object)list[num3].m_dropPrefab != (Object)null && string.Equals(((Object)list[num3].m_dropPrefab).name, req2.Prefab, StringComparison.OrdinalIgnoreCase)) { int num4 = Math.Min(list[num3].m_stack, num2); ItemData obj = list[num3]; obj.m_stack -= num4; num2 -= num4; if (list[num3].m_stack <= 0) { inventory.RemoveItem(list[num3]); } if (num2 <= 0) { break; } } } } } inventory.AddItem(questConfig.RewardItem, questConfig.RewardAmount, 1, 0, 0L, "", false); if (questConfig.ExpReward > 0) { AddExp(questConfig.ExpReward); } completedQuests.Add(questConfig.ID); SaveProgress(); UpdateUI(); PlaySfx("sfx_coins_up"); ((Character)Player.m_localPlayer).Message((MessageType)2, Localization.instance.Localize("$sq_success"), 0, (Sprite)null); } private void AddExp(int amount) { if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } try { if (!Chainloader.PluginInfos.ContainsKey("WackyMole.EpicMMOSystem")) { return; } PluginInfo val = Chainloader.PluginInfos["WackyMole.EpicMMOSystem"]; Assembly assembly = ((object)val.Instance).GetType().Assembly; Type type = assembly.GetType("EpicMMOSystem.LevelSystem"); if (type == null) { return; } object obj = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj == null) { return; } MethodInfo method = type.GetMethod("AddExp", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length == 2) { object obj2 = ((parameters[0].ParameterType == typeof(Player)) ? Player.m_localPlayer : Convert.ChangeType(amount, parameters[0].ParameterType)); object obj3 = ((parameters[1].ParameterType == typeof(Player)) ? Player.m_localPlayer : Convert.ChangeType(amount, parameters[1].ParameterType)); method.Invoke(obj, new object[2] { obj2, obj3 }); } else if (parameters.Length == 1) { object obj4 = Convert.ChangeType(amount, parameters[0].ParameterType); method.Invoke(obj, new object[1] { obj4 }); } } } catch { } } private void LoadLocalization() { try { string path = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "translations"); string path2 = Path.Combine(path, Localization.instance.GetSelectedLanguage() + ".json"); if (!File.Exists(path2)) { path2 = Path.Combine(path, "English.json"); } if (!File.Exists(path2)) { return; } Dictionary<string, string> dictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(File.ReadAllText(path2)); foreach (KeyValuePair<string, string> item in dictionary) { LocalizationManager.Instance.AddToken(item.Key, item.Value, false); } } catch { } } private void CreateUI() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Expected O, but got Unknown //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Expected O, but got Unknown //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Expected O, but got Unknown //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_038d: Unknown result type (might be due to invalid IL or missing references) //IL_039c: Unknown result type (might be due to invalid IL or missing references) //IL_03dd: Unknown result type (might be due to invalid IL or missing references) //IL_03e7: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) window = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 600f, 550f, true); Image component = window.GetComponent<Image>(); if ((Object)(object)component != (Object)null) { component.sprite = GUIManager.Instance.GetSprite("map_base"); ((Graphic)component).color = Color.white; } titleText = GUIManager.Instance.CreateText("", window.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -25f), GUIManager.Instance.AveriaSerifBold, 16, Color.black, false, Color.clear, 400f, 25f, false).GetComponent<Text>(); titleText.alignment = (TextAnchor)4; pageText = GUIManager.Instance.CreateText("", window.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -50f), GUIManager.Instance.AveriaSerifBold, 14, Color.black, false, Color.clear, 200f, 30f, false).GetComponent<Text>(); pageText.alignment = (TextAnchor)4; infoText = GUIManager.Instance.CreateText("", window.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 10f), GUIManager.Instance.AveriaSerifBold, 17, Color.black, false, Color.clear, 500f, 350f, false).GetComponent<Text>(); infoText.alignment = (TextAnchor)4; GameObject val = new GameObject("RewardIcon", new Type[1] { typeof(Image) }); val.transform.SetParent(window.transform, false); rewardIcon = val.GetComponent<Image>(); RectTransform component2 = val.GetComponent<RectTransform>(); component2.anchoredPosition = new Vector2(0f, -130f); component2.sizeDelta = new Vector2(64f, 64f); val.SetActive(false); ((UnityEvent)GUIManager.Instance.CreateButton("<", window.transform, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(60f, 0f), 45f, 45f).GetComponent<Button>().onClick).AddListener((UnityAction)delegate { currentIndex = (currentIndex - 1 + serverQuests.Quests.Count) % serverQuests.Quests.Count; UpdateUI(); PlaySfx("sfx_book_page"); }); ((UnityEvent)GUIManager.Instance.CreateButton(">", window.transform, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-60f, 0f), 45f, 45f).GetComponent<Button>().onClick).AddListener((UnityAction)delegate { currentIndex = (currentIndex + 1) % serverQuests.Quests.Count; UpdateUI(); PlaySfx("sfx_book_page"); }); btnFinish = GUIManager.Instance.CreateButton("", window.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 50f), 200f, 40f); btnText = btnFinish.GetComponentInChildren<Text>(); ((UnityEvent)btnFinish.GetComponent<Button>().onClick).AddListener(new UnityAction(CompleteQuest)); window.SetActive(false); } private int GetItemCount(string prefab) { Player localPlayer = Player.m_localPlayer; return (localPlayer != null) ? (from x in ((Humanoid)localPlayer).GetInventory().GetAllItems() where (Object)(object)x.m_dropPrefab != (Object)null && string.Equals(((Object)x.m_dropPrefab).name, prefab, StringComparison.OrdinalIgnoreCase) select x).Sum((ItemData x) => x.m_stack) : 0; } private string GetItemName(string prefab) { string[] array = new string[3] { "$item_" + prefab.ToLower(), "$" + prefab, "$" + prefab.ToLower() }; string[] array2 = array; foreach (string text in array2) { string text2 = Localization.instance.Localize(text); if (!text2.StartsWith("$")) { return text2; } } return prefab; } private void PlaySfx(string sfxName) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ZNetScene.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null)) { GameObject prefab = ZNetScene.instance.GetPrefab(sfxName); if ((Object)(object)prefab != (Object)null) { Object.Instantiate<GameObject>(prefab, ((Component)Player.m_localPlayer).transform.position, Quaternion.identity); } } } private void LoadQuestsLocal(string dir) { string path = Path.Combine(dir, "quests.json"); if (File.Exists(path)) { RawServerJson = File.ReadAllText(path); serverQuests = JsonConvert.DeserializeObject<QuestList>(RawServerJson) ?? new QuestList(); } } [IteratorStateMachine(typeof(<OnClientQuestRequest>d__31))] private IEnumerator OnClientQuestRequest(long sender, ZPackage package) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <OnClientQuestRequest>d__31(0) { <>4__this = this, sender = sender, package = package }; } [IteratorStateMachine(typeof(<OnServerQuestReceived>d__32))] private IEnumerator OnServerQuestReceived(long sender, ZPackage package) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <OnServerQuestReceived>d__32(0) { <>4__this = this, sender = sender, package = package }; } private void LoadProgress() { string path = Path.Combine(Paths.ConfigPath, "SimpleQuest", "progress_" + Player.m_localPlayer.GetPlayerName() + ".sav"); if (File.Exists(path)) { string[] source = File.ReadAllLines(path); completedQuests = new HashSet<string>(source.Where((string l) => !l.StartsWith("KILLS:"))); string text = source.FirstOrDefault((string l) => l.StartsWith("KILLS:")); if (text != null) { playerKills = JsonConvert.DeserializeObject<Dictionary<string, int>>(text.Replace("KILLS:", "")) ?? new Dictionary<string, int>(); } } } private void SaveProgress() { string path = Path.Combine(Paths.ConfigPath, "SimpleQuest", "progress_" + Player.m_localPlayer.GetPlayerName() + ".sav"); List<string> list = completedQuests.ToList(); list.Add("KILLS:" + JsonConvert.SerializeObject((object)playerKills)); File.WriteAllLines(path, list); } } public class QuestList { public List<QuestConfig> Quests = new List<QuestConfig>(); } public class QuestConfig { public string ID; public string Title; public string Goal; public string Rarity; public string RewardItem; public int RewardAmount; public int ExpReward; public List<QuestRequirement> Reqs; public List<QuestRequirement> KillReqs; } public class QuestRequirement { public string Prefab; public int Amount; }