Decompiled source of EasyVitals v1.0.0

plugins/EasyVitals/EasyVitals.dll

Decompiled 6 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
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(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("EasyVitals")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EasyVitals")]
[assembly: AssemblyTitle("EasyVitals")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 EasyVitals
{
	[BepInPlugin("easyvitals.client.only", "EasyVitals", "1.0.0")]
	public class EasyVitalsPlugin : BaseUnityPlugin
	{
		public const string Guid = "easyvitals.client.only";

		public const string PluginName = "EasyVitals";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> WeightEnabled;

		internal static ConfigEntry<float> WeightMultiplier;

		internal static ConfigEntry<bool> FoodEnabled;

		internal static ConfigEntry<float> FoodDurationMultiplier;

		internal static ConfigEntry<bool> PotionEnabled;

		internal static ConfigEntry<float> PotionDurationMultiplier;

		internal static ConfigEntry<float> PotionMinDuration;

		internal static ConfigEntry<string> PotionSkipNameContains;

		internal static ConfigEntry<bool> MapEnabled;

		internal static ConfigEntry<float> MapExploreMultiplier;

		internal static ConfigEntry<bool> BossPowerEnabled;

		internal static ConfigEntry<float> BossPowerMultiplier;

		internal static ConfigEntry<bool> RestedEnabled;

		internal static ConfigEntry<float> RestedMultiplier;

		internal static ConfigEntry<bool> RestingEnabled;

		internal static ConfigEntry<float> RestingSeconds;

		internal static ConfigEntry<bool> MovePenaltyEnabled;

		internal static ConfigEntry<float> MovePenaltyValue;

		internal static ConfigEntry<bool> MovePenaltyOnlyExisting;

		internal static ConfigEntry<bool> FoodFullEnabled;

		private Harmony harmony;

		private void Awake()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Expected O, but got Unknown
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Expected O, but got Unknown
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Expected O, but got Unknown
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Expected O, but got Unknown
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Expected O, but got Unknown
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Expected O, but got Unknown
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			WeightEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Item Weight", "Enabled", true, "物品重量修改开关。只改重量,完全不动堆叠上限。");
			WeightMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Item Weight", "Multiplier", 0.25f, new ConfigDescription("物品重量倍率:0.25 = 原版 25%,1 = 原版,2 = 两倍重。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 5f), Array.Empty<object>()));
			FoodEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Food Duration", "Enabled", true, "食物持续时间修改开关。");
			FoodDurationMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Food Duration", "Multiplier", 5f, new ConfigDescription("食物时长倍率:5 = 原版 5 倍(物品提示里的「食物持续」会跟着变)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 20f), Array.Empty<object>()));
			PotionEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Potion Duration", "Enabled", true, "药水等消耗品的「增益效果」时长修改开关。");
			PotionDurationMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Potion Duration", "Multiplier", 5f, new ConfigDescription("消耗品效果时长倍率:5 = 原版 5 倍。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 20f), Array.Empty<object>()));
			PotionMinDuration = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Potion Duration", "MinDuration", 300f, new ConfigDescription("只延长「原始时长 >= 该值(秒)」的效果,用来跳过药水的冷却。\n治疗/体力类蜜酒的冷却只有 120 秒,而真正的增益(抗性等)通常 300 秒以上。\n设为 0 = 不限制(连冷却也一起延长)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3600f), Array.Empty<object>()));
			PotionSkipNameContains = ((BaseUnityPlugin)this).Config.Bind<string>("3 - Potion Duration", "SkipNameContains", "", "效果名称里包含这些关键词就不延长(逗号分隔,不区分大小写)。\n留空即可,上面的 MinDuration 已经能过滤掉冷却。");
			MapEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Map Discovery", "Enabled", true, "地图探索揭示半径修改开关。");
			MapExploreMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Map Discovery", "Multiplier", 3f, new ConfigDescription("探索揭示半径倍率:3 = 原版 3 倍。只影响之后新探索的区域。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f), Array.Empty<object>()));
			BossPowerEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Boss Power Duration", "Enabled", true, "遗忘之力(Boss power / 被遗忘者的力量)增益时长修改开关。\n覆盖全部 GP_ 效果:Eikthyr、The Elder、Bonemass、Moder、Yagluth、Queen、Ashlands、DeepNorth。");
			BossPowerMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("5 - Boss Power Duration", "Multiplier", 2f, new ConfigDescription("遗忘之力增益时长倍率:2 = 原版 2 倍(原版 5 分钟 → 10 分钟)。\n只延长「增益持续时间」,20 分钟的使用冷却完全不变(游戏里冷却和时长是两个独立数据)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 20f), Array.Empty<object>()));
			RestedEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("6 - Rested Duration", "Enabled", true, "「休息好了」(Rested)增益时长修改开关。");
			RestedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("6 - Rested Duration", "Multiplier", 3f, new ConfigDescription("Rested 时长倍率:3 = 原版 3 倍。\n改的是 SE_Rested 的两个「源字段」—— m_baseTTL(基准时长)与\nm_TTLPerComfortLevel(每级舒适度加成)—— 两个一起 ×倍率,所以任何舒适度都是准确的 3 倍。\n⚠\ufe0f 不能改 SE_Rested.m_ttl:游戏每次 Player.UpdateBaseValue 都会重算\n   m_ttl = m_baseTTL + (舒适度等级 - 1) × m_TTLPerComfortLevel,改了会被立刻覆盖。\n只影响这个增益的持续时间,不影响「休息多久才拿到」、也不影响其它状态效果。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 20f), Array.Empty<object>()));
			RestingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("7 - Resting Time", "Enabled", true, "「靠火堆休息多久才获得『休息好了(Rested)』」的开关。\n改的是 SE_Cozy 的 m_delay —— 游戏发 Rested 的地方就在它身上:\n  SE_Cozy.UpdateStatusEffect(): if (m_time > m_delay) 给玩家挂 Rested。\n⚠\ufe0f SE_Cozy 的 prefab 名字叫「SE_Resting」(类名 ≠ prefab 名),1.6.1 按名字找 Cozy 因此失效;\n   1.6.2 起改为按类型判定,不再依赖名字。");
			RestingSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("7 - Resting Time", "Seconds", 5f, new ConfigDescription("在火堆旁累计「惬意」多少秒后获得「休息好了」。原版 20 秒,默认 5 秒。\n⚠\ufe0f 千万别去改 SE_Resting(SE_Cozy) 的 m_ttl —— 那只会让它反复到期→被重新挂上→\n   反复弹「休息中」,跟发不发 Rested 无关(1.6.0 的 bug 就是这个)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 120f), Array.Empty<object>()));
			MovePenaltyEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("8 - Equipment Speed", "Enabled", true, "装备/武器「移动速度惩罚」统一开关。\n原版各件装备的减速不一样(重的护甲、大盾、双手武器各有各的数值),这里统一改成同一个值。");
			MovePenaltyValue = ((BaseUnityPlugin)this).Config.Bind<float>("8 - Equipment Speed", "Value", -0.02f, new ConfigDescription("统一后的移动速度惩罚:-0.02 = -2%(原版不少装备是 -5% / -10%)。\n填 0 = 完全不减速。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.5f, 0f), Array.Empty<object>()));
			MovePenaltyOnlyExisting = ((BaseUnityPlugin)this).Config.Bind<bool>("8 - Equipment Speed", "OnlyExistingPenalty", true, "true(默认)= 只改【本来就有减速】的装备,把它们的惩罚都统一成上面的值;\nfalse = 连本来不减速的装备也一起设成上面的值(会变成给它们加惩罚,一般不要开)。");
			FoodFullEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("9 - Food Full Effect", "Enabled", true, "食物效果保持满值:只要还吃着这份食物,最大血量和最大耐力就一直按食物的满值算,\n不再随剩余时间衰减(原版会按 Pow(剩余比例, 0.3) 逐渐减弱)。\n食物时间照旧会走完,走完后加成正常消失。");
			Log.LogInfo((object)"EasyVitals 1.0.0 开始挂载 Harmony 补丁……");
			FoodFullEffect.Init();
			ApplyPatches();
			VerifyPatches();
		}

		private void ApplyPatches()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			harmony = new Harmony("easyvitals.client.only");
			Type[] array = new Type[4]
			{
				typeof(ObjectDbAwakePatch),
				typeof(ZNetSceneAwakePatch),
				typeof(MinimapExplorePatch),
				typeof(PlayerGetTotalFoodValuePatch)
			};
			int num = 0;
			Type[] array2 = array;
			foreach (Type type in array2)
			{
				try
				{
					harmony.CreateClassProcessor(type).Patch();
					Log.LogInfo((object)("  已挂载补丁类:" + type.Name));
					num++;
				}
				catch (Exception ex)
				{
					Log.LogError((object)("  挂载失败 " + type.Name + ":" + ex.Message));
				}
			}
			Log.LogInfo((object)$"Harmony 补丁挂载完成:{num}/{array.Length} 成功。");
		}

		private void VerifyPatches()
		{
			List<MethodBase> list = new List<MethodBase>();
			MethodBase methodBase = AccessTools.Method(typeof(ObjectDB), "Awake", (Type[])null, (Type[])null);
			if (methodBase != null)
			{
				list.Add(methodBase);
			}
			methodBase = AccessTools.Method(typeof(ZNetScene), "Awake", (Type[])null, (Type[])null);
			if (methodBase != null)
			{
				list.Add(methodBase);
			}
			methodBase = AccessTools.Method(typeof(Minimap), "Explore", new Type[2]
			{
				typeof(Vector3),
				typeof(float)
			}, (Type[])null);
			if (methodBase != null)
			{
				list.Add(methodBase);
			}
			methodBase = AccessTools.Method(typeof(Player), "GetTotalFoodValue", (Type[])null, (Type[])null);
			if (methodBase != null)
			{
				list.Add(methodBase);
			}
			Log.LogInfo((object)"---- 补丁挂载自检 ----");
			foreach (MethodBase item in list)
			{
				Patches patchInfo = Harmony.GetPatchInfo(item);
				int num = ((patchInfo != null && patchInfo.Prefixes != null) ? patchInfo.Prefixes.Count : 0);
				int num2 = ((patchInfo != null && patchInfo.Postfixes != null) ? patchInfo.Postfixes.Count : 0);
				string text = ((num + num2 > 0) ? "OK" : "!! 未挂上 !!");
				Log.LogInfo((object)$"  {item.DeclaringType.Name}.{item.Name}()  prefix={num} postfix={num2}  {text}");
			}
			Log.LogInfo((object)"-----------------------");
		}

		private void OnDestroy()
		{
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal static class FoodFullEffect
	{
		private static FieldInfo foodsField;

		private static FieldInfo itemField;

		private static FieldInfo healthField;

		private static FieldInfo staminaField;

		private static FieldInfo eitrField;

		private static int logCount;

		private static int errCount;

		internal static void Init()
		{
			try
			{
				foodsField = AccessTools.Field(typeof(Player), "m_foods");
				Type type = null;
				if (foodsField != null)
				{
					Type fieldType = foodsField.FieldType;
					if (fieldType.IsGenericType && fieldType.GetGenericArguments().Length == 1)
					{
						type = fieldType.GetGenericArguments()[0];
					}
				}
				if (type == null)
				{
					type = AccessTools.Inner(typeof(Player), "Food");
				}
				if (type != null)
				{
					itemField = AccessTools.Field(type, "m_item");
					healthField = AccessTools.Field(type, "m_health");
					staminaField = AccessTools.Field(type, "m_stamina");
					eitrField = AccessTools.Field(type, "m_eitr");
				}
				EasyVitalsPlugin.Log.LogInfo((object)$"食物满值依赖检查: m_foods={foodsField != null}  Food={type != null}  m_item={itemField != null}  m_health={healthField != null}  m_stamina={staminaField != null}  m_eitr={eitrField != null}");
			}
			catch (Exception ex)
			{
				EasyVitalsPlugin.Log.LogError((object)("食物满值初始化失败:" + ex));
			}
		}

		internal static void Apply(Player player, ref float hp, ref float stamina, ref float eitr)
		{
			try
			{
				if (!EasyVitalsPlugin.FoodFullEnabled.Value || (Object)(object)player == (Object)null || foodsField == null || itemField == null || healthField == null || staminaField == null || eitrField == null || !(foodsField.GetValue(player) is IEnumerable enumerable))
				{
					return;
				}
				float num = 0f;
				float num2 = 0f;
				float num3 = 0f;
				int num4 = 0;
				foreach (object item in enumerable)
				{
					if (item == null)
					{
						continue;
					}
					object? value = itemField.GetValue(item);
					ItemData val = (ItemData)((value is ItemData) ? value : null);
					if (val != null && val.m_shared != null)
					{
						float num5 = (float)healthField.GetValue(item);
						float num6 = (float)staminaField.GetValue(item);
						float num7 = (float)eitrField.GetValue(item);
						float food = val.m_shared.m_food;
						float foodStamina = val.m_shared.m_foodStamina;
						float foodEitr = val.m_shared.m_foodEitr;
						num += food - num5;
						num2 += foodStamina - num6;
						num3 += foodEitr - num7;
						if (food != num5 || foodStamina != num6 || foodEitr != num7)
						{
							healthField.SetValue(item, food);
							staminaField.SetValue(item, foodStamina);
							eitrField.SetValue(item, foodEitr);
							num4++;
						}
					}
				}
				if (num != 0f)
				{
					hp += num;
				}
				if (num2 != 0f)
				{
					stamina += num2;
				}
				if (num3 != 0f)
				{
					eitr += num3;
				}
				if (num4 > 0 && logCount < 5)
				{
					logCount++;
					EasyVitalsPlugin.Log.LogInfo((object)$"[食物满值] 补回衰减:+{num:0.#} 血 / +{num2:0.#} 耐力({num4} 项食物)");
				}
			}
			catch (Exception ex)
			{
				if (errCount < 3)
				{
					errCount++;
					EasyVitalsPlugin.Log.LogError((object)("食物满值失败(游戏本身不受影响):" + ex));
				}
			}
		}
	}
	internal static class ObjectDbApplier
	{
		private static readonly Dictionary<SharedData, float> OrigWeight = new Dictionary<SharedData, float>();

		private static readonly Dictionary<SharedData, float> OrigFoodTime = new Dictionary<SharedData, float>();

		private static readonly Dictionary<StatusEffect, float> OrigEffectTtl = new Dictionary<StatusEffect, float>();

		private static readonly Dictionary<StatusEffect, float> OrigBossTtl = new Dictionary<StatusEffect, float>();

		private static readonly Dictionary<SharedData, float> OrigMovePenalty = new Dictionary<SharedData, float>();

		private static readonly Dictionary<StatusEffect, float> OrigCozyDelay = new Dictionary<StatusEffect, float>();

		private static readonly Dictionary<StatusEffect, float> OrigRestedBase = new Dictionary<StatusEffect, float>();

		private static readonly Dictionary<StatusEffect, float> OrigRestedPerComfort = new Dictionary<StatusEffect, float>();

		private static readonly Dictionary<StatusEffect, float> OrigRestTtl = new Dictionary<StatusEffect, float>();

		private static bool appliedOnce;

		internal static bool AppliedOnce => appliedOnce;

		internal static void ApplyIfReady(string source)
		{
			try
			{
				ObjectDB instance = ObjectDB.instance;
				if ((Object)(object)instance == (Object)null)
				{
					EasyVitalsPlugin.Log.LogWarning((object)("[" + source + "] ObjectDB 还没就绪,稍后重试。"));
				}
				else if (instance.m_items == null)
				{
					EasyVitalsPlugin.Log.LogWarning((object)("[" + source + "] ObjectDB.m_items 为 null,跳过。"));
				}
				else
				{
					Apply(instance, source);
				}
			}
			catch (Exception ex)
			{
				EasyVitalsPlugin.Log.LogError((object)("[" + source + "] 应用失败(游戏本身不受影响):" + ex));
			}
		}

		private static void Apply(ObjectDB db, string source)
		{
			bool value = EasyVitalsPlugin.WeightEnabled.Value;
			bool value2 = EasyVitalsPlugin.FoodEnabled.Value;
			bool value3 = EasyVitalsPlugin.PotionEnabled.Value;
			bool value4 = EasyVitalsPlugin.BossPowerEnabled.Value;
			bool value5 = EasyVitalsPlugin.MovePenaltyEnabled.Value;
			bool value6 = EasyVitalsPlugin.RestedEnabled.Value;
			bool value7 = EasyVitalsPlugin.RestingEnabled.Value;
			float value8 = EasyVitalsPlugin.WeightMultiplier.Value;
			float value9 = EasyVitalsPlugin.FoodDurationMultiplier.Value;
			float value10 = EasyVitalsPlugin.PotionDurationMultiplier.Value;
			float num = Mathf.Max(0.05f, EasyVitalsPlugin.BossPowerMultiplier.Value);
			float value11 = EasyVitalsPlugin.MovePenaltyValue.Value;
			bool value12 = EasyVitalsPlugin.MovePenaltyOnlyExisting.Value;
			float num2 = Mathf.Max(0.05f, EasyVitalsPlugin.RestedMultiplier.Value);
			float num3 = Mathf.Max(0.5f, EasyVitalsPlugin.RestingSeconds.Value);
			float value13 = EasyVitalsPlugin.PotionMinDuration.Value;
			string[] array = EasyVitalsPlugin.PotionSkipNameContains.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			int num4 = 0;
			int num5 = 0;
			int num6 = 0;
			int num7 = 0;
			int num8 = 0;
			StringBuilder stringBuilder = new StringBuilder();
			StringBuilder stringBuilder2 = new StringBuilder();
			foreach (GameObject item in db.m_items)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				ItemDrop component = item.GetComponent<ItemDrop>();
				if ((Object)(object)component == (Object)null || component.m_itemData == null)
				{
					continue;
				}
				SharedData shared = component.m_itemData.m_shared;
				if (shared == null)
				{
					continue;
				}
				if (value && shared.m_weight > 0f)
				{
					if (!OrigWeight.TryGetValue(shared, out var value14))
					{
						value14 = shared.m_weight;
						OrigWeight[shared] = value14;
					}
					shared.m_weight = value14 * value8;
					num4++;
				}
				if (value2 && shared.m_foodBurnTime > 0f)
				{
					if (!OrigFoodTime.TryGetValue(shared, out var value15))
					{
						value15 = shared.m_foodBurnTime;
						OrigFoodTime[shared] = value15;
					}
					shared.m_foodBurnTime = value15 * value9;
					num5++;
				}
				StatusEffect consumeStatusEffect = shared.m_consumeStatusEffect;
				if (value3 && (Object)(object)consumeStatusEffect != (Object)null && consumeStatusEffect.m_ttl > 0f)
				{
					if (!OrigEffectTtl.TryGetValue(consumeStatusEffect, out var value16))
					{
						value16 = consumeStatusEffect.m_ttl;
						OrigEffectTtl[consumeStatusEffect] = value16;
					}
					bool flag = value16 < value13;
					if (!flag && array.Length != 0)
					{
						string text = (((Object)consumeStatusEffect).name ?? string.Empty) + "|" + (consumeStatusEffect.m_name ?? string.Empty);
						string[] array2 = array;
						for (int i = 0; i < array2.Length; i++)
						{
							string text2 = array2[i].Trim();
							if (text2.Length > 0 && text.IndexOf(text2, StringComparison.OrdinalIgnoreCase) >= 0)
							{
								flag = true;
								break;
							}
						}
					}
					if (flag)
					{
						consumeStatusEffect.m_ttl = value16;
						num7++;
						if (stringBuilder.Length < 2000)
						{
							stringBuilder.AppendFormat("     跳过 {0}(时长 {1:0}s < 阈值){2}", ((Object)consumeStatusEffect).name ?? consumeStatusEffect.m_name, value16, Environment.NewLine);
						}
					}
					else
					{
						consumeStatusEffect.m_ttl = value16 * value10;
						num6++;
					}
				}
				if (!value5 || shared.m_movementModifier == 0f || (value12 && !(shared.m_movementModifier < 0f)))
				{
					continue;
				}
				if (!OrigMovePenalty.TryGetValue(shared, out var value17))
				{
					value17 = shared.m_movementModifier;
					OrigMovePenalty[shared] = value17;
				}
				if (Mathf.Abs(value17 - value11) > 0.0001f)
				{
					shared.m_movementModifier = value11;
					num8++;
					if (stringBuilder2.Length < 1200)
					{
						stringBuilder2.AppendFormat("     {0}: {1:P0} -> {2:P0}{3}", shared.m_name, value17, value11, Environment.NewLine);
					}
				}
			}
			int num9 = 0;
			int num10 = 0;
			int num11 = 0;
			StringBuilder stringBuilder3 = new StringBuilder();
			StringBuilder stringBuilder4 = new StringBuilder();
			if (db.m_StatusEffects != null)
			{
				foreach (StatusEffect statusEffect in db.m_StatusEffects)
				{
					if ((Object)(object)statusEffect == (Object)null)
					{
						continue;
					}
					string text3 = StatusEffectName(statusEffect);
					if (value4 && text3.StartsWith("GP_", StringComparison.OrdinalIgnoreCase))
					{
						if (statusEffect.m_ttl <= 0f)
						{
							EasyVitalsPlugin.Log.LogWarning((object)$"遗忘之力 {text3} 的 m_ttl={statusEffect.m_ttl:0.##}(<=0),跳过延长。");
							continue;
						}
						if (!OrigBossTtl.TryGetValue(statusEffect, out var value18))
						{
							value18 = statusEffect.m_ttl;
							OrigBossTtl[statusEffect] = value18;
						}
						statusEffect.m_ttl = value18 * num;
						num9++;
						if (stringBuilder3.Length < 1500)
						{
							stringBuilder3.AppendFormat("     {0}: 增益时长 {1:0}s -> {2:0}s(冷却保持 {3:0}s 不变){4}", text3, value18, statusEffect.m_ttl, statusEffect.m_cooldown, Environment.NewLine);
						}
						continue;
					}
					SE_Rested val = (SE_Rested)(object)((statusEffect is SE_Rested) ? statusEffect : null);
					if (value6 && (Object)(object)val != (Object)null)
					{
						if (!OrigRestedBase.TryGetValue(statusEffect, out var value19))
						{
							value19 = val.m_baseTTL;
							OrigRestedBase[statusEffect] = value19;
						}
						if (!OrigRestedPerComfort.TryGetValue(statusEffect, out var value20))
						{
							value20 = val.m_TTLPerComfortLevel;
							OrigRestedPerComfort[statusEffect] = value20;
						}
						val.m_baseTTL = value19 * num2;
						val.m_TTLPerComfortLevel = value20 * num2;
						if (!OrigRestTtl.TryGetValue(statusEffect, out var value21))
						{
							value21 = statusEffect.m_ttl;
							OrigRestTtl[statusEffect] = value21;
						}
						statusEffect.m_ttl = value21 * num2;
						num10++;
						if (stringBuilder4.Length < 1500)
						{
							stringBuilder4.AppendFormat("     {0}({1}): 基准 {2:0.#}s -> {3:0.#}s,每级舒适 {4:0.#}s -> {5:0.#}s,当前 {6:0.#}s -> {7:0.#}s{8}", text3, TypeName(statusEffect), value19, val.m_baseTTL, value20, val.m_TTLPerComfortLevel, value21, statusEffect.m_ttl, Environment.NewLine);
						}
						continue;
					}
					SE_Cozy val2 = (SE_Cozy)(object)((statusEffect is SE_Cozy) ? statusEffect : null);
					if (!value7 || !((Object)(object)val2 != (Object)null))
					{
						continue;
					}
					if (!OrigCozyDelay.TryGetValue(statusEffect, out var value22))
					{
						value22 = val2.m_delay;
						OrigCozyDelay[statusEffect] = value22;
					}
					if (Mathf.Abs(value22 - num3) > 0.001f)
					{
						val2.m_delay = num3;
						num11++;
						if (stringBuilder4.Length < 1500)
						{
							stringBuilder4.AppendFormat("     {0}({1}): 「休息好了」等待 {2:0.#}s -> {3:0.#}s{4}", text3, TypeName(statusEffect), value22, num3, Environment.NewLine);
						}
					}
				}
			}
			if (value4 && num9 == 0)
			{
				EasyVitalsPlugin.Log.LogWarning((object)("遗忘之力:没有匹配到任何 GP_ 效果(m_StatusEffects 数量=" + ((db.m_StatusEffects == null) ? (-1) : db.m_StatusEffects.Count) + ")。前几个名字:" + SampleNames(db)));
			}
			if (value7 && num11 == 0)
			{
				EasyVitalsPlugin.Log.LogWarning((object)("休息等待:没有在 ObjectDB 里找到 SE_Cozy 组件。" + DumpAllEffects(db)));
			}
			if (value6 && num10 == 0)
			{
				EasyVitalsPlugin.Log.LogWarning((object)("Rested 时长:没有在 ObjectDB 里找到 SE_Rested 组件。" + DumpAllEffects(db)));
			}
			appliedOnce = true;
			EasyVitalsPlugin.Log.LogInfo((object)$"[{source}] 已处理 {db.m_items.Count} 件物品 → 重量 x{value8}({num4} 件) | 食物时长 x{value9}({num5} 件) | 药水时长 x{value10}({num6} 个效果,跳过冷却 {num7} 个) | 移动惩罚 {value11:P0}({num8} 件)");
			EasyVitalsPlugin.Log.LogInfo((object)$"                → 状态效果:Boss之力 x{num}({num9} 个) | Rested 时长 x{num2}({num10} 个,改基准+每级舒适) | 「休息好了」等待 {num3:0.#}s(SE_Cozy {num11} 个)");
			if (stringBuilder2.Length > 0)
			{
				EasyVitalsPlugin.Log.LogInfo((object)("---- 移动速度惩罚改动明细(前几件)----" + Environment.NewLine + stringBuilder2));
			}
			if (stringBuilder3.Length > 0)
			{
				EasyVitalsPlugin.Log.LogInfo((object)("---- 遗忘之力(Boss power)时长明细 ----" + Environment.NewLine + stringBuilder3));
			}
			if (stringBuilder4.Length > 0)
			{
				EasyVitalsPlugin.Log.LogInfo((object)("---- 休息相关效果明细 ----" + Environment.NewLine + stringBuilder4));
			}
			if (stringBuilder.Length > 0)
			{
				EasyVitalsPlugin.Log.LogInfo((object)("---- 被跳过的药水效果(视为冷却)----" + Environment.NewLine + stringBuilder));
			}
		}

		internal static string StatusEffectName(StatusEffect se)
		{
			string name = ((Object)se).name;
			if (!string.IsNullOrEmpty(name))
			{
				return name;
			}
			return se.m_name ?? string.Empty;
		}

		private static bool NameMatches(StatusEffect se, string key)
		{
			if (!Contains(((Object)se).name, key))
			{
				return Contains(se.m_name, key);
			}
			return true;
		}

		internal static string TypeName(StatusEffect se)
		{
			try
			{
				return ((Object)(object)se == (Object)null) ? "null" : ((object)se).GetType().Name;
			}
			catch
			{
				return "?";
			}
		}

		private static string DumpAllEffects(ObjectDB db)
		{
			if (db.m_StatusEffects == null)
			{
				return "(列表为 null)";
			}
			StringBuilder stringBuilder = new StringBuilder();
			int num = 0;
			foreach (StatusEffect statusEffect in db.m_StatusEffects)
			{
				if (!((Object)(object)statusEffect == (Object)null))
				{
					if (num > 0)
					{
						stringBuilder.Append(" | ");
					}
					stringBuilder.Append(StatusEffectName(statusEffect)).Append('(').Append(TypeName(statusEffect))
						.Append(')');
					num++;
				}
			}
			return "共 " + num + " 个:" + stringBuilder;
		}

		private static bool Contains(string haystack, string needle)
		{
			if (!string.IsNullOrEmpty(haystack))
			{
				return haystack.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		private static string SampleNames(ObjectDB db)
		{
			if (db.m_StatusEffects == null)
			{
				return "(列表为 null)";
			}
			StringBuilder stringBuilder = new StringBuilder();
			int num = 0;
			foreach (StatusEffect statusEffect in db.m_StatusEffects)
			{
				if (!((Object)(object)statusEffect == (Object)null))
				{
					if (num >= 12)
					{
						stringBuilder.Append(" …");
						break;
					}
					num++;
					stringBuilder.Append(StatusEffectName(statusEffect)).Append(", ");
				}
			}
			if (stringBuilder.Length <= 0)
			{
				return "(空)";
			}
			return stringBuilder.ToString();
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	internal static class ObjectDbAwakePatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			ObjectDbApplier.ApplyIfReady("ObjectDB.Awake");
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class ZNetSceneAwakePatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			ObjectDbApplier.ApplyIfReady("ZNetScene.Awake");
		}
	}
	[HarmonyPatch(typeof(Minimap), "Explore", new Type[]
	{
		typeof(Vector3),
		typeof(float)
	})]
	internal static class MinimapExplorePatch
	{
		[HarmonyPrefix]
		private static void Prefix(ref float radius)
		{
			try
			{
				if (EasyVitalsPlugin.MapEnabled.Value)
				{
					radius *= EasyVitalsPlugin.MapExploreMultiplier.Value;
				}
			}
			catch (Exception ex)
			{
				EasyVitalsPlugin.Log.LogError((object)("地图探索倍率失败:" + ex));
			}
		}
	}
	[HarmonyPatch(typeof(Player), "GetTotalFoodValue")]
	internal static class PlayerGetTotalFoodValuePatch
	{
		[HarmonyPostfix]
		private static void Postfix(Player __instance, ref float hp, ref float stamina, ref float eitr)
		{
			FoodFullEffect.Apply(__instance, ref hp, ref stamina, ref eitr);
		}
	}
}