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 enableJump; private ConfigEntry enableStrength; private ConfigEntry enableStamina; private ConfigEntry enableHealth; private ConfigEntry 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 steamIDRef; private static FieldRef isLocalRef; private static FieldRef healthPlayerAvatarRef; private static FieldRef>> 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("Toggles", "EnableJump", true, "启用跳跃升级"); enableStrength = ((BaseUnityPlugin)this).Config.Bind("Toggles", "EnableStrength", true, "启用力量升级"); enableStamina = ((BaseUnityPlugin)this).Config.Bind("Toggles", "EnableStamina", true, "启用耐力升级"); enableHealth = ((BaseUnityPlugin)this).Config.Bind("Toggles", "EnableHealth", true, "启用生命升级"); verboseLogging = ((BaseUnityPlugin)this).Config.Bind("Debug", "VerboseLogging", true, "详细日志输出(用于调试)"); steamIDRef = AccessTools.FieldRefAccess("steamID"); isLocalRef = AccessTools.FieldRefAccess("isLocal"); healthPlayerAvatarRef = AccessTools.FieldRefAccess("playerAvatar"); dictOfDictsRef = AccessTools.FieldRefAccess>>("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)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> 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()); } } public static class Patches { internal static FieldRef isLocalRef; internal static FieldRef steamIDRef; internal static FieldRef healthPlayerAvatarRef; internal static ManualLogSource pluginLogger; internal static ConfigEntry verboseLogging; private static Vector3 lastPos; private static bool lastPosInitialized; private static readonly HashSet grabbedThisLevel = new HashSet(); 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 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++; } } } }