using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Jonathan's Task List")]
[assembly: AssemblyDescription("Always-visible mission objectives for Burglin' Gnomes.")]
[assembly: AssemblyCompany("Daniel Rose")]
[assembly: AssemblyProduct("Jonathan's Task List")]
[assembly: ComVisible(false)]
[assembly: AssemblyFileVersion("0.1.42.0")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyVersion("0.1.42.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[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]
[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;
}
}
}
namespace JonathansTaskList
{
[BepInPlugin("jonathan.burglignomes.tasklist", "Jonathan's Task List", "0.1.42")]
public sealed class Plugin : BaseUnityPlugin
{
private readonly struct TaskState
{
public int Current { get; }
public int Max { get; }
public bool Completed { get; }
public TaskState(int current, int max, bool completed)
{
Current = current;
Max = max;
Completed = completed || (max > 0 && current >= max);
}
}
public const string PluginGuid = "jonathan.burglignomes.tasklist";
public const string PluginName = "Jonathan's Task List";
public const string PluginVersion = "0.1.42";
private const int ObjectiveFontSize = 14;
private const int MaxObjectiveRows = 5;
private const float AutoStateRefreshInterval = 0.5f;
private const float DefaultTopRightMargin = 24f;
private const float DefaultTopMargin = 32f;
private const string CompletionMarker = "✓";
private ConfigEntry<KeyCode> toggleKey;
private ConfigEntry<KeyCode> secondaryToggleKey;
private ConfigEntry<KeyCode> alternateToggleKey;
private ConfigEntry<float> panelX;
private ConfigEntry<float> panelY;
private ConfigEntry<float> panelScale;
private ConfigEntry<int> panelPlacementVersion;
private ConfigEntry<bool> autoCaptureWhileTabHeld;
private ConfigEntry<bool> lockPanel;
private readonly List<string> capturedObjectives = new List<string>();
private Rect panelRect;
private bool showPanel;
private bool stylesReady;
private bool isDragging;
private Vector2 dragOffset;
private GUIStyle paperStyle;
private GUIStyle titleStyle;
private GUIStyle objectiveStyle;
private GUIStyle smallStyle;
private Texture2D paperTexture;
private Font? bahnschrift;
private float lastAutoCaptureTime;
private float lastStateRefreshTime;
private bool firstGuiLogged;
private bool inputSystemLogged;
private bool rawCaptureLogged;
private string lastRawCaptureSignature = string.Empty;
private string lastKeptCaptureSignature = string.Empty;
private readonly Dictionary<KeyCode, bool> previousInputSystemKeyStates = new Dictionary<KeyCode, bool>();
private string lastSceneName = string.Empty;
private void Awake()
{
//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Expected O, but got Unknown
//IL_015d: Unknown result type (might be due to invalid IL or missing references)
//IL_0167: Invalid comparison between Unknown and I4
//IL_01a7: 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_01da: Unknown result type (might be due to invalid IL or missing references)
//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
//IL_0200: Unknown result type (might be due to invalid IL or missing references)
toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Hotkeys", "ToggleTaskList", (KeyCode)96, "Captures visible objectives and toggles Jonathan's Task List.");
secondaryToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Hotkeys", "SecondaryToggleTaskList", (KeyCode)290, "Also captures visible objectives and toggles Jonathan's Task List.");
alternateToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Hotkeys", "AlternateToggleTaskList", (KeyCode)277, "Alternate key to capture visible objectives and toggle Jonathan's Task List.");
panelX = ((BaseUnityPlugin)this).Config.Bind<float>("Panel", "X", 100f, "Panel X position.");
panelY = ((BaseUnityPlugin)this).Config.Bind<float>("Panel", "Y", 32f, "Panel Y position.");
panelScale = ((BaseUnityPlugin)this).Config.Bind<float>("Panel", "Scale", 1f, new ConfigDescription("Panel scale.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.6f, 2.5f), Array.Empty<object>()));
panelPlacementVersion = ((BaseUnityPlugin)this).Config.Bind<int>("Panel", "PlacementVersion", 0, "Tracks default panel placement migrations.");
lockPanel = ((BaseUnityPlugin)this).Config.Bind<bool>("Panel", "LockPanel", false, "Prevents dragging the task list panel.");
autoCaptureWhileTabHeld = ((BaseUnityPlugin)this).Config.Bind<bool>("Capture", "AutoCaptureWhileTabHeld", true, "Updates the task list while TAB is held and the game's objectives are visible.");
if ((int)toggleKey.Value == 289)
{
toggleKey.Value = (KeyCode)96;
((BaseUnityPlugin)this).Logger.LogInfo((object)"Migrated task-list hotkey from F8 to BackQuote because F8 conflicts with many mods.");
}
panelRect = new Rect(panelX.Value, panelY.Value, 270f, 190f);
((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded. Toggle={2}/{3}/{4}", "Jonathan's Task List", "0.1.42", toggleKey.Value, secondaryToggleKey.Value, alternateToggleKey.Value));
}
private void Start()
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"Jonathan's Task List is active. Listening through legacy input, Unity GUI key events, and Unity Input System.");
}
private void Update()
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Expected I4, but got Unknown
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected I4, but got Unknown
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Expected I4, but got Unknown
HideOnMainMenu();
if (AnyKeyDown((KeyCode)(int)toggleKey.Value, (KeyCode)(int)secondaryToggleKey.Value, (KeyCode)(int)alternateToggleKey.Value))
{
ToggleTaskList("configured hotkey");
}
if (autoCaptureWhileTabHeld.Value && (SafeKeyHeld((KeyCode)9) || InputSystemKeyHeld((KeyCode)9)) && Time.unscaledTime - lastAutoCaptureTime > 0.4f)
{
CaptureVisibleObjectives(showPanelWhenCaptured: true);
lastAutoCaptureTime = Time.unscaledTime;
}
if (capturedObjectives.Count > 0 && Time.unscaledTime - lastStateRefreshTime > 0.5f)
{
RefreshCapturedObjectiveState();
lastStateRefreshTime = Time.unscaledTime;
}
}
private void OnGUI()
{
EnsureStyles();
if (!firstGuiLogged)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"Jonathan's Task List OnGUI is active.");
firstGuiLogged = true;
}
HandleGuiHotkeys();
if (showPanel)
{
DrawObjectivePanel();
}
}
private void HandleGuiHotkeys()
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Invalid comparison between Unknown and I4
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: 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_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: 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)
Event current = Event.current;
if (current != null && (int)current.type == 4 && (current.keyCode == toggleKey.Value || current.keyCode == secondaryToggleKey.Value || current.keyCode == alternateToggleKey.Value))
{
ToggleTaskList($"GUI {current.keyCode}");
current.Use();
}
}
private bool AnyKeyDown(params KeyCode[] keyCodes)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
foreach (KeyCode keyCode in keyCodes)
{
if (SafeKeyDown(keyCode) || InputSystemKeyDown(keyCode))
{
return true;
}
}
return false;
}
private void ToggleTaskList(string source)
{
CaptureVisibleObjectives();
showPanel = !showPanel;
((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Task list toggled {0} by {1}. Captured lines: {2}.", showPanel ? "on" : "off", source, capturedObjectives.Count));
}
private void HideOnMainMenu()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
Scene activeScene = SceneManager.GetActiveScene();
string text = ((Scene)(ref activeScene)).name ?? string.Empty;
if (!string.Equals(text, lastSceneName, StringComparison.Ordinal))
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("Active scene changed to '" + text + "'."));
lastSceneName = text;
}
string text2 = text.ToLowerInvariant();
if ((text2.Contains("menu") || text2.Contains("title")) && (showPanel || capturedObjectives.Count > 0))
{
showPanel = false;
capturedObjectives.Clear();
rawCaptureLogged = false;
lastRawCaptureSignature = string.Empty;
((BaseUnityPlugin)this).Logger.LogInfo((object)"Task list hidden because the main menu/title scene is active.");
}
}
private bool SafeKeyDown(KeyCode keyCode)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
try
{
return Input.GetKeyDown(keyCode);
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("Legacy key check failed: " + ex.GetType().Name + ": " + ex.Message));
return false;
}
}
private bool SafeKeyHeld(KeyCode keyCode)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
try
{
return Input.GetKey(keyCode);
}
catch
{
return false;
}
}
private bool InputSystemKeyDown(KeyCode keyCode)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
KeyControl inputSystemKey = GetInputSystemKey(keyCode);
if (inputSystemKey == null)
{
return false;
}
LogInputSystemOnce();
bool isPressed = ((ButtonControl)inputSystemKey).isPressed;
previousInputSystemKeyStates.TryGetValue(keyCode, out var value);
previousInputSystemKeyStates[keyCode] = isPressed;
if (isPressed)
{
return !value;
}
return false;
}
private bool InputSystemKeyHeld(KeyCode keyCode)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
KeyControl inputSystemKey = GetInputSystemKey(keyCode);
if (inputSystemKey == null)
{
return false;
}
LogInputSystemOnce();
return ((ButtonControl)inputSystemKey).isPressed;
}
private KeyControl? GetInputSystemKey(KeyCode keyCode)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Invalid comparison between Unknown and I4
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Invalid comparison between Unknown and I4
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Invalid comparison between Unknown and I4
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Expected I4, but got Unknown
//IL_0018: 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_0049: Expected I4, but got Unknown
Keyboard current = Keyboard.current;
if (current == null)
{
return null;
}
if ((int)keyCode <= 57)
{
if ((int)keyCode == 9)
{
return current.tabKey;
}
switch (keyCode - 48)
{
case 0:
return current.digit0Key;
case 1:
return current.digit1Key;
case 2:
return current.digit2Key;
case 3:
return current.digit3Key;
case 4:
return current.digit4Key;
case 5:
return current.digit5Key;
case 6:
return current.digit6Key;
case 7:
return current.digit7Key;
case 8:
return current.digit8Key;
case 9:
return current.digit9Key;
}
}
else
{
if ((int)keyCode == 96)
{
return current.backquoteKey;
}
switch (keyCode - 277)
{
case 31:
return current.leftAltKey;
case 30:
return current.rightAltKey;
case 5:
return current.f1Key;
case 6:
return current.f2Key;
case 7:
return current.f3Key;
case 8:
return current.f4Key;
case 9:
return current.f5Key;
case 10:
return current.f6Key;
case 11:
return current.f7Key;
case 12:
return current.f8Key;
case 13:
return current.f9Key;
case 14:
return current.f10Key;
case 15:
return current.f11Key;
case 16:
return current.f12Key;
case 0:
return current.insertKey;
case 1:
return current.homeKey;
case 2:
return current.endKey;
case 3:
return current.pageUpKey;
case 4:
return current.pageDownKey;
}
}
return null;
}
private void LogInputSystemOnce()
{
if (!inputSystemLogged)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"Jonathan's Task List found Unity Input System keyboard.");
inputSystemLogged = true;
}
}
private void DrawObjectivePanel()
{
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_0172: Unknown result type (might be due to invalid IL or missing references)
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
//IL_01d1: Expected O, but got Unknown
//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
float num = Mathf.Clamp(panelScale.Value, 0.6f, 2.5f);
titleStyle.fontSize = 16;
objectiveStyle.fontSize = 14;
float num2 = 300f;
float num3 = (num2 + 28f) * num;
float height = CalculatePanelHeight(num2) * num;
((Rect)(ref panelRect)).width = num3;
((Rect)(ref panelRect)).height = height;
ApplyTopRightPlacementIfNeeded(num3);
GUI.Box(panelRect, GUIContent.none, paperStyle);
Rect dragArea = default(Rect);
((Rect)(ref dragArea))..ctor(((Rect)(ref panelRect)).x, ((Rect)(ref panelRect)).y, ((Rect)(ref panelRect)).width, 28f * num);
HandlePanelDrag(dragArea);
Matrix4x4 matrix = GUI.matrix;
GUIUtility.ScaleAroundPivot(new Vector2(num, num), ((Rect)(ref panelRect)).position);
Rect val = default(Rect);
((Rect)(ref val))..ctor(((Rect)(ref panelRect)).x + 14f, ((Rect)(ref panelRect)).y + 10f, num2, ((Rect)(ref panelRect)).height / num - 20f);
GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, ((Rect)(ref val)).width, 22f), "Tasks", titleStyle);
if (capturedObjectives.Count == 0)
{
GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + 30f, ((Rect)(ref val)).width, 70f), "Hold TAB so the game objectives are visible, then press the toggle hotkey.", objectiveStyle);
}
else
{
float num4 = ((Rect)(ref val)).y + 30f;
foreach (string capturedObjective in capturedObjectives)
{
string text = FormatObjectiveForDisplay(capturedObjective);
float num5 = objectiveStyle.CalcHeight(new GUIContent(text), ((Rect)(ref val)).width);
GUI.Label(new Rect(((Rect)(ref val)).x, num4, ((Rect)(ref val)).width, num5), text, objectiveStyle);
num4 += num5 + 8f;
}
}
GUI.matrix = matrix;
}
private float CalculatePanelHeight(float contentWidth)
{
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Expected O, but got Unknown
float num = 58f;
if (capturedObjectives.Count == 0)
{
return 120f;
}
foreach (string capturedObjective in capturedObjectives)
{
num += objectiveStyle.CalcHeight(new GUIContent(FormatObjectiveForDisplay(capturedObjective)), contentWidth) + 8f;
}
return Mathf.Max(120f, num);
}
private static string FormatObjectiveForDisplay(string objective)
{
return Regex.Replace(objective, "\\bDONE\\s*$", "<color=#B00000>DONE</color>", RegexOptions.IgnoreCase);
}
private void ApplyTopRightPlacementIfNeeded(float panelWidth)
{
if (panelPlacementVersion.Value < 2)
{
float num = ((Screen.width > 0) ? ((float)Screen.width) : 1920f);
((Rect)(ref panelRect)).x = Mathf.Max(24f, num - panelWidth - 24f);
((Rect)(ref panelRect)).y = 32f;
SavePanelPosition();
panelPlacementVersion.Value = 2;
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Moved the task-list panel to the top-right at X={((Rect)(ref panelRect)).x:0}, Y={((Rect)(ref panelRect)).y:0}.");
}
}
private void HandlePanelDrag(Rect dragArea)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Invalid comparison between Unknown and I4
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Invalid comparison between Unknown and I4
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
if (!lockPanel.Value)
{
Event current = Event.current;
if ((int)current.type == 0 && current.button == 0 && ((Rect)(ref dragArea)).Contains(current.mousePosition))
{
isDragging = true;
dragOffset = current.mousePosition - ((Rect)(ref panelRect)).position;
current.Use();
}
if (isDragging && (int)current.type == 3)
{
((Rect)(ref panelRect)).position = current.mousePosition - dragOffset;
SavePanelPosition();
current.Use();
}
if ((int)current.type == 1)
{
isDragging = false;
}
}
}
private void SavePanelPosition()
{
panelX.Value = ((Rect)(ref panelRect)).x;
panelY.Value = ((Rect)(ref panelRect)).y;
}
private void CaptureVisibleObjectives(bool showPanelWhenCaptured = false)
{
List<string> list = NormalizeCapturedCandidates(ObjectiveTextScanner.FindVisibleObjectiveText()).Take(5).ToList();
ApplyTaskManagerState(list);
string text = string.Join(" | ", list);
if (list.Count > 0 && (!rawCaptureLogged || !string.Equals(text, lastRawCaptureSignature, StringComparison.Ordinal)))
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("Task capture order: " + text));
rawCaptureLogged = true;
lastRawCaptureSignature = text;
}
capturedObjectives.RemoveAll(IsGenericTaskHeader);
if (list.Count == 0)
{
return;
}
if (list.Count >= 5)
{
capturedObjectives.Clear();
capturedObjectives.AddRange(list);
}
else
{
bool allowAdd = capturedObjectives.Count < 5;
foreach (string item in list)
{
AddOrUpdateTaskLine(capturedObjectives, item, allowAdd);
allowAdd = capturedObjectives.Count < 5;
}
}
if (capturedObjectives.Count > 0)
{
if (showPanelWhenCaptured)
{
showPanel = true;
}
string a = string.Join(" | ", capturedObjectives);
if (!string.Equals(a, lastKeptCaptureSignature, StringComparison.Ordinal))
{
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Captured {list.Count} visible objective line(s); keeping {capturedObjectives.Count} total line(s).");
lastKeptCaptureSignature = a;
}
}
}
private void RefreshCapturedObjectiveState()
{
string a = string.Join(" | ", capturedObjectives);
ApplyTaskManagerState(capturedObjectives);
string text = string.Join(" | ", capturedObjectives);
if (!string.Equals(a, text, StringComparison.Ordinal))
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("Auto-updated task state: " + text));
lastKeptCaptureSignature = text;
lastRawCaptureSignature = text;
}
}
private static List<string> NormalizeCapturedCandidates(List<string> rawCandidates)
{
List<string> list = new List<string>();
foreach (string rawCandidate in rawCandidates)
{
string text = NormalizeCompletionMarker(rawCandidate.Trim());
if (text.Length == 0 || IsGenericTaskHeader(text))
{
continue;
}
bool completed = IsCompleted(text);
string line = RemoveCompletionMarker(text);
if (ExtractProgress(line) == null)
{
string text2 = ExtractTrailingProgress(line);
if (text2 != null)
{
AddOrUpdateTaskLine(list, FormatTaskLine(GetTaskBaseName(line), text2, completed));
}
else
{
AddOrUpdateTaskLine(list, FormatTaskLine(GetTaskBaseName(line), null, completed));
}
}
}
return list;
}
private static void ApplyTaskManagerState(List<string> tasks)
{
List<TaskState> list = ReadTaskManagerStates();
if (list.Count < tasks.Count)
{
return;
}
for (int i = 0; i < tasks.Count; i++)
{
TaskState taskState = list[i];
string taskBaseName = GetTaskBaseName(tasks[i]);
if (taskBaseName.Length != 0 && !IsGenericTaskHeader(taskBaseName))
{
if (taskState.Completed)
{
tasks[i] = FormatTaskLine(taskBaseName, null, completed: true);
}
else if (taskState.Max > 1)
{
tasks[i] = FormatTaskLine(taskBaseName, $"{taskState.Current}/{taskState.Max}", completed: false);
}
}
}
}
private static List<TaskState> ReadTaskManagerStates()
{
List<TaskState> list = new List<TaskState>();
try
{
Component val = ((IEnumerable<Component>)Resources.FindObjectsOfTypeAll<Component>()).FirstOrDefault((Func<Component, bool>)((Component component) => (Object)(object)component != (Object)null && (Object)(object)component.gameObject != (Object)null && component.gameObject.activeInHierarchy && string.Equals(((object)component).GetType().Name, "PlayerTaskManager", StringComparison.Ordinal)));
if ((Object)(object)val == (Object)null)
{
return list;
}
object obj = ((object)val).GetType().GetProperty("CurrentTasks", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val, null);
if (obj == null)
{
return list;
}
PropertyInfo property = obj.GetType().GetProperty("Length", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
PropertyInfo property2 = obj.GetType().GetProperty("Item", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (property == null || property2 == null)
{
return list;
}
int val2 = Convert.ToInt32(property.GetValue(obj, null));
for (int num = 0; num < Math.Min(val2, 5); num++)
{
object value = property2.GetValue(obj, new object[1] { num });
if (value != null)
{
list.Add(new TaskState(ReadIntField(value, "currentCompletionCount"), ReadIntField(value, "maxCompletionCount"), ReadBoolField(value, "wasCompleted")));
}
}
}
catch
{
list.Clear();
}
return list;
}
private static int ReadIntField(object instance, string fieldName)
{
object obj = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(instance);
if (obj != null)
{
return Convert.ToInt32(obj);
}
return 0;
}
private static bool ReadBoolField(object instance, string fieldName)
{
object obj = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(instance);
if (obj != null)
{
return Convert.ToBoolean(obj);
}
return false;
}
private static void AddOrUpdateTaskLine(List<string> tasks, string incomingLine, bool allowAdd = true)
{
string taskBaseName = GetTaskBaseName(incomingLine);
if (taskBaseName.Length == 0 || IsGenericTaskHeader(taskBaseName))
{
return;
}
for (int i = 0; i < tasks.Count; i++)
{
if (string.Equals(GetTaskBaseName(tasks[i]), taskBaseName, StringComparison.OrdinalIgnoreCase))
{
tasks[i] = incomingLine;
return;
}
}
if (allowAdd)
{
tasks.Add(incomingLine);
}
}
private static bool IsGenericTaskHeader(string line)
{
string text = GetTaskBaseName(line).ToLowerInvariant();
switch (text)
{
default:
return text == "objectives";
case "task":
case "tasks":
case "objective":
return true;
}
}
private static string? ExtractProgress(string line)
{
Match match = Regex.Match(line.Trim(), "^(\\d+\\s*/\\s*\\d+)(?:\\s+tasks?)?$", RegexOptions.IgnoreCase);
if (!match.Success)
{
return null;
}
return Regex.Replace(match.Groups[1].Value, "\\s+", string.Empty);
}
private static string? ExtractTrailingProgress(string line)
{
Match match = Regex.Match(RemoveCompletionMarker(line).Trim(), "\\b(\\d+\\s*/\\s*\\d+)\\)?\\s*$", RegexOptions.IgnoreCase);
if (!match.Success)
{
return null;
}
return Regex.Replace(match.Groups[1].Value, "\\s+", string.Empty);
}
private static bool HasProgress(string line)
{
return Regex.IsMatch(line, "\\(\\d+\\s*/\\s*\\d+\\)|\\b\\d+\\s*/\\s*\\d+\\b", RegexOptions.IgnoreCase);
}
private static string GetTaskBaseName(string line)
{
return Regex.Replace(Regex.Replace(RemoveCompletionMarker(line), "\\s*\\(?\\b\\d+\\s*/\\s*\\d+\\b(?:\\s+tasks?)?\\)?\\s*$", string.Empty, RegexOptions.IgnoreCase), "\\s+", " ").Trim();
}
private static string FormatTaskLine(string taskBase, string? progress, bool completed)
{
taskBase = GetTaskBaseName(taskBase);
string text = taskBase;
if (!string.IsNullOrWhiteSpace(progress))
{
text = text + " (" + progress + ")";
}
if (!completed && !IsCompleteProgress(progress))
{
return text;
}
return taskBase + " DONE";
}
private static bool IsCompleteProgress(string? progress)
{
if (string.IsNullOrWhiteSpace(progress))
{
return false;
}
Match match = Regex.Match(progress, "^(\\d+)\\s*/\\s*(\\d+)$");
if (match.Success && int.TryParse(match.Groups[1].Value, out var result) && int.TryParse(match.Groups[2].Value, out var result2) && result2 > 0)
{
return result >= result2;
}
return false;
}
private static string NormalizeCompletionMarker(string line)
{
return Regex.Replace(line, "[\\u2713\\u2714]\\s*$", "✓").Trim();
}
private static string RemoveCompletionMarker(string line)
{
return Regex.Replace(line, "(?:\\s*(?:[\\u2713\\u2714]|DONE))+\\s*$", string.Empty, RegexOptions.IgnoreCase).Trim();
}
private static bool IsCompleted(string line)
{
return Regex.IsMatch(line.Trim(), "(?:[\\u2713\\u2714]|DONE)\\s*$", RegexOptions.IgnoreCase);
}
private void EnsureStyles()
{
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Expected O, but got Unknown
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Expected O, but got Unknown
//IL_0099: Expected O, but got Unknown
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
//IL_00ed: Expected O, but got Unknown
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_011f: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_0148: Expected O, but got Unknown
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: Unknown result type (might be due to invalid IL or missing references)
//IL_0164: Unknown result type (might be due to invalid IL or missing references)
//IL_016c: Unknown result type (might be due to invalid IL or missing references)
//IL_0173: Unknown result type (might be due to invalid IL or missing references)
//IL_018d: Unknown result type (might be due to invalid IL or missing references)
//IL_019c: Expected O, but got Unknown
if (!stylesReady)
{
bahnschrift = Font.CreateDynamicFontFromOSFont(new string[2] { "Bahnschrift", "Arial" }, 14);
paperTexture = MakeTexture(new Color(0.93f, 0.9f, 0.8f, 0.96f));
GUIStyle val = new GUIStyle(GUI.skin.box);
val.normal.background = paperTexture;
val.border = new RectOffset(8, 8, 8, 8);
val.padding = new RectOffset(12, 12, 10, 10);
paperStyle = val;
GUIStyle val2 = new GUIStyle(GUI.skin.label)
{
font = bahnschrift,
fontSize = 14,
fontStyle = (FontStyle)1
};
val2.normal.textColor = new Color(0.15f, 0.12f, 0.08f, 1f);
titleStyle = val2;
GUIStyle val3 = new GUIStyle(GUI.skin.label)
{
font = bahnschrift,
fontSize = 14,
wordWrap = true,
richText = true
};
val3.normal.textColor = new Color(0.12f, 0.1f, 0.07f, 1f);
objectiveStyle = val3;
GUIStyle val4 = new GUIStyle(GUI.skin.label)
{
font = bahnschrift,
fontSize = 11,
wordWrap = true
};
val4.normal.textColor = new Color(0.18f, 0.15f, 0.1f, 1f);
smallStyle = val4;
stylesReady = true;
}
}
private Texture2D MakeTexture(Color color)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: 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_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
Color[] pixels = Enumerable.Repeat<Color>(color, 4).ToArray();
val.SetPixels(pixels);
val.Apply();
return val;
}
}
internal static class ObjectiveTextScanner
{
private readonly struct TextCandidate
{
public string Line { get; }
public float Y { get; }
public float X { get; }
public int SiblingIndex { get; }
public string SourceType { get; }
public string Path { get; }
public TextCandidate(string line, float y, float x, int siblingIndex, string sourceType, string path)
{
Line = line;
Y = y;
X = x;
SiblingIndex = siblingIndex;
SourceType = sourceType;
Path = path;
}
}
private static readonly string[] ObjectiveWords = new string[11]
{
"objective", "mission", "task", "steal", "break", "bring", "collect", "escape", "complete", "tase",
"shoot"
};
public static List<string> FindVisibleObjectiveText()
{
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
List<TextCandidate> list = new List<TextCandidate>();
Component[] array = Resources.FindObjectsOfTypeAll<Component>();
foreach (Component val in array)
{
if ((Object)(object)val == (Object)null || (Object)(object)val.gameObject == (Object)null || !val.gameObject.activeInHierarchy || !LooksLikeTextComponent(((object)val).GetType().Name))
{
continue;
}
string text = TryReadText(val);
if (string.IsNullOrWhiteSpace(text))
{
continue;
}
bool objectiveContext = LooksLikeObjectiveContext(val, text);
foreach (string item in SplitLines(text))
{
if (LooksLikeObjectiveLine(item, objectiveContext))
{
Vector2 textPosition = GetTextPosition(val);
list.Add(new TextCandidate(NormalizeLine(item), textPosition.y, textPosition.x, val.transform.GetSiblingIndex(), ((object)val).GetType().Name, GetTransformPath(val.transform)));
}
}
}
return (from candidate in (from @group in (from candidate in PairProgressByPosition(list)
orderby candidate.Y descending, candidate.X, candidate.SiblingIndex
select candidate).GroupBy<TextCandidate, string>((TextCandidate candidate) => candidate.Line, StringComparer.OrdinalIgnoreCase)
select @group.First()).Take(24).ToList()
select candidate.Line).ToList();
}
private static List<TextCandidate> PairProgressByPosition(List<TextCandidate> candidates)
{
List<TextCandidate> list = candidates.Where((TextCandidate candidate) => !IsProgressOnlyLine(candidate.Line) && !IsCompletionOnlyLine(candidate.Line) && !IsGenericTaskHeaderLine(candidate.Line)).ToList();
List<TextCandidate> list2 = candidates.Where((TextCandidate candidate) => IsProgressOnlyLine(candidate.Line)).ToList();
List<TextCandidate> list3 = candidates.Where((TextCandidate candidate) => IsCompletionOnlyLine(candidate.Line)).ToList();
List<TextCandidate> list4 = new List<TextCandidate>();
foreach (TextCandidate item in list3)
{
int num = FindNearestTaskIndex(list, item, allowLeftOfTask: true, 60f);
if (num >= 0)
{
TextCandidate textCandidate = list[num];
if (!HasCompletionMarker(textCandidate.Line))
{
list[num] = new TextCandidate(textCandidate.Line + " ✓", textCandidate.Y, textCandidate.X, textCandidate.SiblingIndex, textCandidate.SourceType, textCandidate.Path);
}
}
}
foreach (TextCandidate item2 in list2)
{
int num2 = FindSameRowProgressTaskIndex(list, item2);
if (num2 >= 0)
{
TextCandidate textCandidate2 = list[num2];
string line = (HasCompletionMarker(textCandidate2.Line) ? (RemoveCompletionMarker(textCandidate2.Line) + " " + item2.Line + " ✓") : (textCandidate2.Line + " " + item2.Line));
list[num2] = new TextCandidate(line, textCandidate2.Y, textCandidate2.X, textCandidate2.SiblingIndex, textCandidate2.SourceType, textCandidate2.Path);
}
else
{
list4.Add(item2);
}
}
return list.Concat(list4).ToList();
}
private static int FindSameRowProgressTaskIndex(List<TextCandidate> taskCandidates, TextCandidate progressCandidate)
{
int result = -1;
float num = float.MaxValue;
for (int i = 0; i < taskCandidates.Count; i++)
{
if (Regex.IsMatch(taskCandidates[i].Line, "\\b\\d+\\s*/\\s*\\d+\\b"))
{
continue;
}
float num2 = Math.Abs(taskCandidates[i].Y - progressCandidate.Y);
if (num2 > 14f)
{
continue;
}
float num3 = progressCandidate.X - taskCandidates[i].X;
if (!(num3 < -40f) && !(num3 > 700f))
{
float num4 = num2 + Math.Abs(num3) * 0.01f;
if (num4 < num)
{
num = num4;
result = i;
}
}
}
return result;
}
private static int FindNearestTaskIndex(List<TextCandidate> taskCandidates, TextCandidate markerCandidate, bool allowLeftOfTask, float maxYDistance = 24f)
{
int result = -1;
float num = float.MaxValue;
for (int i = 0; i < taskCandidates.Count; i++)
{
if (Regex.IsMatch(taskCandidates[i].Line, "\\b\\d+\\s*/\\s*\\d+\\b"))
{
continue;
}
float num2 = Math.Abs(taskCandidates[i].Y - markerCandidate.Y);
if (num2 > maxYDistance)
{
continue;
}
float num3 = markerCandidate.X - taskCandidates[i].X;
float num4 = (allowLeftOfTask ? (-180f) : (-20f));
if (!(num3 < num4) && !(num3 > 700f))
{
float num5 = num2 + Math.Abs(num3) * 0.01f;
if (num5 < num)
{
num = num5;
result = i;
}
}
}
return result;
}
private static Vector2 GetTextPosition(Component component)
{
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
Transform transform = component.transform;
RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
if ((Object)(object)val != (Object)null)
{
Vector3[] array = (Vector3[])(object)new Vector3[4];
val.GetWorldCorners(array);
float num = (array[0].x + array[2].x) * 0.5f;
float num2 = (array[0].y + array[2].y) * 0.5f;
return new Vector2(num, num2);
}
Vector3 position = component.transform.position;
return new Vector2(position.x, position.y);
}
private static string GetTransformPath(Transform transform)
{
List<string> list = new List<string>();
Transform val = transform;
int num = 0;
while ((Object)(object)val != (Object)null && num < 10)
{
list.Add(((Object)val).name);
val = val.parent;
num++;
}
list.Reverse();
return string.Join("/", list);
}
private static bool LooksLikeTextComponent(string typeName)
{
if (typeName.IndexOf("Text", StringComparison.OrdinalIgnoreCase) < 0)
{
return typeName.IndexOf("TMP", StringComparison.OrdinalIgnoreCase) >= 0;
}
return true;
}
private static string? TryReadText(Component component)
{
Type type = ((object)component).GetType();
PropertyInfo property = type.GetProperty("text", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (property != null && property.PropertyType == typeof(string))
{
return property.GetValue(component, null) as string;
}
return (type.GetField("m_text", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField("text", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(component) as string;
}
private static bool LooksLikeObjectiveContext(Component component, string text)
{
string lowerText = text.ToLowerInvariant();
if (ObjectiveWords.Any((string word) => lowerText.Contains(word)))
{
return true;
}
Transform val = component.transform;
int num = 0;
while ((Object)(object)val != (Object)null && num < 8)
{
string text2 = ((Object)val).name.ToLowerInvariant();
if (text2.Contains("objective") || text2.Contains("mission") || text2.Contains("task"))
{
return true;
}
val = val.parent;
num++;
}
return false;
}
private static IEnumerable<string> SplitLines(string text)
{
return from line in text.Replace("\r", "\n").Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries).Select(NormalizeLine)
where line.Length > 0
select line;
}
private static string NormalizeLine(string line)
{
return line.Trim().TrimStart('-', '*', '>', '[', ']').Trim();
}
private static bool LooksLikeObjectiveLine(string line, bool objectiveContext)
{
if (line.Length < 3 || line.Length > 140)
{
return false;
}
if (IsProgressOnlyLine(line))
{
return true;
}
if (IsCompletionOnlyLine(line))
{
return true;
}
if (line.Count(char.IsLetter) < 3)
{
return false;
}
string lower = line.ToLowerInvariant();
if (objectiveContext && !LooksLikeGenericUiLabel(lower))
{
return true;
}
if (!ObjectiveWords.Any((string word) => lower.Contains(word)))
{
return Regex.IsMatch(lower, "\\b\\d+\\s*/\\s*\\d+\\b");
}
return true;
}
private static bool IsProgressOnlyLine(string line)
{
return Regex.IsMatch(line.Trim(), "^\\d+\\s*/\\s*\\d+$", RegexOptions.IgnoreCase);
}
private static bool IsGenericTaskHeaderLine(string line)
{
string text = Regex.Replace(Regex.Replace(line, "\\s*\\(?\\b\\d+\\s*/\\s*\\d+\\b(?:\\s+tasks?)?\\)?\\s*$", string.Empty, RegexOptions.IgnoreCase), "\\s+", " ").Trim().ToLowerInvariant();
switch (text)
{
default:
return text == "objectives";
case "task":
case "tasks":
case "objective":
return true;
}
}
private static bool IsCompletionOnlyLine(string line)
{
return Regex.IsMatch(line.Trim(), "^(?:task\\s+)?completed!?\\s*$", RegexOptions.IgnoreCase);
}
private static bool HasCompletionMarker(string line)
{
return Regex.IsMatch(line.Trim(), "[\\u2713\\u2714]\\s*$");
}
private static string RemoveCompletionMarker(string line)
{
return Regex.Replace(line, "\\s*[\\u2713\\u2714]\\s*$", string.Empty).Trim();
}
private static bool LooksLikeGenericUiLabel(string lower)
{
switch (lower)
{
default:
return lower == "controls";
case "objectives":
case "mission":
case "missions":
case "tasks":
case "settings":
case "resume":
case "quit":
case "back":
case "audio":
case "video":
return true;
}
}
}
}