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("EasyGear")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.3.0")] [assembly: AssemblyInformationalVersion("1.0.3")] [assembly: AssemblyProduct("EasyGear")] [assembly: AssemblyTitle("EasyGear")] [assembly: AssemblyVersion("1.0.3.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 EasyGear { [HarmonyPatch(typeof(Player), "DamageArmorDurability", new Type[] { typeof(HitData) })] internal static class PlayerDamageArmorDurabilityPatch { private static readonly FieldInfo F_Chest = AccessTools.Field(typeof(Humanoid), "m_chestItem"); private static readonly FieldInfo F_Leg = AccessTools.Field(typeof(Humanoid), "m_legItem"); private static readonly FieldInfo F_Helmet = AccessTools.Field(typeof(Humanoid), "m_helmetItem"); private static readonly FieldInfo F_Shoulder = AccessTools.Field(typeof(Humanoid), "m_shoulderItem"); private static bool reported; internal static bool FieldsResolved { get { if (F_Chest != null && F_Leg != null && F_Helmet != null) { return F_Shoulder != null; } return false; } } private static float mult0 => Mathf.Max(0.01f, EasyGearPlugin.DurabilityLifetimeMultiplier.Value); private static bool Active() { if (!EasyGearPlugin.DurabilityEnabled.Value) { return false; } string value = EasyGearPlugin.DurabilityMode.Value; if (!(value == "LossReduction") && !(value == "Both")) { return false; } return EasyGearPlugin.DurabilityLifetimeMultiplier.Value > 1.0001f; } [HarmonyPrefix] private static void Prefix(Player __instance, out float[] __state) { __state = null; if (!((Object)(object)__instance == (Object)null) && Active() && FieldsResolved && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { __state = new float[4] { DurabilityOf(__instance, F_Chest), DurabilityOf(__instance, F_Leg), DurabilityOf(__instance, F_Helmet), DurabilityOf(__instance, F_Shoulder) }; } } [HarmonyPostfix] private static void Postfix(Player __instance, HitData hit, float[] __state) { if (__state != null && !((Object)(object)__instance == (Object)null) && hit != null) { float num = hit.GetTotalPhysicalDamage() + hit.GetTotalElementalDamage(); if (!(num <= 0f)) { float num2 = Mathf.Max(0.01f, EasyGearPlugin.DurabilityLifetimeMultiplier.Value); float cost = num / num2; Correct(__instance, F_Chest, __state[0], cost); Correct(__instance, F_Leg, __state[1], cost); Correct(__instance, F_Helmet, __state[2], cost); Correct(__instance, F_Shoulder, __state[3], cost); } } } private static ItemData ItemAt(Player p, FieldInfo f) { if (f == null) { return null; } try { object? value = f.GetValue(p); return (ItemData)((value is ItemData) ? value : null); } catch { return null; } } private static float DurabilityOf(Player p, FieldInfo f) { return ItemAt(p, f)?.m_durability ?? float.NaN; } private static void Correct(Player p, FieldInfo f, float before, float cost) { if (float.IsNaN(before)) { return; } ItemData val = ItemAt(p, f); if (val == null || val.m_durability >= before - 0.0001f) { return; } float num = Mathf.Max(0f, before - cost); if (!(num <= val.m_durability + 0.0001f)) { val.m_durability = num; if (!reported) { reported = true; EasyGearPlugin.Log.LogInfo((object)string.Format("护甲耐久倍率已生效(LossReduction ÷{0:0.##}):{1} 受击伤害 {2:0.##} → 应扣 {3:0.##}(耐久 {4:0.##} → {5:0.##})", mult0, (val.m_shared != null) ? val.m_shared.m_name : "(?)", cost * mult0, cost, before, num)); } } } } internal static class AutoRepair { private static MethodInfo miCanRepair; private static MethodInfo miUpdateRepair; private static MethodInfo miMessage; private static MethodInfo miRaiseSkill; private static MethodInfo miLocalize; private static Type messageTypeEnum; private static Type skillTypeEnum; private const int VanillaRepairSkillValue = 107; private static bool running; internal static void Init() { Type typeFromHandle = typeof(InventoryGui); miCanRepair = AccessTools.Method(typeFromHandle, "CanRepair", new Type[1] { typeof(ItemData) }, (Type[])null); miUpdateRepair = AccessTools.Method(typeFromHandle, "UpdateRepair", (Type[])null, (Type[])null); if (miCanRepair == null) { EasyGearPlugin.Log.LogError((object)"找不到 InventoryGui.CanRepair —— 自动修理无法生效(游戏版本可能已变更,请反馈)。"); } miMessage = FindMethod(typeof(Character), "Message", 5); if (miMessage != null) { messageTypeEnum = miMessage.GetParameters()[0].ParameterType; } miRaiseSkill = FindMethod(typeof(Character), "RaiseSkill", 2); if (miRaiseSkill != null) { skillTypeEnum = miRaiseSkill.GetParameters()[0].ParameterType; } miLocalize = AccessTools.Method(typeof(Localization), "Localize", new Type[1] { typeof(string) }, (Type[])null); } private static MethodInfo FindMethod(Type type, string name, int paramCount) { try { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); for (int i = 0; i < methods.Length; i++) { if (methods[i].Name == name && methods[i].GetParameters().Length == paramCount) { return methods[i]; } } } catch (Exception ex) { EasyGearPlugin.Log.LogWarning((object)("查找 " + type.Name + "." + name + " 失败:" + ex.Message)); } return null; } private static bool CanRepair(InventoryGui gui, ItemData item) { if (miCanRepair == null || (Object)(object)gui == (Object)null || item == null) { return false; } try { object obj = miCanRepair.Invoke(gui, new object[1] { item }); return obj is bool && (bool)obj; } catch (Exception ex) { EasyGearPlugin.Log.LogError((object)("调用 InventoryGui.CanRepair 失败:" + ex.Message)); return false; } } private static bool IsDamaged(ItemData item) { if (item == null) { return false; } float maxDurability = item.GetMaxDurability(); if (maxDurability > 0f) { return item.m_durability < maxDurability - 0.001f; } return false; } internal static int Begin(InventoryGui gui, bool includeBackpack, int intervalMs) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return 0; } CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation(); if ((Object)(object)currentCraftingStation == (Object)null) { return 0; } if (!currentCraftingStation.CheckUsable(localPlayer, false)) { return 0; } Inventory inventory = ((Humanoid)localPlayer).GetInventory(); if (inventory == null) { return 0; } List allItems = inventory.GetAllItems(); if (allItems == null || allItems.Count == 0) { return 0; } List list = new List(); try { inventory.GetWornItems(list); } catch (Exception ex) { EasyGearPlugin.Log.LogWarning((object)("取「穿戴中的物品」失败,本次按全部物品处理:" + ex.Message)); } List list2 = new List(); for (int i = 0; i < allItems.Count; i++) { ItemData item = allItems[i]; if (IsDamaged(item) && CanRepair(gui, item) && (list.Contains(item) || includeBackpack)) { list2.Add(item); } } if (list2.Count == 0) { return 0; } if (intervalMs <= 0 || (Object)(object)EasyGearPlugin.Instance == (Object)null) { int num = RepairAll(list2, currentCraftingStation, list); running = false; Finish(currentCraftingStation, num, 0); return num; } if (running) { return 0; } running = true; ((MonoBehaviour)EasyGearPlugin.Instance).StartCoroutine(RepairSequence(list2, currentCraftingStation, list, intervalMs)); return list2.Count; } private static IEnumerator RepairSequence(List todo, CraftingStation station, List worn, int intervalMs) { float wait = Mathf.Max(0.01f, (float)intervalMs / 1000f); int done = 0; int aborted = 0; for (int i = 0; i < todo.Count; i++) { ItemData val = todo[i]; if (val != null) { Player localPlayer = Player.m_localPlayer; CraftingStation val2 = (((Object)(object)localPlayer == (Object)null) ? null : localPlayer.GetCurrentCraftingStation()); if ((Object)(object)localPlayer == (Object)null || (Object)(object)val2 != (Object)(object)station || !station.CheckUsable(localPlayer, false)) { aborted = todo.Count - i; break; } try { RepairOne(localPlayer, val, station, worn.Contains(val)); done++; } catch (Exception ex) { EasyGearPlugin.Log.LogError((object)("自动修理某件物品时出错(继续修下一件):" + ex.Message)); } if (i < todo.Count - 1) { yield return (object)new WaitForSecondsRealtime(wait); } } } running = false; Finish(station, done, aborted); } private static int RepairAll(List todo, CraftingStation station, List worn) { int num = 0; for (int i = 0; i < todo.Count; i++) { try { if (todo[i] != null) { RepairOne(Player.m_localPlayer, todo[i], station, worn.Contains(todo[i])); num++; } } catch (Exception ex) { EasyGearPlugin.Log.LogError((object)("自动修理某件物品时出错:" + ex.Message)); } } return num; } private static void RepairOne(Player player, ItemData item, CraftingStation station, bool announce) { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) float maxDurability = item.GetMaxDurability(); if (maxDurability <= 0f) { return; } if (miRaiseSkill != null && skillTypeEnum != null) { try { miRaiseSkill.Invoke(player, new object[2] { Enum.ToObject(skillTypeEnum, 107), 1f - item.m_durability / maxDurability }); } catch (Exception ex) { EasyGearPlugin.Log.LogWarning((object)("加修理熟练度失败(不影响修理):" + ex.Message)); } } item.m_durability = maxDurability; if ((Object)(object)station != (Object)null && station.m_repairItemDoneEffects != null && (Object)(object)((Component)station).transform != (Object)null) { try { station.m_repairItemDoneEffects.Create(((Component)station).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); } catch (Exception ex2) { EasyGearPlugin.Log.LogWarning((object)("播放修理特效失败(不影响修理本身):" + ex2.Message)); } } if (announce) { ShowMessage("已修复 " + LocalizeName(item)); } } private static string LocalizeName(ItemData item) { string text = ((item.m_shared == null) ? null : item.m_shared.m_name); if (string.IsNullOrEmpty(text)) { if (!((Object)(object)item.m_dropPrefab != (Object)null)) { return "物品"; } return ((Object)item.m_dropPrefab).name; } if (miLocalize != null) { try { object obj = miLocalize.Invoke(Localization.instance, new object[1] { text }); if (obj is string && !string.IsNullOrEmpty((string)obj)) { return (string)obj; } } catch { } } return text; } private static void Finish(CraftingStation station, int done, int aborted) { string text = (((Object)(object)station == (Object)null) ? "?" : station.m_name); if (aborted > 0) { EasyGearPlugin.Log.LogInfo((object)$"自动修理:「{text}」修好 {done} 件后中断(还剩 {aborted} 件没修)—— 你离开了站点或站点失效。"); } else if (done > 0) { EasyGearPlugin.Log.LogInfo((object)$"自动修理:「{text}」修好 {done} 件(逐件间隔 {EasyGearPlugin.AutoRepairIntervalMs.Value}ms)。"); } if (done > 0 && EasyGearPlugin.AutoRepairShowMessage.Value) { ShowMessage($"自动修理:{done} 件({text})"); } try { InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance != (Object)null && miUpdateRepair != null) { miUpdateRepair.Invoke(instance, null); } } catch (Exception ex) { EasyGearPlugin.Log.LogWarning((object)("刷新修理面板失败(不影响已修好的物品):" + ex.Message)); } } internal static void ShowMessage(string text) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || miMessage == null || messageTypeEnum == null) { return; } try { miMessage.Invoke(localPlayer, new object[5] { Enum.ToObject(messageTypeEnum, 2), text, 0, null, false }); } catch (Exception ex) { EasyGearPlugin.Log.LogWarning((object)("显示提示失败(不影响修理):" + ex.Message)); } } } [BepInPlugin("easygear.client.only", "EasyGear", "1.0.3")] public class EasyGearPlugin : BaseUnityPlugin { public const string Guid = "easygear.client.only"; public const string PluginName = "EasyGear"; public const string PluginVersion = "1.0.3"; internal static ManualLogSource Log; internal static EasyGearPlugin Instance; internal static ConfigEntry DurabilityEnabled; internal static ConfigEntry DurabilityMode; internal static ConfigEntry DurabilityLifetimeMultiplier; internal static ConfigEntry AreaRepairEnabled; internal static ConfigEntry AreaRepairRadius; internal static ConfigEntry AreaRepairVerbose; internal static ConfigEntry AutoRepairEnabled; internal static ConfigEntry AutoRepairIncludeBackpack; internal static ConfigEntry AutoRepairIntervalMs; internal static ConfigEntry AutoRepairShowMessage; internal static ConfigEntry AutoRepairVerbose; internal static ConfigEntry EquipWhileRunningEnabled; private Harmony harmony; private void Awake() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Expected O, but got Unknown //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Instance = this; DurabilityEnabled = ((BaseUnityPlugin)this).Config.Bind("1 - Item Durability", "Enabled", true, "耐久修改开关。覆盖武器、工具、弓箭、盾牌、护甲、锤子、锄头等。"); DurabilityMode = ((BaseUnityPlugin)this).Config.Bind("1 - Item Durability", "Mode", "LossReduction", new ConfigDescription("耐久的实现方式:\n LossReduction = 耐久消耗 ÷ 倍率。装备明显更耐用,但物品提示里的耐久数字下降很慢,不容易一眼看出。\n MaxDurability = 耐久上限 × 倍率。物品提示里的上限直接变成 5 倍,一眼可见。\n 注意:已有的装备需要先用锤子修一次才会满。\n Both = 两者都做(寿命约 ×25,慎用)。", (AcceptableValueBase)(object)new AcceptableValueList(new string[3] { "LossReduction", "MaxDurability", "Both" }), Array.Empty())); DurabilityLifetimeMultiplier = ((BaseUnityPlugin)this).Config.Bind("1 - Item Durability", "LifetimeMultiplier", 5f, new ConfigDescription("耐久倍率:5 = 同样的装备能用 5 倍久。", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 100f), Array.Empty())); AreaRepairEnabled = ((BaseUnityPlugin)this).Config.Bind("2 - Area Repair", "Enabled", true, "锤子「范围修理」开关:用锤子的普通修理动作时,顺带修理附近的建筑部件。"); AreaRepairRadius = ((BaseUnityPlugin)this).Config.Bind("2 - Area Repair", "Radius", 30f, new ConfigDescription("范围修理半径(米),以你鼠标指向的那个部件为中心。默认 30 米。", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 100f), Array.Empty())); AreaRepairVerbose = ((BaseUnityPlugin)this).Config.Bind("2 - Area Repair", "Verbose", true, "打开后在日志里逐次记录修好了几个部件(排查用)。"); AutoRepairEnabled = ((BaseUnityPlugin)this).Config.Bind("3 - Auto Repair At Station", "Enabled", true, "打开工作台 / 熔炉(制造站)时,自动把身上受损的装备、工具、武器修满。\n身上穿戴的那批走的是游戏原版的修理函数,所以涨熟练度、修理特效、\n「已修复 xxx」提示都与手动点修理按钮完全一致;修理不消耗材料(原版修理本来就免费)。"); AutoRepairIncludeBackpack = ((BaseUnityPlugin)this).Config.Bind("3 - Auto Repair At Station", "IncludeBackpackItems", true, "顺便修理背包里【没穿戴】的装备/工具/武器。\ntrue(默认)= 背包里的也一起修好;false = 只修身上穿戴的(= 原版修理按钮的范围)。\n注意:原版修理按钮只修身上穿戴的,背包那批是本模组额外补的。"); AutoRepairIntervalMs = ((BaseUnityPlugin)this).Config.Bind("3 - Auto Repair At Station", "IntervalMilliseconds", 150, new ConfigDescription("逐件修理的间隔(毫秒)。装备多的时候一件件修,能看清耐久条一根根回满。\n0 = 一次性全部修好(原来的行为,会一瞬间全满)。建议 100 - 200。", (AcceptableValueBase)(object)new AcceptableValueRange(0, 2000), Array.Empty())); AutoRepairShowMessage = ((BaseUnityPlugin)this).Config.Bind("3 - Auto Repair At Station", "ShowMessage", false, "在屏幕上再显示一行「自动修理:N 件(站点名)」。\n默认关闭 —— 原版本来就对每件修好的物品各弹一条「已修复 xxx」,够看了。"); AutoRepairVerbose = ((BaseUnityPlugin)this).Config.Bind("3 - Auto Repair At Station", "Verbose", false, "排查用:即使本次没有物品需要修理,也在日志里记一行(确认模组确实触发了)。"); EquipWhileRunningEnabled = ((BaseUnityPlugin)this).Config.Bind("4 - Equip While Running", "Enabled", true, "跑步时也能切换武器 / 工具(解除原版限制)。\n原版在奔跑时会每帧清空「装备动作队列」,导致带抽拿动画的武器/工具\n按数字键后动作被取消、看起来完全没反应。\n打开(默认)后:跑步中也能正常拿出/收回。\n⚠\ufe0f 只拦「跑步」发起的取消 —— 攻击、跳跃、翻滚时的取消保持原版行为。"); Log.LogInfo((object)"EasyGear 1.0.3 开始挂载 Harmony 补丁……"); AutoRepair.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("easygear.client.only"); Type[] array = new Type[7] { typeof(ObjectDbAwakePatch), typeof(ZNetSceneAwakePatch), typeof(PlayerRepairPatch), typeof(InventoryGuiShowPatch), typeof(PlayerCheckRunPatch), typeof(ClearActionQueuePatch), typeof(PlayerDamageArmorDurabilityPatch) }; 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 list = new List(); AddTarget(list, AccessTools.Method(typeof(ObjectDB), "Awake", (Type[])null, (Type[])null), "ObjectDB.Awake(耐久改写入口)"); AddTarget(list, AccessTools.Method(typeof(ZNetScene), "Awake", (Type[])null, (Type[])null), "ZNetScene.Awake(耐久改写兜底)"); AddTarget(list, AccessTools.Method(typeof(Player), "Repair", (Type[])null, (Type[])null), "Player.Repair(范围修理)"); AddTarget(list, AccessTools.Method(typeof(InventoryGui), "Show", new Type[2] { typeof(Container), typeof(int) }, (Type[])null), "InventoryGui.Show(Container,int)(进站自动修理)"); AddTarget(list, AccessTools.Method(typeof(Player), "CheckRun", new Type[2] { typeof(Vector3), typeof(float) }, (Type[])null), "Player.CheckRun(Vector3,float)(跑步可切换装备·标记)"); AddTarget(list, AccessTools.Method(typeof(Humanoid), "ClearActionQueue", (Type[])null, (Type[])null), "Humanoid.ClearActionQueue(跑步可切换装备·拦截)"); MethodBase methodBase = AccessTools.Method(typeof(Player), "DamageArmorDurability", new Type[1] { typeof(HitData) }, (Type[])null); AddTarget(list, methodBase, "Player.DamageArmorDurability(HitData)(护甲耐久倍率)"); if (methodBase != null && methodBase.DeclaringType != typeof(Player)) { Log.LogError((object)(" !! DamageArmorDurability 解析到了 " + methodBase.DeclaringType.Name + ",而不是 Player 的重写 —— 护甲倍率可能不会生效")); } if (!PlayerDamageArmorDurabilityPatch.FieldsResolved) { Log.LogError((object)" !! 反射不到护甲槽位字段(m_chestItem/m_legItem/m_helmetItem/m_shoulderItem) —— 护甲耐久倍率不会生效"); } 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)$" (目标方法 {list.Count} 个,全部已核对)"); Log.LogInfo((object)"-----------------------"); } private static void AddTarget(List targets, MethodBase m, string label) { if (m == null) { Log.LogError((object)(" !! 找不到目标方法,对应功能不会生效:" + label)); } else { targets.Add(m); } } private void OnDestroy() { if (harmony != null) { harmony.UnpatchSelf(); } } } internal static class ObjectDbApplier { private static readonly Dictionary OrigDurabilityDrain = new Dictionary(); private static readonly Dictionary OrigMaxDurability = new Dictionary(); 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) { EasyGearPlugin.Log.LogWarning((object)("[" + source + "] ObjectDB 还没就绪,稍后重试。")); } else if (instance.m_items == null) { EasyGearPlugin.Log.LogWarning((object)("[" + source + "] ObjectDB.m_items 为 null,跳过。")); } else { Apply(instance, source); } } catch (Exception ex) { EasyGearPlugin.Log.LogError((object)("[" + source + "] 应用失败(游戏本身不受影响):" + ex)); } } private static void Apply(ObjectDB db, string source) { bool value = EasyGearPlugin.DurabilityEnabled.Value; float num = Mathf.Max(0.01f, EasyGearPlugin.DurabilityLifetimeMultiplier.Value); string value2 = EasyGearPlugin.DurabilityMode.Value; bool flag = value2 == "LossReduction" || value2 == "Both"; bool flag2 = value2 == "MaxDurability" || value2 == "Both"; int num2 = 0; int num3 = 0; StringBuilder stringBuilder = new StringBuilder(); foreach (GameObject item in db.m_items) { if ((Object)(object)item == (Object)null) { continue; } ItemDrop component = item.GetComponent(); if ((Object)(object)component == (Object)null || component.m_itemData == null) { continue; } SharedData shared = component.m_itemData.m_shared; if (shared == null || !value || !shared.m_useDurability) { continue; } if (flag && shared.m_useDurabilityDrain > 0f) { if (!OrigDurabilityDrain.TryGetValue(shared, out var value3)) { value3 = shared.m_useDurabilityDrain; OrigDurabilityDrain[shared] = value3; } float num4 = (shared.m_useDurabilityDrain = value3 / num); num2++; if (stringBuilder.Length < 1200) { stringBuilder.AppendFormat(" {0}: 每次消耗 {1:0.####} -> {2:0.####}{3}", shared.m_name, value3, num4, Environment.NewLine); } } if (flag2 && shared.m_maxDurability > 0f) { if (!OrigMaxDurability.TryGetValue(shared, out var value4)) { value4 = shared.m_maxDurability; OrigMaxDurability[shared] = value4; } shared.m_maxDurability = value4 * num; num3++; } } appliedOnce = true; string text = ((value2 == "Both") ? string.Format("消耗 ÷{0}({1} 件) + 上限 ×{0}({2} 件)", num, num2, num3) : ((!(value2 == "MaxDurability")) ? $"消耗 ÷{num}({num2} 件)" : $"上限 ×{num}({num3} 件)")); if (!value) { text = "已关闭(Enabled=false)"; } EasyGearPlugin.Log.LogInfo((object)$"[{source}] 已处理 {db.m_items.Count} 件物品 → 耐久 {value2}:{text}"); if (stringBuilder.Length > 0) { EasyGearPlugin.Log.LogInfo((object)("---- 耐久改动明细(前几件)----" + Environment.NewLine + stringBuilder)); } } } [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(Player), "Repair")] internal static class PlayerRepairPatch { private static bool repairing; [HarmonyPostfix] private static void Postfix(Player __instance) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) if (repairing || !EasyGearPlugin.AreaRepairEnabled.Value) { return; } try { if ((Object)(object)__instance == (Object)null) { return; } Piece hoveringPiece = __instance.GetHoveringPiece(); if ((Object)(object)hoveringPiece == (Object)null || (Object)(object)((Component)hoveringPiece).transform == (Object)null) { return; } Vector3 position = ((Component)hoveringPiece).transform.position; float value = EasyGearPlugin.AreaRepairRadius.Value; float num = value * value; List allInstances = WearNTear.GetAllInstances(); if (allInstances == null || allInstances.Count == 0) { return; } repairing = true; int num2 = 0; for (int i = 0; i < allInstances.Count; i++) { WearNTear val = allInstances[i]; if ((Object)(object)val == (Object)null) { continue; } Transform transform = ((Component)val).transform; if (!((Object)(object)transform == (Object)null)) { Vector3 val2 = transform.position - position; if (!(((Vector3)(ref val2)).sqrMagnitude > num) && val.Repair()) { num2++; } } } repairing = false; if (num2 > 0 && EasyGearPlugin.AreaRepairVerbose.Value) { EasyGearPlugin.Log.LogInfo((object)$"范围修理(半径 {value} 米):额外修好 {num2} 个部件。"); } } catch (Exception ex) { repairing = false; EasyGearPlugin.Log.LogError((object)("范围修理失败(普通修理不受影响):" + ex)); } } } [HarmonyPatch(typeof(InventoryGui), "Show", new Type[] { typeof(Container), typeof(int) })] internal static class InventoryGuiShowPatch { private static bool wasVisible; [HarmonyPrefix] private static void Prefix() { try { wasVisible = InventoryGui.IsVisible(); } catch { wasVisible = false; } } [HarmonyPostfix] private static void Postfix(InventoryGui __instance, int activeGroup) { try { if (!wasVisible && activeGroup == 3 && EasyGearPlugin.AutoRepairEnabled.Value && AutoRepair.Begin(__instance, EasyGearPlugin.AutoRepairIncludeBackpack.Value, EasyGearPlugin.AutoRepairIntervalMs.Value) <= 0 && EasyGearPlugin.AutoRepairVerbose.Value) { EasyGearPlugin.Log.LogInfo((object)"自动修理:在制造站触发过检查,本次没有需要修理的物品(或人已不在站点旁)。"); } } catch (Exception ex) { EasyGearPlugin.Log.LogError((object)("自动修理失败(不影响正常游戏):" + ex)); } } } [HarmonyPatch(typeof(Player), "CheckRun", new Type[] { typeof(Vector3), typeof(float) })] internal static class PlayerCheckRunPatch { internal static bool InCheckRun; [HarmonyPrefix] private static void Prefix() { InCheckRun = true; } [HarmonyPostfix] private static void Postfix() { InCheckRun = false; } } [HarmonyPatch(typeof(Humanoid), "ClearActionQueue")] internal static class ClearActionQueuePatch { [HarmonyPrefix] private static bool Prefix(Humanoid __instance) { try { if (!EasyGearPlugin.EquipWhileRunningEnabled.Value) { return true; } if (!PlayerCheckRunPatch.InCheckRun) { return true; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if ((Object)(object)val == (Object)null || !((Character)val).IsRunning()) { return true; } return false; } catch (Exception ex) { EasyGearPlugin.Log.LogWarning((object)("跑步可切换装备:判定出错,本次交给原版处理:" + ex.Message)); return true; } } } }