Decompiled source of RunBasedPassives v0.2.0

plugins/RunBasedPassives.dll

Decompiled 11 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using MoreUIPanel;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("RunBasedPassives")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RunBasedPassives")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("d3524128-8d57-4661-a37a-6231cfd2059c")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace RunBasedPassives;

[BepInPlugin("cn_xc.RunBasedPassives", "RunBasedPassives", "0.2.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
	private ConfigEntry<bool> enableJump;

	private ConfigEntry<bool> enableStrength;

	private ConfigEntry<bool> enableStamina;

	private ConfigEntry<bool> enableHealth;

	private ConfigEntry<bool> verboseLogging;

	public static int JumpLevel;

	public static int StrengthLevel;

	public static int StaminaLevel;

	public static int HealthLevel;

	public static int JumpCount;

	public static int GrabCount;

	public static float MoveDistance;

	public static int HealCount;

	private static int _lastLogJump;

	private static int _lastLogGrab;

	private static float _lastLogMove;

	private static int _lastLogHeal;

	private Harmony harmony;

	private static FieldRef<PlayerAvatar, string> steamIDRef;

	private static FieldRef<PlayerAvatar, bool> isLocalRef;

	private static FieldRef<PlayerHealth, PlayerAvatar> healthPlayerAvatarRef;

	private static FieldRef<StatsManager, SortedDictionary<string, Dictionary<string, int>>> dictOfDictsRef;

	private bool _uiRegistered = false;

	private int GetJumpThreshold()
	{
		return 80 + JumpLevel * 40;
	}

	private int GetGrabThreshold()
	{
		return 50 + StrengthLevel * 10;
	}

	private float GetMoveThreshold()
	{
		return 500f + (float)StaminaLevel * 200f;
	}

	private int GetHealThreshold()
	{
		return 50 + HealthLevel * 15;
	}

	private void Awake()
	{
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Expected O, but got Unknown
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: Expected O, but got Unknown
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_019f: Expected O, but got Unknown
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Expected O, but got Unknown
		//IL_0206: Unknown result type (might be due to invalid IL or missing references)
		//IL_0213: Expected O, but got Unknown
		enableJump = ((BaseUnityPlugin)this).Config.Bind<bool>("Toggles", "EnableJump", true, "启用跳跃升级");
		enableStrength = ((BaseUnityPlugin)this).Config.Bind<bool>("Toggles", "EnableStrength", true, "启用力量升级");
		enableStamina = ((BaseUnityPlugin)this).Config.Bind<bool>("Toggles", "EnableStamina", true, "启用耐力升级");
		enableHealth = ((BaseUnityPlugin)this).Config.Bind<bool>("Toggles", "EnableHealth", true, "启用生命升级");
		verboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "VerboseLogging", true, "详细日志输出(用于调试)");
		steamIDRef = AccessTools.FieldRefAccess<PlayerAvatar, string>("steamID");
		isLocalRef = AccessTools.FieldRefAccess<PlayerAvatar, bool>("isLocal");
		healthPlayerAvatarRef = AccessTools.FieldRefAccess<PlayerHealth, PlayerAvatar>("playerAvatar");
		dictOfDictsRef = AccessTools.FieldRefAccess<StatsManager, SortedDictionary<string, Dictionary<string, int>>>("dictionaryOfDictionaries");
		Patches.isLocalRef = isLocalRef;
		Patches.steamIDRef = steamIDRef;
		Patches.healthPlayerAvatarRef = healthPlayerAvatarRef;
		Patches.pluginLogger = ((BaseUnityPlugin)this).Logger;
		Patches.verboseLogging = verboseLogging;
		Harmony.DEBUG = true;
		harmony = new Harmony("cn_xc.RunBasedPassives");
		harmony.Patch((MethodBase)AccessTools.Method(typeof(PlayerAvatar), "Jump", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "JumpPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)AccessTools.Method(typeof(PhysGrabObject), "GrabStarted", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "GrabStartedPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)AccessTools.Method(typeof(PlayerAvatar), "Update", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "PlayerAvatarUpdatePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)AccessTools.Method(typeof(PlayerHealth), "Heal", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "HealPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		SceneManager.sceneLoaded += OnSceneLoaded;
		((BaseUnityPlugin)this).Logger.LogInfo((object)$"Harmony 补丁总数: {harmony.GetPatchedMethods().Count()}");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"RunBasedPassives v0.2.0 loaded");
		if (verboseLogging.Value)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"详细日志已开启(仅在经验变化时输出)");
		}
	}

	private void OnDestroy()
	{
		SceneManager.sceneLoaded -= OnSceneLoaded;
		if (_uiRegistered)
		{
			Plugin.UnregisterLine("runbasedpassives_stats");
		}
		harmony.UnpatchAll((string)null);
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		ResetCounters();
	}

	private void ResetCounters()
	{
		JumpCount = 0;
		GrabCount = 0;
		MoveDistance = 0f;
		HealCount = 0;
		Patches.ResetState();
		if (verboseLogging.Value)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[场景加载] 计数器已重置");
		}
	}

	private void Update()
	{
		if ((Object)(object)PlayerAvatar.instance == (Object)null)
		{
			return;
		}
		bool flag = SemiFunc.RunIsLevel() || SemiFunc.RunIsShop();
		if (flag && !_uiRegistered)
		{
			Plugin.RegisterLine("runbasedpassives_stats", (Func<string>)BuildDisplayText);
			_uiRegistered = true;
		}
		else if (!flag && _uiRegistered)
		{
			Plugin.UnregisterLine("runbasedpassives_stats");
			_uiRegistered = false;
		}
		if (flag)
		{
			string steamID = GetSteamID();
			if (!string.IsNullOrEmpty(steamID))
			{
				JumpLevel = ReadGameDict("playerUpgradeExtraJump", steamID);
				StrengthLevel = ReadGameDict("playerUpgradeStrength", steamID);
				StaminaLevel = ReadGameDict("playerUpgradeStamina", steamID);
				HealthLevel = ReadGameDict("playerUpgradeHealth", steamID);
			}
			CheckUpgrades();
			ApplyStats();
			if (verboseLogging.Value && (JumpCount != _lastLogJump || GrabCount != _lastLogGrab || (int)MoveDistance != (int)_lastLogMove || HealCount != _lastLogHeal))
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"[状态] 跳跃:{JumpCount}/{GetJumpThreshold()} Lv.{JumpLevel} | 力量:{GrabCount}/{GetGrabThreshold()} Lv.{StrengthLevel} | 耐力:{MoveDistance:F0}/{GetMoveThreshold()} Lv.{StaminaLevel} | 生命:{HealCount}/{GetHealThreshold()} Lv.{HealthLevel}");
				_lastLogJump = JumpCount;
				_lastLogGrab = GrabCount;
				_lastLogMove = MoveDistance;
				_lastLogHeal = HealCount;
			}
		}
	}

	private int ReadGameDict(string dictName, string sid)
	{
		SortedDictionary<string, Dictionary<string, int>> sortedDictionary = dictOfDictsRef.Invoke(StatsManager.instance);
		if (sortedDictionary != null && sortedDictionary.TryGetValue(dictName, out var value) && value != null && value.TryGetValue(sid, out var value2))
		{
			return value2;
		}
		return 0;
	}

	private void CheckUpgrades()
	{
		string steamID = GetSteamID();
		if (string.IsNullOrEmpty(steamID))
		{
			return;
		}
		bool flag = false;
		if (enableJump.Value && JumpCount >= GetJumpThreshold())
		{
			JumpCount -= GetJumpThreshold();
			JumpLevel++;
			StatsManager instance = StatsManager.instance;
			if (instance != null)
			{
				instance.DictionaryUpdateValue("playerUpgradeExtraJump", steamID, JumpLevel);
			}
			if (verboseLogging.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"[升级] 跳跃升级至 Lv.{JumpLevel}");
			}
			flag = true;
		}
		if (enableStrength.Value && GrabCount >= GetGrabThreshold())
		{
			GrabCount -= GetGrabThreshold();
			StrengthLevel++;
			StatsManager instance2 = StatsManager.instance;
			if (instance2 != null)
			{
				instance2.DictionaryUpdateValue("playerUpgradeStrength", steamID, StrengthLevel);
			}
			if (verboseLogging.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"[升级] 力量升级至 Lv.{StrengthLevel}");
			}
			flag = true;
		}
		if (enableStamina.Value && MoveDistance >= GetMoveThreshold())
		{
			MoveDistance -= GetMoveThreshold();
			StaminaLevel++;
			StatsManager instance3 = StatsManager.instance;
			if (instance3 != null)
			{
				instance3.DictionaryUpdateValue("playerUpgradeStamina", steamID, StaminaLevel);
			}
			if (verboseLogging.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"[升级] 耐力升级至 Lv.{StaminaLevel}");
			}
			flag = true;
		}
		if (enableHealth.Value && HealCount >= GetHealThreshold())
		{
			HealCount -= GetHealThreshold();
			HealthLevel++;
			StatsManager instance4 = StatsManager.instance;
			if (instance4 != null)
			{
				instance4.DictionaryUpdateValue("playerUpgradeHealth", steamID, HealthLevel);
			}
			if (verboseLogging.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"[升级] 生命升级至 Lv.{HealthLevel}");
			}
			flag = true;
		}
		if (flag && (Object)(object)StatsUI.instance != (Object)null)
		{
			StatsUI.instance.Fetch();
		}
	}

	private void ApplyStats()
	{
		if (!enableStrength.Value)
		{
			return;
		}
		PlayerAvatar instance = PlayerAvatar.instance;
		if ((Object)(object)instance != (Object)null)
		{
			PhysGrabber physGrabber = instance.physGrabber;
			if ((Object)(object)physGrabber != (Object)null)
			{
				physGrabber.grabStrength = 1f + (float)StrengthLevel;
			}
		}
	}

	private string GetSteamID()
	{
		PlayerAvatar instance = PlayerAvatar.instance;
		if ((Object)(object)instance == (Object)null)
		{
			return null;
		}
		return steamIDRef.Invoke(instance);
	}

	private string BuildDisplayText()
	{
		StringBuilder stringBuilder = new StringBuilder();
		if (enableJump.Value)
		{
			stringBuilder.AppendLine($"跳跃 Lv.{JumpLevel} ({JumpCount}/{GetJumpThreshold()})");
		}
		if (enableStrength.Value)
		{
			stringBuilder.AppendLine($"力量 Lv.{StrengthLevel} ({GrabCount}/{GetGrabThreshold()})");
		}
		if (enableStamina.Value)
		{
			stringBuilder.AppendLine($"耐力 Lv.{StaminaLevel} ({MoveDistance:F0}/{GetMoveThreshold()})");
		}
		if (enableHealth.Value)
		{
			stringBuilder.AppendLine($"生命 Lv.{HealthLevel} ({HealCount}/{GetHealThreshold()})");
		}
		return stringBuilder.ToString().TrimEnd(Array.Empty<char>());
	}
}
public static class Patches
{
	internal static FieldRef<PlayerAvatar, bool> isLocalRef;

