Decompiled source of ShieldBash v1.5.2

BepInEx/plugins/ShieldBash/ShieldBash.dll

Decompiled a week ago
using System;
using System.Collections;
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 HarmonyLib;
using Jotunn.Configs;
using Jotunn.Managers;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Playables;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ShieldBash")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ShieldBash")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("be1580d5-2dda-4cf4-b5c8-d4f902314e67")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ShieldBashMod;

[BepInPlugin("alexbez.valheim.shieldbash", "ShieldBash", "2.2.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class ShieldBashPlugin : BaseUnityPlugin
{
	[CompilerGenerated]
	private sealed class <AntiSlideRoutine>d__76 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public Player player;

		public float duration;

		public ShieldBashPlugin <>4__this;

		private Rigidbody <body>5__1;

		private float <t>5__2;

		private Vector3 <v>5__3;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <AntiSlideRoutine>d__76(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<body>5__1 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_00a6: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				if (!Object.op_Implicit((Object)(object)player))
				{
					return false;
				}
				<body>5__1 = null;
				try
				{
					<body>5__1 = CharacterBody.Invoke((Character)(object)player);
				}
				catch
				{
				}
				if (!Object.op_Implicit((Object)(object)<body>5__1))
				{
					return false;
				}
				<t>5__2 = 0f;
				try
				{
					CharacterMoveDir.Invoke((Character)(object)player) = Vector3.zero;
				}
				catch
				{
				}
				<body>5__1.linearVelocity = Vector3.zero;
				break;
			case 1:
				<>1__state = -1;
				break;
			}
			if (<t>5__2 < duration && Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)<body>5__1))
			{
				<v>5__3 = <body>5__1.linearVelocity;
				<v>5__3.x = 0f;
				<v>5__3.z = 0f;
				<body>5__1.linearVelocity = <v>5__3;
				try
				{
					CharacterMoveDir.Invoke((Character)(object)player) = Vector3.zero;
				}
				catch
				{
				}
				<t>5__2 += Time.deltaTime;
				<>2__current = null;
				<>1__state = 1;
				return true;
			}
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	[CompilerGenerated]
	private sealed class <DoBash>d__75 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public Player player;

		public Animator animator;

		public AnimationClip clip;

		public ShieldBashPlugin <>4__this;

		private bool <prevRootMotion>5__1;

		private PlayableGraph <graph>5__2;

		private AnimatorControllerPlayable <controllerPlayable>5__3;

		private AnimationClipPlayable <clipPlayable>5__4;

		private AnimationLayerMixerPlayable <mixer>5__5;

		private AnimationPlayableOutput <output>5__6;

		private float <hitAt>5__7;

		private float <remain>5__8;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <DoBash>d__75(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			int num = <>1__state;
			if (num == -3 || (uint)(num - 1) <= 1u)
			{
				try
				{
				}
				finally
				{
					<>m__Finally1();
				}
			}
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Expected O, but got Unknown
			try
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (<>4__this.AntiSlideTime.Value > 0.0001f)
					{
						((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.AntiSlideRoutine(player, <>4__this.AntiSlideTime.Value));
					}
					<prevRootMotion>5__1 = animator.applyRootMotion;
					animator.applyRootMotion = false;
					<graph>5__2 = PlayableGraph.Create("ShieldBashGraph");
					<>1__state = -3;
					<controllerPlayable>5__3 = AnimatorControllerPlayable.Create(<graph>5__2, animator.runtimeAnimatorController);
					<clipPlayable>5__4 = AnimationClipPlayable.Create(<graph>5__2, clip);
					((AnimationClipPlayable)(ref <clipPlayable>5__4)).SetApplyFootIK(false);
					((AnimationClipPlayable)(ref <clipPlayable>5__4)).SetApplyPlayableIK(false);
					<mixer>5__5 = AnimationLayerMixerPlayable.Create(<graph>5__2, 2);
					((PlayableGraph)(ref <graph>5__2)).Connect<AnimatorControllerPlayable, AnimationLayerMixerPlayable>(<controllerPlayable>5__3, 0, <mixer>5__5, 0);
					((PlayableGraph)(ref <graph>5__2)).Connect<AnimationClipPlayable, AnimationLayerMixerPlayable>(<clipPlayable>5__4, 0, <mixer>5__5, 1);
					PlayableExtensions.SetInputWeight<AnimationLayerMixerPlayable>(<mixer>5__5, 0, 1f);
					PlayableExtensions.SetInputWeight<AnimationLayerMixerPlayable>(<mixer>5__5, 1, 1f);
					<output>5__6 = AnimationPlayableOutput.Create(<graph>5__2, "ShieldBashOutput", animator);
					PlayableOutputExtensions.SetSourcePlayable<AnimationPlayableOutput, AnimationLayerMixerPlayable>(<output>5__6, <mixer>5__5);
					((PlayableGraph)(ref <graph>5__2)).Play();
					<hitAt>5__7 = Mathf.Clamp(<>4__this.HitDelay.Value, 0.01f, Mathf.Max(0.01f, clip.length));
					<>2__current = (object)new WaitForSeconds(<hitAt>5__7);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -3;
					<>4__this.ApplyBashDamageAndSfx(player);
					<remain>5__8 = Mathf.Max(0.01f, clip.length - <hitAt>5__7);
					<>2__current = (object)new WaitForSeconds(<remain>5__8);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -3;
					<>m__Finally1();
					return false;
				}
			}
			catch
			{
				//try-fault
				((IDisposable)this).Dispose();
				throw;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		private void <>m__Finally1()
		{
			<>1__state = -1;
			if (((PlayableGraph)(ref <graph>5__2)).IsValid())
			{
				((PlayableGraph)(ref <graph>5__2)).Destroy();
			}
			animator.applyRootMotion = <prevRootMotion>5__1;
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	public const string PluginGUID = "alexbez.valheim.shieldbash";

	public const string PluginName = "ShieldBash";

	public const string PluginVersion = "2.2.0";

	private const string ButtonName = "ShieldBash";

	internal static ShieldBashPlugin Instance;

	internal ConfigEntry<KeyCode> BashKey;

	internal ConfigEntry<float> Cooldown;

	internal ConfigEntry<bool> RequireShield;

	internal ConfigEntry<float> StaminaCost;

	internal ConfigEntry<float> AntiSlideTime;

	internal ConfigEntry<float> BaseDamage;

	internal ConfigEntry<float> BlockPowerScale;

	internal ConfigEntry<float> QualityBonusPerLevel;

	internal ConfigEntry<float> MinDamage;

	internal ConfigEntry<float> MaxDamage;

	internal ConfigEntry<float> BlockingSkillMultiplier;

	internal ConfigEntry<float> DamageRandomMin;

	internal ConfigEntry<float> DamageRandomMax;

	internal ConfigEntry<float> CenterHitBonusMax;

	internal ConfigEntry<float> HitDelay;

	internal ConfigEntry<float> Range;

	internal ConfigEntry<float> Radius;

	internal ConfigEntry<float> PushForce;

	internal ConfigEntry<float> Angle;

	internal ConfigEntry<bool> LineOfSightCheck;

	internal ConfigEntry<int> MaxLoSRaycastsPerBash;

	internal ConfigEntry<bool> HitTamed;

	internal ConfigEntry<bool> HitPlayers;

	internal ConfigEntry<int> OverlapBufferSize;

	internal ConfigEntry<bool> ShowShieldBashInTooltip;

	internal ConfigEntry<bool> DebugLog;

	internal ConfigEntry<bool> DebugLogDamageAfterArmor;

	internal ConfigEntry<bool> DamageWorldObjects;

	internal ConfigEntry<float> WorldDamageScale;

	internal ConfigEntry<bool> WorldDamageUseRandom;

	internal ConfigEntry<string> HitClipName;

	internal ConfigEntry<string> MissClipName;

	internal ConfigEntry<bool> PlayHitSfxPerTarget;

	internal ConfigEntry<float> HitSfxVolumeMin;

	internal ConfigEntry<float> HitSfxVolumeMax;

	internal ConfigEntry<float> MissSfxVolume;

	internal ConfigEntry<float> RandomVolJitterMin;

	internal ConfigEntry<float> RandomVolJitterMax;

	internal ConfigEntry<float> RandomPitchJitterMin;

	internal ConfigEntry<float> RandomPitchJitterMax;

	internal ConfigEntry<float> MetalVolumeMul;

	internal ConfigEntry<float> WoodVolumeMul;

	internal ConfigEntry<float> MetalPitchMul;

	internal ConfigEntry<float> WoodPitchMul;

	internal ConfigEntry<float> MultiHitBonusMin;

	internal ConfigEntry<float> MultiHitBonusMax;

	internal ConfigEntry<float> LocalClipVolumeMul;

	private ButtonConfig _bashButton;

	private Harmony _harmony;

	private AnimationClip _bashClip;

	private AudioClip _hitClip;

	private AudioClip _missClip;

	private float _nextUseTime;

	private Collider[] _overlapCols;

	private int[] _hitOnceIds;

	private int _hitOnceCount;

	private int _overlapMask = -1;

	private int _losWorldMask = -1;

	private int _losCharMask = -1;

	private float _cachedAngle = -999f;

	private float _cachedCosHalf = -2f;

	private AudioSource _localSfxSource;

	private static readonly FieldRef<Character, Animator> CharacterAnimator = AccessTools.FieldRefAccess<Character, Animator>("m_animator");

	private static readonly FieldRef<Character, Rigidbody> CharacterBody = AccessTools.FieldRefAccess<Character, Rigidbody>("m_body");

	private static readonly FieldRef<Character, Vector3> CharacterMoveDir = AccessTools.FieldRefAccess<Character, Vector3>("m_moveDir");

	private static readonly FieldRef<Humanoid, ItemData> HumanoidLeftItem = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_leftItem");

	private void Awake()
	{
		//IL_06a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_06a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_06b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_06b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_06c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d5: Expected O, but got Unknown
		//IL_06f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0702: Expected O, but got Unknown
		Instance = this;
		BashKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Input", "BashKey", (KeyCode)102, "Key for Shield Bash");
		Cooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "Cooldown", 0.9f, "Cooldown seconds");
		RequireShield = ((BaseUnityPlugin)this).Config.Bind<bool>("Balance", "RequireShield", true, "Require shield in left hand");
		StaminaCost = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "StaminaCost", 18f, "Stamina cost per bash (no message if insufficient)");
		AntiSlideTime = ((BaseUnityPlugin)this).Config.Bind<float>("Feel", "AntiSlideTime", 0.2f, "Anti-slide duration seconds (0 = off)");
		BaseDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "BaseDamage", 10f, "Flat blunt damage added to bash");
		BlockPowerScale = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "BlockPowerScale", 0.6f, "Damage per 1 shield block power");
		QualityBonusPerLevel = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "QualityBonusPerLevel", 0.8f, "Soft bonus damage per shield upgrade level (quality-1)");
		MinDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "MinDamage", 6f, "Minimum final damage (after multipliers)");
		MaxDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "MaxDamage", 45f, "Maximum final damage cap (after multipliers)");
		BlockingSkillMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "BlockingSkillMultiplier", 0.35f, "Damage multiplier from Blocking skill: damage *= 1 + skillFactor(0..1) * value");
		DamageRandomMin = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "DamageRandomMin", 0.92f, "Per-bash random damage multiplier min (vanilla-like variability).");
		DamageRandomMax = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "DamageRandomMax", 1.08f, "Per-bash random damage multiplier max (vanilla-like variability).");
		CenterHitBonusMax = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "CenterHitBonusMax", 0.12f, "Up to +X% damage when target is centered in cone.");
		HitDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "HitDelay", 0.12f, "Seconds after animation start when damage is applied");
		DamageWorldObjects = ((BaseUnityPlugin)this).Config.Bind<bool>("WorldDamage", "DamageWorldObjects", true, "Allow Shield Bash to damage trees/rocks/buildings like vanilla weapons");
		WorldDamageScale = ((BaseUnityPlugin)this).Config.Bind<float>("WorldDamage", "WorldDamageScale", 0.85f, "Multiplier for world-object damage (trees/rocks/buildings).");
		WorldDamageUseRandom = ((BaseUnityPlugin)this).Config.Bind<bool>("WorldDamage", "WorldDamageUseRandom", false, "If true: world damage also uses per-bash random multiplier (default false).");
		Range = ((BaseUnityPlugin)this).Config.Bind<float>("Hitbox", "Range", 1.6f, "Forward distance of hit center");
		Radius = ((BaseUnityPlugin)this).Config.Bind<float>("Hitbox", "Radius", 0.9f, "Hit radius (capsule radius)");
		PushForce = ((BaseUnityPlugin)this).Config.Bind<float>("Hitbox", "PushForce", 20f, "Push force applied to Characters");
		Angle = ((BaseUnityPlugin)this).Config.Bind<float>("Hitbox", "AngleDegrees", 110f, "Cone angle filter (degrees). 180 = no cone.");
		LineOfSightCheck = ((BaseUnityPlugin)this).Config.Bind<bool>("Hitbox", "LineOfSightCheck", true, "Raycast visibility check (avoid hitting through walls)");
		MaxLoSRaycastsPerBash = ((BaseUnityPlugin)this).Config.Bind<int>("Hitbox", "MaxLoSRaycastsPerBash", 6, "Max LoS raycasts per bash (CPU saver in crowds).");
		HitTamed = ((BaseUnityPlugin)this).Config.Bind<bool>("Targets", "HitTamed", false, "Hit tamed creatures");
		HitPlayers = ((BaseUnityPlugin)this).Config.Bind<bool>("Targets", "HitPlayers", false, "Hit other players (PvP)");
		OverlapBufferSize = ((BaseUnityPlugin)this).Config.Bind<int>("Performance", "OverlapBufferSize", 64, "NonAlloc overlap collider buffer size (64/96/128)");
		ShowShieldBashInTooltip = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "ShowShieldBashInTooltip", true, "Add Shield Bash damage lines near block power in shield tooltip");
		DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Log", false, "General debug logging");
		DebugLogDamageAfterArmor = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogDamageAfterArmor", false, "Log actual dealt damage (HP delta) per hit target");
		HitClipName = ((BaseUnityPlugin)this).Config.Bind<string>("SFX", "HitClipName", "shield_bash_hit", "AudioClip.name inside AssetBundle for HIT sound.");
		MissClipName = ((BaseUnityPlugin)this).Config.Bind<string>("SFX", "MissClipName", "shield_bash_miss", "AudioClip.name inside AssetBundle for MISS sound.");
		PlayHitSfxPerTarget = ((BaseUnityPlugin)this).Config.Bind<bool>("SFX", "PlayHitSfxPerTarget", false, "If true: play hit sound for each target (heavier).");
		HitSfxVolumeMin = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "HitSfxVolumeMin", 0.6f, "Min hit volume at MinDamage.");
		HitSfxVolumeMax = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "HitSfxVolumeMax", 1.1f, "Max hit volume at MaxDamage.");
		MissSfxVolume = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "MissSfxVolume", 0.7f, "Base miss whoosh volume.");
		RandomVolJitterMin = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "RandomVolJitterMin", 0.95f, "Random volume multiplier min.");
		RandomVolJitterMax = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "RandomVolJitterMax", 1.05f, "Random volume multiplier max.");
		RandomPitchJitterMin = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "RandomPitchJitterMin", 0.97f, "Random pitch multiplier min.");
		RandomPitchJitterMax = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "RandomPitchJitterMax", 1.03f, "Random pitch multiplier max.");
		MetalVolumeMul = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "MetalVolumeMul", 1.07f, "Volume multiplier for metal shields.");
		WoodVolumeMul = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "WoodVolumeMul", 0.92f, "Volume multiplier for wood shields.");
		MetalPitchMul = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "MetalPitchMul", 1.02f, "Pitch multiplier for metal shields.");
		WoodPitchMul = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "WoodPitchMul", 0.96f, "Pitch multiplier for wood shields.");
		MultiHitBonusMin = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "MultiHitBonusMin", 0.05f, "Bonus volume add when hits>1, min.");
		MultiHitBonusMax = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "MultiHitBonusMax", 0.1f, "Bonus volume add when hits>1, max.");
		LocalClipVolumeMul = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "LocalClipVolumeMul", 1f, "Multiplier for local AudioClips.");
		_bashButton = new ButtonConfig
		{
			Name = "ShieldBash",
			Key = BashKey.Value,
			HintToken = "Shield Bash"
		};
		InputManager.Instance.AddButton("alexbez.valheim.shieldbash", _bashButton);
		EnsureBuffers();
		_harmony = new Harmony("alexbez.valheim.shieldbash");
		_harmony.PatchAll();
		bool flag = LoadAssetsFromBundle();
		((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("[{0}] Assets loaded: {1} (anim={2}, hit={3}, miss={4})", "ShieldBash", flag, Object.op_Implicit((Object)(object)_bashClip) ? ((Object)_bashClip).name : "null", Object.op_Implicit((Object)(object)_hitClip) ? ((Object)_hitClip).name : "null", Object.op_Implicit((Object)(object)_missClip) ? ((Object)_missClip).name : "null"));
	}

	private void OnDestroy()
	{
		try
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
		catch
		{
		}
		try
		{
			if (Object.op_Implicit((Object)(object)_localSfxSource) && Object.op_Implicit((Object)(object)((Component)_localSfxSource).gameObject))
			{
				Object.Destroy((Object)(object)((Component)_localSfxSource).gameObject);
			}
		}
		catch
		{
		}
	}

	private void EnsureBuffers()
	{
		int num = Mathf.Clamp(OverlapBufferSize.Value, 16, 256);
		if (_overlapCols == null || _overlapCols.Length != num)
		{
			_overlapCols = (Collider[])(object)new Collider[num];
		}
		int num2 = Mathf.Clamp(num * 2, 32, 1024);
		if (_hitOnceIds == null || _hitOnceIds.Length != num2)
		{
			_hitOnceIds = new int[num2];
		}
		_hitOnceCount = 0;
	}

	private void Update()
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		EnsureBuffers();
		if (!Input.GetKeyDown(BashKey.Value))
		{
			return;
		}
		Player localPlayer = Player.m_localPlayer;
		if (!Object.op_Implicit((Object)(object)localPlayer) || Time.time < _nextUseTime)
		{
			return;
		}
		if ((Object)(object)_bashClip == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"[ShieldBash] Bash clip is null. Bundle/clip not loaded.");
		}
		else if ((!RequireShield.Value || HasShieldInLeftHand(localPlayer)) && TryUseStaminaNoMessage(localPlayer, StaminaCost.Value))
		{
			Animator animator = GetAnimator((Character)(object)localPlayer);
			if (Object.op_Implicit((Object)(object)animator))
			{
				_nextUseTime = Time.time + Cooldown.Value;
				((MonoBehaviour)this).StartCoroutine(DoBash(localPlayer, animator, _bashClip));
			}
		}
	}

	[IteratorStateMachine(typeof(<DoBash>d__75))]
	private IEnumerator DoBash(Player player, Animator animator, AnimationClip clip)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <DoBash>d__75(0)
		{
			<>4__this = this,
			player = player,
			animator = animator,
			clip = clip
		};
	}

	[IteratorStateMachine(typeof(<AntiSlideRoutine>d__76))]
	private IEnumerator AntiSlideRoutine(Player player, float duration)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <AntiSlideRoutine>d__76(0)
		{
			<>4__this = this,
			player = player,
			duration = duration
		};
	}

	private bool TryUseStaminaNoMessage(Player player, float cost)
	{
		if (cost <= 0f)
		{
			return true;
		}
		if (player.GetStamina() + 0.001f < cost)
		{
			return false;
		}
		((Character)player).UseStamina(cost);
		return true;
	}

	internal float ComputeShieldBaseDamage(ItemData shield)
	{
		int num = 1;
		float num2 = 0f;
		if (shield != null && shield.m_shared != null)
		{
			num = Mathf.Max(1, shield.m_quality);
			num2 = shield.m_shared.m_blockPower + shield.m_shared.m_blockPowerPerLevel * (float)(num - 1);
		}
		return BaseDamage.Value + num2 * BlockPowerScale.Value + (float)Mathf.Max(0, num - 1) * Mathf.Max(0f, QualityBonusPerLevel.Value);
	}

	private float GetBlockingSkillFactor(Player player)
	{
		if (!Object.op_Implicit((Object)(object)player))
		{
			return 0f;
		}
		try
		{
			return Mathf.Clamp01(((Character)player).GetSkillFactor((SkillType)6));
		}
		catch
		{
			return 0f;
		}
	}

	private float ApplySkillAndRandom(float baseDamage, float skillFactor, float randMul)
	{
		float num = Mathf.Max(0f, BlockingSkillMultiplier.Value);
		float num2 = baseDamage * (1f + skillFactor * num);
		num2 *= randMul;
		return Mathf.Clamp(num2, MinDamage.Value, MaxDamage.Value);
	}

	private float GetCenterBonus01(float dotForward, float cosHalf)
	{
		if (dotForward <= cosHalf)
		{
			return 0f;
		}
		if (cosHalf >= 0.9999f)
		{
			return 1f;
		}
		return Mathf.Clamp01((dotForward - cosHalf) / (1f - cosHalf));
	}

	private int GetOverlapMask()
	{
		if (_overlapMask != -1)
		{
			return _overlapMask;
		}
		_overlapMask = LayerMask.GetMask(new string[7] { "character", "character_net", "Default", "static_solid", "piece", "Hitbox", "hitbox" });
		if (_overlapMask == 0)
		{
			_overlapMask = -1;
		}
		return _overlapMask;
	}

	private int GetWorldLosMask()
	{
		if (_losWorldMask != -1)
		{
			return _losWorldMask;
		}
		_losWorldMask = LayerMask.GetMask(new string[7] { "Default", "static_solid", "piece", "Hitbox", "hitbox", "character", "character_net" });
		if (_losWorldMask == 0)
		{
			_losWorldMask = -1;
		}
		return _losWorldMask;
	}

	private int GetCharacterOnlyLosMask()
	{
		if (_losCharMask != -1)
		{
			return _losCharMask;
		}
		_losCharMask = LayerMask.GetMask(new string[4] { "character", "character_net", "Hitbox", "hitbox" });
		if (_losCharMask == 0)
		{
			_losCharMask = -1;
		}
		return _losCharMask;
	}

	private float GetCosHalfAngle()
	{
		float num = Mathf.Clamp(Angle.Value, 1f, 180f);
		if (Mathf.Abs(num - _cachedAngle) < 0.001f && _cachedCosHalf > -1f)
		{
			return _cachedCosHalf;
		}
		_cachedAngle = num;
		_cachedCosHalf = Mathf.Cos(num * ((float)Math.PI / 180f) * 0.5f);
		return _cachedCosHalf;
	}

	private void HitOnceReset()
	{
		_hitOnceCount = 0;
	}

	private bool HitOnceTryAdd(int id)
	{
		for (int i = 0; i < _hitOnceCount; i++)
		{
			if (_hitOnceIds[i] == id)
			{
				return false;
			}
		}
		if (_hitOnceCount >= _hitOnceIds.Length)
		{
			return false;
		}
		_hitOnceIds[_hitOnceCount++] = id;
		return true;
	}

	private void ApplyBashDamageAndSfx(Player player)
	{
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_01df: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0221: Unknown result type (might be due to invalid IL or missing references)
		//IL_0223: Unknown result type (might be due to invalid IL or missing references)
		//IL_0243: Unknown result type (might be due to invalid IL or missing references)
		//IL_0245: Unknown result type (might be due to invalid IL or missing references)
		//IL_07bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_07c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_07d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_07d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_07da: Unknown result type (might be due to invalid IL or missing references)
		//IL_07e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_07e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_081d: Unknown result type (might be due to invalid IL or missing references)
		//IL_066c: Unknown result type (might be due to invalid IL or missing references)
		//IL_066e: Unknown result type (might be due to invalid IL or missing references)
		//IL_07a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_069b: Unknown result type (might be due to invalid IL or missing references)
		//IL_069d: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_034e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0353: Unknown result type (might be due to invalid IL or missing references)
		//IL_035d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0362: Unknown result type (might be due to invalid IL or missing references)
		//IL_0367: Unknown result type (might be due to invalid IL or missing references)
		//IL_0369: Unknown result type (might be due to invalid IL or missing references)
		//IL_036b: Unknown result type (might be due to invalid IL or missing references)
		//IL_036d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0372: Unknown result type (might be due to invalid IL or missing references)
		//IL_0391: Unknown result type (might be due to invalid IL or missing references)
		//IL_0395: Unknown result type (might be due to invalid IL or missing references)
		//IL_039a: Unknown result type (might be due to invalid IL or missing references)
		//IL_039c: Unknown result type (might be due to invalid IL or missing references)
		//IL_039e: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_0497: 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_04a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_04cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04db: Unknown result type (might be due to invalid IL or missing references)
		//IL_04dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_04de: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0500: Unknown result type (might be due to invalid IL or missing references)
		//IL_0504: Unknown result type (might be due to invalid IL or missing references)
		//IL_0509: Unknown result type (might be due to invalid IL or missing references)
		//IL_050e: Unknown result type (might be due to invalid IL or missing references)
		//IL_051f: Unknown result type (might be due to invalid IL or missing references)
		//IL_052c: Expected O, but got Unknown
		//IL_04c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0603: Unknown result type (might be due to invalid IL or missing references)
		//IL_0605: Unknown result type (might be due to invalid IL or missing references)
		//IL_0640: Unknown result type (might be due to invalid IL or missing references)
		HitOnceReset();
		ItemData leftItem = GetLeftItem((Humanoid)(object)player);
		float num = ComputeShieldBaseDamage(leftItem);
		float num2 = Mathf.Min(DamageRandomMin.Value, DamageRandomMax.Value);
		float num3 = Mathf.Max(DamageRandomMin.Value, DamageRandomMax.Value);
		float num4 = Random.Range(num2, num3);
		float blockingSkillFactor = GetBlockingSkillFactor(player);
		float num5 = ApplySkillAndRandom(num, blockingSkillFactor, num4);
		float randMul = (WorldDamageUseRandom.Value ? num4 : 1f);
		float num6 = ApplySkillAndRandom(num, blockingSkillFactor, randMul) * Mathf.Clamp(WorldDamageScale.Value, 0f, 5f);
		float num7 = Mathf.Clamp01(Mathf.InverseLerp(MinDamage.Value, MaxDamage.Value, num5));
		float num8 = Mathf.Lerp(HitSfxVolumeMin.Value, HitSfxVolumeMax.Value, num7);
		float num9 = Mathf.Max(0f, MissSfxVolume.Value);
		GetMaterialMix(leftItem, out var volMul, out var pitchMul);
		float num10 = Random.Range(Mathf.Min(RandomVolJitterMin.Value, RandomVolJitterMax.Value), Mathf.Max(RandomVolJitterMin.Value, RandomVolJitterMax.Value));
		float num11 = Random.Range(Mathf.Min(RandomPitchJitterMin.Value, RandomPitchJitterMax.Value), Mathf.Max(RandomPitchJitterMin.Value, RandomPitchJitterMax.Value));
		Vector3 forward = ((Component)player).transform.forward;
		Vector3 val = ((Component)player).transform.position + Vector3.up * 1.3f;
		Vector3 val2 = ((Component)player).transform.position + forward * Range.Value;
		Vector3 val3 = val2 + Vector3.up * 0.6f;
		Vector3 val4 = val2 + Vector3.up * 1.6f;
		int overlapMask = GetOverlapMask();
		float cosHalfAngle = GetCosHalfAngle();
		int num12 = Physics.OverlapCapsuleNonAlloc(val3, val4, Radius.Value, _overlapCols, overlapMask, (QueryTriggerInteraction)2);
		int num13 = 0;
		Vector3 pos = val;
		int losChecks = 0;
		int num14 = Mathf.Clamp(MaxLoSRaycastsPerBash.Value, 0, 64);
		float num15 = Mathf.Clamp(CenterHitBonusMax.Value, 0f, 1f);
		RaycastHit val9 = default(RaycastHit);
		for (int i = 0; i < num12; i++)
		{
			Collider val5 = _overlapCols[i];
			if (!Object.op_Implicit((Object)(object)val5))
			{
				continue;
			}
			Character componentInParent = ((Component)val5).GetComponentInParent<Character>();
			Vector3 hitPoint;
			if ((Object)(object)componentInParent != (Object)null)
			{
				if ((Object)(object)componentInParent == (Object)(object)player || componentInParent.IsDead())
				{
					continue;
				}
				if (!HitTamed.Value)
				{
					Tameable component = ((Component)componentInParent).GetComponent<Tameable>();
					if ((Object)(object)component != (Object)null && component.IsTamed())
					{
						continue;
					}
				}
				if (!HitPlayers.Value && componentInParent is Player)
				{
					continue;
				}
				Vector3 val6 = ((Component)componentInParent).transform.position + Vector3.up * 1.1f;
				Vector3 val7 = val6 - val;
				float magnitude = ((Vector3)(ref val7)).magnitude;
				if (magnitude < 0.001f)
				{
					continue;
				}
				Vector3 val8 = val7 / magnitude;
				float num16 = Vector3.Dot(forward, val8);
				if (num16 < cosHalfAngle)
				{
					continue;
				}
				if (LineOfSightCheck.Value && num14 > 0 && losChecks < num14)
				{
					losChecks++;
					int characterOnlyLosMask = GetCharacterOnlyLosMask();
					if (Physics.Raycast(val, val8, ref val9, magnitude, characterOnlyLosMask, (QueryTriggerInteraction)1))
					{
						Character val10 = (Object.op_Implicit((Object)(object)((RaycastHit)(ref val9)).collider) ? ((Component)((RaycastHit)(ref val9)).collider).GetComponentInParent<Character>() : null);
						if ((Object)(object)val10 != (Object)(object)componentInParent)
						{
							continue;
						}
					}
				}
				if (HitOnceTryAdd(((Object)((Component)componentInParent).gameObject).GetInstanceID()))
				{
					float centerBonus = GetCenterBonus01(num16, cosHalfAngle);
					float num17 = 1f + centerBonus * num15;
					float blunt = Mathf.Clamp(num5 * num17, MinDamage.Value, MaxDamage.Value);
					Vector3 val11 = val5.ClosestPoint(((Component)player).transform.position + forward * 0.5f);
					if (val11 == Vector3.zero)
					{
						val11 = val6;
					}
					HitData val12 = new HitData
					{
						m_attacker = ((Character)player).GetZDOID(),
						m_point = val11
					};
					Vector3 val13 = ((Component)componentInParent).transform.position - ((Component)player).transform.position;
					val12.m_dir = ((Vector3)(ref val13)).normalized;
					val12.m_pushForce = PushForce.Value;
					val12.m_backstabBonus = 1f;
					HitData val14 = val12;
					val14.m_damage.m_blunt = blunt;
					float num18 = 0f;
					if (DebugLogDamageAfterArmor.Value)
					{
						num18 = componentInParent.GetHealth();
					}
					componentInParent.Damage(val14);
					if (DebugLogDamageAfterArmor.Value)
					{
						float health = componentInParent.GetHealth();
						float num19 = Mathf.Max(0f, num18 - health);
						((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("[{0}] DEALT '{1}': {2:0.0} (base={3:0.0}, centerMul={4:0.00}) hp {5:0.0}->{6:0.0}", "ShieldBash", ((Object)componentInParent).name, num19, num5, num17, num18, health));
					}
					num13++;
					if (num13 == 1)
					{
						pos = val11;
					}
					if (PlayHitSfxPerTarget.Value)
					{
						float volumeMul = Mathf.Max(0f, num8 * volMul * num10);
						float pitchMul2 = Mathf.Max(0.01f, pitchMul * num11);
						PlayLocalHitAt(player, val11, volumeMul, pitchMul2);
					}
				}
			}
			else if (DamageWorldObjects.Value && TryDamageWorldObject(val5, player, val, forward, cosHalfAngle, ref losChecks, num14, num6, out hitPoint))
			{
				num13++;
				if (num13 == 1)
				{
					pos = hitPoint;
				}
				if (PlayHitSfxPerTarget.Value)
				{
					float volumeMul2 = Mathf.Max(0f, num8 * volMul * num10);
					float pitchMul3 = Mathf.Max(0.01f, pitchMul * num11);
					PlayLocalHitAt(player, hitPoint, volumeMul2, pitchMul3);
				}
			}
		}
		if (!PlayHitSfxPerTarget.Value)
		{
			if (num13 > 0)
			{
				float num20 = 0f;
				if (num13 > 1)
				{
					float num21 = Mathf.Min(MultiHitBonusMin.Value, MultiHitBonusMax.Value);
					float num22 = Mathf.Max(MultiHitBonusMin.Value, MultiHitBonusMax.Value);
					num20 = Random.Range(num21, num22);
				}
				float volumeMul3 = Mathf.Max(0f, (num8 + num20) * volMul * num10);
				float pitchMul4 = Mathf.Max(0.01f, pitchMul * num11);
				PlayLocalHitAt(player, pos, volumeMul3, pitchMul4);
			}
			else
			{
				Vector3 pos2 = ((Component)player).transform.position + ((Component)player).transform.forward * 0.6f + Vector3.up * 1f;
				float volumeMul4 = Mathf.Max(0f, num9 * volMul * num10);
				float pitchMul5 = Mathf.Max(0.01f, 1.02f * pitchMul * num11);
				PlayLocalMissAt(player, pos2, volumeMul4, pitchMul5);
			}
		}
		if (DebugLog.Value)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("[{0}] Bash: shieldBase={1:0.0}, sf={2:0.00}, rand={3:0.00}, base={4:0.0}, world={5:0.0}, hits={6}, LoS={7}/{8}, overlap={9}", "ShieldBash", num, blockingSkillFactor, num4, num5, num6, num13, losChecks, num14, num12));
		}
	}

	private bool TryDamageWorldObject(Collider col, Player player, Vector3 origin, Vector3 forward, float cosHalf, ref int losChecks, int maxLos, float worldDamage, out Vector3 hitPoint)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_020e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0213: Unknown result type (might be due to invalid IL or missing references)
		//IL_021a: Unknown result type (might be due to invalid IL or missing references)
		//IL_021f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0224: Unknown result type (might be due to invalid IL or missing references)
		//IL_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_0230: Unknown result type (might be due to invalid IL or missing references)
		//IL_0235: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0247: Unknown result type (might be due to invalid IL or missing references)
		//IL_0249: Unknown result type (might be due to invalid IL or missing references)
		//IL_0278: Unknown result type (might be due to invalid IL or missing references)
		//IL_027d: Unknown result type (might be due to invalid IL or missing references)
		//IL_027f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0284: Unknown result type (might be due to invalid IL or missing references)
		//IL_0289: Unknown result type (might be due to invalid IL or missing references)
		//IL_028c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0291: Unknown result type (might be due to invalid IL or missing references)
		//IL_0296: Unknown result type (might be due to invalid IL or missing references)
		//IL_0297: 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_029e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ab: Expected O, but got Unknown
		hitPoint = origin;
		if (!Object.op_Implicit((Object)(object)col) || !Object.op_Implicit((Object)(object)player))
		{
			return false;
		}
		TreeBase componentInParent = ((Component)col).GetComponentInParent<TreeBase>();
		TreeLog componentInParent2 = ((Component)col).GetComponentInParent<TreeLog>();
		MineRock componentInParent3 = ((Component)col).GetComponentInParent<MineRock>();
		MineRock5 componentInParent4 = ((Component)col).GetComponentInParent<MineRock5>();
		Destructible componentInParent5 = ((Component)col).GetComponentInParent<Destructible>();
		WearNTear componentInParent6 = ((Component)col).GetComponentInParent<WearNTear>();
		Component val = (Component)(componentInParent ?? componentInParent2 ?? componentInParent3 ?? componentInParent4 ?? ((object)componentInParent5) ?? ((object)componentInParent6));
		if (!Object.op_Implicit((Object)(object)val))
		{
			return false;
		}
		if (!HitOnceTryAdd(((Object)val.gameObject).GetInstanceID()))
		{
			return false;
		}
		Bounds bounds = col.bounds;
		Vector3 center = ((Bounds)(ref bounds)).center;
		Vector3 val2 = center - origin;
		float magnitude = ((Vector3)(ref val2)).magnitude;
		if (magnitude < 0.001f)
		{
			return false;
		}
		Vector3 val3 = val2 / magnitude;
		float num = Vector3.Dot(forward, val3);
		if (num < cosHalf)
		{
			return false;
		}
		if (LineOfSightCheck.Value && maxLos > 0 && losChecks < maxLos)
		{
			losChecks++;
			int worldLosMask = GetWorldLosMask();
			RaycastHit val4 = default(RaycastHit);
			if (Physics.Raycast(origin, val3, ref val4, magnitude, worldLosMask, (QueryTriggerInteraction)1))
			{
				Collider collider = ((RaycastHit)(ref val4)).collider;
				object obj = ((collider != null) ? ((Component)collider).GetComponentInParent<TreeBase>() : null);
				if (obj == null)
				{
					Collider collider2 = ((RaycastHit)(ref val4)).collider;
					obj = ((collider2 != null) ? ((Component)collider2).GetComponentInParent<TreeLog>() : null);
					if (obj == null)
					{
						Collider collider3 = ((RaycastHit)(ref val4)).collider;
						obj = ((collider3 != null) ? ((Component)collider3).GetComponentInParent<MineRock>() : null);
						if (obj == null)
						{
							Collider collider4 = ((RaycastHit)(ref val4)).collider;
							obj = ((collider4 != null) ? ((Component)collider4).GetComponentInParent<MineRock5>() : null);
							if (obj == null)
							{
								Collider collider5 = ((RaycastHit)(ref val4)).collider;
								obj = ((collider5 != null) ? ((Component)collider5).GetComponentInParent<Destructible>() : null);
								if (obj == null)
								{
									Collider collider6 = ((RaycastHit)(ref val4)).collider;
									obj = ((collider6 != null) ? ((Component)collider6).GetComponentInParent<WearNTear>() : null);
								}
							}
						}
					}
				}
				Component val5 = (Component)obj;
				if ((Object)(object)val5 != (Object)(object)val)
				{
					return false;
				}
			}
		}
		hitPoint = col.ClosestPoint(((Component)player).transform.position + forward * 0.5f);
		if (hitPoint == Vector3.zero)
		{
			hitPoint = center;
		}
		bool flag = (Object)(object)componentInParent != (Object)null || (Object)(object)componentInParent2 != (Object)null;
		bool flag2 = (Object)(object)componentInParent3 != (Object)null || (Object)(object)componentInParent4 != (Object)null;
		HitData val6 = new HitData
		{
			m_attacker = ((Character)player).GetZDOID(),
			m_point = hitPoint,
			m_dir = val3,
			m_pushForce = 0f
		};
		float num2 = Mathf.Max(0f, worldDamage);
		if (flag)
		{
			val6.m_damage.m_chop = num2;
		}
		else if (flag2)
		{
			val6.m_damage.m_pickaxe = num2;
		}
		else
		{
			val6.m_damage.m_blunt = num2;
		}
		if ((Object)(object)componentInParent != (Object)null)
		{
			componentInParent.Damage(val6);
		}
		else if ((Object)(object)componentInParent2 != (Object)null)
		{
			componentInParent2.Damage(val6);
		}
		else if ((Object)(object)componentInParent3 != (Object)null)
		{
			componentInParent3.Damage(val6);
		}
		else if ((Object)(object)componentInParent4 != (Object)null)
		{
			componentInParent4.Damage(val6);
		}
		else if ((Object)(object)componentInParent5 != (Object)null)
		{
			componentInParent5.Damage(val6);
		}
		else
		{
			if (!((Object)(object)componentInParent6 != (Object)null))
			{
				return false;
			}
			componentInParent6.Damage(val6);
		}
		return true;
	}

	private void GetMaterialMix(ItemData shield, out float volMul, out float pitchMul)
	{
		volMul = 1f;
		pitchMul = 1f;
		string text = shield?.m_shared?.m_name ?? "";
		string text2 = text.ToLowerInvariant();
		bool flag = text2.Contains("iron") || text2.Contains("blackmetal") || text2.Contains("silver") || text2.Contains("bronze") || text2.Contains("metal");
		bool flag2 = !flag && (text2.Contains("wood") || text2.Contains("tower"));
		if (flag)
		{
			volMul *= Mathf.Max(0.01f, MetalVolumeMul.Value);
			pitchMul *= Mathf.Max(0.01f, MetalPitchMul.Value);
		}
		else if (flag2)
		{
			volMul *= Mathf.Max(0.01f, WoodVolumeMul.Value);
			pitchMul *= Mathf.Max(0.01f, WoodPitchMul.Value);
		}
	}

	private AudioSource GetOrCreateLocalSfxSource(Player p)
	{
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Expected O, but got Unknown
		if (!Object.op_Implicit((Object)(object)p))
		{
			return null;
		}
		if (Object.op_Implicit((Object)(object)_localSfxSource) && Object.op_Implicit((Object)(object)((Component)_localSfxSource).gameObject) && ((Component)_localSfxSource).transform.IsChildOf(((Component)p).transform))
		{
			return _localSfxSource;
		}
		try
		{
			if (Object.op_Implicit((Object)(object)_localSfxSource) && Object.op_Implicit((Object)(object)((Component)_localSfxSource).gameObject))
			{
				Object.Destroy((Object)(object)((Component)_localSfxSource).gameObject);
			}
		}
		catch
		{
		}
		GameObject val = new GameObject("ShieldBash_LocalSFX_Source");
		val.transform.SetParent(((Component)p).transform, false);
		AudioSource val2 = val.AddComponent<AudioSource>();
		val2.spatialBlend = 1f;
		val2.rolloffMode = (AudioRolloffMode)0;
		val2.minDistance = 1f;
		val2.maxDistance = 35f;
		val2.playOnAwake = false;
		val2.loop = false;
		val2.dopplerLevel = 0f;
		_localSfxSource = val2;
		return _localSfxSource;
	}

	private void PlayLocalHitAt(Player player, Vector3 pos, float volumeMul, float pitchMul)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		PlayLocalAt(player, _hitClip, pos, volumeMul, pitchMul);
	}

	private void PlayLocalMissAt(Player player, Vector3 pos, float volumeMul, float pitchMul)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		PlayLocalAt(player, _missClip, pos, volumeMul, pitchMul);
	}

	private void PlayLocalAt(Player player, AudioClip clip, Vector3 pos, float volumeMul, float pitchMul)
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)clip))
		{
			AudioSource orCreateLocalSfxSource = GetOrCreateLocalSfxSource(player);
			if (Object.op_Implicit((Object)(object)orCreateLocalSfxSource))
			{
				((Component)orCreateLocalSfxSource).transform.position = pos;
				orCreateLocalSfxSource.pitch = Mathf.Clamp(pitchMul, 0.5f, 2f);
				float num = Mathf.Clamp01(volumeMul) * Mathf.Clamp(LocalClipVolumeMul.Value, 0f, 3f);
				orCreateLocalSfxSource.PlayOneShot(clip, num);
			}
		}
	}

	private bool LoadAssetsFromBundle()
	{
		string text = Path.Combine(Paths.PluginPath, "ShieldBash", "Assets", "shieldbashbundle");
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[ShieldBash] Bundle path: " + text));
		if (!File.Exists(text))
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[ShieldBash] AssetBundle not found: " + text));
			return false;
		}
		AssetBundle val = AssetBundle.LoadFromFile(text);
		if ((Object)(object)val == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] Failed to load AssetBundle (null). Wrong Unity version or corrupted file.");
			return false;
		}
		try
		{
			_bashClip = val.LoadAsset<AnimationClip>("AttackShield01");
			if ((Object)(object)_bashClip == (Object)null)
			{
				AnimationClip[] array = val.LoadAllAssets<AnimationClip>();
				if (array != null && array.Length != 0)
				{
					foreach (AnimationClip val2 in array)
					{
						if ((Object)(object)val2 != (Object)null && ((Object)val2).name == "AttackShield01")
						{
							_bashClip = val2;
							break;
						}
					}
					if ((Object)(object)_bashClip == (Object)null)
					{
						_bashClip = array[0];
					}
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[ShieldBash] Loaded embedded clip: " + ((Object)_bashClip).name));
				}
			}
			if ((Object)(object)_bashClip == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] No AnimationClip found in bundle.");
				((BaseUnityPlugin)this).Logger.LogError((object)("[ShieldBash] Assets inside bundle:\n - " + string.Join("\n - ", val.GetAllAssetNames())));
				return false;
			}
			_hitClip = null;
			_missClip = null;
			string text2 = (HitClipName.Value ?? "").Trim();
			string text3 = (MissClipName.Value ?? "").Trim();
			AudioClip[] array2 = val.LoadAllAssets<AudioClip>();
			if (array2 != null)
			{
				foreach (AudioClip val3 in array2)
				{
					if (Object.op_Implicit((Object)(object)val3))
					{
						if ((Object)(object)_hitClip == (Object)null && ((Object)val3).name.Equals(text2, StringComparison.OrdinalIgnoreCase))
						{
							_hitClip = val3;
						}
						else if ((Object)(object)_missClip == (Object)null && ((Object)val3).name.Equals(text3, StringComparison.OrdinalIgnoreCase))
						{
							_missClip = val3;
						}
					}
				}
			}
			if (!Object.op_Implicit((Object)(object)_hitClip))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[ShieldBash] HIT clip not found. Expected AudioClip name: '" + text2 + "'"));
			}
			if (!Object.op_Implicit((Object)(object)_missClip))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[ShieldBash] MISS clip not found. Expected AudioClip name: '" + text3 + "'"));
			}
			return true;
		}
		finally
		{
			val.Unload(false);
		}
	}

	private Animator GetAnimator(Character character)
	{
		try
		{
			return CharacterAnimator.Invoke(character);
		}
		catch
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] Cannot access field 'm_animator' on Character.");
			return null;
		}
	}

	private ItemData GetLeftItem(Humanoid humanoid)
	{
		try
		{
			return HumanoidLeftItem.Invoke(humanoid);
		}
		catch
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] Cannot access field 'm_leftItem' on Humanoid.");
			return null;
		}
	}

	private bool HasShieldInLeftHand(Player player)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Invalid comparison between Unknown and I4
		ItemData leftItem = GetLeftItem((Humanoid)(object)player);
		return leftItem != null && leftItem.m_shared != null && (int)leftItem.m_shared.m_itemType == 5;
	}
}
[HarmonyPatch(typeof(ItemData))]
public static class ShieldBashTooltipPatch
{
	[CompilerGenerated]
	private sealed class <TargetMethods>d__1 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private MethodBase <>2__current;

