Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of REPOPathfinder v0.7.2
REPOPathfinder.dll
Decompiled 2 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; using UnityEngine.AI; using UnityEngine.Rendering; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")] [assembly: AssemblyCompany("REPOPathfinder")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.7.2.0")] [assembly: AssemblyInformationalVersion("0.7.2")] [assembly: AssemblyProduct("REPOPathfinder")] [assembly: AssemblyTitle("REPOPathfinder")] [assembly: AssemblyVersion("0.7.2.0")] namespace REPOPathfinder; public static class InputBlocker { [HarmonyPatch(typeof(Input), "GetAxis")] public static class GetAxisPatch { private static bool Prefix(ref float __result) { if (!BlockInput) { return true; } __result = 0f; return false; } } [HarmonyPatch(typeof(Input), "GetAxisRaw")] public static class GetAxisRawPatch { private static bool Prefix(ref float __result) { if (!BlockInput) { return true; } __result = 0f; return false; } } [HarmonyPatch(typeof(Input), "GetMouseButton")] public static class GetMouseButtonPatch { private static bool Prefix(ref bool __result) { if (!BlockInput) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(Input), "GetMouseButtonDown")] public static class GetMouseButtonDownPatch { private static bool Prefix(ref bool __result) { if (!BlockInput) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(Input), "GetMouseButtonUp")] public static class GetMouseButtonUpPatch { private static bool Prefix(ref bool __result) { if (!BlockInput) { return true; } __result = false; return false; } } public static bool BlockInput; public static void PatchInputSystem(Harmony harmony) { //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Expected O, but got Unknown try { Type type = (from a in AppDomain.CurrentDomain.GetAssemblies() where a.GetName().Name == "Unity.InputSystem" select a.GetType("UnityEngine.InputSystem.InputAction")).FirstOrDefault((Type t) => t != null); if (type == null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"New InputSystem not loaded; skipping its patches."); } return; } MethodInfo methodInfo = type.GetMethods(BindingFlags.Instance | BindingFlags.Public).FirstOrDefault((MethodInfo m) => m.Name == "ReadValue" && m.IsGenericMethodDefinition && m.GetParameters().Length == 0); if (methodInfo == null) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)"Could not find InputAction.ReadValue<T>(); InputSystem patches not applied."); } return; } MethodInfo method = typeof(InputBlocker).GetMethod("GenericReadValuePrefix", BindingFlags.Static | BindingFlags.NonPublic); int num = 0; Type[] array = new Type[3] { typeof(Vector2), typeof(float), typeof(Vector3) }; foreach (Type type2 in array) { try { MethodInfo methodInfo2 = methodInfo.MakeGenericMethod(type2); MethodInfo methodInfo3 = method.MakeGenericMethod(type2); harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(methodInfo3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } catch (Exception ex) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogWarning((object)("Could not patch InputAction.ReadValue<" + type2.Name + ">: " + ex.Message)); } } } ManualLogSource log4 = Plugin.Log; if (log4 != null) { log4.LogInfo((object)$"Patched InputAction.ReadValue<T>() for {num} closed generic(s)."); } } catch (Exception arg) { ManualLogSource log5 = Plugin.Log; if (log5 != null) { log5.LogError((object)$"PatchInputSystem failed: {arg}"); } } } private static bool GenericReadValuePrefix<T>(ref T __result) { if (!BlockInput) { return true; } __result = default(T); return false; } } public class PathfinderCustomizeUI : MonoBehaviour { private bool _visible; private Rect _windowRect = new Rect(20f, 60f, 360f, 0f); private int _windowId; private Color _editColor; private string _hexBuffer; private bool _hexBufferDirty; private bool _needsSyncFromConfig = true; private static readonly (string label, string hex)[] Presets = new(string, string)[8] { ("White", "#FFFFFF80"), ("Cyan", "#00E5FF80"), ("Yellow", "#FFEB3B80"), ("Red", "#FF525280"), ("Green", "#00E67680"), ("Blue", "#448AFF80"), ("Magenta", "#E040FB80"), ("Orange", "#FF9100AA") }; private Texture2D _whiteTex; private GUIStyle _boldStyle; private CursorLockMode _savedLockState; private bool _savedCursorVisible; private bool _cursorOverridden; private GUIStyle BoldLabel { get { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown if (_boldStyle == null) { _boldStyle = new GUIStyle(GUI.skin.label) { fontStyle = (FontStyle)1 }; } return _boldStyle; } } private void Awake() { _windowId = ((Object)this).GetInstanceID(); } private void Update() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(Plugin.Instance.CustomizeMenuKey.Value)) { _visible = !_visible; if (_visible) { _needsSyncFromConfig = true; AcquireCursor(); } else { ReleaseCursor(); } InputBlocker.BlockInput = _visible; } } private void OnDisable() { if (_visible) { _visible = false; ReleaseCursor(); InputBlocker.BlockInput = false; } } private void OnGUI() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_006e: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (_visible) { if (_needsSyncFromConfig) { SyncFromConfig(); _needsSyncFromConfig = false; } if ((int)Cursor.lockState != 0) { Cursor.lockState = (CursorLockMode)0; } if (!Cursor.visible) { Cursor.visible = true; } _windowRect = GUILayout.Window(_windowId, _windowRect, new WindowFunction(DrawWindow), "REPOPathfinder — Customize", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(360f) }); } } private void AcquireCursor() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (!_cursorOverridden) { _savedLockState = Cursor.lockState; _savedCursorVisible = Cursor.visible; _cursorOverridden = true; } } private void ReleaseCursor() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (_cursorOverridden) { Cursor.lockState = _savedLockState; Cursor.visible = _savedCursorVisible; _cursorOverridden = false; } } private void SyncFromConfig() { //IL_003d: 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) if (!ColorUtility.TryParseHtmlString(Plugin.Instance.DotColorHex.Value, ref _editColor)) { _editColor = new Color(1f, 1f, 1f, 0.5f); } _hexBuffer = ColorToHex(_editColor); _hexBufferDirty = false; } private void DrawWindow(int id) { //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_034f: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) GUILayout.Space(4f); GUILayout.Label("Dot Color", BoldLabel, Array.Empty<GUILayoutOption>()); DrawColorChannel("R", ref _editColor.r); DrawColorChannel("G", ref _editColor.g); DrawColorChannel("B", ref _editColor.b); DrawColorChannel("A", ref _editColor.a); GUILayout.Space(2f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("Hex:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) }); string text = GUILayout.TextField(_hexBuffer ?? "", 9, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) }); if (text != _hexBuffer) { _hexBuffer = text; _hexBufferDirty = true; } GUI.enabled = _hexBufferDirty; Color editColor = default(Color); if (GUILayout.Button("Apply", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(58f) }) && ColorUtility.TryParseHtmlString(_hexBuffer, ref editColor)) { _editColor = editColor; _hexBufferDirty = false; PushColorToConfig(); } GUI.enabled = true; GUILayout.Label("Preview:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }); DrawSwatch(_editColor, 60f, 18f); GUILayout.EndHorizontal(); GUILayout.Space(6f); GUILayout.Label("Presets", BoldLabel, Array.Empty<GUILayoutOption>()); Color editColor2 = default(Color); for (int i = 0; i < Presets.Length; i++) { if (i % 4 == 0) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); } if (GUILayout.Button(Presets[i].label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(78f) }) && ColorUtility.TryParseHtmlString(Presets[i].hex, ref editColor2)) { _editColor = editColor2; _hexBuffer = ColorToHex(_editColor); _hexBufferDirty = false; PushColorToConfig(); } if (i % 4 == 3 || i == Presets.Length - 1) { GUILayout.EndHorizontal(); } } GUILayout.Space(8f); GUILayout.Label("Trail Shape", BoldLabel, Array.Empty<GUILayoutOption>()); DrawFloatSlider("Dot size", Plugin.Instance.DotScale, 0.02f, 0.5f, "F2"); DrawFloatSlider("Flow speed", Plugin.Instance.FlowSpeed, 0f, 6f, "F1"); DrawFloatSlider("Spacing", Plugin.Instance.Spacing, 0.5f, 4f, "F1"); GUILayout.Space(8f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Reset Visuals", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) })) { ResetVisualDefaults(); } GUILayout.FlexibleSpace(); if (GUILayout.Button("Close", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) })) { _visible = false; ReleaseCursor(); InputBlocker.BlockInput = false; } GUILayout.EndHorizontal(); GUI.DragWindow(new Rect(0f, 0f, 10000f, 20f)); } private void DrawColorChannel(string label, ref float value) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(20f) }); float num = value; value = GUILayout.HorizontalSlider(value, 0f, 1f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) }); GUILayout.Label(Mathf.RoundToInt(Mathf.Clamp01(value) * 255f).ToString("D3"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(36f) }); GUILayout.EndHorizontal(); if (Mathf.Abs(value - num) > 0.0001f) { _hexBuffer = ColorToHex(_editColor); _hexBufferDirty = false; PushColorToConfig(); } } private static void DrawFloatSlider(string label, ConfigEntry<float> entry, float min, float max, string format) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }); float value = entry.Value; float num = GUILayout.HorizontalSlider(entry.Value, min, max, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(180f) }); GUILayout.Label(num.ToString(format), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }); GUILayout.EndHorizontal(); if (Mathf.Abs(num - value) > 0.0001f) { entry.Value = num; } } private void DrawSwatch(Color c, float width, float height) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) EnsureWhiteTex(); Rect rect = GUILayoutUtility.GetRect(width, height, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(width), GUILayout.Height(height) }); Color color = GUI.color; GUI.color = Color.white; GUI.DrawTexture(rect, (Texture)(object)_whiteTex); GUI.color = c; GUI.DrawTexture(rect, (Texture)(object)_whiteTex); GUI.color = color; } private void EnsureWhiteTex() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_whiteTex != (Object)null)) { _whiteTex = new Texture2D(1, 1); _whiteTex.SetPixel(0, 0, Color.white); _whiteTex.Apply(); ((Object)_whiteTex).hideFlags = (HideFlags)61; } } private void ResetVisualDefaults() { Plugin.Instance.DotColorHex.Value = (string)((ConfigEntryBase)Plugin.Instance.DotColorHex).DefaultValue; Plugin.Instance.DotScale.Value = (float)((ConfigEntryBase)Plugin.Instance.DotScale).DefaultValue; Plugin.Instance.FlowSpeed.Value = (float)((ConfigEntryBase)Plugin.Instance.FlowSpeed).DefaultValue; Plugin.Instance.Spacing.Value = (float)((ConfigEntryBase)Plugin.Instance.Spacing).DefaultValue; _needsSyncFromConfig = true; } private void PushColorToConfig() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) string text = ColorToHex(_editColor); if (Plugin.Instance.DotColorHex.Value != text) { Plugin.Instance.DotColorHex.Value = text; } } private static string ColorToHex(Color c) { //IL_0000: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Clamp(Mathf.RoundToInt(c.r * 255f), 0, 255); int num2 = Mathf.Clamp(Mathf.RoundToInt(c.g * 255f), 0, 255); int num3 = Mathf.Clamp(Mathf.RoundToInt(c.b * 255f), 0, 255); int num4 = Mathf.Clamp(Mathf.RoundToInt(c.a * 255f), 0, 255); return $"#{num:X2}{num2:X2}{num3:X2}{num4:X2}"; } } public class PathfinderManager : MonoBehaviour { private bool _trailEnabled; private NavMeshPath _path; private Vector3[] _cachedCorners; private float[] _cachedArcs; private float _totalLength; private object _cachedTargetIdentity; private readonly List<GameObject> _dots = new List<GameObject>(); private readonly List<MeshRenderer> _renderers = new List<MeshRenderer>(); private Vector3[] _smoothedPositions; private bool[] _wasVisible; private float _animOffset; private int _frontPool; private bool _animInitialized; private Material _sharedMaterial; private MaterialPropertyBlock _mpb; private Color _baseColor; private static readonly int ColorPropId = Shader.PropertyToID("_Color"); private FieldInfo _fldExtractionPointCurrent; private FieldInfo _fldAllExtractionPointsCompleted; private FieldInfo _fldLastNavmeshPosition; private float _toastUntil; private string _toastText; private GUIStyle _toastStyle; private void Awake() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) _path = new NavMeshPath(); _mpb = new MaterialPropertyBlock(); _trailEnabled = Plugin.Instance.EnabledOnStart.Value; _baseColor = ParseColor(Plugin.Instance.DotColorHex.Value); _fldExtractionPointCurrent = Reflect.Field(typeof(RoundDirector), "extractionPointCurrent"); _fldAllExtractionPointsCompleted = Reflect.Field(typeof(RoundDirector), "allExtractionPointsCompleted"); _fldLastNavmeshPosition = Reflect.Field(typeof(PlayerAvatar), "LastNavmeshPosition"); if (_fldExtractionPointCurrent == null || _fldAllExtractionPointsCompleted == null || _fldLastNavmeshPosition == null) { Plugin.Log.LogWarning((object)"Could not bind one or more REPO internal fields via reflection. Trail may be inactive."); } Plugin.Instance.DotColorHex.SettingChanged += OnDotColorChanged; } private void OnDestroy() { try { if ((Object)(object)Plugin.Instance != (Object)null && Plugin.Instance.DotColorHex != null) { Plugin.Instance.DotColorHex.SettingChanged -= OnDotColorChanged; } } catch { } } private void OnDotColorChanged(object sender, EventArgs e) { //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) _baseColor = ParseColor(Plugin.Instance.DotColorHex.Value); } private void OnEnable() { SceneManager.sceneLoaded += OnSceneLoaded; } private void OnDisable() { SceneManager.sceneLoaded -= OnSceneLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { InvalidateCache(); HideAllDots(); } private void InvalidateCache() { _cachedCorners = null; _cachedArcs = null; _totalLength = 0f; _cachedTargetIdentity = null; if (_wasVisible != null) { Array.Clear(_wasVisible, 0, _wasVisible.Length); } } private void Update() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: 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_0135: 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) if (Input.GetKeyDown(Plugin.Instance.ToggleKey.Value)) { _trailEnabled = !_trailEnabled; ShowToast(_trailEnabled ? "Pathfinder: ON" : "Pathfinder: OFF"); if (!_trailEnabled) { HideAllDots(); } } if (Input.GetKeyDown(Plugin.Instance.TargetToggleKey.Value)) { PathfinderTargetMode pathfinderTargetMode = ((Plugin.Instance.TargetMode.Value == PathfinderTargetMode.Auto) ? PathfinderTargetMode.Truck : PathfinderTargetMode.Auto); Plugin.Instance.TargetMode.Value = pathfinderTargetMode; ShowToast((pathfinderTargetMode == PathfinderTargetMode.Truck) ? "Target: Truck" : "Target: Auto"); InvalidateCache(); } if (!_trailEnabled) { return; } if ((Object)(object)Map.Instance == (Object)null || (Object)(object)PlayerController.instance == (Object)null || (Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated || (Object)(object)RoundDirector.instance == (Object)null) { HideAllDots(); return; } PlayerAvatar playerAvatarScript = PlayerController.instance.playerAvatarScript; if ((Object)(object)playerAvatarScript == (Object)null) { HideAllDots(); return; } Vector3 fieldValue = Reflect.GetFieldValue<Vector3>(_fldLastNavmeshPosition, playerAvatarScript, ((Component)playerAvatarScript).transform.position); if (NeedRecompute(fieldValue) && !RecomputePath(fieldValue)) { HideAllDots(); return; } if (_cachedCorners == null || _cachedCorners.Length < 2 || _totalLength <= 0.5f) { HideAllDots(); return; } ProjectOnCachedPath(fieldValue, out var arc, out var _); float num = _totalLength - arc; if (num < Plugin.Instance.MinDistanceToTarget.Value) { HideAllDots(); } else { AdvanceAndPlace(Time.deltaTime, arc, num); } } private object ResolveTargetIdentity() { if (Plugin.Instance.TargetMode.Value == PathfinderTargetMode.Truck) { if (!((Object)(object)LevelGenerator.Instance != (Object)null) || !((Object)(object)LevelGenerator.Instance.LevelPathTruck != (Object)null)) { return null; } return "truck"; } if (Reflect.GetFieldValue(_fldAllExtractionPointsCompleted, RoundDirector.instance, fallback: false)) { return "truck"; } return Reflect.GetFieldValue<ExtractionPoint>(_fldExtractionPointCurrent, RoundDirector.instance); } private bool NeedRecompute(Vector3 playerPos) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) object obj = ResolveTargetIdentity(); if (obj == null) { if (_cachedCorners != null) { InvalidateCache(); } return false; } if (_cachedCorners == null || _cachedCorners.Length < 2) { return true; } if (!object.Equals(obj, _cachedTargetIdentity)) { return true; } if (!ProjectOnCachedPath(playerPos, out var _, out var dist)) { return true; } if (dist > Plugin.Instance.OffPathThreshold.Value) { return true; } return false; } private bool RecomputePath(Vector3 playerPos) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_003f: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Invalid comparison between Unknown and I4 object obj = ResolveTargetIdentity(); if (obj == null) { return false; } Vector3 position; if (obj as string == "truck") { LevelPoint levelPathTruck = LevelGenerator.Instance.LevelPathTruck; if ((Object)(object)levelPathTruck == (Object)null) { return false; } position = ((Component)levelPathTruck).transform.position; } else { ExtractionPoint val = (ExtractionPoint)((obj is ExtractionPoint) ? obj : null); if (val == null) { return false; } position = ((Component)val).transform.position; } if (Vector3.Distance(playerPos, position) < Plugin.Instance.MinDistanceToTarget.Value) { return false; } if (!NavMesh.CalculatePath(playerPos, position, -1, _path) || (int)_path.status == 2 || _path.corners == null || _path.corners.Length < 2) { return false; } CacheCurrentPath(); _cachedTargetIdentity = obj; return true; } private void CacheCurrentPath() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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) Vector3[] corners = _path.corners; if (_cachedCorners == null || _cachedCorners.Length != corners.Length) { _cachedCorners = (Vector3[])(object)new Vector3[corners.Length]; _cachedArcs = new float[corners.Length]; } _cachedCorners[0] = corners[0]; _cachedArcs[0] = 0f; for (int i = 1; i < corners.Length; i++) { _cachedCorners[i] = corners[i]; _cachedArcs[i] = _cachedArcs[i - 1] + Vector3.Distance(corners[i - 1], corners[i]); } _totalLength = _cachedArcs[corners.Length - 1]; if (_wasVisible != null) { Array.Clear(_wasVisible, 0, _wasVisible.Length); } } private bool ProjectOnCachedPath(Vector3 p, out float arc, out float dist) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: 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) //IL_0076: 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_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_0084: Unknown result type (might be due to invalid IL or missing references) arc = 0f; dist = float.MaxValue; if (_cachedCorners == null || _cachedCorners.Length < 2) { return false; } for (int i = 1; i < _cachedCorners.Length; i++) { Vector3 val = _cachedCorners[i - 1]; Vector3 val2 = _cachedCorners[i] - val; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (!(sqrMagnitude < 1E-06f)) { float num = Vector3.Dot(p - val, val2) / sqrMagnitude; num = Mathf.Clamp01(num); float num2 = Vector3.Distance(val + val2 * num, p); if (num2 < dist) { dist = num2; arc = _cachedArcs[i - 1] + Mathf.Sqrt(sqrMagnitude) * num; } } } return true; } private Vector3 CachedPointAtDistance(float distance) { //IL_0011: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (_cachedCorners == null || _cachedCorners.Length == 0) { return Vector3.zero; } if (_cachedCorners.Length == 1 || distance <= 0f) { return _cachedCorners[0]; } for (int i = 1; i < _cachedCorners.Length; i++) { if (distance <= _cachedArcs[i]) { float num = _cachedArcs[i] - _cachedArcs[i - 1]; if (num < 1E-06f) { return _cachedCorners[i]; } float num2 = (distance - _cachedArcs[i - 1]) / num; return Vector3.Lerp(_cachedCorners[i - 1], _cachedCorners[i], num2); } } return _cachedCorners[_cachedCorners.Length - 1]; } private void AdvanceAndPlace(float dt, float playerArc, float availableLength) { //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Max(1, Plugin.Instance.MaxDots.Value); float num2 = Mathf.Max(0.1f, Plugin.Instance.Spacing.Value); float value = Plugin.Instance.GroundOffset.Value; float num3 = Mathf.Max(0f, Plugin.Instance.FlowSpeed.Value); float num4 = Mathf.Clamp(Plugin.Instance.FadeZoneFraction.Value, 0.05f, 0.5f); float num5 = Mathf.Max(0.01f, Plugin.Instance.DotScale.Value); EnsurePool(num); EnsureSmoothing(num); if (!_animInitialized) { _frontPool = 0; _animOffset = 0f; _animInitialized = true; } if (_frontPool < 0 || _frontPool >= num) { _frontPool = (_frontPool % num + num) % num; } _animOffset += num3 * dt; while (_animOffset >= num2) { _animOffset -= num2; _frontPool = (_frontPool - 1 + num) % num; _wasVisible[_frontPool] = false; } int num6 = Mathf.Min(num, Mathf.Max(1, Mathf.CeilToInt(availableLength / num2))); float num7 = (float)num6 * num2; float num8 = Mathf.Min(availableLength, num7); float num9 = Mathf.Max(0.05f, Mathf.Min(num2, num8 * 0.5f) * num4); float value2 = Plugin.Instance.PositionSmoothRate.Value; float num10 = ((value2 > 0f) ? (1f - Mathf.Exp((0f - value2) * dt)) : 1f); for (int i = 0; i < num; i++) { int num11 = ((i - _frontPool) % num + num) % num; if (num11 >= num6) { if (_dots[i].activeSelf) { _dots[i].SetActive(false); } _wasVisible[i] = false; continue; } float num12 = (float)num11 * num2 + _animOffset; float num13 = Mathf.Min(num12, availableLength); Vector3 val = CachedPointAtDistance(playerArc + num13); val.y += value; if (!_wasVisible[i]) { _smoothedPositions[i] = val; } else { _smoothedPositions[i] = Vector3.Lerp(_smoothedPositions[i], val, num10); } _dots[i].transform.position = _smoothedPositions[i]; _wasVisible[i] = true; if (_dots[i].transform.localScale.x != num5) { _dots[i].transform.localScale = new Vector3(num5, num5, num5); } float num14 = Mathf.SmoothStep(0f, 1f, num12 / num9); float num15 = Mathf.SmoothStep(0f, 1f, (num8 - num12) / num9); ApplyDotAlpha(i, Mathf.Min(num14, num15)); if (!_dots[i].activeSelf) { _dots[i].SetActive(true); } } } private void EnsureSmoothing(int count) { if (_smoothedPositions == null || _smoothedPositions.Length < count) { Vector3[] array = (Vector3[])(object)new Vector3[count]; bool[] array2 = new bool[count]; if (_smoothedPositions != null) { Array.Copy(_smoothedPositions, array, _smoothedPositions.Length); Array.Copy(_wasVisible, array2, _wasVisible.Length); } _smoothedPositions = array; _wasVisible = array2; } } private void EnsurePool(int count) { if ((Object)(object)_sharedMaterial == (Object)null) { _sharedMaterial = CreateSharedMaterial(); } while (_dots.Count < count) { GameObject val = CreateDot(_dots.Count); _dots.Add(val); _renderers.Add(val.GetComponent<MeshRenderer>()); } } private GameObject CreateDot(int idx) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0); ((Object)obj).name = $"PathfinderDot_{idx}"; obj.transform.SetParent(((Component)this).transform, false); Collider component = obj.GetComponent<Collider>(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } MeshRenderer component2 = obj.GetComponent<MeshRenderer>(); ((Renderer)component2).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)component2).receiveShadows = false; ((Renderer)component2).lightProbeUsage = (LightProbeUsage)0; ((Renderer)component2).reflectionProbeUsage = (ReflectionProbeUsage)0; ((Renderer)component2).sharedMaterial = _sharedMaterial; float num = Mathf.Max(0.01f, Plugin.Instance.DotScale.Value); obj.transform.localScale = new Vector3(num, num, num); obj.SetActive(false); return obj; } private Material CreateSharedMaterial() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_002e: 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) Material val = new Material(Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Standard")); val.color = _baseColor; if (val.HasProperty("_Color")) { val.SetColor("_Color", _baseColor); } if (val.HasProperty("_ZWrite")) { val.SetInt("_ZWrite", 0); } if (val.HasProperty("_SrcBlend")) { val.SetInt("_SrcBlend", 5); } if (val.HasProperty("_DstBlend")) { val.SetInt("_DstBlend", 10); } val.renderQueue = 3500; return val; } private void ApplyDotAlpha(int i, float fade) { //IL_000d: 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_0043: Unknown result type (might be due to invalid IL or missing references) MeshRenderer obj = _renderers[i]; Color baseColor = _baseColor; baseColor.a = _baseColor.a * Mathf.Clamp01(fade); ((Renderer)obj).GetPropertyBlock(_mpb); _mpb.SetColor(ColorPropId, baseColor); ((Renderer)obj).SetPropertyBlock(_mpb); } private void HideAllDots() { for (int i = 0; i < _dots.Count; i++) { if ((Object)(object)_dots[i] != (Object)null && _dots[i].activeSelf) { _dots[i].SetActive(false); } } if (_wasVisible != null) { Array.Clear(_wasVisible, 0, _wasVisible.Length); } } private static Color ParseColor(string hex) { //IL_0028: 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) Color result = default(Color); if (!string.IsNullOrEmpty(hex) && ColorUtility.TryParseHtmlString(hex, ref result)) { return result; } return new Color(1f, 1f, 1f, 0.33f); } private void ShowToast(string text) { _toastText = text; _toastUntil = Time.unscaledTime + 1.5f; } private void OnGUI() { //IL_008b: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (!(Time.unscaledTime > _toastUntil) && !string.IsNullOrEmpty(_toastText)) { if (_toastStyle == null) { _toastStyle = new GUIStyle(GUI.skin.label) { fontSize = 18, alignment = (TextAnchor)4, fontStyle = (FontStyle)1 }; _toastStyle.normal.textColor = Color.white; } float num = 240f; float num2 = 40f; Rect val = new Rect(((float)Screen.width - num) / 2f, (float)Screen.height * 0.18f, num, num2); Color color = GUI.color; GUI.color = new Color(0f, 0f, 0f, 0.6f); GUI.Box(val, GUIContent.none); GUI.color = color; GUI.Label(val, _toastText, _toastStyle); } } } public enum PathfinderTargetMode { Auto, Truck } [BepInPlugin("isaia.repopathfinder", "REPOPathfinder", "0.7.2")] public class Plugin : BaseUnityPlugin { public const string GUID = "isaia.repopathfinder"; public const string NAME = "REPOPathfinder"; public const string VERSION = "0.7.2"; private const int CurrentConfigVersion = 3; public ConfigEntry<KeyCode> ToggleKey; public ConfigEntry<KeyCode> TargetToggleKey; public ConfigEntry<KeyCode> CustomizeMenuKey; public ConfigEntry<bool> EnabledOnStart; public ConfigEntry<PathfinderTargetMode> TargetMode; public ConfigEntry<float> Spacing; public ConfigEntry<int> MaxDots; public ConfigEntry<float> GroundOffset; public ConfigEntry<float> DotScale; public ConfigEntry<string> DotColorHex; public ConfigEntry<float> RecalcInterval; public ConfigEntry<float> MinDistanceToTarget; public ConfigEntry<float> FlowSpeed; public ConfigEntry<float> FadeZoneFraction; public ConfigEntry<float> PositionSmoothRate; public ConfigEntry<float> OffPathThreshold; public ConfigEntry<int> ConfigVersion; public static Plugin Instance { get; private set; } public static ManualLogSource Log { get; private set; } private void Awake() { //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Expected O, but got Unknown //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Expected O, but got Unknown //IL_031c: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Input", "ToggleKey", (KeyCode)285, "Key that toggles the on-the-ground guidance trail."); TargetToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Input", "TargetToggleKey", (KeyCode)286, "Key that switches the trail's destination between Auto (game-driven: current extraction, or truck when all are complete) and Truck (forces the truck so you can run back to charge items mid-run)."); CustomizeMenuKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Input", "CustomizeMenuKey", (KeyCode)287, "Key that opens/closes the in-game customization panel for changing dot color, size, flow speed, and spacing with live preview."); EnabledOnStart = ((BaseUnityPlugin)this).Config.Bind<bool>("Input", "EnabledOnStart", false, "If true, the trail is visible immediately on every level. If false, you must press the toggle key."); TargetMode = ((BaseUnityPlugin)this).Config.Bind<PathfinderTargetMode>("Input", "TargetMode", PathfinderTargetMode.Auto, "Current target mode. Auto follows the game's own pathing logic. Truck always points back to the truck regardless of extraction state. Persisted across sessions; toggle at runtime with TargetToggleKey."); Spacing = ((BaseUnityPlugin)this).Config.Bind<float>("Trail", "SpacingMeters", 1.5f, "Distance between dots in meters along the path."); MaxDots = ((BaseUnityPlugin)this).Config.Bind<int>("Trail", "MaxDots", 30, "Maximum number of dots placed at once. Higher values reach further but cost more."); GroundOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Trail", "GroundOffsetMeters", 0.1f, "Small vertical offset above the NavMesh surface so dots don't z-fight with the floor."); DotScale = ((BaseUnityPlugin)this).Config.Bind<float>("Trail", "DotScale", 0.07f, "Diameter of each dot in meters."); DotColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("Trail", "DotColorHex", "#FFFFFF55", "Dot color as #RRGGBBAA. Default is faint translucent white (~33% alpha)."); RecalcInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Trail", "RecalcIntervalSeconds", 0.25f, "[Deprecated as of 0.5.0 - has no effect.] Path is now cached and only recomputed when the player wanders off-path or the target changes; see OffPathRecomputeThresholdMeters."); MinDistanceToTarget = ((BaseUnityPlugin)this).Config.Bind<float>("Trail", "MinDistanceToTargetMeters", 1.5f, "If the player is within this distance of the target, dots are hidden."); FlowSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Trail", "FlowSpeedMetersPerSec", 2f, "How fast dots flow forward along the path, in meters per second. The trail recycles continuously so the path is always populated from the player."); FadeZoneFraction = ((BaseUnityPlugin)this).Config.Bind<float>("Trail", "FadeZoneFraction", 0.4f, "Fraction of one spacing over which dots fade in (near the player end of the recycle) and fade out (near the front). Smaller = sharper edges; larger = softer flow. Range 0.05-0.5."); PositionSmoothRate = ((BaseUnityPlugin)this).Config.Bind<float>("Trail", "PositionSmoothRate", 25f, "Damping rate for dot world positions (1/seconds). With the cached-path model the trail no longer translates with player movement, but smoothing still helps soften the rare jumps when the path is re-oriented after a turn. Higher = snappier. Lower = softer. Set to 0 to disable."); OffPathThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("Trail", "OffPathRecomputeThresholdMeters", 3f, "When the player drifts further than this many meters from the cached path's polyline, the path is recomputed. Lower values make the trail re-orient faster after a turn but can cause spurious recomputes when hugging walls in wide rooms; higher values are steadier but lag longer after a deliberate turn into a different corridor."); ConfigVersion = ((BaseUnityPlugin)this).Config.Bind<int>("Internal", "ConfigVersion", 0, "Internal: do not edit. Tracks which set of defaults this config was created with so newer mod versions can migrate stale values."); if (ConfigVersion.Value < 3) { MigrateConfig(ConfigVersion.Value); ConfigVersion.Value = 3; } GameObject val = new GameObject("REPOPathfinderManager"); Object.DontDestroyOnLoad((Object)val); ((Object)val).hideFlags = (HideFlags)61; val.AddComponent<PathfinderManager>(); val.AddComponent<PathfinderCustomizeUI>(); Harmony val2 = new Harmony("isaia.repopathfinder"); try { val2.PatchAll(Assembly.GetExecutingAssembly()); } catch (Exception ex) { Log.LogWarning((object)("Harmony PatchAll issues (non-fatal): " + ex.Message)); } InputBlocker.PatchInputSystem(val2); Log.LogInfo((object)string.Format("{0} {1} loaded. Toggle key: {2}", "REPOPathfinder", "0.7.2", ToggleKey.Value)); } private void MigrateConfig(int fromVersion) { if (DotColorHex.Value == "#00E5FFFF" || DotColorHex.Value == "#FFFFFFFF" || DotColorHex.Value == "#FFFFFF80") { DotColorHex.Value = (string)((ConfigEntryBase)DotColorHex).DefaultValue; } if (Mathf.Approximately(DotScale.Value, 0.25f) || Mathf.Approximately(DotScale.Value, 0.125f)) { DotScale.Value = (float)((ConfigEntryBase)DotScale).DefaultValue; } Log.LogInfo((object)$"Migrated config from version {fromVersion} -> {3}."); } } internal static class Reflect { private const BindingFlags InstanceAny = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; public static FieldInfo Field(Type t, string name) { if (t == null) { return null; } return t.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } public static T GetFieldValue<T>(FieldInfo fi, object instance, T fallback = default(T)) { if (fi == null || instance == null) { return fallback; } try { if (fi.GetValue(instance) is T result) { return result; } return fallback; } catch { return fallback; } } } public static class MyPluginInfo { public const string PLUGIN_GUID = "REPOPathfinder"; public const string PLUGIN_NAME = "REPOPathfinder"; public const string PLUGIN_VERSION = "0.7.2"; }