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";
}
}