		private int <>l__initialThreadId;

		private List<MethodInfo>.Enumerator <>s__1;

		private MethodInfo <m>5__2;

		MethodBase IEnumerator<MethodBase>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <TargetMethods>d__1(int <>1__state)
		{
			this.<>1__state = <>1__state;
			<>l__initialThreadId = Environment.CurrentManagedThreadId;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			int num = <>1__state;
			if (num == -3 || num == 1)
			{
				try
				{
				}
				finally
				{
					<>m__Finally1();
				}
			}
			<>s__1 = default(List<MethodInfo>.Enumerator);
			<m>5__2 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			try
			{
				int num = <>1__state;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -3;
					goto IL_00b6;
				}
				<>1__state = -1;
				<>s__1 = AccessTools.GetDeclaredMethods(typeof(ItemData)).GetEnumerator();
				<>1__state = -3;
				goto IL_00be;
				IL_00b6:
				<m>5__2 = null;
				goto IL_00be;
				IL_00be:
				if (<>s__1.MoveNext())
				{
					<m>5__2 = <>s__1.Current;
					if (<m>5__2.Name == "GetTooltip" && <m>5__2.ReturnType == typeof(string))
					{
						<>2__current = <m>5__2;
						<>1__state = 1;
						return true;
					}
					goto IL_00b6;
				}
				<>m__Finally1();
				<>s__1 = default(List<MethodInfo>.Enumerator);
				return false;
			}
			catch
			{
				//try-fault
				((IDisposable)this).Dispose();
				throw;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		private void <>m__Finally1()
		{
			<>1__state = -1;
			((IDisposable)<>s__1).Dispose();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}

		[DebuggerHidden]
		IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator()
		{
			if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
			{
				<>1__state = 0;
				return this;
			}
			return new <TargetMethods>d__1(0);
		}

		[DebuggerHidden]
		IEnumerator IEnumerable.GetEnumerator()
		{
			return ((IEnumerable<MethodBase>)this).GetEnumerator();
		}
	}

