Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SparkleSurvivorsTweaks v1.0.10
plugins/SparkleSurvivorsTweaks.dll
Decompiled 8 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using BanditSmokeBombSpeed; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using EntityStates.Bandit2; using EntityStates.Bandit2.Weapon; using EntityStates.Captain.Weapon; using EntityStates.CaptainDefenseMatrixItem; using EntityStates.CaptainSupplyDrop; using EntityStates.Commando; using EntityStates.Commando.CommandoWeapon; using EntityStates.Croco; using EntityStates.Drifter; using EntityStates.Engi.EngiMissilePainter; using EntityStates.Engi.Mine; using EntityStates.EngiTurret.EngiTurretWeapon; using EntityStates.FalseSon; using EntityStates.Huntress; using EntityStates.Huntress.HuntressWeapon; using EntityStates.Loader; using EntityStates.Mage; using EntityStates.Mage.Weapon; using EntityStates.Merc; using EntityStates.Toolbot; using EntityStates.VoidSurvivor.Weapon; using HG; using HarmonyLib; using KinematicCharacterController; using Microsoft.CodeAnalysis; using On.RoR2; using R2API; using RoR2; using RoR2.CharacterAI; using RoR2.Orbs; using RoR2.Projectile; using RoR2.Skills; using SparkleAcridTweaks; using SparkleArtificerTweaks; using SparkleCaptainTweaks; using SparkleChefTweaks; using SparkleCommandoTweaks; using SparkleDrifterTweaks; using SparkleEngineerTweaks; using SparkleFalseSonTweaks; using SparkleHuntressTweaks; using SparkleLoaderTweaks; using SparkleMercTweaks; using SparkleOperatorTweaks; using SparkleRailgunnerTweaks; using SparkleRexTweaks; using SparkleSeekerTweaks; using SparkleSurvivorsTweaks.SkillText; using SparkleToolbotTweaks; using SparkleVoidFiendTweaks; using UnityEngine; using UnityEngine.Networking; using UnityEngine.Rendering.PostProcessing; [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("SparkleSurvivorsTweaks")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.10.0")] [assembly: AssemblyInformationalVersion("1.0.10")] [assembly: AssemblyProduct("SparkleSurvivorsTweaks")] [assembly: AssemblyTitle("SparkleSurvivorsTweaks")] [assembly: AssemblyVersion("1.0.10.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 SparkleVoidFiendTweaks { public static class CorruptModeStats { private const string Section = "VoidFiend"; private const int DiagnosticCount = 5; private const float VanillaArmor = 100f; private static ConfigEntry<bool> _enabled; private static ConfigEntry<float> _armor; private static ConfigEntry<float> _attackSpeedPercent; private static ConfigEntry<float> _moveSpeedPercent; private static ConfigEntry<float> _regenPenalty; private static ConfigEntry<float> _regenPenaltyPerLevel; private static ManualLogSource _log; private static int _applyCount; private static int _diagCount; public static bool IsEnabled { get { if (_enabled != null) { return _enabled.Value; } return false; } } public static void Init(ConfigFile cfg, ManualLogSource logger) { _log = logger; _enabled = cfg.Bind<bool>("VoidFiend", "CorruptModeStatsEnabled", true, "是否调整「虚空幸存者腐化模式」buff 提供的属性。false = 完全保持原版。"); _armor = cfg.Bind<float>("VoidFiend", "CorruptModeArmor", 200f, "腐化模式下这个 buff 提供的护甲总量。原版是 100,这里补差额到 200。运行期读取。"); _attackSpeedPercent = cfg.Bind<float>("VoidFiend", "CorruptModeAttackSpeedPercent", 30f, "腐化模式下提供的攻击速度加成(百分比)。30 = 总攻速 ×1.30。\n原版没有这一项,是纯新增。运行期读取。"); _moveSpeedPercent = cfg.Bind<float>("VoidFiend", "CorruptModeMoveSpeedPercent", 30f, "腐化模式下提供的移动速度加成(百分比)。30 = 总移速 ×1.30。\n原版没有这一项,是纯新增。运行期读取。"); _regenPenalty = cfg.Bind<float>("VoidFiend", "CorruptModeRegenPenalty", 3f, "腐化模式下每秒扣掉的生命恢复(正数 = 扣多少)。1 级时的数值。\n原版没有这一项,是纯新增。运行期读取。"); _regenPenaltyPerLevel = cfg.Bind<float>("VoidFiend", "CorruptModeRegenPenaltyPerLevel", 0.6f, "腐化模式下每提升 1 级,额外再扣多少生命恢复。\n总扣除 = 基础值 + 这个值 ×(等级 - 1)。运行期读取。"); } public static void Patch(Harmony harmony) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown if (!IsEnabled) { Log((LogLevel)16, "腐化模式属性:按配置保持原版,不挂补丁。"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(CharacterBody), "RecalculateStats", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "腐化模式属性补丁失败:取不到 CharacterBody.RecalculateStats。"); return; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(CorruptModeStats), "RecalculateStatsPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "补丁已挂载:CharacterBody.RecalculateStats <- RecalculateStatsPostfix(腐化模式属性)"); } public static string Summary() { return "腐化模式属性:护甲 " + ArmorValue().ToString("0") + ",攻速 +" + AttackSpeedPercent().ToString("0.#") + "%,移速 +" + MoveSpeedPercent().ToString("0.#") + "%,生命恢复 -" + RegenPenalty().ToString("0.#") + "(每级再 -" + RegenPenaltyPerLevel().ToString("0.#") + ")。"; } private static void RecalculateStatsPostfix(CharacterBody __instance) { if ((Object)(object)__instance == (Object)null || !IsEnabled) { return; } BuffDef voidSurvivorCorruptMode = Buffs.VoidSurvivorCorruptMode; if (!((Object)(object)voidSurvivorCorruptMode == (Object)null) && __instance.HasBuff(voidSurvivorCorruptMode)) { float num = ArmorValue() - 100f; if (Math.Abs(num) > 0.001f) { AddStat(__instance, "armor", num); } float num2 = 1f + AttackSpeedPercent() * 0.01f; if (Math.Abs(num2 - 1f) > 0.0001f) { ScaleStat(__instance, "attackSpeed", num2); } float num3 = 1f + MoveSpeedPercent() * 0.01f; if (Math.Abs(num3 - 1f) > 0.0001f) { ScaleStat(__instance, "moveSpeed", num3); } float num4 = RegenPenalty() + RegenPenaltyLevelPart(__instance); if (Math.Abs(num4) > 0.001f) { AddStat(__instance, "regen", 0f - num4); } _applyCount++; if (_diagCount < 5) { _diagCount++; Log((LogLevel)16, "腐化模式属性诊断 #" + _diagCount + ":等级 " + __instance.level.ToString("0") + ",护甲 " + ReadStat(__instance, "armor").ToString("0.#") + "(原版 100 + 补 " + num.ToString("0.#") + "),攻速 " + ReadStat(__instance, "attackSpeed").ToString("0.###") + ",移速 " + ReadStat(__instance, "moveSpeed").ToString("0.###") + ",生命恢复 " + ReadStat(__instance, "regen").ToString("0.###") + "(扣了 " + num4.ToString("0.##") + ")。"); } } } private static float RegenPenaltyLevelPart(CharacterBody body) { float num = body.level; if (num < 1f) { num = 1f; } return RegenPenaltyPerLevel() * (num - 1f); } private static float ArmorValue() { if (_armor == null) { return 100f; } return _armor.Value; } private static float AttackSpeedPercent() { if (_attackSpeedPercent == null) { return 0f; } return _attackSpeedPercent.Value; } private static float MoveSpeedPercent() { if (_moveSpeedPercent == null) { return 0f; } return _moveSpeedPercent.Value; } private static float RegenPenalty() { if (_regenPenalty == null) { return 0f; } return _regenPenalty.Value; } private static float RegenPenaltyPerLevel() { if (_regenPenaltyPerLevel == null) { return 0f; } return _regenPenaltyPerLevel.Value; } private static void AddStat(CharacterBody body, string name, float delta) { WriteStat(body, name, ReadStat(body, name) + delta); } private static void ScaleStat(CharacterBody body, string name, float factor) { WriteStat(body, name, ReadStat(body, name) * factor); } private static float ReadStat(CharacterBody body, string name) { FieldInfo fieldInfo = AccessTools.Field(typeof(CharacterBody), "<" + name + ">k__BackingField"); if (fieldInfo != null) { return (float)fieldInfo.GetValue(body); } PropertyInfo propertyInfo = AccessTools.Property(typeof(CharacterBody), name); if (propertyInfo != null) { MethodInfo getMethod = propertyInfo.GetGetMethod(nonPublic: true); if (getMethod != null) { return (float)getMethod.Invoke(body, null); } } Log((LogLevel)4, "腐化模式属性:读不到 CharacterBody." + name + ",按 0 处理。"); return 0f; } private static void WriteStat(CharacterBody body, string name, float value) { FieldInfo fieldInfo = AccessTools.Field(typeof(CharacterBody), "<" + name + ">k__BackingField"); if (fieldInfo != null) { fieldInfo.SetValue(body, value); return; } PropertyInfo propertyInfo = AccessTools.Property(typeof(CharacterBody), name); if (propertyInfo != null) { MethodInfo setMethod = propertyInfo.GetSetMethod(nonPublic: true); if (setMethod != null) { setMethod.Invoke(body, new object[1] { value }); return; } } Log((LogLevel)4, "腐化模式属性:写不进 CharacterBody." + name + ",这一项没生效。"); } private static void Log(LogLevel level, string message) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (_log != null) { _log.Log(level, (object)message); } } } public static class FloodCollapse { public class FloodCollapseMarker : MonoBehaviour, IProjectileImpactBehavior { public bool Resolved; public void OnProjectileImpact(ProjectileImpactInfo impactInfo) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) Vector3 val = impactInfo.estimatedPointOfImpact; if (val == Vector3.zero) { val = ((Component)this).transform.position; } Resolve(((Component)this).gameObject, val, impactInfo.collider); } } private const string Section = "VoidFiend"; private const int DiagnosticCount = 8; private static ConfigEntry<bool> _enabled; private static ConfigEntry<int> _stacksNormal; private static ConfigEntry<int> _stacksCharged; private static ConfigEntry<int> _stacksCorrupted; private static ConfigEntry<float> _duration; private static ConfigEntry<float> _radius; private static ConfigEntry<string> _projectileName; private static ManualLogSource _log; private static bool _attached; private static int _diagCount; private static int _triggerCount; public static bool IsEnabled { get { if (_enabled != null) { return _enabled.Value; } return false; } } public static void Init(ConfigFile cfg, ManualLogSource logger) { _log = logger; _enabled = cfg.Bind<bool>("VoidFiend", "FloodCollapseEnabled", true, "M2「腐化流」的射弹命中时,是否给敌人挂「瓦解」(3 秒后爆 400% 基础伤害)。\n未腐化与腐化形态都算,层数按蓄力档位分档。false = 完全保持原版。"); _stacksCorrupted = cfg.Bind<int>("VoidFiend", "FloodCollapseStacksCorrupted", 3, "腐化形态(射弹名带 Corrupted)命中时给每个敌人挂几层瓦解。运行期读取。"); _stacksCharged = cfg.Bind<int>("VoidFiend", "FloodCollapseStacksCharged", 2, "未腐化形态 + 完全蓄力(射弹名带 Big)时挂几层。运行期读取。"); _stacksNormal = cfg.Bind<int>("VoidFiend", "FloodCollapseStacksNormal", 1, "未腐化形态 + 没蓄满(射弹名带 Small)时挂几层。运行期读取。"); _duration = cfg.Bind<float>("VoidFiend", "FloodCollapseDuration", 3f, "单层瓦解的存活时长(秒)。3 = 和游戏原版一致(DotDef 的 interval 就是 3)。\n填 0 或负数也按 3 秒算。运行期读取。"); _radius = cfg.Bind<float>("VoidFiend", "FloodCollapseRadius", 0f, "作用半径(米)。0 = 跟着射弹自己的爆炸半径走;纯直击弹(没有爆炸组件)\n在 0 时只作用于被直接命中的那个目标。运行期读取。"); _projectileName = cfg.Bind<string>("VoidFiend", "FloodProjectileName", "VoidSurvivorMegaBlaster", "要改造的射弹预制体名(包含匹配,大小写不敏感)。\n命中这个名字之后,再按 Corrupted / Big / Small 判断是哪一档。\n游戏改版改名了就把这里改成新名字;清空 = 关闭识别。运行期读取。"); } public static void Patch(Harmony harmony) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown if (!IsEnabled) { Log((LogLevel)16, "腐化流瓦解:按配置保持原版,不挂补丁。"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(ProjectileManager), "InitializeProjectile", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "腐化流瓦解补丁失败:取不到 ProjectileManager.InitializeProjectile。"); return; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(FloodCollapse), "InitializeProjectilePostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "补丁已挂载:ProjectileManager.InitializeProjectile <- InitializeProjectilePostfix(腐化流射弹识别)"); MethodInfo methodInfo2 = AccessTools.Method(typeof(ProjectileExplosion), "DetonateServer", (Type[])null, (Type[])null); if (methodInfo2 == null) { Log((LogLevel)2, "腐化流瓦解补丁失败:取不到 ProjectileExplosion.DetonateServer。"); return; } harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(FloodCollapse), "DetonateServerPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "补丁已挂载:ProjectileExplosion.DetonateServer <- DetonateServerPostfix(腐化流瓦解)"); } public static void InitializeProjectilePostfix(ProjectileController projectileController, FireProjectileInfo fireProjectileInfo) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) GameObject projectilePrefab = fireProjectileInfo.projectilePrefab; if ((Object)(object)projectilePrefab == (Object)null) { return; } string name = ((Object)projectilePrefab).name; bool flag = IsTarget(name); if (name.IndexOf("VoidSurvivor", StringComparison.OrdinalIgnoreCase) >= 0 && _diagCount++ < 10) { Log((LogLevel)16, "腐化流诊断:虚空恶鬼射弹「" + name + "」" + (flag ? (" → 命中目标,打标记(" + StacksFor(name) + " 层)。") : " → 不是目标,跳过。")); } if (!flag || (Object)(object)projectileController == (Object)null) { return; } GameObject gameObject = ((Component)projectileController).gameObject; if (!((Object)(object)gameObject.GetComponent<FloodCollapseMarker>() != (Object)null)) { gameObject.AddComponent<FloodCollapseMarker>(); if (!_attached) { _attached = true; Log((LogLevel)16, "腐化流瓦解:已在射弹「" + name + "」上打标记。"); } } } public static void DetonateServerPostfix(ProjectileExplosion __instance) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null)) { Resolve(((Component)__instance).gameObject, ((Component)__instance).transform.position, null); } } internal unsafe static void Resolve(GameObject projectile, Vector3 center, Collider directHit) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)projectile == (Object)null || !NetworkServer.active) { return; } FloodCollapseMarker component = projectile.GetComponent<FloodCollapseMarker>(); if ((Object)(object)component == (Object)null || component.Resolved || ((Object)(object)directHit != (Object)null && (Object)(object)projectile.GetComponent<ProjectileExplosion>() != (Object)null)) { return; } component.Resolved = true; ProjectileController component2 = projectile.GetComponent<ProjectileController>(); GameObject val = (((Object)(object)component2 != (Object)null) ? component2.owner : null); TeamIndex team = (TeamIndex)(((Object)(object)component2 != (Object)null && (Object)(object)component2.teamFilter != (Object)null) ? ((int)component2.teamFilter.teamIndex) : 0); int stacks = StacksFor(((Object)projectile).name); float num = RadiusValue(); if (num <= 0f) { ProjectileExplosion component3 = projectile.GetComponent<ProjectileExplosion>(); if ((Object)(object)component3 != (Object)null) { num = component3.blastRadius; } } _triggerCount++; bool flag = _triggerCount <= 8; if (flag) { Log((LogLevel)16, "腐化流诊断 #" + _triggerCount + ":「" + ((Object)projectile).name + "」结算,半径 " + num.ToString("0.##") + ",层数 " + stacks + ",队伍 " + ((object)(*(TeamIndex*)(&team))/*cast due to .constrained prefix*/).ToString() + ",攻击者 " + (((Object)(object)val != (Object)null) ? ((Object)val).name : "(无)")); } int num2 = 0; if (num > 0f) { num2 = ApplyInRadius(center, num, team, val, stacks, flag); } else if ((Object)(object)directHit != (Object)null) { HurtBox component4 = ((Component)directHit).GetComponent<HurtBox>(); if ((Object)(object)component4 != (Object)null && (Object)(object)component4.healthComponent != (Object)null && (Object)(object)component4.healthComponent.body != (Object)null && component4.healthComponent.alive) { InflictCollapse(component4.healthComponent.body, val, stacks, flag); num2 = 1; } } if (flag) { Log((LogLevel)16, "腐化流诊断 #" + _triggerCount + ":影响 " + num2 + " 个目标。"); } } private static int ApplyInRadius(Vector3 center, float radius, TeamIndex team, GameObject attacker, int stacks, bool verbose) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) HashSet<CharacterBody> handled = new HashSet<CharacterBody>(); int num = 0; BullseyeSearch val = new BullseyeSearch { searchOrigin = center, teamMaskFilter = TeamMask.GetEnemyTeams(team), filterByLoS = false, sortMode = (SortMode)1, maxDistanceFilter = radius }; val.RefreshCandidates(); foreach (HurtBox result in val.GetResults()) { if (TryInflict(result, team, attacker, stacks, handled, verbose)) { num++; } } int num2 = num; foreach (HurtBox item in OverlapHurtBoxes(center, radius)) { if (TryInflict(item, team, attacker, stacks, handled, verbose)) { num++; } } if (verbose) { float num3 = NearestEnemyDistance(center, radius, team); Log((LogLevel)16, "腐化流诊断:中心 " + Format(center) + ",半径 " + radius.ToString("0.##") + " —— BullseyeSearch " + num2 + " 个,物理球补 " + (num - num2) + " 个,合计 " + num + " 个;" + ((num3 >= 0f) ? ("范围内最近的敌人 " + num3.ToString("0.##") + " 米。") : "范围内一个敌人的 HurtBox 都没有。")); } return num; } private static List<HurtBox> OverlapHurtBoxes(Vector3 center, float radius) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) List<HurtBox> list = new List<HurtBox>(); LayerIndex entityPrecise = LayerIndex.entityPrecise; Collider[] array = Physics.OverlapSphere(center, radius, LayerMask.op_Implicit(((LayerIndex)(ref entityPrecise)).mask), (QueryTriggerInteraction)2); for (int i = 0; i < array.Length; i++) { HurtBox val = (((Object)(object)array[i] != (Object)null) ? ((Component)array[i]).GetComponent<HurtBox>() : null); if ((Object)(object)val != (Object)null) { list.Add(val); } } return list; } private static float NearestEnemyDistance(Vector3 center, float radius, TeamIndex team) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) float num = -1f; foreach (HurtBox item in OverlapHurtBoxes(center, radius)) { CharacterBody val = (((Object)(object)item.healthComponent != (Object)null) ? item.healthComponent.body : null); if (!((Object)(object)val == (Object)null) && IsEnemy(val, team)) { float num2 = Vector3.Distance(center, ((Component)item).transform.position); if (num < 0f || num2 < num) { num = num2; } } } return num; } private static bool IsEnemy(CharacterBody body, TeamIndex team) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) TeamComponent teamComponent = body.teamComponent; if (!((Object)(object)teamComponent == (Object)null)) { return teamComponent.teamIndex != team; } return true; } private static bool TryInflict(HurtBox hurtBox, TeamIndex team, GameObject attacker, int stacks, HashSet<CharacterBody> handled, bool verbose) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)hurtBox == (Object)null || (Object)(object)hurtBox.healthComponent == (Object)null) { return false; } CharacterBody body = hurtBox.healthComponent.body; if ((Object)(object)body == (Object)null || !body.healthComponent.alive || !IsEnemy(body, team) || !handled.Add(body)) { return false; } InflictCollapse(body, attacker, stacks, verbose); return true; } private static string Format(Vector3 value) { return "(" + value.x.ToString("0.#") + ", " + value.y.ToString("0.#") + ", " + value.z.ToString("0.#") + ")"; } private static void InflictCollapse(CharacterBody body, GameObject attacker, int stacks, bool verbose) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) float duration = DurationValue(); for (int i = 0; i < stacks; i++) { InflictDotInfo val = new InflictDotInfo { victimObject = ((Component)body).gameObject, attackerObject = attacker, dotIndex = (DotIndex)8, duration = duration, damageMultiplier = 1f }; DotController.InflictDot(ref val); } if (verbose) { Log((LogLevel)16, "腐化流诊断:→ " + ((Object)body).name + " 挂 " + stacks + " 层瓦解。"); } } private static int StacksFor(string prefabName) { if (prefabName.IndexOf("Corrupted", StringComparison.OrdinalIgnoreCase) >= 0) { return StacksCorrupted(); } if (prefabName.IndexOf("Big", StringComparison.OrdinalIgnoreCase) >= 0) { return StacksCharged(); } return StacksNormal(); } private static bool IsTarget(string prefabName) { string value = MatchValue(); if (string.IsNullOrEmpty(value)) { return false; } return prefabName.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0; } private static string MatchValue() { if (_projectileName == null) { return string.Empty; } return _projectileName.Value; } private static int StacksNormal() { int num = ((_stacksNormal == null) ? 1 : _stacksNormal.Value); if (num <= 0) { return 1; } return num; } private static int StacksCharged() { int num = ((_stacksCharged != null) ? _stacksCharged.Value : 2); if (num <= 0) { return 1; } return num; } private static int StacksCorrupted() { int num = ((_stacksCorrupted != null) ? _stacksCorrupted.Value : 3); if (num <= 0) { return 1; } return num; } private static float DurationValue() { float num = ((_duration != null) ? _duration.Value : 3f); if (!(num > 0f)) { return 3f; } return num; } private static float RadiusValue() { if (_radius == null) { return 0f; } return _radius.Value; } public static string Summary() { if (!IsEnabled) { return "腐化流瓦解:关。"; } return "腐化流瓦解:未腐化 " + StacksNormal() + " 层 / 蓄满 " + StacksCharged() + " 层 / 腐化 " + StacksCorrupted() + " 层," + DurationValue().ToString("0.#") + " 秒后爆(每层 400% 基础伤害)" + ((RadiusValue() > 0f) ? (",半径 " + RadiusValue().ToString("0.#") + " 米") : ",半径跟随爆炸") + "。"; } private static void Log(LogLevel level, string message) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (_log != null) { _log.Log(level, (object)message); } } } public static class FloodIndependentWeapon { private const string Section = "VoidFiend"; private const string DefaultMachineName = "FloodWeapon"; private const string BodyName = "VoidSurvivorBody"; private static readonly string[] FallbackStateTypes = new string[3] { "EntityStates.VoidSurvivor.Weapon.ChargeMegaBlaster", "EntityStates.VoidSurvivor.Weapon.ReadyMegaBlaster", "EntityStates.VoidSurvivor.Weapon.FireMegaBlasterBase" }; private static ConfigEntry<bool> _enabled; private static ConfigEntry<string> _machineName; private static ConfigEntry<bool> _fallback; private const int DiagnosticCount = 5; private static Harmony _harmony; private static ManualLogSource _log; private static bool _done; private static bool _ok; private static bool _fallbackPatched; private static int _diagCount; private static FieldInfo _stateMachineField; public static bool IsEnabled { get { if (_enabled != null) { return _enabled.Value; } return false; } } public static void Init(ConfigFile cfg, ManualLogSource logger) { _log = logger; _enabled = cfg.Bind<bool>("VoidFiend", "FloodIndependentMachineEnabled", true, "M2「腐化流」是不是单独开一个状态机跑。\n开:M2 蓄力/释放期间 M1 照常射击,M2 蓄力时也能随时按 M1(两种形态都算)。\n关:完全保持原版(M2 蓄力时 M1 按不动)。"); _machineName = cfg.Bind<string>("VoidFiend", "FloodIndependentMachineName", "FloodWeapon", "给 M2 单独用的状态机名字。一般不用改,除非和别的模组撞名。改了要重开游戏。"); _fallback = cfg.Bind<bool>("VoidFiend", "FloodInterruptFallback", true, "独立状态机没搭起来时的兜底:把 M2 蓄力/发射状态的打断优先级压到最低,\n让 M1 至少能打断它。代价是蓄力会被取消(等于白蓄)。只在搭状态机失败时生效。"); } public static void Patch(Harmony harmony) { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown _harmony = harmony; if (!IsEnabled) { Log((LogLevel)16, "腐化流独立状态机:按配置保持原版。"); return; } ((ResourceAvailability)(ref BodyCatalog.availability)).CallWhenAvailable((Action)Setup); Log((LogLevel)16, "已注册回调:BodyCatalog.available -> Setup(腐化流独立状态机)"); MethodInfo methodInfo = AccessTools.Method(typeof(GenericSkill), "PickTargetStateMachine", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "腐化流独立状态机:取不到 GenericSkill.PickTargetStateMachine。"); return; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(FloodIndependentWeapon), "PickTargetStateMachinePostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "补丁已挂载:GenericSkill.PickTargetStateMachine <- PickTargetStateMachinePostfix(M2 槽强制走独立状态机)"); } private static void PickTargetStateMachinePostfix(GenericSkill __instance) { //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return; } CharacterBody characterBody = __instance.characterBody; GameObject val = (((Object)(object)characterBody != (Object)null) ? ((Component)characterBody).gameObject : ((Component)__instance).gameObject); if ((Object)(object)val == (Object)null || ((Object)val).name.IndexOf("VoidSurvivor", StringComparison.OrdinalIgnoreCase) < 0) { return; } SkillLocator component = ((Component)__instance).GetComponent<SkillLocator>(); if ((Object)(object)component == (Object)null || (Object)(object)component.secondary != (Object)(object)__instance) { return; } string text = MachineNameValue(); EntityStateMachine val2 = EntityStateMachine.FindByCustomName(val, text); if ((Object)(object)val2 == (Object)null) { return; } if (_stateMachineField == null) { _stateMachineField = AccessTools.Field(typeof(GenericSkill), "<stateMachine>k__BackingField"); if (_stateMachineField == null) { Log((LogLevel)2, "腐化流独立状态机:取不到 GenericSkill.stateMachine 的 backing field。"); return; } } EntityStateMachine stateMachine = __instance.stateMachine; if ((Object)(object)stateMachine != (Object)(object)val2) { _stateMachineField.SetValue(__instance, val2); } SkillDef skillDef = __instance.skillDef; if ((Object)(object)skillDef != (Object)null && !string.Equals(skillDef.activationStateMachineName, text, StringComparison.Ordinal)) { skillDef.activationStateMachineName = text; } if (_diagCount++ < 5) { Log((LogLevel)16, "腐化流诊断:M2 槽取状态机 —— 技能「" + SkillName(skillDef) + "」,激活状态 " + StateName((SerializableEntityStateType)(((Object)(object)skillDef != (Object)null) ? skillDef.activationState : default(SerializableEntityStateType))) + ",槽位缓存 " + (((Object)(object)stateMachine != (Object)null) ? stateMachine.customName : "(无)") + " → " + val2.customName); } } private static string SkillName(SkillDef skillDef) { if (!((Object)(object)skillDef != (Object)null) || string.IsNullOrEmpty(skillDef.skillNameToken)) { return "(无名)"; } return skillDef.skillNameToken; } private static void Setup() { if (_done) { return; } _done = true; try { SetupMachine(); } catch (Exception ex) { Log((LogLevel)2, "腐化流独立状态机:搭建时抛异常 —— " + ex); PatchFallback(); } } private static void SetupMachine() { //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) GameObject val = FindBodyPrefab(); if ((Object)(object)val == (Object)null) { Log((LogLevel)2, "腐化流独立状态机:在 BodyCatalog 里找不到虚空恶鬼的 body 预制体(找的是名字里带 VoidSurvivor 的),改不动。"); PatchFallback(); return; } string text = MachineNameValue(); EntityStateMachine[] components = val.GetComponents<EntityStateMachine>(); List<string> list = new List<string>(); for (int i = 0; i < components.Length; i++) { list.Add(components[i].customName); if (string.Equals(components[i].customName, text, StringComparison.Ordinal)) { Log((LogLevel)16, "腐化流独立状态机:「" + ((Object)val).name + "」上已经有「" + text + "」了,跳过。"); _ok = true; return; } } Log((LogLevel)16, "腐化流独立状态机:虚空恶鬼 prefab「" + ((Object)val).name + "」,现有状态机 [" + string.Join(", ", list.ToArray()) + "]"); EntityStateMachine val2 = null; for (int j = 0; j < components.Length; j++) { if (string.Equals(components[j].customName, "Weapon", StringComparison.Ordinal)) { val2 = components[j]; break; } } EntityStateMachine val3 = val.AddComponent<EntityStateMachine>(); val3.customName = text; SerializableEntityStateType stateType = (val3.mainStateType = (val3.initialStateType = PickIdleState(val2))); if ((Object)(object)val2 != (Object)null) { val3.AllowStartWithoutNetworker = val2.AllowStartWithoutNetworker; val3.ShouldStateTransitionOnUpdate = val2.ShouldStateTransitionOnUpdate; Log((LogLevel)16, "腐化流独立状态机:已建「" + text + "」,初始/主状态 = " + StateName(stateType) + "(Weapon 用的是 " + StateName(val2.mainStateType) + ")"); } else { Log((LogLevel)4, "腐化流独立状态机:prefab 上没有 customName = Weapon 的状态机,只能按默认参数建「" + text + "」,初始/主状态 = " + StateName(stateType) + "。"); } RegisterForNetwork(val, val3); RedirectSecondary(val, text); _ok = true; } private static void RegisterForNetwork(GameObject prefab, EntityStateMachine flood) { NetworkStateMachine component = prefab.GetComponent<NetworkStateMachine>(); if ((Object)(object)component == (Object)null) { Log((LogLevel)4, "腐化流独立状态机:prefab 上没有 NetworkStateMachine,新状态机不会被同步(单机无所谓,联机时别人看不到 M2 动作)。"); return; } FieldInfo fieldInfo = AccessTools.Field(typeof(NetworkStateMachine), "stateMachines"); if (fieldInfo == null) { Log((LogLevel)4, "腐化流独立状态机:取不到 NetworkStateMachine.stateMachines 字段,新状态机不会被同步(单机无所谓,联机时别人看不到 M2 动作)。"); return; } List<EntityStateMachine> list = new List<EntityStateMachine>(); if (fieldInfo.GetValue(component) is EntityStateMachine[] collection) { list.AddRange(collection); } if (!list.Contains(flood)) { list.Add(flood); fieldInfo.SetValue(component, list.ToArray()); Log((LogLevel)16, "腐化流独立状态机:已把「" + flood.customName + "」加进 NetworkStateMachine(共 " + list.Count + " 个状态机)。"); } } private static void RedirectSecondary(GameObject prefab, string machineName) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) SkillLocator component = prefab.GetComponent<SkillLocator>(); if ((Object)(object)component == (Object)null || (Object)(object)component.secondary == (Object)null) { Log((LogLevel)2, "腐化流独立状态机:prefab 上取不到 SkillLocator.secondary。"); PatchFallback(); return; } SkillFamily skillFamily = component.secondary.skillFamily; if ((Object)(object)skillFamily == (Object)null || skillFamily.variants == null || skillFamily.variants.Length == 0) { Log((LogLevel)2, "腐化流独立状态机:M2 的 SkillFamily 是空的。"); PatchFallback(); return; } int num = 0; Variant[] variants = skillFamily.variants; for (int i = 0; i < variants.Length; i++) { SkillDef skillDef = variants[i].skillDef; if (!((Object)(object)skillDef == (Object)null)) { string activationStateMachineName = skillDef.activationStateMachineName; skillDef.activationStateMachineName = machineName; num++; Log((LogLevel)16, "腐化流独立状态机:M2 技能「" + skillDef.skillNameToken + "」状态机 " + (string.IsNullOrEmpty(activationStateMachineName) ? "(空)" : activationStateMachineName) + " → " + machineName + "(激活状态 " + StateName(skillDef.activationState) + ")"); } } if (num == 0) { Log((LogLevel)2, "腐化流独立状态机:M2 家族里一个 SkillDef 都没改到。"); PatchFallback(); return; } Log((LogLevel)16, "腐化流独立状态机:共 " + num + " 个 M2 技能已改到「" + machineName + "」,M1 留在 Weapon,两边互不干扰。"); } private static GameObject FindBodyPrefab() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) BodyIndex val = BodyCatalog.FindBodyIndex("VoidSurvivorBody"); if ((int)val != -1) { GameObject bodyPrefab = BodyCatalog.GetBodyPrefab(val); if ((Object)(object)bodyPrefab != (Object)null) { return bodyPrefab; } } foreach (GameObject allBodyPrefab in BodyCatalog.allBodyPrefabs) { if ((Object)(object)allBodyPrefab != (Object)null && ((Object)allBodyPrefab).name.IndexOf("VoidSurvivor", StringComparison.OrdinalIgnoreCase) >= 0) { return allBodyPrefab; } } return null; } private static SerializableEntityStateType PickIdleState(EntityStateMachine weapon) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)weapon != (Object)null) { Type stateType = ((SerializableEntityStateType)(ref weapon.mainStateType)).stateType; if (stateType != null && stateType != typeof(Uninitialized)) { return weapon.mainStateType; } } return new SerializableEntityStateType(typeof(Idle)); } private static string StateName(SerializableEntityStateType stateType) { Type stateType2 = ((SerializableEntityStateType)(ref stateType)).stateType; if (stateType2 != null) { return stateType2.Name; } if (!string.IsNullOrEmpty(((SerializableEntityStateType)(ref stateType)).typeName)) { return ((SerializableEntityStateType)(ref stateType)).typeName; } return "(空)"; } private static void PatchFallback() { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown if (_fallbackPatched || _harmony == null) { return; } _fallbackPatched = true; if (_fallback == null || !_fallback.Value) { Log((LogLevel)4, "腐化流独立状态机:搭不起来,且兜底方案按配置关闭,M2 保持原版。"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(FloodIndependentWeapon), "LowerPriorityPostfix", (Type[])null, (Type[])null); string[] fallbackStateTypes = FallbackStateTypes; foreach (string text in fallbackStateTypes) { Type type = AccessTools.TypeByName(text); if (type == null) { Log((LogLevel)4, "腐化流兜底补丁:找不到类型 " + text + "。"); continue; } MethodInfo methodInfo2 = AccessTools.Method(type, "GetMinimumInterruptPriority", (Type[])null, (Type[])null); if (methodInfo2 == null) { Log((LogLevel)4, "腐化流兜底补丁:" + text + " 上没有 GetMinimumInterruptPriority。"); continue; } _harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "兜底补丁已挂载:" + text + ".GetMinimumInterruptPriority -> Any(M1 可打断 M2,但蓄力会丢)"); } } private static void LowerPriorityPostfix(ref InterruptPriority __result) { __result = (InterruptPriority)0; } private static string MachineNameValue() { string text = ((_machineName != null) ? _machineName.Value : null); if (!string.IsNullOrEmpty(text)) { return text; } return "FloodWeapon"; } public static string Summary() { if (!IsEnabled) { return "腐化流独立状态机:关(M2 蓄力时 M1 按不动,原版行为)。"; } if (_ok) { return "腐化流独立状态机:M2 跑在「" + MachineNameValue() + "」,M1 留在 Weapon,互不打断。"; } return "腐化流独立状态机:还没搭好(等 BodyCatalog 就绪,或已失败、走了兜底)。"; } private static void Log(LogLevel level, string message) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (_log != null) { _log.Log(level, (object)message); } } } public static class PrimaryFireRate { private const string Section = "VoidFiend"; private const int DiagnosticCount = 6; private static ConfigEntry<bool> _enabled; private static ConfigEntry<float> _baseDuration; private static ManualLogSource _log; private static int _diagCount; private static float _lastOriginal = -1f; private static readonly FieldInfo BaseDurationField = AccessTools.Field(typeof(FireHandBeam), "baseDuration"); private static readonly FieldInfo DurationField = AccessTools.Field(typeof(FireHandBeam), "duration"); private static readonly FieldInfo AttackSpeedStatField = AccessTools.Field(typeof(BaseState), "attackSpeedStat"); public static bool IsEnabled { get { if (_enabled != null) { return _enabled.Value; } return false; } } public static void Init(ConfigFile cfg, ManualLogSource logger) { _log = logger; _enabled = cfg.Bind<bool>("VoidFiend", "PrimaryBaseDurationEnabled", true, "是否调整未腐化形态 M1 的攻击间隔。false = 保持原版。"); _baseDuration = cfg.Bind<float>("VoidFiend", "PrimaryBaseDuration", 0.5f, "未腐化形态 M1 的攻击间隔(秒)。原版 0.6,越小打得越快。\n实际间隔还要除以攻击速度。运行期读取,改了下一发就生效。"); } public static void Patch(Harmony harmony) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_00a6: Expected O, but got Unknown if (!IsEnabled) { Log((LogLevel)16, "未腐化 M1 攻速:按配置保持原版,不挂补丁。"); return; } if (BaseDurationField == null || DurationField == null) { Log((LogLevel)2, "未腐化 M1 攻速补丁失败:取不到 FireHandBeam 的 baseDuration / duration 字段。"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(FireHandBeam), "OnEnter", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "未腐化 M1 攻速补丁失败:取不到 FireHandBeam.OnEnter。"); return; } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(PrimaryFireRate), "OnEnterPrefix", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.Method(typeof(PrimaryFireRate), "OnEnterPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "补丁已挂载:EntityStates.VoidSurvivor.Weapon.FireHandBeam.OnEnter(未腐化 M1 攻击间隔)"); } public static string Summary() { return "未腐化 M1 攻击间隔:" + BaseDurationValue().ToString("0.###") + " 秒。"; } private static void OnEnterPrefix(object __instance) { if (__instance != null && IsEnabled) { _lastOriginal = (float)BaseDurationField.GetValue(__instance); float num = BaseDurationValue(); if (Math.Abs(_lastOriginal - num) > 0.0001f) { BaseDurationField.SetValue(__instance, num); } } } private static void OnEnterPostfix(object __instance) { if (__instance != null) { float num = ((AttackSpeedStatField != null) ? ((float)AttackSpeedStatField.GetValue(__instance)) : 1f); if (num < 0.0001f) { num = 1f; } float num2 = BaseDurationValue() / num; float num3 = (float)DurationField.GetValue(__instance); if (num3 > num2 + 0.0001f) { DurationField.SetValue(__instance, num2); num3 = num2; } if (_diagCount < 6) { _diagCount++; Log((LogLevel)16, "未腐化 M1 诊断 #" + _diagCount + ":原版 baseDuration " + _lastOriginal.ToString("0.###") + " → 目标 " + BaseDurationValue().ToString("0.###") + ",攻击速度 " + num.ToString("0.###") + ",最终时长 " + num3.ToString("0.###") + " 秒。"); } } } private static float BaseDurationValue() { float num = ((_baseDuration != null) ? _baseDuration.Value : 0.5f); if (!(num > 0f)) { return 0.5f; } return num; } private static void Log(LogLevel level, string message) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (_log != null) { _log.Log(level, (object)message); } } } internal class VoidFiendModule { public const string PluginGUID = "com.sparkletwilight.sparklesurvivorstweaks.voidfiend"; public const string PluginName = "SparkleVoidFiendTweaks"; public const string PluginVersion = "1.0.0"; private ConfigFile Config; private ManualLogSource Logger; public void Init(ConfigFile config, ManualLogSource logger) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_0073: Expected O, but got Unknown Config = config; Logger = logger; FloodCollapse.Init(Config, Logger); FloodIndependentWeapon.Init(Config, Logger); CorruptModeStats.Init(Config, Logger); PrimaryFireRate.Init(Config, Logger); Harmony val = new Harmony("com.sparkletwilight.sparklesurvivorstweaks.voidfiend"); FloodCollapse.Patch(val); FloodIndependentWeapon.Patch(val); CorruptModeStats.Patch(val); PrimaryFireRate.Patch(val); Logger.LogInfo((object)("SparkleVoidFiendTweaks v1.0.0 已加载。" + FloodCollapse.Summary() + FloodIndependentWeapon.Summary() + CorruptModeStats.Summary() + PrimaryFireRate.Summary())); } } } namespace SparkleToolbotTweaks { public static class BuzzsawDamage { private const string Section = "Toolbot"; private const float VanillaCoefficient = 1f; private const float DefaultCoefficient = 1.5f; private const int DiagnosticCount = 3; private static ConfigEntry<bool> _enabled; private static ConfigEntry<float> _coefficient; private static ManualLogSource _log; private static int _diagCount; private static readonly FieldInfo AttackField = AccessTools.Field(typeof(FireBuzzsaw), "attack"); private static readonly FieldInfo DamageStatField = AccessTools.Field(typeof(BaseState), "damageStat"); private static readonly FieldInfo CoefficientPerSecondField = AccessTools.Field(typeof(FireBuzzsaw), "damageCoefficientPerSecond"); private static readonly FieldInfo BaseFireFrequencyField = AccessTools.Field(typeof(FireBuzzsaw), "baseFireFrequency"); public static bool IsEnabled { get { if (_enabled != null) { return _enabled.Value; } return false; } } public static void Init(ConfigFile cfg, ManualLogSource logger) { _log = logger; _enabled = cfg.Bind<bool>("Toolbot", "BuzzsawDamageEnabled", true, "是否提高强力锯(MUL-T 主技能,每秒 10 跳那个)的每跳伤害倍率。false = 保持原版。"); _coefficient = cfg.Bind<float>("Toolbot", "BuzzsawDamageCoefficient", 1.5f, "强力锯每一跳的伤害倍率。1 = 原版 100%,1.5 = 150%。"); } public static void Patch(Harmony harmony) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown if (!IsEnabled) { Log((LogLevel)16, "强力锯伤害:按配置保持原版,不挂补丁。"); return; } if (AttackField == null || DamageStatField == null) { Log((LogLevel)2, "强力锯伤害补丁失败:取不到 FireBuzzsaw.attack / BaseState.damageStat。"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(FireBuzzsaw), "OnEnter", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "强力锯伤害补丁失败:取不到 Toolbot.FireBuzzsaw.OnEnter。"); return; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(BuzzsawDamage), "OnEnterPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "强力锯伤害补丁已挂载:每跳倍率 → " + Coefficient().ToString("0.###") + "(" + (Coefficient() * 100f).ToString("0") + "%)。"); } public static string Summary() { if (!IsEnabled) { return "强力锯伤害:按配置保持原版。"; } return "强力锯每跳伤害倍率:" + Coefficient().ToString("0.###") + "(" + (Coefficient() * 100f).ToString("0") + "%,原版 100%)。"; } private static void OnEnterPostfix(object __instance) { if (__instance == null || !IsEnabled) { return; } try { object value = AttackField.GetValue(__instance); if (value == null) { return; } FieldInfo fieldInfo = AccessTools.Field(value.GetType(), "damage"); if (fieldInfo == null) { Log((LogLevel)2, "强力锯伤害补丁失败:取不到 attack.damage。"); return; } float num = Convert.ToSingle(fieldInfo.GetValue(value)); float num2 = Convert.ToSingle(DamageStatField.GetValue(__instance)); float num3 = Coefficient(); float num4 = num2 * num3; fieldInfo.SetValue(value, num4); AttackField.SetValue(__instance, value); if (_diagCount >= 3) { return; } _diagCount++; string text = ""; if (CoefficientPerSecondField != null && BaseFireFrequencyField != null) { float num5 = Convert.ToSingle(CoefficientPerSecondField.GetValue(null)); float num6 = Convert.ToSingle(BaseFireFrequencyField.GetValue(null)); if (num6 > 0f) { text = ",原版每秒倍率 " + num5.ToString("0.##") + " / 每秒 " + num6.ToString("0.##") + " 跳 = 每跳 " + (num5 / num6 * 100f).ToString("0") + "%"; } } Log((LogLevel)16, "强力锯伤害 #" + _diagCount + ":每跳伤害 " + num.ToString("0.##") + " → " + num4.ToString("0.##") + "(倍率 → " + (num3 * 100f).ToString("0") + "%" + ((num2 > 0f) ? (",原版每跳约 " + (num / num2 * 100f).ToString("0") + "%") : "") + text + ")。"); } catch (Exception ex) { Log((LogLevel)2, "强力锯伤害补丁出错:" + ex.GetType().Name + " " + ex.Message); } } private static float Coefficient() { float num = ((_coefficient != null) ? _coefficient.Value : 1.5f); if (!(num > 0f)) { return 1f; } return num; } private static void Log(LogLevel level, string message) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (_log != null) { _log.Log(level, (object)message); } } } public static class NailgunProcCoefficient { private const string Section = "Toolbot"; private const float VanillaCoefficient = 0.6f; private const float DefaultCoefficient = 0.7f; private static ConfigEntry<float> _coefficient; private static ManualLogSource _log; private static int _replaced; private static bool _logged; private static readonly FieldInfo ProcCoefficientField = AccessTools.Field(typeof(BaseNailgunState), "procCoefficient"); public static void Init(ConfigFile cfg, ManualLogSource logger) { _log = logger; _coefficient = cfg.Bind<float>("Toolbot", "NailgunProcCoefficient", 0.7f, "自动钉枪(MUL-T 默认 M1)的触发系数(procCoefficient)。0.6 = 原版;填负数则保持原版不动。"); } public static void Patch(Harmony harmony) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown float num = Coefficient(); if (num < 0f) { Log((LogLevel)16, "自动钉枪触发系数:配置为负数,保持原版 " + 0.6f + "。"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(BaseNailgunState), "FireBullet", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "自动钉枪触发系数补丁失败:取不到 BaseNailgunState.FireBullet。"); return; } _replaced = 0; try { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(NailgunProcCoefficient), "FireBulletTranspiler", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { Log((LogLevel)2, "自动钉枪触发系数转译补丁失败:" + ex.GetType().Name + " " + ex.Message); _replaced = 0; } if (_replaced == 0) { Log((LogLevel)4, "自动钉枪触发系数:IL 里没找到 procCoefficient 读取,退回改写静态字段的方式。"); if (ProcCoefficientField == null) { Log((LogLevel)2, "自动钉枪触发系数补丁失败:取不到 BaseNailgunState.procCoefficient。"); return; } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(NailgunProcCoefficient), "FireBulletPrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } Log((LogLevel)16, "自动钉枪触发系数补丁已挂载:" + 0.6f + " → " + num.ToString("0.##") + "(" + ((_replaced > 0) ? ("IL 注入 " + _replaced + " 处") : "改写静态字段") + ")。"); } public static string Summary() { if (Coefficient() < 0f) { return "自动钉枪触发系数:保持原版。"; } return "自动钉枪触发系数:" + 0.6f + " → " + Coefficient().ToString("0.##") + ";"; } private static IEnumerable<CodeInstruction> FireBulletTranspiler(IEnumerable<CodeInstruction> instructions) { MethodInfo getter = AccessTools.Method(typeof(NailgunProcCoefficient), "GetCoefficient", (Type[])null, (Type[])null); foreach (CodeInstruction instruction in instructions) { FieldInfo fieldInfo = instruction.operand as FieldInfo; if (instruction.opcode == OpCodes.Ldsfld && fieldInfo != null && fieldInfo.Name == "procCoefficient") { _replaced++; yield return new CodeInstruction(OpCodes.Call, (object)getter); } else { yield return instruction; } } } private static float GetCoefficient() { float result = Coefficient(); if (!_logged) { _logged = true; Log((LogLevel)16, "自动钉枪 BulletAttack 触发系数已注入:" + result.ToString("0.##") + "(原版 " + 0.6f + ")。"); } return result; } private static void FireBulletPrefix() { if (ProcCoefficientField == null) { return; } try { ProcCoefficientField.SetValue(null, Coefficient()); } catch (Exception ex) { Log((LogLevel)2, "自动钉枪触发系数补丁出错:" + ex.GetType().Name + " " + ex.Message); } } private static float Coefficient() { if (_coefficient == null) { return 0.7f; } return _coefficient.Value; } private static void Log(LogLevel level, string message) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (_log != null) { _log.Log(level, (object)message); } } } public static class RebarPuncherFireRate { private const string Section = "Toolbot"; private const float DefaultInterval = 1f; private const float DefaultMinRecovery = 0.1f; private const float MinCharge = 0.05f; private const int DiagnosticCount = 3; private static ConfigEntry<bool> _enabled; private static ConfigEntry<float> _interval; private static ConfigEntry<float> _minRecovery; private static ConfigEntry<bool> _attackSpeedScaled; private static ManualLogSource _log; private static int _fireDiagCount; private static int _cooldownDiagCount; private static float _lastFireDuration = -1f; private static readonly FieldInfo FireSpearDurationField = AccessTools.Field(typeof(FireSpear), "duration"); private static readonly FieldInfo CooldownDurationField = AccessTools.Field(typeof(CooldownSpear), "duration"); private static readonly FieldInfo ChargeDurationField = AccessTools.Field(typeof(ChargeSpear), "chargeDuration"); private static readonly FieldInfo MinChargeDurationField = AccessTools.Field(typeof(ChargeSpear), "minChargeDuration"); private static readonly FieldInfo AttackSpeedStatField = AccessTools.Field(typeof(BaseState), "attackSpeedStat"); public static bool IsEnabled { get { if (_enabled != null) { return _enabled.Value; } return false; } } public static void Init(ConfigFile cfg, ManualLogSource logger) { _log = logger; _enabled = cfg.Bind<bool>("Toolbot", "RebarPuncherFireIntervalEnabled", true, "是否把钢筋发射器(MUL-T 主技能,600% 那个)的攻击间隔定成固定值。false = 保持原版节奏。"); _interval = cfg.Bind<float>("Toolbot", "RebarPuncherFireInterval", 1f, "钢筋发射器的攻击间隔(秒),即两次出手之间的总时间:出枪 + 收枪。"); _minRecovery = cfg.Bind<float>("Toolbot", "RebarPuncherMinRecovery", 0.1f, "钢筋发射器收枪阶段的保底时长(秒)。总间隔扣掉出枪时长剩下的都给收枪,但不少于这个值。"); _attackSpeedScaled = cfg.Bind<bool>("Toolbot", "RebarPuncherAttackSpeedScaled", true, "攻击间隔是否除以攻击速度(原版行为)。true = 攻速 2 就 0.5 秒一发;false = 固定 1 秒一发,不吃攻速道具。"); } public static void Patch(Harmony harmony) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Expected O, but got Unknown if (!IsEnabled) { Log((LogLevel)16, "钢筋发射器射速:按配置保持原版,不挂补丁。"); return; } if (FireSpearDurationField == null || CooldownDurationField == null) { Log((LogLevel)2, "钢筋发射器射速补丁失败:取不到 FireSpear.duration / CooldownSpear.duration。"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(FireSpear), "OnEnter", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(CooldownSpear), "OnEnter", (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null) { Log((LogLevel)2, "钢筋发射器射速补丁失败:取不到 FireSpear / CooldownSpear 的 OnEnter。"); return; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(RebarPuncherFireRate), "FireOnEnterPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(RebarPuncherFireRate), "CooldownOnEnterPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo3 = AccessTools.Method(typeof(ChargeSpear), "OnEnter", (Type[])null, (Type[])null); if (methodInfo3 != null && ChargeDurationField != null) { harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(RebarPuncherFireRate), "ChargeOnEnterPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } Log((LogLevel)16, "钢筋发射器射速补丁已挂载:总间隔 → " + Interval().ToString("0.###") + " 秒(出枪 + 收枪,收枪保底 " + MinRecovery().ToString("0.###") + ")" + (AttackSpeedScaled() ? ",会除以攻速" : ",不吃攻速") + "。"); } public static string Summary() { if (!IsEnabled) { return "钢筋发射器攻击间隔:按配置保持原版。"; } return "钢筋发射器攻击间隔:" + Interval().ToString("0.###") + " 秒" + (AttackSpeedScaled() ? "(还会除以攻速)" : "(不吃攻速)") + "。"; } private static void FireOnEnterPostfix(object __instance) { if (__instance == null || !IsEnabled) { return; } try { float num = AttackSpeed(__instance); float num2 = Convert.ToSingle(FireSpearDurationField.GetValue(__instance)); float num3 = Math.Min(AttackSpeedScaled() ? (num2 * num) : num2, Interval() - MinRecovery()); if (num3 < 0f) { num3 = 0f; } float num4 = (AttackSpeedScaled() ? (num3 / num) : num3); FireSpearDurationField.SetValue(__instance, num4); _lastFireDuration = num3; if (_fireDiagCount < 3) { _fireDiagCount++; Log((LogLevel)16, "钢筋发射器出枪 #" + _fireDiagCount + ":" + num2.ToString("0.###") + " → " + num4.ToString("0.###") + " 秒。"); } } catch (Exception ex) { Log((LogLevel)2, "钢筋发射器出枪补丁出错:" + ex.GetType().Name + " " + ex.Message); } } private static void CooldownOnEnterPostfix(object __instance) { if (__instance == null || !IsEnabled) { return; } try { float num = AttackSpeed(__instance); float num2 = Convert.ToSingle(CooldownDurationField.GetValue(__instance)); float num3 = ((_lastFireDuration >= 0f) ? _lastFireDuration : (Interval() - MinRecovery())); float num4 = Interval() - num3; if (num4 < MinRecovery()) { num4 = MinRecovery(); } float num5 = (AttackSpeedScaled() ? (num4 / num) : num4); CooldownDurationField.SetValue(__instance, num5); if (_cooldownDiagCount < 3) { _cooldownDiagCount++; Log((LogLevel)16, "钢筋发射器收枪 #" + _cooldownDiagCount + ":" + num2.ToString("0.###") + " → " + num5.ToString("0.###") + " 秒(出枪 " + num3.ToString("0.###") + ",合计 " + (num3 + num4).ToString("0.###") + " 秒)。"); } } catch (Exception ex) { Log((LogLevel)2, "钢筋发射器收枪补丁出错:" + ex.GetType().Name + " " + ex.Message); } } private static void ChargeOnEnterPostfix(object __instance) { if (__instance == null || !IsEnabled || ChargeDurationField == null) { return; } try { float num = AttackSpeed(__instance); float num2 = Interval() - MinRecovery() * 2f; if (num2 < 0.05f) { num2 = 0.05f; } float num3 = (AttackSpeedScaled() ? (num2 / num) : num2); ChargeDurationField.SetValue(__instance, num3); if (MinChargeDurationField != null) { MinChargeDurationField.SetValue(__instance, num3); } Log((LogLevel)16, "钢筋发射器蓄力:满蓄 / 最短蓄力 → " + num3.ToString("0.###") + " 秒(这条出现说明走的蓄力流程)。"); } catch (Exception ex) { Log((LogLevel)2, "钢筋发射器蓄力补丁出错:" + ex.GetType().Name + " " + ex.Message); } } private static float AttackSpeed(object instance) { float num = 1f; if (AttackSpeedStatField != null && instance != null) { try { num = Convert.ToSingle(AttackSpeedStatField.GetValue(instance)); } catch { num = 1f; } } if (!(num > 0f)) { return 1f; } return num; } private static float Interval() { float num = ((_interval != null) ? _interval.Value : 1f); if (!(num > 0f)) { return 1f; } return num; } private static float MinRecovery() { float num = ((_minRecovery != null) ? _minRecovery.Value : 0.1f); if (!(num >= 0f)) { return 0.1f; } return num; } private static bool AttackSpeedScaled() { if (_attackSpeedScaled != null) { return _attackSpeedScaled.Value; } return false; } private static void Log(LogLevel level, string message) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (_log != null) { _log.Log(level, (object)message); } } } public static class ScrapLauncherBurst { private const string Section = "Toolbot"; private const int VanillaMaxStock = 4; private const float VanillaRechargeInterval = 2.5f; private const int DiagnosticCount = 3; private static ConfigEntry<bool> _enabled; private static ConfigEntry<int> _maxStock; private static ConfigEntry<float> _rechargeInterval; private static ConfigEntry<int> _projectileCount; private static ConfigEntry<float> _spread; private static ManualLogSource _log; private static int _diagCount; private static bool _bursting; private static readonly MethodInfo FireProjectileMethod = AccessTools.Method(typeof(GenericProjectileBaseState), "FireProjectile", (Type[])null, (Type[])null); private static readonly MethodInfo GetAimRayMethod = AccessTools.Method(typeof(BaseState), "GetAimRay", (Type[])null, (Type[])null); private static readonly FieldInfo AimRayOverrideField = AccessTools.Field(typeof(GenericProjectileBaseState), "aimRayOverride"); public static bool IsEnabled { get { if (_enabled != null) { return _enabled.Value; } return false; } } public static void Init(ConfigFile cfg, ManualLogSource logger) { _log = logger; _enabled = cfg.Bind<bool>("Toolbot", "ScrapLauncherBurstEnabled", true, "碎片发射器是否改成「最多 1 发弹仓 + 一次打出多枚火箭」。false = 原版 4 发弹仓、每次 1 枚。"); _maxStock = cfg.Bind<int>("Toolbot", "ScrapLauncherMaxStock", 1, "碎片发射器的弹药上限。1 = 最多攒 1 发(原版 4)。"); _rechargeInterval = cfg.Bind<float>("Toolbot", "ScrapLauncherRechargeInterval", 0f, "碎片发射器的冷却时间(秒)。0 = 无冷却,和另外三个主技能一样,节奏只由出手动作决定(原版 2.5)。"); _projectileCount = cfg.Bind<int>("Toolbot", "ScrapLauncherProjectileCount", 1, "碎片发射器每次开火发射几枚火箭。"); _spread = cfg.Bind<float>("Toolbot", "ScrapLauncherProjectileSpread", 4f, "多枚火箭之间的散布角(度)。0 = 完全重合,容易挤在一起。"); } public static void Patch(Harmony harmony) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown if (!IsEnabled) { Log((LogLevel)16, "碎片发射器连发:按配置保持原版(4 发弹仓、每次 1 枚)。"); return; } if (FireProjectileMethod == null || GetAimRayMethod == null || AimRayOverrideField == null) { Log((LogLevel)2, "碎片发射器连发补丁失败:取不到 FireProjectile / GetAimRay / aimRayOverride。"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(SkillCatalog), "Init", (Type[])null, (Type[])null); if (methodInfo != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(ScrapLauncherBurst), "SkillCatalogInitPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { Log((LogLevel)2, "碎片发射器弹药补丁失败:取不到 SkillCatalog.Init。"); } harmony.Patch((MethodBase)FireProjectileMethod, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(ScrapLauncherBurst), "FireProjectilePostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "碎片发射器连发补丁已挂载:弹药上限 " + 4 + " → " + MaxStock() + ",冷却 " + 2.5f.ToString("0.###") + " → " + RechargeInterval().ToString("0.###") + " 秒,每次发射 " + Count() + " 枚,散布 " + Spread().ToString("0.#") + " 度。"); } public static string Summary() { if (!IsEnabled) { return "碎片发射器连发:按配置保持原版。"; } string text = ((RechargeInterval() <= 0f) ? "无冷却" : (RechargeInterval().ToString("0.###") + " 秒")); return "碎片发射器:弹药上限 " + MaxStock() + "(原版 " + 4 + "),冷却 " + text + "(原版 " + 2.5f.ToString("0.###") + " 秒),每次发射 " + Count() + " 枚火箭(散布 " + Spread().ToString("0.#") + " 度)。"; } private static void SkillCatalogInitPostfix() { if (!IsEnabled) { return; } try { int num = MaxStock(); int num2 = 0; foreach (SkillDef allSkillDef in SkillCatalog.allSkillDefs) { if (!((Object)(object)allSkillDef == (Object)null) && IsScrapLauncher(allSkillDef)) { if (allSkillDef.baseMaxStock != num) { Log((LogLevel)16, "碎片发射器弹药:SkillDef「" + allSkillDef.skillName + "」baseMaxStock " + allSkillDef.baseMaxStock + " → " + num + "。"); allSkillDef.baseMaxStock = num; } float num3 = RechargeInterval(); if (Math.Abs(allSkillDef.baseRechargeInterval - num3) > 0.0001f) { Log((LogLevel)16, "碎片发射器冷却:SkillDef「" + allSkillDef.skillName + "」baseRechargeInterval " + allSkillDef.baseRechargeInterval.ToString("0.###") + " → " + num3.ToString("0.###") + ((num3 <= 0f) ? "(无冷却)" : "") + "。"); allSkillDef.baseRechargeInterval = num3; } num2++; if (num2 >= 2) { break; } } } if (num2 == 0) { Log((LogLevel)4, "碎片发射器弹药:技能目录里没找到碎片发射器的 SkillDef,弹药上限没改。"); } } catch (Exception ex) { Log((LogLevel)2, "碎片发射器弹药补丁出错:" + ex.GetType().Name + " " + ex.Message); } } private static void FireProjectilePostfix(object __instance) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) if (__instance == null || !IsEnabled || _bursting || !(__instance is FireGrenadeLauncher)) { return; } int num = Count(); if (num <= 1) { return; } object value = AimRayOverrideField.GetValue(__instance); _bursting = true; try { Ray val = ((value != null) ? ((Ray)value) : ((Ray)GetAimRayMethod.Invoke(__instance, null))); Vector3 origin = ((Ray)(ref val)).origin; Vector3 val2 = ((Ray)(ref val)).direction; if (((Vector3)(ref val2)).sqrMagnitude > 0f) { ((Vector3)(ref val2)).Normalize(); } else { val2 = Vector3.forward; } Vector3 val3 = Vector3.Cross(val2, Vector3.up); if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f) { val3 = Vector3.right; } ((Vector3)(ref val3)).Normalize(); float num2 = Spread(); int num3 = 1; for (int i = 1; i < num; i++) { Vector3 val4 = Quaternion.AngleAxis(360f / (float)num * (float)i, val2) * (Quaternion.AngleAxis(num2, val3) * val2); AimRayOverrideField.SetValue(__instance, (object)new Ray(origin, val4)); FireProjectileMethod.Invoke(__instance, null); num3++; } if (_diagCount < 3) { _diagCount++; Log((LogLevel)16, "碎片发射器连发 #" + _diagCount + ":本次发射 " + num3 + " 枚(原版 1 枚),散布 " + num2.ToString("0.#") + " 度。"); } } catch (Exception ex) { Log((LogLevel)2, "碎片发射器连发补丁出错:" + ex.GetType().Name + " " + ex.Message); } finally { _bursting = false; try { AimRayOverrideField.SetValue(__instance, value); } catch (Exception ex2) { Log((LogLevel)2, "碎片发射器连发:还原 aimRayOverride 失败 —— " + ex2.GetType().Name + " " + ex2.Message); } } } private static bool IsScrapLauncher(SkillDef def) { if (((SerializableEntityStateType)(ref def.activationState)).stateType == typeof(FireGrenadeLauncher)) { return true; } if (!string.IsNullOrEmpty(def.skillNameToken)) { return def.skillNameToken.IndexOf("TOOLBOT_PRIMARY_ALT2", StringComparison.OrdinalIgnoreCase) >= 0; } return false; } private static int MaxStock() { int num = ((_maxStock == null) ? 1 : _maxStock.Value); if (num < 1) { return 1; } return num; } private static float RechargeInterval() { float num = ((_rechargeInterval != null) ? _rechargeInterval.Value : 0f); if (!(num >= 0f)) { return 0f; } return num; } private static int Count() { int num = ((_projectileCount == null) ? 1 : _projectileCount.Value); if (num < 1) { return 1; } return num; } private static float Spread() { float num = ((_spread != null) ? _spread.Value : 4f); if (!(num >= 0f)) { return 0f; } return num; } private static void Log(LogLevel level, string message) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (_log != null) { _log.Log(level, (object)message); } } } public static class ScrapLauncherFireRate { private const string Section = "Toolbot"; private const float DefaultInterval = 0.5f; private const int DiagnosticCount = 5; private static ConfigEntry<bool> _enabled; private static ConfigEntry<float> _interval; private static ConfigEntry<bool> _attackSpeedScaled; private static ManualLogSource _log; private static int _diagCount; private static readonly FieldInfo DurationField = AccessTools.Field(typeof(GenericProjectileBaseState), "duration"); private static readonly FieldInfo DelayField = AccessTools.Field(typeof(GenericProjectileBaseState), "delayBeforeFiringProjectile"); private static readonly FieldInfo DamageCoefficientField = AccessTools.Field(typeof(GenericProjectileBaseState), "damageCoefficient"); private static readonly FieldInfo AttackSpeedStatField = AccessTools.Field(typeof(BaseState), "attackSpeedStat"); public static bool IsEnabled { get { if (_enabled != null) { return _enabled.Value; } return false; } } public static void Init(ConfigFile cfg, ManualLogSource logger) { _log = logger; _enabled = cfg.Bind<bool>("Toolbot", "ScrapLauncherFireIntervalEnabled", true, "是否缩短碎片发射器(MUL-T 主技能)的发射间隔。false = 保持原版节奏。"); _interval = cfg.Bind<float>("Toolbot", "ScrapLauncherFireInterval", 0.5f, "碎片发射器的基础攻击间隔(秒),即两次出手之间的时间。0.5 = 0.5 秒一次。"); _attackSpeedScaled = cfg.Bind<bool>("Toolbot", "ScrapLauncherAttackSpeedScaled", true, "碎片发射器的攻击间隔是否除以攻击速度(原版行为)。true = 攻速 2 就 0.5 秒一次;false = 固定 1 秒一次,不吃攻速道具。"); } public static void Patch(Harmony harmony) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown if (!IsEnabled) { Log((LogLevel)16, "碎片发射器射速:按配置保持原版,不挂补丁。"); return; } if (DurationField == null || DelayField == null) { Log((LogLevel)2, "碎片发射器射速补丁失败:取不到 GenericProjectileBaseState 的 duration / delayBeforeFiringProjectile。"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(FireGrenadeLauncher), "OnEnter", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "碎片发射器射速补丁失败:取不到 Toolbot.FireGrenadeLauncher.OnEnter。"); return; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(ScrapLauncherFireRate), "OnEnterPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "碎片发射器射速补丁已挂载:Toolbot.FireGrenadeLauncher.OnEnter,发射间隔 → " + Interval().ToString("0.####") + " 秒" + (AttackSpeedScaled() ? "(还会除以攻速)" : "(不吃攻速)") + "。"); } public static string Summary() { if (!IsEnabled) { return "碎片发射器射速:按配置保持原版。"; } return "碎片发射器攻击间隔:" + Interval().ToString("0.###") + " 秒" + (AttackSpeedScaled() ? "(还会除以攻速)" : "(不吃攻速)") + "。"; } private static void OnEnterPostfix(object __instance) { if (__instance == null || !IsEnabled) { return; } try { float num = 1f; if (AttackSpeedStatField != null) { num = Convert.ToSingle(AttackSpeedStatField.GetValue(__instance)); } if (num <= 0f) { num = 1f; } float num2 = Interval(); if (AttackSpeedScaled()) { num2 /= num; } float num3 = Convert.ToSingle(DurationField.GetValue(__instance)); float num4 = Convert.ToSingle(DelayField.GetValue(__instance)); DurationField.SetValue(__instance, num2); if (num4 > num2) { DelayField.SetValue(__instance, num2); } if (_diagCount < 5) { _diagCount++; float num5 = 0f; if (DamageCoefficientField != null) { num5 = Convert.ToSingle(DamageCoefficientField.GetValue(__instance)); } Log((LogLevel)16, "碎片发射器射速 #" + _diagCount + ":间隔 " + num3.ToString("0.###") + " → " + num2.ToString("0.###") + " 秒(基础 " + Interval().ToString("0.###") + " / 攻速 " + num.ToString("0.##") + "),发射延迟 " + num4.ToString("0.###") + ",伤害倍率 " + num5.ToString("0.###") + "(伤害以 200% 那条模块的日志为准)。"); } } catch (Exception ex) { Log((LogLevel)2, "碎片发射器射速补丁出错:" + ex.GetType().Name + " " + ex.Message); } } private static float Interval() { float num = ((_interval != null) ? _interval.Value : 0.5f); if (!(num > 0f)) { return 0.5f; } return num; } private static bool AttackSpeedScaled() { if (_attackSpeedScaled != null) { return _attackSpeedScaled.Value; } return false; } private static void Log(LogLevel level, string message) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (_log != null) { _log.Log(level, (object)message); } } } public static class ScrapLauncherHoming { private const string Section = "Toolbot"; private const float VanillaCoefficient = 3.6f; private const float DefaultCoefficient = 3.6f; private const int DiagnosticCount = 3; private static ConfigEntry<float> _coefficient; private static ConfigEntry<bool> _homingEnabled; private static ConfigEntry<float> _homingRange; private static ConfigEntry<float> _homingCone; private static ConfigEntry<float> _homingRotationSpeed; private static ManualLogSource _log; private static int _diagCount; private static readonly HashSet<int> PatchedPrefabs = new HashSet<int>(); private static readonly FieldInfo DamageCoefficientField = AccessTools.Field(typeof(GenericProjectileBaseState), "damageCoefficient"); private static readonly FieldInfo ProjectilePrefabField = AccessTools.Field(typeof(GenericProjectileBaseState), "projectilePrefab"); public static void Init(ConfigFile cfg, ManualLogSource logger) { _log = logger; _coefficient = cfg.Bind<float>("Toolbot", "ScrapLauncherDamageCoefficient", 3.6f, "碎片发射器(MUL-T 主技能)每枚火箭的伤害倍率。3.6 = 360%(也是原版值),2 = 200%。"); _homingEnabled = cfg.Bind<bool>("Toolbot", "ScrapLauncherHomingEnabled", true, "碎片发射器的火箭弹是否主动追踪敌人(类似磁轨炮手 M1 的 XQR 智能弹药)。"); _homingRange = cfg.Bind<float>("Toolbot", "ScrapLauncherHomingRange", 60f, "追踪搜索距离(米)。"); _homingCone = cfg.Bind<float>("Toolbot", "ScrapLauncherHomingCone", 25f, "追踪搜索锥角(度),以火箭当前朝向为中心的圆锥。"); _homingRotationSpeed = cfg.Bind<float>("Toolbot", "ScrapLauncherHomingRotationSpeed", 360f, "追踪转向速度(度/秒)。越大咬得越紧。"); } public static void Patch(Harmony harmony) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown if (DamageCoefficientField == null || ProjectilePrefabField == null) { Log((LogLevel)2, "碎片发射器伤害/追踪补丁失败:取不到 GenericProjectileBaseState 的 damageCoefficient / projectilePrefab。"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(FireGrenadeLauncher), "OnEnter", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "碎片发射器伤害/追踪补丁失败:取不到 Toolbot.FireGrenadeLauncher.OnEnter。"); return; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(ScrapLauncherHoming), "OnEnterPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "碎片发射器伤害补丁已挂载:倍率 → " + Coefficient().ToString("0.###") + "(" + (Coefficient() * 100f).ToString("0") + "%);追踪 " + (IsHomingEnabled() ? ("开启,范围 " + Range().ToString("0") + " 米 / 锥角 " + Cone().ToString("0") + " 度 / 转向 " + RotationSpeed().ToString("0") + " 度每秒") : "关闭") + "。"); } public static string Summary() { return string.Concat("碎片发射器伤害倍率:" + Coefficient().ToString("0.###") + "(" + (Coefficient() * 100f).ToString("0") + "%,原版 360%);", IsHomingEnabled() ? "火箭追踪:开启。" : "火箭追踪:关闭。"); } public static bool IsHomingEnabled() { if (_homingEnabled != null) { return _homingEnabled.Value; } return false; } private static void OnEnterPostfix(object __instance) { if (__instance == null) { return; } try { float num = Convert.ToSingle(DamageCoefficientField.GetValue(__instance)); float num2 = Coefficient(); if (Math.Abs(num - num2) > 0.0001f) { DamageCoefficientField.SetValue(__instance, num2); } if (IsHomingEnabled()) { object? value = ProjectilePrefabField.GetValue(__instance); EnsureHoming((GameObject)((value is GameObject) ? value : null)); } if (_diagCount < 3) { _diagCount++; Log((LogLevel)16, "碎片发射器伤害/追踪 #" + _diagCount + ":倍率 " + num.ToString("0.###") + " → " + num2.ToString("0.###") + "(" + (num2 * 100f).ToString("0") + "%)" + (IsHomingEnabled() ? ",追踪已就绪" : ",追踪按配置关闭") + "。"); } } catch (Exception ex) { Log((LogLevel)2, "碎片发射器伤害/追踪补丁出错:" + ex.GetType().Name + " " + ex.Message); } } private static void EnsureHoming(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { return; } int instanceID = ((Object)prefab).GetInstanceID(); if (!PatchedPrefabs.Contains(instanceID)) { PatchedPrefabs.Add(instanceID); if ((Object)(object)prefab.GetComponent<ProjectileTargetComponent>() == (Object)null) { prefab.AddComponent<ProjectileTargetComponent>(); } if ((Object)(object)prefab.GetComponent<ProjectileDirectionalTargetFinder>() == (Object)null) { ProjectileDirectionalTargetFinder obj = prefab.AddComponent<ProjectileDirectionalTargetFinder>(); obj.lookRange = Range(); obj.lookCone = Cone(); obj.targetSearchInterval = 0.1f; obj.onlySearchIfNoTarget = false; obj.allowTargetLoss = true; obj.testLoS = false; obj.ignoreAir = false; } if ((Object)(object)prefab.GetComponent<ProjectileSteerTowardTarget>() == (Object)null) { ProjectileSteerTowardTarget obj2 = prefab.AddComponent<ProjectileSteerTowardTarget>(); obj2.rotationSpeed = RotationSpeed(); obj2.yAxisOnly = false; obj2.modifySpeedOverTime = false; } ProjectileSimple component = prefab.GetComponent<ProjectileSimple>(); if ((Object)(object)component != (Object)null && !component.updateAfterFiring) { component.updateAfterFiring = true; } Log((LogLevel)16, "碎片发射器追踪已挂到火箭预制体「" + ((Object)prefab).name + "」:" + (((Object)(object)component != (Object)null) ? ("ProjectileSimple.updateAfterFiring=" + component.updateAfterFiring) : "警告:预制体上没有 ProjectileSimple,火箭可能不是靠它推进的") + "。"); } } private static float Coefficient() { float num = ((_coefficient != null) ? _coefficient.Value : 3.6f); if (!(num > 0f)) { return 3.6f; } return num; } private static float Range() { float num = ((_homingRange != null) ? _homingRange.Value : 60f); if (!(num > 0f)) { return 60f; } return num; } private static float Cone() { float num = ((_homingCone != null) ? _homingCone.Value : 25f); if (!(num > 0f)) { return 25f; } return num; } private static float RotationSpeed() { float num = ((_homingRotationSpeed != null) ? _homingRotationSpeed.Value : 360f); if (!(num > 0f)) { return 360f; } return num; } private static void Log(LogLevel level, string message) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (_log != null) { _log.Log(level, (object)message); } } } public static class ScrapLauncherPocketIcbm { private const string Section = "Toolbot"; private const float DefaultSpread = 15f; private const int DiagnosticCount = 3; private static ConfigEntry<bool> _enabled; private static ConfigEntry<float> _spread; private static ManualLogSource _log; private static int _diagCount; private static bool Enabled { get { if (_enabled != null) { return _enabled.Value; } return true; } } public static void Init(ConfigFile cfg, ManualLogSource logger) { _log = logger; _enabled = cfg.Bind<bool>("Toolbot", "ScrapLauncherPocketIcbmEnabled", true, "碎片发射器(MUL-T 主技能)是否受「袖珍型洲际导弹」影响:持有该物品时每次开火额外发射 2 枚导弹,且伤害 × 导弹倍率。"); _spread = cfg.Bind<float>("Toolbot", "ScrapLauncherPocketIcbmSpread", 15f, "额外两枚导弹相对主弹的扩散角(度),原版导弹类物品用的是 45。"); } public static void Patch(Harmony harmony) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown if (!Enabled) { Log((LogLevel)16, "碎片发射器「袖珍型洲际导弹」联动:按配置未启用。"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(FireGrenadeLauncher), "ModifyProjectileInfo", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "碎片发射器「袖珍型洲际导弹」联动补丁失败:取不到 FireGrenadeLauncher.ModifyProjectileInfo。"); return; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(ScrapLauncherPocketIcbm), "ModifyProjectileInfoPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "碎片发射器「袖珍型洲际导弹」联动补丁已挂载:额外 2 枚导弹,扩散 ±" + Spread().ToString("0") + " 度,伤害倍率走原版 MissileUtils。"); } public static string Summary() { if (!Enabled) { return "碎片发射器洲际导弹联动:关闭。"; } return "碎片发射器洲际导弹联动:开启(+2 枚,±" + Spread().ToString("0") + " 度);"; } public static void ModifyProjectileInfoPostfix(object __instance, ref FireProjectileInfo fireProjectileInfo) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) if (!Enabled) { return; } try { CharacterBody val = OwnerBody(fireProjectileInfo.owner); if ((Object)(object)val == (Object)null || (Object)(object)val.inventory == (Object)null) { return; } ItemDef moreMissile = Items.MoreMissile; if ((Object)(object)moreMissile == (Object)null) { return; } int itemCountEffective = val.inventory.GetItemCountEffective(moreMissile); if (itemCountEffective > 0) { float moreMissileDamageMultiplier = MissileUtils.GetMoreMissileDamageMultiplier(itemCountEffective); float damage = fireProjectileInfo.damage; fireProjectileInfo.damage *= moreMissileDamageMultiplier; FireProjectileInfo val2 = fireProjectileInfo; val2.rotation = Quaternion.AngleAxis(Spread(), Vector3.up) * fireProjectileInfo.rotation; ProjectileManager.instance.FireProjectile(val2); val2.rotation = Quaternion.AngleAxis(0f - Spread(), Vector3.up) * fireProjectileInfo.rotation; ProjectileManager.instance.FireProjectile(val2); if (_diagCount < 3) { _diagCount++; Log((LogLevel)16, "碎片发射器洲际导弹 #" + _diagCount + ":层数 " + itemCountEffective + ",伤害倍率 " + moreMissileDamageMultiplier.ToString("0.##") + "(" + damage.ToString("0.#") + " → " + fireProjectileInfo.damage.ToString("0.#") + "),额外发射 2 枚,扩散 ±" + Spread().ToString("0") + " 度。"); } } } catch (Exception ex) { Log((LogLevel)2, "碎片发射器洲际导弹联动出错:" + ex.GetType().Name + " " + ex.Message); } } private static CharacterBody OwnerBody(GameObject owner) { if ((Object)(object)owner == (Object)null) { return null; } return owner.GetComponent<CharacterBody>(); } private static float Spread() { if (_spread == null) { return 15f; } return _spread.Value; } private static void Log(LogLevel level, string message) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (_log != null) { _log.Log(level, (object)message); } } } public static class ToolbotDamage { private const string Section = "Toolbot"; private const string ToolbotNameToken = "TOOLBOT_BODY_NAME"; private const float VanillaBaseDamage = 11f; private const float VanillaLevelDamage = 2.2f; private const float DefaultBaseDamage = 12f; private const float DefaultLevelDamage = 2.4f; private const int DiagnosticCount = 3; private static ConfigEntry<bool> _enabled; private static ConfigEntry<float> _baseDamage; private static ConfigEntry<float> _levelDamage; private static ManualLogSource _log; private static int _diagCount; private static readonly FieldInfo BaseDamageField = AccessTools.Field(typeof(CharacterBody), "baseDamage"); private static readonly FieldInfo LevelDamageField = AccessTools.Field(typeof(CharacterBody), "levelDamage"); public static bool IsEnabled { get { if (_enabled != null) { return _enabled.Value; } return false; } } public static void Init(ConfigFile cfg, ManualLogSource logger) { _log = logger; _enabled = cfg.Bind<bool>("Toolbot", "ToolbotDamageEnabled", true, "是否提高多功能枪兵(MUL-T)的基础攻击力。false = 保持原版 11(每级 +2.2)。"); _baseDamage = cfg.Bind<float>("Toolbot", "ToolbotBaseDamage", 12f, "多功能枪兵的基础攻击力(原版 11)。"); _levelDamage = cfg.Bind<float>("Toolbot", "ToolbotLevelDamage", 2.4f, "多功能枪兵每升一级增加的攻击力(原版 2.2)。"); } public static void Patch(Harmony harmony) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown if (!IsEnabled) { Log((LogLevel)16, "多功能枪兵攻击力:按配置保持原版,不挂补丁。"); return; } if (BaseDamageField == null || LevelDamageField == null) { Log((LogLevel)2, "多功能枪兵攻击力补丁失败:取不到 CharacterBody 的 baseDamage / levelDamage。"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(CharacterBody), "RecalculateStats", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "多功能枪兵攻击力补丁失败:取不到 CharacterBody.RecalculateStats。"); return; } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(ToolbotDamage), "RecalculateStatsPrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "多功能枪兵攻击力补丁已挂载:基础伤害 → " + BaseDamage().ToString("0.##") + ",每级 +" + LevelDamage().ToString("0.##") + "。"); } public static string Summary() { if (!IsEnabled) { return "多功能枪兵攻击力:按配置保持原版。"; } return "多功能枪兵攻击力:" + BaseDamage().ToString("0.##") + "(每级 +" + LevelDamage().ToString("0.##") + "),原版 " + 11f.ToString("0.##") + "(每级 +" + 2.2f.ToString("0.##") + ")。"; } private static void RecalculateStatsPrefix(CharacterBody __instance)