using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using ArcadeMovement;
using ArcadeMovement.Integration;
using ArcadeMovement.Logging;
using ArcadeMovement.Patches;
using Fusion;
using HarmonyLib;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Utilities;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(ModMain), "Arcade Movement", "1.0.0", "Generic", null)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("ArcadeMovement")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+852064e45704d7481eb1c862897c77a4e247cc87")]
[assembly: AssemblyProduct("Arcade Movement")]
[assembly: AssemblyTitle("Arcade Movement")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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]
[Microsoft.CodeAnalysis.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]
[Microsoft.CodeAnalysis.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 ArcadeMovement
{
public sealed class ModMain : MelonMod
{
public override void OnInitializeMelon()
{
AmLog.Msg("initialized.");
SprintPatch.SetupPreferences();
ADVRIntegration.HookIntoModLoader();
ADVRIntegration.EvaluateAndApply();
}
}
}
namespace ArcadeMovement.Patches
{
internal static class SprintPatch
{
private class SprintState
{
public bool IsSprinting;
public float CooldownEndTime;
public bool CooldownNotified;
public float Meter = -1f;
public float LastUpdateAt = -1f;
public bool RechargeBeganLogged;
public bool IsDashing;
public float DashEndTime;
public int DashCharges = -1;
public float NextDashRechargeAt = -1f;
}
internal static class HarmonyHooks
{
[HarmonyPatch(typeof(PlayerLiving), "Update")]
internal static class PlayerLiving_Update_PostfixPatch
{
[HarmonyPostfix]
private static void Postfix(PlayerLiving __instance)
{
PlayerLiving_Update_Postfix_Impl(__instance);
}
}
[HarmonyPatch(typeof(GameHandler), "ChangePlayerMoveSpeed")]
internal static class GameHandler_ChangePlayerMoveSpeed_PostfixPatch
{
[HarmonyPostfix]
private static void Postfix(float val)
{
GameHandler_ChangePlayerMoveSpeed_Postfix_Impl(val);
}
}
[HarmonyPatch(typeof(PlayerLiving), "MoveSpeed_ValueChanged")]
internal static class PlayerLiving_MoveSpeed_ValueChanged_PostfixPatch
{
[HarmonyPostfix]
private static void Postfix(PlayerLiving __instance)
{
PlayerLiving_MoveSpeed_ValueChanged_Postfix_Impl(__instance);
}
}
[HarmonyPatch(typeof(SettingsMod), "OnApplyClick")]
internal static class SettingsMod_OnApplyClick_PostfixPatch
{
[HarmonyPostfix]
private static void Postfix()
{
try
{
ApplyDominantHandSelection(GetMovementControllerSettingText());
}
catch
{
}
}
}
}
private const string MultKey = "arcade_movement_sprint";
private const string UnlimitedSprintItemId = "am_unlimited_sprint";
private const string UpgradedDashItemId = "am_upgraded_dash";
private const int UpgradedDashExtraCharges = 1;
private const float UpgradedDashRechargeMultiplier = 0.8f;
private static float SprintMultiplier = 1.8f;
private static float SprintDuration = 3f;
private static float SprintCooldown = 5f;
private static float SprintDrainPerSecond = 1f;
private static float SprintRechargePerSecond = 1f;
private static bool DashEnabled = true;
private static float DashSpeedMultiplier = 3f;
private static float DashDurationSeconds = 0.2f;
private static float DashRechargeSeconds = 5f;
private static int DashMaxCharges = 1;
private static float DashDoubleClickWindow = 0.25f;
private static bool DebugLogs = false;
private static float SmoothCheckInterval = 0.5f;
private static float _lastSmoothCheckAt = -1f;
private static bool _lastSmoothSelected = true;
private static float _lastStatusLogAt = -1f;
private static float _statusLogMinInterval = 1f;
private static Harmony? _harmony;
private static InputAction? _leftClick;
private static InputAction? _rightClick;
private static int _clickHeldCount;
private static string? _lastMovementControllerText;
private static float _lastHandCheckAt = -1f;
private static float _lastDashClickReleasedAt = -1f;
private static float _dashRequestAt = -1f;
private static bool _sprintOnLeft = false;
private static bool _dashOnLeft = false;
private static string? _lastMovementTypeText;
private static string? _lastControllerMoveTypeText;
private static readonly ConditionalWeakTable<PlayerLiving, SprintState> _states = new ConditionalWeakTable<PlayerLiving, SprintState>();
private static MelonPreferences_Category? _prefCat;
private static MelonPreferences_Entry<float>? _prefSprintMult;
private static MelonPreferences_Entry<float>? _prefSprintDur;
private static MelonPreferences_Entry<float>? _prefSprintCd;
private static MelonPreferences_Entry<float>? _prefDrainRate;
private static MelonPreferences_Entry<float>? _prefRechargeRate;
private static MelonPreferences_Entry<bool>? _prefDashEnabled;
private static MelonPreferences_Entry<float>? _prefDashSpeedMult;
private static MelonPreferences_Entry<float>? _prefDashDuration;
private static MelonPreferences_Entry<float>? _prefDashRecharge;
private static MelonPreferences_Entry<int>? _prefDashMaxCharges;
private static MelonPreferences_Entry<float>? _prefDashDoubleClick;
private static MelonPreferences_Entry<bool>? _prefDebugLogs;
private static MelonPreferences_Entry<float>? _prefSmoothCheckInterval;
private static MelonPreferences_Entry<float>? _prefStatusLogMinInterval;
public static bool IsApplied { get; private set; }
public static void SetupPreferences()
{
try
{
_prefCat = MelonPreferences.CreateCategory("ArcadeMovement", "Arcade Movement");
_prefSprintMult = _prefCat.CreateEntry<float>("SprintMultiplier", SprintMultiplier, "Sprint speed multiplier", (string)null, false, false, (ValueValidator)null, (string)null);
_prefSprintDur = _prefCat.CreateEntry<float>("SprintDurationSeconds", SprintDuration, "Sprint meter capacity (seconds)", (string)null, false, false, (ValueValidator)null, (string)null);
_prefSprintCd = _prefCat.CreateEntry<float>("SprintCooldownSeconds", SprintCooldown, "Recharge delay after sprint ends (seconds)", (string)null, false, false, (ValueValidator)null, (string)null);
_prefDrainRate = _prefCat.CreateEntry<float>("SprintDrainPerSecond", SprintDrainPerSecond, "Drain rate while sprinting (sec/sec)", (string)null, false, false, (ValueValidator)null, (string)null);
_prefRechargeRate = _prefCat.CreateEntry<float>("SprintRechargePerSecond", SprintRechargePerSecond, "Recharge rate after delay (sec/sec)", (string)null, false, false, (ValueValidator)null, (string)null);
_prefDashEnabled = _prefCat.CreateEntry<bool>("DashEnabled", DashEnabled, "Enable dash on double-click", (string)null, false, false, (ValueValidator)null, (string)null);
_prefDashSpeedMult = _prefCat.CreateEntry<float>("DashSpeedMultiplier", DashSpeedMultiplier, "Dash speed multiplier", (string)null, false, false, (ValueValidator)null, (string)null);
_prefDashDuration = _prefCat.CreateEntry<float>("DashDurationSeconds", DashDurationSeconds, "Dash duration (seconds)", (string)null, false, false, (ValueValidator)null, (string)null);
_prefDashRecharge = _prefCat.CreateEntry<float>("DashRechargeSeconds", DashRechargeSeconds, "Seconds per dash recharge", (string)null, false, false, (ValueValidator)null, (string)null);
_prefDashMaxCharges = _prefCat.CreateEntry<int>("DashMaxCharges", DashMaxCharges, "Max dash charges", (string)null, false, false, (ValueValidator)null, (string)null);
_prefDashDoubleClick = _prefCat.CreateEntry<float>("DashDoubleClickWindowSeconds", DashDoubleClickWindow, "Double-click window (seconds)", (string)null, false, false, (ValueValidator)null, (string)null);
_prefDebugLogs = _prefCat.CreateEntry<bool>("EnableDebugLogs", false, "Verbose logging for troubleshooting", (string)null, false, false, (ValueValidator)null, (string)null);
_prefSmoothCheckInterval = _prefCat.CreateEntry<float>("SmoothCheckIntervalSeconds", SmoothCheckInterval, "How often to re-check movement settings", (string)null, false, false, (ValueValidator)null, (string)null);
_prefStatusLogMinInterval = _prefCat.CreateEntry<float>("StatusLogIntervalSeconds", _statusLogMinInterval, "Minimum seconds between status logs", (string)null, false, false, (ValueValidator)null, (string)null);
ApplyPreferences();
}
catch (Exception ex)
{
AmLog.Warn("[Sprint] Failed to setup preferences: " + ex.Message);
}
}
public static void ApplyPreferences()
{
try
{
if (_prefSprintMult != null)
{
SprintMultiplier = Math.Max(1f, _prefSprintMult.Value);
}
if (_prefSprintDur != null)
{
SprintDuration = Math.Max(0.1f, _prefSprintDur.Value);
}
if (_prefSprintCd != null)
{
SprintCooldown = Math.Max(0f, _prefSprintCd.Value);
}
if (_prefDebugLogs != null)
{
DebugLogs = _prefDebugLogs.Value;
}
AmLog.SetEnabled(DebugLogs);
if (_prefSmoothCheckInterval != null)
{
SmoothCheckInterval = Math.Max(0.1f, _prefSmoothCheckInterval.Value);
}
if (_prefStatusLogMinInterval != null)
{
_statusLogMinInterval = Math.Max(0.25f, _prefStatusLogMinInterval.Value);
}
if (_prefDrainRate != null)
{
SprintDrainPerSecond = Math.Max(0.01f, _prefDrainRate.Value);
}
if (_prefRechargeRate != null)
{
SprintRechargePerSecond = Math.Max(0.01f, _prefRechargeRate.Value);
}
if (_prefDashEnabled != null)
{
DashEnabled = _prefDashEnabled.Value;
}
if (_prefDashSpeedMult != null)
{
DashSpeedMultiplier = Math.Max(1f, _prefDashSpeedMult.Value);
}
if (_prefDashDuration != null)
{
DashDurationSeconds = Math.Max(0.05f, _prefDashDuration.Value);
}
if (_prefDashRecharge != null)
{
DashRechargeSeconds = Math.Max(0.1f, _prefDashRecharge.Value);
}
if (_prefDashMaxCharges != null)
{
DashMaxCharges = Math.Max(1, _prefDashMaxCharges.Value);
}
if (_prefDashDoubleClick != null)
{
DashDoubleClickWindow = Math.Max(0.05f, Math.Min(0.75f, _prefDashDoubleClick.Value));
}
}
catch (Exception ex)
{
AmLog.Warn("[Sprint] Failed to apply preferences: " + ex.Message);
}
}
public static void Apply()
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Expected O, but got Unknown
try
{
if (!IsApplied)
{
_harmony = new Harmony("ArcadeMovement.Sprint");
_harmony.CreateClassProcessor(typeof(SprintPatch)).Patch();
SetupInput();
IsApplied = true;
AmLog.Msg("[Sprint] Enabled (hold stick/trackpad click to sprint)");
}
}
catch (Exception arg)
{
AmLog.Error($"Failed to apply SprintPatch: {arg}");
}
}
public static void Remove()
{
try
{
if (!IsApplied)
{
return;
}
try
{
InputAction? leftClick = _leftClick;
if (leftClick != null)
{
leftClick.Disable();
}
InputAction? rightClick = _rightClick;
if (rightClick != null)
{
rightClick.Disable();
}
}
catch
{
}
_leftClick = null;
_rightClick = null;
ClearForCurrentPlayer();
try
{
Harmony? harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchAll((string)null);
}
}
catch
{
}
_harmony = null;
IsApplied = false;
AmLog.Msg("[Sprint] Disabled by Mod Manager");
}
catch (Exception ex)
{
AmLog.Warn("Failed to remove SprintPatch: " + ex.Message);
}
}
private static void SetupInput()
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Expected O, but got Unknown
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Expected O, but got Unknown
try
{
_leftClick = new InputAction("AM_SprintLeft", (InputActionType)1, (string)null, (string)null, (string)null, (string)null);
_rightClick = new InputAction("AM_SprintRight", (InputActionType)1, (string)null, (string)null, (string)null, (string)null);
AddClickBindings(_leftClick, "{LeftHand}");
AddClickBindings(_rightClick, "{RightHand}");
_leftClick.started += OnClickStarted;
_rightClick.started += OnClickStarted;
_leftClick.canceled += OnClickCanceled;
_rightClick.canceled += OnClickCanceled;
ApplyDominantHandSelection(GetMovementControllerSettingText());
_leftClick.Enable();
_rightClick.Enable();
AmLog.Msg("[Sprint] Input wired: dominant=SPRINT, opposite=DASH");
}
catch (Exception arg)
{
AmLog.Error($"Sprint input setup error: {arg}");
}
static void AddClickBindings(InputAction action, string handTag)
{
InputAction action2 = action;
Add("*/" + handTag + "/Primary2DAxisClick");
Add("<XRController>" + handTag + "/Primary2DAxisClick");
Add("*/" + handTag + "/thumbstickClicked");
Add("<XRController>" + handTag + "/thumbstickClicked");
Add("<ValveIndexController>" + handTag + "/thumbstickClicked");
Add("*/" + handTag + "/joystickClicked");
Add("<XRController>" + handTag + "/joystickClicked");
Add("*/" + handTag + "/trackpadClicked");
Add("<XRController>" + handTag + "/trackpadClicked");
Add("<ValveIndexController>" + handTag + "/trackpadClicked");
Add("*/" + handTag + "/touchpadClicked");
Add("<XRController>" + handTag + "/touchpadClicked");
void Add(string path)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
if (!string.IsNullOrEmpty(path))
{
InputActionSetupExtensions.AddBinding(action2, path, (string)null, (string)null, (string)null);
}
}
}
}
private static void OnClickStarted(CallbackContext ctx)
{
if (IsSprintAction(((CallbackContext)(ref ctx)).action))
{
_clickHeldCount++;
}
try
{
string text = ((((CallbackContext)(ref ctx)).action == _leftClick) ? "Left" : ((((CallbackContext)(ref ctx)).action == _rightClick) ? "Right" : "?"));
GameHandler iNSTANCE = GameHandler.INSTANCE;
PlayerLiving val = (((Object)(object)iNSTANCE != (Object)null) ? iNSTANCE.playerLiving : null);
bool flag = IsInitialized();
if ((Object)(object)val == (Object)null)
{
AmLog.Msg($"[Sprint] Press: {text} held={_clickHeldCount} init={flag} player=null (not spawned yet)");
return;
}
if (IsDashAction(((CallbackContext)(ref ctx)).action))
{
float unscaledTime = Time.unscaledTime;
if (DashEnabled && _lastDashClickReleasedAt > 0f && unscaledTime - _lastDashClickReleasedAt <= DashDoubleClickWindow)
{
_dashRequestAt = Time.time;
AmLog.Msg("[Dash] Double-click detected; scheduling dash (hand=" + text + ")");
}
}
bool flag2 = false;
bool flag3 = false;
bool flag4 = false;
string text2 = "?";
try
{
flag2 = ((NetworkBehaviour)val).HasStateAuthority;
}
catch
{
}
try
{
flag3 = IsWalking(val);
}
catch
{
}
try
{
flag4 = ((LivingBase)val).isDead;
}
catch
{
}
try
{
text2 = GetControllerMovementTypeText(val);
}
catch
{
}
bool flag5 = false;
try
{
flag5 = IsSmoothMovementSelected();
}
catch
{
}
SprintState orCreateValue = _states.GetOrCreateValue(val);
if (orCreateValue.Meter < 0f)
{
orCreateValue.Meter = SprintDuration;
}
float time = Time.time;
float num = Mathf.Max(0f, orCreateValue.CooldownEndTime - time);
bool flag6 = num > 0f;
bool isSprinting = orCreateValue.IsSprinting;
string settingsMovementTypeText = GetSettingsMovementTypeText();
AmLog.Msg(string.Format("[Sprint] Press: {0} auth={1} init={2} smooth={3} settings='{4}' ctrl='{5}' walking={6} dead={7} sprinting={8} cooldown={9} meter={10:0.00}/{11:0.00}", text, flag2, flag, flag5, settingsMovementTypeText, text2, flag3, flag4, isSprinting, flag6 ? (num.ToString("0.00") + "s") : "no", orCreateValue.Meter, SprintDuration));
}
catch
{
}
}
private static void OnClickCanceled(CallbackContext ctx)
{
if (IsSprintAction(((CallbackContext)(ref ctx)).action))
{
_clickHeldCount = Math.Max(0, _clickHeldCount - 1);
}
try
{
string arg = ((((CallbackContext)(ref ctx)).action == _leftClick) ? "Left" : ((((CallbackContext)(ref ctx)).action == _rightClick) ? "Right" : "?"));
AmLog.Msg($"[Sprint] Click released: {arg} (held={_clickHeldCount})");
}
catch
{
}
if (IsDashAction(((CallbackContext)(ref ctx)).action))
{
_lastDashClickReleasedAt = Time.unscaledTime;
}
}
private static void PlayerLiving_Update_Postfix_Impl(PlayerLiving __instance)
{
//IL_0718: Unknown result type (might be due to invalid IL or missing references)
//IL_0613: Unknown result type (might be due to invalid IL or missing references)
//IL_0637: Unknown result type (might be due to invalid IL or missing references)
//IL_062d: Unknown result type (might be due to invalid IL or missing references)
try
{
if (!((NetworkBehaviour)__instance).HasStateAuthority || !IsInitialized())
{
return;
}
LogMovementModeIfChanged(__instance);
float unscaledTime = Time.unscaledTime;
if (_lastHandCheckAt < 0f || unscaledTime >= _lastHandCheckAt + SmoothCheckInterval)
{
_lastHandCheckAt = unscaledTime;
string movementControllerSettingText = GetMovementControllerSettingText();
if (!string.Equals(_lastMovementControllerText, movementControllerSettingText, StringComparison.Ordinal))
{
ApplyDominantHandSelection(movementControllerSettingText);
}
}
if (!IsSmoothMovementSelected())
{
EnsureSprintCleared(__instance);
return;
}
if (!IsWalking(__instance) || ((LivingBase)__instance).isDead)
{
EnsureSprintCleared(__instance);
return;
}
SprintState orCreateValue = _states.GetOrCreateValue(__instance);
if (orCreateValue.Meter < 0f)
{
orCreateValue.Meter = SprintDuration;
}
float time = Time.time;
float num = ((!(orCreateValue.LastUpdateAt < 0f)) ? Mathf.Max(0f, time - orCreateValue.LastUpdateAt) : Time.deltaTime);
orCreateValue.LastUpdateAt = time;
bool flag = _clickHeldCount > 0;
bool flag2 = HasUnlimitedSprintLocal();
bool flag3 = HasUpgradedDashLocal();
bool num2 = flag && !orCreateValue.IsSprinting && IsWalking(__instance) && (flag2 || orCreateValue.Meter > 0f);
if (flag && !orCreateValue.IsSprinting)
{
Mathf.Max(0f, orCreateValue.CooldownEndTime - time);
AmLog.Msg("[Sprint] Update: held=1");
}
if (num2)
{
orCreateValue.IsSprinting = true;
orCreateValue.CooldownNotified = false;
orCreateValue.RechargeBeganLogged = false;
ApplyMoveSpeedMultiplier(__instance, SprintMultiplier);
TryHapticPulse(0.1f, 0.2f);
AmLog.Msg($"[Sprint] START '{GetPlayerObjectName(__instance)}' mult={SprintMultiplier} meter={orCreateValue.Meter:0.00}/{SprintDuration:0.00}");
}
if (orCreateValue.IsSprinting)
{
if (!flag || !IsWalking(__instance) || ((LivingBase)__instance).isDead)
{
orCreateValue.IsSprinting = false;
orCreateValue.CooldownEndTime = (flag2 ? time : (time + SprintCooldown));
orCreateValue.CooldownNotified = false;
ClearMoveSpeedMultiplier(__instance);
AmLog.Msg(string.Format("[Sprint] END '{0}' reason={1} cooldown={2:0.0}s meter={3:0.00}/{4:0.00}", GetPlayerObjectName(__instance), (!flag) ? "release" : (IsWalking(__instance) ? ("dead=" + ((LivingBase)__instance).isDead) : "mode"), SprintCooldown, orCreateValue.Meter, SprintDuration));
}
else if (flag2)
{
orCreateValue.Meter = SprintDuration;
orCreateValue.CooldownEndTime = time;
}
else
{
float num3 = SprintDrainPerSecond * num;
if (num3 > 0f)
{
float meter = orCreateValue.Meter;
orCreateValue.Meter = Mathf.Max(0f, orCreateValue.Meter - num3);
if (meter > 0f && orCreateValue.Meter <= 0f)
{
orCreateValue.IsSprinting = false;
orCreateValue.CooldownEndTime = time + SprintCooldown;
orCreateValue.CooldownNotified = false;
ClearMoveSpeedMultiplier(__instance);
AmLog.Msg($"[Sprint] DEPLETED -> cooldown {SprintCooldown:0.0}s");
}
}
}
}
if (!orCreateValue.IsSprinting)
{
if (flag2)
{
orCreateValue.Meter = SprintDuration;
orCreateValue.CooldownEndTime = time;
orCreateValue.RechargeBeganLogged = false;
}
else if (time < orCreateValue.CooldownEndTime)
{
float num4 = Mathf.Max(0f, orCreateValue.CooldownEndTime - time);
if (flag && !orCreateValue.CooldownNotified)
{
AmLog.Msg($"[Sprint] On cooldown remain={num4:0.0}s meter={orCreateValue.Meter:0.00}/{SprintDuration:0.00}");
orCreateValue.CooldownNotified = true;
}
}
else if (orCreateValue.Meter < SprintDuration)
{
float meter2 = orCreateValue.Meter;
orCreateValue.Meter = Mathf.Min(SprintDuration, orCreateValue.Meter + SprintRechargePerSecond * num);
if (!orCreateValue.RechargeBeganLogged)
{
AmLog.Msg($"[Sprint] Recharge start meter={meter2:0.00}->{orCreateValue.Meter:0.00}/{SprintDuration:0.00}");
orCreateValue.RechargeBeganLogged = true;
}
}
else
{
orCreateValue.RechargeBeganLogged = false;
}
}
if (!DashEnabled)
{
return;
}
int num5 = DashMaxCharges + (flag3 ? 1 : 0);
float num6 = DashRechargeSeconds * (flag3 ? 0.8f : 1f);
if (orCreateValue.DashCharges < 0)
{
orCreateValue.DashCharges = num5;
if (orCreateValue.DashCharges < num5)
{
orCreateValue.NextDashRechargeAt = time + num6;
}
else
{
orCreateValue.NextDashRechargeAt = -1f;
}
}
if (orCreateValue.DashCharges >= 0)
{
if (orCreateValue.DashCharges < num5 && orCreateValue.NextDashRechargeAt <= 0f)
{
orCreateValue.NextDashRechargeAt = time + num6;
}
else if (orCreateValue.DashCharges >= num5)
{
orCreateValue.NextDashRechargeAt = -1f;
}
}
if (orCreateValue.DashCharges < num5 && orCreateValue.NextDashRechargeAt > 0f)
{
while (orCreateValue.DashCharges < num5 && time >= orCreateValue.NextDashRechargeAt)
{
orCreateValue.DashCharges++;
orCreateValue.NextDashRechargeAt += num6;
AmLog.Msg($"[Dash] Recharged -> {orCreateValue.DashCharges}/{num5}");
}
if (orCreateValue.DashCharges >= num5)
{
orCreateValue.NextDashRechargeAt = -1f;
}
}
if (orCreateValue.IsDashing)
{
if (!(time >= orCreateValue.DashEndTime))
{
return;
}
orCreateValue.IsDashing = false;
try
{
GameHandler iNSTANCE = GameHandler.INSTANCE;
if (iNSTANCE != null)
{
iNSTANCE.ChangePlayerMoveSpeed(__instance.MoveSpeed.GetValueFloat());
}
}
catch
{
}
AmLog.Msg("[Dash] End");
}
else
{
if (!(_dashRequestAt > 0f))
{
return;
}
_ = _dashRequestAt;
_dashRequestAt = -1f;
if (orCreateValue.DashCharges <= 0)
{
AmLog.Msg("[Dash] No charges");
return;
}
if (IsWalking(__instance) && !((LivingBase)__instance).isDead)
{
PlayerController playerController = __instance.playerController;
_ = Vector2.zero;
try
{
if (string.Equals(GetMovementControllerSettingText(), "left", StringComparison.OrdinalIgnoreCase))
{
playerController.GetLeftJoystickValue();
}
else
{
playerController.GetRightJoystickValue();
}
}
catch
{
}
float num7 = 0f;
try
{
num7 = __instance.MoveSpeed.GetValueFloat();
}
catch
{
}
float num8 = Math.Max(num7, num7 * DashSpeedMultiplier);
try
{
GameHandler iNSTANCE2 = GameHandler.INSTANCE;
if (iNSTANCE2 != null)
{
PlayerController playerController2 = iNSTANCE2.playerController;
if (playerController2 != null)
{
playerController2.SetSlidingMovementSpeed(num8);
}
}
}
catch
{
}
orCreateValue.IsDashing = true;
orCreateValue.DashEndTime = time + DashDurationSeconds;
orCreateValue.DashCharges--;
if (orCreateValue.DashCharges < num5 && orCreateValue.NextDashRechargeAt <= 0f)
{
orCreateValue.NextDashRechargeAt = time + num6;
}
AmLog.Msg($"[Dash] START speed={num8:0.00} charges={orCreateValue.DashCharges}/{num5}");
try
{
GameHandler.INSTANCE.playerController.RpcMpQuickAction((byte)240, (NetworkObject)null, GameHandler.INSTANCE.networkHandler.GetNetworkRunner().LocalPlayer);
return;
}
catch
{
return;
}
}
AmLog.Msg($"[Dash] Blocked (walking={IsWalking(__instance)} dead={((LivingBase)__instance).isDead})");
}
}
catch (Exception arg)
{
AmLog.Error($"Sprint Update error: {arg}");
}
}
private static void EnsureSprintCleared(PlayerLiving playerLiving)
{
if (_states.TryGetValue(playerLiving, out SprintState value) && value.IsSprinting)
{
value.IsSprinting = false;
ClearMoveSpeedMultiplier(playerLiving);
AmLog.Msg("[Sprint] Cleared sprint for player '" + GetPlayerObjectName(playerLiving) + "'");
}
}
private static void ClearForCurrentPlayer()
{
try
{
if ((Object)(object)GameHandler.INSTANCE?.playerLiving != (Object)null)
{
EnsureSprintCleared(GameHandler.INSTANCE.playerLiving);
}
}
catch
{
}
}
private static bool IsWalking(PlayerLiving playerLiving)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Invalid comparison between Unknown and I4
PlayerController playerController = playerLiving.playerController;
if ((Object)(object)playerController == (Object)null)
{
return false;
}
return (int)playerController.CurrentMovementType == 0;
}
private static string GetControllerMovementTypeText(PlayerLiving playerLiving)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
try
{
PlayerController playerController = playerLiving.playerController;
if ((Object)(object)playerController == (Object)null)
{
return "?";
}
MovementType currentMovementType = playerController.CurrentMovementType;
return ((object)(MovementType)(ref currentMovementType)).ToString();
}
catch
{
return "?";
}
}
private static bool IsInitialized()
{
if ((Object)(object)GameHandler.INSTANCE != (Object)null)
{
return GameHandler.INSTANCE.initialized;
}
return false;
}
private static void ApplyMoveSpeedMultiplier(PlayerLiving playerLiving, float multiplier)
{
try
{
PlayerStat moveSpeed = playerLiving.MoveSpeed;
if (moveSpeed == null)
{
return;
}
float num = 0f;
try
{
num = moveSpeed.GetValueFloat();
}
catch
{
}
float num2 = 0f;
try
{
GameHandler iNSTANCE = GameHandler.INSTANCE;
float? obj2;
if (iNSTANCE == null)
{
obj2 = null;
}
else
{
PlayerController playerController = iNSTANCE.playerController;
obj2 = ((playerController != null) ? new float?(playerController.GetWalkingMovementSpeed()) : null);
}
float? num3 = obj2;
num2 = num3.GetValueOrDefault();
}
catch
{
}
moveSpeed.ChangeMultiplier("arcade_movement_sprint", multiplier);
float num4 = num;
try
{
num4 = moveSpeed.GetValueFloat();
}
catch
{
}
try
{
GameHandler iNSTANCE2 = GameHandler.INSTANCE;
if (iNSTANCE2 != null)
{
iNSTANCE2.ChangePlayerMoveSpeed(num4);
}
}
catch
{
}
float num5 = 0f;
try
{
GameHandler iNSTANCE3 = GameHandler.INSTANCE;
float? obj6;
if (iNSTANCE3 == null)
{
obj6 = null;
}
else
{
PlayerController playerController2 = iNSTANCE3.playerController;
obj6 = ((playerController2 != null) ? new float?(playerController2.GetWalkingMovementSpeed()) : null);
}
float? num3 = obj6;
num5 = num3.GetValueOrDefault();
}
catch
{
}
AmLog.Msg(string.Format("[Sprint] Applied speed mult key='{0}' x{1:0.00} stat {2:0.00}->{3:0.00} pc {4:0.00}->{5:0.00}", "arcade_movement_sprint", multiplier, num, num4, num2, num5));
}
catch (Exception arg)
{
AmLog.Error($"Failed to apply sprint multiplier: {arg}");
}
}
private static void ClearMoveSpeedMultiplier(PlayerLiving playerLiving)
{
try
{
PlayerStat moveSpeed = playerLiving.MoveSpeed;
if (moveSpeed == null)
{
return;
}
float num = 0f;
try
{
num = moveSpeed.GetValueFloat();
}
catch
{
}
float num2 = 0f;
try
{
GameHandler iNSTANCE = GameHandler.INSTANCE;
float? obj2;
if (iNSTANCE == null)
{
obj2 = null;
}
else
{
PlayerController playerController = iNSTANCE.playerController;
obj2 = ((playerController != null) ? new float?(playerController.GetWalkingMovementSpeed()) : null);
}
float? num3 = obj2;
num2 = num3.GetValueOrDefault();
}
catch
{
}
moveSpeed.ClearMultiplier("arcade_movement_sprint");
float num4 = num;
try
{
num4 = moveSpeed.GetValueFloat();
}
catch
{
}
try
{
GameHandler iNSTANCE2 = GameHandler.INSTANCE;
if (iNSTANCE2 != null)
{
iNSTANCE2.ChangePlayerMoveSpeed(num4);
}
}
catch
{
}
float num5 = 0f;
try
{
GameHandler iNSTANCE3 = GameHandler.INSTANCE;
float? obj6;
if (iNSTANCE3 == null)
{
obj6 = null;
}
else
{
PlayerController playerController2 = iNSTANCE3.playerController;
obj6 = ((playerController2 != null) ? new float?(playerController2.GetWalkingMovementSpeed()) : null);
}
float? num3 = obj6;
num5 = num3.GetValueOrDefault();
}
catch
{
}
AmLog.Msg(string.Format("[Sprint] Cleared speed mult key='{0}' stat {1:0.00}->{2:0.00} pc {3:0.00}->{4:0.00}", "arcade_movement_sprint", num, num4, num2, num5));
}
catch (Exception arg)
{
AmLog.Error($"Failed to clear sprint multiplier: {arg}");
}
}
private static void TryHapticPulse(float amplitude, float duration)
{
}
private static bool IsSmoothMovementSelected()
{
try
{
float unscaledTime = Time.unscaledTime;
if (_lastSmoothCheckAt >= 0f && unscaledTime < _lastSmoothCheckAt + SmoothCheckInterval)
{
return _lastSmoothSelected;
}
GameHandler iNSTANCE = GameHandler.INSTANCE;
if ((Object)(object)iNSTANCE == (Object)null || (Object)(object)iNSTANCE.mainMenu == (Object)null || (Object)(object)iNSTANCE.mainMenu.settingsObject == (Object)null)
{
_lastSmoothSelected = false;
_lastSmoothCheckAt = unscaledTime;
return _lastSmoothSelected;
}
Settings settingsObject = iNSTANCE.mainMenu.settingsObject;
if (settingsObject.IsUsingTeleportMovement() || settingsObject.IsUsingMonkeMovement())
{
_lastSmoothSelected = false;
_lastSmoothCheckAt = unscaledTime;
return _lastSmoothSelected;
}
Dictionary<string, string> settings = settingsObject.settings;
if (settings != null && settings.ContainsKey("movement_type"))
{
_lastSmoothSelected = string.Equals(settings["movement_type"], "smooth", StringComparison.OrdinalIgnoreCase);
}
else
{
_lastSmoothSelected = true;
}
_lastSmoothCheckAt = unscaledTime;
return _lastSmoothSelected;
}
catch
{
return _lastSmoothSelected;
}
}
private static void LogMovementModeIfChanged(PlayerLiving playerLiving)
{
if (!DebugLogs)
{
return;
}
float unscaledTime = Time.unscaledTime;
if (!(_lastStatusLogAt >= 0f) || !(unscaledTime < _lastStatusLogAt + _statusLogMinInterval))
{
string settingsMovementTypeText = GetSettingsMovementTypeText();
string controllerMovementTypeText = GetControllerMovementTypeText(playerLiving);
if (!string.Equals(_lastMovementTypeText, settingsMovementTypeText, StringComparison.Ordinal))
{
_lastMovementTypeText = settingsMovementTypeText;
AmLog.Msg("[Sprint] Detected movement setting: " + settingsMovementTypeText);
}
if (!string.Equals(_lastControllerMoveTypeText, controllerMovementTypeText, StringComparison.Ordinal))
{
_lastControllerMoveTypeText = controllerMovementTypeText;
AmLog.Msg("[Sprint] PlayerController movement: " + controllerMovementTypeText);
}
_lastStatusLogAt = unscaledTime;
}
}
private static string GetSettingsMovementTypeText()
{
try
{
GameHandler iNSTANCE = GameHandler.INSTANCE;
if ((Object)(object)iNSTANCE == (Object)null || (Object)(object)iNSTANCE.mainMenu == (Object)null || (Object)(object)iNSTANCE.mainMenu.settingsObject == (Object)null)
{
return "?";
}
Dictionary<string, string> settings = iNSTANCE.mainMenu.settingsObject.settings;
if (settings != null && settings.ContainsKey("movement_type"))
{
return settings["movement_type"] ?? "?";
}
}
catch
{
}
return "?";
}
private static string GetPlayerObjectName(PlayerLiving playerLiving)
{
if (!((Object)(object)playerLiving != (Object)null) || !((Object)(object)((Component)playerLiving).gameObject != (Object)null))
{
return "PlayerLiving";
}
return ((Object)((Component)playerLiving).gameObject).name;
}
private static string GetMovementControllerSettingText()
{
try
{
Dictionary<string, string> dictionary = (GameHandler.INSTANCE?.mainMenu?.settingsObject)?.settings;
if (dictionary != null && dictionary.ContainsKey("movement_controller"))
{
string text = dictionary["movement_controller"];
if (!string.IsNullOrEmpty(text))
{
return text;
}
}
}
catch
{
}
return "right";
}
private static bool HasUnlimitedSprintLocal()
{
try
{
GameHandler iNSTANCE = GameHandler.INSTANCE;
if ((Object)(object)iNSTANCE == (Object)null || (Object)(object)iNSTANCE.itemInterpreter == (Object)null)
{
return false;
}
return iNSTANCE.itemInterpreter.AmountPickupFoundByLocalPlayer("am_unlimited_sprint") > 0;
}
catch
{
return false;
}
}
private static bool HasUpgradedDashLocal()
{
try
{
GameHandler iNSTANCE = GameHandler.INSTANCE;
if ((Object)(object)iNSTANCE == (Object)null || (Object)(object)iNSTANCE.itemInterpreter == (Object)null)
{
return false;
}
return iNSTANCE.itemInterpreter.AmountPickupFoundByLocalPlayer("am_upgraded_dash") > 0;
}
catch
{
return false;
}
}
private static void ApplyDominantHandSelection(string controllerText)
{
_lastMovementControllerText = controllerText ?? "?";
bool sprintOnLeft = string.Equals(_lastMovementControllerText, "left", StringComparison.OrdinalIgnoreCase);
bool dashOnLeft = string.Equals(_lastMovementControllerText, "right", StringComparison.OrdinalIgnoreCase);
_sprintOnLeft = sprintOnLeft;
_dashOnLeft = dashOnLeft;
try
{
_clickHeldCount = 0;
AmLog.Msg("[Sprint] Mapping: sprint=" + (_sprintOnLeft ? "LEFT" : "RIGHT") + ", dash=" + (_dashOnLeft ? "LEFT" : "RIGHT"));
}
catch (Exception ex)
{
AmLog.Warn("[Sprint] Failed to apply dominant hand selection: " + ex.Message);
}
}
private static bool IsSprintAction(InputAction? action)
{
if (action == null)
{
return false;
}
bool flag = action == _leftClick;
bool flag2 = action == _rightClick;
if (!(_sprintOnLeft && flag))
{
return !_sprintOnLeft && flag2;
}
return true;
}
private static bool IsDashAction(InputAction? action)
{
if (action == null)
{
return false;
}
bool flag = action == _leftClick;
bool flag2 = action == _rightClick;
if (!(_dashOnLeft && flag))
{
return !_dashOnLeft && flag2;
}
return true;
}
private static void GameHandler_ChangePlayerMoveSpeed_Postfix_Impl(float val)
{
try
{
float num = 0f;
try
{
GameHandler iNSTANCE = GameHandler.INSTANCE;
float? obj;
if (iNSTANCE == null)
{
obj = null;
}
else
{
PlayerController playerController = iNSTANCE.playerController;
obj = ((playerController != null) ? new float?(playerController.GetWalkingMovementSpeed()) : null);
}
float? num2 = obj;
num = num2.GetValueOrDefault();
}
catch
{
}
GameHandler iNSTANCE2 = GameHandler.INSTANCE;
string arg = ((iNSTANCE2?.mainMenu?.settingsObject?.settings != null && iNSTANCE2.mainMenu.settingsObject.settings.ContainsKey("movement_type")) ? (iNSTANCE2.mainMenu.settingsObject.settings["movement_type"] ?? "?") : "?");
AmLog.Msg($"[Sprint] GH.ChangePlayerMoveSpeed(val={val:0.00}) -> pc={num:0.00} settings='{arg}'");
}
catch
{
}
}
private static void PlayerLiving_MoveSpeed_ValueChanged_Postfix_Impl(PlayerLiving __instance)
{
try
{
float num = 0f;
try
{
num = __instance.MoveSpeed.GetValueFloat();
}
catch
{
}
float num2 = 0f;
try
{
GameHandler iNSTANCE = GameHandler.INSTANCE;
float? obj2;
if (iNSTANCE == null)
{
obj2 = null;
}
else
{
PlayerController playerController = iNSTANCE.playerController;
obj2 = ((playerController != null) ? new float?(playerController.GetWalkingMovementSpeed()) : null);
}
float? num3 = obj2;
num2 = num3.GetValueOrDefault();
}
catch
{
}
AmLog.Msg($"[Sprint] MoveSpeed_ValueChanged -> stat {num:0.00} pc {num2:0.00}");
}
catch
{
}
}
}
internal static class TrackpadClickLogger
{
[HarmonyPatch(typeof(PlayerInputAction))]
private static class PlayerInputAction__ctor_Patch
{
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
[HarmonyPostfix]
private static void Postfix(PlayerInputAction __instance)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: 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)
try
{
AmLog.Msg("[TrackpadClickLogger] PlayerInputAction constructed; wiring maps...");
RightHandActions rightHand = __instance.RightHand;
InputActionMap val = ((RightHandActions)(ref rightHand)).Get();
if (val != null)
{
AmLog.Msg("[TrackpadClickLogger] Found RightHand map");
EnsureClickLogger(val, "{RightHand}", "Right");
EnsurePrimary2DAxisBinding(val, "{RightHand}");
}
else
{
AmLog.Warn("[TrackpadClickLogger] RightHand map not found");
}
LeftHandActions leftHand = __instance.LeftHand;
InputActionMap val2 = ((LeftHandActions)(ref leftHand)).Get();
if (val2 != null)
{
AmLog.Msg("[TrackpadClickLogger] Found LeftHand map");
EnsureClickLogger(val2, "{LeftHand}", "Left");
EnsurePrimary2DAxisBinding(val2, "{LeftHand}");
}
else
{
AmLog.Warn("[TrackpadClickLogger] LeftHand map not found");
}
}
catch (Exception arg)
{
AmLog.Error($"TrackpadClickLogger Postfix error: {arg}");
}
AmInputLog.DumpDevicesOnce();
}
private static void EnsureClickLogger(InputActionMap map, string handTag, string label)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
bool enabled = map.enabled;
if (enabled)
{
map.Disable();
}
try
{
InputAction val = ((IEnumerable<InputAction>)(object)map.actions).FirstOrDefault((Func<InputAction, bool>)((InputAction a) => a.name == "Primary2DAxisClickLogger")) ?? InputActionSetupExtensions.AddAction(map, "Primary2DAxisClickLogger", (InputActionType)1, (string)null, (string)null, (string)null, (string)null, (string)null);
val.expectedControlType = "Button";
AddIfMissing(val, "*/" + handTag + "/Primary2DAxisClick");
AddIfMissing(val, "<XRController>" + handTag + "/Primary2DAxisClick");
AddIfMissing(val, "*/" + handTag + "/thumbstickClicked");
AddIfMissing(val, "<XRController>" + handTag + "/thumbstickClicked");
AddIfMissing(val, "<ValveIndexController>" + handTag + "/thumbstickClicked");
AddIfMissing(val, "*/" + handTag + "/joystickClicked");
AddIfMissing(val, "<XRController>" + handTag + "/joystickClicked");
AddIfMissing(val, "*/" + handTag + "/trackpadClicked");
AddIfMissing(val, "<XRController>" + handTag + "/trackpadClicked");
AddIfMissing(val, "<ValveIndexController>" + handTag + "/trackpadClicked");
AddIfMissing(val, "*/" + handTag + "/touchpadClicked");
AddIfMissing(val, "<XRController>" + handTag + "/touchpadClicked");
AmLog.Msg("[TrackpadClickLogger] Wired click logger for " + label + " hand");
if (_wiredClickActions.Add(val))
{
_actionLabels[val] = label;
val.started += OnPrimary2DAxisClickStarted;
}
}
finally
{
if (enabled)
{
map.Enable();
}
}
static void AddIfMissing(InputAction a, string path)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
string path2 = path;
if (!((IEnumerable<InputBinding>)(object)a.bindings).Any((InputBinding b) => string.Equals(((InputBinding)(ref b)).path, path2, StringComparison.OrdinalIgnoreCase)))
{
InputActionSetupExtensions.AddBinding(a, path2, (string)null, (string)null, (string)null);
AmLog.Msg("[TrackpadClickLogger] Added binding: " + path2);
}
}
}
private static void EnsurePrimary2DAxisBinding(InputActionMap map, string handTag)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
bool enabled = map.enabled;
if (enabled)
{
map.Disable();
}
try
{
InputAction val = ((IEnumerable<InputAction>)(object)map.actions).FirstOrDefault((Func<InputAction, bool>)((InputAction a) => a.name == "JoystickAxis"));
if (val != null)
{
AddIfMissing(val, "*/" + handTag + "/Primary2DAxis");
AddIfMissing(val, "<XRController>" + handTag + "/Primary2DAxis");
AddIfMissing(val, "*/" + handTag + "/thumbstick");
AddIfMissing(val, "<XRController>" + handTag + "/thumbstick");
AddIfMissing(val, "<ValveIndexController>" + handTag + "/thumbstick");
AddIfMissing(val, "*/" + handTag + "/joystick");
AddIfMissing(val, "<XRController>" + handTag + "/joystick");
AddIfMissing(val, "*/" + handTag + "/trackpad");
AddIfMissing(val, "<XRController>" + handTag + "/trackpad");
AddIfMissing(val, "<ValveIndexController>" + handTag + "/trackpad");
AddIfMissing(val, "*/" + handTag + "/touchpad");
AddIfMissing(val, "<XRController>" + handTag + "/touchpad");
}
}
finally
{
if (enabled)
{
map.Enable();
}
}
static void AddIfMissing(InputAction a, string path)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
string path2 = path;
if (!((IEnumerable<InputBinding>)(object)a.bindings).Any((InputBinding b) => string.Equals(((InputBinding)(ref b)).path, path2, StringComparison.OrdinalIgnoreCase)))
{
InputActionSetupExtensions.AddBinding(a, path2, (string)null, (string)null, (string)null);
AmLog.Msg("[TrackpadClickLogger] Added vector2 binding: " + path2);
}
}
}
private static void OnPrimary2DAxisClickStarted(CallbackContext ctx)
{
try
{
if (((CallbackContext)(ref ctx)).action == null)
{
AmInputLog.Primary2DAxisClick("?");
}
else
{
AmInputLog.Primary2DAxisClick(_actionLabels.TryGetValue(((CallbackContext)(ref ctx)).action, out string value) ? value : "?");
}
}
catch (Exception arg)
{
AmLog.Error($"Primary2DAxis click logger error: {arg}");
}
}
}
private static Harmony? _harmony;
private static readonly HashSet<InputAction> _wiredClickActions = new HashSet<InputAction>();
private static readonly Dictionary<InputAction, string> _actionLabels = new Dictionary<InputAction, string>();
public static bool IsApplied { get; private set; }
public static void Apply()
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Expected O, but got Unknown
try
{
if (!IsApplied)
{
_harmony = new Harmony("ArcadeMovement.TrackpadClickLogger");
_harmony.CreateClassProcessor(typeof(TrackpadClickLogger)).Patch();
IsApplied = true;
AmLog.Msg("[TrackpadClickLogger] Applied (gated by mod enable)");
}
}
catch (Exception arg)
{
AmLog.Error($"Failed to apply TrackpadClickLogger: {arg}");
}
}
public static void Remove()
{
try
{
if (!IsApplied)
{
return;
}
try
{
Harmony? harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchAll((string)null);
}
}
catch
{
}
finally
{
_harmony = null;
IsApplied = false;
}
AmLog.Msg("[TrackpadClickLogger] Removed");
}
catch (Exception ex)
{
AmLog.Warn("[TrackpadClickLogger] Remove failed: " + ex.Message);
}
}
}
}
namespace ArcadeMovement.Logging
{
internal static class AmInputLog
{
private static bool _dumpedDevices;
public static void DumpDevicesOnce()
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
if (!AmLog.Enabled || _dumpedDevices)
{
return;
}
_dumpedDevices = true;
try
{
AmLog.Msg("[TrackpadClickLogger] Listing XR input devices and key controls...");
foreach (InputDevice item in ((IEnumerable<InputDevice>)(object)InputSystem.devices).ToList())
{
if ((((InputControl)item).layout ?? string.Empty).IndexOf("XR", StringComparison.OrdinalIgnoreCase) < 0 && !((IEnumerable<InternedString>)(object)((InputControl)item).usages).Any((InternedString u) => string.Equals(((object)(InternedString)(ref u)).ToString(), "LeftHand", StringComparison.OrdinalIgnoreCase) || string.Equals(((object)(InternedString)(ref u)).ToString(), "RightHand", StringComparison.OrdinalIgnoreCase)))
{
continue;
}
AmLog.Msg("- Device: '" + ((InputControl)item).displayName + "' layout='" + ((InputControl)item).layout + "' usages=[" + string.Join(", ", ((IEnumerable<InternedString>)(object)((InputControl)item).usages).Select((InternedString u) => ((object)(InternedString)(ref u)).ToString())) + "]");
string[] array = new string[12]
{
"primary2DAxis", "primary2DAxisClick", "thumbstick", "thumbstickClicked", "joystick", "joystickClicked", "touchpad", "touchpadClicked", "trackpad", "trackpadClicked",
"secondary2DAxis", "secondary2DAxisClick"
};
foreach (string text in array)
{
InputControl val = ((InputControl)item).TryGetChildControl(text);
if (val != null)
{
AmLog.Msg(" control: " + text + " type=" + val.valueType.Name);
}
}
}
}
catch (Exception arg)
{
AmLog.Error($"[TrackpadClickLogger] DumpDevices error: {arg}");
}
}
public static void Primary2DAxisClick(string label)
{
AmLog.Msg("[" + label + "] Primary2DAxis pressed down");
}
}
internal static class AmLog
{
public static bool Enabled { get; private set; }
public static void SetEnabled(bool enabled)
{
Enabled = enabled;
}
public static void Msg(string message)
{
if (Enabled)
{
MelonLogger.Msg("ArcadeMovement: " + message);
}
}
public static void Warn(string message)
{
if (Enabled)
{
MelonLogger.Warning("ArcadeMovement: " + message);
}
}
public static void Error(string message)
{
MelonLogger.Error("ArcadeMovement: " + message);
}
}
}
namespace ArcadeMovement.Integration
{
internal static class ADVRIntegration
{
internal static class IntegrationPatches
{
[HarmonyPatch(typeof(ModLoader), "Initialize")]
internal static class ModLoader_Initialize_PostfixPatch
{
[HarmonyPostfix]
private static void Postfix(ModLoader __instance)
{
AppendPseudoMod(__instance);
}
}
[HarmonyPatch(typeof(SettingsMod), "OnApplyClick")]
internal static class SettingsMod_OnApplyClick_PostfixPatch
{
[HarmonyPostfix]
private static void Postfix()
{
EvaluateAndApply();
}
}
[HarmonyPatch(typeof(GameHandler), "Awake")]
internal static class GameHandler_Awake_PostfixPatch
{
[HarmonyPostfix]
private static void Postfix()
{
RelicInjector.EnsureRelicRepresentations();
EvaluateAndApply();
}
}
}
private const string OurModId = "ArcadeMovement";
public static void EvaluateAndApply()
{
try
{
if (GetManagerEnabledFlag("ArcadeMovement"))
{
if (!SprintPatch.IsApplied)
{
SprintPatch.Apply();
}
if (!TrackpadClickLogger.IsApplied)
{
TrackpadClickLogger.Apply();
}
}
else
{
if (SprintPatch.IsApplied)
{
SprintPatch.Remove();
}
if (TrackpadClickLogger.IsApplied)
{
TrackpadClickLogger.Remove();
}
}
}
catch (Exception ex)
{
AmLog.Warn("[ADVRIntegration] Enablement evaluation failed: " + ex.Message);
}
}
public static void HookIntoModLoader()
{
//IL_0005: 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_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
try
{
Harmony val = new Harmony("ArcadeMovement.ADVRIntegration");
val.CreateClassProcessor(typeof(IntegrationPatches.ModLoader_Initialize_PostfixPatch)).Patch();
val.CreateClassProcessor(typeof(IntegrationPatches.SettingsMod_OnApplyClick_PostfixPatch)).Patch();
val.CreateClassProcessor(typeof(IntegrationPatches.GameHandler_Awake_PostfixPatch)).Patch();
val.CreateClassProcessor(typeof(RelicInjector.HarmonyHooks.PlayerController_OnGameHandlerInitialized_PostfixPatch)).Patch();
}
catch (Exception ex)
{
AmLog.Warn("[ADVRIntegration] Failed to hook mod loader: " + ex.Message);
}
}
internal static bool GetManagerEnabledFlag(string modId)
{
try
{
if ((Object)(object)GameHandler.INSTANCE == (Object)null)
{
return false;
}
return ES3.Load<bool>("mod_enabled_" + modId, false, GameHandler.INSTANCE.e3Settings);
}
catch
{
return false;
}
}
private static string GetGameVersionOrFallback()
{
try
{
return GameHandler.GetGameVersionString();
}
catch
{
return "unknown";
}
}
private static void AppendPseudoMod(ModLoader __instance)
{
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Expected O, but got Unknown
try
{
if (!((Object)(object)__instance == (Object)null))
{
Mod[] array = __instance.loadedMods ?? Array.Empty<Mod>();
if (!array.Any((Mod m) => string.Equals(m.modId, "ArcadeMovement", StringComparison.OrdinalIgnoreCase)))
{
Mod val = new Mod
{
modId = "ArcadeMovement",
modName = "Arcade Movement",
modDesc = "Sprint + input helpers (MelonLoader)",
modVersion = GetGameVersionOrFallback()
};
Mod[] array2 = (Mod[])(object)new Mod[array.Length + 1];
Array.Copy(array, array2, array.Length);
array2[array.Length] = val;
__instance.loadedMods = array2;
}
}
}
catch (Exception ex)
{
AmLog.Warn("[ADVRIntegration] Failed to append mod to list: " + ex.Message);
}
}
}
internal static class AssetBundleLoader
{
private static AssetBundle? _bundle;
private static Sprite? _unlimitedSprintSprite;
private static Sprite? _upgradedDashSprite;
private const string BundleFileName = "am_assets.bundle";
private const string UnlimitedSprintSpritePath = "Assets/Images/Unlimited_Sprint.png";
private const string UpgradedDashSpritePath = "Assets/Images/Upgraded_Dash.png";
private static string GetModDirectory()
{
try
{
string location = typeof(ModMain).Assembly.Location;
if (!string.IsNullOrEmpty(location))
{
string text = Path.GetDirectoryName(location) ?? Directory.GetCurrentDirectory();
AmLog.Msg("[Assets] Mod directory: " + text);
return text;
}
}
catch
{
}
return Directory.GetCurrentDirectory();
}
private static string? FindBundlePath()
{
try
{
string text = Path.Combine(GetModDirectory(), "Assets");
if (!Directory.Exists(text))
{
AmLog.Warn("[Assets] Assets folder not found: " + text);
return null;
}
string text2 = Path.Combine(text, "am_assets.bundle");
if (File.Exists(text2))
{
AmLog.Msg("[Assets] Found bundle on disk: " + text2);
return text2;
}
AmLog.Warn("[Assets] Bundle not found on disk: " + text2);
return null;
}
catch
{
return null;
}
}
private static bool TryExtractEmbeddedBundle(out string? writtenPath)
{
writtenPath = null;
try
{
Assembly executingAssembly = Assembly.GetExecutingAssembly();
string text = executingAssembly.GetManifestResourceNames().FirstOrDefault((string n) => n.EndsWith("am_assets.bundle", StringComparison.OrdinalIgnoreCase));
if (string.IsNullOrEmpty(text))
{
AmLog.Warn("[Assets] Embedded bundle not found in resources.");
return false;
}
string text2 = Path.Combine(GetModDirectory(), "Assets");
Directory.CreateDirectory(text2);
string text3 = Path.Combine(text2, "am_assets.bundle");
using (Stream stream = executingAssembly.GetManifestResourceStream(text))
{
if (stream == null)
{
AmLog.Warn("[Assets] Resource stream null.");
return false;
}
using FileStream destination = File.Create(text3);
stream.CopyTo(destination);
}
AmLog.Msg("[Assets] Extracted embedded bundle to: " + text3);
writtenPath = text3;
return true;
}
catch (Exception ex)
{
AmLog.Warn("[Assets] Failed to extract embedded bundle: " + ex.Message);
return false;
}
}
private static bool EnsureBundleLoaded()
{
if ((Object)(object)_bundle != (Object)null)
{
return true;
}
string writtenPath = FindBundlePath();
if (string.IsNullOrEmpty(writtenPath) && !TryExtractEmbeddedBundle(out writtenPath))
{
return false;
}
try
{
_bundle = AssetBundle.LoadFromFile(writtenPath);
AmLog.Msg(((Object)(object)_bundle != (Object)null) ? "[Assets] AssetBundle loaded." : "[Assets] AssetBundle load failed.");
}
catch
{
_bundle = null;
}
return (Object)(object)_bundle != (Object)null;
}
public static Sprite? GetUnlimitedSprintSprite()
{
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_unlimitedSprintSprite != (Object)null)
{
return _unlimitedSprintSprite;
}
if (!EnsureBundleLoaded())
{
return null;
}
try
{
Texture2D val = _bundle.LoadAsset<Texture2D>("Assets/Images/Unlimited_Sprint.png");
if ((Object)(object)val == (Object)null)
{
AmLog.Warn("[Assets] Unlimited_Sprint texture missing in bundle.");
return null;
}
((Texture)val).filterMode = (FilterMode)0;
_unlimitedSprintSprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0);
AmLog.Msg($"[Assets] Created Unlimited_Sprint sprite from texture ({((Texture)val).width}x{((Texture)val).height}).");
return _unlimitedSprintSprite;
}
catch
{
return null;
}
}
public static Sprite? GetUpgradedDashSprite()
{
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_upgradedDashSprite != (Object)null)
{
return _upgradedDashSprite;
}
if (!EnsureBundleLoaded())
{
return null;
}
try
{
Texture2D val = _bundle.LoadAsset<Texture2D>("Assets/Images/Upgraded_Dash.png");
if ((Object)(object)val == (Object)null)
{
AmLog.Warn("[Assets] Upgraded_Dash texture missing in bundle.");
return null;
}
((Texture)val).filterMode = (FilterMode)0;
_upgradedDashSprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0);
AmLog.Msg($"[Assets] Created Upgraded_Dash sprite from texture ({((Texture)val).width}x{((Texture)val).height}).");
return _upgradedDashSprite;
}
catch
{
return null;
}
}
public static AudioClip? GetWooshClip()
{
if (!EnsureBundleLoaded())
{
return null;
}
try
{
AudioClip obj = _bundle.LoadAsset<AudioClip>("Assets/Audio/woosh.wav");
AmLog.Msg(((Object)(object)obj != (Object)null) ? "[Assets] Loaded woosh.wav." : "[Assets] woosh.wav missing.");
return obj;
}
catch
{
return null;
}
}
}
internal static class RelicInjector
{
internal static class HarmonyHooks
{
[HarmonyPatch(typeof(PlayerController), "OnGameHandlerInitialized")]
internal static class PlayerController_OnGameHandlerInitialized_PostfixPatch
{
[HarmonyPostfix]
private static void Postfix(PlayerController __instance)
{
try
{
if ((Object)(object)__instance != (Object)null && ((NetworkBehaviour)__instance).HasStateAuthority)
{
EnsureRelicRepresentations();
if (ADVRIntegration.GetManagerEnabledFlag("ArcadeMovement"))
{
EnsureUnlimitedSprintRelicForLocal();
EnsureUpgradedDashRelicForLocal();
}
else
{
RemoveUnlimitedSprintRelicForLocal();
RemoveUpgradedDashRelicForLocal();
}
}
}
catch
{
}
}
}
[HarmonyPatch(typeof(PlayerController), "RpcMpQuickAction")]
internal static class PlayerController_RpcMpQuickAction_PostfixPatch
{
[HarmonyPostfix]
private static void Postfix(PlayerController __instance, byte pAction, NetworkObject pNetObj, PlayerRef pSource)
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
try
{
if (pAction == 240)
{
AudioClip wooshClip = AssetBundleLoader.GetWooshClip();
if ((Object)(object)wooshClip != (Object)null)
{
AudioSource.PlayClipAtPoint(wooshClip, ((Component)__instance).transform.position, 1f);
}
}
}
catch
{
}
}
}
private const byte QuickActionDashWoosh = 240;
}
private const string RelicId = "am_unlimited_sprint";
private const string RelicName = "Unlimited Sprint";
private const string RelicDesc = "Hold stick/trackpad click to sprint indefinitely.";
private const string RelicLuaPath = "gamedata/items/am_unlimited_sprint/am_unlimited_sprint.lua";
private const string RelicPngPath = "gamedata/items/am_unlimited_sprint/am_unlimited_sprint.png";
public static void EnsureUnlimitedSprintRelicForLocal()
{
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Expected O, but got Unknown
try
{
if (!ADVRIntegration.GetManagerEnabledFlag("ArcadeMovement"))
{
return;
}
GameHandler iNSTANCE = GameHandler.INSTANCE;
if ((Object)(object)iNSTANCE == (Object)null || (Object)(object)iNSTANCE.itemInterpreter == (Object)null || iNSTANCE.itemInterpreter.AmountPickupFoundByLocalPlayer("am_unlimited_sprint") > 0 || iNSTANCE.itemInterpreter.GetPickupById("am_unlimited_sprint") != null)
{
return;
}
PickupDiskRepresentation val = new PickupDiskRepresentation("function ADVR.onLoad()\n pickup.name = \"Unlimited Sprint\"\n pickup.desc = \"Hold stick/trackpad click to sprint indefinitely.\"\n pickup.maxAmount = 1\n pickup.amountUses = -1\n pickup.price = 0\n pickup.tier = 3\n pickup.supportedInMultiplayer = true\n pickup.probability = 0\n pickup.spawnsIn = {}\nend\n", "gamedata/items/am_unlimited_sprint/am_unlimited_sprint.lua", "am_unlimited_sprint", (Mod)null);
try
{
val.spawnsIn = Array.Empty<string>();
}
catch
{
}
try
{
val.probability = 0f;
}
catch
{
}
try
{
val.sprite = AssetBundleLoader.GetUnlimitedSprintSprite();
}
catch
{
}
try
{
List<PickupDiskRepresentation> list = (iNSTANCE.itemInterpreter.pickupsOnDisk ?? Array.Empty<PickupDiskRepresentation>()).ToList();
list.Add(val);
iNSTANCE.itemInterpreter.pickupsOnDisk = list.ToArray();
}
catch
{
}
}
catch
{
}
}
public static void EnsureUpgradedDashRelicForLocal()
{
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Expected O, but got Unknown
try
{
if (!ADVRIntegration.GetManagerEnabledFlag("ArcadeMovement"))
{
return;
}
GameHandler iNSTANCE = GameHandler.INSTANCE;
if ((Object)(object)iNSTANCE == (Object)null || (Object)(object)iNSTANCE.itemInterpreter == (Object)null || iNSTANCE.itemInterpreter.GetPickupById("am_upgraded_dash") != null)
{
return;
}
PickupDiskRepresentation val = new PickupDiskRepresentation("function ADVR.onLoad()\n pickup.name = \"Upgraded Dash\"\n pickup.desc = \"+1 dash charge and faster recharge.\"\n pickup.maxAmount = 1\n pickup.amountUses = -1\n pickup.price = 0\n pickup.tier = 3\n pickup.supportedInMultiplayer = true\n pickup.probability = 0\n pickup.spawnsIn = {}\nend\n", "gamedata/items/am_upgraded_dash/am_upgraded_dash.lua", "am_upgraded_dash", (Mod)null);
try
{
val.spawnsIn = Array.Empty<string>();
}
catch
{
}
try
{
val.probability = 0f;
}
catch
{
}
try
{
val.sprite = AssetBundleLoader.GetUpgradedDashSprite();
}
catch
{
}
try
{
List<PickupDiskRepresentation> list = (iNSTANCE.itemInterpreter.pickupsOnDisk ?? Array.Empty<PickupDiskRepresentation>()).ToList();
list.Add(val);
iNSTANCE.itemInterpreter.pickupsOnDisk = list.ToArray();
}
catch
{
}
}
catch
{
}
}
public static void RemoveUpgradedDashRelicForLocal()
{
try
{
GameHandler iNSTANCE = GameHandler.INSTANCE;
if ((Object)(object)iNSTANCE == (Object)null || (Object)(object)iNSTANCE.itemInterpreter == (Object)null)
{
return;
}
PickupDiskRepresentation pickupById = iNSTANCE.itemInterpreter.GetPickupById("am_upgraded_dash");
if (pickupById == null || iNSTANCE.itemInterpreter.AmountPickupFoundByLocalPlayer("am_upgraded_dash") <= 0)
{
return;
}
try
{
pickupById.UnregisterItem();
}
catch
{
}
}
catch
{
}
}
public static void EnsureRelicRepresentations()
{
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_00f9: Expected O, but got Unknown
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Expected O, but got Unknown
try
{
GameHandler iNSTANCE = GameHandler.INSTANCE;
if ((Object)(object)iNSTANCE == (Object)null || (Object)(object)iNSTANCE.itemInterpreter == (Object)null)
{
return;
}
if (iNSTANCE.itemInterpreter.GetPickupById("am_unlimited_sprint") == null)
{
PickupDiskRepresentation val = new PickupDiskRepresentation("function ADVR.onLoad()\n pickup.name = \"Unlimited Sprint\"\n pickup.desc = \"Hold stick/trackpad click to sprint indefinitely.\"\n pickup.maxAmount = 1\n pickup.amountUses = -1\n pickup.price = 0\n pickup.tier = 3\n pickup.supportedInMultiplayer = true\n pickup.probability = 0\n pickup.spawnsIn = {}\nend\n", "gamedata/items/am_unlimited_sprint/am_unlimited_sprint.lua", "am_unlimited_sprint", (Mod)null);
try
{
val.spawnsIn = Array.Empty<string>();
}
catch
{
}
try
{
val.probability = 0f;
}
catch
{
}
try
{
val.sprite = AssetBundleLoader.GetUnlimitedSprintSprite();
}
catch
{
}
try
{
List<PickupDiskRepresentation> list = (iNSTANCE.itemInterpreter.pickupsOnDisk ?? Array.Empty<PickupDiskRepresentation>()).ToList();
list.Add(val);
iNSTANCE.itemInterpreter.pickupsOnDisk = list.ToArray();
}
catch
{
}
}
try
{
ES3.Save<bool>("found_am_unlimited_sprint", true, iNSTANCE.e3Settings);
}
catch
{
}
if (iNSTANCE.itemInterpreter.GetPickupById("am_upgraded_dash") == null)
{
PickupDiskRepresentation val2 = new PickupDiskRepresentation("function ADVR.onLoad()\n pickup.name = \"Upgraded Dash\"\n pickup.desc = \"+1 dash charge and faster recharge.\"\n pickup.maxAmount = 1\n pickup.amountUses = -1\n pickup.price = 0\n pickup.tier = 3\n pickup.supportedInMultiplayer = true\n pickup.probability = 0\n pickup.spawnsIn = {}\nend\n", "gamedata/items/am_upgraded_dash/am_upgraded_dash.lua", "am_upgraded_dash", (Mod)null);
try
{
val2.spawnsIn = Array.Empty<string>();
}
catch
{
}
try
{
val2.probability = 0f;
}
catch
{
}
try
{
val2.sprite = AssetBundleLoader.GetUpgradedDashSprite();
}
catch
{
}
try
{
List<PickupDiskRepresentation> list2 = (iNSTANCE.itemInterpreter.pickupsOnDisk ?? Array.Empty<PickupDiskRepresentation>()).ToList();
list2.Add(val2);
iNSTANCE.itemInterpreter.pickupsOnDisk = list2.ToArray();
}
catch
{
}
}
try
{
ES3.Save<bool>("found_am_upgraded_dash", true, iNSTANCE.e3Settings);
}
catch
{
}
}
catch
{
}
}
public static void RemoveUnlimitedSprintRelicForLocal()
{
try
{
GameHandler iNSTANCE = GameHandler.INSTANCE;
if ((Object)(object)iNSTANCE == (Object)null || (Object)(object)iNSTANCE.itemInterpreter == (Object)null)
{
return;
}
PickupDiskRepresentation pickupById = iNSTANCE.itemInterpreter.GetPickupById("am_unlimited_sprint");
if (pickupById == null || iNSTANCE.itemInterpreter.AmountPickupFoundByLocalPlayer("am_unlimited_sprint") <= 0)
{
return;
}
try
{
pickupById.UnregisterItem();
}
catch
{
}
}
catch
{
}
}
}
}
namespace NoisyItems.Audio
{
internal struct WavData
{
public int Channels;
public int SampleRate;
public int Frames;
public float[] Samples;
}
internal static class WavLoader
{
public static bool TryParse(byte[] data, out WavData wav)
{
wav = default(WavData);
try
{
using MemoryStream memoryStream = new MemoryStream(data, writable: false);
using BinaryReader binaryReader = new BinaryReader(memoryStream);
if (ReadFourCC(binaryReader) != "RIFF")
{
return false;
}
binaryReader.ReadInt32();
if (ReadFourCC(binaryReader) != "WAVE")
{
return false;
}
int num = 0;
int num2 = 0;
int num3 = 0;
ushort num4 = 0;
byte[] array = null;
while (memoryStream.Position + 8 <= memoryStream.Length)
{
string text = ReadFourCC(binaryReader);
int num5 = binaryReader.ReadInt32();
long position = memoryStream.Position + num5;
if (text == "fmt ")
{
num4 = binaryReader.ReadUInt16();
num = binaryReader.ReadInt16();
num2 = binaryReader.ReadInt32();
binaryReader.ReadInt32();
binaryReader.ReadInt16();
num3 = binaryReader.ReadInt16();
if (num5 > 16)
{
int num6 = num5 - 16;
if (num6 >= 2)
{
ushort num7 = binaryReader.ReadUInt16();
num6 -= 2;
if (num4 == 65534 && num7 >= 22 && num6 >= 22)
{
binaryReader.ReadUInt16();
binaryReader.ReadUInt32();
byte[] b = binaryReader.ReadBytes(16);
num6 -= 22;
Guid guid = new Guid(b);
Guid guid2 = new Guid("00000001-0000-0010-8000-00AA00389B71");
Guid guid3 = new Guid("00000003-0000-0010-8000-00AA00389B71");
if (guid == guid2)
{
num4 = 1;
}
else if (guid == guid3)
{
num4 = 3;
}
}
if (num6 > 0)
{
memoryStream.Position += num6;
}
}
else
{
memoryStream.Position = position;
}
}
}
else if (text == "data")
{
array = binaryReader.ReadBytes(num5);
}
else
{
memoryStream.Position = position;
}
if ((memoryStream.Position & 1) == 1)
{
memoryStream.Position++;
}
}
if (array == null || num <= 0 || num2 <= 0)
{
return false;
}
int num9;
float[] array2;
switch (num4)
{
case 1:
switch (num3)
{
case 8:
{
num9 = array.Length / num;
if (num9 <= 0)
{
return false;
}
array2 = new float[num9 * num];
for (int k = 0; k < array2.Length; k++)
{
array2[k] = (float)(array[k] - 128) / 128f;
}
break;
}
case 16:
{
num9 = array.Length / 2 / num;
if (num9 <= 0)
{
return false;
}
array2 = new float[num9 * num];
int num15 = 0;
for (int l = 0; l < array2.Length; l++)
{
float num16 = (float)(short)(array[num15] | (array[num15 + 1] << 8)) / 32768f;
if (num16 < -1f)
{
num16 = -1f;
}
else if (num16 > 1f)
{
num16 = 1f;
}
array2[l] = num16;
num15 += 2;
}
break;
}
case 24:
{
int num11 = 3;
num9 = array.Length / num11 / num;
if (num9 <= 0)
{
return false;
}
array2 = new float[num9 * num];
int num12 = 0;
for (int j = 0; j < array2.Length; j++)
{
int num13 = array[num12] | (array[num12 + 1] << 8) | (array[num12 + 2] << 16);
if (((uint)num13 & 0x800000u) != 0)
{
num13 |= -16777216;
}
float num14 = (float)num13 / 8388608f;
if (num14 < -1f)
{
num14 = -1f;
}
else if (num14 > 1f)
{
num14 = 1f;
}
array2[j] = num14;
num12 += 3;
}
break;
}
default:
return false;
}
break;
case 3:
{
if (num3 != 32)
{
return false;
}
int num8 = array.Length / 4;
num9 = num8 / Math.Max(1, num);
if (num9 <= 0)
{
return false;
}
array2 = new float[num8];
Buffer.BlockCopy(array, 0, array2, 0, array.Length);
for (int i = 0; i < array2.Length; i++)
{
float num10 = array2[i];
if (num10 < -1f)
{
num10 = -1f;
}
else if (num10 > 1f)
{
num10 = 1f;
}
array2[i] = num10;
}
break;
}
default:
return false;
}
wav = new WavData
{
Channels = num,
SampleRate = num2,
Frames = num9,
Samples = array2
};
return true;
}
catch
{
return false;
}
}
private static string ReadFourCC(BinaryReader br)
{
byte[] bytes = br.ReadBytes(4);
return Encoding.ASCII.GetString(bytes);
}
}
}