Decompiled source of The Dragonblade v0.2.0

The Dragonblade.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.InputSystem;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Katana Dash Strike Debug")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Katana Dash Strike Debug")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("af2a21a3-46b6-4ff9-9bff-9c01c23a8b09")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace MeleeExpansion;

[BepInPlugin("kumo.sulfur.melee_expansion", "The Dragonblade", "0.2.0")]
public sealed class Plugin : BaseUnityPlugin
{
	private sealed class ToggleState
	{
		public bool IsToggled;

		public bool AttackInProgress;

		public bool SheatheAfterAttack;

		public bool SuppressMeleeUntilReleased;

		public float NextChargeAttemptTime;
	}

	private sealed class SafeAnimatorState
	{
		public bool Valid;

		public int FullPathHash;

		public int ShortNameHash;

		public string ClipName;
	}

	private sealed class KatanaDashState
	{
		public bool IsDashing;

		public bool ForcedSprintActive;

		public float DashEndTime;

		public float NextDashTime;

		public Vector3 Direction;

		public Vector3 LastPosition;

		public object KatanaWeapon;

		public readonly HashSet<int> HitUnitIds = new HashSet<int>();

		public bool PostHangActive;

		public float PostHangEndTime;

		public bool FallingEnabledWasSaved;

		public bool PreviousFallingEnabled = true;

		public float KillRefreshFeedbackEndTime;

		public float HealFeedbackEndTime;

		public float HealFeedbackAmount;
	}

	public const string PluginGuid = "kumo.sulfur.melee_expansion";

	public const string PluginName = "The Dragonblade";

	public const string PluginVersion = "0.2.0";

	internal static ManualLogSource Log;

	internal static ConfigEntry<bool> EnableMod;

	internal static ConfigEntry<bool> FirePerformsMeleeAttack;

	internal static ConfigEntry<bool> ResetMeleeAnimatorBeforeSheathe;

	internal static ConfigEntry<float> ReChargeRetryInterval;

	internal static ConfigEntry<bool> LogStateChanges;

	internal static ConfigEntry<bool> EnableKatanaDash;

	internal static ConfigEntry<string> KatanaNameKeywords;

	internal static ConfigEntry<float> DashCooldown;

	internal static ConfigEntry<float> DashDistance;

	internal static ConfigEntry<float> DashDuration;

	internal static ConfigEntry<float> DashHitRadius;

	internal static ConfigEntry<float> DashDamageMultiplier;

	internal static ConfigEntry<bool> DashHitEachUnitOnce;

	internal static ConfigEntry<bool> RefreshCooldownOnPlayerKill;

	internal static ConfigEntry<bool> RefreshRequiresKatanaStance;

	internal static ConfigEntry<bool> RefreshCooldownOnNonNpcUnitKill;

	internal static ConfigEntry<bool> HealOnEnemyKill;

	internal static ConfigEntry<float> HealAmountOnEnemyKill;

	internal static ConfigEntry<float> DashPostHangDuration;

	internal static ConfigEntry<float> DashPostHangMaxDownwardSpeed;

	internal static ConfigEntry<bool> SuppressFallingAnimationDuringPostHang;

	internal static ConfigEntry<bool> EnableDashHud;

	internal static ConfigEntry<string> DashIconFileName;

	internal static ConfigEntry<float> DashHudIconSize;

	internal static ConfigEntry<bool> DashHudUseActualSprintBinding;

	internal static ConfigEntry<string> DashHudFallbackKeyLabel;

	internal static ConfigEntry<float> DashKillRefreshFeedbackDuration;

	internal static ConfigEntry<float> DashHealFeedbackDuration;

	internal static ConfigEntry<bool> LogDash;

	private Harmony harmony;

	private static Type equipmentManagerType;

	private static Type weaponType;

	private static Type extendedWalkerType;

	private static Type moverType;

	private static Type playerType;

	private static Type unitType;

	private static Type npcType;

	private static Type entityStatsType;

	private static Type entityAttributesType;

	private static MethodInfo mHandleAimInput;

	private static MethodInfo mHandleMeleeInput;

	private static MethodInfo mPullTrigger;

	private static MethodInfo mReleaseTrigger;

	private static MethodInfo mChargeBasicMelee;

	private static MethodInfo mUseBasicMelee;

	private static MethodInfo mOnMeleeDone;

	private static MethodInfo mReportMeleeDone;

	private static MethodInfo mIsMeleeCharging;

	private static MethodInfo mChargeMelee;

	private static MethodInfo mSetAlternativeState;

	private static MethodInfo mUpdateSprinting;

	private static MethodInfo mToggleSprint;

	private static MethodInfo mMoverSetVelocity;

	private static MethodInfo mPlayerDirectionLooking;

	private static MethodInfo mWeaponGetDamage;

	private static MethodInfo mWeaponGetDamageType;

	private static MethodInfo mUnitReceiveDamageWithIDamager;

	private static MethodInfo mUnitReceiveDamageWithDamageSourceData;

	private static MethodInfo mEntityStatsModifyStatus;

	private static PropertyInfo pIsMelee;

	private static PropertyInfo pAnimator;

	private static PropertyInfo pSprintAction;

	private static PropertyInfo pFallingEnabled;

	private static PropertyInfo pSourceName;

	private static PropertyInfo pUnitState;

	private static PropertyInfo pUnitIsPlayer;

	private static PropertyInfo pUnitStats;

	private static PropertyInfo pNpcIsProtectedNpc;

	private static FieldInfo fAltFireAction;

	private static FieldInfo fMeleeFireAction;

	private static FieldInfo fMeleeFireActionAlternative;

	private static FieldInfo fCurrentHoldable;

	private static FieldInfo fEquipmentManager;

	private static FieldInfo fWalkerEquipmentManager;

	private static float LastActualHealAmount;

	private static FieldInfo fIsInMeleeCharge;

	private static FieldInfo fMeleePressed;

	private static FieldInfo fAlternativeMeleePressed;

	private static FieldInfo fAimingInputHeld;

	private static FieldInfo fMeleeInputCooldown;

	private static FieldInfo fCurrentParries;

	private static FieldInfo fWeaponDefinition;

	private static FieldInfo fUnitState;

	private static FieldInfo fUnitIsPlayer;

	private static FieldInfo fPlayerCamera;

	private static FieldInfo fDamageSourceDataIsPlayer;

	private static FieldInfo fDamageSourceDataSourceUnit;

	private static FieldInfo fDamageSourceDataSourceWeapon;

	private static Type hitmeshDataType;

	private static object hitmeshDataDefault;

	private static object entityAttributeStatusCurrentHealth;

	private static string PluginDirectory;

	private static Texture2D DashIconTexture;

	private static Texture2D HudPixelTexture;

	private static bool DashIconLoadAttempted;

	private static MethodInfo mEntityStatsGetStatus;

	private static MethodInfo mEntityStatsGetAttribute;

	private static object entityAttributeMaxHealth;

	private static readonly ConditionalWeakTable<object, ToggleState> ToggleStates = new ConditionalWeakTable<object, ToggleState>();

	private static readonly ConditionalWeakTable<object, SafeAnimatorState> SafeAnimatorStates = new ConditionalWeakTable<object, SafeAnimatorState>();

	private static readonly ConditionalWeakTable<object, KatanaDashState> DashStates = new ConditionalWeakTable<object, KatanaDashState>();

	private static object lastKnownWalkerController;

