using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using FreeFly.Core; using HarmonyLib; using Microsoft.CodeAnalysis; using Peak; using Photon.Pun; using TMPro; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; using UnityEngine.UI; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("FreeFly")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.3.0.0")] [assembly: AssemblyInformationalVersion("1.3.0+10b34f8f1dde0b40b06c71c4c580ae21d6daaffb")] [assembly: AssemblyProduct("FreeFly")] [assembly: AssemblyTitle("FreeFly")] [assembly: AssemblyVersion("1.3.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 FreeFly { internal enum FlightStopReason { UserToggle, FeatureUnavailable, CharacterUnavailable, WarpStarted, PluginDestroyed } internal sealed class FlightRuntime { private readonly ModConfig _config; private readonly ManualLogSource _logger; private readonly FreeFlyInput _input; private readonly FreeFlyNotification _notification; private readonly Dictionary _originalGravity = new Dictionary(); private readonly Dictionary _originalColliderState = new Dictionary(); private Character? _flightCharacter; private bool _flightActive; public bool IsActive => _flightActive; public Character? ActiveCharacter => _flightCharacter; public FlightRuntime(ModConfig config, ManualLogSource logger, FreeFlyInput input, FreeFlyNotification notification) { _config = config; _logger = logger; _input = input; _notification = notification; } public bool TryStart(Character local) { if (!FreeFlyCharacterUtils.IsUsable(local) || (Object)(object)local.refs.ragdoll == (Object)null) { return false; } _flightCharacter = local; _originalGravity.Clear(); _originalColliderState.Clear(); foreach (Bodypart part in local.refs.ragdoll.partList) { if ((Object)(object)((part != null) ? part.Rig : null) != (Object)null) { _originalGravity[part.Rig] = part.Rig.useGravity; } } Collider[] componentsInChildren = ((Component)local.refs.ragdoll).GetComponentsInChildren(true); foreach (Collider val in componentsInChildren) { if ((Object)(object)val != (Object)null) { _originalColliderState[val] = val.enabled; } } local.refs.ragdoll.ToggleCollision(false); _flightActive = true; _notification.Show("Free flight enabled"); _logger.LogInfo((object)"Free flight enabled."); return true; } public void Stop(FlightStopReason reason, bool notify = true) { if (!_flightActive && (Object)(object)_flightCharacter == (Object)null) { return; } Character flightCharacter = _flightCharacter; if ((Object)(object)flightCharacter != (Object)null && (Object)(object)flightCharacter.refs.ragdoll != (Object)null) { flightCharacter.refs.ragdoll.ToggleCollision(true); foreach (KeyValuePair item in _originalColliderState) { if ((Object)(object)item.Key != (Object)null) { item.Key.enabled = item.Value; } } foreach (Bodypart part in flightCharacter.refs.ragdoll.partList) { if ((Object)(object)((part != null) ? part.Rig : null) != (Object)null && _originalGravity.TryGetValue(part.Rig, out var value)) { part.Rig.useGravity = value; } } flightCharacter.refs.ragdoll.HaltBodyVelocity(false); } _originalGravity.Clear(); _originalColliderState.Clear(); _flightCharacter = null; bool flightActive = _flightActive; _flightActive = false; if (flightActive) { if (notify) { _notification.Show("Free flight disabled"); } _logger.LogDebug((object)("Free flight disabled: " + GetReasonText(reason) + ".")); } } public void ApplyPhysics(CharacterMovement movement, bool menuOpen) { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00da: 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) //IL_00e0: 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_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: 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_0268: Unknown result type (might be due to invalid IL or missing references) //IL_022f: 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) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) if (!_flightActive || (Object)(object)_flightCharacter == (Object)null || (Object)(object)movement != (Object)(object)_flightCharacter.refs.movement) { return; } Character flightCharacter = _flightCharacter; if (!FreeFlyCharacterUtils.IsUsable(flightCharacter) || flightCharacter.warping) { Stop(flightCharacter.warping ? FlightStopReason.WarpStarted : FlightStopReason.CharacterUnavailable); return; } CharacterRagdoll ragdoll = flightCharacter.refs.ragdoll; foreach (Bodypart part in ragdoll.partList) { if ((Object)(object)((part != null) ? part.Rig : null) != (Object)null) { part.Rig.useGravity = false; } } Vector2 movementInput = _input.GetMovementInput(flightCharacter, menuOpen); Vector3 lookDirection_Flat = flightCharacter.data.lookDirection_Flat; Vector3 lookDirection_Right = flightCharacter.data.lookDirection_Right; Vector3 val = lookDirection_Flat * movementInput.y + lookDirection_Right * movementInput.x; bool flag = _input.ChordModifierHeld(); int num; if (!_input.IsCrouchHeld(flightCharacter, menuOpen)) { InputAction action_crouchToggle = CharacterInput.action_crouchToggle; num = ((action_crouchToggle != null && action_crouchToggle.IsPressed()) ? 1 : 0); } else { num = 1; } bool flag2 = (byte)num != 0; float num2 = (flag ? 0f : (_input.IsJumpHeld(flightCharacter, menuOpen) ? 1f : 0f)); num2 -= (flag ? 0f : (flag2 ? 1f : 0f)); Vector3 val2 = Vector3.ClampMagnitude(val + Vector3.up * num2, 1f); float num3 = FreeFlyMath.ApplySpeedModifiers(_config.SafeBaseSpeed, _input.SpeedUpHeld(), _input.SlowDownHeld(), _config.SafeSpeedUpMultiplier, _config.SafeSlowDownMultiplier); Vector3 val3 = val2 * num3 * Time.fixedDeltaTime; Vector3 linearVelocity = val2 * num3; ragdoll.HaltBodyVelocity(false); foreach (Bodypart part2 in ragdoll.partList) { if ((Object)(object)((part2 != null) ? part2.Rig : null) == (Object)null) { continue; } if (part2.Rig.isKinematic) { if (FreeFlyCharacterUtils.IsFinite(val3) && ((Vector3)(ref val3)).sqrMagnitude > 0f) { Rigidbody rig = part2.Rig; rig.position += val3; } } else { part2.Rig.linearVelocity = linearVelocity; } } flightCharacter.data.isGrounded = true; flightCharacter.data.sinceGrounded = 0f; flightCharacter.data.sinceJump = 0f; } private static string GetReasonText(FlightStopReason reason) { return reason switch { FlightStopReason.UserToggle => "toggle pressed", FlightStopReason.FeatureUnavailable => "feature unavailable", FlightStopReason.CharacterUnavailable => "character became unavailable", FlightStopReason.WarpStarted => "character changed or PEAK warp started", FlightStopReason.PluginDestroyed => "plugin destroyed", _ => "unknown reason", }; } } internal static class FreeFlyCharacterUtils { public static bool IsUsable(Character character) { if ((Object)(object)character == (Object)(object)Character.localCharacter && (Object)(object)character.data != (Object)null && (Object)(object)character.refs.ragdoll != (Object)null) { return (Object)(object)character.refs.view != (Object)null; } return false; } public static bool IsFinite(Vector3 value) { //IL_0000: 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_001a: Unknown result type (might be due to invalid IL or missing references) if (FreeFlyMath.IsFinite(value.x) && FreeFlyMath.IsFinite(value.y)) { return FreeFlyMath.IsFinite(value.z); } return false; } } internal sealed class FreeFlyController { private readonly ModConfig _config; private readonly FreeFlyInput _input; private readonly FlightRuntime _flight; private readonly TeleportDestinationService _destinations; private readonly TeleportMenuView _menu; private PatchCapabilities _capabilities; public FreeFlyController(ModConfig config, FreeFlyInput input, FlightRuntime flight, TeleportDestinationService destinations, TeleportMenuView menu) { _config = config; _input = input; _flight = flight; _destinations = destinations; _menu = menu; } public void SetCapabilities(PatchCapabilities capabilities) { _capabilities = capabilities; _destinations.SetCapabilities(capabilities); } public void TickUpdate() { Character localCharacter = Character.localCharacter; if (!_config.Enabled.Value || !_capabilities.FlightPatch || (Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null) { _flight.Stop(FlightStopReason.FeatureUnavailable); _menu.Close(); return; } if (_flight.IsActive && ((Object)(object)_flight.ActiveCharacter != (Object)(object)localCharacter || localCharacter.warping)) { _flight.Stop(localCharacter.warping ? FlightStopReason.WarpStarted : FlightStopReason.CharacterUnavailable); } FreeFlyInputSnapshot input = _input.ReadSnapshot(); if (_menu.IsOpen) { if (input.MenuToggle) { _menu.Close(); } else if (!input.FlightToggle) { _menu.Tick(input); } } else if (input.MenuToggle && _input.CanUseInput()) { _menu.Open(); } else if (input.FlightToggle && _input.CanUseInput()) { if (_flight.IsActive) { _flight.Stop(FlightStopReason.UserToggle); } else { _flight.TryStart(localCharacter); } } } public void ApplyFlightPhysics(CharacterMovement movement) { _flight.ApplyPhysics(movement, _menu.IsOpen); } public void DrawMenu() { _menu.Draw(); } public void Shutdown() { _menu.Shutdown(); _flight.Stop(FlightStopReason.PluginDestroyed, notify: false); _input.Dispose(); } } internal sealed class FreeFlyMenuWindow : MenuWindow { public override bool selectOnOpen => false; } internal readonly struct FreeFlyInputSnapshot { public bool MenuToggle { get; } public bool FlightToggle { get; } public bool Cancel { get; } public bool Confirm { get; } public bool Up { get; } public bool Down { get; } public FreeFlyInputSnapshot(bool menuToggle, bool flightToggle, bool cancel, bool confirm, bool up, bool down) { MenuToggle = menuToggle; FlightToggle = flightToggle; Cancel = cancel; Confirm = confirm; Up = up; Down = down; } } internal sealed class FreeFlyInput : IDisposable { private readonly ModConfig _config; private readonly ManualLogSource _logger; private InputAction? _flightToggleAction; private InputAction? _teleportMenuToggleAction; private InputAction? _controllerChordModifierAction; private InputAction? _speedUpKeyboardAction; private InputAction? _slowDownKeyboardAction; private InputAction? _speedUpControllerAction; private InputAction? _slowDownControllerAction; private InputAction? _cancelAction; private InputAction? _confirmAction; private InputAction? _upAction; private InputAction? _downAction; public FreeFlyInput(ModConfig config, ManualLogSource logger) { _config = config; _logger = logger; BindNavigationActions(); BindConfiguredActions(); _config.ToggleFlightKeyboardPath.SettingChanged += OnBindingPathChanged; _config.TeleportMenuKeyboardPath.SettingChanged += OnBindingPathChanged; _config.ControllerChordModifierPath.SettingChanged += OnBindingPathChanged; _config.ControllerFlightTogglePath.SettingChanged += OnBindingPathChanged; _config.ControllerTeleportMenuTogglePath.SettingChanged += OnBindingPathChanged; _config.SpeedUpKeyboardPath.SettingChanged += OnBindingPathChanged; _config.SlowDownKeyboardPath.SettingChanged += OnBindingPathChanged; _config.SpeedUpControllerPath.SettingChanged += OnBindingPathChanged; _config.SlowDownControllerPath.SettingChanged += OnBindingPathChanged; } public FreeFlyInputSnapshot ReadSnapshot() { return new FreeFlyInputSnapshot(WasPressedThisFrame(_teleportMenuToggleAction), WasPressedThisFrame(_flightToggleAction), WasPressedThisFrame(_cancelAction), WasPressedThisFrame(_confirmAction), WasPressedThisFrame(_upAction), WasPressedThisFrame(_downAction)); } public bool SpeedUpHeld() { if (!IsActionHeld(_speedUpKeyboardAction)) { if (!ChordModifierHeld()) { InputAction? speedUpControllerAction = _speedUpControllerAction; if (speedUpControllerAction == null) { return false; } return speedUpControllerAction.IsPressed(); } return false; } return true; } public bool SlowDownHeld() { if (!IsActionHeld(_slowDownKeyboardAction)) { if (!ChordModifierHeld()) { InputAction? slowDownControllerAction = _slowDownControllerAction; if (slowDownControllerAction == null) { return false; } return slowDownControllerAction.IsPressed(); } return false; } return true; } public bool ChordModifierHeld() { InputAction? controllerChordModifierAction = _controllerChordModifierAction; if (controllerChordModifierAction == null) { return false; } return controllerChordModifierAction.IsPressed(); } public Vector2 GetMovementInput(Character local, bool menuOpen) { //IL_0009: 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_0029: 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_002e: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_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_005e: 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_006c: 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) //IL_0076: 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_0083: 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_008e: Unknown result type (might be due to invalid IL or missing references) if (!menuOpen) { return Vector2.ClampMagnitude(local.input.movementInput, 1f); } InputAction action_move = CharacterInput.action_move; Vector2 val = ((action_move != null) ? action_move.ReadValue() : Vector2.zero); if (IsActionHeld(CharacterInput.action_moveForward)) { val += Vector2.up; } if (IsActionHeld(CharacterInput.action_moveBackward)) { val -= Vector2.up; } if (IsActionHeld(CharacterInput.action_moveRight)) { val += Vector2.right; } if (IsActionHeld(CharacterInput.action_moveLeft)) { val -= Vector2.right; } return Vector2.ClampMagnitude(val, 1f); } public bool IsJumpHeld(Character local, bool menuOpen) { if (!menuOpen) { return local.input.jumpIsPressed; } return IsActionHeld(CharacterInput.action_jump); } public bool IsCrouchHeld(Character local, bool menuOpen) { if (!menuOpen) { return local.input.crouchIsPressed; } return IsActionHeld(CharacterInput.action_crouch); } public bool CanUseInput() { GUIManager instance = GUIManager.instance; if (Time.timeScale > 0f && (Object)(object)instance != (Object)null && !instance.windowBlockingInput) { return !instance.wheelActive; } return false; } public void Dispose() { _config.ToggleFlightKeyboardPath.SettingChanged -= OnBindingPathChanged; _config.TeleportMenuKeyboardPath.SettingChanged -= OnBindingPathChanged; _config.ControllerChordModifierPath.SettingChanged -= OnBindingPathChanged; _config.ControllerFlightTogglePath.SettingChanged -= OnBindingPathChanged; _config.ControllerTeleportMenuTogglePath.SettingChanged -= OnBindingPathChanged; _config.SpeedUpKeyboardPath.SettingChanged -= OnBindingPathChanged; _config.SlowDownKeyboardPath.SettingChanged -= OnBindingPathChanged; _config.SpeedUpControllerPath.SettingChanged -= OnBindingPathChanged; _config.SlowDownControllerPath.SettingChanged -= OnBindingPathChanged; DisposeConfiguredActions(); DisposeAction(ref _cancelAction); DisposeAction(ref _confirmAction); DisposeAction(ref _upAction); DisposeAction(ref _downAction); } private void OnBindingPathChanged(object sender, EventArgs eventArgs) { BindConfiguredActions(); } private void BindConfiguredActions() { DisposeConfiguredActions(); string keyboardPath = Normalize(_config.ToggleFlightKeyboardPath.Value); string keyboardPath2 = Normalize(_config.TeleportMenuKeyboardPath.Value); string text = Normalize(_config.ControllerChordModifierPath.Value); string controllerPath = Normalize(_config.ControllerFlightTogglePath.Value); string controllerPath2 = Normalize(_config.ControllerTeleportMenuTogglePath.Value); string text2 = Normalize(_config.SpeedUpKeyboardPath.Value); string text3 = Normalize(_config.SlowDownKeyboardPath.Value); string text4 = Normalize(_config.SpeedUpControllerPath.Value); string text5 = Normalize(_config.SlowDownControllerPath.Value); _controllerChordModifierAction = TryCreateButtonAction("FreeFly Controller Chord Modifier", "controller modifier", text); _flightToggleAction = TryCreateToggleAction("FreeFly Flight Toggle", "flight toggle", keyboardPath, controllerPath, text); _teleportMenuToggleAction = TryCreateToggleAction("FreeFly Teleport Menu Toggle", "teleport menu toggle", keyboardPath2, controllerPath2, text); _speedUpKeyboardAction = TryCreateButtonAction("FreeFly Keyboard Speed Up", "keyboard speed-up", text2); _slowDownKeyboardAction = TryCreateButtonAction("FreeFly Keyboard Slow Down", "keyboard slow-down", text3); _speedUpControllerAction = TryCreateButtonAction("FreeFly Controller Speed Up", "controller speed-up", text4); _slowDownControllerAction = TryCreateButtonAction("FreeFly Controller Slow Down", "controller slow-down", text5); } private void BindNavigationActions() { _cancelAction = TryCreateButtonAction("FreeFly Menu Cancel", "menu cancel", "/escape", "/buttonEast"); _confirmAction = TryCreateButtonAction("FreeFly Menu Confirm", "menu confirm", "/enter", "/buttonSouth"); _upAction = TryCreateButtonAction("FreeFly Menu Up", "menu up", "/upArrow", "/dpad/up"); _downAction = TryCreateButtonAction("FreeFly Menu Down", "menu down", "/downArrow", "/dpad/down"); } private InputAction? TryCreateToggleAction(string name, string description, string keyboardPath, string controllerPath, string modifierPath) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (keyboardPath.Length == 0 && controllerPath.Length == 0) { return null; } InputAction val = null; try { val = new InputAction(name, (InputActionType)1, (string)null, (string)null, (string)null, (string)null); if (keyboardPath.Length > 0) { InputActionSetupExtensions.AddBinding(val, keyboardPath, (string)null, (string)null, (string)null); } if (controllerPath.Length > 0) { if (modifierPath.Length == 0) { InputActionSetupExtensions.AddBinding(val, controllerPath, (string)null, (string)null, (string)null); } else { CompositeSyntax val2 = InputActionSetupExtensions.AddCompositeBinding(val, "OneModifier", (string)null, (string)null); val2 = ((CompositeSyntax)(ref val2)).With("modifier", modifierPath, (string)null, (string)null); ((CompositeSyntax)(ref val2)).With("binding", controllerPath, (string)null, (string)null); } } val.Enable(); return val; } catch (Exception ex) { if (val != null) { val.Dispose(); } _logger.LogWarning((object)("Could not bind the configured " + description + " paths; the action is disabled: " + ex.Message)); return null; } } private InputAction? TryCreateButtonAction(string name, string description, params string[] paths) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) InputAction val = null; try { val = new InputAction(name, (InputActionType)1, (string)null, (string)null, (string)null, (string)null); bool flag = false; foreach (string text in paths) { if (text.Length != 0) { InputActionSetupExtensions.AddBinding(val, text, (string)null, (string)null, (string)null); flag = true; } } if (!flag) { val.Dispose(); return null; } val.Enable(); return val; } catch (Exception ex) { if (val != null) { val.Dispose(); } _logger.LogWarning((object)("Could not bind the configured " + description + " paths; the action is disabled: " + ex.Message)); return null; } } private void DisposeConfiguredActions() { DisposeAction(ref _flightToggleAction); DisposeAction(ref _teleportMenuToggleAction); DisposeAction(ref _controllerChordModifierAction); DisposeAction(ref _speedUpKeyboardAction); DisposeAction(ref _slowDownKeyboardAction); DisposeAction(ref _speedUpControllerAction); DisposeAction(ref _slowDownControllerAction); } private static void DisposeAction(ref InputAction? action) { if (action != null) { action.Disable(); action.Dispose(); action = null; } } private static string Normalize(string? path) { return FreeFlyInputRules.NormalizeBindingPath(path); } private static bool IsActionHeld(InputAction? action) { if (action == null) { return false; } return action.IsPressed(); } private static bool WasPressedThisFrame(InputAction? action) { if (action == null) { return false; } return action.WasPressedThisFrame(); } } internal sealed class FreeFlyNotification : MonoBehaviour { private TextMeshProUGUI? _label; private Material? _labelMaterial; private CanvasGroup? _group; private Coroutine? _routine; public void Show(string message) { if (EnsureLabel() && !((Object)(object)_label == (Object)null) && !((Object)(object)_group == (Object)null)) { ((TMP_Text)_label).text = message; ((TMP_Text)_label).transform.SetAsLastSibling(); if (_routine != null) { ((MonoBehaviour)this).StopCoroutine(_routine); } _routine = ((MonoBehaviour)this).StartCoroutine(ShowRoutine()); } } private bool EnsureLabel() { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0202: 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_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Expected O, but got Unknown if ((Object)(object)_label != (Object)null && (Object)(object)_group != (Object)null) { return true; } if ((Object)(object)GUIManager.instance == (Object)null || (Object)(object)GUIManager.instance.hudCanvas == (Object)null) { return false; } GameObject val = new GameObject("FreeFly Notification", new Type[3] { typeof(RectTransform), typeof(CanvasGroup), typeof(TextMeshProUGUI) }); val.transform.SetParent(((Component)GUIManager.instance.hudCanvas).transform, false); RectTransform component = val.GetComponent(); component.anchorMin = new Vector2(0.5f, 1f); component.anchorMax = new Vector2(0.5f, 1f); component.pivot = new Vector2(0.5f, 1f); component.anchoredPosition = new Vector2(0f, -96f); component.sizeDelta = new Vector2(520f, 52f); _group = val.GetComponent(); _group.alpha = 0f; _group.blocksRaycasts = false; _group.interactable = false; _label = val.GetComponent(); ((TMP_Text)_label).alignment = (TextAlignmentOptions)514; ((TMP_Text)_label).fontSize = 30f; TextMeshProUGUI val2 = GUIManager.instance.interactNameText ?? GUIManager.instance.itemPromptMain; if ((Object)(object)val2 != (Object)null && (Object)(object)((TMP_Text)val2).font != (Object)null) { ((TMP_Text)_label).font = ((TMP_Text)val2).font; ((TMP_Text)_label).fontStyle = ((TMP_Text)val2).fontStyle; if ((Object)(object)((TMP_Text)val2).fontSharedMaterial != (Object)null) { _labelMaterial = new Material(((TMP_Text)val2).fontSharedMaterial); ((TMP_Text)_label).fontSharedMaterial = _labelMaterial; } } ((TMP_Text)_label).faceColor = Color32.op_Implicit(Color.white); ((TMP_Text)_label).outlineColor = Color32.op_Implicit(Color.black); ((TMP_Text)_label).outlineWidth = 0.08f; ((Graphic)_label).raycastTarget = false; return true; } private IEnumerator ShowRoutine() { if (!((Object)(object)_group == (Object)null)) { _group.alpha = 1f; yield return (object)new WaitForSecondsRealtime(1.25f); float elapsed = 0f; while (elapsed < 0.25f && (Object)(object)_group != (Object)null) { elapsed += Time.unscaledDeltaTime; _group.alpha = 1f - Mathf.Clamp01(elapsed / 0.25f); yield return null; } if ((Object)(object)_group != (Object)null) { _group.alpha = 0f; } _routine = null; } } private void OnDestroy() { if ((Object)(object)_label != (Object)null) { Object.Destroy((Object)(object)((Component)_label).gameObject); } if ((Object)(object)_labelMaterial != (Object)null) { Object.Destroy((Object)(object)_labelMaterial); } } } internal sealed class ModConfig { private const float DefaultBaseSpeed = 100f; private const float DefaultSpeedUpMultiplier = 2f; private const float DefaultSlowDownMultiplier = 0.2f; private const float DefaultTeleportVerticalOffset = 2f; private const float DefaultTeleportBackwardOffset = 1.5f; public ConfigEntry Enabled { get; } public ConfigEntry ToggleFlightKeyboardPath { get; } public ConfigEntry TeleportMenuKeyboardPath { get; } public ConfigEntry ControllerChordModifierPath { get; } public ConfigEntry ControllerFlightTogglePath { get; } public ConfigEntry ControllerTeleportMenuTogglePath { get; } public ConfigEntry SpeedUpKeyboardPath { get; } public ConfigEntry SlowDownKeyboardPath { get; } public ConfigEntry SpeedUpControllerPath { get; } public ConfigEntry SlowDownControllerPath { get; } public ConfigEntry BaseSpeed { get; } public ConfigEntry SpeedUpMultiplier { get; } public ConfigEntry SlowDownMultiplier { get; } public ConfigEntry TeleportVerticalOffset { get; } public ConfigEntry TeleportBackwardOffset { get; } public float SafeBaseSpeed => SafeRange(BaseSpeed.Value, 1f, 1000f, 100f); public float SafeSpeedUpMultiplier => SafeRange(SpeedUpMultiplier.Value, 1f, 10f, 2f); public float SafeSlowDownMultiplier => SafeRange(SlowDownMultiplier.Value, 0.05f, 1f, 0.2f); public float SafeTeleportVerticalOffset => SafeRange(TeleportVerticalOffset.Value, 0f, 10f, 2f); public float SafeTeleportBackwardOffset => SafeRange(TeleportBackwardOffset.Value, 0f, 10f, 1.5f); public ModConfig(ConfigFile config) { //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Expected O, but got Unknown //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Expected O, but got Unknown //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Expected O, but got Unknown //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Expected O, but got Unknown Enabled = config.Bind("General", "Enabled", true, "Enable local free flight and teammate teleport."); ToggleFlightKeyboardPath = config.Bind("Controls", "Toggle Flight Keyboard Path", "/f6", "Unity Input System control path used to toggle free flight with a keyboard. Leave empty to disable."); TeleportMenuKeyboardPath = config.Bind("Controls", "Teleport Menu Keyboard Path", "/f7", "Unity Input System control path used to open the teammate teleport menu with a keyboard. Leave empty to disable."); ControllerChordModifierPath = config.Bind("Controls", "Controller Chord Modifier Path", "/select", "Controller button held as the optional modifier for the flight and teleport menu shortcuts. Leave empty for single-button mode. Common paths: /select = View/Share; /start = Menu/Options; /leftShoulder = LB/L1; /rightShoulder = RB/R1; /buttonSouth = A/Cross; /buttonEast = B/Circle; /buttonWest = X/Square; /buttonNorth = Y/Triangle; /leftTrigger = LT/L2; /rightTrigger = RT/R2; /leftStickPress and /rightStickPress; /dpad/up, /dpad/down, /dpad/left, and /dpad/right. These semantic paths require a device recognized as Gamepad."); ControllerFlightTogglePath = config.Bind("Controls", "Controller Flight Toggle Path", "/leftShoulder", "Controller button pressed with the optional modifier to toggle free flight. Default: /leftShoulder (Xbox LB / PlayStation L1). Leave empty to disable."); ControllerTeleportMenuTogglePath = config.Bind("Controls", "Controller Teleport Menu Toggle Path", "/rightShoulder", "Controller button pressed with the optional modifier to toggle the teleport menu. Default: /rightShoulder (Xbox RB / PlayStation R1). Leave empty to disable."); SpeedUpKeyboardPath = config.Bind("Controls", "Speed Up Keyboard Path", "/leftShift", "Unity Input System control path held to temporarily increase flight speed with a keyboard. Leave empty to disable."); SlowDownKeyboardPath = config.Bind("Controls", "Slow Down Keyboard Path", "/leftAlt", "Unity Input System control path held to temporarily decrease flight speed with a keyboard. Leave empty to disable."); SpeedUpControllerPath = config.Bind("Controls", "Speed Up Controller Path", "/rightShoulder", "Unity Input System path held to temporarily increase flight speed. Default: /rightShoulder (Xbox RB / PlayStation R1). Leave empty to disable."); SlowDownControllerPath = config.Bind("Controls", "Slow Down Controller Path", "/leftShoulder", "Unity Input System path held to temporarily decrease flight speed. Default: /leftShoulder (Xbox LB / PlayStation L1). Leave empty to disable."); BaseSpeed = config.Bind("Movement", "Base Speed", 100f, new ConfigDescription("Base flight speed in meters per second.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 1000f), Array.Empty())); SpeedUpMultiplier = config.Bind("Movement", "Speed Up Multiplier", 2f, new ConfigDescription("Multiplier while the configured speed-up key or controller path is held.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 10f), Array.Empty())); SlowDownMultiplier = config.Bind("Movement", "Slow Down Multiplier", 0.2f, new ConfigDescription("Multiplier while the configured slow-down key or controller path is held.", (AcceptableValueBase)(object)new AcceptableValueRange(0.05f, 1f), Array.Empty())); TeleportVerticalOffset = config.Bind("Teleport", "Vertical Offset", 2f, new ConfigDescription("Height above the selected teammate's center when teleporting.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 10f), Array.Empty())); TeleportBackwardOffset = config.Bind("Teleport", "Backward Offset", 1.5f, new ConfigDescription("Distance behind the selected teammate when teleporting.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 10f), Array.Empty())); } private static float SafeRange(float value, float min, float max, float fallback) { if (float.IsNaN(value) || float.IsInfinity(value)) { return fallback; } return Mathf.Clamp(value, min, max); } } internal readonly struct PatchCapabilities { public bool FlightPatch { get; } public bool TeleportPatch { get; } public PatchCapabilities(bool flightPatch, bool teleportPatch) { FlightPatch = flightPatch; TeleportPatch = teleportPatch; } } internal static class PatchInstaller { public static PatchCapabilities Install(Harmony harmony, ManualLogSource logger) { bool flightPatch = TryPatch(harmony, AccessTools.Method(typeof(CharacterMovement), "FixedUpdate", (Type[])null, (Type[])null), AccessTools.Method(typeof(PatchCallbacks), "CharacterMovementFixedPostfix", (Type[])null, (Type[])null), "CharacterMovement.FixedUpdate", logger); bool flag = AccessTools.Method(typeof(Character), "WarpPlayerRPC", (Type[])null, (Type[])null) != null; if (!flag) { logger.LogError((object)"PEAK's Character.WarpPlayerRPC was not found; teleport is disabled."); } return new PatchCapabilities(flightPatch, flag); } private static bool TryPatch(Harmony harmony, MethodInfo? original, MethodInfo? postfix, string description, ManualLogSource logger) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown if (original == null || postfix == null) { logger.LogError((object)("Required patch target is missing: " + description + ".")); return false; } try { harmony.Patch((MethodBase)original, (HarmonyMethod)null, new HarmonyMethod(postfix), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); return true; } catch (Exception arg) { logger.LogError((object)$"Failed to patch {description}: {arg}"); return false; } } } internal static class PatchCallbacks { public static void CharacterMovementFixedPostfix(CharacterMovement __instance) { Plugin.Instance?.Controller.ApplyFlightPhysics(__instance); } } [BepInPlugin("com.github.lllei.FreeFly", "FreeFly", "1.3.0")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.github.lllei.FreeFly"; public const string PluginName = "FreeFly"; private FreeFlyNotification? _notification; private Harmony? _harmony; internal static Plugin? Instance { get; private set; } internal FreeFlyController Controller { get; private set; } private void Awake() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown Instance = this; ModConfig config = new ModConfig(((BaseUnityPlugin)this).Config); _notification = ((Component)this).gameObject.AddComponent(); FreeFlyInput input = new FreeFlyInput(config, ((BaseUnityPlugin)this).Logger); FlightRuntime flight = new FlightRuntime(config, ((BaseUnityPlugin)this).Logger, input, _notification); TeleportDestinationService destinations = new TeleportDestinationService(config, ((BaseUnityPlugin)this).Logger); TeleportMenuView menu = new TeleportMenuView(destinations); Controller = new FreeFlyController(config, input, flight, destinations, menu); _harmony = new Harmony("com.github.lllei.FreeFly"); PatchCapabilities capabilities = PatchInstaller.Install(_harmony, ((BaseUnityPlugin)this).Logger); Controller.SetCapabilities(capabilities); ((BaseUnityPlugin)this).Logger.LogInfo((object)("FreeFly 1.3.0 loaded. " + $"Flight patch: {capabilities.FlightPatch}; teleport: {capabilities.TeleportPatch}.")); } private void Update() { Controller?.TickUpdate(); } private void OnGUI() { Controller?.DrawMenu(); } private void OnDestroy() { Controller?.Shutdown(); Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } Instance = null; } } internal readonly struct TeleportOption { public string Label { get; } public Vector3 Position { get; } public Transform? Anchor { get; } public Character? Character { get; } public bool Enabled { get; } public TeleportOption(string label, Vector3 position, Transform? anchor, Character? character, bool enabled = true) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) Label = label; Position = position; Anchor = anchor; Character = character; Enabled = enabled; } } internal sealed class TeleportDestinationService { private const float RefreshInterval = 0.5f; private readonly ModConfig _config; private readonly ManualLogSource _logger; private readonly List _options = new List(); private Transform? _cachedPeakFlareDestination; private Transform? _cachedPeakPortalDestination; private Transform? _cachedSoulPillarDestination; private float _nextPeakFlareSearchTime; private float _nextPeakPortalSearchTime; private float _nextSoulPillarSearchTime; private float _nextRefreshTime; private int _cachedSceneHandle = int.MinValue; private Segment? _cachedSegment; private bool _hasCachedSegment; private PatchCapabilities _capabilities; public IReadOnlyList Options => _options; public TeleportDestinationService(ModConfig config, ManualLogSource logger) { _config = config; _logger = logger; } public void SetCapabilities(PatchCapabilities capabilities) { _capabilities = capabilities; } public void RefreshIfNeeded(bool force = false) { ObserveWorld(); if (force || !(Time.unscaledTime < _nextRefreshTime)) { _nextRefreshTime = Time.unscaledTime + 0.5f; RefreshTargets(); } } public bool TryTeleport(int selectedIndex) { //IL_005a: 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_007d: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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_0124: 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_0143: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: 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_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) Character localCharacter = Character.localCharacter; if (!_capabilities.TeleportPatch || (Object)(object)localCharacter == (Object)null || !FreeFlyCharacterUtils.IsUsable(localCharacter) || localCharacter.warping || selectedIndex < 0 || selectedIndex >= _options.Count) { return false; } TeleportOption teleportOption = _options[selectedIndex]; if (!teleportOption.Enabled) { return false; } Vector3 val = teleportOption.Position; Vector3 val2 = (((Object)(object)teleportOption.Anchor != (Object)null) ? teleportOption.Anchor.forward : Vector3.forward); if ((Object)(object)teleportOption.Character != (Object)null) { Character character = teleportOption.Character; if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null || (Object)(object)((Component)character).transform == (Object)null) { return false; } val = (character.data.dead ? character.GetSpectatePosition() : character.Center); val2 = ((Component)character).transform.forward; } val += Vector3.up * _config.SafeTeleportVerticalOffset; val -= val2 * _config.SafeTeleportBackwardOffset; if (!FreeFlyCharacterUtils.IsFinite(val)) { return false; } ((MonoBehaviourPun)localCharacter).photonView.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { val, true }); return true; } private void ObserveWorld() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); int num = SceneHandle.op_Implicit(((Scene)(ref activeScene)).handle); bool flag = false; Segment? val = null; try { if (MapHandler.ExistsAndInitialized) { flag = true; val = MapHandler.CurrentSegmentNumber; } } catch { } bool flag2 = flag != _hasCachedSegment || (flag && val != _cachedSegment); if (num != _cachedSceneHandle || flag2) { _cachedSceneHandle = num; _cachedSegment = val; _hasCachedSegment = flag; _cachedPeakFlareDestination = null; _cachedPeakPortalDestination = null; _cachedSoulPillarDestination = null; _nextPeakFlareSearchTime = 0f; _nextPeakPortalSearchTime = 0f; _nextSoulPillarSearchTime = 0f; _nextRefreshTime = 0f; } } private void RefreshTargets() { //IL_0104: Unknown result type (might be due to invalid IL or missing references) _options.Clear(); Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null) { return; } try { AddStageDestinations(); } catch (Exception ex) { _logger.LogDebug((object)("Stage teleport destinations are not ready: " + ex.Message)); } try { List list = new List(); List allPlayerCharacters = PlayerHandler.GetAllPlayerCharacters(); if (allPlayerCharacters != null) { foreach (Character item in allPlayerCharacters) { if (!((Object)(object)item == (Object)null) && !((Object)(object)item == (Object)(object)localCharacter) && !((Object)(object)item.data == (Object)null) && item.refs != null) { string text = (item.data.dead ? "Dead" : (item.data.fullyPassedOut ? "Passed out" : "Alive")); list.Add(new TeleportOption("Teammate: " + item.characterName + " [" + text + "]", Vector3.zero, null, item)); } } } list.Sort((TeleportOption left, TeleportOption right) => string.Compare(left.Label, right.Label, StringComparison.OrdinalIgnoreCase)); _options.AddRange(list); } catch (Exception ex2) { _logger.LogDebug((object)("Teammate teleport destinations are not ready: " + ex2.Message)); } } private void AddStageDestinations() { //IL_0008: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_007c: 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_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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_009a: Unknown result type (might be due to invalid IL or missing references) if (!MapHandler.ExistsAndInitialized) { return; } Segment currentSegmentNumber = MapHandler.CurrentSegmentNumber; if ((int)currentSegmentNumber == 6) { AddNadirDestinations(); return; } int num; int num2; if ((int)currentSegmentNumber != 4) { num = (((int)currentSegmentNumber == 5) ? 1 : 0); if (num == 0) { num2 = currentSegmentNumber + 1; goto IL_002d; } } else { num = 1; } num2 = 5; goto IL_002d; IL_002d: int num3 = num2; bool enabled = IsStageGenerated(currentSegmentNumber); Campfire previousCampfire = MapHandler.PreviousCampfire; object obj; if ((int)currentSegmentNumber != 0) { obj = ((previousCampfire != null) ? ((Component)previousCampfire).transform : null); } else { SpawnPoint localSpawnPoint = SpawnPoint.LocalSpawnPoint; obj = ((localSpawnPoint != null) ? ((Component)localSpawnPoint).transform : null); } Transform val = (Transform)obj; if ((Object)(object)val != (Object)null) { AddStageDestination(position: ((Object)(object)previousCampfire != (Object)null) ? previousCampfire.Center() : val.position, label: $"Stage {num3} start ({GetStageStartName(currentSegmentNumber)})", anchor: val, enabled: enabled); } if (num != 0) { Transform peakDestination = GetPeakDestination(); if ((Object)(object)peakDestination != (Object)null) { AddStageDestination("Stage 5 end (PEAK)", peakDestination.position, peakDestination, enabled); } } else { Campfire currentCampfire = MapHandler.CurrentCampfire; if ((Object)(object)currentCampfire != (Object)null) { AddStageDestination($"Stage {num3} end ({GetStageEndName(currentSegmentNumber)})", currentCampfire.Center(), ((Component)currentCampfire).transform, enabled); } } } private void AddNadirDestinations() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) if (VoidBiome.SoulFreedStatus == 1) { Transform soulPillarDestination = GetSoulPillarDestination(); if ((Object)(object)soulPillarDestination != (Object)null) { AddStageDestination("Nadir waypoint (Scoutmaster Soul)", soulPillarDestination.position, soulPillarDestination); } Transform peakPortalDestination = GetPeakPortalDestination(); if ((Object)(object)peakPortalDestination != (Object)null) { AddStageDestination("Nadir end (The Gate)", peakPortalDestination.position, peakPortalDestination); } return; } Transform val = null; try { val = MapHandler.CurrentBaseCampSpawnPoint; } catch { } if ((Object)(object)val != (Object)null) { AddStageDestination("Nadir start (Spawn)", val.position, val); } Transform soulPillarDestination2 = GetSoulPillarDestination(); if ((Object)(object)soulPillarDestination2 != (Object)null) { AddStageDestination("Nadir waypoint (Scoutmaster Soul)", soulPillarDestination2.position, soulPillarDestination2); } } private Transform? GetSoulPillarDestination() { if ((Object)(object)_cachedSoulPillarDestination != (Object)null) { return _cachedSoulPillarDestination; } if (Time.unscaledTime < _nextSoulPillarSearchTime) { return null; } _nextSoulPillarSearchTime = Time.unscaledTime + 1f; _cachedSoulPillarDestination = FindDestinationInRoots((GameObject?[])(object)new GameObject[1] { GetNadirSegmentRoot() }); return _cachedSoulPillarDestination; } private Transform? GetPeakPortalDestination() { if ((Object)(object)_cachedPeakPortalDestination != (Object)null) { return _cachedPeakPortalDestination; } if (Time.unscaledTime < _nextPeakPortalSearchTime) { return null; } _nextPeakPortalSearchTime = Time.unscaledTime + 1f; _cachedPeakPortalDestination = FindDestinationInRoots((GameObject?[])(object)new GameObject[1] { GetNadirSegmentRoot() }); return _cachedPeakPortalDestination; } private static Transform? FindDestinationInRoots(params GameObject?[] roots) where T : Component { Transform val = null; foreach (GameObject val2 in roots) { if ((Object)(object)val2 == (Object)null) { continue; } T[] componentsInChildren = val2.GetComponentsInChildren(true); foreach (T val3 in componentsInChildren) { if (!((Object)(object)val3 == (Object)null) && !((Object)(object)((Component)val3).transform == (Object)null)) { if (val == null) { val = ((Component)val3).transform; } if (((Component)val3).gameObject.activeInHierarchy) { return ((Component)val3).transform; } } } } return val; } private static GameObject? GetNadirSegmentRoot() { try { VoidBiome instance = VoidBiome.instance; object result; if (instance == null) { result = null; } else { MapSegment segment = instance.segment; result = ((segment != null) ? segment.segmentParent : null); } return (GameObject?)result; } catch { return null; } } private static GameObject? GetPeakHandlerRoot() { try { PeakHandler instance = Singleton.Instance; return (instance != null) ? ((Component)instance).gameObject : null; } catch { return null; } } private void AddStageDestination(string label, Vector3 position, Transform anchor, bool enabled = true) { //IL_0000: 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 (FreeFlyCharacterUtils.IsFinite(position)) { _options.Add(new TeleportOption(label, position, anchor, null, enabled)); } } private static bool IsStageGenerated(Segment segment) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Invalid comparison between Unknown and I4 //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 //IL_0023: Unknown result type (might be due to invalid IL or missing references) if ((int)segment == 0 || (int)segment == 6) { return true; } try { if (!MapHandler.CurrentMapSegment.segmentParent.activeInHierarchy) { return false; } int num = (((int)segment == 5) ? 4 : ((int)segment)); MountainProgressHandler instance = Singleton.Instance; return (Object)(object)instance != (Object)null && instance.maxProgressPointReached >= num; } catch { return false; } } private static string GetStageStartName(Segment segment) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected I4, but got Unknown //IL_000d: Unknown result type (might be due to invalid IL or missing references) if ((int)segment == 0) { return "Spawn"; } try { return GetBiomeDisplayName(MapHandler.GetBiomeForSegment(segment - 1)); } catch { return "Previous campfire"; } } private static string GetStageEndName(Segment segment) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected I4, but got Unknown //IL_0001: Unknown result type (might be due to invalid IL or missing references) try { return GetBiomeDisplayName(MapHandler.GetBiomeForSegment((int)segment)); } catch { return "Current campfire"; } } private unsafe static string GetBiomeDisplayName(BiomeType biome) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 if ((int)biome != 3) { if ((int)biome != 5) { if ((int)biome == 8) { return "Gloom"; } return ((object)(*(BiomeType*)(&biome))/*cast due to .constrained prefix*/).ToString(); } return "PEAK"; } return "Caldera"; } private Transform? GetPeakDestination() { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)_cachedPeakFlareDestination == (Object)null && Time.unscaledTime >= _nextPeakFlareSearchTime) { _nextPeakFlareSearchTime = Time.unscaledTime + 1f; GameObject peakHandlerRoot = GetPeakHandlerRoot(); object obj = (((Object)(object)peakHandlerRoot != (Object)null) ? ((object)peakHandlerRoot.GetComponentsInChildren(true)) : ((object)Array.Empty())); float num = float.MinValue; EndgameFlareSpawner[] array = (EndgameFlareSpawner[])obj; foreach (EndgameFlareSpawner val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).transform == (Object)null)) { Vector3 position = ((Component)val).transform.position; if (FreeFlyCharacterUtils.IsFinite(position) && position.y > num) { num = position.y; _cachedPeakFlareDestination = ((Component)val).transform; } } } } if ((Object)(object)_cachedPeakFlareDestination != (Object)null) { return _cachedPeakFlareDestination; } PeakHandler instance = Singleton.Instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.flareBox != (Object)null) { return instance.flareBox.transform; } MountainProgressHandler instance2 = Singleton.Instance; if ((Object)(object)instance2 == (Object)null || instance2.progressPoints == null || instance2.progressPoints.Length == 0) { return null; } return instance2.progressPoints[instance2.progressPoints.Length - 1]?.transform; } catch { return null; } } } internal sealed class TeleportMenuView { private readonly TeleportDestinationService _destinations; private GameObject? _inputBlockerObject; private FreeFlyMenuWindow? _inputBlockerWindow; private GUIStyle? _boxStyle; private GUIStyle? _labelStyle; private GUIStyle? _buttonStyle; private GUISkin? _styleSkin; private Vector2 _scrollPosition; private int _selectedTarget; public bool IsOpen { get; private set; } public TeleportMenuView(TeleportDestinationService destinations) { _destinations = destinations; } public void Open() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) _destinations.RefreshIfNeeded(force: true); _selectedTarget = FreeFlyInputRules.ClampSelection(_selectedTarget, _destinations.Options.Count); _scrollPosition = Vector2.zero; IsOpen = true; CreateInputBlocker(); } public void Tick(FreeFlyInputSnapshot input) { if (!IsOpen) { return; } _destinations.RefreshIfNeeded(); _selectedTarget = FreeFlyInputRules.ClampSelection(_selectedTarget, _destinations.Options.Count); if (input.Cancel) { Close(); return; } if (input.Up) { _selectedTarget = Mathf.Max(0, _selectedTarget - 1); } if (input.Down) { _selectedTarget = Mathf.Min(Mathf.Max(0, _destinations.Options.Count - 1), _selectedTarget + 1); } if (input.Confirm && _destinations.TryTeleport(_selectedTarget)) { Close(); } } public void Draw() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) if (!IsOpen) { return; } EnsureStyles(); float num = Mathf.Min(720f, (float)Screen.width - 40f); float num2 = Mathf.Min(620f, (float)Screen.height - 40f); Rect val = default(Rect); ((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, ((float)Screen.height - num2) * 0.5f, num, num2); GUI.Box(val, "FreeFly - Teleport", _boxStyle); GUILayout.BeginArea(new Rect(((Rect)(ref val)).x + 24f, ((Rect)(ref val)).y + 64f, ((Rect)(ref val)).width - 48f, ((Rect)(ref val)).height - 88f)); GUILayout.Label("Select a destination. Dead teammates use their corpse position.", _labelStyle, Array.Empty()); GUILayout.Space(12f); if (_destinations.Options.Count == 0) { GUILayout.Label("No teleport destination is available.", _labelStyle, Array.Empty()); } else { _scrollPosition = GUILayout.BeginScrollView(_scrollPosition, Array.Empty()); for (int i = 0; i < _destinations.Options.Count; i++) { TeleportOption teleportOption = _destinations.Options[i]; string text = (teleportOption.Enabled ? string.Empty : " [Generating...]"); string text2 = ((i == _selectedTarget) ? "> " : " ") + teleportOption.Label + text; bool enabled = GUI.enabled; GUI.enabled = teleportOption.Enabled; if (GUILayout.Button(text2, _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(52f) })) { _selectedTarget = i; if (_destinations.TryTeleport(_selectedTarget)) { Close(); } } GUI.enabled = enabled; } GUILayout.EndScrollView(); } GUILayout.FlexibleSpace(); GUILayout.Label("Up/Down or D-pad: select Enter/A: teleport Escape/B: cancel", _labelStyle, Array.Empty()); GUILayout.EndArea(); } public void Close() { IsOpen = false; DestroyInputBlocker(); } public void Shutdown() { Close(); } private void EnsureStyles() { //IL_0041: 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_0053: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown if (!((Object)(object)_styleSkin == (Object)(object)GUI.skin) || _boxStyle == null || _labelStyle == null || _buttonStyle == null) { _styleSkin = GUI.skin; _boxStyle = new GUIStyle(GUI.skin.box) { fontSize = 28 }; _labelStyle = new GUIStyle(GUI.skin.label) { fontSize = 20, wordWrap = true }; _buttonStyle = new GUIStyle(GUI.skin.button) { fontSize = 22 }; } } private void CreateInputBlocker() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown if (!((Object)(object)_inputBlockerObject != (Object)null)) { _inputBlockerObject = new GameObject("FreeFly Teleport Menu Input Blocker"); _inputBlockerWindow = _inputBlockerObject.AddComponent(); if (!MenuWindow.AllActiveWindows.Contains((MenuWindow)(object)_inputBlockerWindow)) { MenuWindow.AllActiveWindows.Add((MenuWindow)(object)_inputBlockerWindow); } } } private void DestroyInputBlocker() { if ((Object)(object)_inputBlockerWindow != (Object)null) { MenuWindow.AllActiveWindows.Remove((MenuWindow)(object)_inputBlockerWindow); } if ((Object)(object)_inputBlockerObject != (Object)null) { Object.Destroy((Object)(object)_inputBlockerObject); } _inputBlockerWindow = null; _inputBlockerObject = null; } } internal static class BuildInfo { internal const string Version = "1.3.0"; } } namespace FreeFly.Core { internal static class FreeFlyInputRules { public static string NormalizeBindingPath(string? path) { return path?.Trim() ?? string.Empty; } public static int ClampSelection(int selectedIndex, int optionCount) { if (optionCount <= 0) { return 0; } if (selectedIndex >= 0) { if (selectedIndex < optionCount) { return selectedIndex; } return optionCount - 1; } return 0; } } internal static class FreeFlyMath { public static float ApplySpeedModifiers(float baseSpeed, bool speedUp, bool slowDown, float speedUpMultiplier, float slowDownMultiplier) { if (!IsFinite(baseSpeed) || baseSpeed < 0f || !IsFinite(speedUpMultiplier) || speedUpMultiplier < 0f || !IsFinite(slowDownMultiplier) || slowDownMultiplier < 0f) { return 0f; } float num = 1f; if (speedUp) { num *= speedUpMultiplier; } if (slowDown) { num *= slowDownMultiplier; } return baseSpeed * num; } public static bool IsFinite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } } }