Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of FroggosGPS v1.2.1
Mods/Froggos-GPS.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using FroggosGps; using HarmonyLib; using Il2Cpp; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppPathfinding; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.Map; using Il2CppScheduleOne.Math; using Il2CppScheduleOne.NPCs; using Il2CppScheduleOne.PlayerScripts; using Il2CppScheduleOne.UI; using Il2CppScheduleOne.UI.Compass; using Il2CppScheduleOne.UI.Phone.Map; using Il2CppScheduleOne.Vehicles.AI; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Il2CppSystem.Reflection; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using S1API.PhoneApp; using S1API.UI; using S1API.Utils; using UnityEngine; using UnityEngine.AI; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(GpsMod), "Froggos-GPS", "1.2.1", "froggonater", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: MelonOptionalDependencies(new string[] { "S1API.Il2Cpp.MelonLoader" })] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("Froggos-GPS")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.2.1.0")] [assembly: AssemblyInformationalVersion("1.2.1")] [assembly: AssemblyProduct("Froggos-GPS")] [assembly: AssemblyTitle("Froggos-GPS")] [assembly: AssemblyVersion("1.2.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 FroggosGps { internal class GpsConfig { public readonly MelonPreferences_Category Category; public readonly MelonPreferences_Entry<string> LineColor; public readonly MelonPreferences_Entry<float> LineOpacity; public readonly MelonPreferences_Entry<float> LineWidth; public readonly MelonPreferences_Entry<float> HeightOffset; public readonly MelonPreferences_Entry<bool> FlatLine; public readonly MelonPreferences_Entry<bool> DrawThroughWalls; public readonly MelonPreferences_Entry<float> MaxDrawDistance; public readonly MelonPreferences_Entry<bool> ShowBeacon; public readonly MelonPreferences_Entry<string> ClearKey; public readonly MelonPreferences_Entry<string> RightClickAction; public readonly MelonPreferences_Entry<float> RecalcInterval; public readonly MelonPreferences_Entry<float> OffRouteDistance; public readonly MelonPreferences_Entry<float> ArrivalRadius; public readonly MelonPreferences_Entry<bool> RoadsAndPathsOnly; public readonly MelonPreferences_Entry<bool> UseRoadsWhenDriving; public readonly MelonPreferences_Entry<bool> RoadNetworkAlways; public readonly MelonPreferences_Entry<bool> ShowOnMinimap; public readonly MelonPreferences_Entry<float> MinimapLineWidth; public readonly MelonPreferences_Entry<float> OffPathAreaCost; public readonly MelonPreferences_Entry<float> RoadAreaCost; public readonly MelonPreferences_Entry<bool> ShowOnMap; public readonly MelonPreferences_Entry<float> MapLineWidthMeters; public readonly MelonPreferences_Entry<bool> ShowOnCompass; public readonly MelonPreferences_Entry<bool> ShowHud; public readonly MelonPreferences_Entry<bool> NotifyOnArrival; public readonly MelonPreferences_Entry<bool> VerboseLogging; private bool _suppress; public event Action Changed; public GpsConfig() { Category = MelonPreferences.CreateCategory("Froggos-GPS", "Froggos-GPS"); LineColor = Category.CreateEntry<string>("LineColor", "#00E5FF", (string)null, "Route color as hex (#RRGGBB).", false, false, (ValueValidator)null, (string)null); LineOpacity = Category.CreateEntry<float>("LineOpacity", 0.9f, (string)null, "Route opacity, 0.1 (very see-through) to 1 (solid).", false, false, (ValueValidator)null, (string)null); LineWidth = Category.CreateEntry<float>("LineWidth", 0.6f, (string)null, "Route line width in meters.", false, false, (ValueValidator)null, (string)null); HeightOffset = Category.CreateEntry<float>("HeightOffset", 0.25f, (string)null, "How far above the ground the line floats (meters).", false, false, (ValueValidator)null, (string)null); FlatLine = Category.CreateEntry<bool>("FlatLine", true, (string)null, "true = line lies flat on the ground like a road marking; false = ribbon that always faces the camera.", false, false, (ValueValidator)null, (string)null); DrawThroughWalls = Category.CreateEntry<bool>("DrawThroughWalls", false, (string)null, "Draw the route on top of everything (visible through buildings/hills).", false, false, (ValueValidator)null, (string)null); MaxDrawDistance = Category.CreateEntry<float>("MaxDrawDistance", 600f, (string)null, "Only draw this many meters of route ahead of you.", false, false, (ValueValidator)null, (string)null); ShowBeacon = Category.CreateEntry<bool>("ShowBeacon", true, (string)null, "Draw a tall light beam at the destination.", false, false, (ValueValidator)null, (string)null); ClearKey = Category.CreateEntry<string>("ClearKey", "G", (string)null, "Key that clears the route (UnityEngine.InputSystem.Key name, e.g. G, F7, Backquote).", false, false, (ValueValidator)null, (string)null); RightClickAction = Category.CreateEntry<string>("RightClickAction", "Clear", (string)null, "What right-clicking the phone map does: Clear or Set.", false, false, (ValueValidator)null, (string)null); RecalcInterval = Category.CreateEntry<float>("RecalcInterval", 1f, (string)null, "Refresh rate: seconds between route updates while moving.", false, false, (ValueValidator)null, (string)null); OffRouteDistance = Category.CreateEntry<float>("OffRouteDistance", 10f, (string)null, "Recalculate immediately when this far (meters) from the route.", false, false, (ValueValidator)null, (string)null); ArrivalRadius = Category.CreateEntry<float>("ArrivalRadius", 5f, (string)null, "Route clears when you are this close (meters) to the destination.", false, false, (ValueValidator)null, (string)null); RoadsAndPathsOnly = Category.CreateEntry<bool>("RoadsAndPathsOnly", true, (string)null, "On foot, keep the route on roads and sidewalks/paths (no shortcuts across grass or lots).", false, false, (ValueValidator)null, (string)null); UseRoadsWhenDriving = Category.CreateEntry<bool>("UseRoadsWhenDriving", true, (string)null, "Use the game's vehicle road graph when you're in a vehicle.", false, false, (ValueValidator)null, (string)null); RoadNetworkAlways = Category.CreateEntry<bool>("RoadNetworkAlways", true, (string)null, "Use the road network (quickest route by road) for every route, walking or driving. Falls back to NavMesh roads/paths when unavailable.", false, false, (ValueValidator)null, (string)null); ShowOnMinimap = Category.CreateEntry<bool>("ShowOnMinimap", true, (string)null, "Draw the route on the MultiMiniMap minimap (if that mod is installed).", false, false, (ValueValidator)null, (string)null); MinimapLineWidth = Category.CreateEntry<float>("MinimapLineWidth", 4f, (string)null, "Route thickness on the minimap, in pixels.", false, false, (ValueValidator)null, (string)null); OffPathAreaCost = Category.CreateEntry<float>("OffPathAreaCost", 3f, (string)null, "NavMesh cost for open ground when RoadsAndPathsOnly is off. Sidewalks/paths cost 1.", false, false, (ValueValidator)null, (string)null); RoadAreaCost = Category.CreateEntry<float>("RoadAreaCost", 1.5f, (string)null, "NavMesh cost for road surface when walking (1 = as good as a sidewalk; the game's NPCs use 5).", false, false, (ValueValidator)null, (string)null); ShowOnMap = Category.CreateEntry<bool>("ShowOnMap", true, (string)null, "Draw the route and destination on the phone map.", false, false, (ValueValidator)null, (string)null); MapLineWidthMeters = Category.CreateEntry<float>("MapLineWidthMeters", 6f, (string)null, "Thickness of the route on the phone map, in world meters.", false, false, (ValueValidator)null, (string)null); ShowOnCompass = Category.CreateEntry<bool>("ShowOnCompass", true, (string)null, "Show the destination on the HUD compass.", false, false, (ValueValidator)null, (string)null); ShowHud = Category.CreateEntry<bool>("ShowHud", true, (string)null, "Show distance and ETA to the destination on screen.", false, false, (ValueValidator)null, (string)null); NotifyOnArrival = Category.CreateEntry<bool>("NotifyOnArrival", true, (string)null, "Phone notification when you arrive.", false, false, (ValueValidator)null, (string)null); VerboseLogging = Category.CreateEntry<bool>("VerboseLogging", false, (string)null, "Log every recalculation.", false, false, (ValueValidator)null, (string)null); foreach (MelonPreferences_Entry entry in Category.Entries) { ((MelonEventBase<LemonAction<object, object>>)(object)entry.OnEntryValueChangedUntyped).Subscribe((LemonAction<object, object>)delegate { RaiseChanged(); }, 0, false); } } public void RaiseChanged() { if (_suppress) { return; } try { this.Changed?.Invoke(); } catch (Exception ex) { GpsMod.Log.Error("Settings change handler failed: " + ex); } } public void Set<T>(MelonPreferences_Entry<T> entry, T value) { _suppress = true; try { entry.Value = value; } finally { _suppress = false; } Category.SaveToFile(false); RaiseChanged(); } public Color BaseColor() { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) string text = (LineColor.Value ?? "").Trim().TrimStart('#'); try { if (text.Length == 6 || text.Length == 8) { float num = (float)Convert.ToInt32(text.Substring(0, 2), 16) / 255f; float num2 = (float)Convert.ToInt32(text.Substring(2, 2), 16) / 255f; float num3 = (float)Convert.ToInt32(text.Substring(4, 2), 16) / 255f; return new Color(num, num2, num3, 1f); } } catch { } return new Color(0f, 0.9f, 1f, 1f); } public Color ParseLineColor() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) Color result = BaseColor(); result.a = Mathf.Clamp(LineOpacity.Value, 0.05f, 1f); return result; } public static string ToHex(Color c) { //IL_0005: 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_0039: Unknown result type (might be due to invalid IL or missing references) return "#" + ((int)(c.r * 255f)).ToString("X2") + ((int)(c.g * 255f)).ToString("X2") + ((int)(c.b * 255f)).ToString("X2"); } } public class GpsController : MonoBehaviour { private static GpsController s_instance; private GpsCore _core; private int _errorCount; private float _nextErrorLog; public GpsController(IntPtr ptr) : base(ptr) { } internal static void EnsureCreated() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)s_instance != (Object)null)) { s_instance = new GameObject("Froggos-GPS").AddComponent<GpsController>(); GpsMod.Log.Msg("GPS controller created."); } } private void Update() { try { if (_core == null) { _core = new GpsCore(((Component)this).gameObject); } _core.Update(); } catch (Exception value) { _errorCount++; if (_errorCount <= 5 || Time.unscaledTime >= _nextErrorLog) { _nextErrorLog = Time.unscaledTime + 10f; GpsMod.Log.Error($"Update error #{_errorCount}: {value}"); } } } private void OnDestroy() { try { _core?.Destroy(); } catch (Exception ex) { GpsMod.Log.Error("Cleanup error: " + ex); } _core = null; if ((Object)(object)s_instance == (Object)(object)this) { s_instance = null; } } } internal class GpsCore { private readonly GameObject _host; private readonly RoutePlanner _planner; private readonly RouteRenderer _renderer; private readonly MapOverlay _map = new MapOverlay(); private bool _hasDest; private Vector3 _dest; private GameObject _destObject; private Element _compassElement; private RectTransform _compassTemplate; private bool _compassFailed; private bool _forceRecalc; private float _lastCalcTime = -999f; private Vector3 _lastCalcPos; private RouteMode _lastMode; private bool _lastFailed; private string _lastFailureInfo; private bool _loggedFirstRoute; private int _recalcCount; private Key _clearKey = (Key)21; private string _parsedKeyName; private readonly GpsHud _hud; private string _destLabel = ""; private List<Vector3> _lastRoutePoints; private Vector3 _speedSamplePos; private float _speedSampleTime; private float _speed; private float _nextHudUpdate; private bool _settingsDirty; public static Action UiTick; private Transform _followTarget; private float _nextFollowCheck; private const float FollowCheckInterval = 2f; private const float FollowMoveThreshold = 8f; private bool _currentComplete; private bool _roadFallbackLogged; public static GpsCore Instance { get; private set; } public bool HasDestination => _hasDest; public string DestinationLabel => _destLabel; public RouteMode CurrentMode => _lastMode; public bool RouteFailed => _lastFailed; public float RemainingMeters { get { if (!_renderer.HasRoute) { return 0f; } return _renderer.RemainingLength(); } } public float EtaSeconds { get; private set; } = float.NaN; public GpsCore(GameObject host) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) _host = host; _planner = new RoutePlanner(host); _renderer = new RouteRenderer(host.transform); _hud = new GpsHud(host.transform); Instance = this; GpsMod.Cfg.Changed += OnSettingsChanged; } public void Update() { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) _planner.Tick(); HandleHotkey(); _map.HandleInput(this); if (_settingsDirty) { ApplySettings(); } try { UiTick?.Invoke(); } catch (Exception ex) { GpsMod.Verbose("Phone app tick failed: " + ex.Message); } Player local = Player.Local; if (!_hasDest || (Object)(object)local == (Object)null) { _hud.Hide(); return; } bool inVehicle; Vector3 playerPosition = GetPlayerPosition(local, out inVehicle); UpdateFollow(); UpdateSpeedAndHud(playerPosition, inVehicle); if (RoutePlanner.HorizontalDistance(playerPosition, _dest) <= GpsMod.Cfg.ArrivalRadius.Value && Mathf.Abs(playerPosition.y - _dest.y) < 6f) { GpsMod.Log.Msg("Arrived at destination " + RoutePlanner.Fmt(_dest) + ". Route cleared."); Notify("You have arrived", string.IsNullOrEmpty(_destLabel) ? "Destination reached" : _destLabel); ClearRoute(null); return; } RouteMode routeMode = ((GpsMod.Cfg.RoadNetworkAlways.Value || (inVehicle && GpsMod.Cfg.UseRoadsWhenDriving.Value)) ? RouteMode.Drive : RouteMode.Walk); float num = Time.unscaledTime - _lastCalcTime; float num2 = Mathf.Max(0.2f, GpsMod.Cfg.RecalcInterval.Value); string text = null; if (_forceRecalc) { text = "new destination"; } else if (routeMode != _lastMode) { text = $"mode changed to {routeMode}"; } else if (_lastFailed) { if (num >= Mathf.Max(num2, 3f)) { text = "retry after failure"; } } else if (num >= num2) { Vector3 val = playerPosition - _lastCalcPos; if (((Vector3)(ref val)).sqrMagnitude > 1f) { text = "interval"; } } if (text == null && _renderer.HasRoute && num >= 0.3f) { float num3 = _renderer.DistanceFromRoute(playerPosition); if (num3 > GpsMod.Cfg.OffRouteDistance.Value) { text = $"off route by {num3:F1}m"; } } if (text != null && !_planner.DriveInFlight) { Recalculate(playerPosition, routeMode, text); } _renderer.UpdateView(playerPosition); } private void UpdateSpeedAndHud(Vector3 pos, bool inVehicle) { //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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) float unscaledTime = Time.unscaledTime; if (unscaledTime - _speedSampleTime >= 0.5f) { if (_speedSampleTime > 0f) { float num = RoutePlanner.HorizontalDistance(pos, _speedSamplePos) / (unscaledTime - _speedSampleTime); _speed = Mathf.Lerp(_speed, Mathf.Min(num, 60f), 0.3f); } _speedSamplePos = pos; _speedSampleTime = unscaledTime; } float remainingMeters = RemainingMeters; float num2 = (inVehicle ? 12f : 3.2f); EtaSeconds = ((remainingMeters > 0f) ? (remainingMeters / Mathf.Max(_speed, num2 * 0.6f)) : float.NaN); if (!GpsMod.Cfg.ShowHud.Value) { _hud.Hide(); } else if (!(unscaledTime < _nextHudUpdate)) { _nextHudUpdate = unscaledTime + 0.25f; string text = (string.IsNullOrEmpty(_destLabel) ? "" : (" · " + _destLabel)); string text2 = ((_lastFailed && !_renderer.HasRoute) ? ("GPS: no route found" + text) : (GpsHud.FormatDistance(remainingMeters) + " · " + GpsHud.FormatEta(EtaSeconds) + text)); _hud.Show(text2, GpsMod.Cfg.BaseColor()); } } private static void Notify(string title, string subtitle) { if (!GpsMod.Cfg.NotifyOnArrival.Value) { return; } try { if (Singleton<NotificationsManager>.InstanceExists) { Singleton<NotificationsManager>.Instance.SendNotification(title, subtitle, GpsIcon.Get(), 5f, true); } } catch (Exception ex) { GpsMod.Verbose("Notification failed: " + ex.Message); } } private void OnSettingsChanged() { _settingsDirty = true; } private void ApplySettings() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) _settingsDirty = false; _renderer.ApplyStyle(); _map.ApplyStyle(); if (_hasDest) { if (GpsMod.Cfg.ShowOnMap.Value && _lastRoutePoints != null) { _map.DrawRoute(_lastRoutePoints, _dest); } if (GpsMod.Cfg.ShowOnCompass.Value) { AddCompassMarker(); } else { RemoveCompassMarker(); } _forceRecalc = true; } if (!GpsMod.Cfg.ShowHud.Value) { _hud.Hide(); } GpsMod.Verbose("Settings applied."); } public void OnMapOpened() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (_hasDest && _lastRoutePoints != null && GpsMod.Cfg.ShowOnMap.Value) { _map.DrawRoute(_lastRoutePoints, _dest); } } public void Reroute() { _forceRecalc = true; } internal bool TryGetMinimapRoute(out List<Vector3> points, out int start, out Vector3 destination, out Vector3 player, out MapProjection projection) { //IL_001c: 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_0036: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) points = _renderer.DensePoints; start = _renderer.TrimIndex; destination = _dest; projection = _map.Projection; player = Vector3.zero; Player local = Player.Local; if (!_hasDest || (Object)(object)local == (Object)null || points.Count < 2) { return false; } player = ((Component)local).transform.position; if (!projection.Valid) { return projection.Calibrate(); } return true; } private static Vector3 GetPlayerPosition(Player player, out bool inVehicle) { //IL_002f: 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) inVehicle = player.IsInVehicle && (Object)(object)player.CurrentVehicle != (Object)null; if (inVehicle) { return ((Component)player.CurrentVehicle).transform.position; } return player.PlayerBasePosition; } private static bool IsTypingInUi() { try { EventSystem current = EventSystem.current; GameObject val = (((Object)(object)current != (Object)null) ? current.currentSelectedGameObject : null); if ((Object)(object)val == (Object)null) { return false; } InputField component = val.GetComponent<InputField>(); return (Object)(object)component != (Object)null && component.isFocused; } catch { return false; } } private void HandleHotkey() { //IL_0051: 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_0090: Unknown result type (might be due to invalid IL or missing references) string value = GpsMod.Cfg.ClearKey.Value; if (value != _parsedKeyName) { _parsedKeyName = value; if (!Enum.TryParse<Key>(value, ignoreCase: true, out _clearKey)) { GpsMod.Log.Warning("ClearKey '" + value + "' is not a valid InputSystem key name; using G."); _clearKey = (Key)21; } } Keyboard current = Keyboard.current; if (current != null && !IsTypingInUi() && ((ButtonControl)current[_clearKey]).wasPressedThisFrame && _hasDest) { ClearRoute($"{_clearKey} key"); } } public void SetDestination(Vector2 worldXZ, string source) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) SetDestination(worldXZ, source, ""); _followTarget = null; } public bool SetDestinationWorld(Vector3 world, string label) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) SetDestination(new Vector2(world.x, world.z), "phone app", label); _followTarget = null; return _hasDest; } public bool SetDestinationFollow(Transform target, string label) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_001f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)target == (Object)null) { return false; } Vector3 position = target.position; SetDestination(new Vector2(position.x, position.z), "phone app (following)", label); _followTarget = (_hasDest ? target : null); _nextFollowCheck = Time.unscaledTime + 2f; return _hasDest; } private void UpdateFollow() { //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_0048: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: 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) if ((Object)(object)_followTarget == (Object)null || Time.unscaledTime < _nextFollowCheck) { return; } _nextFollowCheck = Time.unscaledTime + 2f; Vector3 position; try { position = _followTarget.position; } catch { _followTarget = null; return; } if (RoutePlanner.HorizontalDistance(position, _dest) < 8f) { return; } Player local = Player.Local; float referenceY = (((Object)(object)local != (Object)null) ? local.PlayerBasePosition.y : position.y); if (_planner.ResolveDestination(position.x, position.z, referenceY, out var result, out var _)) { _dest = result; if ((Object)(object)_destObject != (Object)null) { _destObject.transform.position = result; } _forceRecalc = true; GpsMod.Verbose($"Follow target '{_destLabel}' moved; destination now {RoutePlanner.Fmt(result)}."); } } private void SetDestination(Vector2 worldXZ, string source, string label) { //IL_0017: 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) //IL_002e: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_0127: 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_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) Player local = Player.Local; float referenceY = (((Object)(object)local != (Object)null) ? local.PlayerBasePosition.y : 0f); if (!_planner.ResolveDestination(worldXZ.x, worldXZ.y, referenceY, out var result, out var how)) { GpsMod.Log.Warning($"Destination from {source} rejected: clicked ({worldXZ.x:F1}, {worldXZ.y:F1}) - {how}"); return; } _destLabel = label ?? ""; _lastRoutePoints = null; _dest = result; _hasDest = true; _forceRecalc = true; _lastFailed = false; _lastFailureInfo = null; _loggedFirstRoute = false; _recalcCount = 0; _planner.CancelDrive(); float value = (((Object)(object)local != (Object)null) ? Vector3.Distance(local.PlayerBasePosition, result) : (-1f)); GpsMod.Log.Msg($"Destination set from {source}: clicked XZ ({worldXZ.x:F1}, {worldXZ.y:F1}) -> {RoutePlanner.Fmt(result)} [{how}], {value:F0}m away."); EnsureDestObject(); _destObject.transform.position = result; AddCompassMarker(); } public void ClearRoute(string reason) { if (reason != null && _hasDest) { GpsMod.Log.Msg("Route cleared (" + reason + ")."); } _hasDest = false; _forceRecalc = false; _planner.CancelDrive(); _renderer.Clear(); _map.ClearMap(); _hud.Hide(); _lastRoutePoints = null; _followTarget = null; _destLabel = ""; EtaSeconds = float.NaN; RemoveCompassMarker(); } private void Recalculate(Vector3 pos, RouteMode mode, string reason) { //IL_000e: 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) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) _forceRecalc = false; _lastCalcTime = Time.unscaledTime; _lastCalcPos = pos; _lastMode = mode; _recalcCount++; Vector3 dest = _dest; if (mode == RouteMode.Drive) { if (_planner.RequestDrive(pos, dest, delegate(RouteResult r) { //IL_000e: 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_0079: 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) if (_hasDest && !(dest != _dest)) { if (r.Points.Count < 2) { if (!_roadFallbackLogged) { _roadFallbackLogged = true; GpsMod.Log.Warning("Road network route failed (" + r.Info + "); using the NavMesh road/path route instead."); } OnRoute(SafePlanWalk(pos, dest), reason + " (road network fallback)"); } else { OnRoute(r, reason); } } })) { return; } GpsMod.Log.Warning("Vehicle road graph unavailable; using on-foot NavMesh route while driving."); } OnRoute(SafePlanWalk(pos, dest), reason); } private RouteResult SafePlanWalk(Vector3 from, Vector3 to) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) try { return _planner.PlanWalk(from, to); } catch (Exception ex) { return new RouteResult { Mode = RouteMode.Walk, Info = "exception: " + ex }; } } private void OnRoute(RouteResult r, string reason) { //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) if (r == null || r.Points.Count < 2) { string text = r?.Info ?? "no result"; if (!_lastFailed || text != _lastFailureInfo) { GpsMod.Log.Warning("Route FAILED (" + reason + "): " + text); } _lastFailed = true; _lastFailureInfo = text; return; } if ((reason == "interval" || reason.StartsWith("interval ")) && _renderer.HasRoute && !_lastFailed) { float num = _renderer.RemainingLength(); float num2 = r.Length(); bool num3 = num2 < num - Mathf.Max(25f, num * 0.1f); bool flag = !r.Complete && _currentComplete; if (!num3 || flag) { GpsMod.Verbose($"Kept current route ({num:F0}m left); candidate {num2:F0}m [{r.Mode}] wasn't clearly better."); return; } GpsMod.Verbose($"Switched to a shorter route: {num2:F0}m vs {num:F0}m left."); } bool lastFailed = _lastFailed; _lastFailed = false; _lastFailureInfo = null; _currentComplete = r.Complete; _roadFallbackLogged = r.Mode != RouteMode.Drive && _roadFallbackLogged; _lastRoutePoints = r.Points; _renderer.SetRoute(r.Points, _dest); _map.DrawRoute(r.Points, _dest); string text2 = $"Route found [{r.Mode}] ({reason}): {r.Points.Count} nodes, {r.Length():F0}m, {_renderer.DenseCount} line points, {r.Millis:F1}ms - {r.Info}"; if (!_loggedFirstRoute || lastFailed || !r.Complete) { _loggedFirstRoute = true; GpsMod.Log.Msg(text2); return; } GpsMod.Verbose($"#{_recalcCount} " + text2); } private void EnsureDestObject() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown if (!((Object)(object)_destObject != (Object)null)) { _destObject = new GameObject("GPS_Destination"); _destObject.transform.SetParent(_host.transform, false); } } private RectTransform GetCompassTemplate() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0096: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_compassTemplate != (Object)null) { return _compassTemplate; } GameObject val = new GameObject("GPS_CompassTemplateHolder"); val.transform.SetParent(_host.transform, false); val.SetActive(false); GameObject val2 = new GameObject("GPS_CompassIcon"); RectTransform val3 = val2.AddComponent<RectTransform>(); ((Transform)val3).SetParent(val.transform, false); val3.sizeDelta = new Vector2(16f, 16f); ((Transform)val3).localRotation = Quaternion.Euler(0f, 0f, 45f); Image obj = val2.AddComponent<Image>(); ((Graphic)obj).color = GpsMod.Cfg.ParseLineColor(); ((Graphic)obj).raycastTarget = false; _compassTemplate = val3; return val3; } private void AddCompassMarker() { if (!GpsMod.Cfg.ShowOnCompass.Value || _compassFailed || _compassElement != null) { return; } try { if (Singleton<CompassManager>.InstanceExists) { _compassElement = Singleton<CompassManager>.Instance.AddElement(_destObject.transform, GetCompassTemplate(), true); } } catch (Exception ex) { _compassFailed = true; GpsMod.Log.Warning("Compass marker disabled (AddElement failed): " + ex.Message); } } private void RemoveCompassMarker() { if (_compassElement == null) { return; } try { if (Singleton<CompassManager>.InstanceExists) { Singleton<CompassManager>.Instance.RemoveElement(_compassElement, true); } } catch (Exception ex) { GpsMod.Verbose("Compass RemoveElement failed: " + ex.Message); } _compassElement = null; } public void Destroy() { GpsMod.Cfg.Changed -= OnSettingsChanged; ClearRoute(null); _renderer.Destroy(); _map.Destroy(); _hud.Destroy(); if (Instance == this) { Instance = null; } } } internal class GpsHud { private readonly GameObject _root; private Text _text; private bool _fontResolved; public GpsHud(Transform parent) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_005e: 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_007d: Expected O, but got Unknown //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) _root = new GameObject("GPS_Hud"); _root.transform.SetParent(parent, false); Canvas obj = _root.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 40; CanvasScaler obj2 = _root.AddComponent<CanvasScaler>(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); obj2.matchWidthOrHeight = 0.5f; GameObject val = new GameObject("GPS_HudText"); RectTransform obj3 = val.AddComponent<RectTransform>(); ((Transform)obj3).SetParent(_root.transform, false); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0.5f, 1f); obj3.anchorMax = val2; obj3.anchorMin = val2; obj3.pivot = new Vector2(0.5f, 1f); obj3.anchoredPosition = new Vector2(0f, -95f); obj3.sizeDelta = new Vector2(700f, 44f); _text = val.AddComponent<Text>(); _text.alignment = (TextAnchor)4; _text.fontSize = 26; ((Graphic)_text).raycastTarget = false; _text.horizontalOverflow = (HorizontalWrapMode)1; Shadow obj4 = val.AddComponent<Shadow>(); obj4.effectColor = new Color(0f, 0f, 0f, 0.85f); obj4.effectDistance = new Vector2(2f, -2f); _root.SetActive(false); } private void ResolveFont() { if (_fontResolved) { return; } _fontResolved = true; try { foreach (Text item in Object.FindObjectsOfType<Text>()) { if ((Object)(object)item != (Object)null && (Object)(object)item != (Object)(object)_text && (Object)(object)item.font != (Object)null) { _text.font = item.font; return; } } } catch (Exception ex) { GpsMod.Verbose("HUD font lookup failed: " + ex.Message); } try { _text.font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf"); } catch { } } public void Show(string text, Color color) { //IL_0031: 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_005b: 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) ResolveFont(); if (!_root.activeSelf) { _root.SetActive(true); } _text.text = text; ((Graphic)_text).color = new Color(Mathf.Lerp(color.r, 1f, 0.25f), Mathf.Lerp(color.g, 1f, 0.25f), Mathf.Lerp(color.b, 1f, 0.25f), 1f); } public void Hide() { if (_root.activeSelf) { _root.SetActive(false); } } public void Destroy() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } } public static string FormatDistance(float meters) { if (meters >= 1000f) { return $"{meters / 1000f:0.0} km"; } return $"{Mathf.Round(meters / 5f) * 5f:0} m"; } public static string FormatEta(float seconds) { if (float.IsNaN(seconds) || float.IsInfinity(seconds)) { return "--"; } if (seconds < 60f) { return "<1 min"; } int num = Mathf.RoundToInt(seconds / 60f); if (num < 60) { return $"{num} min"; } return $"{num / 60}h {num % 60:00}m"; } } internal static class GpsIcon { private static Sprite s_sprite; public static Sprite Get() { //IL_00aa: 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_00ae: 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_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: 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_0214: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Expected O, but got Unknown if ((Object)(object)s_sprite != (Object)null) { return s_sprite; } Color32[] array = (Color32[])(object)new Color32[16384]; Color32 val = default(Color32); ((Color32)(ref val))..ctor((byte)22, (byte)30, (byte)38, byte.MaxValue); Color32 val2 = default(Color32); ((Color32)(ref val2))..ctor((byte)32, (byte)52, (byte)48, byte.MaxValue); Color32 col = default(Color32); ((Color32)(ref col))..ctor((byte)0, (byte)229, byte.MaxValue, byte.MaxValue); Color32 col2 = default(Color32); ((Color32)(ref col2))..ctor(byte.MaxValue, (byte)70, (byte)90, byte.MaxValue); Color32 col3 = default(Color32); ((Color32)(ref col3))..ctor(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue); for (int i = 0; i < 128; i++) { for (int j = 0; j < 128; j++) { float num = (float)i / 128f; array[i * 128 + j] = Color32.Lerp(val, val2, num); } } Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(22f, 18f); Vector2 val4 = default(Vector2); for (int k = 1; k <= 200; k++) { float num2 = (float)k / 200f; ((Vector2)(ref val4))..ctor(22f + 62f * num2 + 18f * Mathf.Sin(num2 * 7.5f), 18f + 70f * num2); Stamp(array, 128, Vector2.Lerp(val3, val4, 0.5f), 6.5f, col); Stamp(array, 128, val4, 6.5f, col); val3 = val4; } Stamp(array, 128, new Vector2(86f, 96f), 17f, col2); Stamp(array, 128, new Vector2(86f, 96f), 7f, col3); Texture2D val5 = new Texture2D(128, 128, (TextureFormat)4, false) { filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1 }; val5.SetPixels32(new Il2CppStructArray<Color32>(array)); val5.Apply(); ((Object)val5).hideFlags = (HideFlags)32; s_sprite = Sprite.Create(val5, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f)); ((Object)s_sprite).hideFlags = (HideFlags)32; return s_sprite; } private static void Stamp(Color32[] px, int n, Vector2 c, float r, Color32 col) { //IL_0001: 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_002f: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_00ae: 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) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Max(0, (int)(c.x - r - 1f)); int num2 = Mathf.Min(n - 1, (int)(c.x + r + 1f)); int num3 = Mathf.Max(0, (int)(c.y - r - 1f)); int num4 = Mathf.Min(n - 1, (int)(c.y + r + 1f)); for (int i = num3; i <= num4; i++) { for (int j = num; j <= num2; j++) { float num5 = Vector2.Distance(new Vector2((float)j + 0.5f, (float)i + 0.5f), c); float num6 = Mathf.Clamp01(r - num5 + 0.5f); if (!(num6 <= 0f)) { int num7 = i * n + j; px[num7] = Color32.Lerp(px[num7], col, num6); } } } } } public class GpsMod : MelonMod { internal static Instance Log; internal static GpsConfig Cfg; public override void OnInitializeMelon() { Log = ((MelonBase)this).LoggerInstance; Cfg = new GpsConfig(); ClassInjector.RegisterTypeInIl2Cpp<GpsController>(); Log.Msg("Froggos-GPS loaded. Open the phone Map app and left-click a spot to set a destination. Clear with [" + Cfg.ClearKey.Value + "] or right-click the map."); Log.Msg(IsS1ApiLoaded() ? "S1API found: the 'GPS' phone app (settings + places) will be added to the phone." : "S1API not installed: no GPS phone app; edit settings in UserData/MelonPreferences.cfg instead."); } public override void OnLateInitializeMelon() { MinimapBridge.TryPatch(((MelonBase)this).HarmonyInstance); } internal static bool IsS1ApiLoaded() { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { if (assemblies[i].GetName().Name == "S1API.Il2Cpp.MelonLoader") { return true; } } return false; } public override void OnSceneWasInitialized(int buildIndex, string sceneName) { Log.Msg($"Scene initialized: '{sceneName}' (index {buildIndex})"); if (!(sceneName == "Menu")) { GpsController.EnsureCreated(); } } internal static void Verbose(string msg) { if (Cfg != null && Cfg.VerboseLogging.Value) { Log.Msg("[verbose] " + msg); } } } [HarmonyPatch(typeof(MapApp), "SetOpen")] internal static class MapAppSetOpenPatch { private static void Postfix(MapApp __instance, bool open) { try { MapOverlay.OnMapAppSetOpen(__instance, open); if (open) { GpsCore.Instance?.OnMapOpened(); } } catch (Exception ex) { GpsMod.Log.Error("MapApp.SetOpen postfix failed: " + ex); } } } public class GpsPhoneApp : PhoneApp { private sealed class Destination { public string Name; public string Kind; public Transform Follow; public Vector3 Fixed; public Vector3 Position { get { //IL_001b: 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 (!((Object)(object)Follow != (Object)null)) { return Fixed; } return Follow.position; } } } private static readonly Color BgColor = new Color(0.07f, 0.08f, 0.1f, 1f); private static readonly Color RowColor = new Color(1f, 1f, 1f, 0.04f); private static readonly Color ButtonColor = new Color(0.2f, 0.23f, 0.28f, 1f); private static readonly Color OnColor = new Color(0.16f, 0.62f, 0.36f, 1f); private static readonly Color OffColor = new Color(0.33f, 0.33f, 0.36f, 1f); private static readonly Color DangerColor = new Color(0.72f, 0.24f, 0.26f, 1f); private static readonly Color MutedText = new Color(0.72f, 0.75f, 0.8f, 1f); private static readonly (string Name, string Hex)[] Palette = new(string, string)[9] { ("Cyan", "#00E5FF"), ("Green", "#39FF14"), ("Yellow", "#FFE600"), ("Orange", "#FF8C00"), ("Red", "#FF3B3B"), ("Pink", "#FF4FD8"), ("Purple", "#9D5CFF"), ("Blue", "#2F7BFF"), ("White", "#FFFFFF") }; private static readonly float[] RefreshSteps = new float[7] { 0.25f, 0.5f, 1f, 1.5f, 2f, 3f, 5f }; private static readonly float[] OpacitySteps = new float[10] { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1f }; private static readonly float[] WidthSteps = new float[8] { 0.25f, 0.4f, 0.6f, 0.8f, 1f, 1.3f, 1.7f, 2.2f }; private static readonly float[] MapWidthSteps = new float[6] { 3f, 4f, 6f, 8f, 10f, 14f }; private static readonly float[] DrawDistSteps = new float[5] { 150f, 300f, 600f, 1000f, 2000f }; private RectTransform _list; private Text _statusTitle; private Text _statusDetail; private GameObject _placesBox; private readonly List<Action> _refreshers = new List<Action>(); private bool _wasOpen; private float _nextStatus; private RectTransform _frame; private RectTransform _container; private bool _fitted; private const float K = 1.6f; private readonly List<Destination> _destinations = new List<Destination>(); private string _query = ""; private bool _placesExpanded; private Text _placesToggleLabel; private const int MaxNearby = 20; private const int MaxResults = 30; protected override string AppName => "FroggosGPS"; protected override string AppTitle => "Froggos GPS"; protected override string IconLabel => "GPS"; protected override string IconFileName => "FroggosGPS.png"; protected override Sprite IconSprite => GpsIcon.Get(); protected override EOrientation Orientation => (EOrientation)1; protected override void OnCreatedUI(GameObject container) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: 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: Expected O, but got Unknown //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Expected O, but got Unknown //IL_0514: Unknown result type (might be due to invalid IL or missing references) _refreshers.Clear(); GpsCore.UiTick = Tick; UIFactory.Panel("GPS_Backdrop", container.transform, BgColor, (Vector2?)null, (Vector2?)null, true); GameObject val = UIFactory.Panel("GPS_Bg", container.transform, BgColor, (Vector2?)null, (Vector2?)null, true); _frame = val.GetComponent<RectTransform>(); _container = container.GetComponent<RectTransform>(); _fitted = false; GameObject val2 = UIFactory.Panel("GPS_Header", val.transform, new Color(0.1f, 0.13f, 0.16f, 1f), (Vector2?)new Vector2(0f, 0.895f), (Vector2?)new Vector2(1f, 0.97f), false); Stretch(((Graphic)MakeText("GPS_Title", "Froggos GPS", val2.transform, 28, (TextAnchor)3, (FontStyle)1)).rectTransform, 24f); GameObject val3 = UIFactory.Panel("GPS_Body", val.transform, new Color(0f, 0f, 0f, 0f), (Vector2?)new Vector2(0f, 0.005f), (Vector2?)new Vector2(1f, 0.89f), false); ScrollRect scroll = default(ScrollRect); _list = UIFactory.ScrollableVerticalList("GPS_List", val3.transform, ref scroll); FitListToViewport(scroll); SetupScrolling(scroll, val3.GetComponent<RectTransform>()); Section("ROUTE"); _statusTitle = Label("No destination", 22, (FontStyle)1, Color.white, 34f); _statusDetail = Label("Open the Map app and left-click anywhere, or pick a place below.", 17, (FontStyle)0, MutedText, 48f); GameObject val4 = Row("GPS_RouteActions", 56f); Button("Clear route", val4.transform, DangerColor, 0f, delegate { GpsCore.Instance?.ClearRoute("phone app"); }); Button("Re-route", val4.transform, ButtonColor, 0f, delegate { GpsCore.Instance?.Reroute(); }); Section("DESTINATIONS"); SearchRow(); GameObject val5 = Row("GPS_PlacesActions", 56f); _placesToggleLabel = Button("Show nearby", val5.transform, ButtonColor, 0f, delegate { _placesExpanded = !_placesExpanded; RenderPlaces(); }); Button("Refresh", val5.transform, ButtonColor, 130f, delegate { CollectDestinations(); RenderPlaces(); }); _placesBox = new GameObject("GPS_Places"); ((Transform)_placesBox.AddComponent<RectTransform>()).SetParent((Transform)(object)_list, false); UIFactory.VerticalLayoutOnGO(_placesBox, 6, new RectOffset()); _placesBox.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2; GpsConfig cfg = GpsMod.Cfg; Section("LOOK"); ColorRow(); Stepper("Transparency", () => $"{Mathf.RoundToInt(cfg.LineOpacity.Value * 100f)}% solid", delegate(int d) { cfg.Set(cfg.LineOpacity, Step(OpacitySteps, cfg.LineOpacity.Value, d)); }); Stepper("Line width", () => $"{cfg.LineWidth.Value:0.##} m", delegate(int d) { cfg.Set(cfg.LineWidth, Step(WidthSteps, cfg.LineWidth.Value, d)); }); Stepper("Draw distance", () => $"{cfg.MaxDrawDistance.Value:0} m", delegate(int d) { cfg.Set(cfg.MaxDrawDistance, Step(DrawDistSteps, cfg.MaxDrawDistance.Value, d)); }); Toggle("Destination beam", cfg.ShowBeacon); Toggle("Flat on the ground", cfg.FlatLine); Toggle("See through walls", cfg.DrawThroughWalls); Section("MAP & HUD"); Toggle("Show route on phone map", cfg.ShowOnMap); Stepper("Map line width", () => $"{cfg.MapLineWidthMeters.Value:0} m", delegate(int d) { cfg.Set(cfg.MapLineWidthMeters, Step(MapWidthSteps, cfg.MapLineWidthMeters.Value, d)); }); if (MinimapBridge.Available) { Toggle("Show on minimap (MultiMiniMap)", cfg.ShowOnMinimap); } Toggle("Distance / ETA on screen", cfg.ShowHud); Toggle("Compass marker", cfg.ShowOnCompass); Toggle("Arrival notification", cfg.NotifyOnArrival); Section("ROUTING"); Stepper("Refresh rate", () => $"every {cfg.RecalcInterval.Value:0.##} s", delegate(int d) { cfg.Set(cfg.RecalcInterval, Step(RefreshSteps, cfg.RecalcInterval.Value, d)); }); Toggle("Quickest by road (always)", cfg.RoadNetworkAlways); Toggle("Fallback: roads & paths only", cfg.RoadsAndPathsOnly); Label("Clear route: [" + cfg.ClearKey.Value + "] or right-click the map. Settings save automatically.", 16, (FontStyle)2, MutedText, 40f); CollectDestinations(); RenderPlaces(); RefreshAll(); GpsMod.Log.Msg("GPS phone app created."); } protected override void OnDestroyed() { if (GpsCore.UiTick == new Action(Tick)) { GpsCore.UiTick = null; } } private void Tick() { bool flag; try { flag = ((PhoneApp)this).IsOpen(); } catch { return; } if (!flag) { _wasOpen = false; return; } if (!_wasOpen) { _wasOpen = true; if (!_fitted) { FitToScreen(); } CollectDestinations(); RenderPlaces(); RefreshAll(); } if (Time.unscaledTime >= _nextStatus) { _nextStatus = Time.unscaledTime + 0.5f; RefreshStatus(); } } private void FitToScreen() { //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) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: 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_0127: 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_012e: 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_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0170: 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_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) _fitted = true; if ((Object)(object)_frame == (Object)null || (Object)(object)_container == (Object)null) { return; } try { RectTransform val = null; string text = ""; Transform parent = ((Transform)_container).parent; while ((Object)(object)parent != (Object)null && (Object)(object)val == (Object)null) { if ((Object)(object)((Component)parent).GetComponent<RectMask2D>() != (Object)null) { val = ((Il2CppObjectBase)parent).TryCast<RectTransform>(); text = "RectMask2D"; } else if ((Object)(object)((Component)parent).GetComponent<Mask>() != (Object)null) { val = ((Il2CppObjectBase)parent).TryCast<RectTransform>(); text = "Mask"; } else if ((Object)(object)((Component)parent).GetComponent<Canvas>() != (Object)null && ((Component)parent).GetComponent<Canvas>().isRootCanvas) { break; } parent = parent.parent; } if ((Object)(object)val == (Object)null) { Canvas componentInParent = ((Component)_container).GetComponentInParent<Canvas>(); if ((Object)(object)componentInParent != (Object)null) { val = ((Component)componentInParent.rootCanvas).GetComponent<RectTransform>(); text = "root canvas"; } } if (!((Object)(object)val == (Object)null)) { Il2CppStructArray<Vector3> val2 = new Il2CppStructArray<Vector3>(4L); val.GetWorldCorners(val2); Vector3 val3 = ((Transform)_container).InverseTransformPoint(((Il2CppArrayBase<Vector3>)(object)val2)[0]); Vector3 val4 = ((Transform)_container).InverseTransformPoint(((Il2CppArrayBase<Vector3>)(object)val2)[2]); Rect rect = _container.rect; float num = Mathf.Clamp(Mathf.Min(val3.x, val4.x) - ((Rect)(ref rect)).xMin, 0f, ((Rect)(ref rect)).width * 0.4f); float num2 = Mathf.Clamp(((Rect)(ref rect)).xMax - Mathf.Max(val3.x, val4.x), 0f, ((Rect)(ref rect)).width * 0.4f); float num3 = Mathf.Clamp(Mathf.Min(val3.y, val4.y) - ((Rect)(ref rect)).yMin, 0f, ((Rect)(ref rect)).height * 0.4f); float num4 = Mathf.Clamp(((Rect)(ref rect)).yMax - Mathf.Max(val3.y, val4.y), 0f, ((Rect)(ref rect)).height * 0.4f); if (num < 1f && num2 < 1f) { num = (num2 = ((Rect)(ref rect)).width * 0.06f); text += " (no overlap found, default side inset)"; } _frame.offsetMin = new Vector2(num, num3); _frame.offsetMax = new Vector2(0f - num2, 0f - num4); GpsMod.Log.Msg($"GPS app fitted to {text} '{((Object)val).name}': container {((Rect)(ref rect)).width:0}x{((Rect)(ref rect)).height:0}, inset L{num:0} R{num2:0} B{num3:0} T{num4:0}."); LogLayout(); } } catch (Exception ex) { GpsMod.Log.Warning("GPS app screen fit failed: " + ex.Message); } } private void LogLayout() { //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_00bf: 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) try { if ((Object)(object)_list == (Object)null) { return; } StringBuilder stringBuilder = new StringBuilder("GPS app layout: "); Transform val = (Transform)(object)_list; int num = 0; StringBuilder stringBuilder2; StringBuilder.AppendInterpolatedStringHandler handler; while (num < 4 && (Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)_container) { RectTransform val2 = ((Il2CppObjectBase)val).TryCast<RectTransform>(); string value = (((Object)(object)((Component)val).GetComponent<Mask>() != (Object)null) ? " Mask" : "") + (((Object)(object)((Component)val).GetComponent<RectMask2D>() != (Object)null) ? " RectMask2D" : ""); stringBuilder2 = stringBuilder; StringBuilder stringBuilder3 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(7, 3, stringBuilder2); handler.AppendLiteral("'"); handler.AppendFormatted(((Object)val).name); handler.AppendLiteral("' "); object value2; if (!((Object)(object)val2 != (Object)null)) { value2 = "?"; } else { Rect rect = val2.rect; value2 = ((object)((Rect)(ref rect)).size/*cast due to .constrained prefix*/).ToString(); } handler.AppendFormatted((string?)value2); handler.AppendFormatted(value); handler.AppendLiteral(" <- "); stringBuilder3.Append(ref handler); num++; val = val.parent; } stringBuilder2 = stringBuilder; StringBuilder stringBuilder4 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(16, 2, stringBuilder2); handler.AppendLiteral("rows="); handler.AppendFormatted(((Transform)_list).childCount); handler.AppendLiteral(", rotation="); Quaternion rotation = ((Transform)_container).rotation; handler.AppendFormatted<Vector3>(((Quaternion)(ref rotation)).eulerAngles); stringBuilder4.Append(ref handler); GpsMod.Log.Msg(stringBuilder.ToString()); } catch (Exception ex) { GpsMod.Verbose("Layout log failed: " + ex.Message); } } private void RefreshAll() { foreach (Action refresher in _refreshers) { try { refresher(); } catch (Exception ex) { GpsMod.Verbose("App refresh failed: " + ex.Message); } } RefreshStatus(); } private void RefreshStatus() { if ((Object)(object)_statusTitle == (Object)null) { return; } GpsCore instance = GpsCore.Instance; if (instance == null || !instance.HasDestination) { _statusTitle.text = "No destination"; _statusDetail.text = "Open the Map app and left-click anywhere, or pick a place below."; return; } _statusTitle.text = (string.IsNullOrEmpty(instance.DestinationLabel) ? "Map pin" : instance.DestinationLabel); if (instance.RouteFailed && instance.RemainingMeters <= 0f) { _statusDetail.text = "No route found yet - retrying..."; return; } string value = ((instance.CurrentMode == RouteMode.Drive) ? "Road network" : "Roads & paths"); _statusDetail.text = $"{GpsHud.FormatDistance(instance.RemainingMeters)} · ETA {GpsHud.FormatEta(instance.EtaSeconds)} · {value}"; } private void CollectDestinations() { //IL_0027: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: 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_0159: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: 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) _destinations.Clear(); Player local = Player.Local; Vector3 a = (((Object)(object)local != (Object)null) ? ((Component)local).transform.position : Vector3.zero); try { if ((Object)(object)local != (Object)null && (Object)(object)local.LastDrivenVehicle != (Object)null && !local.IsInVehicle) { _destinations.Add(new Destination { Name = "Your vehicle", Kind = "vehicle", Follow = ((Component)local.LastDrivenVehicle).transform }); } } catch (Exception ex) { GpsMod.Verbose("Vehicle destination failed: " + ex.Message); } HashSet<string> hashSet = new HashSet<string>(); try { foreach (POI item2 in Object.FindObjectsOfType<POI>()) { if ((Object)(object)item2 == (Object)null || !((Component)item2).gameObject.activeInHierarchy) { continue; } string text = item2.MainText; if (string.IsNullOrWhiteSpace(text)) { text = item2.DefaultMainText; } if (string.IsNullOrWhiteSpace(text)) { continue; } text = text.Replace("\n", " ").Trim(); if (text.IndexOf("Main Text", StringComparison.OrdinalIgnoreCase) >= 0 || text.Equals("Text", StringComparison.OrdinalIgnoreCase)) { continue; } Vector3 position = ((Component)item2).transform.position; if (!((Object)(object)local != (Object)null) || !(RoutePlanner.HorizontalDistance(a, position) < 2f)) { string item = text + "@" + Mathf.RoundToInt(position.x / 10f) + "," + Mathf.RoundToInt(position.z / 10f); if (hashSet.Add(item)) { _destinations.Add(new Destination { Name = text, Kind = "place", Fixed = position }); } } } } catch (Exception ex2) { GpsMod.Verbose("POI destinations failed: " + ex2.Message); } int num = 0; try { List<NPC> nPCRegistry = NPCManager.NPCRegistry; if (nPCRegistry != null) { for (int i = 0; i < nPCRegistry.Count; i++) { NPC val = nPCRegistry[i]; if (!((Object)(object)val == (Object)null)) { string fullName = val.FullName; if (!string.IsNullOrWhiteSpace(fullName)) { Transform follow = (((Object)(object)val.Movement != (Object)null) ? ((Component)val.Movement).transform : ((Component)val).transform); _destinations.Add(new Destination { Name = fullName.Trim(), Kind = "person", Follow = follow }); num++; } } } } } catch (Exception ex3) { GpsMod.Verbose("NPC destinations failed: " + ex3.Message); } GpsMod.Verbose($"Destinations collected: {_destinations.Count} ({num} people)."); } private void RenderPlaces() { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_placesBox == (Object)null) { return; } UIFactory.ClearChildren(_placesBox.transform); bool flag = !string.IsNullOrWhiteSpace(_query); if ((Object)(object)_placesToggleLabel != (Object)null) { _placesToggleLabel.text = (_placesExpanded ? "Hide nearby" : $"Show nearby ({_destinations.Count})"); } if (!flag && !_placesExpanded) { UIFactory.FitContentHeight(_list); return; } Player local = Player.Local; Vector3 a = (((Object)(object)local != (Object)null) ? ((Component)local).transform.position : Vector3.zero); string text = (flag ? _query.Trim() : null); List<(Destination, float)> list = new List<(Destination, float)>(); foreach (Destination destination in _destinations) { if ((text == null || destination.Name.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0 || destination.Kind.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0) && (text != null || !(destination.Kind == "person"))) { Vector3 position; try { position = destination.Position; } catch { continue; } list.Add((destination, RoutePlanner.HorizontalDistance(a, position))); } } list.Sort(((Destination D, float Dist) tuple, (Destination D, float Dist) b) => tuple.Dist.CompareTo(b.Dist)); int num = (flag ? 30 : 20); int num2 = 0; foreach (var item in list) { if (num2 >= num) { break; } PlaceRow(item.Item1, item.Item2); num2++; } if (num2 == 0) { Label(flag ? ("Nothing matches \"" + text + "\".") : "No places found. Map markers show up here.", 17, (FontStyle)2, MutedText, 34f, _placesBox.transform); } else if (list.Count > num2) { Label($"+{list.Count - num2} more - refine your search.", 15, (FontStyle)2, MutedText, 28f, _placesBox.transform); } UIFactory.FitContentHeight(_list); } private void PlaceRow(Destination d, float dist) { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) GameObject val = Row("GPS_Place", 58f, _placesBox.transform); string text = ((d.Kind == "person") ? " (person)" : ""); Flexible(((Component)MakeText("Name", d.Name + text, val.transform, 17, (TextAnchor)3, (FontStyle)0)).gameObject, 1f, 52f); Text obj = MakeText("Dist", GpsHud.FormatDistance(dist), val.transform, 16, (TextAnchor)5, (FontStyle)0); ((Graphic)obj).color = MutedText; Fixed(((Component)obj).gameObject, 70f, 44f); Button("Go", val.transform, OnColor, 64f, delegate { //IL_0043: Unknown result type (might be due to invalid IL or missing references) GpsCore instance = GpsCore.Instance; if (instance != null) { if ((Object)(object)d.Follow != (Object)null) { instance.SetDestinationFollow(d.Follow, d.Name); } else { instance.SetDestinationWorld(d.Fixed, d.Name); } RefreshStatus(); } }); } private void SearchRow() { //IL_003e: 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_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) GameObject val = Row("GPS_SearchRow", 56f); GameObject val2 = UIFactory.Panel("GPS_Search", val.transform, new Color(1f, 1f, 1f, 0.1f), (Vector2?)null, (Vector2?)null, false); LayoutElement orAddLayout = GetOrAddLayout(val2); orAddLayout.flexibleWidth = 1f; orAddLayout.preferredWidth = 0f; orAddLayout.minHeight = 70.4f; orAddLayout.preferredHeight = 70.4f; Text val3 = MakeText("Placeholder", "Search places & people...", val2.transform, 17, (TextAnchor)3, (FontStyle)2); ((Graphic)val3).color = new Color(1f, 1f, 1f, 0.4f); Stretch(((Graphic)val3).rectTransform, 14f); Text val4 = MakeText("Text", "", val2.transform, 17, (TextAnchor)3, (FontStyle)0); ((Graphic)val4).color = Color.white; val4.supportRichText = false; Stretch(((Graphic)val4).rectTransform, 14f); InputField input = val2.AddComponent<InputField>(); input.textComponent = val4; input.placeholder = (Graphic)(object)val3; ((Selectable)input).targetGraphic = (Graphic)(object)val2.GetComponent<Image>(); input.lineType = (LineType)0; input.characterLimit = 40; EventHelper.AddListener<string>((Action<string>)delegate(string value) { _query = value ?? ""; RenderPlaces(); }, (UnityEvent<string>)(object)input.onValueChanged); Button("X", val.transform, ButtonColor, 52f, delegate { input.text = ""; _query = ""; RenderPlaces(); }); } private void Toggle(string label, MelonPreferences_Entry<bool> entry) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) GameObject val = Row("GPS_Toggle", 52f); Flexible(((Component)MakeText("Label", label, val.transform, 18, (TextAnchor)3, (FontStyle)0)).gameObject, 1f, 44f); var (val2, val3, txt) = UIFactory.ButtonWithLabel("Toggle", "", val.transform, OffColor, 128f, 70.4f); Fixed(val2, 80f, 44f); Image img = val2.GetComponent<Image>(); Action refresh = delegate { //IL_004c: 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) txt.text = (entry.Value ? "ON" : "OFF"); if ((Object)(object)img != (Object)null) { ((Graphic)img).color = (entry.Value ? OnColor : OffColor); } }; _refreshers.Add(refresh); EventHelper.AddListener((Action)delegate { GpsMod.Cfg.Set(entry, !entry.Value); refresh(); }, (UnityEvent)(object)val3.onClick); } private void Stepper(string label, Func<string> value, Action<int> change) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) GameObject val = Row("GPS_Stepper", 52f); Flexible(((Component)MakeText("Label", label, val.transform, 18, (TextAnchor)3, (FontStyle)0)).gameObject, 1f, 44f); Text v = null; Button("-", val.transform, ButtonColor, 44f, delegate { change(-1); v.text = value(); }); v = MakeText("Value", value(), val.transform, 17, (TextAnchor)4, (FontStyle)1); Fixed(((Component)v).gameObject, 100f, 44f); Button("+", val.transform, ButtonColor, 44f, delegate { change(1); v.text = value(); }); _refreshers.Add(delegate { v.text = value(); }); } private void ColorRow() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) Label("Color", 18, (FontStyle)0, Color.white, 30f); GameObject val = null; List<(string Hex, Text Mark)> swatches = new List<(string, Text)>(); for (int i = 0; i < Palette.Length; i++) { var (text, text2) = Palette[i]; if (i % 5 == 0) { val = Row("GPS_Colors", 56f); } Color val2 = HexToColor(text2); var (go, val3, val4) = UIFactory.ButtonWithLabel("Swatch_" + text, "", val.transform, val2, 76.8f, 70.4f); Fixed(go, 48f, 44f); ((Graphic)val4).color = ((((Color)(ref val2)).grayscale > 0.6f) ? Color.black : Color.white); val4.fontStyle = (FontStyle)1; swatches.Add((text2, val4)); string pick = text2; EventHelper.AddListener((Action)delegate { GpsMod.Cfg.Set(GpsMod.Cfg.LineColor, pick); RefreshAll(); }, (UnityEvent)(object)val3.onClick); } _refreshers.Add(delegate { string text3 = (GpsMod.Cfg.LineColor.Value ?? "").Trim().ToUpperInvariant(); foreach (var item in swatches) { var (text4, _) = item; item.Mark.text = ((text4 == text3) ? "X" : ""); } }); } private void Section(string title) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) Label(title, 18, (FontStyle)1, new Color(0.45f, 0.85f, 0.95f, 1f), 40f).alignment = (TextAnchor)6; } private Text Label(string text, int size, FontStyle style, Color color, float height, Transform parent = null) { //IL_0014: 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) Text obj = MakeText("GPS_Label", text, (Transform)(((object)parent) ?? ((object)_list)), size, (TextAnchor)3, style); ((Graphic)obj).color = color; LayoutElement orAddLayout = GetOrAddLayout(((Component)obj).gameObject); orAddLayout.minHeight = height * 1.6f; orAddLayout.preferredHeight = height * 1.6f; orAddLayout.preferredWidth = 0f; orAddLayout.flexibleWidth = 1f; return obj; } private static Text MakeText(string name, string content, Transform parent, int size, TextAnchor anchor, FontStyle style = (FontStyle)0) { //IL_0010: 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) Text obj = UIFactory.Text(name, content, parent, Mathf.RoundToInt((float)size * 1.6f), anchor, style); ContentSizeFitter component = ((Component)obj).GetComponent<ContentSizeFitter>(); if ((Object)(object)component != (Object)null) { component.horizontalFit = (FitMode)0; component.verticalFit = (FitMode)0; ((Behaviour)component).enabled = false; } obj.horizontalOverflow = (HorizontalWrapMode)0; obj.verticalOverflow = (VerticalWrapMode)0; obj.resizeTextForBestFit = false; return obj; } private static void SetupScrolling(ScrollRect scroll, RectTransform body) { //IL_00a0: 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_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0110: 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_0136: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)scroll == (Object)null || (Object)(object)body == (Object)null) { return; } scroll.scrollSensitivity = 72f; scroll.inertia = true; scroll.decelerationRate = 0.12f; scroll.movementType = (MovementType)2; if ((Object)(object)((Component)scroll).GetComponent<Mask>() == (Object)null && (Object)(object)((Component)scroll).GetComponent<RectMask2D>() == (Object)null) { bool flag = (Object)(object)((Component)scroll).GetComponent<Image>() != (Object)null; if (!flag) { Image obj = ((Component)scroll).gameObject.AddComponent<Image>(); ((Graphic)obj).color = Color.white; ((Graphic)obj).raycastTarget = true; } ((Component)scroll).gameObject.AddComponent<Mask>().showMaskGraphic = flag; } float num = 14.400001f; RectTransform component = ((Component)scroll).GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = new Vector2(0f - (num + 6f), 0f); GameObject val = new GameObject("GPS_Scrollbar"); RectTransform val2 = val.AddComponent<RectTransform>(); ((Transform)val2).SetParent((Transform)(object)body, false); val2.anchorMin = new Vector2(1f, 0f); val2.anchorMax = new Vector2(1f, 1f); val2.pivot = new Vector2(1f, 0.5f); val2.sizeDelta = new Vector2(num, -8f); val2.anchoredPosition = new Vector2(-2f, 0f); ((Graphic)val.AddComponent<Image>()).color = new Color(1f, 1f, 1f, 0.06f); RectTransform val3 = new GameObject("Sliding Area").AddComponent<RectTransform>(); ((Transform)val3).SetParent((Transform)(object)val2, false); val3.anchorMin = Vector2.zero; val3.anchorMax = Vector2.one; val3.offsetMin = Vector2.zero; val3.offsetMax = Vector2.zero; GameObject val4 = new GameObject("Handle"); RectTransform val5 = val4.AddComponent<RectTransform>(); ((Transform)val5).SetParent((Transform)(object)val3, false); val5.offsetMin = Vector2.zero; val5.offsetMax = Vector2.zero; Image val6 = val4.AddComponent<Image>(); ((Graphic)val6).color = new Color(0.45f, 0.85f, 0.95f, 0.75f); Scrollbar val7 = val.AddComponent<Scrollbar>(); val7.handleRect = val5; ((Selectable)val7).targetGraphic = (Graphic)(object)val6; val7.direction = (Direction)2; scroll.verticalScrollbar = val7; scroll.verticalScrollbarVisibility = (ScrollbarVisibility)0; } private void FitListToViewport(ScrollRect scroll) { //IL_0020: 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_0054: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown if ((Object)(object)scroll != (Object)null) { scroll.horizontal = false; } _list.anchorMin = new Vector2(0f, 1f); _list.anchorMax = new Vector2(1f, 1f); _list.pivot = new Vector2(0.5f, 1f); _list.sizeDelta = new Vector2(0f, _list.sizeDelta.y); _list.anchoredPosition = new Vector2(0f, _list.anchoredPosition.y); ContentSizeFitter component = ((Component)_list).GetComponent<ContentSizeFitter>(); if ((Object)(object)component != (Object)null) { component.horizontalFit = (FitMode)0; } VerticalLayoutGroup component2 = ((Component)_list).GetComponent<VerticalLayoutGroup>(); if ((Object)(object)component2 != (Object)null) { ((HorizontalOrVerticalLayoutGroup)component2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)component2).childForceExpandWidth = true; ((LayoutGroup)component2).padding = new RectOffset(8, 8, 6, 16); ((HorizontalOrVerticalLayoutGroup)component2).spacing = 6f; } } private GameObject Row(string name, float height, Transform parent = null) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) GameObject obj = UIFactory.Panel(name, (Transform)(((object)parent) ?? ((object)_list)), RowColor, (Vector2?)null, (Vector2?)null, false); UIFactory.HorizontalLayoutOnGO(obj, Mathf.RoundToInt(16f), Mathf.RoundToInt(22.4f), Mathf.RoundToInt(16f), 4, 4, (TextAnchor)3); HorizontalLayoutGroup component = obj.GetComponent<HorizontalLayoutGroup>(); if ((Object)(object)component != (Object)null) { ((HorizontalOrVerticalLayoutGroup)component).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)component).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = false; } LayoutElement orAddLayout = GetOrAddLayout(obj); orAddLayout.minHeight = height * 1.6f; orAddLayout.preferredHeight = height * 1.6f; orAddLayout.flexibleWidth = 1f; return obj; } private static Text Button(string label, Transform parent, Color color, float width, Action onClick) { //IL_002d: 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) bool flag = width <= 0f; var (go, val, val2) = UIFactory.ButtonWithLabel("GPS_Btn", label, parent, color, (flag ? 100f : width) * 1.6f, 70.4f); if (flag) { LayoutElement orAddLayout = GetOrAddLayout(go); orAddLayout.minWidth = 96f; orAddLayout.preferredWidth = 0f; orAddLayout.flexibleWidth = 1f; orAddLayout.minHeight = 70.4f; orAddLayout.preferredHeight = 70.4f; } else { Fixed(go, width, 44f); } ((Graphic)val2).color = Color.white; val2.fontSize = Mathf.RoundToInt(27.2f); EventHelper.AddListener((Action)delegate { try { onClick(); } catch (Exception value) { GpsMod.Log.Error($"GPS app button '{label}' failed: {value}"); } }, (UnityEvent)(object)val.onClick); return val2; } private static void Fixed(GameObject go, float w, float h) { LayoutElement orAddLayout = GetOrAddLayout(go); orAddLayout.minWidth = w * 1.6f; orAddLayout.preferredWidth = w * 1.6f; orAddLayout.flexibleWidth = 0f; orAddLayout.minHeight = h * 1.6f; orAddLayout.preferredHeight = h * 1.6f; } private static void Flexible(GameObject go, float flex, float h) { LayoutElement orAddLayout = GetOrAddLayout(go); orAddLayout.flexibleWidth = flex; orAddLayout.minWidth = 96f; orAddLayout.preferredWidth = 0f; orAddLayout.minHeight = h * 1.6f; orAddLayout.preferredHeight = h * 1.6f; } private static LayoutElement GetOrAddLayout(GameObject go) { LayoutElement val = go.GetComponent<LayoutElement>(); if ((Object)(object)val == (Object)null) { val = go.AddComponent<LayoutElement>(); } return val; } private static void Stretch(RectTransform rt, float padLeft) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_002f: Unknown result type (might be due to invalid IL or missing references) rt.anchorMin = Vector2.zero; rt.anchorMax = Vector2.one; rt.offsetMin = new Vector2(padLeft, 0f); rt.offsetMax = new Vector2(0f - padLeft, 0f); } private static float Step(float[] steps, float current, int dir) { int num = 0; for (int i = 1; i < steps.Length; i++) { if (Mathf.Abs(steps[i] - current) < Mathf.Abs(steps[num] - current)) { num = i; } } return steps[Mathf.Clamp(num + dir, 0, steps.Length - 1)]; } private static Color HexToColor(string hex) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) string text = hex.TrimStart('#'); return new Color((float)Convert.ToInt32(text.Substring(0, 2), 16) / 255f, (float)Convert.ToInt32(text.Substring(2, 2), 16) / 255f, (float)Convert.ToInt32(text.Substring(4, 2), 16) / 255f, 1f); } } internal class MapProjection { private Vector2 _m0; private Vector2 _a; private Vector2 _b; private float _det; private bool _logged; public bool Valid { get; private set; } public Vector2 PerMeterX => _a; public Vector2 PerMeterZ => _b; public float UnitsPerMeter { get; private set; } = 1f; public static MapPositionUtility Util { get { if (!Singleton<MapPositionUtility>.InstanceExists) { return null; } return Singleton<MapPositionUtility>.Instance; } } public bool Calibrate() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_0074: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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_008f: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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_00a6: 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_0122: 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_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: 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_0257: Unknown result type (might be due to invalid IL or missing references) MapPositionUtility util = Util; if ((Object)(object)util == (Object)null) { Valid = false; return false; } Vector2 mapPosition = util.GetMapPosition(Vector3.zero); Vector2 mapPosition2 = util.GetMapPosition(new Vector3(1000f, 0f, 0f)); Vector2 mapPosition3 = util.GetMapPosition(new Vector3(0f, 0f, 1000f)); Vector2 mapPosition4 = util.GetMapPosition(new Vector3(1000f, 0f, 1000f)); _m0 = mapPosition; _a = (mapPosition2 - mapPosition) / 1000f; _b = (mapPosition3 - mapPosition) / 1000f; _det = _a.x * _b.y - _b.x * _a.y; Valid = Mathf.Abs(_det) > 1E-12f; UnitsPerMeter = Mathf.Sqrt(Mathf.Abs(_det)); if (!_logged) { _logged = true; Vector2 val = mapPosition + _a * 1000f + _b * 1000f - mapPosition4; float magnitude = ((Vector2)(ref val)).magnitude; GpsMod.Log.Msg($"Map projection: origin={mapPosition}, perMeterX={_a}, perMeterZ={_b}, scale={UnitsPerMeter:F4} map units/m, linearity error={magnitude:F4} ({((magnitude < 0.5f) ? "OK" : "NON-LINEAR, clicks may be off")}). OriginPoint={(((Object)(object)util.OriginPoint != (Object)null) ? RoutePlanner.Fmt(util.OriginPoint.position) : "null")}, MapDimensions={util.MapDimensions}, conversionFactor={util.conversionFactor}"); if (!Valid) { GpsMod.Log.Error("Map projection is degenerate; map clicks can't be converted to world positions."); } } return Valid; } public Vector2 WorldToMap(Vector3 world) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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) MapPositionUtility util = Util; if (!((Object)(object)util != (Object)null)) { return _m0 + _a * world.x + _b * world.z; } return util.GetMapPosition(world); } public Vector2 MapToWorldXZ(Vector2 m) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_0044: 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_0067: Unknown result type (might be due to invalid IL or missing references) Vector2 val = m - _m0; float num = (val.x * _b.y - _b.x * val.y) / _det; float num2 = (_a.x * val.y - val.x * _a.y) / _det; return new Vector2(num, num2); } } internal class MapOverlay { private static MapApp s_app; private readonly MapProjection _proj = new MapProjection(); private RectTransform _layer; private readonly List<Image> _segments = new List<Image>(); private Image _destMarker; private int _usedSegments; private Vector2 _downPos; private float _downTime; private bool _leftDownOnMap; private bool _checkedPoiAlignment; private bool _loggedDraw; private static MapApp App { get { if ((Object)(object)s_app != (Object)null) { return s_app; } if (PlayerSingleton<MapApp>.InstanceExists) { s_app = PlayerSingleton<MapApp>.Instance; } return s_app; } } public MapProjection Projection => _proj; public static void OnMapAppSetOpen(MapApp app, bool open) { s_app = app; GpsMod.Verbose($"MapApp.SetOpen({open})"); } public void HandleInput(GpsCore core) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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) //IL_0089: 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_0114: 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) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) MapApp app = App; if ((Object)(object)app == (Object)null || !((App<MapApp>)(object)app).isOpen) { _leftDownOnMap = false; return; } Mouse current = Mouse.current; if (current == null) { return; } Vector2 val = ((InputControl<Vector2>)(object)((Pointer)current).position).ReadValue(); if (current.leftButton.wasPressedThisFrame) { _leftDownOnMap = IsOverMap(app, val); _downPos = val; _downTime = Time.unscaledTime; } if (current.leftButton.wasReleasedThisFrame && _leftDownOnMap) { _leftDownOnMap = false; Vector2 val2 = val - _downPos; if (((Vector2)(ref val2)).magnitude <= 8f && Time.unscaledTime - _downTime < 0.6f) { if (TryScreenToWorldXZ(app, val, out var worldXZ)) { core.SetDestination(worldXZ, "map left-click"); } } else { GpsMod.Verbose("Map drag ignored (not a click)."); } } if (!current.rightButton.wasPressedThisFrame || !IsOverMap(app, val)) { return; } if (string.Equals(GpsMod.Cfg.RightClickAction.Value, "Set", StringComparison.OrdinalIgnoreCase)) { if (TryScreenToWorldXZ(app, val, out var worldXZ2)) { core.SetDestination(worldXZ2, "map right-click"); } } else { core.ClearRoute("map right-click"); } } private static Camera GetUICamera(RectTransform rt) {