	private void Awake()
	{
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Expected O, but got Unknown
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Expected O, but got Unknown
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Expected O, but got Unknown
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Expected O, but got Unknown
		//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Expected O, but got Unknown
		//IL_0223: Unknown result type (might be due to invalid IL or missing references)
		//IL_022d: Expected O, but got Unknown
		//IL_0300: Unknown result type (might be due to invalid IL or missing references)
		//IL_030a: Expected O, but got Unknown
		//IL_033d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0347: Expected O, but got Unknown
		//IL_037a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0384: 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_049c: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a6: Expected O, but got Unknown
		//IL_04d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e3: Expected O, but got Unknown
		//IL_0551: Unknown result type (might be due to invalid IL or missing references)
		//IL_055b: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		PluginDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
		EnableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableMod", true, "Enable Melee Expansion.");
		FirePerformsMeleeAttack = ((BaseUnityPlugin)this).Config.Bind<bool>("ToggleMelee", "FirePerformsMeleeAttack", true, "When melee stance is toggled on, pressing the normal Fire action performs one melee attack.");
		ReChargeRetryInterval = ((BaseUnityPlugin)this).Config.Bind<float>("ToggleMelee", "ReChargeRetryInterval", 0.08f, new ConfigDescription("Seconds between retry attempts when the mod tries to re-enter melee charge after an attack.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.5f), Array.Empty<object>()));
		ResetMeleeAnimatorBeforeSheathe = ((BaseUnityPlugin)this).Config.Bind<bool>("ToggleMelee", "ResetMeleeAnimatorBeforeSheathe", true, "Before sheathing a toggled melee weapon, reset its Animator to the cached safe equip state.");
		EnableKatanaDash = ((BaseUnityPlugin)this).Config.Bind<bool>("KatanaDash", "EnableKatanaDash", true, "Enable Katana Dash Strike.");
		KatanaNameKeywords = ((BaseUnityPlugin)this).Config.Bind<string>("KatanaDash", "KatanaNameKeywords", "Katana,Wakizashi,BiggerKatana", "Comma-separated keywords used to detect katana-like melee weapons.");
		DashCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("KatanaDash", "Cooldown", 5f, new ConfigDescription("Dash cooldown in seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 60f), Array.Empty<object>()));
		DashDistance = ((BaseUnityPlugin)this).Config.Bind<float>("KatanaDash", "Distance", 8f, new ConfigDescription("Dash distance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 50f), Array.Empty<object>()));
		DashDuration = ((BaseUnityPlugin)this).Config.Bind<float>("KatanaDash", "Duration", 0.22f, new ConfigDescription("Dash duration in seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.03f, 2f), Array.Empty<object>()));
		DashHitRadius = ((BaseUnityPlugin)this).Config.Bind<float>("KatanaDash", "HitRadius", 1f, new ConfigDescription("Radius used to scan units along the dash path.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
		DashDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("KatanaDash", "DamageMultiplier", 1f, new ConfigDescription("Dash damage multiplier applied to the current katana weapon damage.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
		DashHitEachUnitOnce = ((BaseUnityPlugin)this).Config.Bind<bool>("KatanaDash", "HitEachUnitOnce", true, "If true, each unit can only be damaged once per dash.");
		RefreshCooldownOnPlayerKill = ((BaseUnityPlugin)this).Config.Bind<bool>("KatanaDash", "RefreshCooldownOnPlayerKill", true, "Refresh Katana Dash cooldown when the player kills an enemy.");
		RefreshRequiresKatanaStance = ((BaseUnityPlugin)this).Config.Bind<bool>("KatanaDash", "RefreshRequiresKatanaStance", true, "If true, kill refresh only works while the player is in toggled katana stance.");
		RefreshCooldownOnNonNpcUnitKill = ((BaseUnityPlugin)this).Config.Bind<bool>("KatanaDash", "RefreshCooldownOnNonNpcUnitKill", false, "If true, killing non-NPC Units such as breakable obstacles can also refresh Katana Dash cooldown. Healing never triggers from non-NPC Units.");
		HealOnEnemyKill = ((BaseUnityPlugin)this).Config.Bind<bool>("KatanaDash", "HealOnEnemyKill", true, "Heal the player when killing an enemy NPC while in katana stance. This never triggers from breakable obstacles.");
		HealAmountOnEnemyKill = ((BaseUnityPlugin)this).Config.Bind<float>("KatanaDash", "HealAmountOnEnemyKill", 5f, new ConfigDescription("Health restored when killing an enemy NPC.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 999f), Array.Empty<object>()));
		DashPostHangDuration = ((BaseUnityPlugin)this).Config.Bind<float>("KatanaDash", "PostHangDuration", 0.12f, new ConfigDescription("Short hang time after Katana Dash ends. This prevents the player from immediately dropping at full falling speed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f), Array.Empty<object>()));
		DashPostHangMaxDownwardSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("KatanaDash", "PostHangMaxDownwardSpeed", 0.5f, new ConfigDescription("Maximum downward speed during post-dash hang. 0 means no downward velocity during hang.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
		SuppressFallingAnimationDuringPostHang = ((BaseUnityPlugin)this).Config.Bind<bool>("KatanaDash", "SuppressFallingAnimationDuringPostHang", true, "Temporarily suppress the Falling animation during post-dash hang.");
		EnableDashHud = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "EnableDashHud", true, "Show a bottom-right Katana Dash cooldown HUD.");
		DashIconFileName = ((BaseUnityPlugin)this).Config.Bind<string>("UI", "DashIconFileName", "dash_icon.png", "PNG file name for the Katana Dash HUD icon. Place it next to MeleeExpansion.dll.");
		DashHudIconSize = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "DashHudIconSize", 76f, new ConfigDescription("Dash HUD icon size in pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(48f, 128f), Array.Empty<object>()));
		DashHudUseActualSprintBinding = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "DashHudUseActualSprintBinding", true, "Show the actual Sprint binding from the game's InputAction when possible.");
		DashHudFallbackKeyLabel = ((BaseUnityPlugin)this).Config.Bind<string>("UI", "DashHudFallbackKeyLabel", "SHIFT", "Fallback key label shown on the Dash HUD.");
		DashKillRefreshFeedbackDuration = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "DashKillRefreshFeedbackDuration", 0.45f, new ConfigDescription("Seconds to flash the Dash HUD when a kill refreshes the cooldown.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>()));
		DashHealFeedbackDuration = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "DashHealFeedbackDuration", 0.85f, new ConfigDescription("Seconds to show +HP feedback on enemy kill.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>()));
		LogStateChanges = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogStateChanges", false, "Log toggle melee state changes.");
		LogDash = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogDash", false, "Log Katana Dash debug events.");
		if (!InitializeReflection())
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Reflection initialization failed. Mod will not patch.");
			return;
		}
		harmony = new Harmony("kumo.sulfur.melee_expansion");
		Patch(mHandleAimInput, "HandleAimInputPrefix");
		Patch(mHandleMeleeInput, "HandleMeleeInputPrefix");
		Patch(mPullTrigger, "PullTriggerPrefix");
		Patch(mReleaseTrigger, "ReleaseTriggerPrefix");
		Patch(mReportMeleeDone, "ReportMeleeDonePrefix", "ReportMeleeDonePostfix");
		Patch(mChargeMelee, null, "ChargeMeleePostfix");
		Patch(mUpdateSprinting, "UpdateSprintingPrefix");
		Patch(mMoverSetVelocity, "MoverSetVelocityPrefix");
		Patch(mUnitReceiveDamageWithDamageSourceData, "UnitReceiveDamageDamageSourcePrefix", "UnitReceiveDamageDamageSourcePostfix");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Melee Expansion loaded.");
	}

	private void OnDestroy()
	{
		Harmony obj = harmony;
		if (obj != null)
		{
			obj.UnpatchSelf();
		}
	}

	private void OnGUI()
	{
		if (!IsModActive() || EnableDashHud == null || !EnableDashHud.Value || lastKnownWalkerController == null)
		{
			return;
		}
		object equipmentManagerFromWalker = GetEquipmentManagerFromWalker(lastKnownWalkerController);
		if (equipmentManagerFromWalker != null)
		{
			ToggleState toggleState = GetToggleState(equipmentManagerFromWalker);
			if (IsKatanaDashHudContext(lastKnownWalkerController, equipmentManagerFromWalker, toggleState, out var _))
			{
				KatanaDashState dashState = GetDashState(lastKnownWalkerController);
				object katana2;
				bool canUseDashNow = IsKatanaDashContext(lastKnownWalkerController, equipmentManagerFromWalker, toggleState, out katana2);
				DrawKatanaDashHud(dashState, canUseDashNow);
			}
		}
	}

	private static bool InitializeReflection()
	{
		equipmentManagerType = AccessTools.TypeByName("PerfectRandom.Sulfur.Core.Items.EquipmentManager");
		weaponType = AccessTools.TypeByName("PerfectRandom.Sulfur.Core.Weapons.Weapon");
		extendedWalkerType = AccessTools.TypeByName("PerfectRandom.Sulfur.Core.Movement.ExtendedAdvancedWalkerController");
		moverType = AccessTools.TypeByName("CMF.Mover");
		playerType = AccessTools.TypeByName("PerfectRandom.Sulfur.Core.Units.Player");
		unitType = AccessTools.TypeByName("PerfectRandom.Sulfur.Core.Units.Unit");
		npcType = AccessTools.TypeByName("PerfectRandom.Sulfur.Core.Units.Npc");
		entityStatsType = AccessTools.TypeByName("PerfectRandom.Sulfur.Core.Stats.EntityStats");
		entityAttributesType = AccessTools.TypeByName("PerfectRandom.Sulfur.Core.Stats.EntityAttributes");
		if (equipmentManagerType == null)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogError((object)"Could not find EquipmentManager type.");
			}
			return false;
		}
		if (weaponType == null)
		{
			ManualLogSource log2 = Log;
			if (log2 != null)
			{
				log2.LogError((object)"Could not find Weapon type.");
			}
			return false;
		}
		if (extendedWalkerType == null)
		{
			ManualLogSource log3 = Log;
			if (log3 != null)
			{
				log3.LogError((object)"Could not find ExtendedAdvancedWalkerController type.");
			}
			return false;
		}
		if (moverType == null)
		{
			ManualLogSource log4 = Log;
			if (log4 != null)
			{
				log4.LogError((object)"Could not find CMF.Mover type.");
			}
			return false;
		}
		if (playerType == null)
		{
			ManualLogSource log5 = Log;
			if (log5 != null)
			{
				log5.LogError((object)"Could not find Player type.");
			}
			return false;
		}
		if (unitType == null)
		{
			ManualLogSource log6 = Log;
			if (log6 != null)
			{
				log6.LogError((object)"Could not find Unit type.");
			}
			return false;
		}
		if (entityStatsType == null)
		{
			ManualLogSource log7 = Log;
			if (log7 != null)
			{
				log7.LogError((object)"Could not find EntityStats type.");
			}
			return false;
		}
		if (entityAttributesType == null)
		{
			ManualLogSource log8 = Log;
			if (log8 != null)
			{
				log8.LogError((object)"Could not find EntityAttributes type.");
			}
			return false;
		}
		try
		{
			entityAttributeStatusCurrentHealth = Enum.Parse(entityAttributesType, "Status_CurrentHealth");
			entityAttributeMaxHealth = TryParseEntityAttribute("Stat_MaxHealth", "Status_MaxHealth", "MaxHealth", "HealthMax", "Stat_HealthMax");
			if (entityAttributeMaxHealth == null)
			{
				ManualLogSource log9 = Log;
				if (log9 != null)
				{
					log9.LogError((object)"Could not resolve max health EntityAttributes value.");
				}
				return false;
			}
		}
		catch (Exception ex)
		{
			ManualLogSource log10 = Log;
			if (log10 != null)
			{
				log10.LogError((object)("Could not parse EntityAttributes.Status_CurrentHealth: " + ex));
			}
			return false;
		}
		mHandleAimInput = AccessTools.Method(equipmentManagerType, "HandleAimInput", new Type[1] { typeof(bool) }, (Type[])null);
		mHandleMeleeInput = AccessTools.Method(equipmentManagerType, "HandleMeleeInput", new Type[1] { typeof(bool) }, (Type[])null);
		mPullTrigger = AccessTools.Method(equipmentManagerType, "PullTrigger", (Type[])null, (Type[])null);
		mReleaseTrigger = AccessTools.Method(equipmentManagerType, "ReleaseTrigger", (Type[])null, (Type[])null);
		mChargeBasicMelee = AccessTools.Method(equipmentManagerType, "ChargeBasicMelee", (Type[])null, (Type[])null);
		mUseBasicMelee = AccessTools.Method(equipmentManagerType, "UseBasicMelee", (Type[])null, (Type[])null);
		mOnMeleeDone = AccessTools.Method(equipmentManagerType, "OnMeleeDone", (Type[])null, (Type[])null);
		mReportMeleeDone = AccessTools.Method(weaponType, "ReportMeleeDone", (Type[])null, (Type[])null);
		mIsMeleeCharging = AccessTools.Method(weaponType, "IsMeleeCharging", (Type[])null, (Type[])null);
		mChargeMelee = AccessTools.Method(weaponType, "ChargeMelee", new Type[1] { typeof(bool) }, (Type[])null);
		mSetAlternativeState = AccessTools.Method(weaponType, "SetAlternativeState", new Type[1] { typeof(int) }, (Type[])null);
		mWeaponGetDamage = AccessTools.Method(weaponType, "GetDamage", (Type[])null, (Type[])null);
		mWeaponGetDamageType = AccessTools.Method(weaponType, "GetDamageType", (Type[])null, (Type[])null);
		mUpdateSprinting = AccessTools.Method(extendedWalkerType, "UpdateSprinting", (Type[])null, (Type[])null);
		mToggleSprint = AccessTools.Method(extendedWalkerType, "ToggleSprint", new Type[1] { typeof(bool) }, (Type[])null);
		mMoverSetVelocity = AccessTools.Method(moverType, "SetVelocity", new Type[1] { typeof(Vector3) }, (Type[])null);
		mPlayerDirectionLooking = AccessTools.Method(playerType, "DirectionLooking", new Type[1] { typeof(bool) }, (Type[])null);
		mUnitReceiveDamageWithIDamager = FindUnitReceiveDamageWithIDamager();
		mUnitReceiveDamageWithDamageSourceData = FindUnitReceiveDamageWithDamageSourceData();
		if (mUnitReceiveDamageWithIDamager != null)
		{
			ParameterInfo[] parameters = mUnitReceiveDamageWithIDamager.GetParameters();
			hitmeshDataType = parameters[3].ParameterType;
			hitmeshDataDefault = GetHitmeshDataDefault(hitmeshDataType);
		}
		if (mUnitReceiveDamageWithDamageSourceData != null)
		{
			Type parameterType = mUnitReceiveDamageWithDamageSourceData.GetParameters()[2].ParameterType;
			fDamageSourceDataIsPlayer = AccessTools.Field(parameterType, "isPlayer");
			fDamageSourceDataSourceUnit = AccessTools.Field(parameterType, "sourceUnit");
			fDamageSourceDataSourceWeapon = AccessTools.Field(parameterType, "sourceWeapon");
		}
		pIsMelee = AccessTools.Property(weaponType, "IsMelee");
		pAnimator = FindPropertyRecursive(weaponType, "Animator");
		pSprintAction = FindPropertyRecursive(extendedWalkerType, "sprintAction");
		pFallingEnabled = FindPropertyRecursive(extendedWalkerType, "fallingEnabled");
		pSourceName = FindPropertyRecursive(weaponType, "SourceName");
		pUnitState = FindPropertyRecursive(unitType, "UnitState");
		pUnitIsPlayer = FindPropertyRecursive(unitType, "isPlayer");
		pUnitStats = FindPropertyRecursive(unitType, "Stats");
		if (npcType != null)
		{
			pNpcIsProtectedNpc = FindPropertyRecursive(npcType, "IsProtectedNpc");
		}
		mEntityStatsModifyStatus = AccessTools.Method(entityStatsType, "ModifyStatus", new Type[3]
		{
			entityAttributesType,
			typeof(float),
			typeof(bool)
		}, (Type[])null);
		mEntityStatsGetStatus = AccessTools.Method(entityStatsType, "GetStatus", new Type[1] { entityAttributesType }, (Type[])null);
		mEntityStatsGetAttribute = AccessTools.Method(entityStatsType, "GetAttribute", new Type[1] { entityAttributesType }, (Type[])null);
		fAltFireAction = FindFieldRecursive(equipmentManagerType, "altFireAction");
		fMeleeFireAction = FindFieldRecursive(equipmentManagerType, "meleeFireAction");
		fMeleeFireActionAlternative = FindFieldRecursive(equipmentManagerType, "meleeFireActionAlternative");
		fCurrentHoldable = FindFieldRecursive(equipmentManagerType, "currentHoldable");
		fEquipmentManager = FindFieldRecursive(weaponType, "equipmentManager");
		fWalkerEquipmentManager = FindFieldRecursive(extendedWalkerType, "equipmentManager");
		fIsInMeleeCharge = FindFieldRecursive(equipmentManagerType, "<isInMeleeCharge>k__BackingField", "isInMeleeCharge");
		fMeleePressed = FindFieldRecursive(equipmentManagerType, "<meleePressed>k__BackingField", "meleePressed");
		fAlternativeMeleePressed = FindFieldRecursive(equipmentManagerType, "<alternativeMeleePressed>k__BackingField", "alternativeMeleePressed");
		fAimingInputHeld = FindFieldRecursive(equipmentManagerType, "<AimingInputHeld>k__BackingField", "AimingInputHeld");
		fMeleeInputCooldown = FindFieldRecursive(equipmentManagerType, "meleeInputCooldown");
		fCurrentParries = FindFieldRecursive(weaponType, "currentParries");
		fWeaponDefinition = FindFieldRecursive(weaponType, "weaponDefinition", "<weaponDefinition>k__BackingField");
		fUnitState = FindFieldRecursive(unitType, "UnitState", "<UnitState>k__BackingField");
		fUnitIsPlayer = FindFieldRecursive(unitType, "isPlayer", "<isPlayer>k__BackingField");
		fPlayerCamera = FindFieldRecursive(playerType, "playerCamera");
		return Require(mHandleAimInput, "EquipmentManager.HandleAimInput(bool)") && Require(mHandleMeleeInput, "EquipmentManager.HandleMeleeInput(bool)") && Require(mPullTrigger, "EquipmentManager.PullTrigger()") && Require(mReleaseTrigger, "EquipmentManager.ReleaseTrigger()") && Require(mChargeBasicMelee, "EquipmentManager.ChargeBasicMelee()") && Require(mUseBasicMelee, "EquipmentManager.UseBasicMelee()") && Require(mOnMeleeDone, "EquipmentManager.OnMeleeDone()") && Require(mReportMeleeDone, "Weapon.ReportMeleeDone()") && Require(mIsMeleeCharging, "Weapon.IsMeleeCharging()") && Require(mChargeMelee, "Weapon.ChargeMelee(bool)") && Require(mSetAlternativeState, "Weapon.SetAlternativeState(int)") && Require(mWeaponGetDamage, "Weapon.GetDamage()") && Require(entityAttributeMaxHealth, "EntityAttributes max health") && Require(mEntityStatsGetStatus, "EntityStats.GetStatus(EntityAttributes)") && Require(mWeaponGetDamageType, "Weapon.GetDamageType()") && Require(mUpdateSprinting, "ExtendedAdvancedWalkerController.UpdateSprinting()") && Require(mToggleSprint, "ExtendedAdvancedWalkerController.ToggleSprint(bool)") && Require(mMoverSetVelocity, "Mover.SetVelocity(Vector3)") && Require(mUnitReceiveDamageWithIDamager, "Unit.ReceiveDamage(float, DamageTypes, IDamager, Hitmesh.Data, Vector3?)") && Require(mUnitReceiveDamageWithDamageSourceData, "Unit.ReceiveDamage(float, DamageTypes, DamageSourceData, Hitmesh.Data, Vector3?)") && Require(hitmeshDataType, "Hitmesh.Data parameter type") && Require(hitmeshDataDefault, "Hitmesh.Data.Default") && Require(fDamageSourceDataIsPlayer, "DamageSourceData.isPlayer") && Require(fDamageSourceDataSourceUnit, "DamageSourceData.sourceUnit") && Require(pIsMelee, "Weapon.IsMelee") && Require(pAnimator, "Holdable.Animator") && Require(pSprintAction, "ExtendedAdvancedWalkerController.sprintAction") && Require(pUnitStats, "Unit.Stats") && Require(mEntityStatsModifyStatus, "EntityStats.ModifyStatus(EntityAttributes, float, bool)") && Require(entityAttributeStatusCurrentHealth, "EntityAttributes.Status_CurrentHealth") && Require(fAltFireAction, "EquipmentManager.altFireAction") && Require(fMeleeFireAction, "EquipmentManager.meleeFireAction") && Require(fMeleeFireActionAlternative, "EquipmentManager.meleeFireActionAlternative") && Require(fCurrentHoldable, "EquipmentManager.currentHoldable") && Require(fEquipmentManager, "Weapon.equipmentManager") && Require(fWalkerEquipmentManager, "ExtendedAdvancedWalkerController.equipmentManager") && Require(fIsInMeleeCharge, "EquipmentManager.isInMeleeCharge") && Require(fMeleePressed, "EquipmentManager.meleePressed") && Require(fAlternativeMeleePressed, "EquipmentManager.alternativeMeleePressed") && Require(fAimingInputHeld, "EquipmentManager.AimingInputHeld") && Require(fMeleeInputCooldown, "EquipmentManager.meleeInputCooldown");
	}

	private static bool Require(object member, string name)
	{
		if (member != null)
		{
			return true;
		}
		ManualLogSource log = Log;
		if (log != null)
		{
			log.LogError((object)("Missing required member: " + name));
		}
		return false;
	}

	private void Patch(MethodInfo original, string prefix = null, string postfix = null)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Expected O, but got Unknown
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		HarmonyMethod val = null;
		HarmonyMethod val2 = null;
		if (!string.IsNullOrEmpty(prefix))
		{
			val = new HarmonyMethod(AccessTools.Method(typeof(Plugin), prefix, (Type[])null, (Type[])null));
		}
		if (!string.IsNullOrEmpty(postfix))
		{
			val2 = new HarmonyMethod(AccessTools.Method(typeof(Plugin), postfix, (Type[])null, (Type[])null));
		}
		harmony.Patch((MethodBase)original, val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
	}

	private static MethodInfo FindUnitReceiveDamageWithIDamager()
	{
		MethodInfo[] methods = unitType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo methodInfo in methods)
		{
			if (!(methodInfo.Name != "ReceiveDamage"))
			{
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length == 5 && !(parameters[0].ParameterType != typeof(float)) && !(parameters[2].ParameterType.Name != "IDamager") && !(parameters[4].ParameterType != typeof(Vector3?)))
				{
					return methodInfo;
				}
			}
		}
		return null;
	}

	private static MethodInfo FindUnitReceiveDamageWithDamageSourceData()
	{
		MethodInfo[] methods = unitType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo methodInfo in methods)
		{
			if (!(methodInfo.Name != "ReceiveDamage"))
			{
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length == 5 && !(parameters[0].ParameterType != typeof(float)) && !(parameters[2].ParameterType.Name != "DamageSourceData") && !(parameters[4].ParameterType != typeof(Vector3?)))
				{
					return methodInfo;
				}
			}
		}
		return null;
	}

	private static object GetHitmeshDataDefault(Type type)
	{
		if (type == null)
		{
			return null;
		}
		FieldInfo fieldInfo = AccessTools.Field(type, "Default");
		if (fieldInfo != null)
		{
			return fieldInfo.GetValue(null);
		}
		PropertyInfo propertyInfo = AccessTools.Property(type, "Default");
		if (propertyInfo != null)
		{
			return propertyInfo.GetValue(null, null);
		}
		try
		{
			return Activator.CreateInstance(type);
		}
		catch
		{
			return null;
		}
	}

	private static FieldInfo FindFieldRecursive(Type type, params string[] names)
	{
		Type type2 = type;
		while (type2 != null)
		{
			foreach (string text in names)
			{
				FieldInfo fieldInfo = AccessTools.Field(type2, text);
				if (fieldInfo != null)
				{
					return fieldInfo;
				}
			}
			type2 = type2.BaseType;
		}
		return null;
	}

	private static PropertyInfo FindPropertyRecursive(Type type, string name)
	{
		Type type2 = type;
		while (type2 != null)
		{
			PropertyInfo propertyInfo = AccessTools.Property(type2, name);
			if (propertyInfo != null)
			{
				return propertyInfo;
			}
			type2 = type2.BaseType;
		}
		return null;
	}

	private static bool IsModActive()
	{
		return EnableMod != null && EnableMod.Value;
	}

	private static ToggleState GetToggleState(object equipmentManager)
	{
		return ToggleStates.GetValue(equipmentManager, (object _) => new ToggleState());
	}

	private static KatanaDashState GetDashState(object walkerController)
	{
		return DashStates.GetValue(walkerController, (object _) => new KatanaDashState());
	}

	private static void HandleAimInputPrefix(object __instance, ref bool holdingMeleeAction)
	{
		if (IsModActive())
		{
			ToggleState toggleState = GetToggleState(__instance);
			if (toggleState.IsToggled)
			{
				holdingMeleeAction = true;
			}
		}
	}

	private static bool HandleMeleeInputPrefix(object __instance, bool holdingMeleeAction)
	{
		if (!IsModActive())
		{
			return true;
		}
		ToggleState toggleState = GetToggleState(__instance);
		if (toggleState.SuppressMeleeUntilReleased)
		{
			if (IsMeleeHeld(__instance))
			{
				return false;
			}
			toggleState.SuppressMeleeUntilReleased = false;
			if (LogStateChanges.Value)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)"Melee input released after manual sheathe. Input suppression cleared.");
				}
			}
			return false;
		}
		bool flag = WasMeleePressedThisFrame(__instance);
		if (!toggleState.IsToggled && IsAimingInputHeld(__instance) && holdingMeleeAction)
		{
			return true;
		}
		if (!toggleState.IsToggled && IsMeleeInputCoolingDown(__instance))
		{
			return true;
		}
		if (flag)
		{
			if (!toggleState.IsToggled)
			{
				ToggleOn(__instance, toggleState);
				return false;
			}
			ToggleOff(__instance, toggleState);
			return false;
		}
		if (toggleState.IsToggled)
		{
			MaintainToggledMelee(__instance, toggleState);
			return false;
		}
		return true;
	}

	private static bool PullTriggerPrefix(object __instance)
	{
		if (!IsModActive())
		{
			return true;
		}
		ToggleState toggleState = GetToggleState(__instance);
		if (!toggleState.IsToggled)
		{
			return true;
		}
		if (!FirePerformsMeleeAttack.Value)
		{
			return false;
		}
		object currentHoldable = GetCurrentHoldable(__instance);
		if (!IsMeleeWeapon(currentHoldable))
		{
			MaintainToggledMelee(__instance, toggleState);
			return false;
		}
		if (!IsMeleeCharging(currentHoldable))
		{
			MaintainToggledMelee(__instance, toggleState);
			return false;
		}
		if (toggleState.AttackInProgress)
		{
			return false;
		}
		toggleState.AttackInProgress = true;
		toggleState.SheatheAfterAttack = false;
		toggleState.SuppressMeleeUntilReleased = false;
		if (LogStateChanges.Value)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)"Fire action converted to melee attack.");
			}
		}
		InvokeUseBasicMelee(__instance);
		return false;
	}

	private static bool ReleaseTriggerPrefix(object __instance)
	{
		if (!IsModActive())
		{
			return true;
		}
		ToggleState toggleState = GetToggleState(__instance);
		if (!toggleState.IsToggled && !toggleState.AttackInProgress && !toggleState.SheatheAfterAttack)
		{
			return true;
		}
		return false;
	}

	private static void ReportMeleeDonePrefix(object __instance)
	{
		if (!IsModActive())
		{
			return;
		}
		object equipmentManagerFromWeapon = GetEquipmentManagerFromWeapon(__instance);
		if (equipmentManagerFromWeapon != null)
		{
			ToggleState toggleState = GetToggleState(equipmentManagerFromWeapon);
			if (toggleState.IsToggled || toggleState.AttackInProgress || toggleState.SheatheAfterAttack)
			{
				PrepareMeleeAnimatorForFutureDraw(__instance);
			}
		}
	}

	private static void ReportMeleeDonePostfix(object __instance)
	{
		if (!IsModActive())
		{
			return;
		}
		object equipmentManagerFromWeapon = GetEquipmentManagerFromWeapon(__instance);
		if (equipmentManagerFromWeapon == null)
		{
			return;
		}
		ToggleState toggleState = GetToggleState(equipmentManagerFromWeapon);
		if (toggleState.SheatheAfterAttack)
		{
			toggleState.AttackInProgress = false;
			toggleState.SheatheAfterAttack = false;
			toggleState.IsToggled = false;
			toggleState.SuppressMeleeUntilReleased = true;
			toggleState.NextChargeAttemptTime = 0f;
			if (LogStateChanges.Value)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)"Melee attack finished. Staying sheathed.");
				}
			}
			return;
		}
		if (!toggleState.IsToggled)
		{
			toggleState.AttackInProgress = false;
			toggleState.NextChargeAttemptTime = 0f;
			return;
		}
		toggleState.AttackInProgress = false;
		toggleState.NextChargeAttemptTime = Time.time + ClampRetryInterval();
		if (LogStateChanges.Value)
		{
			ManualLogSource log2 = Log;
			if (log2 != null)
			{
				log2.LogInfo((object)"Melee attack finished. Re-entering toggled melee stance.");
			}
		}
		InvokeChargeBasicMelee(equipmentManagerFromWeapon);
	}