	private static readonly string[] BlockLineHints = new string[6] { "$item_blockpower", "Block power", "Block Power", "Сопротивление урону", "Блокирование", "Блок" };

	[IteratorStateMachine(typeof(<TargetMethods>d__1))]
	private static IEnumerable<MethodBase> TargetMethods()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <TargetMethods>d__1(-2);
	}

	private static void Postfix(ItemData __instance, ref string __result)
	{
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Invalid comparison between Unknown and I4
		ShieldBashPlugin instance = ShieldBashPlugin.Instance;
		if ((Object)(object)instance == (Object)null || !instance.ShowShieldBashInTooltip.Value || __instance == null || __instance.m_shared == null || (int)__instance.m_shared.m_itemType != 5)
		{
			return;
		}
		float num = instance.ComputeShieldBaseDamage(__instance);
		Player localPlayer = Player.m_localPlayer;
		float num2 = 0f;
		try
		{
			if (Object.op_Implicit((Object)(object)localPlayer))
			{
				num2 = Mathf.Clamp01(((Character)localPlayer).GetSkillFactor((SkillType)6));
			}
		}
		catch
		{
			num2 = 0f;
		}
		float num3 = Mathf.Max(0f, instance.BlockingSkillMultiplier.Value);
		float num4 = num * (1f + num2 * num3);
		num4 = Mathf.Clamp(num4, instance.MinDamage.Value, instance.MaxDamage.Value);
		float num5 = Mathf.Clamp(num, instance.MinDamage.Value, instance.MaxDamage.Value);
		string text = $"\n<color=orange>Удар щитом</color>: {num5:0.0}";
		string text2 = (((Object)(object)localPlayer != (Object)null) ? $"\n<color=orange>Удар щитом (твой блок)</color>: {num4:0.0}" : $"\n<color=orange>Удар щитом (твой блок)</color>: {num5:0.0}");
		string text3 = text + text2;
		if (!TryInsertAfterBlockLine(ref __result, text3))
		{
			__result += text3;
		}
	}

	private static bool TryInsertAfterBlockLine(ref string tooltip, string insert)
	{
		if (string.IsNullOrEmpty(tooltip))
		{
			return false;
		}
		string[] blockLineHints = BlockLineHints;
		foreach (string value in blockLineHints)
		{
			int num = tooltip.IndexOf(value, StringComparison.OrdinalIgnoreCase);
			if (num >= 0)
			{
				int num2 = tooltip.IndexOf('\n', num);
				if (num2 < 0)
				{
					num2 = tooltip.Length;
				}
				tooltip = tooltip.Insert(num2, insert);
				return true;
			}
		}
		return false;
	}
}