Decompiled source of SparkleSurvivorsTweaks v1.0.5

plugins/SparkleSurvivorsTweaks.dll

Decompiled 13 hours ago
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.5.0")]
[assembly: AssemblyInformationalVersion("1.0.5")]
[assembly: AssemblyProduct("SparkleSurvivorsTweaks")]
[assembly: AssemblyTitle("SparkleSurvivorsTweaks")]
[assembly: AssemblyVersion("1.0.5.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)
		{