	private static void ChargeMeleePostfix(object __instance, bool state)
	{
		if (IsModActive() && state)
		{
			CacheSafeMeleeAnimatorStateIfUseful(__instance, "ChargeMelee(true)");
		}
	}

	private static bool UpdateSprintingPrefix(object __instance)
	{
		if (!IsModActive() || !EnableKatanaDash.Value)
		{
			return true;
		}
		KatanaDashState dashState = GetDashState(__instance);
		object equipmentManagerFromWalker = GetEquipmentManagerFromWalker(__instance);
		if (equipmentManagerFromWalker == null)
		{
			return true;
		}
		ToggleState toggleState = GetToggleState(equipmentManagerFromWalker);
		if (!IsKatanaDashContext(__instance, equipmentManagerFromWalker, toggleState, out var katana))
		{
			dashState.ForcedSprintActive = false;
			return true;
		}
		lastKnownWalkerController = __instance;
		InputAction sprintAction = GetSprintAction(__instance);
		if (WasPerformedThisFrame(sprintAction))
		{
			TryStartKatanaDash(__instance, equipmentManagerFromWalker, katana);
		}
		dashState.ForcedSprintActive = true;
		InvokeToggleSprint(__instance, state: true);
		return false;
	}

	private static void MoverSetVelocityPrefix(object __instance, ref Vector3 _velocity)
	{
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		if (!IsModActive() || !EnableKatanaDash.Value)
		{
			return;
		}
		Component val = (Component)((__instance is Component) ? __instance : null);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Component component = val.GetComponent(extendedWalkerType);
		if ((Object)(object)component == (Object)null)
		{
			return;
		}
		KatanaDashState dashState = GetDashState(component);
		if (dashState.IsDashing)
		{
			UpdateKatanaDash(component, dashState);
			if (dashState.IsDashing)
			{
				float dashSpeed = GetDashSpeed();
				_velocity = dashState.Direction * dashSpeed;
				return;
			}
		}
		if (dashState.PostHangActive)
		{
			ApplyPostDashHangVelocity(component, dashState, ref _velocity);
		}
	}

