Decompiled source of MercExtraEffects v1.3.3

plugins/MercExtraEffects/MercExtraEffects.dll

Decompiled 3 days ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using EntityStates;
using EntityStates.Merc;
using EntityStates.Merc.Weapon;
using Microsoft.CodeAnalysis;
using On.EntityStates.Merc;
using On.EntityStates.Merc.Weapon;
using RiskOfOptions;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using RoR2.Skills;
using UnityEngine;
using UnityEngine.AddressableAssets;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MercExtraEffects")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+b7b2c9c3b69d1c7d9c8bb5e35fb3fb1d84483aaf")]
[assembly: AssemblyProduct("MercExtraEffects")]
[assembly: AssemblyTitle("MercExtraEffects")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 ExamplePlugin
{
	public sealed class ConfigValue<T>
	{
		public ConfigEntry<T> Entry;

		public readonly T DefaultValue;

		public readonly T MinValue;

		public readonly T MaxValue;

		public readonly T IncrementValue;

		public T Value => Entry.Value;

		public ConfigValue(T defaultValue)
		{
			DefaultValue = defaultValue;
			MinValue = default(T);
			MaxValue = default(T);
			IncrementValue = default(T);
		}

		public ConfigValue(T defaultValue, T minValue, T maxValue, T incrementValue)
		{
			DefaultValue = defaultValue;
			MinValue = minValue;
			MaxValue = maxValue;
			IncrementValue = incrementValue;
		}

		public string DefaultAsString()
		{
			return $"Default: {DefaultValue}";
		}
	}
	[BepInPlugin("com.fafnir62.mercenary_extra_effects", "Mercenary Extra Effects", "1.3.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class MercExtraEffectsPlugin : BaseUnityPlugin
	{
		private class MercTracker : MonoBehaviour
		{
			public bool uppercutActive;

			public bool whirlwindActive;
		}

		public const string PluginGUID = "com.fafnir62.mercenary_extra_effects";

		public const string PluginName = "Mercenary Extra Effects";

		public const string PluginVersion = "1.3.2";

		private static BodyIndex mercBodyIndex = (BodyIndex)(-1);

		private static ConfigValue<float> cfgSecondaryLifestealPercent = new ConfigValue<float>(15f, 0f, 200f, 1f);

		private static ConfigValue<float> cfgEvisBarrierPercent = new ConfigValue<float>(15f, 0f, 40f, 1f);

		private static ConfigValue<float> cfgFocusedAssaultDamagePercent = new ConfigValue<float>(700f, 350f, 1400f, 10f);

		private static ConfigValue<float> cfgFocusedAssaultCooldownSeconds = new ConfigValue<float>(8f, 4f, 16f, 1f);

		private static ConfigValue<float> cfgEvisDamagePercent = new ConfigValue<float>(110f, 50f, 220f, 10f);

		private static ConfigValue<float> cfgEvisCooldownSeconds = new ConfigValue<float>(6f, 3f, 16f, 1f);

		private static ConfigValue<float> cfgBlindingAssaultDamagePercent = new ConfigValue<float>(300f, 150f, 600f, 10f);

		private static ConfigValue<float> cfgBlindingAssaultCooldownSeconds = new ConfigValue<float>(5f, 3f, 16f, 1f);

		private const float UtilityCooldownSeconds = 6f;

		private const string FocusedAssaultSkillDefPath = "RoR2/Base/Merc/MercBodyFocusedAssault.asset";

		private const string BlindingAssaultSkillDefPath = "RoR2/Base/Merc/MercBodyAssaulter.asset";

		private static readonly string[] EvisSkillDefPaths = new string[3] { "RoR2/Base/Merc/MercBodyEviscerate.asset", "RoR2/Base/Merc/MercBodyEvis.asset", "RoR2/Base/Merc/MercBodySpecialEviscerate.asset" };

		public static ConfigValue<bool> M1AttackSpeedFix { get; set; } = new ConfigValue<bool>(defaultValue: true);


		public static ConfigValue<bool> M2AttackSpeedIgnore { get; set; } = new ConfigValue<bool>(defaultValue: true);


		public static ConfigValue<bool> EvisIgnoreAllies { get; set; } = new ConfigValue<bool>(defaultValue: true);


		private void Awake()
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[MercExtraEffects] Awake");
			InitConfig();
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(OnGameLoaded));
		}

		private void OnGameLoaded()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Expected O, but got Unknown
			mercBodyIndex = BodyCatalog.FindBodyIndex("MercBody");
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[MercExtraEffects] MercBodyIndex=" + ((object)(BodyIndex)(ref mercBodyIndex)).ToString()));
			CharacterBody.onBodyStartGlobal += OnBodyStart;
			Uppercut.OnEnter += new hook_OnEnter(Uppercut_OnEnter);
			Uppercut.OnExit += new hook_OnExit(Uppercut_OnExit);
			WhirlwindBase.OnEnter += new hook_OnEnter(WhirlwindBase_OnEnter);
			WhirlwindBase.OnExit += new hook_OnExit(WhirlwindBase_OnExit);
			EvisDash.FixedUpdate += new hook_FixedUpdate(Evis_FixedUpdate);
			GroundLight2.OnEnter += new hook_OnEnter(M1_onEnter);
			Uppercut.PlayAnim += new hook_PlayAnim(Uppercut_PlayAnim);
			WhirlwindAir.PlayAnim += new hook_PlayAnim(WhirlwindAir_PlayAnim);
			WhirlwindGround.PlayAnim += new hook_PlayAnim(WhirlwindGround_PlayAnim);
			Evis.OnExit += new hook_OnExit(Evis_OnExit);
			FocusedAssaultDash.AuthorityModifyOverlapAttack += new hook_AuthorityModifyOverlapAttack(FocusedAssaultDash_AuthorityModifyOverlapAttack);
			Assaulter2.AuthorityModifyOverlapAttack += new hook_AuthorityModifyOverlapAttack(Assaulter2_AuthorityModifyOverlapAttack);
			GlobalEventManager.onServerDamageDealt += OnServerDamageDealt;
			ApplySkillTuning();
		}

		private static Sprite LoadEmbeddedSprite(string resourceName)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			using Stream stream = typeof(MercExtraEffectsPlugin).Assembly.GetManifestResourceStream(resourceName);
			if (stream == null)
			{
				Debug.LogError((object)("Failed to load resource: " + resourceName));
				return null;
			}
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			Texture2D val = new Texture2D(2, 2);
			ImageConversion.LoadImage(val, array);
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
		}

		private void InitConfig()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Expected O, but got Unknown
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Expected O, but got Unknown
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Expected O, but got Unknown
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Expected O, but got Unknown
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Expected O, but got Unknown
			//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b2: Expected O, but got Unknown
			//IL_0407: Unknown result type (might be due to invalid IL or missing references)
			//IL_0411: Expected O, but got Unknown
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Expected O, but got Unknown
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0439: Expected O, but got Unknown
			cfgSecondaryLifestealPercent.Entry = ((BaseUnityPlugin)this).Config.Bind<float>("Skills effects", "Secondary Lifesteal (%)", cfgSecondaryLifestealPercent.DefaultValue, new ConfigDescription("How much of damage dealt is healed while Merc M2 (Uppercut/Whirlwind) is active. " + cfgSecondaryLifestealPercent.DefaultAsString(), (AcceptableValueBase)(object)new AcceptableValueRange<float>(cfgSecondaryLifestealPercent.MinValue, cfgSecondaryLifestealPercent.MaxValue), Array.Empty<object>()));
			cfgEvisBarrierPercent.Entry = ((BaseUnityPlugin)this).Config.Bind<float>("Skills effects", "Evis Barrier HP (%)", cfgEvisBarrierPercent.DefaultValue, new ConfigDescription("Barrier gained after Eviscerate as % of max mercenary health. " + cfgEvisBarrierPercent.DefaultAsString(), (AcceptableValueBase)(object)new AcceptableValueRange<float>(cfgEvisBarrierPercent.MinValue, cfgEvisBarrierPercent.MaxValue), Array.Empty<object>()));
			M1AttackSpeedFix.Entry = ((BaseUnityPlugin)this).Config.Bind<bool>("Skills effects", "M1 attack speed fix", M1AttackSpeedFix.DefaultValue, "When enabled, gives Merc's 3rd m1 a fixed duration, allowing for consistent m1 extends. " + M1AttackSpeedFix.DefaultAsString());
			M2AttackSpeedIgnore.Entry = ((BaseUnityPlugin)this).Config.Bind<bool>("Skills effects", "M2 Attack Speed Ignore", M2AttackSpeedIgnore.DefaultValue, "When enabled, Whirlwind and Rising Thunder ignore attack speed, making their utility consistent throughout the run. " + M2AttackSpeedIgnore.DefaultAsString());
			EvisIgnoreAllies.Entry = ((BaseUnityPlugin)this).Config.Bind<bool>("Skills effects", "Eviscerate ignore allies", EvisIgnoreAllies.DefaultValue, "When enabled, Eviscerate will not target drones and other allies. " + EvisIgnoreAllies.DefaultAsString());
			cfgFocusedAssaultDamagePercent.Entry = ((BaseUnityPlugin)this).Config.Bind<float>("Damage and cooldown", "Focused Assault Damage (%)", cfgFocusedAssaultDamagePercent.DefaultValue, new ConfigDescription("Focused Assault damage per dash hit (vanilla 700%). " + cfgFocusedAssaultDamagePercent.DefaultAsString(), (AcceptableValueBase)(object)new AcceptableValueRange<float>(cfgFocusedAssaultDamagePercent.MinValue, cfgFocusedAssaultDamagePercent.MaxValue), Array.Empty<object>()));
			cfgFocusedAssaultCooldownSeconds.Entry = ((BaseUnityPlugin)this).Config.Bind<float>("Damage and cooldown", "Focused Assault Cooldown (s)", cfgFocusedAssaultCooldownSeconds.DefaultValue, new ConfigDescription("Focused Assault base cooldown in seconds (vanilla 8). " + cfgFocusedAssaultCooldownSeconds.DefaultAsString(), (AcceptableValueBase)(object)new AcceptableValueRange<float>(cfgFocusedAssaultCooldownSeconds.MinValue, cfgFocusedAssaultCooldownSeconds.MaxValue), Array.Empty<object>()));
			cfgEvisDamagePercent.Entry = ((BaseUnityPlugin)this).Config.Bind<float>("Damage and cooldown", "Eviscerate Damage (%)", cfgEvisDamagePercent.DefaultValue, new ConfigDescription("Eviscerate damage per hit (vanilla 110%). Example: 110 = 110%. " + cfgEvisDamagePercent.DefaultAsString(), (AcceptableValueBase)(object)new AcceptableValueRange<float>(cfgEvisDamagePercent.MinValue, cfgEvisDamagePercent.MaxValue), Array.Empty<object>()));
			cfgEvisCooldownSeconds.Entry = ((BaseUnityPlugin)this).Config.Bind<float>("Damage and cooldown", "Eviscerate Cooldown (s)", cfgEvisCooldownSeconds.DefaultValue, new ConfigDescription("Eviscerate base cooldown in seconds (vanilla 6). " + cfgEvisCooldownSeconds.DefaultAsString(), (AcceptableValueBase)(object)new AcceptableValueRange<float>(cfgEvisCooldownSeconds.MinValue, cfgEvisCooldownSeconds.MaxValue), Array.Empty<object>()));
			cfgBlindingAssaultDamagePercent.Entry = ((BaseUnityPlugin)this).Config.Bind<float>("Damage and cooldown", "Blinding Assault Damage (%)", cfgBlindingAssaultDamagePercent.DefaultValue, new ConfigDescription("Blinding Assault damage per dash hit (vanilla 300%). Example: 300 = 300%. " + cfgBlindingAssaultDamagePercent.DefaultAsString(), (AcceptableValueBase)(object)new AcceptableValueRange<float>(cfgBlindingAssaultDamagePercent.MinValue, cfgBlindingAssaultDamagePercent.MaxValue), Array.Empty<object>()));
			cfgBlindingAssaultCooldownSeconds.Entry = ((BaseUnityPlugin)this).Config.Bind<float>("Damage and cooldown", "Blinding Assault Cooldown (s)", cfgBlindingAssaultCooldownSeconds.DefaultValue, new ConfigDescription("Blinding Assault base cooldown in seconds (vanilla 8). " + cfgBlindingAssaultCooldownSeconds.DefaultAsString(), (AcceptableValueBase)(object)new AcceptableValueRange<float>(cfgBlindingAssaultCooldownSeconds.MinValue, cfgBlindingAssaultCooldownSeconds.MaxValue), Array.Empty<object>()));
			((BaseUnityPlugin)this).Config.SettingChanged += OnAnyConfigSettingChanged;
			try
			{
				ModSettingsManager.SetModDescription("Mercenary skill effects.\n\nThis mod is configured via the BepInEx config file and RiskUI.");
				ModSettingsManager.SetModIcon(LoadEmbeddedSprite("ExamplePlugin.Assets.MercExtraEffectIcon128.png"));
				AddConfigSlider(cfgSecondaryLifestealPercent);
				AddConfigSlider(cfgEvisBarrierPercent);
				ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(M1AttackSpeedFix.Entry));
				ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(M2AttackSpeedIgnore.Entry));
				ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(EvisIgnoreAllies.Entry));
				AddConfigSlider(cfgFocusedAssaultDamagePercent);
				AddConfigSlider(cfgFocusedAssaultCooldownSeconds);
				AddConfigSlider(cfgEvisDamagePercent);
				AddConfigSlider(cfgEvisCooldownSeconds);
				AddConfigSlider(cfgBlindingAssaultDamagePercent);
				AddConfigSlider(cfgBlindingAssaultCooldownSeconds);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[MercExtraEffects] RiskOfOptions UI not available: " + ex.Message));
			}
		}

		private void AddConfigSlider(ConfigValue<float> entry)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			ModSettingsManager.AddOption((BaseOption)new StepSliderOption(entry.Entry, new StepSliderConfig
			{
				min = entry.MinValue,
				max = entry.MaxValue,
				increment = entry.IncrementValue
			}));
		}

		private void OnAnyConfigSettingChanged(object sender, SettingChangedEventArgs e)
		{
			if (e == null || e.ChangedSetting == null)
			{
				return;
			}
			try
			{
				if (e.ChangedSetting == cfgSecondaryLifestealPercent.Entry || e.ChangedSetting == cfgEvisBarrierPercent.Entry || e.ChangedSetting == cfgFocusedAssaultDamagePercent.Entry || e.ChangedSetting == cfgFocusedAssaultCooldownSeconds.Entry || e.ChangedSetting == cfgEvisDamagePercent.Entry || e.ChangedSetting == cfgEvisCooldownSeconds.Entry || e.ChangedSetting == cfgBlindingAssaultDamagePercent.Entry || e.ChangedSetting == cfgBlindingAssaultCooldownSeconds.Entry || e.ChangedSetting == M1AttackSpeedFix.Entry || e.ChangedSetting == M2AttackSpeedIgnore.Entry || e.ChangedSetting == EvisIgnoreAllies.Entry)
				{
					ApplySkillTuning();
					((BaseUnityPlugin)this).Logger.LogInfo((object)"[MercExtraEffects] In-game config change detected");
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[MercExtraEffects] Failed config update: " + ex));
			}
		}

		private static bool IsMerc(CharacterBody body)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)body != (Object)null)
			{
				return body.bodyIndex == mercBodyIndex;
			}
			return false;
		}

		private void OnBodyStart(CharacterBody body)
		{
			if (!((Object)(object)body == (Object)null) && (Object)(object)((Component)body).GetComponent<MercTracker>() == (Object)null)
			{
				((Component)body).gameObject.AddComponent<MercTracker>();
			}
		}

		private static MercTracker GetTracker(CharacterBody body)
		{
			if (!((Object)(object)body != (Object)null))
			{
				return null;
			}
			return ((Component)body).GetComponent<MercTracker>();
		}

		private void Uppercut_OnEnter(orig_OnEnter orig, Uppercut self)
		{
			orig.Invoke(self);
			CharacterBody characterBody = ((EntityState)self).characterBody;
			if (IsMerc(characterBody))
			{
				MercTracker tracker = GetTracker(characterBody);
				if ((Object)(object)tracker != (Object)null)
				{
					tracker.uppercutActive = true;
				}
			}
		}

		private void Uppercut_OnExit(orig_OnExit orig, Uppercut self)
		{
			CharacterBody characterBody = ((EntityState)self).characterBody;
			if (IsMerc(characterBody))
			{
				MercTracker tracker = GetTracker(characterBody);
				if ((Object)(object)tracker != (Object)null)
				{
					tracker.uppercutActive = false;
				}
			}
			orig.Invoke(self);
		}

		private void WhirlwindBase_OnEnter(orig_OnEnter orig, WhirlwindBase self)
		{
			orig.Invoke(self);
			CharacterBody characterBody = ((EntityState)self).characterBody;
			if (IsMerc(characterBody))
			{
				MercTracker tracker = GetTracker(characterBody);
				if ((Object)(object)tracker != (Object)null)
				{
					tracker.whirlwindActive = true;
				}
			}
		}

		private void WhirlwindBase_OnExit(orig_OnExit orig, WhirlwindBase self)
		{
			CharacterBody characterBody = ((EntityState)self).characterBody;
			if (IsMerc(characterBody))
			{
				MercTracker tracker = GetTracker(characterBody);
				if ((Object)(object)tracker != (Object)null)
				{
					tracker.whirlwindActive = false;
				}
			}
			orig.Invoke(self);
		}

		private void Evis_FixedUpdate(orig_FixedUpdate orig, EvisDash self)
		{
			//IL_004f: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Expected O, but got Unknown
			if (!EvisIgnoreAllies.Value)
			{
				orig.Invoke(self);
				return;
			}
			self.stopwatch += Time.fixedDeltaTime;
			if (self.stopwatch > EvisDash.dashPrepDuration && !self.isDashing)
			{
				self.isDashing = true;
				self.dashVector = ((EntityState)self).inputBank.aimDirection;
				self.CreateBlinkEffect(Util.GetCorePosition(((EntityState)self).gameObject));
				((EntityState)self).PlayCrossfade("FullBody, Override", "EvisLoop", 0.1f);
				if (Object.op_Implicit((Object)(object)self.modelTransform))
				{
					TemporaryOverlay obj = ((Component)self.modelTransform).gameObject.AddComponent<TemporaryOverlay>();
					obj.duration = 0.6f;
					obj.animateShaderAlpha = true;
					obj.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f);
					obj.destroyComponentOnEnd = true;
					obj.originalMaterial = Resources.Load<Material>("Materials/matHuntressFlashBright");
					obj.AddToCharacerModel(((Component)self.modelTransform).GetComponent<CharacterModel>());
					TemporaryOverlay obj2 = ((Component)self.modelTransform).gameObject.AddComponent<TemporaryOverlay>();
					obj2.duration = 0.7f;
					obj2.animateShaderAlpha = true;
					obj2.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f);
					obj2.destroyComponentOnEnd = true;
					obj2.originalMaterial = Resources.Load<Material>("Materials/matHuntressFlashExpanded");
					obj2.AddToCharacerModel(((Component)self.modelTransform).GetComponent<CharacterModel>());
				}
			}
			bool flag = self.stopwatch >= EvisDash.dashDuration + EvisDash.dashPrepDuration;
			if (self.isDashing)
			{
				if (Object.op_Implicit((Object)(object)((EntityState)self).characterMotor) && Object.op_Implicit((Object)(object)((EntityState)self).characterDirection))
				{
					CharacterMotor characterMotor = ((EntityState)self).characterMotor;
					characterMotor.rootMotion += self.dashVector * (((BaseState)self).moveSpeedStat * EvisDash.speedCoefficient * Time.fixedDeltaTime);
				}
				if (((EntityState)self).isAuthority)
				{
					Collider[] array = Physics.OverlapSphere(((EntityState)self).transform.position, ((EntityState)self).characterBody.radius + EvisDash.overlapSphereRadius * (flag ? EvisDash.lollypopFactor : 1f), LayerMask.op_Implicit(((LayerIndex)(ref LayerIndex.entityPrecise)).mask));
					for (int i = 0; i < array.Length; i++)
					{
						HurtBox component = ((Component)array[i]).GetComponent<HurtBox>();
						if (Object.op_Implicit((Object)(object)component) && (Object)(object)component.healthComponent != (Object)(object)((EntityState)self).healthComponent && component.teamIndex != ((EntityState)self).teamComponent.teamIndex)
						{
							Evis nextState = new Evis();
							((EntityState)self).outer.SetNextState((EntityState)(object)nextState);
							return;
						}
					}
				}
			}
			if (flag && ((EntityState)self).isAuthority)
			{
				((EntityState)self).outer.SetNextStateToMain();
			}
		}

		private void M1_onEnter(orig_OnEnter orig, GroundLight2 self)
		{
			if (M1AttackSpeedFix.Value)
			{
				if (self.step == 2)
				{
					((BasicMeleeAttack)self).ignoreAttackSpeed = true;
				}
				orig.Invoke(self);
				if (((BasicMeleeAttack)self).ignoreAttackSpeed && self.isComboFinisher)
				{
					self.durationBeforeInterruptable = GroundLight2.comboFinisherBaseDurationBeforeInterruptable;
				}
			}
			else
			{
				orig.Invoke(self);
			}
		}

		private void Uppercut_PlayAnim(orig_PlayAnim orig, Uppercut self)
		{
			if (M2AttackSpeedIgnore.Value)
			{
				self.duration = Uppercut.baseDuration;
			}
			orig.Invoke(self);
		}

		private void WhirlwindAir_PlayAnim(orig_PlayAnim orig, WhirlwindAir self)
		{
			if (M2AttackSpeedIgnore.Value)
			{
				((WhirlwindBase)self).duration = ((WhirlwindBase)self).baseDuration;
			}
			orig.Invoke(self);
		}

		private void WhirlwindGround_PlayAnim(orig_PlayAnim orig, WhirlwindGround self)
		{
			if (M2AttackSpeedIgnore.Value)
			{
				((WhirlwindBase)self).duration = ((WhirlwindBase)self).baseDuration;
			}
			orig.Invoke(self);
		}

		private void Evis_OnExit(orig_OnExit orig, Evis self)
		{
			CharacterBody characterBody = ((EntityState)self).characterBody;
			if (IsMerc(characterBody))
			{
				HealthComponent healthComponent = characterBody.healthComponent;
				if (Object.op_Implicit((Object)(object)healthComponent))
				{
					float num = Mathf.Clamp(cfgEvisBarrierPercent.Value, 0f, 100f) / 100f;
					float num2 = healthComponent.fullCombinedHealth * num;
					if (num2 > 0f)
					{
						healthComponent.AddBarrier(num2);
					}
				}
			}
			orig.Invoke(self);
		}

		private void FocusedAssaultDash_AuthorityModifyOverlapAttack(orig_AuthorityModifyOverlapAttack orig, FocusedAssaultDash self, OverlapAttack overlapAttack)
		{
			orig.Invoke(self, overlapAttack);
			try
			{
				if (self != null && overlapAttack != null)
				{
					float num = Mathf.Clamp(cfgFocusedAssaultDamagePercent.Value, 0f, 5000f) / 100f;
					overlapAttack.damage = ((BaseState)self).damageStat * num;
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[MercExtraEffects] FocusedAssaultDash_AuthorityModifyOverlapAttack error: " + ex));
			}
		}

		private void Assaulter2_AuthorityModifyOverlapAttack(orig_AuthorityModifyOverlapAttack orig, Assaulter2 self, OverlapAttack attack)
		{
			orig.Invoke(self, attack);
			try
			{
				if (self != null && attack != null)
				{
					float num = Mathf.Clamp(cfgBlindingAssaultDamagePercent.Value, 0f, 5000f) / 100f;
					attack.damage = ((BaseState)self).damageStat * num;
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[MercExtraEffects] Assaulter2_AuthorityModifyOverlapAttack error: " + ex));
			}
		}

		private void OnServerDamageDealt(DamageReport report)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (report == null)
				{
					return;
				}
				CharacterBody attackerBody = report.attackerBody;
				if (!IsMerc(attackerBody))
				{
					return;
				}
				MercTracker tracker = GetTracker(attackerBody);
				if ((Object)(object)tracker == (Object)null)
				{
					return;
				}
				HealthComponent healthComponent = attackerBody.healthComponent;
				if (!Object.op_Implicit((Object)(object)healthComponent))
				{
					return;
				}
				float damageDealt = report.damageDealt;
				if (!(damageDealt <= 0f) && (tracker.uppercutActive || tracker.whirlwindActive))
				{
					float num = Mathf.Clamp(cfgSecondaryLifestealPercent.Value, 0f, 200f) / 100f;
					float num2 = damageDealt * num;
					if (num2 > 0f)
					{
						healthComponent.Heal(num2, default(ProcChainMask), true);
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[MercExtraEffects] OnServerDamageDealt error: " + ex));
			}
		}

		private void ApplySkillTuning()
		{
			ApplyFocusedAssaultCooldown();
			ApplyBlindingAssaultCooldown();
			ApplyEvisDamageCoefficient();
			ApplyEvisCooldown();
		}

		private void ApplyFocusedAssaultCooldown()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				float baseRechargeInterval = Mathf.Clamp(cfgFocusedAssaultCooldownSeconds.Value, 0f, 60f);
				SkillDef val = Addressables.LoadAssetAsync<SkillDef>((object)"RoR2/Base/Merc/MercBodyFocusedAssault.asset").WaitForCompletion();
				if ((Object)(object)val == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"[MercExtraEffects] Focused Assault SkillDef not found at: RoR2/Base/Merc/MercBodyFocusedAssault.asset");
					return;
				}
				float baseRechargeInterval2 = val.baseRechargeInterval;
				val.baseRechargeInterval = baseRechargeInterval;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[MercExtraEffects] Focused Assault cooldown changed: " + baseRechargeInterval2 + " -> " + val.baseRechargeInterval));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[MercExtraEffects] Failed to set Focused Assault cooldown: " + ex));
			}
		}

		private void ApplyBlindingAssaultCooldown()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				float baseRechargeInterval = Mathf.Clamp(cfgBlindingAssaultCooldownSeconds.Value, 0f, 60f);
				SkillDef val = Addressables.LoadAssetAsync<SkillDef>((object)"RoR2/Base/Merc/MercBodyAssaulter.asset").WaitForCompletion();
				if ((Object)(object)val == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"[MercExtraEffects] Blinding Assault SkillDef not found at: RoR2/Base/Merc/MercBodyAssaulter.asset");
					return;
				}
				float baseRechargeInterval2 = val.baseRechargeInterval;
				val.baseRechargeInterval = baseRechargeInterval;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[MercExtraEffects] Blinding Assault changed: " + baseRechargeInterval2 + " -> " + val.baseRechargeInterval));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[MercExtraEffects] Failed to set Blinding Assault cooldown: " + ex));
			}
		}

		private void ApplyEvisDamageCoefficient()
		{
			try
			{
				float value = Mathf.Clamp(cfgEvisDamagePercent.Value, 0f, 5000f) / 100f;
				if (!TrySetStaticFloat(typeof(Evis), "damageCoefficient", value))
				{
					TrySetStaticFloat(typeof(Evis), "baseDamageCoefficient", value);
					TrySetStaticFloat(typeof(Evis), "damageCoefficientPerHit", value);
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[MercExtraEffects] Failed to set Evis damage coefficient: " + ex));
			}
		}

		private void ApplyEvisCooldown()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				float baseRechargeInterval = Mathf.Clamp(cfgEvisCooldownSeconds.Value, 0f, 60f);
				SkillDef val = null;
				string[] evisSkillDefPaths = EvisSkillDefPaths;
				foreach (string text in evisSkillDefPaths)
				{
					try
					{
						val = Addressables.LoadAssetAsync<SkillDef>((object)text).WaitForCompletion();
						if ((Object)(object)val != (Object)null)
						{
							break;
						}
					}
					catch
					{
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					val = FindMercSpecialSkillDefByState(typeof(EvisDash)) ?? FindMercSpecialSkillDefByState(typeof(Evis));
				}
				if ((Object)(object)val == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"[MercExtraEffects] Could not find Eviscerate SkillDef to set cooldown. (Tried addressables + MercBody scan)");
					return;
				}
				float baseRechargeInterval2 = val.baseRechargeInterval;
				val.baseRechargeInterval = baseRechargeInterval;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[MercExtraEffects] Eviscerate cooldown changed: " + baseRechargeInterval2 + " -> " + val.baseRechargeInterval));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[MercExtraEffects] Failed to set Eviscerate cooldown: " + ex));
			}
		}

		private SkillDef FindMercSpecialSkillDefByState(Type targetStateType)
		{
			try
			{
				GameObject val = BodyCatalog.FindBodyPrefab("MercBody");
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				SkillLocator component = val.GetComponent<SkillLocator>();
				if ((Object)(object)component == (Object)null || (Object)(object)component.special == (Object)null)
				{
					return null;
				}
				SkillDef skillDef = component.special.skillDef;
				if ((Object)(object)skillDef == (Object)null)
				{
					return null;
				}
				if (((SerializableEntityStateType)(ref skillDef.activationState)).stateType == targetStateType)
				{
					return skillDef;
				}
				return null;
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[MercExtraEffects] FindMercSpecialSkillDefByState error: " + ex.Message));
				return null;
			}
		}

		private bool TrySetStaticFloat(Type type, string fieldName, float value)
		{
			try
			{
				FieldInfo field = type.GetField(fieldName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (field == null)
				{
					return false;
				}
				if (field.FieldType != typeof(float))
				{
					return false;
				}
				float num = (float)field.GetValue(null);
				field.SetValue(null, value);
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"[MercExtraEffects] {type.Name}.{fieldName} changed: {num} -> {value}");
				return true;
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[MercExtraEffects] Failed setting " + type.Name + "." + fieldName + ": " + ex.Message));
				return false;
			}
		}
	}
}