Decompiled source of SprintSpeedCap v1.0.2

SprintSpeedCap.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("Igor_Does_Nothing")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SprintSpeedCap")]
[assembly: AssemblyTitle("SprintSpeedCap")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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;
		}
	}
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace Repo.SprintCap
{
	[BepInPlugin("com.yourname.repo.sprintcap", "R.E.P.O Sprint Cap", "1.6.1")]
	public class SprintCapPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.yourname.repo.sprintcap";

		public const string PluginName = "R.E.P.O Sprint Cap";

		public const string PluginVersion = "1.6.1";

		internal static volatile bool Enabled = true;

		internal static volatile float MaxUpgradeAdd = 2f;

		internal static volatile float AbsMaxSprint = 0f;

		private ConfigEntry<bool> _enabledCfg;

		private ConfigEntry<float> _maxUpgradeAddCfg;

		private ConfigEntry<float> _absMaxSprintCfg;

		private ConfigEntry<bool> _attachToGameDirector;

		private ManualLogSource _log;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			_log = ((BaseUnityPlugin)this).Logger;
			_enabledCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Turn the cap on/off.");
			_maxUpgradeAddCfg = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MaxSprintUpgradeAdditive", 2f, "Maximum additive sprint-speed upgrade allowed.");
			_absMaxSprintCfg = ((BaseUnityPlugin)this).Config.Bind<float>("General", "AbsoluteMaxSprintSpeed", 0f, "Optional absolute cap for SprintSpeed (0 disables).");
			_attachToGameDirector = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "AttachToGameDirector", false, "If true, parent the host under GameDirector when present.");
			ApplyConfigToStatics();
			_enabledCfg.SettingChanged += delegate
			{
				ApplyConfigToStatics();
			};
			_maxUpgradeAddCfg.SettingChanged += delegate
			{
				ApplyConfigToStatics();
			};
			_absMaxSprintCfg.SettingChanged += delegate
			{
				ApplyConfigToStatics();
			};
			BuildOrAttachHost();
			_harmony = new Harmony("com.yourname.repo.sprintcap");
			_harmony.PatchAll();
			_log.LogInfo((object)string.Format("{0} {1} loaded. Enabled={2}, MaxUpAdd={3}, AbsMax={4}", "R.E.P.O Sprint Cap", "1.6.1", Enabled, MaxUpgradeAdd, AbsMaxSprint));
			SceneManager.activeSceneChanged += OnActiveSceneChanged;
		}

		private void OnDestroy()
		{
			SceneManager.activeSceneChanged -= OnActiveSceneChanged;
			_log.LogWarning((object)"R.E.P.O Sprint Cap OnDestroy() — patches left active, host persists.");
		}

		private void ApplyConfigToStatics()
		{
			Enabled = _enabledCfg.Value;
			MaxUpgradeAdd = Mathf.Max(0f, _maxUpgradeAddCfg.Value);
			AbsMaxSprint = _absMaxSprintCfg.Value;
		}

		private void OnActiveSceneChanged(Scene from, Scene to)
		{
			BuildOrAttachHost();
		}

		private void BuildOrAttachHost()
		{
			//IL_0049: 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_0057: Expected O, but got Unknown
			GameObject val = null;
			if (_attachToGameDirector.Value && (Object)(object)GameDirector.instance != (Object)null)
			{
				val = ((Component)GameDirector.instance).gameObject;
			}
			if ((Object)(object)val == (Object)null)
			{
				val = GameObject.Find("SprintCapHost (BepInEx)");
				if ((Object)(object)val == (Object)null)
				{
					val = new GameObject("SprintCapHost (BepInEx)")
					{
						hideFlags = (HideFlags)61
					};
					Object.DontDestroyOnLoad((Object)(object)val);
				}
			}
			if ((Object)(object)val.GetComponent<SprintCapHost>() == (Object)null)
			{
				val.AddComponent<SprintCapHost>();
			}
		}
	}
	public sealed class SprintCapHost : MonoBehaviour
	{
	}
	internal static class SprintCapState
	{
		internal sealed class Data
		{
			public bool Initialized;

			public float BaseNoUpgrade;
		}

		internal static readonly Dictionary<PlayerController, Data> Cache = new Dictionary<PlayerController, Data>(16);

		internal static readonly FieldInfo FiOriginalSprint = AccessTools.Field(typeof(PlayerController), "playerOriginalSprintSpeed");

		internal static Data Get(PlayerController pc)
		{
			if (!Cache.TryGetValue(pc, out Data value))
			{
				value = new Data();
				Cache[pc] = value;
			}
			return value;
		}
	}
	[HarmonyPatch(typeof(PlayerController), "FixedUpdate")]
	internal static class PlayerController_FixedUpdate_Prefix
	{
		private static void Prefix(PlayerController __instance)
		{
			if (!SprintCapPlugin.Enabled || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			SprintCapState.Data data = SprintCapState.Get(__instance);
			if (!data.Initialized)
			{
				try
				{
					float num = (float)SprintCapState.FiOriginalSprint.GetValue(__instance);
					float sprintSpeedUpgrades = __instance.SprintSpeedUpgrades;
					data.BaseNoUpgrade = num - sprintSpeedUpgrades;
				}
				catch
				{
					data.BaseNoUpgrade = __instance.SprintSpeed - __instance.SprintSpeedUpgrades;
				}
				data.Initialized = true;
			}
			float num2 = (__instance.SprintSpeedUpgrades = Mathf.Min(__instance.SprintSpeedUpgrades, SprintCapPlugin.MaxUpgradeAdd));
			float num3 = data.BaseNoUpgrade + num2;
			if (SprintCapPlugin.AbsMaxSprint > 0f)
			{
				num3 = Mathf.Min(num3, SprintCapPlugin.AbsMaxSprint);
			}
			if (__instance.SprintSpeed > num3)
			{
				__instance.SprintSpeed = num3;
			}
		}
	}
	internal static class LocalPlayerKey
	{
		private static readonly FieldInfo FiPlayerSteamID = AccessTools.Field(typeof(PlayerController), "playerSteamID");

		private static readonly MethodInfo MiPlayerGetSteamID = AccessTools.Method(typeof(SemiFunc), "PlayerGetSteamID", new Type[1] { typeof(PlayerAvatar) }, (Type[])null);

		internal static bool TryGet(out string steamID)
		{
			steamID = null;
			PlayerController instance = PlayerController.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			try
			{
				if (MiPlayerGetSteamID != null && (Object)(object)instance.playerAvatarScript != (Object)null)
				{
					object obj = MiPlayerGetSteamID.Invoke(null, new object[1] { instance.playerAvatarScript });
					if (obj is string text && !string.IsNullOrEmpty(text))
					{
						steamID = text;
						return true;
					}
				}
			}
			catch
			{
			}
			try
			{
				if (FiPlayerSteamID != null)
				{
					string text2 = FiPlayerSteamID.GetValue(instance) as string;
					if (!string.IsNullOrEmpty(text2))
					{
						steamID = text2;
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		internal static int ClampIntUpgrade(int original)
		{
			int num = Mathf.FloorToInt(SprintCapPlugin.MaxUpgradeAdd);
			if (original <= num)
			{
				return original;
			}
			return num;
		}
	}
	internal static class UpgradeClampHelper
	{
		internal struct State
		{
			public string key;

			public int previous;

			public bool changed;
		}

		internal static State ClampForLocalIfNeeded()
		{
			State state = default(State);
			state.key = null;
			state.previous = 0;
			state.changed = false;
			State result = state;
			if (!LocalPlayerKey.TryGet(out string steamID))
			{
				return result;
			}
			StatsManager instance = StatsManager.instance;
			if ((Object)(object)instance == (Object)null || instance.playerUpgradeSpeed == null)
			{
				return result;
			}
			if (instance.playerUpgradeSpeed.TryGetValue(steamID, out var value))
			{
				int num = value;
				int num2 = num;
				int num3 = LocalPlayerKey.ClampIntUpgrade(num2);
				if (num3 != num2)
				{
					result.key = steamID;
					result.previous = num2;
					result.changed = true;
					instance.playerUpgradeSpeed[steamID] = num3;
				}
			}
			return result;
		}

		internal static void Restore(in State st)
		{
			if (st.changed && !string.IsNullOrEmpty(st.key))
			{
				StatsManager instance = StatsManager.instance;
				if (!((Object)(object)instance == (Object)null) && instance.playerUpgradeSpeed != null)
				{
					instance.playerUpgradeSpeed[st.key] = st.previous;
				}
			}
		}
	}
	[HarmonyPatch(typeof(CameraBob), "Update")]
	internal static class CameraBob_Update_PrefixPostfix
	{
		private static void Prefix(out UpgradeClampHelper.State __state)
		{
			__state = UpgradeClampHelper.ClampForLocalIfNeeded();
		}

		private static void Postfix(in UpgradeClampHelper.State __state)
		{
			UpgradeClampHelper.Restore(in __state);
		}
	}
	[HarmonyPatch(typeof(CameraZoom), "Update")]
	internal static class CameraZoom_Update_PrefixPostfix
	{
		private static void Prefix(out UpgradeClampHelper.State __state)
		{
			__state = UpgradeClampHelper.ClampForLocalIfNeeded();
		}

		private static void Postfix(in UpgradeClampHelper.State __state)
		{
			UpgradeClampHelper.Restore(in __state);
		}
	}
	[HarmonyPatch(typeof(PlayerAvatarVisuals), "Update")]
	internal static class PlayerAvatarVisuals_Update_PrefixPostfix
	{
		private static void Prefix(out UpgradeClampHelper.State __state)
		{
			__state = UpgradeClampHelper.ClampForLocalIfNeeded();
		}

		private static void Postfix(in UpgradeClampHelper.State __state)
		{
			UpgradeClampHelper.Restore(in __state);
		}
	}
}