	private static void UnitReceiveDamageDamageSourcePrefix(object __instance, ref bool __state)
	{
		__state = false;
		if (IsModActive() && RefreshCooldownOnPlayerKill != null && RefreshCooldownOnPlayerKill.Value && __instance != null && !IsDeadUnit(__instance) && IsKilledUnitEligibleForDashRefresh(__instance))
		{
			__state = true;
		}
	}

	private static void UnitReceiveDamageDamageSourcePostfix(object __instance, bool __state, object[] __args)
	{
		if (__state && __instance != null && IsDeadUnit(__instance) && IsKilledUnitEligibleForDashRefresh(__instance) && __args != null && __args.Length >= 3)
		{
			object damageSourceData = __args[2];
			if (IsPlayerDamageSource(damageSourceData, out var sourceUnit))
			{
				RefreshKatanaDashCooldownAndHealForKill(sourceUnit, __instance);
			}
		}
	}

	private static bool IsPlayerDamageSource(object damageSourceData, out object sourceUnit)
	{
		sourceUnit = null;
		if (damageSourceData == null)
		{
			return false;
		}
		try
		{
			if (!(fDamageSourceDataIsPlayer.GetValue(damageSourceData) is int num) || num == 0)
			{
				return false;
			}
			if (fDamageSourceDataSourceUnit != null)
			{
				sourceUnit = fDamageSourceDataSourceUnit.GetValue(damageSourceData);
			}
			return true;
		}
		catch (Exception ex)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogError((object)("Failed to read DamageSourceData: " + ex));
			}
			return false;
		}
	}

	private static void RefreshKatanaDashCooldownAndHealForKill(object sourceUnit, object killedUnit)
	{
		object obj = null;
		Component val = (Component)((sourceUnit is Component) ? sourceUnit : null);
		if ((Object)(object)val != (Object)null)
		{
			obj = val.GetComponent(extendedWalkerType);
		}
		if (obj == null)
		{
			obj = lastKnownWalkerController;
		}
		if (obj == null)
		{
			return;
		}
		object equipmentManagerFromWalker = GetEquipmentManagerFromWalker(obj);
		if (equipmentManagerFromWalker == null)
		{
			return;
		}
		ToggleState toggleState = GetToggleState(equipmentManagerFromWalker);
		if (RefreshRequiresKatanaStance != null && RefreshRequiresKatanaStance.Value && !IsKatanaDashHudContext(obj, equipmentManagerFromWalker, toggleState, out var _))
		{
			return;
		}
		KatanaDashState dashState = GetDashState(obj);
		float num = Mathf.Max(0f, dashState.NextDashTime - Time.time);
		dashState.NextDashTime = Time.time;
		dashState.KillRefreshFeedbackEndTime = Time.time + GetDashKillRefreshFeedbackDuration();
		LastActualHealAmount = 0f;
		bool flag = TryHealPlayerFromEnemyKill(sourceUnit, killedUnit);
		if (flag && LastActualHealAmount > 0f)
		{
			dashState.HealFeedbackAmount = LastActualHealAmount;
			dashState.HealFeedbackEndTime = Time.time + GetDashHealFeedbackDuration();
		}
		if (LogDash != null && LogDash.Value)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)("Katana Dash cooldown refreshed by kill. Previous cooldown left: " + num.ToString("F2") + "s healed=" + flag + " killedUnit=" + killedUnit));
			}
		}
	}

	private static bool TryHealPlayerFromEnemyKill(object sourceUnit, object killedUnit)
	{
		if (HealOnEnemyKill == null || !HealOnEnemyKill.Value)
		{
			return false;
		}
		float healAmountOnEnemyKill = GetHealAmountOnEnemyKill();
		if (healAmountOnEnemyKill <= 0f)
		{
			return false;
		}
		if (!HasNpcComponent(killedUnit))
		{
			return false;
		}
		if (IsPlayerUnit(killedUnit))
		{
			return false;
		}
		if (IsProtectedNpc(killedUnit))
		{
			return false;
		}
		if (sourceUnit == null)
		{
			return false;
		}
		if (!IsPlayerUnit(sourceUnit))
		{
			return false;
		}
		return HealUnit(sourceUnit, healAmountOnEnemyKill);
	}

	private static bool HealUnit(object unit, float amount)
	{
		if (unit == null || amount <= 0f)
		{
			return false;
		}
		try
		{
			object obj = null;
			if (pUnitStats != null)
			{
				obj = pUnitStats.GetValue(unit, null);
			}
			if (obj == null)
			{
				return false;
			}
			float entityStatValue = GetEntityStatValue(obj, entityAttributeStatusCurrentHealth, preferStatus: true);
			float entityStatValue2 = GetEntityStatValue(obj, entityAttributeMaxHealth, preferStatus: false);
			if (entityStatValue2 <= 0f)
			{
				return false;
			}
			float num = Mathf.Max(0f, entityStatValue2 - entityStatValue);
			float num2 = Mathf.Min(amount, num);
			if (num2 <= 0f)
			{
				return false;
			}
			mEntityStatsModifyStatus.Invoke(obj, new object[3] { entityAttributeStatusCurrentHealth, num2, false });
			if (LogDash != null && LogDash.Value)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)("Healed player for " + num2.ToString("F1") + " on enemy kill. Current=" + entityStatValue.ToString("F1") + " Max=" + entityStatValue2.ToString("F1")));
				}
			}
			LastActualHealAmount = num2;
			return true;
		}
		catch (Exception ex)
		{
			ManualLogSource log2 = Log;
			if (log2 != null)
			{
				log2.LogError((object)("Failed to heal player on enemy kill: " + ex));
			}
			return false;
		}
	}

	private static bool IsKilledUnitEligibleForDashRefresh(object unit)
	{
		if (unit == null)
		{
			return false;
		}
		if (IsPlayerUnit(unit))
		{
			return false;
		}
		if (IsProtectedNpc(unit))
		{
			return false;
		}
		if (HasNpcComponent(unit))
		{
			return true;
		}
		return RefreshCooldownOnNonNpcUnitKill != null && RefreshCooldownOnNonNpcUnitKill.Value;
	}

	private static bool HasNpcComponent(object unit)
	{
		if (unit == null || npcType == null)
		{
			return false;
		}
		Component val = (Component)((unit is Component) ? unit : null);
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		Component component = val.GetComponent(npcType);
		return (Object)(object)component != (Object)null;
	}

	private static void ToggleOn(object equipmentManager, ToggleState state)
	{
		state.IsToggled = true;
		state.AttackInProgress = false;
		state.SheatheAfterAttack = false;
		state.SuppressMeleeUntilReleased = false;
		state.NextChargeAttemptTime = Time.time + ClampRetryInterval();
		if (LogStateChanges.Value)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)"Toggle melee ON.");
			}
		}
		InvokeChargeBasicMelee(equipmentManager);
		SetMeleePressed(equipmentManager, value: true);
	}

	private static void ToggleOff(object equipmentManager, ToggleState state)
	{
		if (LogStateChanges.Value)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)"Toggle melee OFF.");
			}
		}
		state.IsToggled = false;
		state.NextChargeAttemptTime = 0f;
		state.SuppressMeleeUntilReleased = true;
		SetAlternativeMeleePressed(equipmentManager, value: false);
		SetMeleePressed(equipmentManager, value: false);
		object currentHoldable = GetCurrentHoldable(equipmentManager);
		if (state.AttackInProgress)
		{
			state.SheatheAfterAttack = true;
			if (LogStateChanges.Value)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogInfo((object)"Melee attack is in progress. Will sheathe after current attack finishes.");
				}
			}
		}
		else
		{
			state.AttackInProgress = false;
			state.SheatheAfterAttack = false;
			CleanCurrentMeleeWeaponState(currentHoldable);
			InvokeOnMeleeDone(equipmentManager);
		}
	}

	private static void MaintainToggledMelee(object equipmentManager, ToggleState state)
	{
		if (!state.AttackInProgress && !state.SheatheAfterAttack)
		{
			bool flag = IsAltFirePressed(equipmentManager);
			SetAlternativeMeleePressed(equipmentManager, flag);
			UpdateCurrentMeleeAlternativeAnimator(equipmentManager, flag);
			if (!IsInMeleeCharge(equipmentManager) && !(Time.time < state.NextChargeAttemptTime))
			{
				state.NextChargeAttemptTime = Time.time + ClampRetryInterval();
				InvokeChargeBasicMelee(equipmentManager);
				SetMeleePressed(equipmentManager, value: true);
			}
		}
	}

	private static bool IsKatanaDashContext(object walkerController, object equipmentManager, ToggleState toggleState, out object katana)
	{
		katana = null;
		if (walkerController == null || equipmentManager == null || toggleState == null)
		{
			return false;
		}
		if (!toggleState.IsToggled || toggleState.AttackInProgress || toggleState.SheatheAfterAttack)
		{
			return false;
		}
		object currentHoldable = GetCurrentHoldable(equipmentManager);
		if (!IsKatanaWeapon(currentHoldable))
		{
			return false;
		}
		if (!IsInMeleeCharge(equipmentManager))
		{
			return false;
		}
		katana = currentHoldable;
		return true;
	}

	private static bool IsKatanaDashHudContext(object walkerController, object equipmentManager, ToggleState toggleState, out object katana)
	{
		katana = null;
		if (walkerController == null || equipmentManager == null || toggleState == null)
		{
			return false;
		}
		if (!toggleState.IsToggled || toggleState.SheatheAfterAttack)
		{
			return false;
		}
		object currentHoldable = GetCurrentHoldable(equipmentManager);
		if (!IsKatanaWeapon(currentHoldable))
		{
			return false;
		}
		katana = currentHoldable;
		return true;
	}

	private static void TryStartKatanaDash(object walkerController, object equipmentManager, object katana)
	{
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		if (walkerController == null || equipmentManager == null || katana == null)
		{
			return;
		}
		KatanaDashState dashState = GetDashState(walkerController);
		EndPostDashHang(walkerController, dashState);
		if (dashState.IsDashing)
		{
			return;
		}
		if (Time.time < dashState.NextDashTime)
		{
			if (LogDash.Value)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)("Katana Dash is cooling down: " + Mathf.Max(0f, dashState.NextDashTime - Time.time).ToString("F2") + "s"));
				}
			}
			return;
		}
		Vector3 lookingDirection = GetLookingDirection(walkerController);
		if (((Vector3)(ref lookingDirection)).sqrMagnitude < 0.0001f)
		{
			return;
		}
		((Vector3)(ref lookingDirection)).Normalize();
		Component val = (Component)((walkerController is Component) ? walkerController : null);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		dashState.IsDashing = true;
		dashState.DashEndTime = Time.time + GetDashDuration();
		dashState.NextDashTime = Time.time + GetDashCooldown();
		dashState.Direction = lookingDirection;
		dashState.LastPosition = val.transform.position;
		dashState.KatanaWeapon = katana;
		dashState.HitUnitIds.Clear();
		if (LogDash.Value)
		{
			ManualLogSource log2 = Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("Katana Dash started. direction=" + ((object)(Vector3)(ref lookingDirection)).ToString() + " duration=" + GetDashDuration().ToString("F2") + " distance=" + GetDashDistance().ToString("F2")));
			}
		}
	}

	private static void UpdateKatanaDash(Component walkerComponent, KatanaDashState dashState)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: 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)
		if ((Object)(object)walkerComponent == (Object)null || dashState == null)
		{
			return;
		}
		Vector3 position = walkerComponent.transform.position;
		ProcessDashHits(walkerComponent, dashState, dashState.LastPosition, position);
		dashState.LastPosition = position;
		if (!(Time.time >= dashState.DashEndTime))
		{
			return;
		}
		dashState.IsDashing = false;
		BeginPostDashHang(walkerComponent, dashState);
		if (LogDash.Value)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)"Katana Dash ended. Post hang started.");
			}
		}
	}

	private static void BeginPostDashHang(Component walkerComponent, KatanaDashState dashState)
	{
		if ((Object)(object)walkerComponent == (Object)null || dashState == null)
		{
			return;
		}
		float dashPostHangDuration = GetDashPostHangDuration();
		if (dashPostHangDuration <= 0f)
		{
			EndPostDashHang(walkerComponent, dashState);
			return;
		}
		dashState.PostHangActive = true;
		dashState.PostHangEndTime = Time.time + dashPostHangDuration;
		if (SuppressFallingAnimationDuringPostHang.Value)
		{
			SaveAndSetFallingEnabled(walkerComponent, dashState, value: false);
		}
	}

	private static void ApplyPostDashHangVelocity(Component walkerComponent, KatanaDashState dashState, ref Vector3 velocity)
	{
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//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_0079: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)walkerComponent == (Object)null || dashState == null)
		{
			return;
		}
		if (Time.time >= dashState.PostHangEndTime)
		{
			EndPostDashHang(walkerComponent, dashState);
			return;
		}
		Vector3 up = walkerComponent.transform.up;
		float num = Vector3.Dot(velocity, up);
		float dashPostHangMaxDownwardSpeed = GetDashPostHangMaxDownwardSpeed();
		if (num < 0f - dashPostHangMaxDownwardSpeed)
		{
			velocity += up * (0f - dashPostHangMaxDownwardSpeed - num);
		}
	}

	private static void EndPostDashHang(object walkerController, KatanaDashState dashState)
	{
		if (dashState != null)
		{
			Component val = (Component)((walkerController is Component) ? walkerController : null);
			if ((Object)(object)val != (Object)null)
			{
				RestoreFallingEnabled(val, dashState);
			}
			dashState.PostHangActive = false;
			dashState.PostHangEndTime = 0f;
		}
	}

	private static void SaveAndSetFallingEnabled(Component walkerComponent, KatanaDashState dashState, bool value)
	{
		if ((Object)(object)walkerComponent == (Object)null || dashState == null || pFallingEnabled == null)
		{
			return;
		}
		try
		{
			if (!dashState.FallingEnabledWasSaved)
			{
				object value2 = pFallingEnabled.GetValue(walkerComponent, null);
				if (value2 is bool)
				{
					dashState.PreviousFallingEnabled = (bool)value2;
					dashState.FallingEnabledWasSaved = true;
				}
			}
			pFallingEnabled.SetValue(walkerComponent, value, null);
		}
		catch (Exception ex)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogError((object)("Failed to set fallingEnabled during post dash hang: " + ex));
			}
		}
	}

	private static void RestoreFallingEnabled(Component walkerComponent, KatanaDashState dashState)
	{
		if ((Object)(object)walkerComponent == (Object)null || dashState == null || pFallingEnabled == null || !dashState.FallingEnabledWasSaved)
		{
			return;
		}
		try
		{
			pFallingEnabled.SetValue(walkerComponent, dashState.PreviousFallingEnabled, null);
		}
		catch (Exception ex)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogError((object)("Failed to restore fallingEnabled after post dash hang: " + ex));
			}
		}
		finally
		{
			dashState.FallingEnabledWasSaved = false;
			dashState.PreviousFallingEnabled = true;
		}
	}

	private static void ProcessDashHits(Component walkerComponent, KatanaDashState dashState, Vector3 start, Vector3 end)
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//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_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: 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_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)walkerComponent == (Object)null || dashState == null || dashState.KatanaWeapon == null)
		{
			return;
		}
		float dashHitRadius = GetDashHitRadius();
		Vector3 val = end - start;
		Collider[] array = ((!(((Vector3)(ref val)).sqrMagnitude <= 0.0001f)) ? Physics.OverlapCapsule(start, end, dashHitRadius, -1, (QueryTriggerInteraction)2) : Physics.OverlapSphere(start, dashHitRadius, -1, (QueryTriggerInteraction)2));
		if (array == null || array.Length == 0)
		{
			return;
		}
		object component = GetComponent(walkerComponent, unitType);
		foreach (Collider val2 in array)
		{
			if ((Object)(object)val2 == (Object)null)
			{
				continue;
			}
			object componentInParent = ((Component)val2).GetComponentInParent(unitType);
			if (componentInParent == null || componentInParent == component || IsPlayerUnit(componentInParent) || IsDeadUnit(componentInParent) || IsProtectedNpc(componentInParent))
			{
				continue;
			}
			int instanceID = ((Object)componentInParent).GetInstanceID();
			if (DashHitEachUnitOnce.Value && dashState.HitUnitIds.Contains(instanceID))
			{
				continue;
			}
			Vector3 hitPoint = val2.ClosestPoint(end);
			if (!ApplyKatanaDashDamage(componentInParent, dashState.KatanaWeapon, hitPoint))
			{
				continue;
			}
			dashState.HitUnitIds.Add(instanceID);
			if (LogDash.Value)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)("Katana Dash hit unit: " + componentInParent));
				}
			}
		}
	}

	private static bool ApplyKatanaDashDamage(object unit, object katana, Vector3 hitPoint)
	{
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		if (unit == null || katana == null)
		{
			return false;
		}
		try
		{
			float num = Convert.ToSingle(mWeaponGetDamage.Invoke(katana, null));
			float num2 = num * GetDashDamageMultiplier();
			object obj = mWeaponGetDamageType.Invoke(katana, null);
			object[] parameters = new object[5] { num2, obj, katana, hitmeshDataDefault, hitPoint };
			object obj2 = mUnitReceiveDamageWithIDamager.Invoke(unit, parameters);
			return obj2 is bool && (bool)obj2;
		}
		catch (Exception ex)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogError((object)("Failed to apply Katana Dash damage: " + ex));
			}
			return false;
		}
	}

	private static Vector3 GetLookingDirection(object walkerController)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: 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)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		Component val = (Component)((walkerController is Component) ? walkerController : null);
		if ((Object)(object)val == (Object)null)
		{
			return Vector3.zero;
		}
		object component = GetComponent(val, playerType);
		if (component != null && mPlayerDirectionLooking != null)
		{
			try
			{
				object obj = mPlayerDirectionLooking.Invoke(component, new object[1] { false });
				if (obj is Vector3)
				{
					return (Vector3)obj;
				}
			}
			catch
			{
			}
		}
		if (component != null && fPlayerCamera != null)
		{
			try
			{
				object? value = fPlayerCamera.GetValue(component);
				Camera val2 = (Camera)((value is Camera) ? value : null);
				if ((Object)(object)val2 != (Object)null)
				{
					return ((Component)val2).transform.forward;
				}
			}
			catch
			{
			}
		}
		if ((Object)(object)Camera.main != (Object)null)
		{
			return ((Component)Camera.main).transform.forward;
		}
		return val.transform.forward;
	}

	private static bool IsKatanaWeapon(object weapon)
	{
		if (!IsMeleeWeapon(weapon))
		{
			return false;
		}
		string value = KatanaNameKeywords.Value;
		if (string.IsNullOrEmpty(value))
		{
			return false;
		}
		string[] array = value.Split(new char[1] { ',' });
		string weaponSearchText = GetWeaponSearchText(weapon);
		for (int i = 0; i < array.Length; i++)
		{
			string value2 = array[i].Trim();
			if (!string.IsNullOrEmpty(value2) && weaponSearchText.IndexOf(value2, StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
		}
		return false;
	}

	private static string GetWeaponSearchText(object weapon)
	{
		if (weapon == null)
		{
			return string.Empty;
		}
		string empty = string.Empty;
		empty += weapon.ToString();
		empty += " ";
		Component val = (Component)((weapon is Component) ? weapon : null);
		if ((Object)(object)val != (Object)null)
		{
			empty += ((Object)val).name;
			empty += " ";
			empty += ((Object)val.gameObject).name;
			empty += " ";
		}
		if (pSourceName != null)
		{
			try
			{
				object value = pSourceName.GetValue(weapon, null);
				if (value != null)
				{
					empty += value.ToString();
					empty += " ";
				}
			}
			catch
			{
			}
		}
		if (fWeaponDefinition != null)
		{
			try
			{
				object value2 = fWeaponDefinition.GetValue(weapon);
				if (value2 != null)
				{
					empty += value2.ToString();
					empty += " ";
				}
			}
			catch
			{
			}
		}
		return empty;
	}

	private static object GetEquipmentManagerFromWalker(object walkerController)
	{
		if (walkerController == null || fWalkerEquipmentManager == null)
		{
			return null;
		}
		return fWalkerEquipmentManager.GetValue(walkerController);
	}

	private static object TryParseEntityAttribute(params string[] names)
	{
		if (entityAttributesType == null || names == null)
		{
			return null;
		}
		foreach (string value in names)
		{
			if (string.IsNullOrEmpty(value))
			{
				continue;
			}
			try
			{
				if (Enum.IsDefined(entityAttributesType, value))
				{
					return Enum.Parse(entityAttributesType, value);
				}
			}
			catch
			{
			}
		}
		return null;
	}

	private static InputAction GetSprintAction(object walkerController)
	{
		if (walkerController == null || pSprintAction == null)
		{
			return null;
		}
		try
		{
			object? value = pSprintAction.GetValue(walkerController, null);
			return (InputAction)((value is InputAction) ? value : null);
		}
		catch
		{
			return null;
		}
	}

	private static void InvokeToggleSprint(object walkerController, bool state)
	{
		if (walkerController == null || mToggleSprint == null)
		{
			return;
		}
		try
		{
			mToggleSprint.Invoke(walkerController, new object[1] { state });
		}
		catch (Exception ex)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogError((object)("Failed to invoke ToggleSprint: " + ex));
			}
		}
	}

	private static void CacheSafeMeleeAnimatorStateIfUseful(object weapon, string source)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		if (!IsMeleeWeapon(weapon))
		{
			return;
		}
		Animator animator = GetAnimator(weapon);
		if ((Object)(object)animator == (Object)null)
		{
			return;
		}
		AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(0);
		string currentClipName = GetCurrentClipName(animator);
		if (!IsSafeMeleeDrawClip(currentClipName))
		{
			return;
		}
		SafeAnimatorState value = SafeAnimatorStates.GetValue(weapon, (object _) => new SafeAnimatorState());
		value.FullPathHash = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash;
		value.ShortNameHash = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).shortNameHash;
		value.ClipName = currentClipName;
		value.Valid = true;
		if (LogStateChanges.Value)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)("Cached safe melee animator state from " + source + ": clip=" + currentClipName + " fullPathHash=" + ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash));
			}
		}
	}

	private static bool IsSafeMeleeDrawClip(string clipName)
	{
		if (string.IsNullOrEmpty(clipName))
		{
			return false;
		}
		if (ContainsIgnoreCase(clipName, "Slash"))
		{
			return false;
		}
		if (ContainsIgnoreCase(clipName, "Attack"))
		{
			return false;
		}
		if (ContainsIgnoreCase(clipName, "Fire"))
		{
			return false;
		}
		if (ContainsIgnoreCase(clipName, "ADS"))
		{
			return false;
		}
		if (ContainsIgnoreCase(clipName, "ToADS"))
		{
			return false;
		}
		if (ContainsIgnoreCase(clipName, "Charge") || ContainsIgnoreCase(clipName, "Charged"))
		{
			return false;
		}
		return ContainsIgnoreCase(clipName, "Equip");
	}

	private static bool ContainsIgnoreCase(string value, string part)
	{
		return value != null && part != null && value.IndexOf(part, StringComparison.OrdinalIgnoreCase) >= 0;
	}

	private static void PrepareMeleeAnimatorForFutureDraw(object weapon)
	{
		if (!ResetMeleeAnimatorBeforeSheathe.Value || !IsMeleeWeapon(weapon))
		{
			return;
		}
		try
		{
			InvokeSetAlternativeState(weapon, 0);
			if (fCurrentParries != null)
			{
				fCurrentParries.SetValue(weapon, 0);
			}
			Animator animator = GetAnimator(weapon);
			if ((Object)(object)animator == (Object)null)
			{
				return;
			}
			animator.SetBool("Charge", false);
			animator.SetBool("Sprinting", false);
			animator.SetBool("AlternativePressed", false);
			animator.ResetTrigger("Parry");
			if (!SafeAnimatorStates.TryGetValue(weapon, out var value) || value == null || !value.Valid)
			{
				CacheSafeMeleeAnimatorStateIfUseful(weapon, "PrepareMeleeAnimatorForFutureDraw fallback");
				if (!SafeAnimatorStates.TryGetValue(weapon, out value) || value == null || !value.Valid)
				{
					if (LogStateChanges.Value)
					{
						ManualLogSource log = Log;
						if (log != null)
						{
							log.LogInfo((object)("No cached safe melee animator state available for " + weapon));
						}
					}
					return;
				}
			}
			animator.Play(value.FullPathHash, 0, 0f);
			animator.Update(0f);
			if (LogStateChanges.Value)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogInfo((object)("Reset melee animator to safe draw state before sheathe: " + value.ClipName + " hash=" + value.FullPathHash));
				}
			}
		}
		catch (Exception ex)
		{
			ManualLogSource log3 = Log;
			if (log3 != null)
			{
				log3.LogError((object)("Failed to prepare melee animator for future draw: " + ex));
			}
		}
	}

	private static void CleanCurrentMeleeWeaponState(object currentHoldable)
	{
		if (!IsMeleeWeapon(currentHoldable))
		{
			return;
		}
		try
		{
			PrepareMeleeAnimatorForFutureDraw(currentHoldable);
		}
		catch (Exception ex)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogError((object)("Failed to clean melee weapon state: " + ex));
			}
		}
	}

	private static string GetCurrentClipName(Animator animator)
	{
		if ((Object)(object)animator == (Object)null)
		{
			return string.Empty;
		}
		try
		{
			AnimatorClipInfo[] currentAnimatorClipInfo = animator.GetCurrentAnimatorClipInfo(0);
			if (currentAnimatorClipInfo != null && currentAnimatorClipInfo.Length != 0 && (Object)(object)((AnimatorClipInfo)(ref currentAnimatorClipInfo[0])).clip != (Object)null)
			{
				return ((Object)((AnimatorClipInfo)(ref currentAnimatorClipInfo[0])).clip).name;
			}
		}
		catch
		{
			return string.Empty;
		}
		return string.Empty;
	}

	private static float ClampRetryInterval()
	{
		if (ReChargeRetryInterval == null)
		{
			return 0.08f;
		}
		float value = ReChargeRetryInterval.Value;
		if (float.IsNaN(value) || float.IsInfinity(value))
		{
			return 0.08f;
		}
		return Mathf.Clamp(value, 0.01f, 0.5f);
	}

	private static float GetDashCooldown()
	{
		return Mathf.Clamp(DashCooldown.Value, 0.1f, 60f);
	}

	private static float GetDashDistance()
	{
		return Mathf.Clamp(DashDistance.Value, 0.5f, 50f);
	}

	private static float GetDashDuration()
	{
		return Mathf.Clamp(DashDuration.Value, 0.03f, 2f);
	}

	private static float GetDashSpeed()
	{
		return GetDashDistance() / GetDashDuration();
	}

	private static float GetDashHitRadius()
	{
		return Mathf.Clamp(DashHitRadius.Value, 0.1f, 5f);
	}

	private static float GetEntityStatValue(object stats, object attribute, bool preferStatus)
	{
		if (stats == null || attribute == null)
		{
			return 0f;
		}
		if (preferStatus && mEntityStatsGetStatus != null)
		{
			try
			{
				object value = mEntityStatsGetStatus.Invoke(stats, new object[1] { attribute });
				return Convert.ToSingle(value);
			}
			catch
			{
			}
		}
		if (mEntityStatsGetAttribute != null)
		{
			try
			{
				object value2 = mEntityStatsGetAttribute.Invoke(stats, new object[1] { attribute });
				return Convert.ToSingle(value2);
			}
			catch
			{
			}
		}
		if (!preferStatus && mEntityStatsGetStatus != null)
		{
			try
			{
				object value3 = mEntityStatsGetStatus.Invoke(stats, new object[1] { attribute });
				return Convert.ToSingle(value3);
			}
			catch
			{
			}
		}
		return 0f;
	}

	private static float GetDashDamageMultiplier()
	{
		return Mathf.Clamp(DashDamageMultiplier.Value, 0f, 20f);
	}

	private static float GetHealAmountOnEnemyKill()
	{
		if (HealAmountOnEnemyKill == null)
		{
			return 5f;
		}
		float value = HealAmountOnEnemyKill.Value;
		if (float.IsNaN(value) || float.IsInfinity(value))
		{
			return 5f;
		}
		return Mathf.Clamp(value, 0f, 999f);
	}

	private static float GetDashPostHangDuration()
	{
		if (DashPostHangDuration == null)
		{
			return 0.12f;
		}
		float value = DashPostHangDuration.Value;
		if (float.IsNaN(value) || float.IsInfinity(value))
		{
			return 0.12f;
		}
		return Mathf.Clamp(value, 0f, 0.5f);
	}

	private static float GetDashPostHangMaxDownwardSpeed()
	{
		if (DashPostHangMaxDownwardSpeed == null)
		{
			return 0.5f;
		}
		float value = DashPostHangMaxDownwardSpeed.Value;
		if (float.IsNaN(value) || float.IsInfinity(value))
		{
			return 0.5f;
		}
		return Mathf.Clamp(value, 0f, 20f);
	}

	private static float GetDashKillRefreshFeedbackDuration()
	{
		if (DashKillRefreshFeedbackDuration == null)
		{
			return 0.45f;
		}
		float value = DashKillRefreshFeedbackDuration.Value;
		if (float.IsNaN(value) || float.IsInfinity(value))
		{
			return 0.45f;
		}
		return Mathf.Clamp(value, 0f, 3f);
	}

	private static float GetDashHealFeedbackDuration()
	{
		if (DashHealFeedbackDuration == null)
		{
			return 0.85f;
		}
		float value = DashHealFeedbackDuration.Value;
		if (float.IsNaN(value) || float.IsInfinity(value))
		{
			return 0.85f;
		}
		return Mathf.Clamp(value, 0f, 3f);
	}

	private static bool WasMeleePressedThisFrame(object equipmentManager)
	{
		InputAction inputAction = GetInputAction(fMeleeFireAction, equipmentManager);
		InputAction inputAction2 = GetInputAction(fMeleeFireActionAlternative, equipmentManager);
		return WasPerformedThisFrame(inputAction) || WasPerformedThisFrame(inputAction2);
	}

	private static bool IsMeleeHeld(object equipmentManager)
	{
		InputAction inputAction = GetInputAction(fMeleeFireAction, equipmentManager);
		InputAction inputAction2 = GetInputAction(fMeleeFireActionAlternative, equipmentManager);
		bool flag = inputAction != null && inputAction.IsPressed();
		bool flag2 = inputAction2 != null && inputAction2.IsPressed();
		return flag || flag2;
	}

	private static bool IsAltFirePressed(object equipmentManager)
	{
		InputAction inputAction = GetInputAction(fAltFireAction, equipmentManager);
		return inputAction != null && inputAction.IsPressed();
	}

	private static bool WasPerformedThisFrame(InputAction action)
	{
		return action != null && action.WasPerformedThisFrame();
	}

	private static InputAction GetInputAction(FieldInfo field, object instance)
	{
		if (field == null || instance == null)
		{
			return null;
		}
		object? value = field.GetValue(instance);
		return (InputAction)((value is InputAction) ? value : null);
	}

	private static object GetCurrentHoldable(object equipmentManager)
	{
		if (fCurrentHoldable == null || equipmentManager == null)
		{
			return null;
		}
		return fCurrentHoldable.GetValue(equipmentManager);
	}

	private static object GetEquipmentManagerFromWeapon(object weapon)
	{
		if (fEquipmentManager == null || weapon == null)
		{
			return null;
		}
		return fEquipmentManager.GetValue(weapon);
	}

	private static bool IsMeleeWeapon(object holdable)
	{
		if (holdable == null)
		{
			return false;
		}
		if (!weaponType.IsInstanceOfType(holdable))
		{
			return false;
		}
		object value = pIsMelee.GetValue(holdable, null);
		return value is bool && (bool)value;
	}

	private static bool IsMeleeCharging(object weapon)
	{
		if (weapon == null || mIsMeleeCharging == null)
		{
			return false;
		}
		object obj = mIsMeleeCharging.Invoke(weapon, null);
		return obj is bool && (bool)obj;
	}

	private static bool IsInMeleeCharge(object equipmentManager)
	{
		return GetBoolField(fIsInMeleeCharge, equipmentManager);
	}

	private static bool IsAimingInputHeld(object equipmentManager)
	{
		return GetBoolField(fAimingInputHeld, equipmentManager);
	}

	private static bool IsMeleeInputCoolingDown(object equipmentManager)
	{
		if (fMeleeInputCooldown == null || equipmentManager == null)
		{
			return false;
		}
		object value = fMeleeInputCooldown.GetValue(equipmentManager);
		if (!(value is float))
		{
			return false;
		}
		return Time.time < (float)value;
	}

	private static bool GetBoolField(FieldInfo field, object instance)
	{
		if (field == null || instance == null)
		{
			return false;
		}
		object value = field.GetValue(instance);
		return value is bool && (bool)value;
	}

	private static void SetMeleePressed(object equipmentManager, bool value)
	{
		SetBoolField(fMeleePressed, equipmentManager, value);
	}

	private static void SetAlternativeMeleePressed(object equipmentManager, bool value)
	{
		SetBoolField(fAlternativeMeleePressed, equipmentManager, value);
	}

	private static void SetBoolField(FieldInfo field, object instance, bool value)
	{
		if (!(field == null) && instance != null)
		{
			field.SetValue(instance, value);
		}
	}

	private static void UpdateCurrentMeleeAlternativeAnimator(object equipmentManager, bool altHeld)
	{
		object currentHoldable = GetCurrentHoldable(equipmentManager);
		if (IsMeleeWeapon(currentHoldable))
		{
			Animator animator = GetAnimator(currentHoldable);
			if (!((Object)(object)animator == (Object)null))
			{
				animator.SetBool("AlternativePressed", altHeld);
			}
		}
	}

	private static Animator GetAnimator(object holdable)
	{
		if (holdable == null || pAnimator == null)
		{
			return null;
		}
		object? value = pAnimator.GetValue(holdable, null);
		return (Animator)((value is Animator) ? value : null);
	}

	private static void InvokeChargeBasicMelee(object equipmentManager)
	{
		try
		{
			mChargeBasicMelee.Invoke(equipmentManager, null);
		}
		catch (Exception ex)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogError((object)("Failed to invoke ChargeBasicMelee: " + ex));
			}
		}
	}

	private static void InvokeUseBasicMelee(object equipmentManager)
	{
		try
		{
			mUseBasicMelee.Invoke(equipmentManager, null);
		}
		catch (Exception ex)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogError((object)("Failed to invoke UseBasicMelee: " + ex));
			}
		}
	}

	private static void InvokeOnMeleeDone(object equipmentManager)
	{
		try
		{
			mOnMeleeDone.Invoke(equipmentManager, null);
		}
		catch (Exception ex)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogError((object)("Failed to invoke OnMeleeDone: " + ex));
			}
		}
	}

	private static void InvokeSetAlternativeState(object weapon, int value)
	{
		if (weapon == null || mSetAlternativeState == null)
		{
			return;
		}
		try
		{
			mSetAlternativeState.Invoke(weapon, new object[1] { value });
		}
		catch (Exception ex)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogError((object)("Failed to invoke SetAlternativeState: " + ex));
			}
		}
	}

	private static object GetComponent(Component component, Type type)
	{
		if ((Object)(object)component == (Object)null || type == null)
		{
			return null;
		}
		return component.GetComponent(type);
	}

	private static bool IsPlayerUnit(object unit)
	{
		if (unit == null)
		{
			return false;
		}
		try
		{
			object obj = null;
			if (pUnitIsPlayer != null)
			{
				obj = pUnitIsPlayer.GetValue(unit, null);
			}
			else if (fUnitIsPlayer != null)
			{
				obj = fUnitIsPlayer.GetValue(unit);
			}
			return obj is bool && (bool)obj;
		}
		catch
		{
			return false;
		}
	}

	private static bool IsDeadUnit(object unit)
	{
		if (unit == null)
		{
			return true;
		}
		try
		{
			object obj = null;
			if (pUnitState != null)
			{
				obj = pUnitState.GetValue(unit, null);
			}
			else if (fUnitState != null)
			{
				obj = fUnitState.GetValue(unit);
			}
			if (obj == null)
			{
				return false;
			}
			return string.Equals(obj.ToString(), "Dead", StringComparison.OrdinalIgnoreCase);
		}
		catch
		{
			return false;
		}
	}

	private static bool IsProtectedNpc(object unit)
	{
		if (unit == null || npcType == null || pNpcIsProtectedNpc == null)
		{
			return false;
		}
		Component val = (Component)((unit is Component) ? unit : null);
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		Component component = val.GetComponent(npcType);
		if ((Object)(object)component == (Object)null)
		{
			return false;
		}
		try
		{
			object value = pNpcIsProtectedNpc.GetValue(component, null);
			return value is bool && (bool)value;
		}
		catch
		{
			return false;
		}
	}

	private static void DrawKatanaDashHud(KatanaDashState dashState, bool canUseDashNow)
	{
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0219: Unknown result type (might be due to invalid IL or missing references)
		//IL_0261: Unknown result type (might be due to invalid IL or missing references)
		//IL_0246: Unknown result type (might be due to invalid IL or missing references)
		//IL_02be: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02df: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0299: Unknown result type (might be due to invalid IL or missing references)
		//IL_0402: Unknown result type (might be due to invalid IL or missing references)
		//IL_0304: Unknown result type (might be due to invalid IL or missing references)
		//IL_031a: Unknown result type (might be due to invalid IL or missing references)
		//IL_034b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0361: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0447: Unknown result type (might be due to invalid IL or missing references)
		//IL_042c: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_047c: Unknown result type (might be due to invalid IL or missing references)
		//IL_049c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0520: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_050c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0555: Unknown result type (might be due to invalid IL or missing references)
		//IL_053a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0560: Unknown result type (might be due to invalid IL or missing references)
		//IL_059a: Unknown result type (might be due to invalid IL or missing references)
		//IL_057f: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_05cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_05c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d9: Unknown result type (might be due to invalid IL or missing references)
		EnsureDashHudTextures();
		float num = Mathf.Clamp(DashHudIconSize.Value, 48f, 128f);
		float num2 = num + 26f;
		float num3 = num + 42f;
		float num4 = (float)Screen.width - num2 - 34f;
		float num5 = (float)Screen.height - num3 - 34f;
		Rect rect = default(Rect);
		((Rect)(ref rect))..ctor(num4, num5, num2, num3);
		Rect val = default(Rect);
		((Rect)(ref val))..ctor(num4 + 13f, num5 + 10f, num, num);
		Rect rect2 = default(Rect);
		((Rect)(ref rect2))..ctor(num4 + 13f, num5 + 13f + num, num, 22f);
		float num6 = Mathf.Max(0f, dashState.NextDashTime - Time.time);
		float num7 = Mathf.Max(0.01f, GetDashCooldown());
		bool flag = num6 <= 0f && !dashState.IsDashing && canUseDashNow;
		float num8 = Mathf.Clamp01(num6 / num7);
		bool flag2 = Time.time < dashState.KillRefreshFeedbackEndTime;
		bool flag3 = Time.time < dashState.HealFeedbackEndTime;
		Color color = GUI.color;
		Color val2 = (flag2 ? new Color(0.45f, 1f, 0.55f, 1f) : new Color(0.95f, 0.95f, 0.9f, 0.85f));
		DrawRect(new Rect(((Rect)(ref rect)).x + 4f, ((Rect)(ref rect)).y + 4f, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), new Color(0f, 0f, 0f, 0.35f));
		DrawRect(rect, new Color(0.02f, 0.02f, 0.025f, 0.78f));
		DrawBorder(rect, flag2 ? 3f : 2f, (Color)(flag ? val2 : new Color(0.45f, 0.45f, 0.45f, 0.85f)));
		DrawBorder(new Rect(((Rect)(ref val)).x - 3f, ((Rect)(ref val)).y - 3f, ((Rect)(ref val)).width + 6f, ((Rect)(ref val)).height + 6f), flag2 ? 3f : 2f, flag2 ? new Color(0.3f, 1f, 0.45f, 1f) : new Color(0f, 0f, 0f, 0.9f));
		if ((Object)(object)DashIconTexture != (Object)null)
		{
			GUI.color = (Color)((flag || flag2) ? Color.white : new Color(0.55f, 0.55f, 0.55f, 1f));
			GUI.DrawTexture(val, (Texture)(object)DashIconTexture, (ScaleMode)2, true);
		}
		else
		{
			DrawRect(val, new Color(0.15f, 0.15f, 0.16f, 1f));
			DrawOutlinedLabel(val, "DASH", 18, Color.white, (TextAnchor)4);
		}
		if (!flag)
		{
			DrawRect(val, new Color(0f, 0f, 0f, 0.45f));
			Rect rect3 = default(Rect);
			((Rect)(ref rect3))..ctor(((Rect)(ref val)).x, ((Rect)(ref val)).y, ((Rect)(ref val)).width, ((Rect)(ref val)).height * num8);
			DrawRect(rect3, new Color(0f, 0f, 0f, 0.55f));
			DrawOutlinedLabel(text: (!(num6 > 0f)) ? "—" : ((!(num6 >= 1f)) ? num6.ToString("F1") : Mathf.CeilToInt(num6).ToString()), rect: val, fontSize: (num6 >= 1f) ? 34 : 28, color: (Color)(flag2 ? new Color(0.7f, 1f, 0.75f, 1f) : Color.white), alignment: (TextAnchor)4);
		}
		else
		{
			DrawBorder(val, flag2 ? 3f : 2f, flag2 ? new Color(0.35f, 1f, 0.45f, 1f) : new Color(0.75f, 1f, 0.85f, 0.95f));
		}
		if (flag2)
		{
			DrawOutlinedLabel(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y - 22f, ((Rect)(ref val)).width, 20f), "RESET", 14, new Color(0.45f, 1f, 0.55f, 1f), (TextAnchor)4);
		}
		if (flag3)
		{
			DrawOutlinedLabel(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y - 42f, ((Rect)(ref val)).width, 20f), "+" + dashState.HealFeedbackAmount.ToString("F0") + " HP", 15, new Color(0.45f, 1f, 0.55f, 1f), (TextAnchor)4);
		}
		string dashKeyLabel = GetDashKeyLabel();
		DrawRect(rect2, flag ? new Color(0.1f, 0.1f, 0.1f, 0.9f) : new Color(0.05f, 0.05f, 0.05f, 0.9f));
		DrawBorder(rect2, 1f, flag2 ? new Color(0.45f, 1f, 0.55f, 0.9f) : new Color(0.7f, 0.7f, 0.7f, 0.75f));
		DrawOutlinedLabel(rect2, dashKeyLabel, 14, (Color)((flag || flag2) ? Color.white : new Color(0.65f, 0.65f, 0.65f, 1f)), (TextAnchor)4);
		GUI.color = color;
	}

	private static void EnsureDashHudTextures()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Expected O, but got Unknown
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Expected O, but got Unknown
		if ((Object)(object)HudPixelTexture == (Object)null)
		{
			HudPixelTexture = new Texture2D(1, 1, (TextureFormat)4, false);
			((Object)HudPixelTexture).name = "MeleeExpansion_HudPixel";
			HudPixelTexture.SetPixel(0, 0, Color.white);
			HudPixelTexture.Apply(false, true);
		}
		if (DashIconLoadAttempted)
		{
			return;
		}
		DashIconLoadAttempted = true;
		try
		{
			string text = ((DashIconFileName != null) ? DashIconFileName.Value : "dash_icon.png");
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			string text2 = Path.Combine(PluginDirectory, text);
			if (!File.Exists(text2))
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("Dash icon PNG not found: " + text2));
				}
				return;
			}
			byte[] bytes = File.ReadAllBytes(text2);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			((Object)val).name = "MeleeExpansion_DashIcon";
			if (!LoadImageReflective(val, bytes, markNonReadable: false))
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("Failed to load dash icon PNG: " + text2));
				}
				Object.Destroy((Object)(object)val);
				return;
			}
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)1;
			DashIconTexture = val;
			if (LogDash != null && LogDash.Value)
			{
				ManualLogSource log3 = Log;
				if (log3 != null)
				{
					log3.LogInfo((object)("Loaded dash icon PNG: " + text2));
				}
			}
		}
		catch (Exception ex)
		{
			ManualLogSource log4 = Log;
			if (log4 != null)
			{
				log4.LogError((object)("Failed to load dash icon PNG: " + ex));
			}
		}
	}

	private static bool LoadImageReflective(Texture2D texture, byte[] bytes, bool markNonReadable)
	{
		if ((Object)(object)texture == (Object)null || bytes == null || bytes.Length == 0)
		{
			return false;
		}
		try
		{
			Type type = AccessTools.TypeByName("UnityEngine.ImageConversion");
			if (type == null)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogError((object)"Could not find UnityEngine.ImageConversion type.");
				}
				return false;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "LoadImage", new Type[3]
			{
				typeof(Texture2D),
				typeof(byte[]),
				typeof(bool)
			}, (Type[])null);
			if (methodInfo == null)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogError((object)"Could not find ImageConversion.LoadImage(Texture2D, byte[], bool).");
				}
				return false;
			}
			object obj = methodInfo.Invoke(null, new object[3] { texture, bytes, markNonReadable });
			return obj is bool && (bool)obj;
		}
		catch (Exception ex)
		{
			ManualLogSource log3 = Log;
			if (log3 != null)
			{
				log3.LogError((object)("Failed to load image through reflection: " + ex));
			}
			return false;
		}
	}

	private static void DrawRect(Rect rect, Color color)
	{
		//IL_0012: 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_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)HudPixelTexture == (Object)null))
		{
			Color color2 = GUI.color;
			GUI.color = color;
			GUI.DrawTexture(rect, (Texture)(object)HudPixelTexture);
			GUI.color = color2;
		}
	}

	private static void DrawBorder(Rect rect, float thickness, Color color)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: 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_0062: 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_0086: Unknown result type (might be due to invalid IL or missing references)
		DrawRect(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, thickness), color);
		DrawRect(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - thickness, ((Rect)(ref rect)).width, thickness), color);
		DrawRect(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color);
		DrawRect(new Rect(((Rect)(ref rect)).xMax - thickness, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color);
	}

	private static void DrawOutlinedLabel(Rect rect, string text, int fontSize, Color color, TextAnchor alignment)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0012: 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_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Expected O, but got Unknown
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: 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_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		GUIStyle val = new GUIStyle(GUI.skin.label);
		val.alignment = alignment;
		val.fontSize = fontSize;
		val.fontStyle = (FontStyle)1;
		val.normal.textColor = color;
		GUIStyle val2 = new GUIStyle(val);
		val2.normal.textColor = Color.black;
		Rect val3 = rect;
		((Rect)(ref val3)).x = ((Rect)(ref val3)).x - 1f;
		GUI.Label(val3, text, val2);
		val3 = rect;
		((Rect)(ref val3)).x = ((Rect)(ref val3)).x + 1f;
		GUI.Label(val3, text, val2);
		val3 = rect;
		((Rect)(ref val3)).y = ((Rect)(ref val3)).y - 1f;
		GUI.Label(val3, text, val2);
		val3 = rect;
		((Rect)(ref val3)).y = ((Rect)(ref val3)).y + 1f;
		GUI.Label(val3, text, val2);
		GUI.Label(rect, text, val);
	}

	private static string GetDashKeyLabel()
	{
		if (DashHudUseActualSprintBinding != null && DashHudUseActualSprintBinding.Value && lastKnownWalkerController != null)
		{
			try
			{
				InputAction sprintAction = GetSprintAction(lastKnownWalkerController);
				if (sprintAction != null)
				{
					string bindingDisplayString = InputActionRebindingExtensions.GetBindingDisplayString(sprintAction, (DisplayStringOptions)0, (string)null);
					if (!string.IsNullOrEmpty(bindingDisplayString))
					{
						return bindingDisplayString.ToUpperInvariant();
					}
				}
			}
			catch
			{
			}
		}
		if (DashHudFallbackKeyLabel != null && !string.IsNullOrEmpty(DashHudFallbackKeyLabel.Value))
		{
			return DashHudFallbackKeyLabel.Value.ToUpperInvariant();
		}
		return "SPRINT";
	}
}