Decompiled source of SparkleMercTweaks v1.19.0

plugins/SparkleMercTweaks.dll

Decompiled 11 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates;
using EntityStates.Merc;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using R2API;
using RoR2;
using RoR2.Projectile;
using RoR2.Skills;
using UnityEngine;

[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("SparkleMercTweaks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SparkleMercTweaks")]
[assembly: AssemblyTitle("SparkleMercTweaks")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SparkleMercTweaks
{
	public static class EvisZeroArmorDouble
	{
		private static ConfigEntry<bool> _enable;

		private static ConfigEntry<float> _multiplier;

		private static ManualLogSource _log;

		private static float _lastLogAt = -999f;

		private static int _appliedHits;

		private static bool _diagnoseLogged;

		private static FieldInfo _damageInfoField;

		public static void Init(ConfigFile cfg, ManualLogSource log)
		{
			_log = log;
			_damageInfoField = AccessTools.Field(typeof(HealthComponent), "damageInfo");
			_enable = cfg.Bind<bool>("EvisZeroArmorDouble", "EnableDoubleDamage", true, "剔除内脏是否对护甲 <= 0 的目标造成双倍伤害。true = 启用,false = 原版行为。");
			_multiplier = cfg.Bind<float>("EvisZeroArmorDouble", "DoubleDamageMultiplier", 2f, "对护甲 <= 0 的目标的伤害倍率。2 = 双倍伤害,1 = 原版。");
			Log((LogLevel)16, "剔除内脏「零/负护甲双倍伤害」已载入:" + (IsEnabled() ? "已启用" : "已禁用(只剩半径改动)"));
		}

		public static bool IsEnabled()
		{
			if (_enable != null)
			{
				return _enable.Value;
			}
			return true;
		}

		public static string Summary()
		{
			string text = ((_enable != null && _enable.Value) ? "开" : "关");
			float num = ((_multiplier == null) ? 2f : _multiplier.Value);
			return " [零护甲双倍:" + text + ((num <= 0f) ? "" : (" x" + num.ToString("0.##"))) + "]";
		}

		public static void Patch(Harmony harmony)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			MethodBase methodBase = AccessTools.Method(typeof(HealthComponent), "TakeDamageProcess", (Type[])null, (Type[])null);
			if (methodBase == null)
			{
				Log((LogLevel)2, "双倍伤害补丁失败:找不到 HealthComponent.TakeDamageProcess。");
				return;
			}
			HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(EvisZeroArmorDouble), "TakeDamageProcessPrefix", (Type[])null, (Type[])null));
			harmony.Patch(methodBase, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Log((LogLevel)16, "补丁已挂载:HealthComponent.TakeDamageProcess <- TakeDamageProcessPrefix()(零/负护甲双倍伤害)");
			MethodBase methodBase2 = AccessTools.Method(typeof(Evis), "OnEnter", (Type[])null, (Type[])null);
			if (methodBase2 != null)
			{
				harmony.Patch(methodBase2, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(EvisZeroArmorDouble), "EvisOnEnterPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Log((LogLevel)16, "补丁已挂载:Evis.OnEnter <- EvisOnEnterPostfix()(状态机自检)");
			}
			else
			{
				Log((LogLevel)4, "自检补丁未挂载:找不到 EntityStates.Merc.Evis.OnEnter。");
			}
		}

		public static void EvisOnEnterPostfix(Evis __instance)
		{
			if (_diagnoseLogged || __instance == null)
			{
				return;
			}
			_diagnoseLogged = true;
			try
			{
				object member = GetMember(__instance, "characterBody");
				CharacterBody val = (CharacterBody)((member is CharacterBody) ? member : null);
				if ((Object)(object)val == (Object)null)
				{
					Log((LogLevel)4, "状态自检失败:Evis.OnEnter 里取 characterBody 为空,「双倍伤害」判定会永远不触发。");
					return;
				}
				Component[] components = ((Component)val).GetComponents<Component>();
				int num = 0;
				string text = "n/a";
				if (components != null)
				{
					foreach (Component obj in components)
					{
						EntityStateMachine val2 = (EntityStateMachine)(object)((obj is EntityStateMachine) ? obj : null);
						if (!((Object)(object)val2 == (Object)null))
						{
							num++;
							if (num == 1)
							{
								object member2 = GetMember(val2, "state");
								text = ((member2 == null) ? "null" : member2.GetType().Name);
							}
						}
					}
				}
				Log((LogLevel)16, "状态自检:当前状态 = " + text + ",角色身上 EntityStateMachine 数量 = " + num + "(找不到的话「双倍伤害」不会生效,把这个数字发我即可定位)。");
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "状态自检异常:" + ex.GetType().Name + " " + ex.Message);
			}
		}

		public static void TakeDamageProcessPrefix(HealthComponent __instance, ref DamageInfo damageInfo)
		{
			try
			{
				if (!IsEnabled())
				{
					return;
				}
				float num = ((_multiplier == null) ? 2f : _multiplier.Value);
				if (num <= 0f || num == 1f || (Object)(object)__instance == (Object)null || (Object)(object)damageInfo.attacker == (Object)null)
				{
					return;
				}
				CharacterBody component = damageInfo.attacker.GetComponent<CharacterBody>();
				if ((Object)(object)component == (Object)null || !IsEvisAttacker(component))
				{
					return;
				}
				float num2 = TargetArmor(__instance);
				if (num2 > 0f)
				{
					return;
				}
				float damage = damageInfo.damage;
				damageInfo.damage = damage * num;
				if (_damageInfoField != null)
				{
					try
					{
						_damageInfoField.SetValue(__instance, damageInfo);
					}
					catch
					{
					}
				}
				_appliedHits++;
				if (Time.time - _lastLogAt >= 3f)
				{
					_lastLogAt = Time.time;
					Log((LogLevel)16, "剔除内脏「零护甲双倍伤害」已生效:目标护甲 " + num2.ToString("0.##") + "(<= 0)→ 伤害由 " + damage.ToString("0.##") + " 变为 " + damageInfo.damage.ToString("0.##") + "(x" + num.ToString("0.##") + ")。");
				}
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "双倍伤害结算异常(已忽略):" + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static bool IsEvisAttacker(CharacterBody attackerBody)
		{
			if ((Object)(object)attackerBody == (Object)null)
			{
				return false;
			}
			Component[] components = ((Component)attackerBody).GetComponents<Component>();
			if (components == null)
			{
				return false;
			}
			foreach (Component obj in components)
			{
				EntityStateMachine val = (EntityStateMachine)(object)((obj is EntityStateMachine) ? obj : null);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				try
				{
					if (val.state is Evis)
					{
						return true;
					}
				}
				catch
				{
				}
			}
			return false;
		}

		private static float TargetArmor(HealthComponent healthComponent)
		{
			float num = 0f;
			if ((Object)(object)healthComponent == (Object)null)
			{
				return num;
			}
			if ((Object)(object)healthComponent.body != (Object)null)
			{
				num = healthComponent.body.armor;
			}
			FieldInfo fieldInfo = AccessTools.Field(typeof(HealthComponent), "adaptiveArmorValue");
			if (fieldInfo != null)
			{
				try
				{
					num += Convert.ToSingle(fieldInfo.GetValue(healthComponent));
				}
				catch
				{
				}
			}
			return num;
		}

		private static object GetMember(object instance, string memberName)
		{
			if (instance == null)
			{
				return null;
			}
			Type type = instance.GetType();
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(type, memberName);
				if (fieldInfo != null)
				{
					return fieldInfo.GetValue(instance);
				}
				PropertyInfo propertyInfo = AccessTools.Property(type, memberName);
				if (propertyInfo != null && propertyInfo.CanRead)
				{
					return propertyInfo.GetValue(instance, null);
				}
			}
			catch
			{
				return null;
			}
			return null;
		}

		private static void Log(LogLevel level, string message)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (_log != null)
			{
				_log.Log(level, (object)("[SparkleMercTweaks] " + message));
			}
		}
	}
	public static class MercBodyStatsTweaks
	{
		private const string MercBodyPrefabName = "MercBody";

		private const string MercBodyNameToken = "MERC_BODY_NAME";

		private static ConfigEntry<bool> _enable;

		private static ConfigEntry<float> _baseRegen;

		private static ConfigEntry<float> _levelRegen;

		private static ManualLogSource _log;

		private static bool _logged;

		private static float _originalBaseRegen = -1f;

		private static float _originalLevelRegen = -1f;

		private static bool _errorLogged;

		public static void Init(ConfigFile cfg, ManualLogSource logger)
		{
			_log = logger;
			_enable = cfg.Bind<bool>("BodyStats", "Enable", true, "是否改动雇佣兵的生命恢复。关掉则完全保持原版(基础 1/s,每级 +0.2/s)。");
			_baseRegen = cfg.Bind<float>("BodyStats", "BaseRegen", 2.5f, "雇佣兵的「基础生命恢复」(每秒回复量,不含等级成长)。原版是 1。\n填 0 或负数 = 不改这项。");
			_levelRegen = cfg.Bind<float>("BodyStats", "LevelRegen", 0.5f, "雇佣兵「每升一级」额外获得的生命恢复(每秒)。原版是 0.2。\n填 0 或负数 = 不改这项。");
		}

		public static void Patch(Harmony harmony)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			if (_enable != null && _enable.Value)
			{
				MethodInfo methodInfo = null;
				try
				{
					methodInfo = AccessTools.Method(typeof(CharacterBody), "RecalculateStats", (Type[])null, (Type[])null);
				}
				catch (Exception ex)
				{
					Log((LogLevel)2, "生命恢复改动未生效:反射拿不到 CharacterBody.RecalculateStats():" + ex.Message);
					return;
				}
				if (methodInfo == null)
				{
					Log((LogLevel)2, "生命恢复改动未生效:找不到 CharacterBody.RecalculateStats()。");
					return;
				}
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(MercBodyStatsTweaks), "RecalculateStatsPrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Log((LogLevel)16, "补丁已挂载:CharacterBody.RecalculateStats() <- RecalculateStatsPrefix()(雇佣兵生命恢复 MercBody)");
			}
		}

		public static string Summary()
		{
			if (_enable == null || !_enable.Value)
			{
				return " [生命恢复:原版]";
			}
			float num = ((_baseRegen == null) ? 2.5f : _baseRegen.Value);
			float num2 = ((_levelRegen == null) ? 0.5f : _levelRegen.Value);
			return " [生命恢复:" + num.ToString("0.##") + "/s 每级+" + num2.ToString("0.##") + "]";
		}

		public static void RecalculateStatsPrefix(CharacterBody __instance)
		{
			if (_enable == null || !_enable.Value || (Object)(object)__instance == (Object)null || !IsMerc(__instance))
			{
				return;
			}
			try
			{
				float num = ((_baseRegen == null) ? 2.5f : _baseRegen.Value);
				float num2 = ((_levelRegen == null) ? 0.5f : _levelRegen.Value);
				if (!_logged)
				{
					_logged = true;
					_originalBaseRegen = __instance.baseRegen;
					_originalLevelRegen = __instance.levelRegen;
					Log((LogLevel)16, "雇佣兵原版生命恢复基准:基础 " + _originalBaseRegen.ToString("0.##") + "/s、每级 +" + _originalLevelRegen.ToString("0.##") + "/s;将覆写为基础 " + ((num > 0f) ? num.ToString("0.##") : _originalBaseRegen.ToString("0.##")) + "/s、每级 +" + ((num2 > 0f) ? num2.ToString("0.##") : _originalLevelRegen.ToString("0.##")) + "/s。");
				}
				if (num > 0f && Math.Abs(__instance.baseRegen - num) > 0.0001f)
				{
					__instance.baseRegen = num;
				}
				if (num2 > 0f && Math.Abs(__instance.levelRegen - num2) > 0.0001f)
				{
					__instance.levelRegen = num2;
				}
			}
			catch (Exception ex)
			{
				if (!_errorLogged)
				{
					_errorLogged = true;
					Log((LogLevel)4, "雇佣兵生命恢复覆写异常:" + ex.GetType().Name + " " + ex.Message);
				}
			}
		}

		private static bool IsMerc(CharacterBody body)
		{
			string baseNameToken = body.baseNameToken;
			if (!string.IsNullOrEmpty(baseNameToken) && baseNameToken.IndexOf("MERC", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			if (!string.IsNullOrEmpty(((Object)body).name))
			{
				return ((Object)body).name.StartsWith("MercBody", StringComparison.OrdinalIgnoreCase);
			}
			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)("[SparkleMercTweaks] " + message));
			}
		}
	}
	public static class MercEvisTweak
	{
		private const string FallbackToken = "MERC_SPECIAL_DESCRIPTION";

		private const string DescriptionZh = "向前冲锋并斩击最近的敌人,重复造成<style=cIsDamage>110%的伤害</style>。这个伤害对<style=cIsUtility>无护甲</style>目标<style=cIsDamage>翻倍</style>。过程中<style=cIsUtility>无法被攻击</style>。";

		internal static ConfigEntry<float> RadiusMultiplier;

		internal static ConfigEntry<bool> OverrideSkillDescription;

		private static ManualLogSource _log;

		private static bool _evisCaptured;

		private static float _baseEvisMaxRadius;

		private static bool _dashCaptured;

		private static float _baseDashOverlapRadius;

		private static bool _capturedLogged;

		private static bool _tokenProbed;

		public static void Init(ConfigFile config, ManualLogSource logger)
		{
			_log = logger;
			RadiusMultiplier = config.Bind<float>("Eviscerate", "RadiusMultiplier", 1.5f, "剔除内脏的判定半径与伤害半径的放大倍率。1.5 = 扩大 50%(原版 1.0)。\n同时作用于两处:连续斩击的索敌 / 伤害半径,以及起手突进的判定半径。");
			OverrideSkillDescription = config.Bind<bool>("Eviscerate", "OverrideSkillDescription", true, "是否把游戏内「剔除内脏」的技能说明改成与实际效果一致的描述。\n关掉则显示原版文本。改完需要重启游戏。");
		}

		public static void ApplyRadii()
		{
			float num = RadiusMultiplier.Value;
			if (num <= 0f)
			{
				num = 1f;
			}
			ApplyEvisRadius(num);
			ApplyDashRadius(num);
			LogCapturedOnce();
		}

		private static void ApplyEvisRadius(float mult)
		{
			float maxRadius = Evis.maxRadius;
			if (!_evisCaptured)
			{
				if (!(maxRadius > 0f))
				{
					return;
				}
				_baseEvisMaxRadius = maxRadius;
				_evisCaptured = true;
			}
			Evis.maxRadius = _baseEvisMaxRadius * mult;
		}

		private static void ApplyDashRadius(float mult)
		{
			float overlapSphereRadius = EvisDash.overlapSphereRadius;
			if (!_dashCaptured)
			{
				if (!(overlapSphereRadius > 0f))
				{
					return;
				}
				_baseDashOverlapRadius = overlapSphereRadius;
				_dashCaptured = true;
			}
			EvisDash.overlapSphereRadius = _baseDashOverlapRadius * mult;
		}

		private static void LogCapturedOnce()
		{
			if (!_capturedLogged && _evisCaptured && _dashCaptured)
			{
				_capturedLogged = true;
				Log((LogLevel)16, "剔除内脏原版半径已记录:斩击半径 " + _baseEvisMaxRadius.ToString("0.##") + ",突进判定半径 " + _baseDashOverlapRadius.ToString("0.##") + ",放大后分别为 " + (_baseEvisMaxRadius * RadiusMultiplier.Value).ToString("0.##") + " / " + (_baseDashOverlapRadius * RadiusMultiplier.Value).ToString("0.##"));
			}
		}

		public static void ApplyLanguage()
		{
			if (OverrideSkillDescription.Value)
			{
				LanguageAPI.Add("MERC_SPECIAL_DESCRIPTION", "向前冲锋并斩击最近的敌人,重复造成<style=cIsDamage>110%的伤害</style>。这个伤害对<style=cIsUtility>无护甲</style>目标<style=cIsDamage>翻倍</style>。过程中<style=cIsUtility>无法被攻击</style>。", "en");
				LanguageAPI.Add("MERC_SPECIAL_DESCRIPTION", "向前冲锋并斩击最近的敌人,重复造成<style=cIsDamage>110%的伤害</style>。这个伤害对<style=cIsUtility>无护甲</style>目标<style=cIsDamage>翻倍</style>。过程中<style=cIsUtility>无法被攻击</style>。", "zh-CN");
			}
		}

		public static void ProbeToken()
		{
			if (_tokenProbed || !OverrideSkillDescription.Value)
			{
				return;
			}
			GameObject val = BodyCatalog.FindBodyPrefab("MercBody");
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			SkillLocator component = val.GetComponent<SkillLocator>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.special == (Object)null || (Object)(object)component.special.skillFamily == (Object)null)
			{
				return;
			}
			_tokenProbed = true;
			Variant[] variants = component.special.skillFamily.variants;
			if (variants == null)
			{
				return;
			}
			for (int i = 0; i < variants.Length; i++)
			{
				SkillDef skillDef = variants[i].skillDef;
				if ((Object)(object)skillDef == (Object)null || string.IsNullOrEmpty(skillDef.skillDescriptionToken))
				{
					continue;
				}
				string text = null;
				try
				{
					text = ((SerializableEntityStateType)(ref skillDef.activationState)).typeName;
				}
				catch (Exception ex)
				{
					Log((LogLevel)4, "读取激活状态失败 " + skillDef.skillNameToken + ":" + ex.Message);
					continue;
				}
				if (string.IsNullOrEmpty(text) || text.IndexOf("Merc.Evis", StringComparison.Ordinal) < 0)
				{
					Log((LogLevel)16, "跳过雇佣兵 R 槽位的其它技能:" + skillDef.skillNameToken + "(激活状态 " + text + ",游戏内显示名 " + Language.GetString(skillDef.skillNameToken) + ")");
					continue;
				}
				string skillDescriptionToken = skillDef.skillDescriptionToken;
				Log((LogLevel)16, "发现剔除内脏的技能说明 token: " + skillDescriptionToken + "(技能名 " + skillDef.skillNameToken + ",游戏内显示名 " + Language.GetString(skillDef.skillNameToken) + ")");
				if (!string.Equals(skillDescriptionToken, "MERC_SPECIAL_DESCRIPTION", StringComparison.Ordinal))
				{
					LanguageAPI.Add(skillDescriptionToken, "向前冲锋并斩击最近的敌人,重复造成<style=cIsDamage>110%的伤害</style>。这个伤害对<style=cIsUtility>无护甲</style>目标<style=cIsDamage>翻倍</style>。过程中<style=cIsUtility>无法被攻击</style>。", "en");
					LanguageAPI.Add(skillDescriptionToken, "向前冲锋并斩击最近的敌人,重复造成<style=cIsDamage>110%的伤害</style>。这个伤害对<style=cIsUtility>无护甲</style>目标<style=cIsDamage>翻倍</style>。过程中<style=cIsUtility>无法被攻击</style>。", "zh-CN");
				}
			}
		}

		public static string Summary()
		{
			return "剔除内脏(雇佣兵 R):判定半径与伤害半径 x" + RadiusMultiplier.Value.ToString("0.##") + "(每次挥砍只打 1 名敌人),对护甲 <= 0 的目标双倍伤害。" + (OverrideSkillDescription.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 MercExposeCripple
	{
		private const uint ApplyMercExposeFlag = 8388608u;

		private const float VanillaBonusMultiplier = 3.5f;

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<float> _duration;

		private static ConfigEntry<bool> _requireMercAttacker;

		private static ConfigEntry<float> _bonusMultiplier;

		private static ManualLogSource _log;

		private static BuffDef _exposeDef;

		private static BuffDef _crippleDef;

		private static bool _appliedLogged;

		private static float _lastLogAt = -999f;

		public static void Init(ConfigFile cfg, ManualLogSource logger)
		{
			_log = logger;
			_enabled = cfg.Bind<bool>("MercExpose", "ApplyCripple", true, "雇佣兵消耗敌人身上的「暴露」时,是否改为给这名敌人挂「残废」(降低移动速度和护甲)。\ntrue = 消耗暴露的那一下附带残废,false = 不挂残废。");
			_duration = cfg.Bind<float>("MercExpose", "CrippleDuration", 3f, "「残废」的持续时间(秒)。3 = 3 秒。");
			_requireMercAttacker = cfg.Bind<bool>("MercExpose", "RequireMercAttacker", true, "是否只在攻击者是雇佣兵时才挂残废。true = 只有雇佣兵消耗暴露才触发;\nfalse = 任何人(含队友、召唤物)消耗暴露都会触发。");
			_bonusMultiplier = cfg.Bind<float>("MercExpose", "ExposeDamageBonusMultiplier", 0f, "消耗暴露时那笔「额外伤害」的系数(以攻击者的面板伤害 damage 为基数,是加值不是乘法)。\n0 = 取消原版那 350% 的额外伤害(默认);3.5 = 保持原版;其它值自行调整。\n改这一项需要重启游戏才生效(它在补丁里被写死进 IL)。");
		}

		public static string Summary()
		{
			string text = " [暴露:消耗时";
			text = text + ((_bonusMultiplier == null) ? 0f : _bonusMultiplier.Value).ToString("0.##") + "倍额外伤害";
			if (_enabled == null || !_enabled.Value)
			{
				return text + "/无残废]";
			}
			return text + "/残废 " + ((_duration == null) ? 2f : _duration.Value).ToString("0.##") + "秒]";
		}

		public static void Patch(Harmony harmony)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_008c: Expected O, but got Unknown
			//IL_008c: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(HealthComponent), "TakeDamageProcess", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				Log((LogLevel)2, "「暴露消耗改造」补丁失败:找不到 HealthComponent.TakeDamageProcess。");
				return;
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(MercExposeCripple), "CrippleExposedPrefix", (Type[])null, (Type[])null);
			MethodInfo methodInfo3 = AccessTools.Method(typeof(MercExposeCripple), "CrippleExposedPostfix", (Type[])null, (Type[])null);
			MethodInfo methodInfo4 = AccessTools.Method(typeof(MercExposeCripple), "ExposeBonusTranspiler", (Type[])null, (Type[])null);
			harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), new HarmonyMethod(methodInfo3), new HarmonyMethod(methodInfo4), (HarmonyMethod)null, (HarmonyMethod)null);
			Log((LogLevel)16, "补丁已挂载:HealthComponent.TakeDamageProcess <- CrippleExposedPrefix/Postfix + ExposeBonusTranspiler(消耗暴露:取消额外伤害、改挂残废)");
		}

		public static void CrippleExposedPrefix(HealthComponent __instance, DamageInfo damageInfo, ref bool __state)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			__state = false;
			try
			{
				if (_enabled == null || !_enabled.Value || (Object)(object)__instance == (Object)null)
				{
					return;
				}
				CharacterBody body = __instance.body;
				if (!((Object)(object)body == (Object)null))
				{
					BuffDef val = ResolveBuff(ref _exposeDef, "MercExpose");
					if (!((Object)(object)val == (Object)null) && body.HasBuff(val.buffIndex) && IsMercAttacker(damageInfo.attacker))
					{
						__state = true;
					}
				}
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "「暴露消耗改造」Prefix 异常(已忽略):" + ex.GetType().Name + " " + ex.Message);
			}
		}

		public static void CrippleExposedPostfix(HealthComponent __instance, DamageInfo damageInfo, bool __state)
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected I4, but got Unknown
			if (!__state)
			{
				return;
			}
			try
			{
				if ((Object)(object)__instance == (Object)null || damageInfo.rejected)
				{
					return;
				}
				CharacterBody body = __instance.body;
				if ((Object)(object)body == (Object)null)
				{
					return;
				}
				BuffDef val = ResolveBuff(ref _crippleDef, "Cripple");
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				float num = ((_duration == null) ? 2f : _duration.Value);
				if (!(num <= 0f))
				{
					body.AddTimedBuff(val, num);
					if (!_appliedLogged)
					{
						_appliedLogged = true;
						Log((LogLevel)16, "「消耗暴露」已触发:目标被挂上 " + num.ToString("0.##") + " 秒残废(Cripple,BuffIndex " + (int)val.buffIndex + ")。");
					}
					else
					{
						LogThrottled("「消耗暴露」已触发:挂上 " + num.ToString("0.##") + " 秒残废。");
					}
				}
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "「暴露消耗改造」Postfix 异常(已忽略):" + ex.GetType().Name + " " + ex.Message);
			}
		}

		public static IEnumerable<CodeInstruction> ExposeBonusTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			float num = ((_bonusMultiplier == null) ? 0f : _bonusMultiplier.Value);
			bool flag = false;
			int num2 = 0;
			for (int i = 0; i < list.Count; i++)
			{
				CodeInstruction val = list[i];
				FieldInfo fieldInfo = val.operand as FieldInfo;
				if (fieldInfo != null && string.Equals(fieldInfo.Name, "MercExpose", StringComparison.Ordinal))
				{
					flag = true;
				}
				else if (flag && !(val.opcode != OpCodes.Ldc_R4) && val.operand is float && !(Mathf.Abs((float)val.operand - 3.5f) > 0.0001f))
				{
					val.operand = num;
					flag = false;
					num2++;
				}
			}
			if (num2 == 1)
			{
				Log((LogLevel)16, "暴露额外伤害已改写:" + 3.5f.ToString("0.##") + " → " + num.ToString("0.##") + "(0 = 取消那 350% 加成,改为挂残废;暴露消耗与冷却缩减保持原版)。");
			}
			else
			{
				Log((LogLevel)4, "暴露额外伤害改写异常:命中 " + num2 + " 处(预期 1 处),伤害加成可能仍是原版的 " + 3.5f.ToString("0.##") + " 倍。请把这条日志连同游戏版本一起反馈。");
			}
			return list;
		}

		private static bool IsMercAttacker(GameObject attacker)
		{
			if (_requireMercAttacker != null && !_requireMercAttacker.Value)
			{
				return true;
			}
			if ((Object)(object)attacker == (Object)null)
			{
				return false;
			}
			CharacterBody component = attacker.GetComponent<CharacterBody>();
			if ((Object)(object)component != (Object)null && !string.IsNullOrEmpty(component.baseNameToken) && component.baseNameToken.IndexOf("MERC", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			return ((Object)attacker).name.StartsWith("MercBody", StringComparison.OrdinalIgnoreCase);
		}

		private static BuffDef ResolveBuff(ref BuffDef cache, string keyword)
		{
			//IL_004e: 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)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Invalid comparison between Unknown and I4
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected I4, but got Unknown
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Expected I4, but got Unknown
			if ((Object)(object)cache != (Object)null)
			{
				return cache;
			}
			string[] array = new string[4]
			{
				"bd" + keyword,
				keyword,
				"RoR2/Base/Buffs/bd" + keyword + ".asset",
				"RoR2/Base/Buffs/bd" + keyword
			};
			for (int i = 0; i < array.Length; i++)
			{
				BuffIndex val = BuffCatalog.FindBuffIndex(array[i]);
				if ((int)val > 0)
				{
					BuffDef buffDef = BuffCatalog.GetBuffDef(val);
					if ((Object)(object)buffDef != (Object)null)
					{
						cache = buffDef;
						Log((LogLevel)16, "BuffDef 已定位:" + keyword + " 按名字 " + array[i] + " 命中,BuffIndex " + (int)val + "。");
						return buffDef;
					}
				}
			}
			BuffDef[] allBuffDefs = GetAllBuffDefs();
			if (allBuffDefs != null)
			{
				foreach (BuffDef val2 in allBuffDefs)
				{
					if (!((Object)(object)val2 == (Object)null) && !string.IsNullOrEmpty(((Object)val2).name) && ((Object)val2).name.IndexOf(keyword, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						cache = val2;
						Log((LogLevel)16, "BuffDef 已定位:" + keyword + " 按资产名 " + ((Object)val2).name + " 命中,BuffIndex " + (int)val2.buffIndex + "。");
						return val2;
					}
				}
			}
			Log((LogLevel)4, "BuffDef 定位失败:" + keyword + ",相关功能不会生效。已扫描的 BuffDef 数量:" + ((allBuffDefs == null) ? "null" : allBuffDefs.Length.ToString()) + ",前 40 个资产名:");
			if (allBuffDefs != null)
			{
				for (int k = 0; k < allBuffDefs.Length && k < 40; k++)
				{
					if (!((Object)(object)allBuffDefs[k] == (Object)null))
					{
						Log((LogLevel)4, "    [" + k + "] " + (string.IsNullOrEmpty(((Object)allBuffDefs[k]).name) ? "(空)" : ((Object)allBuffDefs[k]).name));
					}
				}
			}
			return null;
		}

		private static BuffDef[] GetAllBuffDefs()
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(BuffCatalog), "buffDefs");
			if (fieldInfo == null)
			{
				Log((LogLevel)4, "BuffDef 定位失败:反射拿不到 BuffCatalog.buffDefs。");
				return null;
			}
			return fieldInfo.GetValue(null) as BuffDef[];
		}

		private static void LogThrottled(string message)
		{
			if (!(Time.time - _lastLogAt < 3f))
			{
				_lastLogAt = Time.time;
				Log((LogLevel)16, message);
			}
		}

		private static void Log(LogLevel level, string message)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (_log != null)
			{
				_log.Log(level, (object)("[SparkleMercTweaks] " + message));
			}
		}
	}
	public static class MercSecondaryTweaks
	{
		private const string WhirlwindDescriptionToken = "MERC_SECONDARY_DESCRIPTION";

		private const string UppercutDescriptionToken = "MERC_SECONDARY_ALT1_DESCRIPTION";

		private const string WhirlwindDescription = "快速横斩两次,每次造成<style=cIsDamage>350%的伤害</style>,若位于空中,则改为<style=cIsUtility>竖斩</style>。";

		private const string UppercutDescription = "跳起并释放一个上挑斩,造成<style=cIsDamage>700%的伤害</style>并<style=cIsUtility>击飞敌人</style>。";

		private static readonly string[] WhirlwindTypeNames = new string[3] { "EntityStates.Merc.WhirlwindBase", "EntityStates.Merc.WhirlwindGround", "EntityStates.Merc.WhirlwindAir" };

		private static ConfigEntry<float> _whirlwindCoefficient;

		private static ConfigEntry<float> _uppercutCoefficient;

		private static ConfigEntry<bool> _overrideDescription;

		private static ManualLogSource _log;

		private static int _whirlwindPatched;

		private static bool _whirlwindLogged;

		private static float _whirlwindOriginal = -1f;

		private static bool _whirlwindErrorLogged;

		private static FieldInfo _uppercutField;

		private static bool _uppercutLogged;

		private static float _uppercutOriginal = -1f;

		public static void Init(ConfigFile cfg, ManualLogSource logger)
		{
			_log = logger;
			_whirlwindCoefficient = cfg.Bind<float>("Whirlwind", "DamageCoefficient", 3.5f, "旋风斩每段挥砍的伤害系数(百分比)。3.5 = 350%(原版是 2 = 200%),段数仍是原版的 2 段。\n填 0 或负数 = 不改这项,保持原版 200%。");
			_uppercutCoefficient = cfg.Bind<float>("Uppercut", "DamageCoefficient", 7f, "升雷的单段伤害系数(百分比)。7 = 700%,原版是 5.5(550%)。\n填 0 或负数 = 不改这项,保持原版 550%。");
			_overrideDescription = cfg.Bind<bool>("Secondary", "OverrideSkillDescription", true, "是否把游戏内「旋风斩 / 升雷」的技能说明改成与实际效果一致的描述。关掉则显示原版文本。");
			_uppercutField = FindStaticFloatField("EntityStates.Merc.Uppercut", "升雷");
		}

		public static void Patch(Harmony harmony)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(MercSecondaryTweaks), "WhirlwindOnEnterPostfix", (Type[])null, (Type[])null);
			string[] whirlwindTypeNames = WhirlwindTypeNames;
			foreach (string text in whirlwindTypeNames)
			{
				Type type = AccessTools.TypeByName(text);
				if (!(type == null))
				{
					MethodInfo methodInfo2 = AccessTools.Method(type, "OnEnter", (Type[])null, (Type[])null);
					if (!(methodInfo2 == null) && !(methodInfo2.DeclaringType != type))
					{
						harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						_whirlwindPatched++;
						Log((LogLevel)16, "补丁已挂载:" + text + ".OnEnter() <- WhirlwindOnEnterPostfix()(旋风斩每段伤害系数覆写)");
					}
				}
			}
			if (_whirlwindPatched == 0)
			{
				Log((LogLevel)2, "旋风斩伤害改动未生效:三个 Whirlwind 类里都没找到可挂的 OnEnter()。");
			}
		}

		public static string Summary()
		{
			float num = ((_whirlwindCoefficient == null) ? 3.5f : _whirlwindCoefficient.Value);
			float num2 = ((_uppercutCoefficient == null) ? 7f : _uppercutCoefficient.Value);
			return " [旋风斩:" + ((num > 0f) ? ((num * 100f).ToString("0") + "%") : "原版 200%") + "] [升雷:" + ((num2 > 0f) ? ((num2 * 100f).ToString("0") + "%") : "原版 550%") + "]";
		}

		public static void ApplyLanguage()
		{
			if (_overrideDescription != null && _overrideDescription.Value)
			{
				LanguageAPI.Add("MERC_SECONDARY_DESCRIPTION", "快速横斩两次,每次造成<style=cIsDamage>350%的伤害</style>,若位于空中,则改为<style=cIsUtility>竖斩</style>。", "en");
				LanguageAPI.Add("MERC_SECONDARY_DESCRIPTION", "快速横斩两次,每次造成<style=cIsDamage>350%的伤害</style>,若位于空中,则改为<style=cIsUtility>竖斩</style>。", "zh-CN");
				LanguageAPI.Add("MERC_SECONDARY_ALT1_DESCRIPTION", "跳起并释放一个上挑斩,造成<style=cIsDamage>700%的伤害</style>并<style=cIsUtility>击飞敌人</style>。", "en");
				LanguageAPI.Add("MERC_SECONDARY_ALT1_DESCRIPTION", "跳起并释放一个上挑斩,造成<style=cIsDamage>700%的伤害</style>并<style=cIsUtility>击飞敌人</style>。", "zh-CN");
			}
		}

		public static void ApplyCoefficients()
		{
			float target = ((_uppercutCoefficient == null) ? 7f : _uppercutCoefficient.Value);
			ApplyStatic(_uppercutField, target, "升雷", ref _uppercutLogged, ref _uppercutOriginal);
		}

		public static void WhirlwindOnEnterPostfix(object __instance)
		{
			float num = ((_whirlwindCoefficient == null) ? 3.5f : _whirlwindCoefficient.Value);
			if (num <= 0f || __instance == null)
			{
				return;
			}
			Type type = __instance.GetType();
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(type, "baseDamageCoefficient");
				FieldInfo fieldInfo2 = AccessTools.Field(type, "overlapAttack");
				if (fieldInfo == null || fieldInfo2 == null)
				{
					return;
				}
				float num2 = Convert.ToSingle(fieldInfo.GetValue(__instance));
				if (num2 <= 0f)
				{
					return;
				}
				object? value = fieldInfo2.GetValue(__instance);
				OverlapAttack val = (OverlapAttack)((value is OverlapAttack) ? value : null);
				if (val != null)
				{
					if (!_whirlwindLogged)
					{
						_whirlwindLogged = true;
						_whirlwindOriginal = num2;
						Log((LogLevel)16, "旋风斩原版伤害系数基准 = " + num2.ToString("0.##") + "(= " + (num2 * 100f).ToString("0") + "%),将覆写为 " + num.ToString("0.##") + "(= " + (num * 100f).ToString("0") + "%)。");
					}
					if (Mathf.Abs(num2 - num) > 0.0001f)
					{
						val.damage = val.damage / num2 * num;
						fieldInfo.SetValue(__instance, num);
					}
				}
			}
			catch (Exception ex)
			{
				if (!_whirlwindErrorLogged)
				{
					_whirlwindErrorLogged = true;
					Log((LogLevel)4, "旋风斩伤害覆写异常:" + ex.GetType().Name + " " + ex.Message);
				}
			}
		}

		private static void ApplyStatic(FieldInfo field, float target, string label, ref bool logged, ref float original)
		{
			if (field == null || target <= 0f)
			{
				return;
			}
			try
			{
				float num = Convert.ToSingle(field.GetValue(null));
				if (!(num <= 0f))
				{
					if (!logged)
					{
						logged = true;
						original = num;
						Log((LogLevel)16, label + "原版伤害系数基准 = " + num.ToString("0.##") + "(= " + (num * 100f).ToString("0") + "%),将覆写为 " + target.ToString("0.##") + "(= " + (target * 100f).ToString("0") + "%)。");
					}
					if (Mathf.Abs(num - target) > 0.0001f)
					{
						field.SetValue(null, target);
					}
				}
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, label + "伤害系数覆写异常(已忽略):" + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static FieldInfo FindStaticFloatField(string typeName, string label)
		{
			Type type = AccessTools.TypeByName(typeName);
			if (type == null)
			{
				Log((LogLevel)4, label + "伤害改动未生效:找不到类型 " + typeName + "。");
				return null;
			}
			FieldInfo fieldInfo = AccessTools.Field(type, "baseDamageCoefficient");
			if (fieldInfo == null)
			{
				Log((LogLevel)4, label + "伤害改动未生效:反射拿不到 " + typeName + ".baseDamageCoefficient。");
			}
			return fieldInfo;
		}

		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)("[SparkleMercTweaks] " + message));
			}
		}
	}
	public static class MercSlicingWindsTweak
	{
		private const string BladeName = "EvisProjectile";

		private const string WindName = "EvisOverlapProjectile";

		private const string AltDescriptionToken = "MERC_SPECIAL_ALT1_DESCRIPTION";

		private const uint ApplyMercExposeFlag = 8388608u;

		private const string AltDescriptionZh = "发射一片斩击风暴,在击中敌人时<style=cIsUtility>暴露</style>周围最多<style=cIsDamage>3名敌人</style>,并重复造成<style=cIsDamage>100%伤害</style>。";

		private static ConfigEntry<float> _speedMultiplier;

		private static ConfigEntry<bool> _scaleHitCount;

		private static ConfigEntry<bool> _removeExpose;

		private static ConfigEntry<bool> _exposeOnFirstHit;

		private static ConfigEntry<float> _bladeRadiusMultiplier;

		private static ConfigEntry<float> _windRadiusMultiplier;

		private static ConfigEntry<bool> _overrideDescription;

		private static ManualLogSource _log;

		private static int _castId;

		private static readonly Dictionary<int, int> _exposeCast = new Dictionary<int, int>();

		private static readonly Dictionary<int, float> _exposeAt = new Dictionary<int, float>();

		private const float SameCastWindow = 6f;

		private static FieldInfo _speedField;

		private static MethodInfo _setForwardSpeed;

		private static FieldInfo _fireFrequencyField;

		private static FieldInfo _resetIntervalField;

		private static FieldInfo _attackField;

		private static FieldInfo _hitboxOriginalScalesField;

		private static FieldInfo _hitboxTransformsField;

		private static FieldInfo _projDamageTypeField;

		private static FieldInfo _overlapDamageTypeField;

		private static FieldInfo _damageInfoTypeField;

		private static FieldInfo _comboDamageTypeField;

		private static FieldInfo _healthDamageInfoField;

		private static float _baseSpeed = -1f;

		private static float _baseFireFrequency = -1f;

		private static float _baseResetInterval = -1f;

		private static Vector3 _baseColliderSize = new Vector3(-1f, -1f, -1f);

		private static bool _baselineLogged;

		private static bool _exposeDiagnosed;

		private static bool _exposeClearedLogged;

		private static bool _exposeAppliedLogged;

		private static float _lastLogAt = -999f;

		public static void Init(ConfigFile cfg, ManualLogSource logger)
		{
			_log = logger;
			_speedMultiplier = cfg.Bind<float>("SlicingWinds", "ProjectileSpeedMultiplier", 2f, "「裂片之风」刀刃射弹的飞行速度倍率。2 = 翻倍(原版 90),1 = 原版。");
			_scaleHitCount = cfg.Bind<bool>("SlicingWinds", "ScaleHitCountWithAttackSpeed", true, "「裂片之风」的伤害段数是否随攻击速度缩放:段数 = 原版 8 段 x 角色攻击速度倍率。\n关掉则保持原版的固定 8 段。");
			_removeExpose = cfg.Bind<bool>("SlicingWinds", "RemoveExpose", true, "是否移除「裂片之风」原版的「暴露」效果(原版是最后一次打击才给敌人挂暴露)。\ntrue = 清掉原版那次暴露(配合 ApplyExposeOnFirstHit 就变成首次命中暴露),false = 完全保留原版。");
			_exposeOnFirstHit = cfg.Bind<bool>("SlicingWinds", "ApplyExposeOnFirstHit", true, "「裂片之风」是否改为首次命中就给敌人挂「暴露」:每次施法对每个敌人只挂一次。\ntrue = 第一下就暴露(与原版「最后一下才暴露」不同),false = 不额外施加。");
			_bladeRadiusMultiplier = cfg.Bind<float>("SlicingWinds", "BladeRadiusMultiplier", 2f, "「裂片之风」刀刃本体飞行时的判定范围倍率(改的是 BoxCollider 尺寸)。\n2 = 扩大 100%,1.5 = 扩大 50%,1 = 原版。");
			_windRadiusMultiplier = cfg.Bind<float>("SlicingWinds", "WindRadiusMultiplier", 1.25f, "「裂片之风」风场的伤害判定范围倍率(改的是 ProjectileOverlapAttack 的 HitBox 缩放)。\n1.25 = 扩大 25%,1.5 = 扩大 50%,1 = 原版。");
			_overrideDescription = cfg.Bind<bool>("SlicingWinds", "OverrideSkillDescription", true, "是否把游戏内「裂片之风」的技能说明改成与实际效果一致的描述。\n关掉则显示原版文本。改完需要重启游戏。");
			_speedField = AccessTools.Field(typeof(ProjectileSimple), "desiredForwardSpeed");
			_setForwardSpeed = AccessTools.Method(typeof(ProjectileSimple), "SetForwardSpeed", (Type[])null, (Type[])null);
			_fireFrequencyField = AccessTools.Field(typeof(ProjectileOverlapAttack), "fireFrequency");
			_resetIntervalField = AccessTools.Field(typeof(ProjectileOverlapAttack), "resetInterval");
			_attackField = AccessTools.Field(typeof(ProjectileOverlapAttack), "attack");
			_hitboxOriginalScalesField = AccessTools.Field(typeof(ProjectileOverlapAttack), "HitboxOriginalScales");
			_hitboxTransformsField = AccessTools.Field(typeof(ProjectileOverlapAttack), "HitboxTransforms");
			_projDamageTypeField = AccessTools.Field(typeof(ProjectileDamage), "damageType");
			_damageInfoTypeField = AccessTools.Field(typeof(DamageInfo), "damageType");
			_healthDamageInfoField = AccessTools.Field(typeof(HealthComponent), "damageInfo");
			if (_damageInfoTypeField != null)
			{
				_comboDamageTypeField = AccessTools.Field(_damageInfoTypeField.FieldType, "damageType");
			}
			if (_attackField != null)
			{
				_overlapDamageTypeField = AccessTools.Field(_attackField.FieldType, "damageType");
			}
			if (_speedField == null)
			{
				Log((LogLevel)2, "字段定位失败:ProjectileSimple.desiredForwardSpeed,速度调整不会生效。");
			}
			if (_setForwardSpeed == null)
			{
				Log((LogLevel)2, "方法定位失败:ProjectileSimple.SetForwardSpeed,速度调整不会生效。");
			}
			if (_fireFrequencyField == null || _resetIntervalField == null)
			{
				Log((LogLevel)2, "字段定位失败:ProjectileOverlapAttack.fireFrequency / resetInterval,段数调整不会生效。");
			}
			if (_hitboxOriginalScalesField == null || _hitboxTransformsField == null)
			{
				Log((LogLevel)2, "字段定位失败:ProjectileOverlapAttack.HitboxOriginalScales / HitboxTransforms,判定范围不会生效。");
			}
			if (_comboDamageTypeField == null)
			{
				Log((LogLevel)2, "字段定位失败:DamageTypeCombo.damageType,移除「暴露」不会生效。");
			}
		}

		public static string Summary()
		{
			float num = ((_speedMultiplier == null) ? 2f : _speedMultiplier.Value);
			string text = ((_scaleHitCount == null || _scaleHitCount.Value) ? "随攻速" : "固定");
			bool num2 = _exposeOnFirstHit != null && _exposeOnFirstHit.Value;
			bool flag = _removeExpose == null || _removeExpose.Value;
			string text2 = (num2 ? "首击暴露" : (flag ? "无暴露" : "原版暴露"));
			float num3 = ((_bladeRadiusMultiplier == null) ? 2f : _bladeRadiusMultiplier.Value);
			float num4 = ((_windRadiusMultiplier == null) ? 1.25f : _windRadiusMultiplier.Value);
			return " [裂片之风:速度 x" + num.ToString("0.##") + " 段数" + text + " 判定 刀刃x" + num3.ToString("0.##") + "/风场x" + num4.ToString("0.##") + " " + text2 + "]";
		}

		public static void ApplyLanguage()
		{
			if (_overrideDescription != null && _overrideDescription.Value)
			{
				LanguageAPI.Add("MERC_SPECIAL_ALT1_DESCRIPTION", "发射一片斩击风暴,在击中敌人时<style=cIsUtility>暴露</style>周围最多<style=cIsDamage>3名敌人</style>,并重复造成<style=cIsDamage>100%伤害</style>。", "en");
				LanguageAPI.Add("MERC_SPECIAL_ALT1_DESCRIPTION", "发射一片斩击风暴,在击中敌人时<style=cIsUtility>暴露</style>周围最多<style=cIsDamage>3名敌人</style>,并重复造成<style=cIsDamage>100%伤害</style>。", "zh-CN");
			}
		}

		public static void Patch(Harmony harmony)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(ProjectileSimple), "Start", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				Log((LogLevel)2, "「裂片之风」补丁失败:找不到 ProjectileSimple.Start。");
			}
			else
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(MercSlicingWindsTweak), "BladeStartPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Log((LogLevel)16, "补丁已挂载:ProjectileSimple.Start <- BladeStartPostfix()(裂片之风刀刃提速 + 判定放大)");
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(ProjectileOverlapAttack), "Start", (Type[])null, (Type[])null);
			if (methodInfo2 == null)
			{
				Log((LogLevel)2, "「裂片之风」补丁失败:找不到 ProjectileOverlapAttack.Start。");
			}
			else
			{
				harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(MercSlicingWindsTweak), "WindStartPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Log((LogLevel)16, "补丁已挂载:ProjectileOverlapAttack.Start <- WindStartPostfix()(裂片之风段数随攻速 + 去原版暴露 + 判定放大)");
			}
			MethodInfo methodInfo3 = AccessTools.Method(typeof(HealthComponent), "TakeDamageProcess", (Type[])null, (Type[])null);
			if (methodInfo3 == null)
			{
				Log((LogLevel)2, "「裂片之风」补丁失败:找不到 HealthComponent.TakeDamageProcess(暴露时机控制)。");
				return;
			}
			harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(AccessTools.Method(typeof(MercSlicingWindsTweak), "ExposeControlPrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Log((LogLevel)16, "补丁已挂载:HealthComponent.TakeDamageProcess <- ExposeControlPrefix()(裂片之风首击暴露)");
		}

		public static void BladeStartPostfix(ProjectileSimple __instance)
		{
			try
			{
				if ((Object)(object)__instance == (Object)null)
				{
					return;
				}
				GameObject gameObject = ((Component)__instance).gameObject;
				if ((Object)(object)gameObject == (Object)null || !((Object)gameObject).name.StartsWith("EvisProjectile", StringComparison.Ordinal) || (Object)(object)gameObject.GetComponent<ProjectileExplosion>() == (Object)null)
				{
					return;
				}
				_castId++;
				if (_speedField != null && _setForwardSpeed != null)
				{
					float baseSpeed = Convert.ToSingle(_speedField.GetValue(__instance));
					if (_baseSpeed < 0f)
					{
						_baseSpeed = baseSpeed;
					}
					float num = ((_speedMultiplier == null) ? 1f : _speedMultiplier.Value);
					if (num <= 0f)
					{
						num = 1f;
					}
					float num2 = _baseSpeed * num;
					_speedField.SetValue(__instance, num2);
					_setForwardSpeed.Invoke(__instance, new object[1] { num2 });
				}
				ScaleBladeCollider(gameObject);
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "「裂片之风」刀刃处理异常(已忽略):" + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static void ScaleBladeCollider(GameObject go)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			float num = ((_bladeRadiusMultiplier == null) ? 2f : _bladeRadiusMultiplier.Value);
			if (num <= 0f)
			{
				num = 1f;
			}
			BoxCollider component = go.GetComponent<BoxCollider>();
			if ((Object)(object)component != (Object)null)
			{
				if (_baseColliderSize.x < 0f)
				{
					_baseColliderSize = component.size;
				}
				component.size = _baseColliderSize * num;
				string[] obj = new string[7]
				{
					"「裂片之风」刀刃判定范围:原版 ",
					((Vector3)(ref _baseColliderSize)).ToString("0.##"),
					" → ",
					null,
					null,
					null,
					null
				};
				Vector3 size = component.size;
				obj[3] = ((Vector3)(ref size)).ToString("0.##");
				obj[4] = "(x";
				obj[5] = num.ToString("0.##");
				obj[6] = ")。";
				LogThrottled(string.Concat(obj));
				return;
			}
			SphereCollider component2 = go.GetComponent<SphereCollider>();
			if ((Object)(object)component2 != (Object)null)
			{
				if (_baseColliderSize.x < 0f)
				{
					_baseColliderSize = new Vector3(component2.radius, component2.radius, component2.radius);
				}
				component2.radius = _baseColliderSize.x * num;
			}
		}

		public static void WindStartPostfix(ProjectileOverlapAttack __instance)
		{
			try
			{
				if ((Object)(object)__instance == (Object)null)
				{
					return;
				}
				GameObject gameObject = ((Component)__instance).gameObject;
				if ((Object)(object)gameObject == (Object)null || !((Object)gameObject).name.StartsWith("EvisOverlapProjectile", StringComparison.Ordinal))
				{
					return;
				}
				if (_fireFrequencyField != null && _resetIntervalField != null)
				{
					float baseFireFrequency = Convert.ToSingle(_fireFrequencyField.GetValue(__instance));
					float baseResetInterval = Convert.ToSingle(_resetIntervalField.GetValue(__instance));
					if (_baseFireFrequency < 0f)
					{
						_baseFireFrequency = baseFireFrequency;
					}
					if (_baseResetInterval < 0f)
					{
						_baseResetInterval = baseResetInterval;
					}
					if (_scaleHitCount == null || _scaleHitCount.Value)
					{
						float ownerAttackSpeed = GetOwnerAttackSpeed(gameObject);
						float num = _baseFireFrequency * ownerAttackSpeed;
						if (num < 0.5f)
						{
							num = 0.5f;
						}
						float num2 = _baseResetInterval / ownerAttackSpeed;
						if (num2 <= 0f)
						{
							num2 = 1f / num;
						}
						_fireFrequencyField.SetValue(__instance, num);
						_resetIntervalField.SetValue(__instance, num2);
						LogThrottled("「裂片之风」段数随攻击速度生效:攻击速度 x" + ownerAttackSpeed.ToString("0.##") + ",原版 " + _baseFireFrequency.ToString("0.##") + " 段 → 本次 " + num.ToString("0.##") + " 段(重置间隔 " + _baseResetInterval.ToString("0.###") + " → " + num2.ToString("0.###") + ")。");
					}
				}
				RemoveExposeFromWind(__instance);
				ScaleWindHitboxes(__instance);
				LogBaselineOnce();
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "「裂片之风」风场处理异常(已忽略):" + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static void RemoveExposeFromWind(ProjectileOverlapAttack instance)
		{
			if (_removeExpose == null || !_removeExpose.Value)
			{
				return;
			}
			ProjectileDamage component = ((Component)instance).GetComponent<ProjectileDamage>();
			uint num = 0u;
			if ((Object)(object)component != (Object)null && _projDamageTypeField != null)
			{
				object value = _projDamageTypeField.GetValue(component);
				num = ComboDamageTypeValue(value);
				if (ClearExposeFlag(value))
				{
					_projDamageTypeField.SetValue(component, value);
				}
			}
			if (_attackField != null && _overlapDamageTypeField != null)
			{
				object value2 = _attackField.GetValue(instance);
				if (value2 != null)
				{
					object value3 = _overlapDamageTypeField.GetValue(value2);
					if (num == 0)
					{
						num = ComboDamageTypeValue(value3);
					}
					if (ClearExposeFlag(value3))
					{
						_overlapDamageTypeField.SetValue(value2, value3);
					}
				}
			}
			if (!_exposeDiagnosed)
			{
				_exposeDiagnosed = true;
				bool flag = (num & 0x800000) != 0;
				Log((LogLevel)16, "「裂片之风」风场伤害类型诊断:damageType = " + num + ",是否带「暴露」标志(" + 8388608u + ")= " + (flag ? "是" : "否") + "。已按配置处理。");
			}
		}

		private static void ScaleWindHitboxes(ProjectileOverlapAttack instance)
		{
			//IL_008a: 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)
			if (_hitboxOriginalScalesField == null || _hitboxTransformsField == null)
			{
				return;
			}
			float num = ((_windRadiusMultiplier == null) ? 1.25f : _windRadiusMultiplier.Value);
			if (num <= 0f)
			{
				num = 1f;
			}
			Vector3[] array = _hitboxOriginalScalesField.GetValue(instance) as Vector3[];
			Transform[] array2 = _hitboxTransformsField.GetValue(instance) as Transform[];
			if (array == null || array2 == null)
			{
				Log((LogLevel)4, "「裂片之风」判定范围:HitboxOriginalScales / HitboxTransforms 取不到,跳过放大。");
				return;
			}
			for (int i = 0; i < array2.Length && i < array.Length; i++)
			{
				if (!((Object)(object)array2[i] == (Object)null))
				{
					array2[i].localScale = array[i] * num;
				}
			}
			LogThrottled("「裂片之风」风场判定范围:HitBox 数量 " + array2.Length + ",缩放 x" + num.ToString("0.##") + "。");
		}

		public static void ExposeControlPrefix(HealthComponent __instance, ref DamageInfo damageInfo)
		{
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			try
			{
				bool num = _removeExpose == null || _removeExpose.Value;
				bool flag = _exposeOnFirstHit != null && _exposeOnFirstHit.Value;
				if (!num && !flag)
				{
					return;
				}
				GameObject inflictor = damageInfo.inflictor;
				if ((Object)(object)inflictor == (Object)null)
				{
					return;
				}
				string name = ((Object)inflictor).name;
				if ((!name.StartsWith("EvisProjectile", StringComparison.Ordinal) && !name.StartsWith("EvisOverlapProjectile", StringComparison.Ordinal)) || _damageInfoTypeField == null || _comboDamageTypeField == null)
				{
					return;
				}
				bool flag2 = IsFirstHitOfCast(__instance);
				bool flag3 = flag && flag2;
				object obj = damageInfo;
				object value = _damageInfoTypeField.GetValue(obj);
				if (flag3 ? SetExposeFlag(value) : ClearExposeFlag(value))
				{
					_damageInfoTypeField.SetValue(obj, value);
					damageInfo = (DamageInfo)obj;
				}
				if (_healthDamageInfoField != null && (Object)(object)__instance != (Object)null)
				{
					object value2 = _healthDamageInfoField.GetValue(__instance);
					object value3 = _damageInfoTypeField.GetValue(value2);
					if (flag3 ? SetExposeFlag(value3) : ClearExposeFlag(value3))
					{
						_damageInfoTypeField.SetValue(value2, value3);
						_healthDamageInfoField.SetValue(__instance, value2);
					}
				}
				if (flag3 && !_exposeAppliedLogged)
				{
					_exposeAppliedLogged = true;
					Log((LogLevel)16, "「裂片之风」首击暴露已生效:本次伤害来自 " + name + ",已给目标加上「暴露」(ApplyMercExpose)。本次施法序号 " + _castId + "。");
				}
				else if (!flag3 && !flag2 && !_exposeClearedLogged)
				{
					_exposeClearedLogged = true;
					Log((LogLevel)16, "「裂片之风」后续伤害段已清掉「暴露」标志位(本次施法只暴露一次)。");
				}
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "「裂片之风」暴露控制异常(已忽略):" + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static bool IsFirstHitOfCast(HealthComponent victim)
		{
			if ((Object)(object)victim == (Object)null)
			{
				return false;
			}
			int instanceID = ((Object)victim).GetInstanceID();
			float time = Time.time;
			int value;
			bool num = _exposeCast.TryGetValue(instanceID, out value);
			float value2;
			float num2 = (_exposeAt.TryGetValue(instanceID, out value2) ? value2 : (-999f));
			int num3;
			if (num && value == _castId)
			{
				num3 = ((time - num2 > 6f) ? 1 : 0);
				if (num3 == 0)
				{
					goto IL_007a;
				}
			}
			else
			{
				num3 = 1;
			}
			_exposeCast[instanceID] = _castId;
			_exposeAt[instanceID] = time;
			PruneExposeRecords();
			goto IL_007a;
			IL_007a:
			return (byte)num3 != 0;
		}

		private static void PruneExposeRecords()
		{
			if (_exposeCast.Count < 64)
			{
				return;
			}
			List<int> list = new List<int>();
			foreach (KeyValuePair<int, int> item in _exposeCast)
			{
				if (item.Value != _castId)
				{
					list.Add(item.Key);
				}
			}
			for (int i = 0; i < list.Count; i++)
			{
				_exposeCast.Remove(list[i]);
				_exposeAt.Remove(list[i]);
			}
		}

		private static uint ComboDamageTypeValue(object combo)
		{
			if (combo == null || _comboDamageTypeField == null)
			{
				return 0u;
			}
			try
			{
				return Convert.ToUInt32(_comboDamageTypeField.GetValue(combo));
			}
			catch (Exception)
			{
				return 0u;
			}
		}

		private static bool ClearExposeFlag(object combo)
		{
			if (combo == null || _comboDamageTypeField == null)
			{
				return false;
			}
			uint num;
			try
			{
				num = Convert.ToUInt32(_comboDamageTypeField.GetValue(combo));
			}
			catch (Exception)
			{
				return false;
			}
			if ((num & 0x800000) == 0)
			{
				return false;
			}
			_comboDamageTypeField.SetValue(combo, Enum.ToObject(_comboDamageTypeField.FieldType, num & 0xFF7FFFFFu));
			return true;
		}

		private static bool SetExposeFlag(object combo)
		{
			if (combo == null || _comboDamageTypeField == null)
			{
				return false;
			}
			uint num;
			try
			{
				num = Convert.ToUInt32(_comboDamageTypeField.GetValue(combo));
			}
			catch (Exception)
			{
				return false;
			}
			if ((num & 0x800000) != 0)
			{
				return false;
			}
			_comboDamageTypeField.SetValue(combo, Enum.ToObject(_comboDamageTypeField.FieldType, num | 0x800000));
			return true;
		}

		private static float GetOwnerAttackSpeed(GameObject projectile)
		{
			ProjectileController component = projectile.GetComponent<ProjectileController>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.owner == (Object)null)
			{
				return 1f;
			}
			CharacterBody component2 = component.owner.GetComponent<CharacterBody>();
			if ((Object)(object)component2 == (Object)null)
			{
				return 1f;
			}
			float num = component2.attackSpeed;
			if (num < 0.1f)
			{
				num = 0.1f;
			}
			return num;
		}

		private static void LogBaselineOnce()
		{
			if (!_baselineLogged && !(_baseFireFrequency < 0f))
			{
				_baselineLogged = true;
				Log((LogLevel)16, "「裂片之风」原版数值已记录:风场段数 " + _baseFireFrequency.ToString("0.##") + " 段/秒(重置间隔 " + _baseResetInterval.ToString("0.###") + ")" + ((_baseSpeed >= 0f) ? (",刀刃速度 " + _baseSpeed.ToString("0.##")) : "") + "。");
			}
		}

		private static void LogThrottled(string message)
		{
			if (!(Time.time - _lastLogAt < 3f))
			{
				_lastLogAt = Time.time;
				Log((LogLevel)16, message);
			}
		}

		private static void Log(LogLevel level, string message)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (_log != null)
			{
				_log.Log(level, (object)("[SparkleMercTweaks] " + message));
			}
		}
	}
	public static class MercUtilityTweaks
	{
		private const string BlindingAssaultDescriptionToken = "MERC_UTILITY_DESCRIPTION";

		private const string FocusedAssaultDescriptionToken = "MERC_UTILITY_ALT1_DESCRIPTION";

		private const string BlindingAssaultDescription = "<style=cIsUtility>眩晕</style>。向前连续冲锋并造成<style=cIsDamage>400%的伤害</style>,最多<style=cIsDamage>3</style>次。";

		private const string FocusedAssaultDescription = "<style=cIsUtility>眩晕</style>。向前冲锋并在<style=cIsDamage>1秒</style>后造成<style=cIsDamage>800%的伤害</style>并<style=cIsUtility>暴露</style>敌人。";

		private static ConfigEntry<float> _blindingCoefficient;

		private static ConfigEntry<bool> _removeHitRequirement;

		private static ConfigEntry<float> _focusedCoefficient;

		private static ConfigEntry<bool> _overrideDescription;

		private static ManualLogSource _log;

		private static FieldInfo _assaulterStaticField;

		private static bool _assaulterStaticLogged;

		private static float _assaulterStaticOriginal = -1f;

		private static bool _focusedLogged;

		private static bool _blindingLogged;

		private static bool _dashGrantedLogged;

		public static void Init(ConfigFile cfg, ManualLogSource logger)
		{
			_log = logger;
			_blindingCoefficient = cfg.Bind<float>("BlindingAssault", "DamageCoefficient", 4f, "「盲目突击」每段冲刺的伤害系数(百分比)。4 = 400%(原版是 3 = 300%)。\n填 0 或负数 = 不改这项,保持原版 300%。");
			_removeHitRequirement = cfg.Bind<bool>("BlindingAssault", "RemoveHitRequirement", true, "是否移除「必须命中敌人才能进行下一段突击」的限制。\ntrue = 不管有没有打中都给下一段(原版只有命中才追加充能),false = 保持原版。");
			_focusedCoefficient = cfg.Bind<float>("FocusedAssault", "DamageCoefficient", 8f, "「凝神一击」的伤害系数(百分比)。8 = 800%(原版是 7 = 700%)。\n填 0 或负数 = 不改这项,保持原版 700%。");
			_overrideDescription = cfg.Bind<bool>("Utility", "OverrideSkillDescription", true, "是否把游戏内「盲目突击 / 凝神一击」的技能说明改成与实际效果一致的描述。关掉则显示原版文本。");
			Type type = AccessTools.TypeByName("EntityStates.Merc.Assaulter");
			if (type != null)
			{
				_assaulterStaticField = AccessTools.Field(type, "damageCoefficient");
			}
			if (_assaulterStaticField == null)
			{
				Log((LogLevel)4, "盲目突击静态伤害系数取不到(EntityStates.Merc.Assaulter.damageCoefficient),只改 Assaulter2 的实例系数;通常不影响效果。");
			}
		}

		public static string Summary()
		{
			float num = ((_blindingCoefficient == null) ? 4f : _blindingCoefficient.Value);
			float num2 = ((_focusedCoefficient == null) ? 8f : _focusedCoefficient.Value);
			return string.Concat(string.Concat(" [盲目突击:" + ((num > 0f) ? ((num * 100f).ToString("0") + "%") : "原版 300%") + "]", " [凝神一击:", (num2 > 0f) ? ((num2 * 100f).ToString("0") + "%") : "原版 700%", "]"), (_removeHitRequirement == null || _removeHitRequirement.Value) ? " [突击:免命中续段]" : "");
		}

		public static void ApplyLanguage()
		{
			if (_overrideDescription != null && _overrideDescription.Value)
			{
				LanguageAPI.Add("MERC_UTILITY_DESCRIPTION", "<style=cIsUtility>眩晕</style>。向前连续冲锋并造成<style=cIsDamage>400%的伤害</style>,最多<style=cIsDamage>3</style>次。", "en");
				LanguageAPI.Add("MERC_UTILITY_DESCRIPTION", "<style=cIsUtility>眩晕</style>。向前连续冲锋并造成<style=cIsDamage>400%的伤害</style>,最多<style=cIsDamage>3</style>次。", "zh-CN");
				LanguageAPI.Add("MERC_UTILITY_ALT1_DESCRIPTION", "<style=cIsUtility>眩晕</style>。向前冲锋并在<style=cIsDamage>1秒</style>后造成<style=cIsDamage>800%的伤害</style>并<style=cIsUtility>暴露</style>敌人。", "en");
				LanguageAPI.Add("MERC_UTILITY_ALT1_DESCRIPTION", "<style=cIsUtility>眩晕</style>。向前冲锋并在<style=cIsDamage>1秒</style>后造成<style=cIsDamage>800%的伤害</style>并<style=cIsUtility>暴露</style>敌人。", "zh-CN");
			}
		}

		public static void ApplyCoefficients()
		{
			if (_assaulterStaticField == null)
			{
				return;
			}
			float num = ((_blindingCoefficient == null) ? 4f : _blindingCoefficient.Value);
			if (num <= 0f)
			{
				return;
			}
			try
			{
				float num2 = Convert.ToSingle(_assaulterStaticField.GetValue(null));
				if (!(num2 <= 0f))
				{
					if (!_assaulterStaticLogged)
					{
						_assaulterStaticLogged = true;
						_assaulterStaticOriginal = num2;
						Log((LogLevel)16, "盲目突击静态伤害系数基准 = " + num2.ToString("0.##") + "(= " + (num2 * 100f).ToString("0") + "%),将覆写为 " + num.ToString("0.##") + "。");
					}
					if (Mathf.Abs(num2 - num) > 0.0001f)
					{
						_assaulterStaticField.SetValue(null, num);
					}
				}
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "盲目突击静态伤害系数覆写异常(已忽略):" + ex.GetType().Name + " " + ex.Message);
			}
		}

		public static void Patch(Harmony harmony)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			PatchInstance(harmony, "EntityStates.Merc.FocusedAssaultDash", "FocusedAssaultDamagePrefix", "凝神一击伤害系数");
			PatchInstance(harmony, "EntityStates.Merc.Assaulter2", "BlindingAssaultDamagePrefix", "盲目突击伤害系数");
			Type type = AccessTools.TypeByName("EntityStates.Merc.Assaulter2");
			MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "OnEnter", (Type[])null, (Type[])null));
			if (methodInfo == null)
			{
				Log((LogLevel)2, "「免命中续段」补丁失败:找不到 EntityStates.Merc.Assaulter2.OnEnter。");
				return;
			}
			try
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(MercUtilityTweaks), "Assaulter2OnEnterPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Log((LogLevel)16, "补丁已挂载:Assaulter2.OnEnter <- Assaulter2OnEnterPostfix()(盲目突击免命中续段)");
			}
			catch (Exception ex)
			{
				Log((LogLevel)2, "「免命中续段」补丁挂载失败:" + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static void PatchInstance(Harmony harmony, string typeName, string prefixName, string label)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			Type type = AccessTools.TypeByName(typeName);
			MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "AuthorityModifyOverlapAttack", (Type[])null, (Type[])null));
			if (methodInfo == null)
			{
				Log((LogLevel)2, label + "补丁失败:找不到 " + typeName + ".AuthorityModifyOverlapAttack。");
				return;
			}
			try
			{
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(MercUtilityTweaks), prefixName, (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Log((LogLevel)16, "补丁已挂载:" + typeName + ".AuthorityModifyOverlapAttack <- " + prefixName + "()(" + label + ")");
			}
			catch (Exception ex)
			{
				Log((LogLevel)2, label + "补丁挂载失败:" + ex.GetType().Name + " " + ex.Message);
			}
		}

		public static void FocusedAssaultDamagePrefix(object __instance)
		{
			ApplyInstanceCoefficient(__instance, _focusedCoefficient, 8f, "凝神一击", ref _focusedLogged);
		}

		public static void BlindingAssaultDamagePrefix(object __instance)
		{
			ApplyInstanceCoefficient(__instance, _blindingCoefficient, 4f, "盲目突击", ref _blindingLogged);
		}

		public static void Assaulter2OnEnterPostfix(object __instance)
		{
			try
			{
				if (_removeHitRequirement == null || !_removeHitRequirement.Value || __instance == null)
				{
					return;
				}
				FieldInfo fieldInfo = AccessTools.Field(__instance.GetType(), "grantAnotherDash");
				if (!(fieldInfo == null))
				{
					fieldInfo.SetValue(__instance, true);
					if (!_dashGrantedLogged)
					{
						_dashGrantedLogged = true;
						Log((LogLevel)16, "盲目突击「免命中续段」已生效:冲刺开始即视为可追加下一段(原版要命中才给,grantAnotherDash = true)。");
					}
				}
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "盲目突击「免命中续段」异常(已忽略):" + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static void ApplyInstanceCoefficient(object instance, ConfigEntry<float> entry, float fallback, string label, ref bool logged)
		{
			try
			{
				float num = entry?.Value ?? fallback;
				if (num <= 0f || instance == null)
				{
					return;
				}
				FieldInfo fieldInfo = AccessTools.Field(instance.GetType(), "damageCoefficient");
				if (fieldInfo == null)
				{
					return;
				}
				float num2 = Convert.ToSingle(fieldInfo.GetValue(instance));
				if (!(num2 <= 0f))
				{
					if (!logged)
					{
						logged = true;
						Log((LogLevel)16, label + "原版伤害系数基准 = " + num2.ToString("0.##") + "(= " + (num2 * 100f).ToString("0") + "%),将覆写为 " + num.ToString("0.##") + "(= " + (num * 100f).ToString("0") + "%)。");
					}
					if (Mathf.Abs(num2 - num) > 0.0001f)
					{
						fieldInfo.SetValue(instance, num);
					}
				}
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, label + "伤害系数覆写异常(已忽略):" + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static void Log(LogLevel level, string message)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (_log != null)
			{
				_log.Log(level, (object)("[SparkleMercTweaks] " + message));
			}
		}
	}
	[BepInPlugin("com.sparkletwilight.sparklemerctweaks", "SparkleMercTweaks", "1.19.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class SparkleMercTweaksPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.sparkletwilight.sparklemerctweaks";

		public const string PluginName = "SparkleMercTweaks";

		public const string PluginVersion = "1.19.0";

		public void Awake()
		{
			//IL_006e: 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_008a: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			//IL_00b8: Expected O, but got Unknown
			MercEvisTweak.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			MercEvisTweak.ApplyLanguage();
			MercSlicingWindsTweak.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			MercSlicingWindsTweak.ApplyLanguage();
			MercSecondaryTweaks.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			MercSecondaryTweaks.ApplyLanguage();
			MercUtilityTweaks.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			MercUtilityTweaks.ApplyLanguage();
			MercBodyStatsTweaks.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			Harmony val = new Harmony("com.sparkletwilight.sparklemerctweaks");
			EvisZeroArmorDouble.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			EvisZeroArmorDouble.Patch(val);
			MercSlicingWindsTweak.Patch(val);
			MercExposeCripple.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			MercExposeCripple.Patch(val);
			MercUtilityTweaks.Patch(val);
			MercSecondaryTweaks.Patch(val);
			MercBodyStatsTweaks.Patch(val);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("SparkleMercTweaks v1.19.0 已加载。" + MercEvisTweak.Summary() + EvisZeroArmorDouble.Summary() + MercSlicingWindsTweak.Summary() + MercExposeCripple.Summary() + MercSecondaryTweaks.Summary() + MercUtilityTweaks.Summary() + MercBodyStatsTweaks.Summary()));
		}

		public void Update()
		{
			MercEvisTweak.ApplyRadii();
			MercSecondaryTweaks.ApplyCoefficients();
			MercUtilityTweaks.ApplyCoefficients();
			MercEvisTweak.ProbeToken();
		}
	}
}