Decompiled source of QuestMod v1.1.1
plugins/QuestMod/QuestMod.dll
Decompiled 18 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using HutongGames.PlayMaker; using HutongGames.PlayMaker.Actions; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using QuestPlaymakerActions; using Silksong.DataManager; using Silksong.UnityHelper.Extensions; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("QuestMod")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.1.0")] [assembly: AssemblyInformationalVersion("1.1.1+1e563a43f188437863cd4c109ecefc7245a7fabc")] [assembly: AssemblyProduct("QuestMod")] [assembly: AssemblyTitle("QuestMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] [Microsoft.CodeAnalysis.Embedded] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] [Microsoft.CodeAnalysis.Embedded] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace Microsoft.CodeAnalysis { [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace QuestMod { public struct QuestInfo { public string Name; public string DisplayName; public bool IsAccepted; public bool IsCompleted; } public struct ChainInfo { public string ChainName; public string DisplayName; public string[] Steps; public int CurrentStep; public int TotalSteps; public bool IsFullyComplete; } public static class QuestAcceptance { public static string GetExclusionConflict(string questName) { if (!QuestRegistry.MutuallyExclusiveQuests.TryGetValue(questName, out string value)) { return null; } IDictionary runtimeData = QuestDataAccess.GetRuntimeData(); if (runtimeData == null || !runtimeData.Contains(value)) { return null; } object qd = runtimeData[value]; if (QuestDataAccess.IsAccepted(qd) || QuestDataAccess.IsCompleted(qd)) { return value; } return null; } public static bool IsChainPrereqMet(string questName) { foreach (string[] value in QuestRegistry.ChainRegistry.Values) { for (int i = 0; i < value.Length; i++) { if (value[i] != questName) { continue; } if (i == 0) { return true; } IDictionary runtimeData = QuestDataAccess.GetRuntimeData(); if (runtimeData == null) { return false; } for (int j = 0; j < i; j++) { if (!runtimeData.Contains(value[j])) { return false; } if (!QuestDataAccess.IsCompleted(runtimeData[value[j]])) { return false; } } return true; } } return true; } public static string GetDisplayName(string internalName) { if (QuestRegistry.DisplayNames.TryGetValue(internalName, out string value)) { return value; } return internalName; } public static void Initialize() { QuestModPlugin.Log.LogInfo((object)"QuestAcceptance initialized"); } public static void InjectAndAcceptAllQuests() { if (PlayerData.instance == null) { QuestModPlugin.Log.LogWarning((object)"InjectAndAcceptAllQuests: PlayerData not available yet"); return; } IDictionary runtimeData = QuestDataAccess.GetRuntimeData(); if (runtimeData == null) { QuestModPlugin.Log.LogWarning((object)"InjectAndAcceptAllQuests: RuntimeData not available yet"); return; } FullQuestBase[] array = Resources.FindObjectsOfTypeAll<FullQuestBase>(); int num = 0; int num2 = 0; FullQuestBase[] array2 = array; for (int i = 0; i < array2.Length; i++) { string name = ((Object)array2[i]).name; if (string.IsNullOrEmpty(name)) { continue; } if (QuestRegistry.ExcludedQuests.Contains(name)) { QuestModPlugin.Log.LogInfo((object)(" SKIP [" + name + "]: excluded")); num2++; } else { if (runtimeData.Contains(name)) { continue; } if (!QuestModPlugin.IsQuestDiscovered(name)) { QuestModPlugin.Log.LogInfo((object)(" SKIP [" + name + "]: not discovered")); num2++; continue; } if (!IsChainPrereqMet(name)) { QuestModPlugin.Log.LogInfo((object)(" SKIP [" + name + "]: chain prereq not met")); num2++; continue; } object anyValue = GetAnyValue(runtimeData); if (anyValue != null) { object value = QuestDataAccess.SetFields(anyValue, seen: true, accepted: true, completed: false, wasEver: false); runtimeData[name] = value; num++; } } } QuestModPlugin.Log.LogInfo((object)$"Injected {num} new quests into RuntimeData (skipped {num2} excluded, total ScriptableObjects: {array.Length})"); AcceptAllQuests(); } public static void ForceAcceptAllQuests() { ForceAllQuestsOp(complete: false); } public static void ForceCompleteAllQuests() { ForceAllQuestsOp(complete: true); } private static void ForceAllQuestsOp(bool complete) { if (PlayerData.instance == null) { return; } IDictionary runtimeData = QuestDataAccess.GetRuntimeData(); if (runtimeData == null) { return; } bool blackThreadWorld = PlayerData.instance.blackThreadWorld; FullQuestBase[] array = Resources.FindObjectsOfTypeAll<FullQuestBase>(); int num = 0; FullQuestBase[] array2 = array; for (int i = 0; i < array2.Length; i++) { string name = ((Object)array2[i]).name; if (!string.IsNullOrEmpty(name) && !QuestRegistry.ExcludedQuests.Contains(name) && !runtimeData.Contains(name)) { object anyValue = GetAnyValue(runtimeData); if (anyValue != null) { object value = QuestDataAccess.SetFields(anyValue, seen: true, accepted: true, completed: false, wasEver: false); runtimeData[name] = value; num++; } } } ModifyAllQuests(runtimeData, complete); PlayerData.instance.blackThreadWorld = blackThreadWorld; string arg = (complete ? "completed" : "accepted"); QuestModPlugin.Log.LogInfo((object)$"Force {arg} ALL quests (injected {num} new, total ScriptableObjects: {array.Length}), act state preserved"); } public static void AcceptAllQuests() { if (PlayerData.instance != null) { IDictionary runtimeData = QuestDataAccess.GetRuntimeData(); if (runtimeData != null) { ModifyAllQuests(runtimeData, complete: false); } } } public static List<QuestInfo> GetQuestList() { List<QuestInfo> list = new List<QuestInfo>(); if (PlayerData.instance == null) { return list; } IDictionary runtimeData = QuestDataAccess.GetRuntimeData(); HashSet<string> hashSet = new HashSet<string>(); if (runtimeData != null) { foreach (DictionaryEntry item in runtimeData) { if (item.Key is string text) { hashSet.Add(text); list.Add(new QuestInfo { Name = text, DisplayName = GetDisplayName(text), IsAccepted = QuestDataAccess.IsAccepted(item.Value), IsCompleted = QuestDataAccess.IsCompleted(item.Value) }); } } } FullQuestBase[] array = Resources.FindObjectsOfTypeAll<FullQuestBase>(); foreach (FullQuestBase val in array) { if (!string.IsNullOrEmpty(((Object)val).name) && !hashSet.Contains(((Object)val).name)) { list.Add(new QuestInfo { Name = ((Object)val).name, DisplayName = GetDisplayName(((Object)val).name), IsAccepted = false, IsCompleted = false }); } } list.Sort((QuestInfo a, QuestInfo b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase)); return list; } public static void AcceptQuest(string name) { IDictionary dictionary; object qd; (dictionary, qd) = EnsureQuestEntry(name); if (dictionary != null) { qd = QuestDataAccess.SetFields(qd, seen: true, accepted: true, QuestDataAccess.IsCompleted(qd), QuestDataAccess.IsCompleted(qd)); dictionary[name] = qd; QuestModPlugin.LogDebugInfo("Accepted: " + name); } } public static void CompleteQuest(string name) { IDictionary dictionary; object qd; (dictionary, qd) = EnsureQuestEntry(name); if (dictionary != null) { qd = QuestDataAccess.SetFields(qd, seen: true, accepted: true, completed: true, wasEver: true); dictionary[name] = qd; QuestModPlugin.LogDebugInfo("Completed: " + name); } } public static void UnacceptQuest(string name) { if (PlayerData.instance != null) { IDictionary runtimeData = QuestDataAccess.GetRuntimeData(); if (runtimeData != null && runtimeData.Contains(name)) { object qd = runtimeData[name]; qd = QuestDataAccess.SetFields(qd, seen: true, accepted: false, completed: false, QuestDataAccess.IsCompleted(qd)); runtimeData[name] = qd; QuestModPlugin.LogDebugInfo("Unaccepted: " + name); } } } public static void UncompleteQuest(string name) { if (PlayerData.instance != null) { IDictionary runtimeData = QuestDataAccess.GetRuntimeData(); if (runtimeData != null && runtimeData.Contains(name)) { object qd = runtimeData[name]; qd = QuestDataAccess.SetFields(qd, seen: true, accepted: true, completed: false, wasEver: true); runtimeData[name] = qd; QuestModPlugin.LogDebugInfo("Uncompleted: " + name); } } } public static void CompleteAllQuests() { if (PlayerData.instance != null) { IDictionary runtimeData = QuestDataAccess.GetRuntimeData(); if (runtimeData != null) { ModifyAllQuests(runtimeData, complete: true); } } } private static (IDictionary rt, object qd) EnsureQuestEntry(string name) { if (PlayerData.instance == null) { return (null, null); } IDictionary runtimeData = QuestDataAccess.GetRuntimeData(); if (runtimeData == null) { return (null, null); } if (runtimeData.Contains(name)) { return (runtimeData, runtimeData[name]); } object anyValue = GetAnyValue(runtimeData); if (anyValue == null) { return (null, null); } object item = (runtimeData[name] = QuestDataAccess.SetFields(anyValue, seen: false, accepted: false, completed: false, wasEver: false)); QuestModPlugin.LogDebugInfo("Injected into RuntimeData: " + name); return (runtimeData, item); } private static void ModifyAllQuests(IDictionary rt, bool complete) { int num = 0; List<object> list = new List<object>(); foreach (object key in rt.Keys) { list.Add(key); } foreach (string item in list) { if (IsChainPrereqMet(item)) { object qd = rt[item]; bool flag = QuestDataAccess.IsCompleted(qd); qd = QuestDataAccess.SetFields(qd, seen: true, accepted: true, complete || flag, complete || flag); rt[item] = qd; num++; } } string arg = (complete ? "Completed" : "Accepted"); QuestModPlugin.Log.LogInfo((object)$"{arg} {num} quests"); } public static bool IsChainStep(string name) { return QuestRegistry.ChainStepNames.Contains(name); } public static List<ChainInfo> GetChainList() { List<ChainInfo> list = new List<ChainInfo>(); IDictionary runtimeData = QuestDataAccess.GetRuntimeData(); foreach (KeyValuePair<string, string[]> item in QuestRegistry.ChainRegistry) { string key = item.Key; string[] value = item.Value; int num = -1; for (int num2 = value.Length - 1; num2 >= 0; num2--) { if (runtimeData != null && runtimeData.Contains(value[num2])) { object qd = runtimeData[value[num2]]; if (QuestDataAccess.IsCompleted(qd)) { num = num2; break; } if (QuestDataAccess.IsAccepted(qd)) { num = num2; break; } } } string value2; string displayName = (QuestRegistry.ChainDisplayNames.TryGetValue(key, out value2) ? value2 : key); bool isFullyComplete = num == value.Length - 1 && runtimeData != null && runtimeData.Contains(value[num]) && QuestDataAccess.IsCompleted(runtimeData[value[num]]); list.Add(new ChainInfo { ChainName = key, DisplayName = displayName, Steps = value, CurrentStep = num, TotalSteps = value.Length, IsFullyComplete = isFullyComplete }); } return list; } public static void AdvanceChain(string chainName) { if (!QuestRegistry.ChainRegistry.TryGetValue(chainName, out string[] value)) { return; } IDictionary runtimeData = QuestDataAccess.GetRuntimeData(); if (runtimeData == null) { return; } int num = -1; for (int num2 = value.Length - 1; num2 >= 0; num2--) { if (runtimeData.Contains(value[num2])) { object qd = runtimeData[value[num2]]; if (QuestDataAccess.IsAccepted(qd) && !QuestDataAccess.IsCompleted(qd)) { num = num2; break; } if (QuestDataAccess.IsCompleted(qd)) { num = num2; break; } } } if (num >= 0 && !IsStepCompleted(runtimeData, value[num])) { CompleteQuest(value[num]); QuestModPlugin.Log.LogInfo((object)$"Chain '{chainName}': completed step {num + 1}/{value.Length} ({value[num]})"); } int num3 = num + 1; if (num3 < value.Length) { AcceptQuest(value[num3]); QuestModPlugin.Log.LogInfo((object)$"Chain '{chainName}': accepted step {num3 + 1}/{value.Length} ({value[num3]})"); } } public static void RewindChain(string chainName) { if (!QuestRegistry.ChainRegistry.TryGetValue(chainName, out string[] value)) { return; } IDictionary runtimeData = QuestDataAccess.GetRuntimeData(); if (runtimeData == null) { return; } int num = -1; for (int num2 = value.Length - 1; num2 >= 0; num2--) { if (runtimeData.Contains(value[num2])) { object qd = runtimeData[value[num2]]; if (QuestDataAccess.IsAccepted(qd) || QuestDataAccess.IsCompleted(qd)) { num = num2; break; } } } if (num >= 0) { if (!IsStepCompleted(runtimeData, value[num])) { UnacceptQuest(value[num]); QuestModPlugin.Log.LogInfo((object)$"Chain '{chainName}': unaccepted step {num + 1}/{value.Length} ({value[num]})"); } else { UncompleteQuest(value[num]); QuestModPlugin.Log.LogInfo((object)$"Chain '{chainName}': uncompleted step {num + 1}/{value.Length} ({value[num]})"); } } } private static bool IsStepCompleted(IDictionary rt, string name) { if (!rt.Contains(name)) { return false; } return QuestDataAccess.IsCompleted(rt[name]); } private static object GetAnyValue(IDictionary dict) { IDictionaryEnumerator dictionaryEnumerator = dict.GetEnumerator(); try { if (dictionaryEnumerator.MoveNext()) { return ((DictionaryEntry)dictionaryEnumerator.Current).Value; } } finally { IDisposable disposable = dictionaryEnumerator as IDisposable; if (disposable != null) { disposable.Dispose(); } } return null; } } public struct QuestTargetInfo { public string CounterName; public string DisplayName; public int CurrentCount; public int OriginalCount; public int TargetIndex; } public struct QuestOverrideInfo { public string QuestName; public string QuestTypeName; public int CompletedCount; public List<QuestTargetInfo> Targets; } public static class QuestCompletionOverrides { private static FieldInfo? targetsBackingField; private static FieldInfo? countField; private static Dictionary<string, int[]> originalCounts = new Dictionary<string, int[]>(); private static Dictionary<string, int[]> overrideCounts = new Dictionary<string, int[]>(); private static FullQuestBase[]? cachedQuests; public static bool IsInitialized { get; private set; } public static int GetMaxCap(string questName, int targetIndex) { if (QuestRegistry.MaxCaps.TryGetValue(questName, out int[] value) && targetIndex < value.Length) { return value[targetIndex]; } return -1; } public static int ClampCount(string questName, int targetIndex, int value) { if (value < 0) { value = 0; } if (QuestModPlugin.DevRemoveLimits.Value) { return value; } int maxCap = GetMaxCap(questName, targetIndex); if (maxCap > 0 && value > maxCap) { value = maxCap; } return value; } public static int GetQoLCount(int originalCount) { return (originalCount + 1) / 2; } public static int GetFarmableCount(int originalCount) { int num = (originalCount + 1) / 2; if (num > 1 && num % 2 != 0) { num--; } return num; } public static void ApplyPresetAll(string preset) { if (!IsInitialized) { return; } if (cachedQuests == null) { CacheQuests(); } if (cachedQuests == null || countField == null) { return; } FullQuestBase[] array = cachedQuests; for (int i = 0; i < array.Length; i++) { string text = ((Object)array[i]).name ?? ""; if (QuestRegistry.QuestCategories.ContainsKey(text) && originalCounts.ContainsKey(text)) { int[] array2 = originalCounts[text]; for (int j = 0; j < array2.Length; j++) { SetTargetCount(text, j, preset switch { "set1" => 1, "qol" => GetQoLCount(array2[j]), "farmable" => (!QuestRegistry.FarmableExcluded.Contains(text)) ? GetFarmableCount(array2[j]) : array2[j], _ => array2[j], }); } } } QuestModPlugin.LogDebugInfo("Applied preset '" + preset + "' to all quests"); } public static string? GetCategory(string questName) { if (QuestRegistry.QuestCategories.TryGetValue(questName, out string value)) { return value; } return null; } public static List<QuestOverrideInfo> GetQuestsByCategory(string category) { List<QuestOverrideInfo> allQuestsWithTargets = GetAllQuestsWithTargets(); List<QuestOverrideInfo> list = new List<QuestOverrideInfo>(); foreach (QuestOverrideInfo item in allQuestsWithTargets) { if (GetCategory(item.QuestName) == category) { list.Add(item); } } return list; } public static void Initialize() { Type type = typeof(FullQuestBase); while (type != null && type != typeof(Object)) { foreach (FieldInfo declaredField in AccessTools.GetDeclaredFields(type)) { if (declaredField.FieldType.IsArray && declaredField.FieldType.GetElementType()?.Name == "QuestTarget") { targetsBackingField = declaredField; countField = ReflectionCache.GetField(declaredField.FieldType.GetElementType(), "Count"); QuestModPlugin.Log.LogInfo((object)("Found targets backing field: " + declaredField.Name + " on " + type.Name)); break; } } if (targetsBackingField != null) { break; } type = type.BaseType; } if (targetsBackingField == null || countField == null) { QuestModPlugin.Log.LogWarning((object)"QuestCompletionOverrides: Could not find targets backing field"); return; } IsInitialized = true; QuestModPlugin.Log.LogInfo((object)"QuestCompletionOverrides initialized"); } internal static Array GetTargetsArray(FullQuestBase quest) { return targetsBackingField?.GetValue(quest) as Array; } public static void CacheQuests() { //IL_0083: Unknown result type (might be due to invalid IL or missing references) if (!IsInitialized) { return; } cachedQuests = Resources.FindObjectsOfTypeAll<FullQuestBase>(); QuestModPlugin.Log.LogInfo((object)$"Cached {cachedQuests.Length} FullQuestBase objects"); originalCounts.Clear(); FullQuestBase[] array = cachedQuests; foreach (FullQuestBase obj in array) { string key = ((Object)obj).name ?? ""; IReadOnlyList<QuestTarget> targets = obj.Targets; if (targets != null && targets.Count != 0) { int[] array2 = new int[targets.Count]; for (int j = 0; j < targets.Count; j++) { array2[j] = targets[j].Count; } originalCounts[key] = array2; } } } public static List<QuestOverrideInfo> GetAllQuestsWithTargets() { //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) List<QuestOverrideInfo> list = new List<QuestOverrideInfo>(); if (!IsInitialized) { return list; } if (cachedQuests == null) { CacheQuests(); } if (cachedQuests == null || countField == null) { return list; } FullQuestBase[] array = cachedQuests; foreach (FullQuestBase val in array) { string text = ((Object)val).name ?? ""; if (!QuestRegistry.QuestCategories.ContainsKey(text) || !QuestModPlugin.IsQuestDiscovered(text)) { continue; } IReadOnlyList<QuestTarget> targets = val.Targets; if (targets == null || targets.Count == 0) { continue; } QuestOverrideInfo questOverrideInfo = default(QuestOverrideInfo); questOverrideInfo.QuestName = text; questOverrideInfo.QuestTypeName = ((object)val).GetType().Name; questOverrideInfo.CompletedCount = 0; questOverrideInfo.Targets = new List<QuestTargetInfo>(); QuestOverrideInfo item = questOverrideInfo; IDictionary runtimeData = QuestDataAccess.GetRuntimeData(); if (runtimeData != null && runtimeData.Contains(text)) { object qd = runtimeData[text]; item.CompletedCount = QuestDataAccess.GetCompletedCount(qd); } for (int j = 0; j < targets.Count; j++) { QuestTarget val2 = targets[j]; int count = val2.Count; string text2 = ((object)val2.Counter)?.ToString() ?? "?"; string displayName = text2; int originalCount = count; if (originalCounts.ContainsKey(text) && j < originalCounts[text].Length) { originalCount = originalCounts[text][j]; } item.Targets.Add(new QuestTargetInfo { CounterName = text2, DisplayName = displayName, CurrentCount = count, OriginalCount = originalCount, TargetIndex = j }); } list.Add(item); } return list; } public static bool SetTargetCount(string questName, int targetIndex, int newCount) { if (!IsInitialized) { return false; } if (cachedQuests == null) { CacheQuests(); } if (cachedQuests == null || countField == null) { return false; } newCount = ClampCount(questName, targetIndex, newCount); FullQuestBase[] array = cachedQuests; foreach (FullQuestBase val in array) { if (((Object)val).name != questName) { continue; } Array targetsArray = GetTargetsArray(val); if (targetsArray == null || targetIndex >= targetsArray.Length) { return false; } object value = targetsArray.GetValue(targetIndex); countField.SetValue(value, newCount); targetsArray.SetValue(value, targetIndex); if (!overrideCounts.ContainsKey(questName)) { int[] array2 = new int[targetsArray.Length]; for (int j = 0; j < targetsArray.Length; j++) { object value2 = targetsArray.GetValue(j); array2[j] = (int)countField.GetValue(value2); } overrideCounts[questName] = array2; } else { overrideCounts[questName][targetIndex] = newCount; } QuestModSaveData saveData = QuestModPlugin.Instance.SaveData; if (saveData != null) { saveData.QuestTargetOverrides[$"{questName}:{targetIndex}"] = newCount; } QuestModPlugin.LogDebugInfo($"Set {questName} target[{targetIndex}] count to {newCount}"); if (QuestRegistry.SharedTargetQuests.TryGetValue(questName, out string value3)) { FullQuestBase[] array3 = cachedQuests; foreach (FullQuestBase val2 in array3) { if (((Object)val2).name != value3) { continue; } Array targetsArray2 = GetTargetsArray(val2); if (targetsArray2 == null || targetIndex >= targetsArray2.Length) { break; } object value4 = targetsArray2.GetValue(targetIndex); countField.SetValue(value4, newCount); targetsArray2.SetValue(value4, targetIndex); if (!overrideCounts.ContainsKey(value3)) { int[] array4 = new int[targetsArray2.Length]; for (int l = 0; l < targetsArray2.Length; l++) { object value5 = targetsArray2.GetValue(l); array4[l] = (int)countField.GetValue(value5); } overrideCounts[value3] = array4; } else { overrideCounts[value3][targetIndex] = newCount; } QuestModSaveData saveData2 = QuestModPlugin.Instance.SaveData; if (saveData2 != null) { saveData2.QuestTargetOverrides[$"{value3}:{targetIndex}"] = newCount; } break; } } return true; } return false; } public static void SetAllTargetCounts(string questName, int newCount) { if (!IsInitialized) { return; } if (cachedQuests == null) { CacheQuests(); } if (cachedQuests == null || countField == null) { return; } FullQuestBase[] array = cachedQuests; foreach (FullQuestBase val in array) { if (((Object)val).name != questName) { continue; } Array targetsArray = GetTargetsArray(val); if (targetsArray != null) { for (int j = 0; j < targetsArray.Length; j++) { object value = targetsArray.GetValue(j); countField.SetValue(value, newCount); targetsArray.SetValue(value, j); } QuestModPlugin.LogDebugInfo($"Set all {targetsArray.Length} targets for {questName} to {newCount}"); } break; } } public static void ResetToOriginal(string questName) { if (!IsInitialized || !originalCounts.ContainsKey(questName) || cachedQuests == null || countField == null) { return; } FullQuestBase[] array = cachedQuests; foreach (FullQuestBase val in array) { if (((Object)val).name != questName) { continue; } Array targetsArray = GetTargetsArray(val); if (targetsArray == null) { break; } int[] array2 = originalCounts[questName]; for (int j = 0; j < targetsArray.Length && j < array2.Length; j++) { object value = targetsArray.GetValue(j); countField.SetValue(value, array2[j]); targetsArray.SetValue(value, j); } overrideCounts.Remove(questName); QuestModSaveData saveData = QuestModPlugin.Instance.SaveData; if (saveData != null) { List<string> list = new List<string>(); foreach (string key in saveData.QuestTargetOverrides.Keys) { if (key.StartsWith(questName + ":")) { list.Add(key); } } foreach (string item in list) { saveData.QuestTargetOverrides.Remove(item); } } QuestModPlugin.LogDebugInfo("Reset " + questName + " to original counts"); break; } } public static void ResetAll() { foreach (string item in new List<string>(originalCounts.Keys)) { ResetToOriginal(item); } } public static void ApplySavedOverrides() { QuestModSaveData saveData = QuestModPlugin.Instance.SaveData; if (saveData == null || saveData.QuestTargetOverrides.Count == 0) { return; } if (cachedQuests == null) { CacheQuests(); } int num = 0; foreach (KeyValuePair<string, int> questTargetOverride in saveData.QuestTargetOverrides) { string[] array = questTargetOverride.Key.Split(':'); if (array.Length == 2) { string questName = array[0]; if (int.TryParse(array[1], out var result) && SetTargetCount(questName, result, questTargetOverride.Value)) { num++; } } } QuestModPlugin.Log.LogInfo((object)$"Applied {num} saved quest target overrides"); } public static bool[] GetChecklistStatus(string questName) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) if (!QuestRegistry.ChecklistQuests.ContainsKey(questName)) { return new bool[0]; } if (!IsInitialized || cachedQuests == null) { return new bool[QuestRegistry.ChecklistQuests[questName].Length]; } FullQuestBase[] array = cachedQuests; foreach (FullQuestBase val in array) { if (!(((Object)val).name != questName)) { IReadOnlyList<QuestTarget> targets = val.Targets; if (targets == null) { return new bool[QuestRegistry.ChecklistQuests[questName].Length]; } bool[] array2 = new bool[targets.Count]; for (int j = 0; j < targets.Count; j++) { array2[j] = targets[j].Count == 0; } return array2; } } return new bool[QuestRegistry.ChecklistQuests[questName].Length]; } public static void ToggleChecklistTarget(string questName, int index, bool done) { SetTargetCount(questName, index, (!done) ? 1 : 0); if (!done && QuestRegistry.SequentialQuests.Contains(questName)) { string[] array = QuestRegistry.ChecklistQuests[questName]; for (int i = index + 1; i < array.Length; i++) { SetTargetCount(questName, i, 1); } } } } public static class SilkSoulOverrides { public struct PointEntry { public string QuestName; public float Value; public float DefaultValue; public int EntryIndex; } private static Type groupType; private static FieldInfo f_target; private static PropertyInfo p_currentValue; private static FieldInfo f_requiredCompleteTotalGroups; private static object cachedGroup; private static bool resolved; private static FieldInfo f_entries; private static FieldInfo f_entryQuest; private static FieldInfo f_entryValue; private static Array cachedEntries; private static bool entriesResolved; private static int? thresholdOverride; private static Dictionary<string, float> pointOverrides = new Dictionary<string, float>(); public static bool HasEntries { get { if (cachedEntries != null && f_entryQuest != null) { return f_entryValue != null; } return false; } } public static bool TryResolve() { if (resolved) { return cachedGroup != null; } resolved = true; groupType = ReflectionCache.GetType("QuestCompleteTotalGroup"); if (groupType == null) { return false; } f_target = ReflectionCache.GetField(groupType, "target"); p_currentValue = ReflectionCache.GetProperty(groupType, "CurrentValueCount"); Type type = ReflectionCache.GetType("FullQuestBase"); if (type != null) { f_requiredCompleteTotalGroups = ReflectionCache.GetField(type, "requiredCompleteTotalGroups"); } Type type2 = ReflectionCache.GetType("QuestManager"); if (type2 == null) { return false; } MethodInfo methodInfo = AccessTools.Method(type2, "GetQuest", new Type[1] { typeof(string) }, (Type[])null); if (methodInfo == null) { return false; } object obj = methodInfo.Invoke(null, new object[1] { "Soul Snare Pre" }); if (obj == null) { return false; } if (f_requiredCompleteTotalGroups != null && f_requiredCompleteTotalGroups.GetValue(obj) is Array array && array.Length > 0) { cachedGroup = array.GetValue(0); QuestModPlugin.Log.LogInfo((object)"SilkSoul: resolved CompleteTotalGroup"); TryResolveEntries(); return true; } QuestModPlugin.Log.LogWarning((object)"SilkSoul: could not resolve group from Soul Snare Pre"); return false; } private static void TryResolveEntries() { if (entriesResolved || cachedGroup == null) { return; } entriesResolved = true; foreach (FieldInfo declaredField in AccessTools.GetDeclaredFields(groupType)) { if (!declaredField.FieldType.IsArray || !(declaredField.GetValue(cachedGroup) is Array array) || array.Length == 0) { continue; } Type type = array.GetValue(0).GetType(); FieldInfo fieldInfo = null; FieldInfo fieldInfo2 = null; foreach (FieldInfo declaredField2 in AccessTools.GetDeclaredFields(type)) { if (declaredField2.FieldType.Name.Contains("Quest") || declaredField2.FieldType.Name.Contains("FullQuestBase")) { fieldInfo = declaredField2; } else if (declaredField2.FieldType == typeof(float) || declaredField2.FieldType == typeof(int)) { fieldInfo2 = declaredField2; } } if (fieldInfo != null && fieldInfo2 != null) { f_entries = declaredField; f_entryQuest = fieldInfo; f_entryValue = fieldInfo2; cachedEntries = array; QuestModPlugin.Log.LogInfo((object)$"SilkSoul: resolved {array.Length} entries via field '{declaredField.Name}' (quest={fieldInfo.Name}, value={fieldInfo2.Name})"); return; } } QuestModPlugin.Log.LogInfo((object)"SilkSoul: no entry array found — per-quest overrides not available"); } public static List<PointEntry> GetPointEntries() { List<PointEntry> list = new List<PointEntry>(); if (!HasEntries) { return list; } for (int i = 0; i < cachedEntries.Length; i++) { object value = cachedEntries.GetValue(i); object? value2 = f_entryQuest.GetValue(value); Object val = (Object)((value2 is Object) ? value2 : null); if (!(val == (Object)null)) { string name = val.name; float num = ((!(f_entryValue.FieldType == typeof(float))) ? ((float)(int)f_entryValue.GetValue(value)) : ((float)f_entryValue.GetValue(value))); float defaultValue = (QuestRegistry.SilkSoulPointValues.ContainsKey(name) ? QuestRegistry.SilkSoulPointValues[name] : num); list.Add(new PointEntry { QuestName = name, Value = num, DefaultValue = defaultValue, EntryIndex = i }); } } return list; } public static bool SetPointValue(int entryIndex, float value) { if (!HasEntries || entryIndex < 0 || entryIndex >= cachedEntries.Length) { return false; } object value2 = cachedEntries.GetValue(entryIndex); object? value3 = f_entryQuest.GetValue(value2); Object val = (Object)((value3 is Object) ? value3 : null); string text = ((val != (Object)null) ? val.name : ""); object value4 = ((f_entryValue.FieldType == typeof(float)) ? ((object)value) : ((object)(int)value)); ReflectionCache.WriteToArray(cachedEntries, entryIndex, value2, f_entryValue, value4); pointOverrides[text] = value; QuestModPlugin.LogDebugInfo($"SilkSoul: set {text} value to {value}"); return true; } public static void ResetAllPointValues() { if (!HasEntries) { return; } for (int i = 0; i < cachedEntries.Length; i++) { object value = cachedEntries.GetValue(i); object? value2 = f_entryQuest.GetValue(value); Object val = (Object)((value2 is Object) ? value2 : null); if (!(val == (Object)null)) { string name = val.name; if (QuestRegistry.SilkSoulPointValues.ContainsKey(name)) { float num = QuestRegistry.SilkSoulPointValues[name]; object value3 = ((f_entryValue.FieldType == typeof(float)) ? ((object)num) : ((object)(int)num)); ReflectionCache.WriteToArray(cachedEntries, i, value, f_entryValue, value3); } } } pointOverrides.Clear(); } public static int GetThreshold() { if (thresholdOverride.HasValue) { return thresholdOverride.Value; } return ReflectionCache.Read(cachedGroup, f_target, QuestRegistry.DefaultThreshold); } public static void SetThreshold(int value) { if (value < 0) { value = 0; } thresholdOverride = value; ReflectionCache.Write(cachedGroup, f_target, value); QuestModPlugin.LogDebugInfo($"SilkSoul: threshold set to {value}"); } public static void ResetThreshold() { thresholdOverride = null; ReflectionCache.Write(cachedGroup, f_target, QuestRegistry.DefaultThreshold); } public static int GetCurrentPoints() { return ReflectionCache.Read(cachedGroup, p_currentValue, -1); } public static void Reset() { cachedGroup = null; cachedEntries = null; resolved = false; entriesResolved = false; thresholdOverride = null; pointOverrides.Clear(); } } internal static class QuestDataAccess { private static readonly FieldInfo compField; private static readonly FieldInfo rtField; private static MemberInfo hasBeenSeenMember; private static MemberInfo isAcceptedMember; private static MemberInfo isCompletedMember; private static MemberInfo wasEverCompletedMember; private static MemberInfo completedCountMember; private static bool membersResolved; static QuestDataAccess() { compField = ReflectionCache.GetField(typeof(PlayerData), "QuestCompletionData"); if (!(compField != null)) { return; } rtField = ReflectionCache.GetField(compField.FieldType, "RuntimeData"); if (rtField == null) { Type baseType = compField.FieldType.BaseType; while (baseType != null && rtField == null) { rtField = baseType.GetField("RuntimeData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); baseType = baseType.BaseType; } } } private static void ResolveMembers(Type runtimeType) { if (!membersResolved) { hasBeenSeenMember = ReflectionCache.FindMember(runtimeType, "HasBeenSeen"); isAcceptedMember = ReflectionCache.FindMember(runtimeType, "IsAccepted"); isCompletedMember = ReflectionCache.FindMember(runtimeType, "IsCompleted"); wasEverCompletedMember = ReflectionCache.FindMember(runtimeType, "WasEverCompleted"); completedCountMember = ReflectionCache.FindMember(runtimeType, "CompletedCount"); membersResolved = true; QuestModPlugin.LogDebugInfo("QuestDataAccess resolved members on runtime type " + runtimeType.FullName + ":"); QuestModPlugin.LogDebugInfo(" HasBeenSeen=" + ReflectionCache.MemberTag(hasBeenSeenMember) + ", IsAccepted=" + ReflectionCache.MemberTag(isAcceptedMember) + ", IsCompleted=" + ReflectionCache.MemberTag(isCompletedMember) + ", WasEverCompleted=" + ReflectionCache.MemberTag(wasEverCompletedMember) + ", CompletedCount=" + ReflectionCache.MemberTag(completedCountMember)); } } internal static IDictionary GetRuntimeData() { if (compField == null) { return null; } if (rtField == null) { return null; } if (PlayerData.instance == null) { return null; } object value = compField.GetValue(PlayerData.instance); if (value == null) { return null; } return rtField.GetValue(value) as IDictionary; } internal static bool IsAccepted(object qd) { if (qd == null) { return false; } if (!membersResolved) { ResolveMembers(qd.GetType()); } return (bool)(ReflectionCache.ReadMember(isAcceptedMember, qd) ?? ((object)false)); } internal static bool IsCompleted(object qd) { if (qd == null) { return false; } if (!membersResolved) { ResolveMembers(qd.GetType()); } return (bool)(ReflectionCache.ReadMember(isCompletedMember, qd) ?? ((object)false)); } internal static bool HasBeenSeen(object qd) { if (qd == null) { return false; } if (!membersResolved) { ResolveMembers(qd.GetType()); } return (bool)(ReflectionCache.ReadMember(hasBeenSeenMember, qd) ?? ((object)false)); } internal static int GetCompletedCount(object qd) { if (qd == null) { return 0; } if (!membersResolved) { ResolveMembers(qd.GetType()); } return (int)(ReflectionCache.ReadMember(completedCountMember, qd) ?? ((object)0)); } internal static object SetFields(object qd, bool seen, bool accepted, bool completed, bool wasEver) { if (qd == null) { return qd; } if (!membersResolved) { ResolveMembers(qd.GetType()); } ReflectionCache.WriteMember(hasBeenSeenMember, qd, seen); ReflectionCache.WriteMember(isAcceptedMember, qd, accepted); ReflectionCache.WriteMember(isCompletedMember, qd, completed); ReflectionCache.WriteMember(wasEverCompletedMember, qd, wasEver); return qd; } } public class QuestModSaveData { public HashSet<string> InjectedQuests { get; set; } = new HashSet<string>(); public HashSet<string> CompletedQuests { get; set; } = new HashSet<string>(); public Dictionary<string, int> QuestTargetOverrides { get; set; } = new Dictionary<string, int>(); public bool AllQuestsAvailable { get; set; } public bool AllQuestsAccepted { get; set; } } public static class QuestRegistry { public static HashSet<string> ExcludedQuests { get; private set; } = new HashSet<string>(); public static Dictionary<string, string[]> ChainRegistry { get; private set; } = new Dictionary<string, string[]>(); public static Dictionary<string, string> ChainDisplayNames { get; private set; } = new Dictionary<string, string>(); public static HashSet<string> ChainStepNames { get; private set; } = new HashSet<string>(); public static Dictionary<string, string> MutuallyExclusiveQuests { get; private set; } = new Dictionary<string, string>(); public static Dictionary<string, string> SharedTargetQuests { get; private set; } = new Dictionary<string, string>(); public static Dictionary<string, string> DisplayNames { get; private set; } = new Dictionary<string, string>(); public static Dictionary<string, string> QuestCategories { get; private set; } = new Dictionary<string, string>(); public static string[] Categories { get; private set; } = Array.Empty<string>(); public static Dictionary<string, int[]> MaxCaps { get; private set; } = new Dictionary<string, int[]>(); public static Dictionary<string, string[]> ChecklistQuests { get; private set; } = new Dictionary<string, string[]>(); public static HashSet<string> SequentialQuests { get; private set; } = new HashSet<string>(); public static HashSet<string> FarmableExcluded { get; private set; } = new HashSet<string>(); public static int DefaultThreshold { get; private set; } = 17; public static Dictionary<string, float> SilkSoulPointValues { get; private set; } = new Dictionary<string, float>(); public static string[] SilkSoulRequiredQuests { get; private set; } = Array.Empty<string>(); public static bool IsLoaded { get; private set; } public static void Load() { if (IsLoaded) { return; } Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = "QuestMod.Data.QuestCapabilities.json"; using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { QuestModPlugin.Log.LogError((object)("Failed to load embedded resource: " + text)); return; } using StreamReader streamReader = new StreamReader(stream); JObject root = JObject.Parse(streamReader.ReadToEnd()); LoadExcluded(root); LoadFarmableExclude(root); LoadMutuallyExclusive(root); LoadSharedTargets(root); LoadSilkSoul(root); LoadMaxCaps(root); LoadChecklist(root); LoadChains(root); LoadCategories(root); IsLoaded = true; QuestModPlugin.Log.LogInfo((object)$"QuestRegistry loaded: {DisplayNames.Count} quests, {ChainRegistry.Count} chains, {ChecklistQuests.Count} checklists, {MaxCaps.Count} max caps"); } private static void LoadExcluded(JObject root) { JToken obj = root["excluded"]; JArray val = (JArray)(object)((obj is JArray) ? obj : null); if (val == null) { return; } foreach (JToken item in val) { string text = Extensions.Value<string>((IEnumerable<JToken>)item); if (text != null) { ExcludedQuests.Add(text); } } } private static void LoadFarmableExclude(JObject root) { JToken obj = root["farmableExclude"]; JArray val = (JArray)(object)((obj is JArray) ? obj : null); if (val == null) { return; } foreach (JToken item in val) { string text = Extensions.Value<string>((IEnumerable<JToken>)item); if (text != null) { FarmableExcluded.Add(text); } } } private static void LoadMutuallyExclusive(JObject root) { JToken obj = root["mutuallyExclusive"]; JObject val = (JObject)(object)((obj is JObject) ? obj : null); if (val == null) { return; } foreach (KeyValuePair<string, JToken> item in val) { JToken value = item.Value; string text = ((value != null) ? Extensions.Value<string>((IEnumerable<JToken>)value) : null); if (text != null) { MutuallyExclusiveQuests[item.Key] = text; } } } private static void LoadSharedTargets(JObject root) { JToken obj = root["sharedTargets"]; JObject val = (JObject)(object)((obj is JObject) ? obj : null); if (val == null) { return; } foreach (KeyValuePair<string, JToken> item in val) { JToken value = item.Value; string text = ((value != null) ? Extensions.Value<string>((IEnumerable<JToken>)value) : null); if (text != null) { SharedTargetQuests[item.Key] = text; } } } private static void LoadSilkSoul(JObject root) { JToken obj = root["silkSoul"]; JObject val = (JObject)(object)((obj is JObject) ? obj : null); if (val == null) { return; } JToken val2 = val["defaultThreshold"]; if (val2 != null) { DefaultThreshold = Extensions.Value<int>((IEnumerable<JToken>)val2); } JToken obj2 = val["requiredQuests"]; JArray val3 = (JArray)(object)((obj2 is JArray) ? obj2 : null); if (val3 != null) { List<string> list = new List<string>(); foreach (JToken item in val3) { string text = Extensions.Value<string>((IEnumerable<JToken>)item); if (text != null) { list.Add(text); } } SilkSoulRequiredQuests = list.ToArray(); } JToken obj3 = val["pointValues"]; JObject val4 = (JObject)(object)((obj3 is JObject) ? obj3 : null); if (val4 == null) { return; } foreach (KeyValuePair<string, JToken> item2 in val4) { SilkSoulPointValues[item2.Key] = Extensions.Value<float>((IEnumerable<JToken>)item2.Value); } } private static void LoadMaxCaps(JObject root) { JToken obj = root["maxCaps"]; JObject val = (JObject)(object)((obj is JObject) ? obj : null); if (val == null) { return; } foreach (KeyValuePair<string, JToken> item in val) { JToken value = item.Value; JArray val2 = (JArray)(object)((value is JArray) ? value : null); if (val2 == null) { continue; } List<int> list = new List<int>(); foreach (JToken item2 in val2) { list.Add(Extensions.Value<int>((IEnumerable<JToken>)item2)); } MaxCaps[item.Key] = list.ToArray(); } } private static void LoadChecklist(JObject root) { JToken obj = root["checklist"]; JObject val = (JObject)(object)((obj is JObject) ? obj : null); if (val != null) { foreach (KeyValuePair<string, JToken> item in val) { JToken value = item.Value; JArray val2 = (JArray)(object)((value is JArray) ? value : null); if (val2 == null) { continue; } List<string> list = new List<string>(); foreach (JToken item2 in val2) { string text = Extensions.Value<string>((IEnumerable<JToken>)item2); if (text != null) { list.Add(text); } } ChecklistQuests[item.Key] = list.ToArray(); } } JToken obj2 = root["sequentialQuests"]; JArray val3 = (JArray)(object)((obj2 is JArray) ? obj2 : null); if (val3 == null) { return; } foreach (JToken item3 in val3) { string text2 = Extensions.Value<string>((IEnumerable<JToken>)item3); if (text2 != null) { SequentialQuests.Add(text2); } } } private static void LoadChains(JObject root) { JToken obj = root["chains"]; JObject val = (JObject)(object)((obj is JObject) ? obj : null); if (val == null) { return; } foreach (KeyValuePair<string, JToken> item in val) { string key = item.Key; JToken value = item.Value; JObject val2 = (JObject)(object)((value is JObject) ? value : null); if (val2 == null) { continue; } JToken obj2 = val2["display"]; string text = ((obj2 != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj2) : null); if (text != null) { ChainDisplayNames[key] = text; } JToken obj3 = val2["steps"]; JArray val3 = (JArray)(object)((obj3 is JArray) ? obj3 : null); if (val3 == null) { continue; } List<string> list = new List<string>(); foreach (JToken item2 in val3) { string text2 = Extensions.Value<string>((IEnumerable<JToken>)item2); if (text2 != null) { list.Add(text2); ChainStepNames.Add(text2); } } ChainRegistry[key] = list.ToArray(); } } private static void LoadCategories(JObject root) { JToken obj = root["categories"]; JObject val = (JObject)(object)((obj is JObject) ? obj : null); if (val == null) { return; } List<string> list = new List<string>(); foreach (KeyValuePair<string, JToken> item in val) { string key = item.Key; if (key == "Main Story") { continue; } list.Add(key); JToken value = item.Value; JObject val2 = (JObject)(object)((value is JObject) ? value : null); if (val2 == null) { continue; } foreach (KeyValuePair<string, JToken> item2 in val2) { string key2 = item2.Key; JToken value2 = item2.Value; LoadQuest(key2, (JObject?)(object)((value2 is JObject) ? value2 : null), key); } } JToken obj2 = val["Main Story"]; JObject val3 = (JObject)(object)((obj2 is JObject) ? obj2 : null); if (val3 != null) { foreach (KeyValuePair<string, JToken> item3 in val3) { string key3 = item3.Key; JToken value3 = item3.Value; LoadQuest(key3, (JObject?)(object)((value3 is JObject) ? value3 : null), null); } } Categories = list.ToArray(); } private static void LoadQuest(string questName, JObject? questObj, string? categoryName) { if (categoryName != null) { QuestCategories[questName] = categoryName; } if (questObj != null) { JToken obj = questObj["display"]; string text = ((obj != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj) : null); if (text != null) { DisplayNames[questName] = text; } } } } public class QuestGUI : MonoBehaviour { private bool show; private Vector2 questScroll; private Vector2 overrideScroll; private Rect rect = new Rect(20f, 20f, 580f, 580f); private int tab; private string[] tabs; private Action[] tabDrawers; private int categoryTab; private Dictionary<string, string> countInputs = new Dictionary<string, string>(); private Dictionary<string, List<QuestOverrideInfo>> cachedByCategory = new Dictionary<string, List<QuestOverrideInfo>>(); private float multiplier = 1f; private string multiplierText = "1.0"; private Vector2 checklistScroll; private List<QuestInfo> cachedQuestList; private bool questListDirty = true; private Vector2 silkSoulScroll; private string thresholdInput = ""; private Dictionary<string, string> pointInputs = new Dictionary<string, string>(); private List<ChainInfo> cachedChainList; private List<QuestInfo> undoSnapshot; private void DrawChecklistTab() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (!QuestCompletionOverrides.IsInitialized) { GUILayout.Label("Not initialized - load a save first", Array.Empty<GUILayoutOption>()); return; } checklistScroll = GUILayout.BeginScrollView(checklistScroll, Array.Empty<GUILayoutOption>()); foreach (KeyValuePair<string, string[]> checklistQuest in QuestRegistry.ChecklistQuests) { string key = checklistQuest.Key; string[] value = checklistQuest.Value; bool flag = QuestRegistry.SequentialQuests.Contains(key); bool[] checklistStatus = QuestCompletionOverrides.GetChecklistStatus(key); int num = 0; for (int i = 0; i < checklistStatus.Length; i++) { if (checklistStatus[i]) { num++; } } GUILayout.BeginVertical(GUI.skin.box, Array.Empty<GUILayoutOption>()); string text = (flag ? " (sequential)" : ""); GUILayout.Label($"{key}{text} ({num}/{value.Length})", GUI.skin.label, Array.Empty<GUILayoutOption>()); for (int j = 0; j < value.Length && j < checklistStatus.Length; j++) { bool flag2 = checklistStatus[j]; bool flag3 = true; if (flag && !flag2) { int num2 = -1; for (int k = 0; k < checklistStatus.Length; k++) { if (!checklistStatus[k]) { num2 = k; break; } } flag3 = j == num2; } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Space(12f); string text2 = (flag2 ? "■" : "□") + " " + value[j]; if (flag3) { if (GUILayout.Button(text2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) })) { int index = j; QuestCompletionOverrides.ToggleChecklistTarget(key, index, !flag2); } } else { GUI.enabled = false; GUILayout.Button(text2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); GUI.enabled = true; } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); GUILayout.Space(3f); } GUILayout.EndScrollView(); } private void Update() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = QuestModPlugin.GuiToggleKey.Value; if (!((KeyboardShortcut)(ref value)).IsDown()) { return; } show = !show; if (show) { questListDirty = true; if (tab == 1) { RefreshOverrides(); } } } private float GetGuiScale() { float value = QuestModPlugin.GuiScale.Value; if (value > 0f) { return Mathf.Round(value * 20f) / 20f; } float dpi = Screen.dpi; if (dpi <= 0f) { return 1f; } return Mathf.Round(Mathf.Clamp(dpi / 96f, 0.5f, 3f) * 20f) / 20f; } private void OnGUI() { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) if (show) { float guiScale = GetGuiScale(); Matrix4x4 matrix = GUI.matrix; GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(guiScale, guiScale, 1f)); GUI.skin = QuestGUISkin.Get(); KeyboardShortcut value = QuestModPlugin.GuiToggleKey.Value; KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey; string text = ((object)(KeyCode)(ref mainKey)).ToString(); Version version = typeof(QuestModPlugin).Assembly.GetName().Version; rect = GUI.Window(12345, rect, new WindowFunction(Draw), $"Quest Manager ({text}) v{version.Major}.{version.Minor}.{version.Build}"); GUI.matrix = matrix; } } private void RefreshOverrides() { cachedByCategory.Clear(); string[] categories = QuestRegistry.Categories; foreach (string text in categories) { cachedByCategory[text] = QuestCompletionOverrides.GetQuestsByCategory(text); } } private void Draw(int id) { //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0123: 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_0164: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0182: 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) RebuildTabs(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); for (int i = 0; i < tabs.Length; i++) { GUIStyle val = ((i == tab) ? GUI.skin.GetStyle("ToolbarButtonActive") : GUI.skin.GetStyle("ToolbarButton")); if (GUILayout.Button(tabs[i], val, Array.Empty<GUILayoutOption>())) { if (i != tab && tabs[i] == "Targets") { RefreshOverrides(); } tab = i; } } GUILayout.EndHorizontal(); if (tab >= tabs.Length) { tab = 0; } GUILayout.Space(6f); tabDrawers[tab](); if (!string.IsNullOrEmpty(GUI.tooltip)) { Vector2 mousePosition = Event.current.mousePosition; GUIContent val2 = new GUIContent(GUI.tooltip); Vector2 val3 = QuestGUISkin.TooltipStyle.CalcSize(val2); val3.x = Mathf.Min(val3.x, 280f); val3.y = QuestGUISkin.TooltipStyle.CalcHeight(val2, val3.x); float num = Mathf.Min(mousePosition.x + 12f, ((Rect)(ref rect)).width - val3.x - 10f); float num2 = Mathf.Min(mousePosition.y + 18f, ((Rect)(ref rect)).height - val3.y - 10f); GUI.Label(new Rect(num, num2, val3.x, val3.y), val2, QuestGUISkin.TooltipStyle); } GUI.DragWindow(); } private void RebuildTabs() { List<string> list = new List<string> { "Quests", "Targets", "Checklist" }; List<Action> list2 = new List<Action> { DrawQuestsTab, DrawCompletionTab, DrawChecklistTab }; if (QuestModPlugin.EnableSilkSoulTab.Value) { list.Add("Silk & Soul"); list2.Add(DrawSilkSoulTab); } list.Add("⚙ Tools"); list2.Add(DrawToolsTab); tabs = list.ToArray(); tabDrawers = list2.ToArray(); } private void DrawQuestsTab() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Expected O, but got Unknown //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Expected O, but got Unknown if (questListDirty) { cachedQuestList = QuestAcceptance.GetQuestList(); cachedChainList = QuestAcceptance.GetChainList(); questListDirty = false; } questScroll = GUILayout.BeginScrollView(questScroll, Array.Empty<GUILayoutOption>()); if (cachedChainList != null) { GUILayout.Label("Chains", QuestGUISkin.SectionHeader, Array.Empty<GUILayoutOption>()); foreach (ChainInfo cachedChain in cachedChainList) { GUILayout.BeginVertical(GUI.skin.box, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); string text; string text2; if (cachedChain.IsFullyComplete) { text = "Complete"; text2 = "✓"; } else if (cachedChain.CurrentStep < 0) { text = "Not started"; text2 = "○"; } else { string displayName = QuestAcceptance.GetDisplayName(cachedChain.Steps[cachedChain.CurrentStep]); text = $"Step {cachedChain.CurrentStep + 1}/{cachedChain.TotalSteps}: {displayName}"; text2 = "◐"; } string text3 = (QuestModPlugin.ShowQuestDisplayNames.Value ? cachedChain.DisplayName : cachedChain.ChainName); GUILayout.Label(new GUIContent(text2 + " " + text3, cachedChain.ChainName), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) }); GUILayout.Label(text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(180f) }); GUILayout.FlexibleSpace(); GUI.enabled = cachedChain.CurrentStep >= 0; if (GUILayout.Button("◀", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(25f) })) { QuestAcceptance.RewindChain(cachedChain.ChainName); questListDirty = true; } GUI.enabled = !cachedChain.IsFullyComplete; if (GUILayout.Button("▶", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(25f) })) { QuestAcceptance.AdvanceChain(cachedChain.ChainName); questListDirty = true; } GUI.enabled = true; GUILayout.EndHorizontal(); GUILayout.EndVertical(); } } if (cachedQuestList != null) { GUILayout.Space(6f); GUILayout.Label("Quests", QuestGUISkin.SectionHeader, Array.Empty<GUILayoutOption>()); foreach (QuestInfo cachedQuest in cachedQuestList) { if (!QuestAcceptance.IsChainStep(cachedQuest.Name)) { string obj = (cachedQuest.IsCompleted ? "✓" : (cachedQuest.IsAccepted ? "◐" : "○")); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); string text4 = (QuestModPlugin.ShowQuestDisplayNames.Value ? cachedQuest.DisplayName : cachedQuest.Name); GUILayout.Label(new GUIContent(obj + " " + text4, cachedQuest.Name), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(260f) }); GUILayout.FlexibleSpace(); if (!cachedQuest.IsAccepted && GUILayout.Button("Accept", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) })) { QuestAcceptance.AcceptQuest(cachedQuest.Name); questListDirty = true; } if (cachedQuest.IsAccepted && !cachedQuest.IsCompleted && GUILayout.Button("Drop", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(45f) })) { QuestAcceptance.UnacceptQuest(cachedQuest.Name); questListDirty = true; } if (cachedQuest.IsAccepted && !cachedQuest.IsCompleted && GUILayout.Button("Complete", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(65f) })) { QuestAcceptance.CompleteQuest(cachedQuest.Name); questListDirty = true; } if (cachedQuest.IsCompleted && GUILayout.Button("Undo", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) })) { QuestAcceptance.UncompleteQuest(cachedQuest.Name); questListDirty = true; } GUILayout.EndHorizontal(); } } } GUILayout.EndScrollView(); } private void DrawSilkSoulTab() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_038e: Unknown result type (might be due to invalid IL or missing references) //IL_05df: Unknown result type (might be due to invalid IL or missing references) //IL_05e4: Unknown result type (might be due to invalid IL or missing references) //IL_05f5: Unknown result type (might be due to invalid IL or missing references) //IL_0641: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Unknown result type (might be due to invalid IL or missing references) //IL_06a3: Unknown result type (might be due to invalid IL or missing references) //IL_06a8: Unknown result type (might be due to invalid IL or missing references) //IL_06b4: Unknown result type (might be due to invalid IL or missing references) //IL_06ad: Unknown result type (might be due to invalid IL or missing references) //IL_04c2: Unknown result type (might be due to invalid IL or missing references) //IL_04fa: Unknown result type (might be due to invalid IL or missing references) //IL_0773: Unknown result type (might be due to invalid IL or missing references) //IL_0778: Unknown result type (might be due to invalid IL or missing references) //IL_06ed: Unknown result type (might be due to invalid IL or missing references) //IL_0784: Unknown result type (might be due to invalid IL or missing references) //IL_077d: Unknown result type (might be due to invalid IL or missing references) //IL_0815: Unknown result type (might be due to invalid IL or missing references) if (!SilkSoulOverrides.TryResolve()) { GUILayout.Label("Silk & Soul data not available (load a save first)", Array.Empty<GUILayoutOption>()); return; } int currentPoints = SilkSoulOverrides.GetCurrentPoints(); int threshold = SilkSoulOverrides.GetThreshold(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("Quest Points:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }); Color color = GUI.color; GUI.color = ((currentPoints >= threshold) ? Color.green : Color.white); GUILayout.Label($"{currentPoints} / {threshold}", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }); GUI.color = color; GUILayout.EndHorizontal(); GUILayout.Space(3f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(new GUIContent("Threshold:", "Number of points needed to unlock Silk & Soul quest"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }); if (GUILayout.Button("−", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(22f) })) { SilkSoulOverrides.SetThreshold(threshold - 1); thresholdInput = (threshold - 1).ToString(); } if (thresholdInput == "") { thresholdInput = threshold.ToString(); } thresholdInput = GUILayout.TextField(thresholdInput, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) }); if (GUILayout.Button("+", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(22f) })) { SilkSoulOverrides.SetThreshold(threshold + 1); thresholdInput = (threshold + 1).ToString(); } if (GUILayout.Button("Set", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(32f) }) && int.TryParse(thresholdInput, out var result)) { SilkSoulOverrides.SetThreshold(result); } if (GUILayout.Button("Reset", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(48f) })) { SilkSoulOverrides.ResetThreshold(); thresholdInput = QuestRegistry.DefaultThreshold.ToString(); } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); if (threshold != QuestRegistry.DefaultThreshold) { GUILayout.Label($" (default: {QuestRegistry.DefaultThreshold})", Array.Empty<GUILayoutOption>()); } GUILayout.Space(4f); if (SilkSoulOverrides.HasEntries) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Reset All Values", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) })) { SilkSoulOverrides.ResetAllPointValues(); pointInputs.Clear(); } if (GUILayout.Button("Set All to 0", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) })) { foreach (SilkSoulOverrides.PointEntry pointEntry in SilkSoulOverrides.GetPointEntries()) { SilkSoulOverrides.SetPointValue(pointEntry.EntryIndex, 0f); pointInputs[pointEntry.QuestName] = "0"; } } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); } GUILayout.Space(5f); silkSoulScroll = GUILayout.BeginScrollView(silkSoulScroll, Array.Empty<GUILayoutOption>()); IDictionary runtimeData = QuestDataAccess.GetRuntimeData(); if (SilkSoulOverrides.HasEntries) { List<SilkSoulOverrides.PointEntry> pointEntries = SilkSoulOverrides.GetPointEntries(); GUILayout.Label("Quest Point Values (editable)", QuestGUISkin.SectionHeader, Array.Empty<GUILayoutOption>()); foreach (SilkSoulOverrides.PointEntry item in pointEntries) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); bool num = runtimeData != null && runtimeData.Contains(item.QuestName) && QuestDataAccess.IsCompleted(runtimeData[item.QuestName]); Color color2 = GUI.color; GUI.color = (num ? Color.green : Color.white); string displayName = QuestAcceptance.GetDisplayName(item.QuestName); GUILayout.Label(num ? "✓" : "✗", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(14f) }); GUILayout.Label(displayName, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) }); GUI.color = color2; string questName = item.QuestName; if (!pointInputs.ContainsKey(questName)) { pointInputs[questName] = item.Value.ToString("0.##"); } pointInputs[questName] = GUILayout.TextField(pointInputs[questName], (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) }); if (GUILayout.Button("Set", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(32f) }) && float.TryParse(pointInputs[questName], out var result2)) { SilkSoulOverrides.SetPointValue(item.EntryIndex, result2); } if (!(Math.Abs(item.Value - item.DefaultValue) < 0.01f)) { GUI.color = Color.yellow; GUILayout.Label($"({item.DefaultValue:0.##})", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) }); GUI.color = color2; } GUILayout.EndHorizontal(); } } else { int num2 = 0; int num3 = QuestRegistry.SilkSoulRequiredQuests.Length; string[] silkSoulRequiredQuests = QuestRegistry.SilkSoulRequiredQuests; foreach (string key in silkSoulRequiredQuests) { if (runtimeData != null && runtimeData.Contains(key) && QuestDataAccess.IsCompleted(runtimeData[key])) { num2++; } } int num4 = 0; int count = QuestRegistry.SilkSoulPointValues.Count; foreach (KeyValuePair<string, float> silkSoulPointValue in QuestRegistry.SilkSoulPointValues) { if (runtimeData != null && runtimeData.Contains(silkSoulPointValue.Key) && QuestDataAccess.IsCompleted(runtimeData[silkSoulPointValue.Key])) { num4++; } } Color color3 = GUI.color; GUI.color = new Color(0.7f, 0.8f, 0.95f); GUILayout.Label($"Required: {num2}/{num3} | Optional: {num4}/{count}", Array.Empty<GUILayoutOption>()); GUI.color = color3; GUILayout.Space(3f); GUILayout.Label("Required Quests", QuestGUISkin.SectionHeader, Array.Empty<GUILayoutOption>()); silkSoulRequiredQuests = QuestRegistry.SilkSoulRequiredQuests; foreach (string text in silkSoulRequiredQuests) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); bool num5 = runtimeData != null && runtimeData.Contains(text) && QuestDataAccess.IsCompleted(runtimeData[text]); Color color4 = GUI.color; GUI.color = (num5 ? Color.green : Color.white); string displayName2 = QuestAcceptance.GetDisplayName(text); GUILayout.Label(num5 ? (" ✓ " + displayName2) : (" ✗ " + displayName2), Array.Empty<GUILayoutOption>()); GUI.color = color4; GUILayout.EndHorizontal(); } GUILayout.Space(5f); GUILayout.Label("Optional Quests (contribute points)", QuestGUISkin.SectionHeader, Array.Empty<GUILayoutOption>()); foreach (KeyValuePair<string, float> silkSoulPointValue2 in QuestRegistry.SilkSoulPointValues) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); bool num6 = runtimeData != null && runtimeData.Contains(silkSoulPointValue2.Key) && QuestDataAccess.IsCompleted(runtimeData[silkSoulPointValue2.Key]); Color color5 = GUI.color; GUI.color = (num6 ? Color.green : Color.white); string displayName3 = QuestAcceptance.GetDisplayName(silkSoulPointValue2.Key); string text2 = ((silkSoulPointValue2.Value == 1f) ? "1 pt" : "0.5 pt"); GUILayout.Label(num6 ? (" ✓ " + displayName3) : (" ✗ " + displayName3), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(250f) }); GUILayout.Label("[" + text2 + "]", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }); GUI.color = color5; GUILayout.EndHorizontal(); } } GUILayout.EndScrollView(); } private void DrawCompletionTab() { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Expected O, but got Unknown //IL_0454: Unknown result type (might be due to invalid IL or missing references) //IL_045e: Unknown result type (might be due to invalid IL or missing references) //IL_0463: 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_0421: Unknown result type (might be due to invalid IL or missing references) //IL_0518: Unknown result type (might be due to invalid IL or missing references) //IL_0535: Expected O, but got Unknown //IL_0535: Unknown result type (might be due to invalid IL or missing references) //IL_053a: Unknown result type (might be due to invalid IL or missing references) //IL_054e: Unknown result type (might be due to invalid IL or missing references) //IL_0547: Unknown result type (might be due to invalid IL or missing references) //IL_0572: Unknown result type (might be due to invalid IL or missing references) bool value = QuestModPlugin.EnableCompletionOverrides.Value; if (!QuestCompletionOverrides.IsInitialized) { GUILayout.Label("Not initialized - load a save first", Array.Empty<GUILayoutOption>()); return; } int num = categoryTab; categoryTab = GUILayout.Toolbar(categoryTab, QuestRegistry.Categories, Array.Empty<GUILayoutOption>()); if (categoryTab != num) { multiplierText = multiplier.ToString("0.0"); } GUILayout.Space(4f); GUI.enabled = value; GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(new GUIContent("Multiplier:", "Scale all targets in this category"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(68f) }); multiplier = GUILayout.HorizontalSlider(multiplier, 0f, 1f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }); multiplier = Mathf.Round(multiplier * 20f) / 20f; string text = multiplier.ToString("0.0"); if (text != multiplierText) { multiplierText = text; } multiplierText = GUILayout.TextField(multiplierText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(35f) }); if (GUILayout.Button("Apply", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(48f) }) && float.TryParse(multiplierText, out var result)) { multiplier = result; ApplyMultiplier(result); } if (GUILayout.Button("1x", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(28f) })) { multiplier = 1f; multiplierText = "1.0"; ApplyMultiplier(1f); } if (GUILayout.Button(new GUIContent("R", "Reset this category to original values"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(24f) })) { ResetCategory(); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("Presets:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }); if (GUILayout.Button("Set to 1", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) })) { QuestCompletionOverrides.ApplyPresetAll("set1"); countInputs.Clear(); RefreshOverrides(); } if (GUILayout.Button("QoL Half", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(65f) })) { QuestCompletionOverrides.ApplyPresetAll("qol"); countInputs.Clear(); RefreshOverrides(); } if (GUILayout.Button("Farmable", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(65f) })) { QuestCompletionOverrides.ApplyPresetAll("farmable"); countInputs.Clear(); RefreshOverrides(); } if (GUILayout.Button("Default", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) })) { QuestCompletionOverrides.ApplyPresetAll("default"); countInputs.Clear(); RefreshOverrides(); } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUI.enabled = true; if (!value) { GUILayout.Label("Overrides disabled in config — counts are read-only", Array.Empty<GUILayoutOption>()); } else if (QuestModPlugin.DevRemoveLimits.Value) { GUILayout.Label("⚠ DevRemoveLimits — no count limits (may break quest state)", Array.Empty<GUILayoutOption>()); } GUILayout.Space(4f); string key = QuestRegistry.Categories[categoryTab]; if (!cachedByCategory.ContainsKey(key) || cachedByCategory[key].Count == 0) { GUILayout.Label("No quests found in this category.", Array.Empty<GUILayoutOption>()); return; } int num2 = 0; int num3 = 0; foreach (QuestOverrideInfo item in cachedByCategory[key]) { foreach (QuestTargetInfo target in item.Targets) { num3++; if (target.CurrentCount != target.OriginalCount) { num2++; } } } if (num2 > 0) { Color color = GUI.color; GUI.color = new Color(1f, 0.85f, 0.4f); GUILayout.Label($"{num2} of {num3} targets modified", Array.Empty<GUILayoutOption>()); GUI.color = color; } overrideScroll = GUILayout.BeginScrollView(overrideScroll, Array.Empty<GUILayoutOption>()); bool flag = false; foreach (QuestOverrideInfo item2 in cachedByCategory[key]) { GUILayout.BeginVertical(GUI.skin.box, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); int num4 = 0; foreach (QuestTargetInfo target2 in item2.Targets) { num4 += target2.CurrentCount; } string text2 = $"[{item2.CompletedCount}/{num4}]"; GUILayout.Label(new GUIContent(item2.QuestName, item2.QuestName), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(240f) }); Color color2 = GUI.color; GUI.color = ((item2.CompletedCount >= num4) ? Color.green : Color.white); GUILayout.Label(text2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }); GUI.color = color2; GUILayout.FlexibleSpace(); if (value && GUILayout.Button("Reset", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(48f) })) { QuestCompletionOverrides.ResetToOriginal(item2.QuestName); foreach (QuestTargetInfo target3 in item2.Targets) { string key2 = $"{item2.QuestName}_{target3.TargetIndex}"; countInputs.Remove(key2); } flag = true; } GUILayout.EndHorizontal(); foreach (QuestTargetInfo target4 in item2.Targets) { string key3 = $"{item2.QuestName}_{target4.TargetIndex}"; if (!countInputs.ContainsKey(key3)) { countInputs[key3] = target4.CurrentCount.ToString(); } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Space(15f); string text3 = ((target4.CurrentCount != target4.OriginalCount) ? $"{target4.DisplayName} ({target4.OriginalCount}→{target4.CurrentCount})" : $"{target4.DisplayName} ({target4.OriginalCount})"); int maxCap = QuestCompletionOverrides.GetMaxCap(item2.QuestName, target4.TargetIndex); if (maxCap > 0) { text3 += $" [max {maxCap}]"; } GUILayout.Label(text3, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(210f) }); if (!value) { GUILayout.EndHorizontal(); continue; } if (item2.Targets.Count > 1) { bool flag2 = target4.CurrentCount > 0; bool flag3 = GUILayout.Toggle(flag2, "", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(18f) }); if (flag3 != flag2) { int newCount = (flag3 ? target4.OriginalCount : 0); QuestCompletionOverrides.SetTargetCount(item2.QuestName, target4.TargetIndex, newCount); countInputs[key3] = newCount.ToString(); flag = true; } } if (GUILayout.Button("−", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(22f) })) { int newCount2 = QuestCompletionOverrides.ClampCount(item2.QuestName, target4.TargetIndex, target4.CurrentCount - 1); QuestCompletionOverrides.SetTargetCount(item2.QuestName, target4.TargetIndex, newCount2); countInputs[key3] = newCount2.ToString(); flag = true; } countInputs[key3] = GUILayout.TextField(countInputs[key3], (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(38f) }); if (GUILayout.Button("+", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(22f) })) { int newCount3 = QuestCompletionOverrides.ClampCount(item2.QuestName, target4.TargetIndex, target4.CurrentCount + 1); QuestCompletionOverrides.SetTargetCount(item2.QuestName, target4.TargetIndex, newCount3); countInputs[key3] = newCount3.ToString(); flag = true; } if (GUILayout.Button("Set", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(32f) }) && int.TryParse(countInputs[key3], out var result2)) { QuestCompletionOverrides.SetTargetCount(item2.QuestName, target4.TargetIndex, result2); flag = true; } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); GUILayout.Space(2f); } GUILayout.EndScrollView(); if (flag) { RefreshOverrides(); } } private void ApplyMultiplier(float mult) { string key = QuestRegistry.Categories[categoryTab]; if (!cachedByCategory.ContainsKey(key)) { return; } foreach (QuestOverrideInfo item in cachedByCategory[key]) { foreach (QuestTargetInfo target in item.Targets) { int num = Mathf.Max(1, Mathf.RoundToInt((float)target.OriginalCount * mult)); int newCount = ((num <= 1) ? 1 : ((num % 2 == 0) ? num : (num + 1))); string key2 = $"{item.QuestName}_{target.TargetIndex}"; countInputs[key2] = newCount.ToString(); QuestCompletionOverrides.SetTargetCount(item.QuestName, target.TargetIndex, newCount); } } RefreshOverrides(); } private void ResetCategory() { string key = QuestRegistry.Categories[categoryTab]; if (!cachedByCategory.ContainsKey(key)) { return; } foreach (QuestOverrideInfo item in cachedByCategory[key]) { QuestCompletionOverrides.ResetToOriginal(item.QuestName); foreach (QuestTargetInfo target in item.Targets) { string key2 = $"{item.QuestName}_{target.TargetIndex}"; countInputs.Remove(key2); } } multiplier = 1f; multiplierText = "1.0"; RefreshOverrides(); } private void SnapshotBeforeMassOp() { undoSnapshot = QuestAcceptance.GetQuestList(); } private void UndoMassOp() { if (undoSnapshot == null) { return; } foreach (QuestInfo item in undoSnapshot) { if (item.IsCompleted) { QuestAcceptance.CompleteQuest(item.Name); } else { QuestAcceptance.UncompleteQuest(item.Name); } if (item.IsAccepted) { QuestAcceptance.AcceptQuest(item.Name); } else { QuestAcceptance.UnacceptQuest(item.Name); } } undoSnapshot = null; questListDirty = true; QuestModPlugin.LogDebugInfo("Undid last mass operation"); } private void DrawToolsTab() { //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Expected O, but got Unknown //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Expected O, but got Unknown GUILayout.Label("Mass Operations", QuestGUISkin.SectionHeader, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Accept Available", Array.Empty<GUILayoutOption>())) { SnapshotBeforeMassOp(); QuestAcceptance.AcceptAllQuests(); questListDirty = true; } if (GUILayout.Button("Complete Available", Array.Empty<GUILayoutOption>())) { SnapshotBeforeMassOp(); QuestAcceptance.CompleteAllQuests(); questListDirty = true; } GUILayout.EndHorizontal(); if (QuestModPlugin.DevForceOperations.Value) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Accept ALL (force)", Array.Empty<GUILayoutOption>())) { SnapshotBeforeMassOp(); QuestAcceptance.ForceAcceptAllQuests(); questListDirty = true; } if (GUILayout.Button("Complete ALL (force)", Array.Empty<GUILayoutOption>())) { SnapshotBeforeMassOp(); QuestAcceptance.ForceCompleteAllQuests(); questListDirty = true; } GUILayout.EndHorizontal(); } GUI.enabled = undoSnapshot != null; if (GUILayout.Button("Undo Last Mass Operation", Array.Empty<GUILayoutOption>())) { UndoMassOp(); } GUI.enabled = true; GUILayout.Space(10f); GUILayout.Label("Mode (this save)", QuestGUISkin.SectionHeader, Array.Empty<GUILayoutOption>()); bool allQuestsAccepted = QuestModPlugin.AllQuestsAccepted; bool flag = GUILayout.Toggle(allQuestsAccepted, new GUIContent("All Quests Accepted", "Auto-inject and accept every quest each scene load. Forces Available + Wishboards on."), Array.Empty<GUILayoutOption>()); if (flag != allQuestsAccepted) { QuestModPlugin.SetAllQuestsAccepted(flag); } GUI.enabled = !allQuestsAccepted; bool allQuestsAvailable = QuestModPlugin.AllQuestsAvailable; bool flag2 = GUILayout.Toggle(allQuestsAvailable, new GUIContent(" All Quests Available", "Bypasses act/chain prerequisites for this save."), Array.Empty<GUILayoutOption>()); if (flag2 != allQuestsAvailable) { QuestModPlugin.SetAllQuestsAvailable(flag2); } GUI.enabled = true; GUILayout.Space(10f); GUILayout.Label("Quick Config", QuestGUISkin.SectionHeader, Array.Empty<GUILayoutOption>()); bool value = QuestModPlugin.OnlyDiscoveredQuests.Value; bool flag3 = GUILayout.Toggle(value, new GUIContent("Only Discovered Quests", "Only show quests the player has encountered"), Array.Empty<GUILayoutOption>()); if (flag3 != value) { QuestModPlugin.OnlyDiscoveredQuests.Value = flag3; } bool value2 = QuestModPlugin.QuestItemInvincible.Value; bool flag4 = GUILayout.Toggle(value2, "Quest Item Invincible", Array.Empty<GUILayoutOption>()); if (flag4 != value2) { QuestModPlugin.QuestItemInvincible.Value = flag4; } bool value3 = QuestModPlugin.ShowQuestDisplayNames.Value; bool flag5 = GUILayout.Toggle(value3, "Show Display Names", Array.Empty<GUILayoutOption>()); if (flag5 != value3) { QuestModPlugin.ShowQuestDisplayNames.Value = flag5; } GUILayout.Space(8f); if (PlayerData.instance != null) { bool blackThreadWorld = PlayerData.instance.blackThreadWorld; bool flag6 = GUILayout.Toggle(blackThreadWorld, "Act 3 (Black Thread World)", Array.Empty<GUILayoutOption>()); if (flag6 != blackThreadWorld) { PlayerData.instance.blackThreadWorld = flag6; } } } } public static class QuestGUISkin { private static GUISkin skin; private static GUIStyle sectionHeader; private static GUIStyle tooltipStyle; private static Texture2D darkTex; private static Texture2D midTex; private static Texture2D lightTex; private static Texture2D accentTex; private static Texture2D hoverTex; private static Texture2D activeTex; private static Texture2D fieldTex; private static Texture2D greenTex; public static GUIStyle SectionHeader => sectionHeader; public static GUIStyle TooltipStyle => tooltipStyle; private static Texture2D MakeTex(Color col) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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) Texture2D val = new Texture2D(2, 2); val.SetPixels((Color[])(object)new Color[4] { col, col, col, col }); val.Apply(); ((Object)val).hideFlags = (HideFlags)52; return val; } public static GUISkin Get() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0196: 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_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Expected O, but got Unknown //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Expected O, but got Unknown //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Expected O, but got Unknown //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Expected O, but got Unknown //IL_0260: Expected O, but got Unknown //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0274: 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_028a: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Expected O, but got Unknown //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Expected O, but got Unknown //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_0330: Expected O, but got Unknown //IL_0335: Expected O, but got Unknown //IL_0344: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_0359: 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_0378: Unknown result type (might be due to invalid IL or missing references) //IL_0380: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Expected O, but got Unknown //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03a5: Expected O, but got Unknown //IL_03a5: Unknown result type (might be due to invalid IL or missing references) //IL_03aa: Unknown result type (might be due to invalid IL or missing references) //IL_03b4: Expected O, but got Unknown //IL_03b4: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Expected O, but got Unknown //IL_03cf: Unknown result type (might be due to invalid IL or missing references) //IL_03d4: Unknown result type (might be due to invalid IL or missing references) //IL_03e9: Unknown result type (might be due to invalid IL or missing references) //IL_03f3: Unknown result type (might be due to invalid IL or missing references) //IL_0408: 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) //IL_0418: Unknown result type (might be due to invalid IL or missing references) //IL_0422: Unknown result type (might be due to invalid IL or missing references) //IL_0437: Unknown result type (might be due to invalid IL or missing references) //IL_0441: Unknown result type (might be due to invalid IL or missing references) //IL_0449: Unknown result type (might be due to invalid IL or missing references) //IL_044f: Unknown result type (might be due to invalid IL or missing references) //IL_0459: Expected O, but got Unknown //IL_045e: Expected O, but got Unknown //IL_046d: Unknown result type (might be due to invalid IL or missing references) //IL_0472: Unknown result type (might be due to invalid IL or missing references) //IL_0482: Unknown result type (might be due to invalid IL or missing references) //IL_0488: Unknown result type (might be due to invalid IL or missing references) //IL_0492: Unknown result type (might be due to invalid IL or missing references) //IL_04a2: Unknown result type (might be due to invalid IL or missing references) //IL_04a8: Unknown result type (might be due to invalid IL or missing references) //IL_04b2: Unknown result type (might be due to invalid IL or missing references) //IL_04c2: Unknown result type (might be due to invalid IL or missing references) //IL_04c8: Unknown result type (might be due to invalid IL or missing references) //IL_04d2: Unknown result type (might be due to invalid IL or missing references) //IL_04da: Unknown result type (might be due to invalid IL or missing references) //IL_04df: Unknown result type (might be due to invalid IL or missing references) //IL_04e9: Expected O, but got Unknown //IL_04e9: Unknown result type (might be due to invalid IL or missing references) //IL_04ee: Unknown result type (might be due to invalid IL or missing references) //IL_04f8: Expected O, but got Unknown //IL_04fd: Expected O, but got Unknown //IL_0507: Unknown result type (might be due to invalid IL or missing references) //IL_050c: Unknown result type (might be due to invalid IL or missing references) //IL_051c: Unknown result type (might be due to invalid IL or missing references) //IL_0531: Unknown result type (might be due to invalid IL or missing references) //IL_053b: Unknown result type (might be due to invalid IL or missing references) //IL_054b: Unknown result type (might be due to invalid IL or missing references) //IL_0551: