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 SparkleCaptainTweaks v1.3.0
plugins/SparkleCaptainTweaks.dll
Decompiled 19 hours agousing System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using EntityStates.Captain.Weapon; using EntityStates.CaptainSupplyDrop; using HarmonyLib; using Microsoft.CodeAnalysis; using R2API; using RoR2; using RoR2.Orbs; using RoR2.Projectile; using RoR2.Skills; using UnityEngine; using UnityEngine.Networking; [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("SparkleCaptainTweaks")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.3.0.0")] [assembly: AssemblyInformationalVersion("1.3.0")] [assembly: AssemblyProduct("SparkleCaptainTweaks")] [assembly: AssemblyTitle("SparkleCaptainTweaks")] [assembly: AssemblyVersion("1.3.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SparkleCaptainTweaks { internal static class CaptainOrbitalProbe { private const string UtilityToken = "CAPTAIN_UTILITY_NAME"; private const float VanillaDamageCoefficient = 10f; private const float VanillaCooldown = 11f; private static ManualLogSource _log; private static ConfigEntry<bool> _damageEnabled; private static ConfigEntry<float> _damagePercent; private static ConfigEntry<bool> _cooldownEnabled; private static ConfigEntry<float> _cooldown; private static readonly FieldInfo _damageField = AccessTools.Field(typeof(AimThrowableBase), "damageCoefficient"); private static float _base = -1f; private static bool _damageAppliedLogged; private static int _damageAppliedCount; private static bool _cooldownDone; private static bool _cooldownFailedLogged; private static bool DamageEnabled { get { if (_damageEnabled != null) { return _damageEnabled.Value; } return true; } } private static bool CooldownEnabled { get { if (_cooldownEnabled != null) { return _cooldownEnabled.Value; } return true; } } internal static void Init(ConfigFile config, ManualLogSource log) { _log = log; _damageEnabled = config.Bind<bool>("Utility.轨道探测器", "DamageEnabled", true, "是否把 Shift「轨道探测器」的伤害从每台 1000% 提升到 2000%。"); _damagePercent = config.Bind<float>("Utility.轨道探测器", "DamagePercent", 2000f, "每台轨道探测器的伤害百分比。2000 = 每台 2000% 伤害;1000 = 原版。"); _cooldownEnabled = config.Bind<bool>("Utility.轨道探测器", "CooldownEnabled", true, "是否把 Shift「轨道探测器」的冷却时间从 11 秒提升到 20 秒。"); _cooldown = config.Bind<float>("Utility.轨道探测器", "Cooldown", 20f, "Shift「轨道探测器」的冷却时间(秒)。20 = 20 秒;11 = 原版。"); } internal static string Summary() { string text = " [Shift伤害:原版1000%]"; string text2 = " [Shift冷却:原版11s]"; if (DamageEnabled) { float num = ((_base > 0f) ? _base : 10f); text = " [Shift伤害:" + (num * 100f).ToString("0") + "% → " + DamagePercent().ToString("0") + "%]"; } if (CooldownEnabled) { text2 = " [Shift冷却:11s → " + Cooldown().ToString("0.##") + "s]"; } return text + text2; } private static float DamagePercent() { if (_damagePercent == null) { return 2000f; } return _damagePercent.Value; } private static float Cooldown() { if (_cooldown == null) { return 20f; } return Math.Max(0f, _cooldown.Value); } internal static void Patch(Harmony harmony) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown if (!DamageEnabled) { Log((LogLevel)16, "Shift 探测器伤害:按配置保持原版,不挂补丁。"); return; } if (_damageField == null) { Log((LogLevel)2, "Shift 探测器伤害补丁失败:取不到 AimThrowableBase.damageCoefficient。"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(AimThrowableBase), "FireProjectile", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "Shift 探测器伤害补丁失败:取不到 AimThrowableBase.FireProjectile。"); return; } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(CaptainOrbitalProbe), "FireProjectilePrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "补丁已挂载:EntityStates.AimThrowableBase.FireProjectile <- CaptainOrbitalProbe.FireProjectilePrefix(每台探测器伤害 → " + DamagePercent().ToString("0") + "%)"); } internal static void Tick() { if (!CooldownEnabled || _cooldownDone) { return; } try { SkillDef val = FindUtilitySkillDef(); if (!((Object)(object)val == (Object)null)) { float baseRechargeInterval = val.baseRechargeInterval; float num = Cooldown(); if (Math.Abs(baseRechargeInterval - num) < 0.001f) { _cooldownDone = true; return; } val.baseRechargeInterval = num; _cooldownDone = true; Log((LogLevel)16, "Shift「轨道探测器」冷却已改:" + baseRechargeInterval.ToString("0.##") + " 秒 → " + num.ToString("0.##") + " 秒(SkillDef: " + val.skillName + ",原版 " + 11f.ToString("0.##") + ")。"); RefreshCaptainBodies(); } } catch (Exception ex) { if (!_cooldownFailedLogged) { _cooldownFailedLogged = true; Log((LogLevel)4, "改 Shift 冷却时异常(下一帧会重试一次)—— " + ex.GetType().Name + " " + ex.Message); } } } private static SkillDef FindUtilitySkillDef() { IEnumerable<SkillDef> allSkillDefs = SkillCatalog.allSkillDefs; if (allSkillDefs == null) { return null; } SkillDef val = null; foreach (SkillDef item in allSkillDefs) { if (!((Object)(object)item == (Object)null) && string.Equals(item.skillNameToken, "CAPTAIN_UTILITY_NAME", StringComparison.Ordinal) && !(item.baseRechargeInterval <= 0.001f)) { string text = StateTypeName(item); if (!string.IsNullOrEmpty(text) && text.IndexOf("SetupAirstrike", StringComparison.Ordinal) >= 0) { return item; } if ((Object)(object)val == (Object)null || item.baseRechargeInterval > val.baseRechargeInterval) { val = item; } } } return val; } private static string StateTypeName(SkillDef def) { try { string typeName = ((SerializableEntityStateType)(ref def.activationState)).typeName; if (!string.IsNullOrEmpty(typeName)) { return typeName; } Type stateType = ((SerializableEntityStateType)(ref def.activationState)).stateType; return (stateType != null) ? stateType.FullName : null; } catch (Exception) { return null; } } private static void RefreshCaptainBodies() { try { ReadOnlyCollection<CharacterBody> readOnlyInstancesList = CharacterBody.readOnlyInstancesList; if (readOnlyInstancesList == null) { return; } int num = 0; foreach (CharacterBody item in readOnlyInstancesList) { if (!((Object)(object)item == (Object)null) && !((Object)(object)item.skillLocator == (Object)null) && ((Object)item).name != null && ((Object)item).name.IndexOf("CaptainBody", StringComparison.Ordinal) >= 0) { GenericSkill utility = item.skillLocator.utility; if (!((Object)(object)utility == (Object)null)) { utility.RecalculateValues(); num++; } } } if (num > 0) { Log((LogLevel)16, "已让场上 " + num + " 个船长按新冷却重算技能数值。"); } } catch (Exception ex) { Log((LogLevel)4, "刷新船长技能数值时异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message); } } public static void FireProjectilePrefix(AimThrowableBase __instance) { try { if (DamageEnabled && __instance != null && !(_damageField == null) && (__instance is CallAirstrike1 || __instance is CallAirstrike2 || __instance is CallAirstrike3)) { if (_base < 0f) { _base = (float)_damageField.GetValue(__instance); Log((LogLevel)16, "Shift「轨道探测器」原版伤害系数 = " + _base.ToString("0.###") + "(原版 10 = 1000%;若不是 10 说明游戏改过数值,百分比仍按百分比生效)。"); } float num = DamagePercent() / 100f; _damageField.SetValue(__instance, num); _damageAppliedCount++; if (!_damageAppliedLogged) { _damageAppliedLogged = true; Log((LogLevel)16, "Shift「轨道探测器」伤害已生效:" + (_base * 100f).ToString("0") + "% → " + (num * 100f).ToString("0") + "% 每台(" + ((object)__instance).GetType().Name + ")。"); } else if (_damageAppliedCount % 20 == 0) { Log((LogLevel)16, "Shift「轨道探测器」伤害已应用 " + _damageAppliedCount + " 次,当前每台 " + (num * 100f).ToString("0") + "%。"); } } } catch (Exception ex) { Log((LogLevel)4, "Shift 探测器:改写伤害系数时异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message); } } 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 static class CaptainShotgunCharge { private const float VanillaBaseChargeDuration = 1.2f; private static ManualLogSource _log; private static ConfigEntry<bool> _enabled; private static ConfigEntry<float> _multiplier; private static ConfigEntry<float> _minMultiplier; private static readonly FieldInfo _baseChargeDurationField = AccessTools.Field(typeof(ChargeCaptainShotgun), "baseChargeDuration"); private static readonly FieldInfo _minBaseChargeDurationField = AccessTools.Field(typeof(ChargeCaptainShotgun), "baseMinChargeDuration"); private static readonly FieldInfo _chargeDurationField = AccessTools.Field(typeof(ChargeCaptainShotgun), "chargeDuration"); private static readonly FieldInfo _minChargeDurationField = AccessTools.Field(typeof(ChargeCaptainShotgun), "minChargeDuration"); private static readonly FieldInfo _attackSpeedField = AccessTools.Field(typeof(ChargeCaptainShotgun), "attackSpeedStat"); private static float _baseCharge = -1f; private static float _baseMinCharge = -1f; private static bool _missingFieldLogged; private static bool _appliedLogged; private static int _appliedCount; private static bool IsEnabled { get { if (_enabled != null) { return _enabled.Value; } return true; } } internal static void Init(ConfigFile config, ManualLogSource log) { _log = log; _enabled = config.Bind<bool>("Primary.火神霰弹枪", "Enabled", true, "是否缩短 M1「火神霰弹枪」的蓄力时间(1.2 秒 → 0.6 秒)。\n基础攻击间隔(开火动作的时长,原版 0.9 秒)不受影响。"); _multiplier = config.Bind<float>("Primary.火神霰弹枪", "ChargeDurationMultiplier", 0.5f, "蓄力时间倍率。0.5 = 原版 1.2 秒变成 0.6 秒;1 = 原版。\n原版基准值是从游戏里读出来的(正常是 1.2),改这个值即可自由调整。"); _minMultiplier = config.Bind<float>("Primary.火神霰弹枪", "MinChargeDurationMultiplier", 1f, "最短蓄力时间的倍率(原版 0.1 秒)。默认 1 = 保持原版,一般不用动。"); } internal static string Summary() { if (!IsEnabled) { return " [M1蓄力:原版未改动]"; } float num = ((_baseCharge > 0f) ? _baseCharge : 1.2f); float num2 = num * Multiplier(); return " [M1蓄力:" + num.ToString("0.##") + "s → " + num2.ToString("0.##") + "s(攻击间隔不变)]"; } private static float Multiplier() { if (_multiplier == null) { return 0.5f; } return _multiplier.Value; } private static float MinMultiplier() { if (_minMultiplier == null) { return 1f; } return _minMultiplier.Value; } internal 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 (_baseChargeDurationField == null || _chargeDurationField == null) { Log((LogLevel)2, "M1 蓄力补丁失败:取不到 ChargeCaptainShotgun 的 baseChargeDuration / chargeDuration 字段,蓄力时间不会变。"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(ChargeCaptainShotgun), "OnEnter", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "M1 蓄力补丁失败:取不到 ChargeCaptainShotgun.OnEnter。"); return; } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(CaptainShotgunCharge), "OnEnterPrefix", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.Method(typeof(CaptainShotgunCharge), "OnEnterPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "补丁已挂载:EntityStates.Captain.Weapon.ChargeCaptainShotgun.OnEnter <- CaptainShotgunCharge(M1 蓄力时间 ×" + Multiplier().ToString("0.##") + ")"); } public static void OnEnterPrefix() { try { if (IsEnabled && !(_baseChargeDurationField == null)) { if (_baseCharge < 0f) { _baseCharge = (float)_baseChargeDurationField.GetValue(null); Log((LogLevel)16, "M1「火神霰弹枪」原版基础蓄力时间 = " + _baseCharge.ToString("0.###") + " 秒(原版 1.2;若不是 1.2 说明游戏改过数值,倍率仍按倍率生效)。"); } if (_minBaseChargeDurationField != null && _baseMinCharge < 0f) { _baseMinCharge = (float)_minBaseChargeDurationField.GetValue(null); } float num = _baseCharge * Multiplier(); _baseChargeDurationField.SetValue(null, num); if (_minBaseChargeDurationField != null && _baseMinCharge > 0f) { _minBaseChargeDurationField.SetValue(null, _baseMinCharge * MinMultiplier()); } } } catch (Exception ex) { Log((LogLevel)4, "M1 蓄力:改写基础蓄力时间时异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message); } } public static void OnEnterPostfix(ChargeCaptainShotgun __instance) { try { if (!IsEnabled || __instance == null || _chargeDurationField == null || _baseCharge <= 0f) { return; } if (_attackSpeedField == null) { if (!_missingFieldLogged) { _missingFieldLogged = true; Log((LogLevel)4, "M1 蓄力:取不到 BaseState.attackSpeedStat,只靠静态基准值那道保险(一般也够用)。"); } return; } float num = 1f; object value = _attackSpeedField.GetValue(__instance); if (value is float) { num = (float)value; } if (num <= 0f) { num = 1f; } float num2 = _baseCharge * Multiplier() / num; float num3 = (float)_chargeDurationField.GetValue(__instance); if (Math.Abs(num3 - num2) > 0.001f) { _chargeDurationField.SetValue(__instance, num2); } if (_minChargeDurationField != null && _baseMinCharge > 0f) { float num4 = _baseMinCharge * MinMultiplier() / num; if (Math.Abs((float)_minChargeDurationField.GetValue(__instance) - num4) > 0.001f) { _minChargeDurationField.SetValue(__instance, num4); } } _appliedCount++; if (!_appliedLogged) { _appliedLogged = true; Log((LogLevel)16, "M1「火神霰弹枪」蓄力时间已生效:本次 " + num3.ToString("0.###") + " 秒 → " + num2.ToString("0.###") + " 秒(攻速 " + num.ToString("0.##") + ",基础值 " + _baseCharge.ToString("0.###") + " × " + Multiplier().ToString("0.##") + ",攻击间隔不动)。"); } else if (_appliedCount % 40 == 0) { Log((LogLevel)16, "M1「火神霰弹枪」蓄力时间已应用 " + _appliedCount + " 次,最近一次 = " + num2.ToString("0.###") + " 秒。"); } } catch (Exception ex) { Log((LogLevel)4, "M1 蓄力:核对蓄力时长时异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message); } } 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 static class CaptainSkillText { private const string SecondaryDescriptionToken = "CAPTAIN_SECONDARY_DESCRIPTION"; private const string UtilityDescriptionToken = "CAPTAIN_UTILITY_DESCRIPTION"; private const string SupplyRestockDescriptionToken = "CAPTAIN_SUPPLY_EQUIPMENT_RESTOCK_DESCRIPTION"; private const string ZhSecondaryDescription = "<style=cIsDamage>震荡</style>。连续发射<style=cIsDamage>两枚</style>造成<style=cIsDamage>280%伤害</style>的快速电镖。命中时会连锁至多<style=cIsDamage>3</style>个敌人,每个造成<style=cIsDamage>80%</style>的伤害。如果弹射将能飞行到更远地点。"; private const string EnSecondaryDescription = "<style=cIsDamage>Shocking</style>. Fire <style=cIsDamage>two</style> fast tazers, each dealing <style=cIsDamage>280% damage</style>. Chains to up to <style=cIsDamage>3</style> enemies for <style=cIsDamage>80%</style> damage each. Travels farther if bounced."; private const string ZhUtilityDescription = "<style=cIsDamage>眩晕</style>。向<style=cIsDamage>尤伊思顺风号</style>请求至多<style=cIsDamage>3台</style>轨道探测器。每台探测器将造成<style=cIsDamage>2000%伤害</style>。<style=cIsUtility>冷却20秒</style>。"; private const string EnUtilityDescription = "<style=cIsDamage>Stunning</style>. Request up to <style=cIsDamage>3</style> Orbital Probes from the <style=cIsDamage>UES Safe Travels</style>. Each probe deals <style=cIsDamage>2000% damage</style>. <style=cIsUtility>20 second cooldown</style>."; private const string ZhSupplyRestockDescription = "使用时<style=cIsUtility>为装备充能</style>,并为<style=cIsUtility>每个技能补充一层</style>。"; private const string EnSupplyRestockDescription = "<style=cIsUtility>Recharge Equipment</style> on use. Also restores <style=cIsUtility>one charge to every skill</style>."; private static ManualLogSource _log; private static ConfigEntry<bool> _enabled; private static string _appliedLanguage; internal static bool IsEnabled { get { if (_enabled != null) { return _enabled.Value; } return true; } } internal static void Init(ConfigFile config, ManualLogSource log) { _log = log; _enabled = config.Bind<bool>("SkillText", "Enabled", true, "是否把技能描述改成和模组效果一致的说法(M2「连发两枚 + 闪电链 + 280%」、Shift「每台 2000% + 冷却 20 秒」)。"); } internal static void Tick() { if (!IsEnabled) { return; } try { string text = CurrentLanguage(); if (!string.IsNullOrEmpty(text) && !string.Equals(_appliedLanguage, text, StringComparison.Ordinal)) { _appliedLanguage = text; LanguageAPI.Add("CAPTAIN_SECONDARY_DESCRIPTION", "<style=cIsDamage>Shocking</style>. Fire <style=cIsDamage>two</style> fast tazers, each dealing <style=cIsDamage>280% damage</style>. Chains to up to <style=cIsDamage>3</style> enemies for <style=cIsDamage>80%</style> damage each. Travels farther if bounced.", "en"); LanguageAPI.Add("CAPTAIN_SECONDARY_DESCRIPTION", "<style=cIsDamage>震荡</style>。连续发射<style=cIsDamage>两枚</style>造成<style=cIsDamage>280%伤害</style>的快速电镖。命中时会连锁至多<style=cIsDamage>3</style>个敌人,每个造成<style=cIsDamage>80%</style>的伤害。如果弹射将能飞行到更远地点。", "zh-CN"); LanguageAPI.Add("CAPTAIN_UTILITY_DESCRIPTION", "<style=cIsDamage>Stunning</style>. Request up to <style=cIsDamage>3</style> Orbital Probes from the <style=cIsDamage>UES Safe Travels</style>. Each probe deals <style=cIsDamage>2000% damage</style>. <style=cIsUtility>20 second cooldown</style>.", "en"); LanguageAPI.Add("CAPTAIN_UTILITY_DESCRIPTION", "<style=cIsDamage>眩晕</style>。向<style=cIsDamage>尤伊思顺风号</style>请求至多<style=cIsDamage>3台</style>轨道探测器。每台探测器将造成<style=cIsDamage>2000%伤害</style>。<style=cIsUtility>冷却20秒</style>。", "zh-CN"); LanguageAPI.Add("CAPTAIN_SUPPLY_EQUIPMENT_RESTOCK_DESCRIPTION", "<style=cIsUtility>Recharge Equipment</style> on use. Also restores <style=cIsUtility>one charge to every skill</style>.", "en"); LanguageAPI.Add("CAPTAIN_SUPPLY_EQUIPMENT_RESTOCK_DESCRIPTION", "使用时<style=cIsUtility>为装备充能</style>,并为<style=cIsUtility>每个技能补充一层</style>。", "zh-CN"); Log((LogLevel)16, "技能描述已覆盖(当前语言 " + text + "):CAPTAIN_SECONDARY_DESCRIPTION + CAPTAIN_UTILITY_DESCRIPTION + CAPTAIN_SUPPLY_EQUIPMENT_RESTOCK_DESCRIPTION"); CheckApplied(text, "CAPTAIN_SECONDARY_DESCRIPTION", "280%", "280%"); CheckApplied(text, "CAPTAIN_UTILITY_DESCRIPTION", "2000%", "2000%"); CheckApplied(text, "CAPTAIN_SUPPLY_EQUIPMENT_RESTOCK_DESCRIPTION", "补充一层", "one charge to every skill"); } } catch (Exception ex) { Log((LogLevel)4, "改写技能描述时异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message); } } private static void CheckApplied(string language, string token, string expectedZh, string expectedEn) { try { string text = Language.GetString(token); if (!string.IsNullOrEmpty(text) && text.IndexOf(expectedZh, StringComparison.Ordinal) < 0 && text.IndexOf(expectedEn, StringComparison.Ordinal) < 0) { Log((LogLevel)4, token + " 回读不一致(语言 " + language + "),实际生效的是:" + text); } } catch (Exception) { } } private static string CurrentLanguage() { try { string currentLanguageName = Language.currentLanguageName; if (!string.IsNullOrEmpty(currentLanguageName)) { return currentLanguageName; } Language currentLanguage = Language.currentLanguage; if (currentLanguage != null && !string.IsNullOrEmpty(currentLanguage.selfName)) { return currentLanguage.selfName; } } catch (Exception) { } return null; } 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 static class CaptainSupplyRestockSkills { private static ManualLogSource _log; private static ConfigEntry<bool> _enabled; private static ConfigEntry<bool> _addOneStockOnly; private static ConfigEntry<bool> _includeSpecial; private static ConfigEntry<bool> _alwaysInteractable; private static ConfigEntry<bool> _ignoreEnergy; private static bool _appliedLogged; private static int _appliedCount; private static bool _interactLogged; private static readonly FieldInfo _energyComponentField = AccessTools.Field(typeof(BaseCaptainSupplyDropState), "energyComponent"); private static readonly FieldInfo _activationCostField = AccessTools.Field(typeof(EquipmentRestockMainState), "activationCost"); private static PropertyInfo _energyProperty; private static bool IsEnabled { get { if (_enabled != null) { return _enabled.Value; } return true; } } internal static void Init(ConfigFile config, ManualLogSource log) { _log = log; _enabled = config.Bind<bool>("Special.信标补给", "RestockSkillsEnabled", true, "是否让 R「信标:补给」在给装备充能的同时,也把所有技能的冷却补满。"); _addOneStockOnly = config.Bind<bool>("Special.信标补给", "AddOneStockOnly", true, "补技能冷却的方式:true = 每个技能只补一层(默认,已满的技能不动);false = 直接把每个技能的层数和冷却恢复到满。"); _includeSpecial = config.Bind<bool>("Special.信标补给", "IncludeSpecial", true, "是否连 R(补给信标本身)一起补。它本来就没有冷却、永远是满的,勾不勾都一样。"); _alwaysInteractable = config.Bind<bool>("Special.信标补给", "AlwaysInteractable", true, "是否让补给信标随时都能交互。false = 原版条件(必须持有主动装备、且装备有待补的充能)。"); _ignoreEnergy = config.Bind<bool>("Special.信标补给", "IgnoreEnergyRequirement", false, "连信标自身能量不足时也强行允许交互(true = 完全无条件,能量空了也能按)。默认 false:至少信标自己还有能量才让按。"); } internal static string Summary() { string text = (AlwaysInteractable() ? " [信标:随时可交互]" : " [信标:原版交互条件]"); if (!IsEnabled) { return text + " [信标补给:只充装备]"; } return text + " [信标补给:装备 + 全部技能冷却" + (AddOneStockOnly() ? "(每层+1)" : "(补满)") + "]"; } private static bool AddOneStockOnly() { if (_addOneStockOnly != null) { return _addOneStockOnly.Value; } return false; } private static bool IncludeSpecial() { if (_includeSpecial != null) { return _includeSpecial.Value; } return true; } private static bool AlwaysInteractable() { if (_alwaysInteractable != null) { return _alwaysInteractable.Value; } return true; } private static bool IgnoreEnergy() { if (_ignoreEnergy != null) { return _ignoreEnergy.Value; } return false; } internal static void Patch(Harmony harmony) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown PatchInteractability(harmony); if (!IsEnabled) { Log((LogLevel)16, "信标补给:按配置只给装备充能,不补技能冷却。"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(EquipmentRestockMainState), "OnInteractionBegin", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "信标补给补丁失败:取不到 EntityStates.CaptainSupplyDrop.EquipmentRestockMainState.OnInteractionBegin。"); return; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(CaptainSupplyRestockSkills), "OnInteractionBeginPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "补丁已挂载:EntityStates.CaptainSupplyDrop.EquipmentRestockMainState.OnInteractionBegin <- CaptainSupplyRestockSkills.OnInteractionBeginPostfix(信标补给顺手补满技能冷却)"); } private static void PatchInteractability(Harmony harmony) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown if (!AlwaysInteractable()) { Log((LogLevel)16, "信标补给:按配置保持原版交互条件(要持有待充能的主动装备)。"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(EquipmentRestockMainState), "GetInteractability", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "信标补给交互补丁失败:取不到 EquipmentRestockMainState.GetInteractability。"); return; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(CaptainSupplyRestockSkills), "GetInteractabilityPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "补丁已挂载:EntityStates.CaptainSupplyDrop.EquipmentRestockMainState.GetInteractability <- CaptainSupplyRestockSkills.GetInteractabilityPostfix(补给信标不再要求「有主动装备且它在冷却」" + (IgnoreEnergy() ? ",连能量也不卡" : ",但信标自身仍要有能量") + ")"); } public static void GetInteractabilityPostfix(EquipmentRestockMainState __instance, ref Interactability __result) { try { if (AlwaysInteractable() && __instance != null && (int)__result == 1 && (IgnoreEnergy() || HasEnoughEnergy(__instance))) { __result = (Interactability)2; if (!_interactLogged) { _interactLogged = true; Log((LogLevel)16, "补给信标交互条件已放宽:即使没有主动装备(或装备没在冷却)也能交互补技能。"); } } } catch (Exception ex) { Log((LogLevel)4, "补给信标:放宽交互条件时异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message); } } private static bool HasEnoughEnergy(EquipmentRestockMainState instance) { if (_energyComponentField == null) { return true; } object value = _energyComponentField.GetValue(instance); if (value == null) { return true; } if (_energyProperty == null) { _energyProperty = AccessTools.Property(value.GetType(), "energy"); } if (_energyProperty == null) { return true; } object value2 = _energyProperty.GetValue(value, null); if (!(value2 is float)) { return true; } float num = 0f; if (_activationCostField != null) { object value3 = _activationCostField.GetValue(instance); if (value3 is float) { num = (float)value3; } } return (float)value2 >= num; } public static void OnInteractionBeginPostfix(object[] __args) { try { if (!IsEnabled || __args == null || __args.Length == 0) { return; } CharacterBody val = FindBody(__args[0]); if ((Object)(object)val == (Object)null || (Object)(object)val.skillLocator == (Object)null) { return; } int num = RestockAllSkills(val.skillLocator); if (num > 0) { _appliedCount++; if (!_appliedLogged) { _appliedLogged = true; Log((LogLevel)16, "R「信标:补给」已给 " + val.GetDisplayName() + " 补了 " + num + " 个技能的冷却(" + (AddOneStockOnly() ? "每层 +1" : "补到满") + ")。"); } else if (_appliedCount % 10 == 0) { Log((LogLevel)16, "R「信标:补给」补技能冷却已触发 " + _appliedCount + " 次。"); } } } catch (Exception ex) { Log((LogLevel)4, "信标补给:补技能冷却时异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message); } } private static CharacterBody FindBody(object raw) { Component val = (Component)((raw is Component) ? raw : null); if ((Object)(object)val == (Object)null) { GameObject val2 = (GameObject)((raw is GameObject) ? raw : null); if ((Object)(object)val2 != (Object)null) { val = (Component)(object)val2.transform; } } if ((Object)(object)val == (Object)null) { return null; } return val.GetComponent<CharacterBody>(); } private static int RestockAllSkills(SkillLocator locator) { int num = 0; num += RestockSkill(locator.primary); num += RestockSkill(locator.secondary); num += RestockSkill(locator.utility); if (IncludeSpecial()) { num += RestockSkill(locator.special); } return num; } private static int RestockSkill(GenericSkill skill) { if ((Object)(object)skill == (Object)null) { return 0; } if (AddOneStockOnly()) { if (skill.stock >= skill.maxStock) { return 0; } skill.AddOneStock(); return 1; } int maxStock = skill.maxStock; if (maxStock <= 0) { return 0; } if (skill.stock >= maxStock) { return 0; } skill.stock = maxStock; skill.rechargeStopwatch = 0f; return 1; } 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 static class CaptainTazerBurst { internal const string TazerProjectileName = "CaptainTazer"; private static ManualLogSource _log; private static ConfigEntry<bool> _enabled; private static ConfigEntry<float> _secondShotDelay; private static readonly FieldInfo _hasFiredField = AccessTools.Field(typeof(FireTazer), "hasFired"); private static readonly FieldInfo _delayField = AccessTools.Field(typeof(FireTazer), "delay"); private static readonly FieldInfo _durationField = AccessTools.Field(typeof(FireTazer), "duration"); private static readonly FieldInfo _projectilePrefabField = AccessTools.Field(typeof(FireTazer), "projectilePrefab"); private static readonly ConditionalWeakTable<FireTazer, StrongBox<int>> _fireCounts = new ConditionalWeakTable<FireTazer, StrongBox<int>>(); private static readonly ConditionalWeakTable<FireTazer, StrongBox<int>>.CreateValueCallback _makeCount = MakeCount; private static GameObject _tazerPrefab; private static int _scheduledCount; private static bool _missingFieldLogged; private static bool _prefabLogged; internal static GameObject TazerPrefab => _tazerPrefab; internal static bool IsEnabled { get { if (_enabled != null) { return _enabled.Value; } return true; } } private static StrongBox<int> MakeCount(FireTazer state) { return new StrongBox<int>(0); } internal static void Init(ConfigFile config, ManualLogSource log) { _log = log; _enabled = config.Bind<bool>("Secondary.能量电镖", "Enabled", true, "是否让 M2「能量电镖」一次技能连续射出两枚射弹。"); _secondShotDelay = config.Bind<float>("Secondary.能量电镖", "SecondShotDelay", 0.1f, "第二枚射弹相对第一枚的延迟(秒)。0.1 = 连发间隔 0.1 秒;0 = 几乎同时射出。"); } internal static string Summary() { if (!IsEnabled) { return " [M2电镖:原版单发]"; } return " [M2电镖:连发 2 枚,间隔 " + SecondShotDelay().ToString("0.##") + "s]"; } private static float SecondShotDelay() { if (_secondShotDelay == null) { return 0.1f; } return Math.Max(0f, _secondShotDelay.Value); } internal static void Patch(Harmony harmony) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(FireTazer), "Fire", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "M2 电镖补丁失败:取不到 EntityStates.Captain.Weapon.FireTazer.Fire,连发和闪电链都不会生效。"); return; } try { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(CaptainTazerBurst), "FirePostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "补丁已挂载:EntityStates.Captain.Weapon.FireTazer.Fire <- CaptainTazerBurst.FirePostfix(记住电镖 prefab + 排入第二枚)"); } catch (Exception ex) { Log((LogLevel)2, "M2 电镖补丁失败(FireTazer.Fire 没挂上,连发和闪电链都会失效)—— " + ex.GetType().Name + " " + ex.Message); } } public static void FirePostfix(FireTazer __instance) { try { if (__instance == null) { return; } LearnPrefab(); if (!IsEnabled) { return; } StrongBox<int> value = _fireCounts.GetValue(__instance, _makeCount); value.Value++; if (value.Value > 1) { return; } if (_hasFiredField == null || _delayField == null) { if (!_missingFieldLogged) { _missingFieldLogged = true; Log((LogLevel)2, "M2 电镖:取不到 FireTazer 的 hasFired / delay 字段,连发不会生效。"); } return; } float num = SecondShotDelay(); float num2 = (float)_delayField.GetValue(__instance) + num; _hasFiredField.SetValue(__instance, false); _delayField.SetValue(__instance, num2); if (_durationField != null && (float)_durationField.GetValue(__instance) < num2 + 0.05f) { _durationField.SetValue(__instance, num2 + 0.05f); } _scheduledCount++; if (_scheduledCount == 1 || _scheduledCount % 20 == 0) { Log((LogLevel)16, "M2「能量电镖」已排入第二枚射弹(间隔 " + num.ToString("0.##") + " 秒,累计 " + _scheduledCount + " 次)。"); } } catch (Exception ex) { Log((LogLevel)4, "M2 电镖:编排第二枚射弹时异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message); } } private static void LearnPrefab() { try { if ((Object)(object)_tazerPrefab != (Object)null || _projectilePrefabField == null) { return; } object? value = _projectilePrefabField.GetValue(null); GameObject val = (GameObject)((value is GameObject) ? value : null); if (!((Object)(object)val == (Object)null)) { _tazerPrefab = val; if (!_prefabLogged) { _prefabLogged = true; Log((LogLevel)16, "已记住「能量电镖」的射弹 prefab: " + ((Object)val).name); } } } catch (Exception ex) { Log((LogLevel)4, "记住电镖 prefab 时异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message); } } internal 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 static class CaptainTazerChainLightning { private static ConfigEntry<bool> _enabled; private static ConfigEntry<float> _damageRatio; private static ConfigEntry<float> _procCoefficient; private static ConfigEntry<int> _chainTargets; private static ConfigEntry<float> _range; private static ConfigEntry<bool> _inheritCrit; private static ConfigEntry<bool> _excludePrimaryTarget; private static ConfigEntry<bool> _singleTargetFallback; private static ConfigEntry<bool> _electrical; private static ConfigEntry<string> _projectileName; private static ManualLogSource _log; private static readonly HashSet<string> _seenProjectiles = new HashSet<string>(); private static FieldInfo _controllerField; private static FieldInfo _damageField; private static bool _fieldsTried; private static bool _firedLogged; private static int _firedCount; internal static bool IsEnabled { get { if (_enabled != null) { return _enabled.Value; } return true; } } internal static void Init(ConfigFile config, ManualLogSource log) { _log = log; _enabled = config.Bind<bool>("ChainLightning", "Enabled", true, "是否让 M2「能量电镖」命中后甩出一道尤克里里式连锁闪电。"); _damageRatio = config.Bind<float>("ChainLightning", "DamageRatio", 0.8f, "闪电每一跳的伤害 = 电镖原本伤害 × 这个值。尤克里里是 0.8(原版还会保底 1 点伤害)。"); _procCoefficient = config.Bind<float>("ChainLightning", "ProcCoefficient", 0.2f, "闪电的触发系数。尤克里里是 0.2(填 0 就等于完全不触发道具)。"); _chainTargets = config.Bind<int>("ChainLightning", "ChainTargets", 3, "这道闪电一共能打到几个敌人(不含被电镖直接命中的那个)。"); _range = config.Bind<float>("ChainLightning", "Range", 20f, "每次弹跳的搜索半径(米)。尤克里里基础 20。"); _inheritCrit = config.Bind<bool>("ChainLightning", "InheritCrit", true, "true = 电镖那一下暴击的话,闪电也跟着暴击(尤克里里就是这么干的)。"); _excludePrimaryTarget = config.Bind<bool>("ChainLightning", "ExcludePrimaryTarget", true, "true = 被电镖直接命中的那个敌人不会再被闪电打一次(跟尤克里里一样);\nfalse = 闪电也可能回头打他。"); _singleTargetFallback = config.Bind<bool>("ChainLightning", "SingleTargetFallback", false, "附近没有别的敌人时,要不要让闪电回头打被直接命中的那个?\nfalse(默认)= 跟尤克里里一致:只有 1 个敌人时不会有任何闪电。"); _electrical = config.Bind<bool>("ChainLightning", "Electrical", true, "闪电要不要带 <b>Electrical</b>(电击)伤害标记。\ntrue(默认)= 带。原版电镖本身就带这个标记,带上才统一;\n带它会让 <c>HealthComponent.CheckElectrocutionSpread</c> 以 50% 概率在 15 米内\n再放一次范围伤害并挂上持续伤害(就是原版电镖的电击扩散)。\nfalse = 闪电只是纯伤害,不会额外扩散。"); _projectileName = config.Bind<string>("ChainLightning", "ProjectileName", "CaptainTazer", "电镖射弹的对象名(兜底用,不区分大小写)。游戏更新后改名了可以在这里改。"); } internal static string Summary() { if (!IsEnabled) { return " [M2闪电链:关闭]"; } return " [M2闪电链:命中后弹 " + ChainTargets() + " 个 / 半径 " + Range().ToString("0.#") + "m / 每跳 " + DamageRatio().ToString("0.##") + " 倍伤害,触发系数 " + ProcCoefficient().ToString("0.##") + "]"; } private static float DamageRatio() { if (_damageRatio == null) { return 0.8f; } return _damageRatio.Value; } private static float ProcCoefficient() { if (_procCoefficient == null) { return 0.2f; } return _procCoefficient.Value; } private static int ChainTargets() { int num = ((_chainTargets != null) ? _chainTargets.Value : 3); if (num >= 1) { return num; } return 1; } private static float Range() { if (_range == null) { return 20f; } return _range.Value; } private static bool InheritCrit() { if (_inheritCrit != null) { return _inheritCrit.Value; } return true; } private static bool ExcludePrimaryTarget() { if (_excludePrimaryTarget != null) { return _excludePrimaryTarget.Value; } return true; } private static bool SingleTargetFallback() { if (_singleTargetFallback != null) { return _singleTargetFallback.Value; } return false; } private static bool Electrical() { if (_electrical != null) { return _electrical.Value; } return true; } internal static void Patch(Harmony harmony) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown if (!IsEnabled) { Log((LogLevel)16, "M2 闪电链:按配置保持原版,不挂任何补丁。"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(ProjectileExplosion), "DetonateServer", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "M2 闪电链补丁失败:取不到 ProjectileExplosion.DetonateServer。"); return; } try { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(CaptainTazerChainLightning), "DetonateServerPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "补丁已挂载:ProjectileExplosion.DetonateServer <- CaptainTazerChainLightning.DetonateServerPostfix(电镖命中后甩闪电链)"); } catch (Exception ex) { Log((LogLevel)2, "M2 闪电链补丁失败(DetonateServer 没挂上,功能将完全失效)—— " + ex.GetType().Name + " " + ex.Message); } } public static void DetonateServerPostfix(ProjectileExplosion __instance) { //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) try { if (!IsEnabled || (Object)(object)__instance == (Object)null || !NetworkServer.active) { return; } ProjectileController projectileController = GetProjectileController(__instance); ProjectileDamage projectileDamage = GetProjectileDamage(__instance); if ((Object)(object)projectileController == (Object)null || (Object)(object)projectileDamage == (Object)null) { return; } GameObject projectilePrefab = ProjectileCatalog.GetProjectilePrefab(projectileController.catalogIndex); if ((Object)(object)projectilePrefab == (Object)null) { return; } bool flag = IsTazer(projectilePrefab); if (!_seenProjectiles.Contains(((Object)projectilePrefab).name)) { _seenProjectiles.Add(((Object)projectilePrefab).name); Log((LogLevel)16, "M2 闪电链:DetonateServer 收到射弹「" + ((Object)projectilePrefab).name + "」—— " + (flag ? "能量电镖,会引雷" : "不是能量电镖,跳过")); } if (flag) { float num = projectileDamage.damage * __instance.blastDamageCoefficient; if (!(num <= 0f)) { float lightningDamage = Mathf.Max(1f, num * DamageRatio()); FireChain(((Component)__instance).transform.position, TeamOf(projectileController), projectileController.owner, InheritCrit() && projectileDamage.crit, lightningDamage, __instance.blastRadius, num); } } } catch (Exception ex) { Log((LogLevel)4, "M2 闪电链:引雷时异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message); } } private static void FireChain(Vector3 position, TeamIndex teamIndex, GameObject attacker, bool crit, float lightningDamage, float blastRadius, float originalDamage) { //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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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_00de: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) HurtBox val = (ExcludePrimaryTarget() ? FindNearestEnemy(position, teamIndex, blastRadius) : null); Vector3 val2 = (((Object)(object)val != (Object)null) ? ((Component)val).transform.position : position); LightningOrb val3 = new LightningOrb(); ((Orb)val3).origin = val2; val3.damageValue = lightningDamage; val3.isCrit = crit; val3.teamIndex = teamIndex; val3.attacker = attacker; val3.bouncesRemaining = ChainTargets() - 1; val3.bouncedObjects = new List<HealthComponent>(); if ((Object)(object)val != (Object)null && (Object)(object)val.healthComponent != (Object)null) { val3.bouncedObjects.Add(val.healthComponent); } val3.procChainMask = default(ProcChainMask); ((ProcChainMask)(ref val3.procChainMask)).AddProc((ProcType)3); val3.procCoefficient = ProcCoefficient(); val3.damageType = default(DamageTypeCombo); if (Electrical()) { val3.damageType.damageTypeExtended = (DamageTypeExtended)8192; } val3.lightningType = (LightningType)0; val3.damageColorIndex = (DamageColorIndex)3; val3.range = Range(); HurtBox val4 = val3.PickNextTarget(val2); if ((Object)(object)val4 == (Object)null && SingleTargetFallback() && (Object)(object)val != (Object)null) { val3.bouncedObjects = new List<HealthComponent>(); val4 = val; } if ((Object)(object)val4 == (Object)null) { Log((LogLevel)32, "M2 闪电链:半径 " + Range().ToString("0.#") + " 米内没有第二个敌人可弹,这一发没有闪电(想要单挑时也出闪电就把 cfg 里的 SingleTargetFallback 改成 true)。"); return; } ((Orb)val3).target = val4; OrbManager.instance.AddOrb((Orb)(object)val3); _firedCount++; if (!_firedLogged) { _firedLogged = true; Log((LogLevel)16, "M2 闪电链已生效:电镖命中,原伤害 " + originalDamage.ToString("0.#") + " → 闪电每跳 " + lightningDamage.ToString("0.#") + "(最多打 " + ChainTargets() + " 个目标,半径 " + Range().ToString("0.#") + " 米" + (Electrical() ? ",带电击标记" : ",不带电击标记") + ",触发系数 " + ProcCoefficient().ToString("0.##") + ")"); } else if (_firedCount % 20 == 0) { Log((LogLevel)16, "M2 闪电链已放出 " + _firedCount + " 次,最近一次每跳 " + lightningDamage.ToString("0.#") + " 伤害,目标 " + ((Object)val4).name); } } private static HurtBox FindNearestEnemy(Vector3 position, TeamIndex teamIndex, float radius) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_000c: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) BullseyeSearch val = new BullseyeSearch { searchOrigin = position, searchDirection = Vector3.zero, teamMaskFilter = TeamMask.allButNeutral }; ((TeamMask)(ref val.teamMaskFilter)).RemoveTeam(teamIndex); val.filterByLoS = false; val.sortMode = (SortMode)1; val.maxDistanceFilter = ((radius > 0f) ? radius : 1f); val.RefreshCandidates(); using (IEnumerator<HurtBox> enumerator = val.GetResults().GetEnumerator()) { if (enumerator.MoveNext()) { return enumerator.Current; } } return null; } private static void EnsureFields() { if (!_fieldsTried) { _fieldsTried = true; _controllerField = AccessTools.Field(typeof(ProjectileExplosion), "projectileController"); _damageField = AccessTools.Field(typeof(ProjectileExplosion), "projectileDamage"); if (_controllerField == null || _damageField == null) { Log((LogLevel)2, "M2 闪电链:取不到 ProjectileExplosion 的 projectileController / projectileDamage 字段,认不出射弹也算不出伤害。"); } } } private static ProjectileController GetProjectileController(ProjectileExplosion explosion) { EnsureFields(); if (!(_controllerField != null)) { return null; } object? value = _controllerField.GetValue(explosion); return (ProjectileController)((value is ProjectileController) ? value : null); } private static ProjectileDamage GetProjectileDamage(ProjectileExplosion explosion) { EnsureFields(); if (!(_damageField != null)) { return null; } object? value = _damageField.GetValue(explosion); return (ProjectileDamage)((value is ProjectileDamage) ? value : null); } private static bool IsTazer(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { return false; } if (prefab == CaptainTazerBurst.TazerPrefab) { return true; } string text = ((_projectileName != null) ? _projectileName.Value : "CaptainTazer"); if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(((Object)prefab).name)) { return false; } return string.Equals(((Object)prefab).name, text, StringComparison.OrdinalIgnoreCase); } private static TeamIndex TeamOf(ProjectileController controller) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)controller != (Object)null) { TeamFilter teamFilter = controller.teamFilter; if ((Object)(object)teamFilter != (Object)null) { return teamFilter.teamIndex; } if ((Object)(object)controller.owner != (Object)null) { return TeamComponent.GetObjectTeam(controller.owner); } } return (TeamIndex)0; } internal 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 static class CaptainTazerDamage { private const float VanillaCoefficient = 1f; private static ManualLogSource _log; private static ConfigEntry<bool> _enabled; private static ConfigEntry<float> _damagePercent; private static readonly FieldInfo _damageField = AccessTools.Field(typeof(FireTazer), "damageCoefficient"); private static float _base = -1f; private static bool _appliedLogged; private static int _appliedCount; private static bool IsEnabled { get { if (_enabled != null) { return _enabled.Value; } return true; } } internal static void Init(ConfigFile config, ManualLogSource log) { _log = log; _enabled = config.Bind<bool>("Secondary.能量电镖", "DamageEnabled", true, "是否把 M2「能量电镖」的伤害从每发 100% 提升到 280%。"); _damagePercent = config.Bind<float>("Secondary.能量电镖", "DamagePercent", 280f, "每发电镖的伤害百分比。280 = 每发 280% 伤害;100 = 原版。"); } internal static string Summary() { if (!IsEnabled) { return " [M2伤害:原版100%]"; } float num = ((_base > 0f) ? _base : 1f); return " [M2伤害:" + (num * 100f).ToString("0") + "% → " + DamagePercent().ToString("0") + "%]"; } private static float DamagePercent() { if (_damagePercent == null) { return 280f; } return _damagePercent.Value; } private static float Multiplier() { return Math.Max(0f, DamagePercent()) / 100f; } internal static void Patch(Harmony harmony) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown if (!IsEnabled) { Log((LogLevel)16, "M2 伤害:按配置保持原版,不挂补丁。"); return; } if (_damageField == null) { Log((LogLevel)2, "M2 伤害补丁失败:取不到 FireTazer.damageCoefficient,伤害不会变。"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(FireTazer), "Fire", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "M2 伤害补丁失败:取不到 EntityStates.Captain.Weapon.FireTazer.Fire。"); return; } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(CaptainTazerDamage), "FirePrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "补丁已挂载:EntityStates.Captain.Weapon.FireTazer.Fire <- CaptainTazerDamage.FirePrefix(每发伤害 → " + DamagePercent().ToString("0") + "%)"); } public static void FirePrefix() { try { if (IsEnabled && !(_damageField == null)) { if (_base < 0f) { _base = (float)_damageField.GetValue(null); Log((LogLevel)16, "M2「能量电镖」原版伤害系数 = " + _base.ToString("0.###") + "(原版 1 = 100%;若不是 1 说明游戏改过数值,百分比仍按百分比生效)。"); } float num = _base * Multiplier(); _damageField.SetValue(null, num); _appliedCount++; if (!_appliedLogged) { _appliedLogged = true; Log((LogLevel)16, "M2「能量电镖」伤害已生效:" + (_base * 100f).ToString("0") + "% → " + (num * 100f).ToString("0") + "% 每发。"); } else if (_appliedCount % 60 == 0) { Log((LogLevel)16, "M2「能量电镖」伤害已应用 " + _appliedCount + " 次,当前每发 " + (num * 100f).ToString("0") + "%。"); } } } catch (Exception ex) { Log((LogLevel)4, "M2 伤害:改写伤害系数时异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message); } } 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); } } } [BepInPlugin("com.sparkletwilight.sparklecaptaintweaks", "SparkleCaptainTweaks", "1.3.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class SparkleCaptainTweaksPlugin : BaseUnityPlugin { public const string PluginGUID = "com.sparkletwilight.sparklecaptaintweaks"; public const string PluginName = "SparkleCaptainTweaks"; public const string PluginVersion = "1.3.0"; internal ManualLogSource Logger; public void Awake() { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; CaptainShotgunCharge.Init(((BaseUnityPlugin)this).Config, Logger); CaptainTazerBurst.Init(((BaseUnityPlugin)this).Config, Logger); CaptainTazerDamage.Init(((BaseUnityPlugin)this).Config, Logger); CaptainTazerChainLightning.Init(((BaseUnityPlugin)this).Config, Logger); CaptainOrbitalProbe.Init(((BaseUnityPlugin)this).Config, Logger); CaptainSupplyRestockSkills.Init(((BaseUnityPlugin)this).Config, Logger); CaptainSkillText.Init(((BaseUnityPlugin)this).Config, Logger); Harmony harmony = new Harmony("com.sparkletwilight.sparklecaptaintweaks"); SafePatch("M1 蓄力时间", delegate { CaptainShotgunCharge.Patch(harmony); }); SafePatch("M2 连发", delegate { CaptainTazerBurst.Patch(harmony); }); SafePatch("M2 伤害", delegate { CaptainTazerDamage.Patch(harmony); }); SafePatch("M2 闪电链", delegate { CaptainTazerChainLightning.Patch(harmony); }); SafePatch("Shift 轨道探测器", delegate { CaptainOrbitalProbe.Patch(harmony); }); SafePatch("R 信标补给", delegate { CaptainSupplyRestockSkills.Patch(harmony); }); Logger.LogInfo((object)("SparkleCaptainTweaks v1.3.0 已加载。" + CaptainShotgunCharge.Summary() + CaptainTazerBurst.Summary() + CaptainTazerDamage.Summary() + CaptainTazerChainLightning.Summary() + CaptainOrbitalProbe.Summary() + CaptainSupplyRestockSkills.Summary())); } public void Update() { CaptainSkillText.Tick(); CaptainOrbitalProbe.Tick(); } private void SafePatch(string label, Action patch) { try { patch(); } catch (Exception ex) { Logger.LogError((object)("SparkleCaptainTweaks:「" + label + "」挂补丁时抛异常,已跳过该模块 —— " + ex.GetType().Name + " " + ex.Message)); } } } }