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.Security; using System.Security.Permissions; using HarmonyLib; using Il2Cpp; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppKeepsake; using Il2CppKeepsake.GeneratedItems; using Il2CppKeepsake.HyperSpace.System.Modifiers.ItemModule; using Il2CppKeepsake.Modifiers; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using JumpSpaceChainLinkFix; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(ChainLinkFixPlugin), "Jump Space ChainLink Fix", "1.0.0", "ChainLinkFix", null)] [assembly: MelonGame("Keepsake Games", "Jump Space")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("ChainLinkFix Author")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Jump Space 链式连接模块修复插件 - 修复舰载武器上链式连接显示空白、不生效、0伤害问题")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Jump Space ChainLink Fix")] [assembly: AssemblyTitle("JumpSpaceChainLinkFix")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [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 JumpSpaceChainLinkFix { public class ChainLinkFixPlugin : MelonMod { internal static MelonPreferences_Entry EnableMod; internal static MelonPreferences_Entry ChainRadius; internal static MelonPreferences_Entry EnableDebugLogging; private bool _patchesApplied; private bool _dataFixed; public override void OnInitializeMelon() { MelonPreferences_Category obj = MelonPreferences.CreateCategory("ChainLinkFix", "链式连接修复"); EnableMod = obj.CreateEntry("Enable", true, "启用修复", (string)null, false, false, (ValueValidator)null, (string)null); ChainRadius = obj.CreateEntry("ChainRadius", 20f, "链式伤害搜索半径(米)", (string)null, false, false, (ValueValidator)null, (string)null); EnableDebugLogging = obj.CreateEntry("Debug", true, "启用调试日志", (string)null, false, false, (ValueValidator)null, (string)null); ((MelonBase)this).LoggerInstance.Msg("[ChainLinkFix] 插件已初始化"); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { if (!_patchesApplied) { _patchesApplied = true; ApplyPatches(); } if (!_dataFixed && EnableMod.Value) { MelonCoroutines.Start(DelayedDataFix()); } } private IEnumerator DelayedDataFix() { yield return (object)new WaitForSeconds(3f); FixChainLinkData(); } private void FixChainLinkData() { //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Expected O, but got Unknown if (_dataFixed) { return; } try { Type val = Il2CppType.From(typeof(ItemModuleScriptable)); if (val == (Type)null) { ((MelonBase)this).LoggerInstance.Warning("[ChainLinkFix] 无法获取ItemModuleScriptable的Il2Cpp类型"); return; } Il2CppReferenceArray val2 = Resources.FindObjectsOfTypeAll(val); if (val2 == null || ((Il2CppArrayBase)(object)val2).Length == 0) { ((MelonBase)this).LoggerInstance.Warning("[ChainLinkFix] 未找到任何ItemModuleScriptable对象"); return; } ((MelonBase)this).LoggerInstance.Msg($"[ChainLinkFix] 扫描 {((Il2CppArrayBase)(object)val2).Length} 个ItemModuleScriptable对象..."); int fixedCount = 0; for (int i = 0; i < ((Il2CppArrayBase)(object)val2).Length; i++) { Object val3 = ((Il2CppArrayBase)(object)val2)[i]; if (val3 == (Object)null) { continue; } ItemModuleScriptable val4 = ((Il2CppObjectBase)val3).TryCast(); if ((Object)(object)val4 == (Object)null) { continue; } string text = ""; string text2 = ""; try { text = ((Object)val4).name ?? ""; } catch { } try { text2 = ((GameplayModifierScriptable)val4).m_AssetGUID ?? ""; } catch { } bool flag = text2.Contains("ChainLink_Ship") || text.Contains("ChainLink_Ship"); if (!flag && (text2.Contains("ChainLink") || text.Contains("ChainLink"))) { ((MelonBase)this).LoggerInstance.Msg("[ChainLinkFix] 找到ChainLink(步战版): name=" + text + ", guid=" + text2); FixBouncesPerUpgrade(val4.m_TweakableValues_Epic, "Epic", text, ref fixedCount); FixBouncesPerUpgrade(val4.m_TweakableValues_Legendary, "Legendary", text, ref fixedCount); } else { if (!flag) { continue; } ((MelonBase)this).LoggerInstance.Msg("[ChainLinkFix] 找到ChainLink_Ship: name=" + text + ", guid=" + text2); List tweakableValues_Legendary = val4.m_TweakableValues_Legendary; int num = 0; try { num = tweakableValues_Legendary?.Count ?? 0; } catch { } ((MelonBase)this).LoggerInstance.Msg($"[ChainLinkFix] ChainLink_Ship Legendary TweakableValues数量: {num}"); if (tweakableValues_Legendary != null && num < 3) { ItemModuleTweakableValue val5 = new ItemModuleTweakableValue(); val5.m_Name = "Chance to chain"; val5.m_BaseValueMin = 1f; val5.m_BaseValueMax = 1f; val5.m_ValuePerUpgrade = 0f; val5.m_ValueIndex = 2; val5.m_RoundToNearest = 0f; tweakableValues_Legendary.Add(val5); fixedCount++; ((MelonBase)this).LoggerInstance.Msg($"[ChainLinkFix] ✓ 数据修复成功! ChainLink_Ship Legendary TweakableValues: {num} → {tweakableValues_Legendary.Count}"); try { for (int j = 0; j < tweakableValues_Legendary.Count; j++) { ItemModuleTweakableValue val6 = tweakableValues_Legendary[j]; ((MelonBase)this).LoggerInstance.Msg($"[ChainLinkFix] [{j}] {val6.m_Name}: {val6.m_BaseValueMin}~{val6.m_BaseValueMax} (+{val6.m_ValuePerUpgrade}/级) Index={val6.m_ValueIndex}"); } } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Warning("[ChainLinkFix] 验证修复结果异常: " + ex.Message); } } else if (num >= 3) { ((MelonBase)this).LoggerInstance.Msg($"[ChainLinkFix] ChainLink_Ship Legendary已有{num}个值,无需修复"); } } } if (fixedCount > 0) { _dataFixed = true; ((MelonBase)this).LoggerInstance.Msg($"[ChainLinkFix] === 数据修复完成: 修复了{fixedCount}个ChainLink实例 ==="); } } catch (Exception ex2) { ((MelonBase)this).LoggerInstance.Error("[ChainLinkFix] 数据修复异常: " + ex2.Message + "\n" + ex2.StackTrace); } } private void FixBouncesPerUpgrade(List values, string rarityName, string moduleName, ref int fixedCount) { if (values == null) { return; } int num = 0; try { num = values.Count; } catch { return; } for (int i = 0; i < num; i++) { ItemModuleTweakableValue val = values[i]; if (val.m_Name != null && val.m_Name.Contains("bounces") && val.m_ValuePerUpgrade == 0f) { ((MelonBase)this).LoggerInstance.Msg($"[ChainLinkFix] {moduleName} {rarityName} [{i}] {val.m_Name}: ValuePerUpgrade 0.00 → 1.00"); val.m_ValuePerUpgrade = 1f; values[i] = val; fixedCount++; } } } private void ApplyPatches() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown if (!EnableMod.Value) { ((MelonBase)this).LoggerInstance.Warning("[ChainLinkFix] 修复已禁用,跳过补丁"); return; } TryPatch("Il2CppKeepsake.HyperSpace.System.Modifiers.ItemModule.ItemModuleScriptable", "GetLocalizedDescription", null, new HarmonyMethod(typeof(ChainLinkDescriptionPatch), "Postfix", (Type[])null)); TryPatch("Il2Cpp.DamageComponent_Base", "ReceiveDamage", null, new HarmonyMethod(typeof(ChainLinkLogicPatch), "Postfix", (Type[])null)); TryPatch("Il2CppKeepsake.GameplayModifier", "TweakableGetter", new HarmonyMethod(typeof(ChainLinkSafetyPatch), "Prefix", (Type[])null)); TryPatch("Il2Cpp.DamageComponent_Base", "GetOverlappingDamageComponents", new HarmonyMethod(typeof(ChainLinkRadiusDiagnostic), "Prefix", (Type[])null)); ((MelonBase)this).LoggerInstance.Msg("[ChainLinkFix] === 补丁应用完成 ==="); } private void TryPatch(string typeName, string methodName, HarmonyMethod prefix = null, HarmonyMethod postfix = null) { try { Type type = AccessTools.TypeByName(typeName); if (type == null) { ((MelonBase)this).LoggerInstance.Warning("[ChainLinkFix] 未找到类型: " + typeName + ",跳过补丁"); return; } MethodInfo methodInfo = AccessTools.Method(type, methodName, (Type[])null, (Type[])null); if (methodInfo == null) { ((MelonBase)this).LoggerInstance.Warning($"[ChainLinkFix] 未找到方法: {typeName}.{methodName},跳过补丁"); } else { ((MelonBase)this).HarmonyInstance.Patch((MethodBase)methodInfo, prefix, postfix, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[ChainLinkFix] ✓ 已补丁: " + typeName + "." + methodName); } } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error($"[ChainLinkFix] ✗ 补丁失败: {typeName}.{methodName} - {ex.Message}"); } } internal static void LogDebug(string message) { if (EnableDebugLogging.Value) { MelonLogger.Msg("[ChainLinkFix] " + message); } } } public static class ChainLinkDescriptionPatch { private static readonly HashSet _reportedBlank = new HashSet(); public static void Postfix(ItemModuleScriptable __instance, ItemRarity rarity, int upgradeLevel, ref string __result) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null) { return; } string text = ""; string text2 = ""; try { text = ((Object)__instance).name ?? ""; } catch { } try { text2 = ((GameplayModifierScriptable)__instance).m_AssetGUID ?? ""; } catch { } if ((!text2.Contains("ChainLink_Ship") && !text.Contains("ChainLink_Ship")) || !string.IsNullOrEmpty(__result)) { return; } int instanceID = ((Object)__instance).GetInstanceID(); if (!_reportedBlank.Contains(instanceID)) { _reportedBlank.Add(instanceID); ChainLinkFixPlugin.LogDebug($"描述修复: ChainLink_Ship描述为空, rarity={rarity}, upgradeLevel={upgradeLevel}"); } List tweakableValues_Legendary = __instance.m_TweakableValues_Legendary; if (tweakableValues_Legendary == null || tweakableValues_Legendary.Count < 2) { __result = "命中时有 100% 的概率连锁至附近的敌人,造成原始伤害的 75%"; ChainLinkFixPlugin.LogDebug("描述修复: 使用默认描述(数据不足)"); return; } float baseValueMin = tweakableValues_Legendary[0].m_BaseValueMin; _ = tweakableValues_Legendary[0].m_BaseValueMax; float baseValueMin2 = tweakableValues_Legendary[1].m_BaseValueMin; _ = tweakableValues_Legendary[1].m_BaseValueMax; float valuePerUpgrade = tweakableValues_Legendary[0].m_ValuePerUpgrade; float valuePerUpgrade2 = tweakableValues_Legendary[1].m_ValuePerUpgrade; float num = baseValueMin + valuePerUpgrade * (float)upgradeLevel; float value = baseValueMin2 + valuePerUpgrade2 * (float)upgradeLevel; float value2 = 1f; if (tweakableValues_Legendary.Count >= 3) { float baseValueMin3 = tweakableValues_Legendary[2].m_BaseValueMin; float valuePerUpgrade3 = tweakableValues_Legendary[2].m_ValuePerUpgrade; value2 = baseValueMin3 + valuePerUpgrade3 * (float)upgradeLevel; } int value3 = Mathf.RoundToInt(num); __result = $"命中时有 {value2:0%} 的概率连锁至 {value3} 个附近的敌人,造成原始伤害的 {value:0%}"; ChainLinkFixPlugin.LogDebug("描述修复: ChainLink_Ship描述已重建: " + __result); } catch (Exception ex) { ChainLinkFixPlugin.LogDebug("描述修复异常: " + ex.Message); } } } public static class ChainLinkLogicPatch { private static bool _isChaining; private static ItemModule _cachedModule; private static float _lastSearchTime; public static void Postfix(DamageComponent_Base __instance, ref DamageInfo damageInfo) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected I4, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Invalid comparison between Unknown and I4 //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Expected O, but got Unknown //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) try { if (_isChaining) { return; } int num = (int)damageInfo.m_DamageTeamFlags; if (((num & 1) == 0 && (num & 8) == 0) || (int)__instance.m_Team == 1) { return; } float damage = damageInfo.m_Damage; if (damage <= 0f) { return; } ItemModule val = FindChainLinkModule(); if (val == null) { return; } Func getTweakableValue = ((GameplayModifier)val).GetTweakableValue; if ((Delegate)(object)getTweakableValue == (Delegate)null) { return; } float num2 = getTweakableValue.Invoke(2); if (num2 <= 0f || Random.value > num2) { return; } int num3 = Mathf.RoundToInt(getTweakableValue.Invoke(0)); if (num3 <= 0) { return; } float num4 = getTweakableValue.Invoke(1); if (num4 <= 0f) { return; } float value = ChainLinkFixPlugin.ChainRadius.Value; Vector3 val2 = damageInfo.m_HitPos; if (val2 == Vector3.zero) { GameObject damageSender = damageInfo.m_DamageSender; if (!((Object)(object)damageSender != (Object)null)) { return; } val2 = damageSender.transform.position; } GameObject damageSender2 = damageInfo.m_DamageSender; if ((Object)(object)damageSender2 == (Object)null) { return; } List val3 = new List(); Vector3 val4 = val2; if (!DamageComponent_Base.GetOverlappingDamageComponents(damageSender2, ref val4, value, val3, (Il2CppReferenceArray)null) || val3 == null || val3.Count <= 0) { return; } _isChaining = true; try { HashSet hashSet = new HashSet(); hashSet.Add(((Object)__instance).GetInstanceID()); DamageComponent_Base component = damageSender2.GetComponent(); if ((Object)(object)component != (Object)null) { hashSet.Add(((Object)component).GetInstanceID()); } int num5 = 0; for (int i = 0; i < val3.Count; i++) { if (num5 >= num3) { break; } DamageComponent_Base val5 = val3[i]; if (!((Object)(object)val5 == (Object)null) && !hashSet.Contains(((Object)val5).GetInstanceID()) && (int)val5.m_Team != 1) { float num6 = Mathf.Pow(num4, (float)(num5 + 1)); float num7 = damage * num6; if (!(num7 <= 0f)) { DamageInfo val6 = new DamageInfo(); val6.m_DamageType = damageInfo.m_DamageType; val6.m_DamageSpace = damageInfo.m_DamageSpace; val6.m_WorldSpaceDirection = damageInfo.m_WorldSpaceDirection; val6.m_DamageOriginWorldSpace = val2; val6.m_HitPos = (((Object)(object)((Component)val5).transform != (Object)null) ? ((Component)val5).transform.position : val2); val6.m_Damage = num7; val6.m_CriticalMultiplier = damageInfo.m_CriticalMultiplier; val6.m_ImpactMagnitude = 0f; val6.m_DamageSender = damageInfo.m_DamageSender; val6.m_DamageTeamFlags = damageInfo.m_DamageTeamFlags; val6.m_HitCollider = null; val6.m_ForceCritical = false; val6.m_IsMultiShot = false; val5.ReceiveDamage(ref val6); hashSet.Add(((Object)val5).GetInstanceID()); num5++; ChainLinkFixPlugin.LogDebug($"链式伤害 #{num5}: 伤害={num7:F1} (原始={damage:F1} × 衰减={num6:F2})"); } } } if (num5 > 0) { ChainLinkFixPlugin.LogDebug($"链式伤害完成: {num5}次弹跳"); } } finally { _isChaining = false; } } catch (Exception ex) { _isChaining = false; MelonLogger.Error("[ChainLinkFix] 链式伤害回调异常: " + ex.Message + "\n" + ex.StackTrace); } } private static ItemModule FindChainLinkModule() { if (_cachedModule != null && Time.time - _lastSearchTime < 10f) { return _cachedModule; } try { Type val = Il2CppType.From(typeof(ItemModule)); if (val == (Type)null) { return null; } Il2CppReferenceArray val2 = Resources.FindObjectsOfTypeAll(val); if (val2 == null) { return null; } for (int i = 0; i < ((Il2CppArrayBase)(object)val2).Length; i++) { Object val3 = ((Il2CppArrayBase)(object)val2)[i]; if (val3 == (Object)null) { continue; } ItemModule val4 = ((Il2CppObjectBase)val3).TryCast(); if (val4 == null) { continue; } ItemModuleScriptable template = val4.Template; if (!((Object)(object)template == (Object)null)) { string text = ""; string text2 = ""; try { text = ((Object)template).name ?? ""; } catch { } try { text2 = ((GameplayModifierScriptable)template).m_AssetGUID ?? ""; } catch { } if (text2.Contains("ChainLink_Ship") || text.Contains("ChainLink_Ship")) { _cachedModule = val4; _lastSearchTime = Time.time; return val4; } } } } catch (Exception ex) { ChainLinkFixPlugin.LogDebug("查找ChainLink模块异常: " + ex.Message); } return null; } } public static class ChainLinkSafetyPatch { public static bool Prefix(GameplayModifier __instance, int index, ref float __result) { try { if (index < 0 || index >= __instance.m_MaxTweakableIndex) { GameplayModifierScriptable template = __instance.m_Template; if ((Object)(object)template != (Object)null && ((Object)template).name != null && ((Object)template).name.Contains("ChainLink")) { ChainLinkFixPlugin.LogDebug($"安全防护: GetTweakableValue({index})越界 (max={__instance.m_MaxTweakableIndex}), 返回1.0"); __result = ((index == 2) ? 1f : 0f); } else { __result = 0f; } return false; } } catch (Exception ex) { MelonLogger.Error("[ChainLinkFix] 安全防护补丁异常: " + ex.Message); } return true; } } public static class ChainLinkRadiusDiagnostic { private static int _logCount; public static void Prefix(GameObject instigator, in Vector3 worldOrigin, float radius, List overlappingComponents, GameObject[] ignoreObjects) { try { if (_logCount < 20) { string value = (((Object)(object)instigator != (Object)null) ? ((Object)instigator).name : "null"); ChainLinkFixPlugin.LogDebug($"[半径诊断] GetOverlappingDamageComponents: radius={radius:F1}m, origin=({worldOrigin.x:F1},{worldOrigin.y:F1},{worldOrigin.z:F1}), instigator={value}"); _logCount++; } } catch { } } } }