	internal static FieldRef<PlayerAvatar, string> steamIDRef;

	internal static FieldRef<PlayerHealth, PlayerAvatar> healthPlayerAvatarRef;

	internal static ManualLogSource pluginLogger;

	internal static ConfigEntry<bool> verboseLogging;

	private static Vector3 lastPos;

	private static bool lastPosInitialized;

	private static readonly HashSet<int> grabbedThisLevel = new HashSet<int>();

	private static bool IsInGameplay => SemiFunc.RunIsLevel() || SemiFunc.RunIsShop();

	public static void ResetState()
	{
		lastPosInitialized = false;
		grabbedThisLevel.Clear();
	}

	public static void JumpPrefix(PlayerAvatar __instance)
	{
		if (IsInGameplay && isLocalRef.Invoke(__instance))
		{
			Plugin.JumpCount++;
		}
	}

	public static void GrabStartedPostfix(PhysGrabObject __instance)
	{
		if (!IsInGameplay || SemiFunc.RunIsShop())
		{
			return;
		}
		int instanceID = ((Object)__instance).GetInstanceID();
		if (grabbedThisLevel.Contains(instanceID))
		{
			return;
		}
		List<PhysGrabber> playerGrabbing = __instance.playerGrabbing;
		if (playerGrabbing == null)
		{
			return;
		}
		foreach (PhysGrabber item in playerGrabbing)
		{
			if ((Object)(object)item.playerAvatar != (Object)null && isLocalRef.Invoke(item.playerAvatar))
			{
				grabbedThisLevel.Add(instanceID);
				Plugin.GrabCount++;
				break;
			}
		}
	}

	public static void PlayerAvatarUpdatePostfix(PlayerAvatar __instance)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: 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_003a: Unknown result type (might be due to invalid IL or missing references)
		if (IsInGameplay && isLocalRef.Invoke(__instance))
		{
			Vector3 position = ((Component)__instance).transform.position;
			if (!lastPosInitialized)
			{
				lastPos = position;
				lastPosInitialized = true;
			}
			else
			{
				float num = Vector3.Distance(position, lastPos);
				Plugin.MoveDistance += num;
				lastPos = position;
			}
		}
	}

	public static void HealPrefix(int healAmount, PlayerHealth __instance)
	{
		if (IsInGameplay && !SemiFunc.RunIsShop() && healAmount > 0)
		{
			PlayerAvatar val = healthPlayerAvatarRef.Invoke(__instance);
			if (!((Object)(object)val == (Object)null) && isLocalRef.Invoke(val))
			{
				Plugin.HealCount++;
			}
		}
	}
}