using System;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.NET.Common;
using Candide;
using Candide.Entities.PlayerState;
using Candide.PlayerMode.Recording;
using Candide.Terminal;
using CandideCreator.Shared.Collision;
using HarmonyLib;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Shared.Entity;
using Shared.Entity.Base;
using Shared.Models.Stats;
using SmoothDash.Patches;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(/*Could not decode attribute arguments.*/)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace SmoothDash
{
[BepInPlugin("com.atomiz.romestead.smoothdash", "Smooth Dash", "1.1.1")]
public class SmoothDashPlugin : BasePlugin
{
public const string PluginGuid = "com.atomiz.romestead.smoothdash";
public const string PluginName = "Smooth Dash";
public const string PluginVersion = "1.1.1";
public static ConfigEntry<bool> ModEnabled;
public static ConfigEntry<string> ToggleKeyConfig;
public static ConfigEntry<float> TargetSpeedOverride;
public static ConfigEntry<float> DecelerationMultiplier;
private static KeyboardState _previousKeyboardState;
private static bool _terminalCommandRegistered;
[field: CompilerGenerated]
public static SmoothDashPlugin Instance
{
[CompilerGenerated]
get;
[CompilerGenerated]
private set;
}
public override void Load()
{
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Expected O, but got Unknown
Instance = this;
ModEnabled = ((BasePlugin)this).Config.Bind<bool>("General", "Enabled", true, "Whether the smooth dash momentum modification is enabled.");
ToggleKeyConfig = ((BasePlugin)this).Config.Bind<string>("General", "ToggleKey", "F6", "Keyboard key to toggle Smooth Dash on/off in-game (e.g. F6, F7, G).");
TargetSpeedOverride = ((BasePlugin)this).Config.Bind<float>("General", "TargetSpeedOverride", 0f, "Custom exit speed at the end of dash. If 0.0, dynamically calculates player normal walk/run speed.");
DecelerationMultiplier = ((BasePlugin)this).Config.Bind<float>("General", "DecelerationDurationMultiplier", 1f, "Multiplier for dash wind-down duration (e.g. 1.0 = vanilla duration, 1.2 = slightly longer glide).");
Harmony val = new Harmony("com.atomiz.romestead.smoothdash");
val.PatchAll(typeof(DashPatches));
val.PatchAll(typeof(SmoothDashPlugin));
ManualLogSource log = ((BasePlugin)this).Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(33, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("Smooth Dash");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("] loaded successfully! Version: ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("1.1.1");
}
log.LogInfo(val2);
}
public static float CalculateTargetSpeed(EntityWrapper entity)
{
if (TargetSpeedOverride.Value > 0f)
{
return TargetSpeedOverride.Value;
}
float num = 1f;
try
{
if (entity != null)
{
num = ((EntityStats)(ref entity.Stats)).Get("MovementSpeed");
}
}
catch
{
num = 1f;
}
if (num <= 0.01f)
{
num = 1f;
}
float num2 = 2560f;
double num3 = 1E-14;
try
{
if (entity != null)
{
if (entity.AccelerationScale > 0f)
{
num2 = entity.AccelerationScale;
}
if (entity.Friction > 0.0 && entity.Friction < 1.0)
{
num3 = entity.Friction;
}
}
}
catch
{
}
double num4 = 0.0 - Math.Log(num3);
if (num4 <= 0.001)
{
num4 = 32.236;
}
float num5 = (float)((double)(num2 * num) / num4);
AbstractController obj3 = ((entity != null) ? entity.Controller : null);
PlayerController val = (PlayerController)(object)((obj3 is PlayerController) ? obj3 : null);
if (val != null && val.IsWalking)
{
num5 *= 0.5f;
}
return num5;
}
public static void ToggleMod()
{
ModEnabled.Value = !ModEnabled.Value;
string text = "[SmoothDash] Dash modification is now " + (ModEnabled.Value ? "ENABLED" : "DISABLED") + ".";
SmoothDashPlugin instance = Instance;
if (instance != null)
{
ManualLogSource log = ((BasePlugin)instance).Log;
if (log != null)
{
log.LogInfo((object)text);
}
}
try
{
CandideEngine game = Globals.Game;
if (game != null)
{
GameTerminal terminal = game.Terminal;
if (terminal != null)
{
terminal.AddLine(text);
}
}
}
catch
{
}
}
[HarmonyPatch(typeof(CandideEngine), "Update")]
[HarmonyPostfix]
public static void CandideEngine_Update_Postfix()
{
//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_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: 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)
try
{
KeyboardState state = Keyboard.GetState();
Keys val = default(Keys);
if (global::System.Enum.TryParse<Keys>(ToggleKeyConfig.Value, true, ref val) && ((KeyboardState)(ref state)).IsKeyDown(val) && !((KeyboardState)(ref _previousKeyboardState)).IsKeyDown(val))
{
ToggleMod();
}
_previousKeyboardState = state;
}
catch
{
}
}
[HarmonyPatch(typeof(CandideEngine), "AddTerminalCommands")]
[HarmonyPostfix]
public static void CandideEngine_AddTerminalCommands_Postfix(CandideEngine __instance)
{
RegisterTerminalCommands(__instance?.Terminal);
}
public static void RegisterTerminalCommands(GameTerminal terminal)
{
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Expected O, but got Unknown
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected O, but got Unknown
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Expected O, but got Unknown
if (terminal == null || _terminalCommandRegistered)
{
return;
}
try
{
terminal.AddCommand("smoothdash", new TerminalCommandAction(HandleDashCommand));
terminal.AddCommand("dashsmooth", new TerminalCommandAction(HandleDashCommand));
_terminalCommandRegistered = true;
SmoothDashPlugin instance = Instance;
if (instance != null)
{
ManualLogSource log = ((BasePlugin)instance).Log;
if (log != null)
{
log.LogInfo((object)"[SmoothDash] In-game terminal commands registered.");
}
}
}
catch (global::System.Exception ex)
{
SmoothDashPlugin instance2 = Instance;
if (instance2 == null)
{
return;
}
ManualLogSource log2 = ((BasePlugin)instance2).Log;
if (log2 != null)
{
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(50, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SmoothDash] Failed to register terminal command: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
log2.LogWarning(val);
}
}
}
public static object HandleDashCommand(string[] parameters)
{
if (parameters == null || parameters.Length <= 1)
{
ToggleMod();
return "[SmoothDash] Toggled. Mod is now: " + (ModEnabled.Value ? "ENABLED" : "DISABLED");
}
string text = parameters[1].ToLowerInvariant();
if (text == "on" || text == "enable" || text == "1" || text == "true")
{
ModEnabled.Value = true;
return "[SmoothDash] Mod ENABLED.";
}
if (text == "off" || text == "disable" || text == "0" || text == "false")
{
ModEnabled.Value = false;
return "[SmoothDash] Mod DISABLED.";
}
if (text == "status")
{
return $"[SmoothDash] Status: {(ModEnabled.Value ? "ENABLED" : "DISABLED")} | SpeedOverride: {TargetSpeedOverride.Value} | DurationMult: {DecelerationMultiplier.Value}";
}
if ((text == "speed" || text == "targetspeed") && parameters.Length > 2)
{
float num = default(float);
if (float.TryParse(parameters[2], (NumberStyles)167, (IFormatProvider)(object)CultureInfo.InvariantCulture, ref num))
{
TargetSpeedOverride.Value = num;
if (!(num <= 0f))
{
return $"[SmoothDash] Target speed override set to {num}.";
}
return "[SmoothDash] Target speed set to dynamic (automatic player walk/run speed).";
}
return "[SmoothDash] Invalid speed value. Usage: smoothdash speed <number> (0 for auto)";
}
if ((text == "duration" || text == "mult") && parameters.Length > 2)
{
float num2 = default(float);
if (float.TryParse(parameters[2], (NumberStyles)167, (IFormatProvider)(object)CultureInfo.InvariantCulture, ref num2))
{
DecelerationMultiplier.Value = Math.Clamp(num2, 0.1f, 5f);
return $"[SmoothDash] Deceleration duration multiplier set to {DecelerationMultiplier.Value}.";
}
return "[SmoothDash] Invalid duration multiplier. Usage: smoothdash duration <number>";
}
return "[SmoothDash] Commands: smoothdash [on | off | status | speed <val> | duration <val>]";
}
}
}
namespace SmoothDash.Patches
{
public static class DashPatches
{
private static readonly FieldInfo DashSpeedField = AccessTools.Field(typeof(PlayerDashHandler), "_dashSpeed");
private static readonly FieldInfo WindingDownField = AccessTools.Field(typeof(PlayerDashHandler), "_windingDown");
private static readonly FieldInfo OldAccelerationField = AccessTools.Field(typeof(PlayerDashHandler), "_oldAcceleration");
private static float GetDashSpeed()
{
FieldInfo dashSpeedField = DashSpeedField;
return (float)(((dashSpeedField != null) ? dashSpeedField.GetValue((object)null) : null) ?? ((object)400f));
}
private static void SetDashSpeed(float val)
{
FieldInfo dashSpeedField = DashSpeedField;
if (dashSpeedField != null)
{
dashSpeedField.SetValue((object)null, (object)val);
}
}
private static bool GetWindingDown()
{
FieldInfo windingDownField = WindingDownField;
return (bool)(((windingDownField != null) ? windingDownField.GetValue((object)null) : null) ?? ((object)false));
}
private static void SetWindingDown(bool val)
{
FieldInfo windingDownField = WindingDownField;
if (windingDownField != null)
{
windingDownField.SetValue((object)null, (object)val);
}
}
private static Vector3 GetOldAcceleration()
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
FieldInfo oldAccelerationField = OldAccelerationField;
return (Vector3)(((oldAccelerationField != null) ? oldAccelerationField.GetValue((object)null) : null) ?? ((object)Vector3.Zero));
}
private static void SetOldAcceleration(Vector3 val)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
FieldInfo oldAccelerationField = OldAccelerationField;
if (oldAccelerationField != null)
{
oldAccelerationField.SetValue((object)null, (object)val);
}
}
[HarmonyPatch(typeof(PlayerDashHandler), "UpdateAndCheckIfShouldTransition")]
[HarmonyPrefix]
public static bool UpdateAndCheckIfShouldTransition_Prefix(EntityWrapper entity, ref bool __result)
{
//IL_0185: Unknown result type (might be due to invalid IL or missing references)
//IL_018c: Expected O, but got Unknown
//IL_014d: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
//IL_0134: Unknown result type (might be due to invalid IL or missing references)
//IL_013a: Unknown result type (might be due to invalid IL or missing references)
if (!SmoothDashPlugin.ModEnabled.Value)
{
return true;
}
try
{
PlayerDashHandler.Timer += entity.Fdt;
bool windingDown = GetWindingDown();
float dashSpeed = GetDashSpeed();
float num = SmoothDashPlugin.CalculateTargetSpeed(entity);
float value = SmoothDashPlugin.DecelerationMultiplier.Value;
float num2 = PlayerDashHandler.WindDownTime * value;
if (num2 <= 0.001f)
{
num2 = 0.001f;
}
float num3;
if (!windingDown)
{
num3 = dashSpeed;
SetWindingDown(val: true);
PlayerDashHandler.Timer = 0f;
}
else
{
float num4 = MathHelper.Clamp(PlayerDashHandler.Timer / num2, 0f, 1f);
num3 = MathHelper.SmoothStep(dashSpeed, num, num4);
if ((object)Globals.Game.ModeManager != CinematicCameraModeManager.Instance)
{
Globals.Game.Camera.FollowTarget(entity);
Globals.Game.Camera.SetSpeed(0.8f);
}
if (PlayerDashHandler.Timer > 0.05f)
{
Globals.Game.Camera.SetSpeed(0.5f);
}
if (num4 >= 1f || num3 <= num)
{
SetWindingDown(val: false);
PlayerDashHandler.Timer = 0f;
entity.Acceleration = GetOldAcceleration();
if ((object)Globals.Game.ModeManager != CinematicCameraModeManager.Instance)
{
Globals.Game.Camera.SetSpeed(1f);
}
entity.Velocity = PlayerDashHandler.DashDirection * num;
__result = true;
return false;
}
}
entity.Velocity = PlayerDashHandler.DashDirection * num3;
__result = false;
return false;
}
catch (global::System.Exception ex)
{
SmoothDashPlugin instance = SmoothDashPlugin.Instance;
if (instance != null)
{
ManualLogSource log = ((BasePlugin)instance).Log;
if (log != null)
{
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(63, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SmoothDash] Error in UpdateAndCheckIfShouldTransition prefix: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<global::System.Exception>(ex);
}
log.LogError(val);
}
}
return true;
}
}
[HarmonyPatch(typeof(PlayerDashHandler), "OnLeave")]
[HarmonyPrefix]
public static bool OnLeave_Prefix(EntityWrapper entity, PlayerController controller)
{
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Expected O, but got Unknown
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
if (!SmoothDashPlugin.ModEnabled.Value)
{
return true;
}
try
{
if (controller != null)
{
controller.LockDirection = false;
}
float num = SmoothDashPlugin.CalculateTargetSpeed(entity);
Vector3 velocity = entity.Velocity;
if (((Vector3)(ref velocity)).LengthSquared() < num * num * 0.25f)
{
entity.Velocity = PlayerDashHandler.DashDirection * num;
}
CollisionMasksExtension.RemoveFlag(ref entity.System.CollisionComponent[entity.Eid].NoCollisionGroupMask, (CollisionMasks)128);
CollisionMasksExtension.RemoveFlag(ref entity.System.CollisionComponent[entity.Eid].NoCollisionGroupMask, (CollisionMasks)64);
if ((object)Globals.Game.ModeManager != CinematicCameraModeManager.Instance && (!object.Equals((object)Globals.Game.Camera.Target, (object)Globals.Game.Player) || Globals.Game.Player.Removed))
{
Globals.Game.Camera.FollowTarget(entity);
Globals.Game.Camera.SetSpeed(1f);
}
return false;
}
catch (global::System.Exception ex)
{
SmoothDashPlugin instance = SmoothDashPlugin.Instance;
if (instance != null)
{
ManualLogSource log = ((BasePlugin)instance).Log;
if (log != null)
{
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(38, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SmoothDash] Error in OnLeave prefix: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<global::System.Exception>(ex);
}
log.LogError(val);
}
}
return true;
}
}
}
}