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<Rigidbody, bool> _originalGravity = new Dictionary<Rigidbody, bool>();
private readonly Dictionary<Collider, bool> _originalColliderState = new Dictionary<Collider, bool>();
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<Collider>(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<Collider, bool> 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>() : 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", "<Keyboard>/escape", "<Gamepad>/buttonEast");
_confirmAction = TryCreateButtonAction("FreeFly Menu Confirm", "menu confirm", "<Keyboard>/enter", "<Gamepad>/buttonSouth");
_upAction = TryCreateButtonAction("FreeFly Menu Up", "menu up", "<Keyboard>/upArrow", "<Gamepad>/dpad/up");
_downAction = TryCreateButtonAction("FreeFly Menu Down", "menu down", "<Keyboard>/downArrow", "<Gamepad>/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<RectTransform>();
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<CanvasGroup>();
_group.alpha = 0f;
_group.blocksRaycasts = false;
_group.interactable = false;
_label = val.GetComponent<TextMeshProUGUI>();
((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<bool> Enabled { get; }
public ConfigEntry<string> ToggleFlightKeyboardPath { get; }
public ConfigEntry<string> TeleportMenuKeyboardPath { get; }
public ConfigEntry<string> ControllerChordModifierPath { get; }
public ConfigEntry<string> ControllerFlightTogglePath { get; }
public ConfigEntry<string> ControllerTeleportMenuTogglePath { get; }
public ConfigEntry<string> SpeedUpKeyboardPath { get; }
public ConfigEntry<string> SlowDownKeyboardPath { get; }
public ConfigEntry<string> SpeedUpControllerPath { get; }
public ConfigEntry<string> SlowDownControllerPath { get; }
public ConfigEntry<float> BaseSpeed { get; }
public ConfigEntry<float> SpeedUpMultiplier { get; }
public ConfigEntry<float> SlowDownMultiplier { get; }
public ConfigEntry<float> TeleportVerticalOffset { get; }
public ConfigEntry<float> 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<bool>("General", "Enabled", true, "Enable local free flight and teammate teleport.");
ToggleFlightKeyboardPath = config.Bind<string>("Controls", "Toggle Flight Keyboard Path", "<Keyboard>/f6", "Unity Input System control path used to toggle free flight with a keyboard. Leave empty to disable.");
TeleportMenuKeyboardPath = config.Bind<string>("Controls", "Teleport Menu Keyboard Path", "<Keyboard>/f7", "Unity Input System control path used to open the teammate teleport menu with a keyboard. Leave empty to disable.");
ControllerChordModifierPath = config.Bind<string>("Controls", "Controller Chord Modifier Path", "<Gamepad>/select", "Controller button held as the optional modifier for the flight and teleport menu shortcuts. Leave empty for single-button mode. Common paths: <Gamepad>/select = View/Share; <Gamepad>/start = Menu/Options; <Gamepad>/leftShoulder = LB/L1; <Gamepad>/rightShoulder = RB/R1; <Gamepad>/buttonSouth = A/Cross; <Gamepad>/buttonEast = B/Circle; <Gamepad>/buttonWest = X/Square; <Gamepad>/buttonNorth = Y/Triangle; <Gamepad>/leftTrigger = LT/L2; <Gamepad>/rightTrigger = RT/R2; <Gamepad>/leftStickPress and <Gamepad>/rightStickPress; <Gamepad>/dpad/up, <Gamepad>/dpad/down, <Gamepad>/dpad/left, and <Gamepad>/dpad/right. These semantic paths require a device recognized as Gamepad.");
ControllerFlightTogglePath = config.Bind<string>("Controls", "Controller Flight Toggle Path", "<Gamepad>/leftShoulder", "Controller button pressed with the optional modifier to toggle free flight. Default: <Gamepad>/leftShoulder (Xbox LB / PlayStation L1). Leave empty to disable.");
ControllerTeleportMenuTogglePath = config.Bind<string>("Controls", "Controller Teleport Menu Toggle Path", "<Gamepad>/rightShoulder", "Controller button pressed with the optional modifier to toggle the teleport menu. Default: <Gamepad>/rightShoulder (Xbox RB / PlayStation R1). Leave empty to disable.");
SpeedUpKeyboardPath = config.Bind<string>("Controls", "Speed Up Keyboard Path", "<Keyboard>/leftShift", "Unity Input System control path held to temporarily increase flight speed with a keyboard. Leave empty to disable.");
SlowDownKeyboardPath = config.Bind<string>("Controls", "Slow Down Keyboard Path", "<Keyboard>/leftAlt", "Unity Input System control path held to temporarily decrease flight speed with a keyboard. Leave empty to disable.");
SpeedUpControllerPath = config.Bind<string>("Controls", "Speed Up Controller Path", "<Gamepad>/rightShoulder", "Unity Input System path held to temporarily increase flight speed. Default: <Gamepad>/rightShoulder (Xbox RB / PlayStation R1). Leave empty to disable.");
SlowDownControllerPath = config.Bind<string>("Controls", "Slow Down Controller Path", "<Gamepad>/leftShoulder", "Unity Input System path held to temporarily decrease flight speed. Default: <Gamepad>/leftShoulder (Xbox LB / PlayStation L1). Leave empty to disable.");
BaseSpeed = config.Bind<float>("Movement", "Base Speed", 100f, new ConfigDescription("Base flight speed in meters per second.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 1000f), Array.Empty<object>()));
SpeedUpMultiplier = config.Bind<float>("Movement", "Speed Up Multiplier", 2f, new ConfigDescription("Multiplier while the configured speed-up key or controller path is held.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
SlowDownMultiplier = config.Bind<float>("Movement", "Slow Down Multiplier", 0.2f, new ConfigDescription("Multiplier while the configured slow-down key or controller path is held.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>()));
TeleportVerticalOffset = config.Bind<float>("Teleport", "Vertical Offset", 2f, new ConfigDescription("Height above the selected teammate's center when teleporting.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
TeleportBackwardOffset = config.Bind<float>("Teleport", "Backward Offset", 1.5f, new ConfigDescription("Distance behind the selected teammate when teleporting.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
}
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<FreeFlyNotification>();
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<TeleportOption> _options = new List<TeleportOption>();
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<TeleportOption> 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<TeleportOption> list = new List<TeleportOption>();
List<Character> 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<ScoutmasterSoulPillar>((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<PeakGatePortal>((GameObject?[])(object)new GameObject[1] { GetNadirSegmentRoot() });
return _cachedPeakPortalDestination;
}
private static Transform? FindDestinationInRoots<T>(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<T>(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<PeakHandler>.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<MountainProgressHandler>.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<EndgameFlareSpawner>(true)) : ((object)Array.Empty<EndgameFlareSpawner>()));
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<PeakHandler>.Instance;
if ((Object)(object)instance != (Object)null && (Object)(object)instance.flareBox != (Object)null)
{
return instance.flareBox.transform;
}
MountainProgressHandler instance2 = Singleton<MountainProgressHandler>.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<GUILayoutOption>());
GUILayout.Space(12f);
if (_destinations.Options.Count == 0)
{
GUILayout.Label("No teleport destination is available.", _labelStyle, Array.Empty<GUILayoutOption>());
}
else
{
_scrollPosition = GUILayout.BeginScrollView(_scrollPosition, Array.Empty<GUILayoutOption>());
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<GUILayoutOption>());
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<FreeFlyMenuWindow>();
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;
}
}
}