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<bool> EnableMod;
internal static MelonPreferences_Entry<float> ChainRadius;
internal static MelonPreferences_Entry<bool> EnableDebugLogging;
private bool _patchesApplied;
private bool _dataFixed;
public override void OnInitializeMelon()
{
MelonPreferences_Category obj = MelonPreferences.CreateCategory("ChainLinkFix", "链式连接修复");
EnableMod = obj.CreateEntry<bool>("Enable", true, "启用修复", (string)null, false, false, (ValueValidator)null, (string)null);
ChainRadius = obj.CreateEntry<float>("ChainRadius", 20f, "链式伤害搜索半径(米)", (string)null, false, false, (ValueValidator)null, (string)null);
EnableDebugLogging = obj.CreateEntry<bool>("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<Object> val2 = Resources.FindObjectsOfTypeAll(val);
if (val2 == null || ((Il2CppArrayBase<Object>)(object)val2).Length == 0)
{
((MelonBase)this).LoggerInstance.Warning("[ChainLinkFix] 未找到任何ItemModuleScriptable对象");
return;
}
((MelonBase)this).LoggerInstance.Msg($"[ChainLinkFix] 扫描 {((Il2CppArrayBase<Object>)(object)val2).Length} 个ItemModuleScriptable对象...");
int fixedCount = 0;
for (int i = 0; i < ((Il2CppArrayBase<Object>)(object)val2).Length; i++)
{
Object val3 = ((Il2CppArrayBase<Object>)(object)val2)[i];
if (val3 == (Object)null)
{
continue;
}
ItemModuleScriptable val4 = ((Il2CppObjectBase)val3).TryCast<ItemModuleScriptable>();
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<ItemModuleTweakableValue> 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<ItemModuleTweakableValue> 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<int> _reportedBlank = new HashSet<int>();
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<ItemModuleTweakableValue> 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<int, float> 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<DamageComponent_Base> val3 = new List<DamageComponent_Base>();
Vector3 val4 = val2;
if (!DamageComponent_Base.GetOverlappingDamageComponents(damageSender2, ref val4, value, val3, (Il2CppReferenceArray<GameObject>)null) || val3 == null || val3.Count <= 0)
{
return;
}
_isChaining = true;
try
{
HashSet<int> hashSet = new HashSet<int>();
hashSet.Add(((Object)__instance).GetInstanceID());
DamageComponent_Base component = damageSender2.GetComponent<DamageComponent_Base>();
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<Object> val2 = Resources.FindObjectsOfTypeAll(val);
if (val2 == null)
{
return null;
}
for (int i = 0; i < ((Il2CppArrayBase<Object>)(object)val2).Length; i++)
{
Object val3 = ((Il2CppArrayBase<Object>)(object)val2)[i];
if (val3 == (Object)null)
{
continue;
}
ItemModule val4 = ((Il2CppObjectBase)val3).TryCast<ItemModule>();
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<DamageComponent_Base> 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
{
}
}
}
}