Decompiled source of StaminaCostTweaks v1.0.11

plugins\youxia173.StaminaCostTweaks.dll

Decompiled a day ago
using System;
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;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("youxia173")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.11.0")]
[assembly: AssemblyInformationalVersion("1.0.11")]
[assembly: AssemblyProduct("StaminaCostTweaks")]
[assembly: AssemblyTitle("youxia173.StaminaCostTweaks")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.11.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace StaminaCostTweaks
{
	[HarmonyPatch(typeof(Character), "UseStamina")]
	internal static class Character_UseStamina_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(Character __instance, ref float usage, ref bool __result)
		{
			if (usage == 0f || (Object)(object)__instance == (Object)null)
			{
				return true;
			}
			if (Plugin.FreeStaminaEnabled && __instance.IsLocal)
			{
				__result = true;
				return false;
			}
			if (IsExtremeClimbActive(__instance) && IsClimbRelatedSpend(__instance))
			{
				float num = Plugin.PercentToMultiplier(Plugin.ExtremeClimbCostPercent.Value);
				if (!Mathf.Approximately(num, 1f))
				{
					usage *= num;
				}
				return true;
			}
			if (!TryGetManagedMultiplier(__instance, out var mult))
			{
				return true;
			}
			if (Mathf.Approximately(mult, 1f))
			{
				return true;
			}
			usage *= mult;
			return true;
		}

		private static bool IsExtremeClimbActive(Character character)
		{
			if (!Plugin.ExtremeClimbEnabled.Value || (Object)(object)character == (Object)null || !character.IsLocal)
			{
				return false;
			}
			CharacterData data = character.data;
			if ((Object)(object)data == (Object)null)
			{
				return false;
			}
			float num = Mathf.Clamp(Plugin.ExtremeClimbBelowPercent.Value, 1f, 100f) / 100f;
			bool num2 = data.extraStamina <= 0.001f && data.currentStamina < num;
			bool flag = data.currentStamina <= 0.001f && data.extraStamina < num;
			return num2 || flag;
		}

		private static bool IsClimbRelatedSpend(Character character)
		{
			if (StaminaCostContext.Kind == StaminaCostKind.ClimbJump || StaminaCostContext.Kind == StaminaCostKind.VineIdle || StaminaCostContext.Kind == StaminaCostKind.Glider)
			{
				return true;
			}
			CharacterData data = character.data;
			if ((Object)(object)data == (Object)null)
			{
				return false;
			}
			if (!data.isClimbing && !data.isVineClimbing)
			{
				return data.isRopeClimbing;
			}
			return true;
		}

		private static bool TryGetManagedMultiplier(Character character, out float mult)
		{
			mult = 1f;
			if (StaminaCostContext.Kind == StaminaCostKind.ClimbJump)
			{
				mult = Plugin.PercentToMultiplier(Plugin.ClimbJumpCostPercent.Value);
				return true;
			}
			if (StaminaCostContext.Kind == StaminaCostKind.VineIdle)
			{
				mult = Plugin.PercentToMultiplier(Plugin.VineIdleCostPercent.Value);
				return true;
			}
			if (StaminaCostContext.Kind == StaminaCostKind.Glider)
			{
				mult = Plugin.PercentToMultiplier(Plugin.GliderCostPercent.Value);
				return true;
			}
			CharacterData data = character.data;
			if ((Object)(object)data == (Object)null)
			{
				return false;
			}
			if (data.isVineClimbing)
			{
				if (Mathf.Abs(character.input.movementInput.y) < 0.01f)
				{
					mult = Plugin.PercentToMultiplier(Plugin.VineIdleCostPercent.Value);
					return true;
				}
				return false;
			}
			if (data.isClimbing)
			{
				mult = Plugin.PercentToMultiplier(Plugin.ClimbCostPercent.Value);
				return true;
			}
			if (data.isSprinting)
			{
				mult = Plugin.PercentToMultiplier(Plugin.SprintCostPercent.Value);
				return true;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(CharacterClimbing), "RPCA_ClimbJump")]
	internal static class CharacterClimbing_ClimbJump_Patch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			StaminaCostContext.Kind = StaminaCostKind.ClimbJump;
		}

		[HarmonyFinalizer]
		private static void Finalizer()
		{
			StaminaCostContext.Kind = StaminaCostKind.None;
		}
	}
	[HarmonyPatch(typeof(CharacterVineClimbing), "Update")]
	internal static class CharacterVineClimbing_Update_Patch
	{
		[HarmonyPrefix]
		private static void Prefix(CharacterVineClimbing __instance)
		{
			object? obj = AccessTools.Field(typeof(CharacterVineClimbing), "character")?.GetValue(__instance);
			Character val = (Character)((obj is Character) ? obj : null);
			if (!((Object)(object)val == (Object)null) && val.IsLocal && val.data.isVineClimbing && (__instance.Sliding() || Mathf.Abs(val.input.movementInput.y) < 0.01f))
			{
				StaminaCostContext.Kind = StaminaCostKind.VineIdle;
			}
		}

		[HarmonyFinalizer]
		private static void Finalizer()
		{
			if (StaminaCostContext.Kind == StaminaCostKind.VineIdle)
			{
				StaminaCostContext.Kind = StaminaCostKind.None;
			}
		}
	}
	[HarmonyPatch(typeof(Glider), "FixedUpdate")]
	internal static class Glider_FixedUpdate_Patch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			StaminaCostContext.Kind = StaminaCostKind.Glider;
		}

		[HarmonyFinalizer]
		private static void Finalizer()
		{
			if (StaminaCostContext.Kind == StaminaCostKind.Glider)
			{
				StaminaCostContext.Kind = StaminaCostKind.None;
			}
		}
	}
	[HarmonyPatch(typeof(Character), "UpdateVariablesFixed")]
	internal static class Character_UpdateVariablesFixed_Patch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			StaminaCostContext.Kind = StaminaCostKind.NaturalRegen;
		}

		[HarmonyFinalizer]
		private static void Finalizer()
		{
			if (StaminaCostContext.Kind == StaminaCostKind.NaturalRegen)
			{
				StaminaCostContext.Kind = StaminaCostKind.None;
			}
		}
	}
	[HarmonyPatch(typeof(Character), "AddStamina")]
	internal static class Character_AddStamina_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(ref float add)
		{
			if (StaminaCostContext.Kind != StaminaCostKind.NaturalRegen)
			{
				return true;
			}
			if (add <= 0f)
			{
				return true;
			}
			float num = Plugin.PercentToMultiplier(Plugin.StaminaRegenPercent.Value);
			if (num <= 0f)
			{
				return false;
			}
			if (Mathf.Approximately(num, 1f))
			{
				return true;
			}
			add *= num;
			return add > 0f;
		}
	}
	[HarmonyPatch(typeof(Character), "CanRegenStamina")]
	internal static class Character_CanRegenStamina_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(Character __instance, ref bool __result)
		{
			float num = Plugin.PercentToMultiplier(Plugin.StaminaRegenDelayPercent.Value);
			if (Mathf.Approximately(num, 1f))
			{
				return true;
			}
			CharacterData data = __instance.data;
			if ((Object)(object)data == (Object)null)
			{
				return true;
			}
			if (Object.op_Implicit((Object)(object)data.currentClimbHandle))
			{
				__result = true;
				return false;
			}
			if (__instance.IsStuck())
			{
				__result = true;
				return false;
			}
			float num2 = ((data.currentStamina > 0f) ? 1f : 2f) * num;
			if ((data.sinceGrounded > 0.2f && ((Object)(object)__instance.refs?.afflictions == (Object)null || !__instance.refs.afflictions.isWebbed)) || data.sinceUseStamina < num2)
			{
				__result = false;
				return false;
			}
			__result = true;
			return false;
		}
	}
	[BepInPlugin("youxia173.StaminaCostTweaks", "StaminaCostTweaks", "1.0.11")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		public static ConfigEntry<float> SprintCostPercent;

		public static ConfigEntry<float> ClimbCostPercent;

		public static ConfigEntry<float> ClimbJumpCostPercent;

		public static ConfigEntry<float> VineIdleCostPercent;

		public static ConfigEntry<float> GliderCostPercent;

		public static ConfigEntry<float> StaminaRegenPercent;

		public static ConfigEntry<float> StaminaRegenDelayPercent;

		public static ConfigEntry<bool> ExtremeClimbEnabled;

		public static ConfigEntry<float> ExtremeClimbCostPercent;

		public static ConfigEntry<float> ExtremeClimbBelowPercent;

		public static ConfigEntry<KeyCode> ToggleFreeStaminaKey;

		private Harmony? _harmony;

		private float _toastUntil;

		private string _toastText = "";

		public static bool FreeStaminaEnabled { get; private set; }

		private void Awake()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Expected O, but got Unknown
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Expected O, but got Unknown
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Expected O, but got Unknown
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Expected O, but got Unknown
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Expected O, but got Unknown
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Expected O, but got Unknown
			//IL_0391: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			SprintCostPercent = ((BaseUnityPlugin)this).Config.Bind<float>("StaminaCost", "SprintCostPercent", 80f, new ConfigDescription("冲刺体力消耗百分比。 / Sprint stamina cost percent. 消耗百分比:100 = 原版,80 = 原版的 80%。在难度系数之后生效。范围 0–500。仅在「免费体力」关闭时生效。 / Cost percent: 100 = vanilla, 80 = 80% of vanilla. Applied after difficulty multipliers. Range 0-500. Only when free stamina is OFF.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>()));
			ClimbCostPercent = ((BaseUnityPlugin)this).Config.Bind<float>("StaminaCost", "ClimbCostPercent", 80f, new ConfigDescription("攀爬(持续)体力消耗百分比。 / Climb (continuous) stamina cost percent. 消耗百分比:100 = 原版,80 = 原版的 80%。在难度系数之后生效。范围 0–500。仅在「免费体力」关闭时生效。 / Cost percent: 100 = vanilla, 80 = 80% of vanilla. Applied after difficulty multipliers. Range 0-500. Only when free stamina is OFF.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>()));
			ClimbJumpCostPercent = ((BaseUnityPlugin)this).Config.Bind<float>("StaminaCost", "ClimbJumpCostPercent", 80f, new ConfigDescription("攀爬跳跃体力消耗百分比。 / Climb-jump stamina cost percent. 消耗百分比:100 = 原版,80 = 原版的 80%。在难度系数之后生效。范围 0–500。仅在「免费体力」关闭时生效。 / Cost percent: 100 = vanilla, 80 = 80% of vanilla. Applied after difficulty multipliers. Range 0-500. Only when free stamina is OFF.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>()));
			VineIdleCostPercent = ((BaseUnityPlugin)this).Config.Bind<float>("StaminaCost", "VineIdleCostPercent", 80f, new ConfigDescription("藤蔓空闲(几乎不动)体力消耗百分比。 / Vine idle stamina cost percent. 消耗百分比:100 = 原版,80 = 原版的 80%。在难度系数之后生效。范围 0–500。仅在「免费体力」关闭时生效。 / Cost percent: 100 = vanilla, 80 = 80% of vanilla. Applied after difficulty multipliers. Range 0-500. Only when free stamina is OFF.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>()));
			GliderCostPercent = ((BaseUnityPlugin)this).Config.Bind<float>("StaminaCost", "GliderCostPercent", 80f, new ConfigDescription("滑翔伞体力消耗百分比(开伞+持续)。 / Glider stamina cost percent (open + continuous). 消耗百分比:100 = 原版,80 = 原版的 80%。在难度系数之后生效。范围 0–500。仅在「免费体力」关闭时生效。 / Cost percent: 100 = vanilla, 80 = 80% of vanilla. Applied after difficulty multipliers. Range 0-500. Only when free stamina is OFF.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>()));
			StaminaRegenPercent = ((BaseUnityPlugin)this).Config.Bind<float>("StaminaCost", "StaminaRegenPercent", 120f, new ConfigDescription("自然体力恢复速度百分比(原版约每秒 0.2)。100 = 原版,120 = 快 20%,200 = 两倍,0 = 不自然回体。不影响食物/士气等额外回体。范围 0–500。 / Natural stamina regen percent (vanilla ~0.2/s). 100 = vanilla, 120 = +20%, 200 = 2x, 0 = no natural regen. Does not affect food/morale bonus stamina. Range 0-500.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>()));
			StaminaRegenDelayPercent = ((BaseUnityPlugin)this).Config.Bind<float>("StaminaCost", "StaminaRegenDelayPercent", 50f, new ConfigDescription("耗体后开始自然回体的等待时间百分比。原版:有体力约 1 秒,空条约 2 秒。100 = 原版,50 = 延迟减半(有体力 0.5 秒 / 空条 1 秒),0 = 几乎立刻开始回。范围 0–500。 / Delay before natural regen after spending stamina. Vanilla: ~1s if stamina>0, ~2s if empty. 100 = vanilla, 50 = half delay, 0 = near-instant. Range 0-500.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>()));
			ExtremeClimbEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("StaminaCost", "ExtremeClimbEnabled", true, "极限攀爬:满足任一条件时,攀爬/藤蔓/绳/滑翔伞消耗改为「极限攀爬消耗百分比」——①额外体力≈0 且当前体力低于阈值;②当前体力≈0 且额外体力低于阈值。 / Extreme climb when (bonus≈0 & current below threshold) OR (current≈0 & bonus below threshold).");
			ExtremeClimbCostPercent = ((BaseUnityPlugin)this).Config.Bind<float>("StaminaCost", "ExtremeClimbCostPercent", 30f, new ConfigDescription("极限状态下的消耗百分比(相对原版)。默认 30 = 正常的 30%。覆盖攀爬/攀爬跳/藤蔓/滑翔伞等配置。范围 0–500。 / Cost percent in extreme state (vs vanilla). Default 30. Overrides climb/vine/glider percents. Range 0-500.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>()));
			ExtremeClimbBelowPercent = ((BaseUnityPlugin)this).Config.Bind<float>("StaminaCost", "ExtremeClimbBelowPercent", 10f, new ConfigDescription("极限攀爬阈值(百分比)。用于:当前体力 < 此值(额外体力为 0 时),或额外体力 < 此值(当前体力为 0 时)。默认 10。范围 1–100。 / Threshold % for extreme climb: current < N when bonus=0, or bonus < N when current=0. Default 10. Range 1-100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>()));
			ToggleFreeStaminaKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Hotkeys", "ToggleFreeStaminaKey", (KeyCode)54, "切换免费体力(本机所有 UseStamina 归零)。默认大键盘 6(Alpha6);小键盘用 Keypad6。 / Toggle free stamina (skip all local UseStamina). Default Alpha6 (top-row 6). Use Keypad6 for numpad.");
			FreeStaminaEnabled = false;
			_harmony = new Harmony("youxia173.StaminaCostTweaks");
			_harmony.PatchAll();
			Log.LogInfo((object)("StaminaCostTweaks v1.0.11 by youxia173 loaded. " + $"Sprint={SprintCostPercent.Value}% Climb={ClimbCostPercent.Value}% " + $"ClimbJump={ClimbJumpCostPercent.Value}% VineIdle={VineIdleCostPercent.Value}% " + $"Glider={GliderCostPercent.Value}% Regen={StaminaRegenPercent.Value}% " + $"RegenDelay={StaminaRegenDelayPercent.Value}% " + string.Format("ExtremeClimb={0}@{1}%/<{2}% ", ExtremeClimbEnabled.Value ? "ON" : "OFF", ExtremeClimbCostPercent.Value, ExtremeClimbBelowPercent.Value) + $"ToggleKey={ToggleFreeStaminaKey.Value} FreeStamina=OFF"));
		}

		private void Update()
		{
			//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_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			KeyCode value = ToggleFreeStaminaKey.Value;
			if ((int)value != 0 && Input.GetKeyDown(value))
			{
				FreeStaminaEnabled = !FreeStaminaEnabled;
				_toastText = (FreeStaminaEnabled ? "免费体力 ON / Free stamina ON" : "免费体力 OFF / Free stamina OFF");
				_toastUntil = Time.unscaledTime + 2.5f;
				Log.LogInfo((object)(FreeStaminaEnabled ? "Free stamina ON (all local UseStamina skipped)" : "Free stamina OFF (config percents apply)"));
			}
		}

		private void OnGUI()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			if (!(Time.unscaledTime > _toastUntil) && !string.IsNullOrEmpty(_toastText))
			{
				GUIStyle val = new GUIStyle(GUI.skin.box)
				{
					fontSize = 20,
					alignment = (TextAnchor)4,
					fontStyle = (FontStyle)1
				};
				val.normal.textColor = Color.white;
				float num = 360f;
				float num2 = 48f;
				GUI.Box(new Rect(((float)Screen.width - num) * 0.5f, (float)Screen.height * 0.18f, num, num2), _toastText, val);
			}
		}

		private void OnDestroy()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		public static float PercentToMultiplier(float percent)
		{
			if (percent < 0f)
			{
				percent = 0f;
			}
			return percent / 100f;
		}
	}
	internal enum StaminaCostKind
	{
		None,
		ClimbJump,
		VineIdle,
		Glider,
		NaturalRegen
	}
	internal static class StaminaCostContext
	{
		[ThreadStatic]
		private static StaminaCostKind _kind;

		public static StaminaCostKind Kind
		{
			get
			{
				return _kind;
			}
			set
			{
				_kind = value;
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "youxia173.StaminaCostTweaks";

		public const string PLUGIN_NAME = "StaminaCostTweaks";

		public const string PLUGIN_VERSION = "1.0.11";
	}
}