Decompiled source of SmoothDash v1.1.1

SmoothDash.dll

Decompiled a week ago
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;
			}
		}
	}
}