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 SparkleRailgunnerTweaks v1.11.0
plugins/SparkleRailgunnerTweaks.dll
Decompiled 6 hours agousing System; using System.Collections.Generic; 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 HarmonyLib; using Microsoft.CodeAnalysis; using R2API; using RoR2; 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("SparkleRailgunnerTweaks")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.11.0.0")] [assembly: AssemblyInformationalVersion("1.11.0")] [assembly: AssemblyProduct("SparkleRailgunnerTweaks")] [assembly: AssemblyTitle("SparkleRailgunnerTweaks")] [assembly: AssemblyVersion("1.11.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 SparkleRailgunnerTweaks { public static class CryochargeFrost { private const string RailgunnerBodyName = "RailgunnerBody"; private static ConfigEntry<bool> _enabled; private static ConfigEntry<int> _stacks; private static ConfigEntry<float> _duration; private static ManualLogSource _log; private static bool _appliedLogged; private static bool _frostMissingLogged; private static int _appliedCount; private static float _lastLogAt = -999f; public static bool IsEnabled { get { if (_enabled != null) { return _enabled.Value; } return true; } } public static void Init(ConfigFile cfg, ManualLogSource logger) { _log = logger; _enabled = cfg.Bind<bool>("Cryocharge", "Enabled", true, "是否让「低温充能」(替代 R,2000% 伤害)在命中时给予目标「霜冻」。\ntrue = 命中即叠霜冻;false = 完全保持原版(只有原版的 2 秒冰冻)。"); _stacks = cfg.Bind<int>("Cryocharge", "FrostStacks", 4, "每次命中给几层霜冻。4 = 一次命中 4 层。\n提示:霜冻叠到 6 层会由游戏本体自动转成冰冻;\n想让低温充能「一发冻住」,把这里填 6 或更多(穿透打多个目标也是各给这么多次)。"); _duration = cfg.Bind<float>("Cryocharge", "FrostDuration", 10f, "每层霜冻的持续时间(秒)。10 = 命中后 10 秒内一直挂着这些层。"); } public static string Summary() { if (_enabled == null || !_enabled.Value) { return " [低温充能:原版未改动]"; } return " [低温充能:命中给" + Stacks() + "层霜冻×" + StackDuration().ToString("0.##") + "秒]"; } public static void Patch(Harmony harmony) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(GlobalEventManager), "OnHitEnemy", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "「低温充能霜冻」补丁失败:找不到 RoR2.GlobalEventManager.OnHitEnemy。"); return; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(CryochargeFrost), "OnHitEnemyPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "补丁已挂载:RoR2.GlobalEventManager.OnHitEnemy <- OnHitEnemyPostfix(低温充能命中后补霜冻)"); } public static void OnHitEnemyPostfix(object[] __args) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) try { if (_enabled == null || !_enabled.Value || !NetworkServer.active || __args == null || __args.Length < 2) { return; } object obj = __args[0]; DamageInfo val = (DamageInfo)((obj is DamageInfo) ? obj : null); object obj2 = __args[1]; GameObject val2 = (GameObject)((obj2 is GameObject) ? obj2 : null); if (val == null || (Object)(object)val2 == (Object)null || (val.damageType.damageType & 0x100) == 0) { return; } GameObject attacker = val.attacker; CharacterBody val3 = (((Object)(object)attacker == (Object)null) ? null : attacker.GetComponent<CharacterBody>()); if ((Object)(object)val3 == (Object)null) { return; } string name = ((Object)val3).name; if (string.IsNullOrEmpty(name) || name.IndexOf("RailgunnerBody", StringComparison.OrdinalIgnoreCase) < 0) { return; } BuffDef frost = Buffs.Frost; if ((Object)(object)frost == (Object)null) { if (!_frostMissingLogged) { _frostMissingLogged = true; Log((LogLevel)4, "低温充能霜冻未生效:DLC2Content.Buffs.Frost 取不到(可能没装 DLC2)。"); } return; } CharacterBody component = val2.GetComponent<CharacterBody>(); if ((Object)(object)component == (Object)null || (Object)(object)component.healthComponent == (Object)null || !component.healthComponent.alive) { return; } int num = Stacks(); if (num > 0) { float num2 = StackDuration(); for (int i = 0; i < num; i++) { component.AddTimedBuff(frost, num2); } _appliedCount++; if (!_appliedLogged) { _appliedLogged = true; Log((LogLevel)16, "低温充能已给予霜冻:" + num + " 层 × " + num2.ToString("0.##") + " 秒 -> " + ((Object)component).name + "(原版的 2 秒冰冻照常生效)。"); } else if (Time.time - _lastLogAt > 5f) { _lastLogAt = Time.time; LogThrottled("低温充能霜冻累计生效 " + _appliedCount + " 次。"); } } } catch (Exception ex) { Log((LogLevel)4, "「低温充能霜冻」命中后处理异常(已忽略):" + ex.GetType().Name + " " + ex.Message); } } private static int Stacks() { int val = ((_stacks == null) ? 4 : _stacks.Value); return Math.Max(0, val); } private static float StackDuration() { float num = ((_duration == null) ? 10f : _duration.Value); if (!(num > 0.05f)) { return 0.05f; } return num; } private static void LogThrottled(string message) { Log((LogLevel)16, 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); } } } public static class HH44AttackSpeed { private const string FireSnipeLightTypeName = "EntityStates.Railgunner.Weapon.FireSnipeLight"; private const string GenericBulletBaseStateTypeName = "EntityStates.GenericBulletBaseState"; private static ConfigEntry<bool> _enabled; private static ConfigEntry<float> _multiplier; private static ConfigEntry<bool> _scaleBonusOnly; private static ManualLogSource _log; private static Type _fireSnipeLightType; private static bool _typeResolveFailedLogged; private static FieldInfo _attackSpeedField; private static FieldInfo _durationField; private static bool _fieldsResolveFailedLogged; private static bool _firstShotLogged; private static float _lastLogAt = -999f; public static bool IsEnabled { get { if (_enabled != null) { return _enabled.Value; } return true; } } public static void Init(ConfigFile cfg, ManualLogSource logger) { _log = logger; _enabled = cfg.Bind<bool>("HH44", "Enabled", true, "是否增强 HH44 的攻击速度收益。false = 保持原版(攻速只按原版公式生效)。"); _multiplier = cfg.Bind<float>("HH44", "AttackSpeedMultiplier", 1.5f, "HH44 从攻击速度「加成部分」上获得的额外倍率。\n有效攻速 = 1 + 倍率 × (attackSpeedStat − 1):\n 基础间隔 0.5 秒;+100% 攻速时有效攻速 1 + 1.5×1 = 2.5,间隔 0.2 秒(原版 0.25 秒);\n +200% 攻速时有效攻速 4,间隔 0.125 秒(原版 0.167 秒);0 攻速加成时与原版一致。"); _scaleBonusOnly = cfg.Bind<bool>("HH44", "ScaleBonusOnly", true, "true = 只放大「攻速加成部分」:有效攻速 = 1 + 倍率 × (attackSpeedStat − 1)\n(+100% 攻速时有效攻速 2.5,间隔 0.2 秒;0 攻速加成时与原版一致)。\nfalse = 直接把 attackSpeedStat 整体乘倍率(间隔恒为原版的 1 / 倍率,\n +100% 攻速时间隔 0.167 秒,但 0 攻速加成时也比原版快 50%)。"); } public static string Summary() { if (_enabled == null || !_enabled.Value) { return " [HH44:原版未改动]"; } float num = ((_multiplier == null) ? 1.5f : _multiplier.Value); bool flag = _scaleBonusOnly != null && _scaleBonusOnly.Value; return " [HH44:攻速收益×" + num.ToString("0.##") + (flag ? "(仅加成部分)" : "(整体)") + "]"; } public static void Patch(Harmony harmony) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown _fireSnipeLightType = AccessTools.TypeByName("EntityStates.Railgunner.Weapon.FireSnipeLight"); if (_fireSnipeLightType == null) { Log((LogLevel)2, "HH44 补丁失败:找不到状态类型 EntityStates.Railgunner.Weapon.FireSnipeLight。"); } Type type = AccessTools.TypeByName("EntityStates.GenericBulletBaseState"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "OnEnter", (Type[])null, (Type[])null)); if (methodInfo == null) { Log((LogLevel)2, "HH44 补丁失败:找不到 EntityStates.GenericBulletBaseState.OnEnter。"); return; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(HH44AttackSpeed), "OnEnterPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "补丁已挂载:EntityStates.GenericBulletBaseState.OnEnter <- OnEnterPostfix(仅对 EntityStates.Railgunner.Weapon.FireSnipeLight 生效,重写 duration)"); } public static void OnEnterPostfix(GenericBulletBaseState __instance) { try { if (_enabled == null || !_enabled.Value || __instance == null) { return; } if (_fireSnipeLightType == null) { _fireSnipeLightType = AccessTools.TypeByName("EntityStates.Railgunner.Weapon.FireSnipeLight"); if (_fireSnipeLightType == null) { if (!_typeResolveFailedLogged) { _typeResolveFailedLogged = true; Log((LogLevel)4, "HH44 未生效:解析不出 EntityStates.Railgunner.Weapon.FireSnipeLight。"); } return; } } if (((object)__instance).GetType() != _fireSnipeLightType) { return; } float num = ((_multiplier == null) ? 1.5f : _multiplier.Value); if (!(num <= 0f) && EnsureFields()) { float baseDuration = __instance.baseDuration; float num2 = (float)_attackSpeedField.GetValue(__instance); if (num2 <= 0f) { num2 = 1f; } bool flag = _scaleBonusOnly != null && _scaleBonusOnly.Value; float num3 = ((!flag) ? (num2 * num) : ((num2 > 1f) ? (1f + num * (num2 - 1f)) : num2)); if (num3 < 0.01f) { num3 = 0.01f; } float num4 = baseDuration / num2; float num5 = baseDuration / num3; _durationField.SetValue(__instance, num5); if (!_firstShotLogged) { _firstShotLogged = true; Log((LogLevel)16, "HH44 攻速改写已生效:基础间隔 " + baseDuration.ToString("0.###") + "s / 攻速 " + num2.ToString("0.##") + " → 原版 " + num4.ToString("0.###") + "s → 实际 " + num5.ToString("0.###") + "s" + (flag ? "(仅放大加成部分)" : ("(整体×" + num.ToString("0.##") + ")")) + "。"); } else { LogThrottled("HH44 开火:攻速 " + num2.ToString("0.##") + " → 间隔 " + num5.ToString("0.###") + "s(原版 " + num4.ToString("0.###") + "s)"); } } } catch (Exception ex) { Log((LogLevel)4, "HH44 攻速改写异常(已忽略):" + ex.GetType().Name + " " + ex.Message); } } private static bool EnsureFields() { if (_attackSpeedField != null && _durationField != null) { return true; } Type type = AccessTools.TypeByName("EntityStates.GenericBulletBaseState"); if (type == null) { return false; } _attackSpeedField = FindField(type, "attackSpeedStat"); _durationField = FindField(type, "duration"); if (_attackSpeedField == null || _durationField == null) { if (!_fieldsResolveFailedLogged) { _fieldsResolveFailedLogged = true; Log((LogLevel)2, "HH44 未生效:取不到字段 attackSpeedStat / duration(attackSpeedStat=" + ((_attackSpeedField == null) ? "缺失" : "OK") + ",duration=" + ((_durationField == null) ? "缺失" : "OK") + ")。"); } return false; } return true; } private static FieldInfo FindField(Type type, string name) { Type type2 = type; while (type2 != null) { FieldInfo field = type2.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field; } type2 = type2.BaseType; } return null; } private static void LogThrottled(string message) { if (!(Time.time - _lastLogAt < 3f)) { _lastLogAt = Time.time; Log((LogLevel)16, 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); } } } public static class PolarField { private sealed class ActiveField { public GameObject gameObject; public CharacterBody owner; public bool ownerGuessed; public float expireTime; } private const string RailgunnerBodyName = "RailgunnerBody"; private const string BlindingSkillNameToken = "RAILGUNNER_UTILITY_ALT_NAME"; private const string BlindingStateTypeName = "EntityStates.Railgunner.Weapon.FireMineBlinding"; private const string FieldPrefabName = "RailgunnerMineAltDetonated"; private const string ThrownPrefabName = "RailgunnerMineAlt"; private const float VanillaFieldRadius = 15f; private const float ThrowerMemoryWindow = 10f; private static ConfigEntry<bool> _enabled; private static ConfigEntry<float> _radius; private static ConfigEntry<float> _duration; private static ConfigEntry<float> _projectileSlowStrength; private static ConfigEntry<float> _cooldown; private static ConfigEntry<int> _maxFieldsPerOwner; private static ConfigEntry<bool> _spawnEffect; private static ConfigEntry<bool> _frostInsteadOfSlow; private static ConfigEntry<float> _frostInterval; private static ConfigEntry<float> _frostDuration; private static ConfigEntry<float> _frostBurstStacks; private static ManualLogSource _log; private static GameObject _effectPrefab; private static bool _frostResolveFailedLogged; private static CharacterBody _lastThrowerOwner; private static float _lastThrowerAt = -999f; private static bool _frostLogged; private static bool _cooldownPatched; private static readonly List<ActiveField> _fields = new List<ActiveField>(); private static bool _spawnLogged; private static float _lastLogAt = -999f; public static bool IsEnabled { get { if (_enabled != null) { return _enabled.Value; } return true; } } public static void Init(ConfigFile cfg, ManualLogSource logger) { _log = logger; _enabled = cfg.Bind<bool>("PolarField", "Enabled", true, "是否强化「极性力场装置」。true = 装置照原版扔出,但生成的力场按下方的半径 / 时长 / 减速 / 霜冻参数强化;\nfalse = 完全保持原版。"); _radius = cfg.Bind<float>("PolarField", "Radius", 60f, "力场的半径(米,直接写绝对值,不是倍率)。原版是 15 米;60 = 半径 60 米。\n改的是力场实例上的 BuffWard.radius 与射弹减速用的球形触发器,两者同步。\n填 0 或负数 = 保持原版半径不动。"); _duration = cfg.Bind<float>("PolarField", "Duration", 120f, "力场的持续时间(秒)。原版 BuffWard 的 expireDuration 是 10 秒;120 = 持续两分钟。\n注意:力场是原版 BuffWard 到点自己销毁的,这里会同步改 BuffWard.expireDuration。"); _projectileSlowStrength = cfg.Bind<float>("PolarField", "ProjectileSlowStrength", 0.5f, "力场对敌方射弹的减速幅度(0~1,越大越慢):射弹在力场里还剩 (1 - 这个值) 的速度。\n0.90 = 与原版一致(只剩 10% 速度);0.5 = 还剩一半速度;0.99 = 只剩 1%(几乎钉在原地)。"); _cooldown = cfg.Bind<float>("PolarField", "Cooldown", 40f, "「极性力场装置」的基础冷却(秒),改的是 SkillDef.baseRechargeInterval。\n12 = 与原版一致;40 = 明显更长(力场半径 60 米、持续 120 秒,冷却也跟着拉长)。\n冷却类道具会在新基准上继续结算。"); _maxFieldsPerOwner = cfg.Bind<int>("PolarField", "MaxFieldsPerOwner", 1, "同一个角色同时最多能维持几个力场。1 = 场上已有力场时再扔一个装置,上一个立刻消失(默认,也就是「场上始终只有最新那一个」);\n2 = 最多同时两个;0 或负数 = 不限制(各自到时间才消失)。"); _spawnEffect = cfg.Bind<bool>("PolarField", "SpawnEffect", true, "力场展开时是否额外播放一份按半径放大的力场特效(RailgunnerMineExplosionAlt)。\n原版特效是按 15 米做的,半径调到 60 米后本体特效偏小,补一份大的方便看清范围;\n觉得重复就填 false(投掷装置引爆时那份原版特效照常播放,不受这一项影响)。"); _frostInsteadOfSlow = cfg.Bind<bool>("PolarField", "FrostInsteadOfSlow", true, "力场对「敌人」的光环效果:true = 改成持续叠原版的「霜冻」(frost),\n叠到 6 层由游戏本体自动转成冰冻;false = 保持原版减速。\n(对敌方射弹的减速不受这一项影响,仍由 ProjectileSlowStrength 决定。)"); _frostInterval = cfg.Bind<float>("PolarField", "FrostInterval", 0.5f, "霜冻的叠加间隔(秒)。0.5 = 每 0.5 秒给范围内的敌人叠 1 层。\n提示:同时存在的层数上限约等于 FrostDuration / FrostInterval,\n想要叠满 6 层触发冰冻,需要 FrostDuration / FrostInterval >= 6。"); _frostDuration = cfg.Bind<float>("PolarField", "FrostDuration", 2f, "每层霜冻的持续时间(秒)。2 = 每层 2 秒后自己掉(展开瞬间给的层也是这个时长)。"); _frostBurstStacks = cfg.Bind<float>("PolarField", "FrostBurstStacks", 0f, "力场展开的一瞬间,先给范围内所有敌人直接叠几层霜冻。\n0 = 不额外给(默认);5 = 立刻 5 层(再吃一层光环就到 6 层,由游戏本体自动转冰冻)。"); } public static string Summary() { if (_enabled == null || !_enabled.Value) { return " [极性力场:原版未改动]"; } float num = CurrentRadius(); float num2 = ((_duration == null) ? 10f : _duration.Value); float num3 = ((_cooldown == null) ? 12f : _cooldown.Value); bool flag = _frostInsteadOfSlow == null || _frostInsteadOfSlow.Value; float num4 = ((_frostInterval == null) ? 1f : _frostInterval.Value); float num5 = ((_frostDuration == null) ? 8f : _frostDuration.Value); float num6 = ((_frostBurstStacks == null) ? 0f : Mathf.Max(0f, _frostBurstStacks.Value)); return " [极性力场:扔出装置/半径" + num.ToString("0.#") + "米/" + num2.ToString("0.##") + "秒/射弹减速" + ProjectileSlowStrength().ToString("0.##") + "/冷却" + num3.ToString("0.##") + "秒" + (flag ? ("/敌人霜冻每" + num4.ToString("0.##") + "秒1层×" + num5.ToString("0.##") + "秒") : "/敌人原版减速") + ((num6 > 0f) ? ("/展开瞬间" + num6.ToString("0.#") + "层") : "") + "]"; } public 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 //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(BuffWard), "Awake", (Type[])null, (Type[])null); if (methodInfo == null) { Log((LogLevel)2, "「极性力场」补丁失败:找不到 RoR2.BuffWard.Awake。"); } else { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(PolarField), "BuffWardAwakePostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "补丁已挂载:RoR2.BuffWard.Awake <- BuffWardAwakePostfix(认出极性力场实例并强化它)"); } MethodInfo methodInfo2 = AccessTools.Method(typeof(ProjectileManager), "InitializeProjectile", (Type[])null, (Type[])null); if (methodInfo2 == null) { Log((LogLevel)4, "找不到 ProjectileManager.InitializeProjectile,力场放大特效不会播放(功能不受影响)。"); return; } harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(PolarField), "InitializeProjectilePostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log((LogLevel)16, "补丁已挂载:ProjectileManager.InitializeProjectile <- InitializeProjectilePostfix(记录投掷装置的力场特效)"); } public static void InitializeProjectilePostfix(FireProjectileInfo fireProjectileInfo) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)fireProjectileInfo.projectilePrefab == (Object)null || !string.Equals(((Object)fireProjectileInfo.projectilePrefab).name, "RailgunnerMineAlt", StringComparison.OrdinalIgnoreCase)) { return; } _lastThrowerOwner = Sanitize(OwnerBody(fireProjectileInfo.owner)); _lastThrowerAt = Time.time; if (!((Object)(object)_effectPrefab != (Object)null)) { ProjectileImpactExplosion component = fireProjectileInfo.projectilePrefab.GetComponent<ProjectileImpactExplosion>(); if ((Object)(object)component != (Object)null && (Object)(object)((ProjectileExplosion)component).explosionEffect != (Object)null) { _effectPrefab = ((ProjectileExplosion)component).explosionEffect; Log((LogLevel)16, "力场特效已记录:" + ((Object)_effectPrefab).name + "。"); } } } catch (Exception ex) { Log((LogLevel)4, "记录力场特效异常(已忽略):" + ex.GetType().Name + " " + ex.Message); } } public static void BuffWardAwakePostfix(BuffWard __instance) { try { if (_enabled == null || !_enabled.Value || (Object)(object)__instance == (Object)null) { return; } GameObject gameObject = ((Component)__instance).gameObject; if ((Object)(object)gameObject == (Object)null) { return; } Transform val = (((Object)(object)gameObject.transform == (Object)null) ? null : gameObject.transform.root); if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null) { gameObject = ((Component)val).gameObject; } if (IsFieldObject(gameObject)) { CharacterBody val2 = Sanitize(OwnerBodyOf(gameObject)); bool ownerGuessed = false; if ((Object)(object)val2 == (Object)null && Time.time - _lastThrowerAt < 10f) { val2 = Sanitize(_lastThrowerOwner); ownerGuessed = (Object)(object)val2 != (Object)null; } float num = ((_duration == null) ? 10f : Mathf.Max(0f, _duration.Value)); ApplyFieldTuning(gameObject, num); if (_spawnEffect == null || _spawnEffect.Value) { SpawnEffect(gameObject); } int num2 = ApplyFrostBurst(gameObject); EnforceMaxFields(val2); ActiveField item = new ActiveField { gameObject = gameObject, owner = val2, ownerGuessed = ownerGuessed, expireTime = Time.time + num }; _fields.Add(item); if (!_spawnLogged) { _spawnLogged = true; Log((LogLevel)16, "极性力场已生成 半径 " + CurrentRadius().ToString("0.0") + " 米 持续 " + num.ToString("0.##") + " 秒 射弹只剩 " + ProjectileSlowCoefficient().ToString("0.###") + " 的速度" + ((_frostInsteadOfSlow == null || _frostInsteadOfSlow.Value) ? (",敌人霜冻每 " + FrostInterval().ToString("0.##") + " 秒 1 层×" + FrostStackDuration().ToString("0.##") + " 秒" + ((BurstStacks() > 0) ? (",展开瞬间 " + BurstStacks() + " 层 -> " + num2 + " 个敌人") : "")) : ",敌人原版减速") + "(authority=" + NetworkServer.active + ")。"); } else { LogThrottled("极性力场已生成(当前有效数量 " + CountAlive() + ")。"); } } } catch (Exception ex) { Log((LogLevel)4, "「极性力场」BuffWard.Awake 后处理异常(已忽略):" + ex.GetType().Name + " " + ex.Message); } } public static void TickFields() { try { if (_enabled == null || !_enabled.Value || _fields.Count == 0) { return; } List<CharacterBody> list = null; for (int num = _fields.Count - 1; num >= 0; num--) { ActiveField activeField = _fields[num]; if (activeField == null || (Object)(object)activeField.gameObject == (Object)null) { _fields.RemoveAt(num); } else if (Time.time >= activeField.expireTime) { DestroyField(activeField.gameObject); _fields.RemoveAt(num); } else { if (activeField.ownerGuessed || activeField.owner == null) { CharacterBody val = Sanitize(OwnerBodyOf(activeField.gameObject)); if ((Object)(object)val != (Object)null) { bool num2 = val != activeField.owner; activeField.owner = val; activeField.ownerGuessed = false; if (num2) { if (list == null) { list = new List<CharacterBody>(); } list.Add(val); } } } if (activeField.owner != null) { CharacterBody owner = activeField.owner; if ((Object)(object)owner == (Object)null || (Object)(object)owner.healthComponent == (Object)null || !owner.healthComponent.alive) { DestroyField(activeField.gameObject); _fields.RemoveAt(num); } } } } if (list != null) { for (int i = 0; i < list.Count; i++) { EnforceMaxFields(list[i]); } } } catch (Exception ex) { Log((LogLevel)4, "「极性力场」刷新异常(已忽略):" + ex.GetType().Name + " " + ex.Message); } } private static bool IsFieldObject(GameObject go) { if ((Object)(object)go == (Object)null) { return false; } string name = ((Object)go).name; if (string.IsNullOrEmpty(name) || name.IndexOf("RailgunnerMine", StringComparison.OrdinalIgnoreCase) < 0) { return false; } if ((Object)(object)go.GetComponent<BuffWard>() != (Object)null) { return (Object)(object)go.GetComponent<SlowDownProjectiles>() != (Object)null; } return false; } private static CharacterBody OwnerBodyOf(GameObject go) { if ((Object)(object)go == (Object)null) { return null; } ProjectileController component = go.GetComponent<ProjectileController>(); if ((Object)(object)component == (Object)null) { return null; } return OwnerBody(component.owner); } private static void ApplyFieldTuning(GameObject go, float duration) { float num = CurrentRadius(); BuffWard component = go.GetComponent<BuffWard>(); if ((Object)(object)component != (Object)null) { if (num > 0f && Mathf.Abs(component.radius - num) > 0.0001f) { component.radius = num; } if (Mathf.Abs(component.expireDuration - duration) > 0.0001f) { component.expireDuration = duration; } ApplyFrostWard(component); } if (num > 0f) { SphereCollider component2 = go.GetComponent<SphereCollider>(); if ((Object)(object)component2 != (Object)null && Mathf.Abs(component2.radius - num) > 0.0001f) { component2.radius = num; } } SlowDownProjectiles component3 = go.GetComponent<SlowDownProjectiles>(); if ((Object)(object)component3 != (Object)null) { float num2 = ProjectileSlowCoefficient(); if (Mathf.Abs(num2 - component3.slowDownCoefficient) > 0.0001f) { component3.slowDownCoefficient = num2; } } } private static void ApplyFrostWard(BuffWard ward) { if (_frostInsteadOfSlow == null || !_frostInsteadOfSlow.Value) { return; } BuffDef frost = Buffs.Frost; if ((Object)(object)frost == (Object)null) { if (!_frostResolveFailedLogged) { _frostResolveFailedLogged = true; Log((LogLevel)4, "霜冻光环未生效:DLC2Content.Buffs.Frost 取不到(可能没装 DLC2),保留原版减速。"); } return; } ward.buffDef = frost; ward.interval = FrostInterval(); ward.buffDuration = FrostStackDuration(); if (!_frostLogged) { _frostLogged = true; Log((LogLevel)16, "力场光环已改为霜冻:" + ((Object)frost).name + ",每 " + ward.interval.ToString("0.##") + " 秒叠 1 层、每层持续 " + ward.buffDuration.ToString("0.##") + " 秒(同时存在的层数上限约 " + (ward.buffDuration / Mathf.Max(0.05f, ward.interval)).ToString("0.#") + " 层,叠满 6 层由游戏本体转冰冻)。"); } } private static float CurrentRadius() { float num = ((_radius == null) ? 15f : _radius.Value); if (!(num > 0f)) { return 0f; } return num; } private static float ProjectileSlowStrength() { return Mathf.Clamp((_projectileSlowStrength == null) ? 0.9f : _projectileSlowStrength.Value, 0f, 1f); } private static float ProjectileSlowCoefficient() { return Mathf.Clamp(1f - ProjectileSlowStrength(), 0.01f, 1f); } private static float FrostInterval() { float num = ((_frostInterval == null) ? 1f : _frostInterval.Value); return Mathf.Max(0.05f, num); } private static float FrostStackDuration() { float num = ((_frostDuration == null) ? 8f : _frostDuration.Value); return Mathf.Max(0.05f, num); } private static int BurstStacks() { float num = ((_frostBurstStacks == null) ? 0f : _frostBurstStacks.Value); return (int)Mathf.Max(0f, Mathf.Round(num)); } private static int ApplyFrostBurst(GameObject go) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) int num = BurstStacks(); if (num <= 0 || (Object)(object)go == (Object)null || !NetworkServer.active) { return 0; } if (_frostInsteadOfSlow == null || !_frostInsteadOfSlow.Value) { return 0; } BuffDef frost = Buffs.Frost; if ((Object)(object)frost == (Object)null) { return 0; } BuffWard component = go.GetComponent<BuffWard>(); float num2 = (((Object)(object)component == (Object)null) ? 0f : component.radius); if (num2 <= 0f) { return 0; } Vector3 position = go.transform.position; float num3 = num2 * num2; float num4 = FrostStackDuration(); TeamIndex val = (TeamIndex)(-1); TeamFilter val2 = (((Object)(object)go == (Object)null) ? null : go.GetComponent<TeamFilter>()); if ((Object)(object)val2 != (Object)null) { val = val2.teamIndex; } int num5 = 0; foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList) { if ((Object)(object)readOnlyInstances == (Object)null || (Object)(object)readOnlyInstances.healthComponent == (Object)null || !readOnlyInstances.healthComponent.alive) { continue; } TeamComponent teamComponent = readOnlyInstances.teamComponent; if ((Object)(object)teamComponent == (Object)null || (int)teamComponent.teamIndex == 0 || teamComponent.teamIndex == val) { continue; } Vector3 val3 = readOnlyInstances.corePosition - position; if (!(((Vector3)(ref val3)).sqrMagnitude > num3)) { for (int i = 0; i < num; i++) { readOnlyInstances.AddTimedBuff(frost, num4); } num5++; } } return num5; } public static void TryPatchCooldown() { //IL_00ee: Unknown result type (might be due to invalid IL or missing references) if (_cooldownPatched || _enabled == null || !_enabled.Value) { return; } try { if (!((ResourceAvailability)(ref BodyCatalog.availability)).available) { return; } GameObject val = BodyCatalog.FindBodyPrefab("RailgunnerBody"); if ((Object)(object)val == (Object)null) { Log((LogLevel)4, "BodyCatalog 里找不到 RailgunnerBody,极性力场冷却未修改。"); _cooldownPatched = true; return; } SkillLocator component = val.GetComponent<SkillLocator>(); if ((Object)(object)component == (Object)null || (Object)(object)component.utility == (Object)null) { Log((LogLevel)2, "RailgunnerBody 上取不到 utility 技能槽,极性力场冷却未修改。"); _cooldownPatched = true; return; } SkillFamily skillFamily = component.utility.skillFamily; if ((Object)(object)skillFamily == (Object)null || skillFamily.variants == null) { Log((LogLevel)2, "磁轨炮手 utility 技能族为空,极性力场冷却未修改。"); _cooldownPatched = true; return; } float baseRechargeInterval = ((_cooldown == null) ? 12f : _cooldown.Value); bool flag = false; Variant[] variants = skillFamily.variants; for (int i = 0; i < variants.Length; i++) { SkillDef skillDef = variants[i].skillDef; if (!((Object)(object)skillDef == (Object)null) && IsBlindingSkillDef(skillDef)) { float baseRechargeInterval2 = skillDef.baseRechargeInterval; skillDef.baseRechargeInterval = baseRechargeInterval; flag = true; Log((LogLevel)16, "极性力场冷却:" + baseRechargeInterval2.ToString("0.##") + "s -> " + baseRechargeInterval.ToString("0.##") + "s(SkillDef " + skillDef.skillNameToken + ")"); } } if (!flag) { Log((LogLevel)4, "磁轨炮手 utility 技能族里没匹配到「极性力场装置」,冷却未修改。"); } else { RefreshLiveBodies(); } _cooldownPatched = true; } catch (Exception ex) { _cooldownPatched = true; Log((LogLevel)2, "修改极性力场冷却异常(已放弃重试):" + ex.GetType().Name + " " + ex.Message); } } private static bool IsBlindingSkillDef(SkillDef def) { try { Type type = AccessTools.TypeByName("EntityStates.Railgunner.Weapon.FireMineBlinding"); if (type != null && ((SerializableEntityStateType)(ref def.activationState)).stateType == type) { return true; } string typeName = ((SerializableEntityStateType)(ref def.activationState)).typeName; if (!string.IsNullOrEmpty(typeName) && typeName == "EntityStates.Railgunner.Weapon.FireMineBlinding") { return true; } } catch (Exception) { } if (!string.IsNullOrEmpty(def.skillNameToken)) { return def.skillNameToken == "RAILGUNNER_UTILITY_ALT_NAME"; } return false; } private static void RefreshLiveBodies() { foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList) { if (!((Object)(object)readOnlyInstances == (Object)null)) { SkillLocator skillLocator = readOnlyInstances.skillLocator; if (!((Object)(object)skillLocator == (Object)null) && !((Object)(object)skillLocator.utility == (Object)null)) { skillLocator.utility.RecalculateValues(); } } } } private static void EnforceMaxFields(CharacterBody owner) { int num = ((_maxFieldsPerOwner == null) ? 1 : _maxFieldsPerOwner.Value); if (num <= 0 || (Object)(object)owner == (Object)null) { return; } int num2 = 0; for (int i = 0; i < _fields.Count; i++) { ActiveField activeField = _fields[i]; if (activeField != null && (Object)(object)activeField.gameObject != (Object)null && activeField.owner == owner) { num2++; } } int num3 = 0; for (int j = 0; j < _fields.Count; j++) { if (num2 < num) { break; } ActiveField activeField2 = _fields[j]; if (activeField2 != null && activeField2.owner == owner) { DestroyField(activeField2.gameObject); _fields.RemoveAt(j); j--; num2--; num3++; } } if (num3 > 0) { LogThrottled("已有极性力场,摧毁了上一个(同时最多 " + num + " 个,本次清理 " + num3 + " 个)。"); } } private static CharacterBody Sanitize(CharacterBody body) { if (!((Object)(object)body != (Object)null)) { return null; } return body; } private static void SpawnEffect(GameObject fieldObject) { //IL_0022: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_effectPrefab == (Object)null) && !((Object)(object)fieldObject == (Object)null)) { GameObject val = Object.Instantiate<GameObject>(_effectPrefab, fieldObject.transform.position, Quaternion.identity); float num = CurrentRadius(); if (num > 0f && Mathf.Abs(num - 15f) > 0.0001f) { val.transform.localScale = val.transform.localScale * (num / 15f); } } } private static void DestroyField(GameObject go) { if (!((Object)(object)go == (Object)null)) { if (NetworkServer.active) { NetworkServer.Destroy(go); } else { Object.Destroy((Object)(object)go); } } } private static int CountAlive() { int num = 0; for (int i = 0; i < _fields.Count; i++) { if (_fields[i] != null && (Object)(object)_fields[i].gameObject != (Object)null) { num++; } } return num; } private static CharacterBody OwnerBody(GameObject owner) { if (!((Object)(object)owner == (Object)null)) { return owner.GetComponent<CharacterBody>(); } return null; } private static void LogThrottled(string message) { if (!(Time.time - _lastLogAt < 3f)) { _lastLogAt = Time.time; Log((LogLevel)16, 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); } } } public static class SkillDescriptions { private const string HH44Token = "RAILGUNNER_SECONDARY_ALT_DESCRIPTION"; private const string FieldToken = "RAILGUNNER_UTILITY_ALT_DESCRIPTION"; private const string CryoToken = "RAILGUNNER_SPECIAL_ALT_DESCRIPTION"; private const string DefaultHH44Zh = "启动你的<style=cIsUtility>近程瞄准镜</style>,高亮显示<style=cIsDamage>弱点</style>,并将你的武器转化为一门可造成<style=cIsDamage>400%伤害</style>的连续磁轨炮。<style=cIsUtility>从攻击速度获得更多收益</style>。"; private const string DefaultHH44En = "Activate your <style=cIsUtility>short-range scope</style>, highlighting <style=cIsDamage>Weak Points</style> and transforming your weapon into a continuous <style=cIsDamage>400% damage</style> railgun. <style=cIsUtility>Gains increased benefit from attack speed.</style>"; private const string DefaultFieldZh = "扔出一部装置,该装置会展开一个可使范围内<style=cIsUtility>所有敌人和射弹</style><style=cIsUtility>减速</style>的领域。"; private const string DefaultFieldEn = "Throw out a device that deploys a field, <style=cIsUtility>slowing down</style> all <style=cIsUtility>enemies and projectiles</style> within its radius."; private const string DefaultCryoZh = "冰霜。冰冻。发射一枚具有穿刺效果的子弹,造成2000%的伤害。"; private const string DefaultCryoEn = "Frost. Freezing. Fire a piercing shot that deals 2000% damage."; private static ConfigEntry<bool> _enabled; private static ConfigEntry<string> _hh44Text; private static ConfigEntry<string> _fieldText; private static ConfigEntry<string> _cryoText; private static ManualLogSource _log; public static void Init(ConfigFile cfg, ManualLogSource logger) { _log = logger; _enabled = cfg.Bind<bool>("Descriptions", "Enabled", true, "是否改写技能说明文字。false = 完全保留原版文案。"); _hh44Text = cfg.Bind<string>("Descriptions", "HH44Description", "启动你的<style=cIsUtility>近程瞄准镜</style>,高亮显示<style=cIsDamage>弱点</style>,并将你的武器转化为一门可造成<style=cIsDamage>400%伤害</style>的连续磁轨炮。<style=cIsUtility>从攻击速度获得更多收益</style>。", "「代号HH44神射手」(替代 M2)的说明文字。留空 = 不改写。\n支持 <style=cIsUtility> / <style=cIsDamage> 之类的富文本标签。"); _fieldText = cfg.Bind<string>("Descriptions", "PolarFieldDescription", "扔出一部装置,该装置会展开一个可使范围内<style=cIsUtility>所有敌人和射弹</style><style=cIsUtility>减速</style>的领域。", "「极性力场装置」(替代辅助技能)的说明文字。留空 = 不改写。"); _cryoText = cfg.Bind<string>("Descriptions", "CryochargeDescription", "冰霜。冰冻。发射一枚具有穿刺效果的子弹,造成2000%的伤害。", "「低温充能」(替代特殊技能)的说明文字。留空 = 不改写。"); } public static void Apply(bool hh44Enabled, bool polarFieldEnabled, bool cryoEnabled) { try { if (_enabled == null || !_enabled.Value) { Log((LogLevel)16, "技能说明:按配置保留原版文案。"); return; } if (hh44Enabled) { string text = ((_hh44Text == null) ? "启动你的<style=cIsUtility>近程瞄准镜</style>,高亮显示<style=cIsDamage>弱点</style>,并将你的武器转化为一门可造成<style=cIsDamage>400%伤害</style>的连续磁轨炮。<style=cIsUtility>从攻击速度获得更多收益</style>。" : _hh44Text.Value); if (!string.IsNullOrEmpty(text)) { LanguageAPI.Add("RAILGUNNER_SECONDARY_ALT_DESCRIPTION", text, "zh-CN"); LanguageAPI.Add("RAILGUNNER_SECONDARY_ALT_DESCRIPTION", "Activate your <style=cIsUtility>short-range scope</style>, highlighting <style=cIsDamage>Weak Points</style> and transforming your weapon into a continuous <style=cIsDamage>400% damage</style> railgun. <style=cIsUtility>Gains increased benefit from attack speed.</style>", "en"); Log((LogLevel)16, "技能说明已改写:RAILGUNNER_SECONDARY_ALT_DESCRIPTION(代号HH44神射手)。"); } } if (polarFieldEnabled) { string text2 = ((_fieldText == null) ? "扔出一部装置,该装置会展开一个可使范围内<style=cIsUtility>所有敌人和射弹</style><style=cIsUtility>减速</style>的领域。" : _fieldText.Value); if (!string.IsNullOrEmpty(text2)) { LanguageAPI.Add("RAILGUNNER_UTILITY_ALT_DESCRIPTION", text2, "zh-CN"); LanguageAPI.Add("RAILGUNNER_UTILITY_ALT_DESCRIPTION", "Throw out a device that deploys a field, <style=cIsUtility>slowing down</style> all <style=cIsUtility>enemies and projectiles</style> within its radius.", "en"); Log((LogLevel)16, "技能说明已改写:RAILGUNNER_UTILITY_ALT_DESCRIPTION(极性力场装置)。"); } } if (cryoEnabled) { string text3 = ((_cryoText == null) ? "冰霜。冰冻。发射一枚具有穿刺效果的子弹,造成2000%的伤害。" : _cryoText.Value); if (!string.IsNullOrEmpty(text3)) { LanguageAPI.Add("RAILGUNNER_SPECIAL_ALT_DESCRIPTION", text3, "zh-CN"); LanguageAPI.Add("RAILGUNNER_SPECIAL_ALT_DESCRIPTION", "Frost. Freezing. Fire a piercing shot that deals 2000% damage.", "en"); Log((LogLevel)16, "技能说明已改写:RAILGUNNER_SPECIAL_ALT_DESCRIPTION(低温充能)。"); } } } catch (Exception ex) { Log((LogLevel)4, "技能说明改写失败(已忽略):" + 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.sparklerailgunnertweaks", "SparkleRailgunnerTweaks", "1.11.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class SparkleRailgunnerTweaksPlugin : BaseUnityPlugin { public const string PluginGUID = "com.sparkletwilight.sparklerailgunnertweaks"; public const string PluginName = "SparkleRailgunnerTweaks"; public const string PluginVersion = "1.11.0"; public void Awake() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //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 PolarField.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger); HH44AttackSpeed.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger); CryochargeFrost.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger); SkillDescriptions.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger); SkillDescriptions.Apply(HH44AttackSpeed.IsEnabled, PolarField.IsEnabled, CryochargeFrost.IsEnabled); Harmony val = new Harmony("com.sparkletwilight.sparklerailgunnertweaks"); PolarField.Patch(val); HH44AttackSpeed.Patch(val); CryochargeFrost.Patch(val); ((BaseUnityPlugin)this).Logger.LogInfo((object)("SparkleRailgunnerTweaks v1.11.0 已加载。" + PolarField.Summary() + HH44AttackSpeed.Summary() + CryochargeFrost.Summary())); } public void Update() { PolarField.TryPatchCooldown(); } public void FixedUpdate() { PolarField.TickFields(); } } }