Decompiled source of SparkleHuntressTweaks v1.6.0

plugins/SparkleHuntressTweaks.dll

Decompiled 20 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
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.Huntress;
using EntityStates.Huntress.HuntressWeapon;
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("SparkleHuntressTweaks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.6.0.0")]
[assembly: AssemblyInformationalVersion("1.6.0")]
[assembly: AssemblyProduct("SparkleHuntressTweaks")]
[assembly: AssemblyTitle("SparkleHuntressTweaks")]
[assembly: AssemblyVersion("1.6.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 SparkleHuntressTweaks
{
	internal static class HuntressArrowRainTweaks
	{
		private const string SectionName = "ArrowRain.箭雨";

		private const string ProjectileName = "HuntressArrowRain";

		private const float FallbackOverlapCoefficient = 0.5f;

		private const float AimMaxDistance = 1000f;

		private static ManualLogSource _log;

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<float> _damageCoefficientPerTick;

		private static ConfigEntry<float> _procCoefficient;

		private static ConfigEntry<bool> _allowEnemyTargeting;

		private static ConfigEntry<float> _enemyAimAssistRadius;

		private static readonly MethodInfo GetAimRayMethod = AccessTools.Method(typeof(BaseState), "GetAimRay", (Type[])null, (Type[])null);

		private static readonly FieldInfo AreaIndicatorField = AccessTools.Field(typeof(ArrowRain), "areaIndicatorInstance");

		private static readonly FieldInfo AttackField = AccessTools.Field(typeof(ProjectileOverlapAttack), "attack");

		private static readonly FieldInfo ProjectileControllerField = AccessTools.Field(typeof(ProjectileOverlapAttack), "projectileController");

		private static readonly FieldInfo ControllerProcField = AccessTools.Field(typeof(ProjectileController), "procCoefficient");

		private static float _vanillaStateCoefficient = -1f;

		private static bool _loggedDamage;

		private static bool _loggedProc;

		private static bool _loggedTargeting;

		internal static void Init(ConfigFile config, ManualLogSource log)
		{
			_log = log;
			_enabled = config.Bind<bool>("ArrowRain.箭雨", "Enabled", true, "是否启用女猎人 R「箭雨」的调整(伤害倍率 / 触发系数 / 可对敌人释放)。");
			_damageCoefficientPerTick = config.Bind<float>("ArrowRain.箭雨", "DamageCoefficientPerTick", 1.5f, "箭雨每段伤害倍率。1.5 = 150% 攻击力;原版为 1.1。");
			_procCoefficient = config.Bind<float>("ArrowRain.箭雨", "ProcCoefficient", 0.5f, "箭雨的触发系数。0.5 = 50%;原版为 0.2。");
			_allowEnemyTargeting = config.Bind<bool>("ArrowRain.箭雨", "AllowEnemyTargeting", true, "是否允许把箭雨的落点瞄准在敌人身上(原版只能瞄地形)。");
			_enemyAimAssistRadius = config.Bind<float>("ArrowRain.箭雨", "EnemyAimAssistRadius", 1f, "瞄敌人的球形辅助半径:射线没打中时再按这个半径做一次球形扫描,0 = 关闭。");
		}

		internal static void Patch(Harmony harmony)
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(ArrowRain), "DoFireArrowRain", (Type[])null, (Type[])null);
			harmony.Patch((MethodBase)methodInfo, PatchMethod("Prefix_DoFireArrowRain"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_log.LogInfo((object)("补丁已挂载:ArrowRain.DoFireArrowRain <- Prefix_DoFireArrowRain() [target=" + (methodInfo != null) + "]"));
			MethodInfo methodInfo2 = AccessTools.Method(typeof(ProjectileOverlapAttack), "Start", (Type[])null, (Type[])null);
			harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, PatchMethod("Postfix_ProjectileOverlapAttackStart"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_log.LogInfo((object)("补丁已挂载:ProjectileOverlapAttack.Start <- Postfix_ProjectileOverlapAttackStart() [target=" + (methodInfo2 != null) + "]"));
			MethodInfo methodInfo3 = AccessTools.Method(typeof(ProjectileOverlapAttack), "OnEnable", (Type[])null, (Type[])null);
			harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, PatchMethod("Postfix_ProjectileOverlapAttackEnable"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_log.LogInfo((object)("补丁已挂载:ProjectileOverlapAttack.OnEnable <- Postfix_ProjectileOverlapAttackEnable() [target=" + (methodInfo3 != null) + "]"));
			MethodInfo methodInfo4 = AccessTools.Method(typeof(ArrowRain), "UpdateAreaIndicator", (Type[])null, (Type[])null);
			harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, PatchMethod("Postfix_UpdateAreaIndicator"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_log.LogInfo((object)("补丁已挂载:ArrowRain.UpdateAreaIndicator <- Postfix_UpdateAreaIndicator() [target=" + (methodInfo4 != null) + "]"));
		}

		private static HarmonyMethod PatchMethod(string name)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			return new HarmonyMethod(typeof(HuntressArrowRainTweaks).GetMethod(name, BindingFlags.Static | BindingFlags.NonPublic));
		}

		private static void Prefix_DoFireArrowRain()
		{
			if (!_enabled.Value)
			{
				return;
			}
			try
			{
				float projectileOverlapCoefficient = GetProjectileOverlapCoefficient();
				float damageCoefficient = ArrowRain.damageCoefficient;
				if (_vanillaStateCoefficient < 0f)
				{
					_vanillaStateCoefficient = damageCoefficient;
				}
				float value = _damageCoefficientPerTick.Value;
				float num = (ArrowRain.damageCoefficient = value / ((projectileOverlapCoefficient > 0f) ? projectileOverlapCoefficient : 0.5f));
				GameObject projectilePrefab = ArrowRain.projectilePrefab;
				if ((Object)(object)projectilePrefab != (Object)null)
				{
					ProjectileOverlapAttack component = projectilePrefab.GetComponent<ProjectileOverlapAttack>();
					if ((Object)(object)component != (Object)null)
					{
						component.overlapProcCoefficient = _procCoefficient.Value;
					}
				}
				if (!_loggedDamage)
				{
					_loggedDamage = true;
					_log.LogInfo((object)("箭雨伤害:原版每段 " + _vanillaStateCoefficient * projectileOverlapCoefficient + " -> " + value + "(状态系数 " + _vanillaStateCoefficient + " -> " + num + ",射弹重叠系数 " + projectileOverlapCoefficient + ")"));
				}
			}
			catch (Exception ex)
			{
				_log.LogError((object)("箭雨伤害调整异常: " + ex));
			}
		}

		private static float GetProjectileOverlapCoefficient()
		{
			GameObject projectilePrefab = ArrowRain.projectilePrefab;
			if ((Object)(object)projectilePrefab != (Object)null)
			{
				ProjectileOverlapAttack component = projectilePrefab.GetComponent<ProjectileOverlapAttack>();
				if ((Object)(object)component != (Object)null && component.damageCoefficient > 0f)
				{
					return component.damageCoefficient;
				}
			}
			return 0.5f;
		}

		private static void Postfix_ProjectileOverlapAttackStart(ProjectileOverlapAttack __instance)
		{
			if (!_enabled.Value || (Object)(object)__instance == (Object)null || !IsArrowRainProjectile(__instance))
			{
				return;
			}
			try
			{
				__instance.overlapProcCoefficient = _procCoefficient.Value;
				__instance.UpdateAttackValues();
				if (!_loggedProc)
				{
					_loggedProc = true;
					_log.LogInfo((object)("箭雨触发系数:0.2 -> " + _procCoefficient.Value + "(已应用到射弹 " + ((Object)((Component)__instance).gameObject).name + ")"));
				}
			}
			catch (Exception ex)
			{
				_log.LogError((object)("箭雨触发系数调整异常(Start): " + ex));
			}
		}

		private static void Postfix_ProjectileOverlapAttackEnable(ProjectileOverlapAttack __instance)
		{
			if (!_enabled.Value || (Object)(object)__instance == (Object)null || !IsArrowRainProjectile(__instance))
			{
				return;
			}
			try
			{
				__instance.overlapProcCoefficient = _procCoefficient.Value;
				object? value = AttackField.GetValue(__instance);
				OverlapAttack val = (OverlapAttack)((value is OverlapAttack) ? value : null);
				if (val != null)
				{
					float num = 1f;
					object? value2 = ProjectileControllerField.GetValue(__instance);
					ProjectileController val2 = (ProjectileController)((value2 is ProjectileController) ? value2 : null);
					if ((Object)(object)val2 != (Object)null)
					{
						num = val2.procCoefficient;
					}
					val.procCoefficient = _procCoefficient.Value * num;
				}
			}
			catch (Exception ex)
			{
				_log.LogError((object)("箭雨触发系数调整异常(OnEnable): " + ex));
			}
		}

		private static bool IsArrowRainProjectile(ProjectileOverlapAttack attack)
		{
			if ((Object)(object)((Component)attack).gameObject == (Object)null)
			{
				return false;
			}
			string name = ((Object)((Component)attack).gameObject).name;
			if (!string.IsNullOrEmpty(name))
			{
				return name.StartsWith("HuntressArrowRain", StringComparison.Ordinal);
			}
			return false;
		}

		private static void Postfix_UpdateAreaIndicator(ArrowRain __instance)
		{
			//IL_004b: 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_0058: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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_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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: 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)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			if (!_enabled.Value || !_allowEnemyTargeting.Value || __instance == null)
			{
				return;
			}
			try
			{
				object? value = AreaIndicatorField.GetValue(__instance);
				GameObject val = (GameObject)((value is GameObject) ? value : null);
				if ((Object)(object)val == (Object)null || !TryGetAimRay(__instance, out var aimRay))
				{
					return;
				}
				Ray val2 = aimRay;
				LayerIndex val3 = LayerIndex.world;
				RaycastHit val4 = default(RaycastHit);
				bool flag = Physics.Raycast(val2, ref val4, 1000f, LayerMask.op_Implicit(((LayerIndex)(ref val3)).mask), (QueryTriggerInteraction)0);
				val3 = LayerIndex.entityPrecise;
				int num = LayerMask.op_Implicit(((LayerIndex)(ref val3)).mask);
				val3 = LayerIndex.playerBody;
				int num2 = num | LayerMask.op_Implicit(((LayerIndex)(ref val3)).mask);
				val3 = LayerIndex.enemyBody;
				int num3 = num2 | LayerMask.op_Implicit(((LayerIndex)(ref val3)).mask);
				RaycastHit hit = default(RaycastHit);
				bool flag2 = Physics.Raycast(aimRay, ref hit, 1000f, num3, (QueryTriggerInteraction)0);
				if (!flag2 && _enemyAimAssistRadius.Value > 0f)
				{
					flag2 = Physics.SphereCast(aimRay, _enemyAimAssistRadius.Value, ref hit, 1000f, num3, (QueryTriggerInteraction)0);
				}
				if (!flag2 || (flag && ((RaycastHit)(ref val4)).distance <= ((RaycastHit)(ref hit)).distance))
				{
					return;
				}
				CharacterBody val5 = FindTargetBody(hit);
				if ((Object)(object)val5 == (Object)null)
				{
					return;
				}
				CharacterBody val6 = (((Object)(object)((EntityState)__instance).outer != (Object)null) ? ((Component)((EntityState)__instance).outer).GetComponent<CharacterBody>() : null);
				if (!((Object)(object)val6 != (Object)null) || !((Object)(object)val5 == (Object)(object)val6))
				{
					val.transform.position = val5.corePosition;
					val.transform.up = Vector3.up;
					if (!_loggedTargeting)
					{
						_loggedTargeting = true;
						_log.LogInfo((object)("箭雨可对敌人释放:落点已吸附到 " + ((Object)val5).name));
					}
				}
			}
			catch (Exception ex)
			{
				_log.LogError((object)("箭雨瞄敌异常: " + ex));
			}
		}

		private static CharacterBody FindTargetBody(RaycastHit hit)
		{
			if ((Object)(object)((RaycastHit)(ref hit)).collider == (Object)null)
			{
				return null;
			}
			HurtBox component = ((Component)((RaycastHit)(ref hit)).collider).GetComponent<HurtBox>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.healthComponent != (Object)null)
			{
				return component.healthComponent.body;
			}
			CharacterBody componentInParent = ((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<CharacterBody>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				return componentInParent;
			}
			HealthComponent componentInParent2 = ((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<HealthComponent>();
			if (!((Object)(object)componentInParent2 != (Object)null))
			{
				return null;
			}
			return componentInParent2.body;
		}

		private static bool TryGetAimRay(ArrowRain state, out Ray aimRay)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			aimRay = default(Ray);
			try
			{
				if (GetAimRayMethod != null)
				{
					object obj = GetAimRayMethod.Invoke(state, null);
					if (obj is Ray)
					{
						aimRay = (Ray)obj;
						return true;
					}
				}
			}
			catch (Exception ex)
			{
				_log.LogWarning((object)("GetAimRay 反射调用失败,改用 InputBankTest: " + ex.Message));
			}
			if ((Object)(object)((EntityState)state).outer == (Object)null)
			{
				return false;
			}
			InputBankTest component = ((Component)((EntityState)state).outer).GetComponent<InputBankTest>();
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			aimRay = new Ray(component.aimOrigin, component.aimDirection);
			return true;
		}
	}
	internal static class HuntressBlinkTweaks
	{
		private const string HuntressBodyName = "HuntressBody";

		private const string BlinkSkillNameToken = "HUNTRESS_UTILITY_NAME";

		private const string BlinkStateTypeName = "EntityStates.Huntress.BlinkState";

		private static ManualLogSource _log;

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<float> _distanceMultiplier;

		private static ConfigEntry<float> _cooldown;

		private static bool _cooldownPatched;

		private static bool _loggedDistance;

		internal static void Init(ConfigFile config, ManualLogSource log)
		{
			_log = log;
			_enabled = config.Bind<bool>("Blink.闪现", "Enabled", true, "是否启用女猎人 Shift「闪现」的调整(位移缩短 + 冷却降低)。");
			_distanceMultiplier = config.Bind<float>("Blink.闪现", "DistanceMultiplier", 0.67f, "闪现位移距离的倍率。0.67 = 缩短 33%;1 = 原版。");
			_cooldown = config.Bind<float>("Blink.闪现", "Cooldown", 4f, "闪现的冷却时间(秒)。原版 7 秒;设为 7 即恢复原版。");
		}

		internal static void Patch(Harmony harmony)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			MethodInfo method = typeof(BlinkState).GetMethod("OnEnter", BindingFlags.Instance | BindingFlags.Public);
			MethodInfo method2 = typeof(HuntressBlinkTweaks).GetMethod("OnEnterPostfix", BindingFlags.Static | BindingFlags.NonPublic);
			harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_log.LogInfo((object)("补丁已挂载 EntityStates.Huntress.BlinkState.OnEnter [target=" + (method != null) + "]"));
		}

		private static void OnEnterPostfix(BlinkState __instance)
		{
			if (!_enabled.Value || __instance == null || ((object)__instance).GetType() != typeof(BlinkState))
			{
				return;
			}
			float value = _distanceMultiplier.Value;
			if (!(Math.Abs(value - 1f) < 0.0001f))
			{
				float speedCoefficient = __instance.speedCoefficient;
				__instance.speedCoefficient = speedCoefficient * value;
				if (!_loggedDistance)
				{
					_loggedDistance = true;
					_log.LogInfo((object)("闪现位移:速度系数 " + speedCoefficient + " -> " + __instance.speedCoefficient + "(距离 x" + value + ",持续 " + __instance.duration + "s)"));
				}
			}
		}

		internal static void TryPatchCooldown()
		{
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			if (_cooldownPatched || !_enabled.Value)
			{
				return;
			}
			try
			{
				if (!((ResourceAvailability)(ref BodyCatalog.availability)).available)
				{
					return;
				}
				GameObject val = BodyCatalog.FindBodyPrefab("HuntressBody");
				if ((Object)(object)val == (Object)null)
				{
					_log.LogWarning((object)"BodyCatalog 里找不到 HuntressBody,闪现冷却未修改。");
					_cooldownPatched = true;
					return;
				}
				SkillLocator component = val.GetComponent<SkillLocator>();
				if ((Object)(object)component == (Object)null || (Object)(object)component.utility == (Object)null)
				{
					_log.LogError((object)"HuntressBody 上取不到 utility 技能槽,闪现冷却未修改。");
					_cooldownPatched = true;
					return;
				}
				SkillFamily skillFamily = component.utility.skillFamily;
				if ((Object)(object)skillFamily == (Object)null || skillFamily.variants == null)
				{
					_log.LogError((object)"女猎人 utility 技能族为空,闪现冷却未修改。");
					_cooldownPatched = true;
					return;
				}
				bool flag = false;
				Variant[] variants = skillFamily.variants;
				for (int i = 0; i < variants.Length; i++)
				{
					SkillDef skillDef = variants[i].skillDef;
					if (!((Object)(object)skillDef == (Object)null) && IsBlinkSkillDef(skillDef))
					{
						float value = _cooldown.Value;
						float baseRechargeInterval = skillDef.baseRechargeInterval;
						skillDef.baseRechargeInterval = value;
						flag = true;
						_log.LogInfo((object)("闪现冷却:" + baseRechargeInterval + "s -> " + value + "s(SkillDef " + skillDef.skillNameToken + ")"));
					}
				}
				if (!flag)
				{
					_log.LogWarning((object)"女猎人 utility 技能族里没匹配到闪现 SkillDef,冷却未修改。");
				}
				else
				{
					RefreshLiveBodies();
				}
				_cooldownPatched = true;
			}
			catch (Exception ex)
			{
				_cooldownPatched = true;
				_log.LogError((object)("修改闪现冷却异常: " + ex));
			}
		}

		private static bool IsBlinkSkillDef(SkillDef def)
		{
			try
			{
				if (((SerializableEntityStateType)(ref def.activationState)).stateType == typeof(BlinkState))
				{
					return true;
				}
				string typeName = ((SerializableEntityStateType)(ref def.activationState)).typeName;
				if (!string.IsNullOrEmpty(typeName) && typeName == "EntityStates.Huntress.BlinkState")
				{
					return true;
				}
			}
			catch (Exception)
			{
			}
			if (!string.IsNullOrEmpty(def.skillNameToken))
			{
				return def.skillNameToken == "HUNTRESS_UTILITY_NAME";
			}
			return false;
		}

		private static void RefreshLiveBodies()
		{
			foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList)
			{
				if (HuntressSeasonedPassive.IsHuntress(readOnlyInstances))
				{
					SkillLocator skillLocator = readOnlyInstances.skillLocator;
					if (!((Object)(object)skillLocator == (Object)null) && !((Object)(object)skillLocator.utility == (Object)null))
					{
						skillLocator.utility.RecalculateValues();
					}
				}
			}
		}
	}
	internal static class HuntressSeasonedPassive
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static StatHookEventHandler <0>__OnGetStatCoefficients;
		}

		internal const string PassiveNameToken = "HUNTRESS_PASSIVE_NAME";

		internal const string PassiveDescriptionToken = "HUNTRESS_PASSIVE_DESCRIPTION";

		private const string HuntressBodyName = "HuntressBody";

		private static ManualLogSource _log;

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<float> _percentPerLevel;

		private static Sprite _icon;

		private static bool _prefabPatched;

		private static readonly ConditionalWeakTable<CharacterBody, StrongBox<float>> _lastLevels = new ConditionalWeakTable<CharacterBody, StrongBox<float>>();

		private static bool _loggedRecalcOnce;

		internal static void Init(ConfigFile config, ManualLogSource log)
		{
			_log = log;
			_enabled = config.Bind<bool>("Passive.老练", "Enabled", true, "是否启用女猎人被动「老练」(攻击速度与暴击几率随玩家等级提升)。");
			_percentPerLevel = config.Bind<float>("Passive.老练", "PercentPerLevel", 1f, "每一级玩家等级提供的攻击速度与暴击几率(%)。1 = 玩家等级 10 时 +10% 攻速和 +10% 暴击几率。");
		}

		internal static void ApplyLanguage()
		{
			LanguageAPI.Add("HUNTRESS_PASSIVE_NAME", "Seasoned", "en");
			LanguageAPI.Add("HUNTRESS_PASSIVE_DESCRIPTION", "Gain attack speed % and critical chance % equal to your level.", "en");
			LanguageAPI.Add("HUNTRESS_PASSIVE_NAME", "老练", "zh-CN");
			LanguageAPI.Add("HUNTRESS_PASSIVE_DESCRIPTION", "获得相当于你等级的攻击速度%与暴击几率%。", "zh-CN");
			_log.LogInfo((object)"被动文本已注册: HUNTRESS_PASSIVE_NAME / HUNTRESS_PASSIVE_DESCRIPTION");
		}

		internal static void LoadIcon()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string text = Path.Combine(Path.GetDirectoryName(typeof(HuntressSeasonedPassive).Assembly.Location), "passiveIcon.png");
				if (!File.Exists(text))
				{
					_log.LogWarning((object)("找不到被动图标文件: " + text));
					return;
				}
				byte[] array = File.ReadAllBytes(text);
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
				if (!ImageConversion.LoadImage(val, array))
				{
					_log.LogWarning((object)("被动图标解码失败: " + text));
					return;
				}
				((Texture)val).wrapMode = (TextureWrapMode)1;
				_icon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
				((Object)_icon).name = "texSparkleHuntressSeasonedIcon";
				_log.LogInfo((object)("被动图标已加载: " + text + " (" + ((Texture)val).width + "x" + ((Texture)val).height + ")"));
			}
			catch (Exception ex)
			{
				_log.LogError((object)("加载被动图标异常: " + ex));
			}
		}

		internal static void TryPatchPrefab()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			if (_prefabPatched)
			{
				return;
			}
			try
			{
				if (!((ResourceAvailability)(ref BodyCatalog.availability)).available)
				{
					return;
				}
				GameObject val = BodyCatalog.FindBodyPrefab("HuntressBody");
				if ((Object)(object)val == (Object)null)
				{
					_log.LogWarning((object)"BodyCatalog 里找不到 HuntressBody,被动槽位未挂载。");
					_prefabPatched = true;
					return;
				}
				SkillLocator component = val.GetComponent<SkillLocator>();
				if ((Object)(object)component == (Object)null)
				{
					_log.LogError((object)"HuntressBody 上没有 SkillLocator,被动槽位未挂载。");
					_prefabPatched = true;
					return;
				}
				PassiveSkill passiveSkill = component.passiveSkill;
				passiveSkill.enabled = true;
				passiveSkill.skillNameToken = "HUNTRESS_PASSIVE_NAME";
				passiveSkill.skillDescriptionToken = "HUNTRESS_PASSIVE_DESCRIPTION";
				passiveSkill.keywordToken = string.Empty;
				passiveSkill.icon = _icon;
				component.passiveSkill = passiveSkill;
				_prefabPatched = true;
				_log.LogInfo((object)("已为 HuntressBody 启用被动「老练」 icon=" + ((Object)(object)_icon != (Object)null)));
			}
			catch (Exception ex)
			{
				_prefabPatched = true;
				_log.LogError((object)("挂载被动槽位异常: " + ex));
			}
		}

		internal static void RegisterStatHook()
		{
			//IL_0010: 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_001b: Expected O, but got Unknown
			object obj = <>O.<0>__OnGetStatCoefficients;
			if (obj == null)
			{
				StatHookEventHandler val = OnGetStatCoefficients;
				<>O.<0>__OnGetStatCoefficients = val;
				obj = (object)val;
			}
			RecalculateStatsAPI.GetStatCoefficients += (StatHookEventHandler)obj;
			_log.LogInfo((object)"RecalculateStatsAPI.GetStatCoefficients 钩子已注册。");
		}

		private static void OnGetStatCoefficients(CharacterBody body, StatHookEventArgs args)
		{
			if (_enabled.Value && !((Object)(object)body == (Object)null) && IsHuntress(body))
			{
				float level = body.level;
				if (!(level <= 0f))
				{
					float num = level * _percentPerLevel.Value;
					args.attackSpeedMultAdd += num * 0.01f;
					args.critAdd += num;
				}
			}
		}

		internal static void RefreshOnPlayerLevelChange()
		{
			if (CharacterBody.readOnlyInstancesList.Count == 0)
			{
				return;
			}
			int num = 0;
			float num2 = 0f;
			foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList)
			{
				if (IsHuntress(readOnlyInstances))
				{
					StrongBox<float> orCreateValue = _lastLevels.GetOrCreateValue(readOnlyInstances);
					float level = readOnlyInstances.level;
					num2 = level;
					if (!(Math.Abs(level - orCreateValue.Value) < 0.001f))
					{
						orCreateValue.Value = level;
						readOnlyInstances.RecalculateStats();
						num++;
					}
				}
			}
			if (!_loggedRecalcOnce && num > 0)
			{
				_loggedRecalcOnce = true;
				_log.LogInfo((object)("玩家等级 " + num2 + " -> 女猎人攻速/暴击加成已生效 (重算了 " + num + " 个女猎人)。"));
			}
		}

		internal static bool IsHuntress(CharacterBody body)
		{
			if ((Object)(object)body == (Object)null)
			{
				return false;
			}
			string name = ((Object)body).name;
			if (!string.IsNullOrEmpty(name))
			{
				return name.StartsWith("HuntressBody", StringComparison.Ordinal);
			}
			return false;
		}
	}
	internal static class HuntressSkillText
	{
		internal const string PrimaryNameToken = "HUNTRESS_PRIMARY_NAME";

		internal const string PrimaryDescriptionToken = "HUNTRESS_PRIMARY_DESCRIPTION";

		internal const string PrimaryAltNameToken = "HUNTRESS_PRIMARY_ALT_NAME";

		internal const string PrimaryAltDescriptionToken = "HUNTRESS_PRIMARY_ALT_DESCRIPTION";

		internal const string SpecialNameToken = "HUNTRESS_SPECIAL_NAME";

		internal const string SpecialDescriptionToken = "HUNTRESS_SPECIAL_DESCRIPTION";

		internal static void Apply(ManualLogSource log)
		{
			LanguageAPI.Add("HUNTRESS_PRIMARY_NAME", "扫射", "zh-CN");
			LanguageAPI.Add("HUNTRESS_PRIMARY_DESCRIPTION", "<style=cIsUtility>灵巧</style>。射出<style=cIsDamage>1</style>发能够造成<style=cIsDamage>150%伤害</style>的跟踪箭。<style=cIsUtility>从攻击速度获得更多收益。</style>", "zh-CN");
			LanguageAPI.Add("HUNTRESS_PRIMARY_NAME", "Strafe", "en");
			LanguageAPI.Add("HUNTRESS_PRIMARY_DESCRIPTION", "<style=cIsUtility>Agile</style>. Fire <style=cIsDamage>1</style> seeking arrow for <style=cIsDamage>150% damage</style>. <style=cIsUtility>Benefits more from attack speed.</style>", "en");
			LanguageAPI.Add("HUNTRESS_PRIMARY_ALT_NAME", "疾风", "zh-CN");
			LanguageAPI.Add("HUNTRESS_PRIMARY_ALT_DESCRIPTION", "<style=cIsUtility>灵巧</style>。连续射出<style=cIsDamage>3</style>发能够造成<style=cIsDamage>100%伤害</style>的跟踪箭。倘若暴击则改为射出<style=cIsDamage>6</style>发。", "zh-CN");
			LanguageAPI.Add("HUNTRESS_PRIMARY_ALT_NAME", "Flurry", "en");
			LanguageAPI.Add("HUNTRESS_PRIMARY_ALT_DESCRIPTION", "<style=cIsUtility>Agile</style>. Fire <style=cIsDamage>3</style> seeking arrows for <style=cIsDamage>100% damage</style> each. Fires <style=cIsDamage>6</style> on a critical strike.", "en");
			LanguageAPI.Add("HUNTRESS_SPECIAL_NAME", "箭雨", "zh-CN");
			LanguageAPI.Add("HUNTRESS_SPECIAL_DESCRIPTION", "<style=cIsUtility>传送</style>至空中,向目标区域射下箭雨,使区域内所有敌人<style=cIsUtility>减速</style>,并持续造成<style=cIsDamage>150%的伤害</style>。", "zh-CN");
			LanguageAPI.Add("HUNTRESS_SPECIAL_NAME", "Arrow Rain", "en");
			LanguageAPI.Add("HUNTRESS_SPECIAL_DESCRIPTION", "<style=cIsUtility>Teleport</style> into the air, raining arrows down on a target area, <style=cIsUtility>slowing</style> all enemies and dealing <style=cIsDamage>150% damage</style> continuously.", "en");
			log.LogInfo((object)"技能文案已覆盖:扫射 / 疾风 / 箭雨。");
		}
	}
	internal static class HuntressStrafeAttackSpeed
	{
		private static ManualLogSource _log;

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<float> _multiplier;

		private static bool _loggedOnce;

		internal static void Init(ConfigFile config, ManualLogSource log)
		{
			_log = log;
			_enabled = config.Bind<bool>("Strafe.扫射", "Enabled", true, "是否让「扫射」(M1) 的攻击速度获得额外收益。");
			_multiplier = config.Bind<float>("Strafe.扫射", "AttackSpeedMultiplier", 1.5f, "攻速收益倍率。1.5 = 获得 10% 攻击速度时,射击频率相当于原版获得 15% 攻击速度;1 = 原版。");
		}

		internal static void Patch(Harmony harmony)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(FireSeekingArrow), "OnEnter", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					_log.LogError((object)"找不到 FireSeekingArrow.OnEnter,扫射攻速补丁未挂载。");
					return;
				}
				MethodInfo methodInfo2 = AccessTools.Method(typeof(HuntressStrafeAttackSpeed), "OnEnterTranspiler", (Type[])null, (Type[])null);
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null);
				_log.LogInfo((object)"补丁已挂载:FireSeekingArrow.OnEnter <- HuntressStrafeAttackSpeed.OnEnterTranspiler()");
			}
			catch (Exception ex)
			{
				_log.LogError((object)("扫射攻速补丁挂载失败: " + ex));
			}
		}

		private static IEnumerable<CodeInstruction> OnEnterTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			MethodInfo methodInfo = AccessTools.Method(typeof(HuntressStrafeAttackSpeed), "ScaleAttackSpeed", (Type[])null, (Type[])null);
			int num = 0;
			for (int i = 0; i < list.Count; i++)
			{
				CodeInstruction val = list[i];
				if (!(val.opcode != OpCodes.Ldfld))
				{
					FieldInfo fieldInfo = val.operand as FieldInfo;
					if (!(fieldInfo == null) && !(fieldInfo.Name != "attackSpeedStat") && i + 1 < list.Count && !(list[i + 1].opcode != OpCodes.Div))
					{
						list.Insert(i + 1, new CodeInstruction(OpCodes.Ldarg_0, (object)null));
						list.Insert(i + 2, new CodeInstruction(OpCodes.Call, (object)methodInfo));
						num++;
						i += 2;
					}
				}
			}
			_log.LogInfo((object)("扫射攻速 IL 改写:命中 " + num + " 处 attackSpeedStat 除法(预期 2 处:状态时长 / 填充间隔)。"));
			return list;
		}

		private static float ScaleAttackSpeed(float attackSpeed, object state)
		{
			if (!_enabled.Value || state == null)
			{
				return attackSpeed;
			}
			if (state.GetType() != typeof(FireSeekingArrow))
			{
				return attackSpeed;
			}
			float value = _multiplier.Value;
			if (value <= 0f)
			{
				return attackSpeed;
			}
			float num = 1f + value * (attackSpeed - 1f);
			if (num <= 0.05f)
			{
				return attackSpeed;
			}
			if (!_loggedOnce)
			{
				_loggedOnce = true;
				_log.LogInfo((object)("「扫射」攻速收益已生效:攻击速度 " + attackSpeed.ToString("0.00") + " → 按 " + num.ToString("0.00") + " 计算(收益 x" + value.ToString("0.##") + ")。"));
			}
			return num;
		}
	}
	[BepInPlugin("com.sparkletwilight.sparklehuntresstweaks", "SparkleHuntressTweaks", "1.6.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class SparkleHuntressTweaksPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.sparkletwilight.sparklehuntresstweaks";

		public const string PluginName = "SparkleHuntressTweaks";

		public const string PluginVersion = "1.6.0";

		internal ManualLogSource Logger;

		public void Awake()
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_0085: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			HuntressSkillText.Apply(Logger);
			HuntressSeasonedPassive.Init(((BaseUnityPlugin)this).Config, Logger);
			HuntressSeasonedPassive.ApplyLanguage();
			HuntressSeasonedPassive.LoadIcon();
			HuntressSeasonedPassive.RegisterStatHook();
			HuntressStrafeAttackSpeed.Init(((BaseUnityPlugin)this).Config, Logger);
			HuntressArrowRainTweaks.Init(((BaseUnityPlugin)this).Config, Logger);
			HuntressBlinkTweaks.Init(((BaseUnityPlugin)this).Config, Logger);
			Harmony val = new Harmony("com.sparkletwilight.sparklehuntresstweaks");
			HuntressStrafeAttackSpeed.Patch(val);
			HuntressArrowRainTweaks.Patch(val);
			HuntressBlinkTweaks.Patch(val);
			Logger.LogInfo((object)"SparkleHuntressTweaks v1.6.0 已加载。被动「老练」+ M1「扫射」攻速收益翻倍 + R「箭雨」强化 + Shift「闪现」调整。");
		}

		public void Update()
		{
			HuntressSeasonedPassive.TryPatchPrefab();
			HuntressBlinkTweaks.TryPatchCooldown();
			HuntressSeasonedPassive.RefreshOnPlayerLevelChange();
		}
	}
}