Decompiled source of ShieldBash v1.5.5

BepInEx/plugins/ShieldBash/ShieldBash.dll

Decompiled a month 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("mexanik.shieldbash", "ShieldBash", "1.5.5")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class ShieldBashPlugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Player), "Awake")]
	private static class PlayerAwakePatch
	{
		private static void Postfix(Player __instance)
		{
			ShieldBashPlugin instance = Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				instance.RegisterPlayerRpc(__instance);
			}
		}
	}

	[HarmonyPatch]
	private static class ShieldTooltipPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			MethodInfo[] methods = typeof(ItemData).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo method in methods)
			{
				if (method != null && method.Name == "GetTooltip" && method.ReturnType == typeof(string))
				{
					yield return method;
				}
			}
		}

		private static void Postfix(ItemData __instance, ref string __result)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Invalid comparison between Unknown and I4
			try
			{
				ShieldBashPlugin instance = Instance;
				if ((Object)(object)instance == (Object)null || !instance.ShowShieldBashInTooltip.Value || __instance == null || __instance.m_shared == null || (int)__instance.m_shared.m_itemType != 5)
				{
					return;
				}
				string text = __result ?? string.Empty;
				if (text.IndexOf("Shield Bash:", StringComparison.Ordinal) < 0 && text.IndexOf("Удар щитом:", StringComparison.Ordinal) < 0)
				{
					string text2 = instance.BuildTooltipLineForShield(__instance);
					if (!string.IsNullOrEmpty(text2))
					{
						__result = text + text2;
					}
				}
			}
			catch (Exception ex)
			{
				ShieldBashPlugin instance2 = Instance;
				if ((Object)(object)instance2 != (Object)null && instance2.DebugLog != null && instance2.DebugLog.Value)
				{
					((BaseUnityPlugin)instance2).Logger.LogWarning((object)("[ShieldBash] Tooltip patch error: " + ex.Message));
				}
			}
		}
	}

	public const string PluginGUID = "mexanik.shieldbash";

	public const string PluginName = "ShieldBash";

	public const string PluginVersion = "1.5.5";

	private const string InputName = "ShieldBash_Bash";

	private const string RpcPlayBashVisual = "ShieldBash_PlayVisual";

	internal static ShieldBashPlugin Instance;

	internal ConfigEntry<KeyCode> BashKey;

	internal ConfigEntry<float> Cooldown;

	internal ConfigEntry<bool> RequireShield;

	internal ConfigEntry<float> BaseStaminaCost;

	internal ConfigEntry<float> BlockPowerStaminaScale;

	internal ConfigEntry<float> SkillStaminaReduction;

	internal ConfigEntry<float> MinStaminaCost;

	internal ConfigEntry<float> MaxStaminaCost;

	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> HitDelay;

	internal ConfigEntry<bool> DamageWorldObjects;

	internal ConfigEntry<float> WorldDamageScale;

	internal ConfigEntry<bool> WorldDamageUseRandom;

	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<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 bool _isBashing;

	private Collider[] _overlapCols;

	private int[] _hitOnceIds;

	private int _hitOnceCount;

	private int _overlapMask = -1;

	private int _losWorldMask = -1;

	private float _cachedAngle = -999f;

	private float _cachedCosHalf = -2f;

	private AudioSource _localSfxSource;

	private static bool _locRefReady;

	private static Type _locType;

	private static PropertyInfo _locInstanceProp;

	private static MethodInfo _locGetSelectedLanguage;

	private static readonly FieldInfo CharacterAnimatorField = AccessTools.Field(typeof(Character), "m_animator");

	private static readonly FieldInfo CharacterBodyField = AccessTools.Field(typeof(Character), "m_body");

	private static readonly FieldInfo CharacterMoveDirField = AccessTools.Field(typeof(Character), "m_moveDir");

	private static readonly FieldInfo HumanoidLeftItemField = AccessTools.Field(typeof(Humanoid), "m_leftItem");

	private static readonly FieldInfo CharacterNViewField = AccessTools.Field(typeof(Character), "m_nview");

	private void Awake()
	{
		//IL_0710: Unknown result type (might be due to invalid IL or missing references)
		//IL_071a: Expected O, but got Unknown
		//IL_078b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0795: 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");
		BaseStaminaCost = ((BaseUnityPlugin)this).Config.Bind<float>("Stamina", "BaseStaminaCost", 10f, "Base stamina cost of Shield Bash");
		BlockPowerStaminaScale = ((BaseUnityPlugin)this).Config.Bind<float>("Stamina", "BlockPowerStaminaScale", 0.08f, "Additional stamina cost per point of shield block power");
		SkillStaminaReduction = ((BaseUnityPlugin)this).Config.Bind<float>("Stamina", "SkillStaminaReduction", 0.25f, "Maximum stamina cost reduction at Blocking skill 100");
		MinStaminaCost = ((BaseUnityPlugin)this).Config.Bind<float>("Stamina", "MinStaminaCost", 8f, "Minimum stamina cost of Shield Bash");
		MaxStaminaCost = ((BaseUnityPlugin)this).Config.Bind<float>("Stamina", "MaxStaminaCost", 18f, "Maximum stamina cost of Shield Bash");
		AntiSlideTime = ((BaseUnityPlugin)this).Config.Bind<float>("Feel", "AntiSlideTime", 0.2f, "Anti-slide duration seconds (0 = off)");
		BaseDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "BaseDamage", 4f, "Flat blunt damage added to bash");
		BlockPowerScale = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "BlockPowerScale", 0.16f, "Damage per 1 shield block power");
		QualityBonusPerLevel = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "QualityBonusPerLevel", 0.4f, "Bonus damage per shield upgrade level (quality-1)");
		MinDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "MinDamage", 3f, "Minimum final damage");
		MaxDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "MaxDamage", 20f, "Maximum final damage cap");
		BlockingSkillMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "BlockingSkillMultiplier", 0.3f, "At Blocking skill 100, damage is increased by 30 percent");
		DamageRandomMin = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "DamageRandomMin", 0.92f, "Per-bash random damage multiplier min.");
		DamageRandomMax = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "DamageRandomMax", 1.05f, "Per-bash random damage multiplier max.");
		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.");
		WorldDamageScale = ((BaseUnityPlugin)this).Config.Bind<float>("WorldDamage", "WorldDamageScale", 0.85f, "Multiplier for world-object damage.");
		WorldDamageUseRandom = ((BaseUnityPlugin)this).Config.Bind<bool>("WorldDamage", "WorldDamageUseRandom", false, "If true: world damage uses per-bash random multiplier.");
		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");
		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).");
		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 line to shield tooltip (RU/EN)");
		DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Log", false, "General debug logging");
		DebugLogDamageAfterArmor = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogDamageAfterArmor", false, "Log dealt damage 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.");
		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();
		_bashButton.Name = "ShieldBash_Bash";
		_bashButton.Config = BashKey;
		_bashButton.HintToken = "Shield Bash";
		_bashButton.ActiveInGUI = false;
		_bashButton.ActiveInCustomGUI = false;
		InputManager.Instance.AddButton("mexanik.shieldbash", _bashButton);
		EnsureBuffers();
		_harmony = new Harmony("mexanik.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)(object)_bashClip != (Object)null) ? ((Object)_bashClip).name : "null", ((Object)(object)_hitClip != (Object)null) ? ((Object)_hitClip).name : "null", ((Object)(object)_missClip != (Object)null) ? ((Object)_missClip).name : "null"));
	}

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

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

	private void Update()
	{
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Expected O, but got Unknown
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Expected O, but got Unknown
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Invalid comparison between Unknown and I4
		if (ZInput.instance == null || !ZInput.GetButtonDown(_bashButton.Name))
		{
			return;
		}
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || _isBashing || Time.time < _nextUseTime)
		{
			return;
		}
		if ((Object)(object)_bashClip == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"[ShieldBash] Bash clip is null. Bundle/clip not loaded.");
			return;
		}
		ItemData leftItem = GetLeftItem((Humanoid)localPlayer);
		if (RequireShield.Value && (leftItem == null || leftItem.m_shared == null || (int)leftItem.m_shared.m_itemType != 5))
		{
			return;
		}
		float cost = ComputeStaminaCost(localPlayer, leftItem);
		if (TryUseStaminaNoMessage(localPlayer, cost))
		{
			Animator animator = GetAnimator((Character)localPlayer);
			if (!((Object)(object)animator == (Object)null))
			{
				EnsureBuffers();
				_nextUseTime = Time.time + Cooldown.Value;
				((MonoBehaviour)this).StartCoroutine(DoBash(localPlayer, animator, _bashClip, applyDamage: true));
				BroadcastBashVisual(localPlayer);
			}
		}
	}

	private IEnumerator DoBash(Player player, Animator animator, AnimationClip clip, bool applyDamage)
	{
		if (applyDamage)
		{
			_isBashing = true;
		}
		bool prevRootMotion = animator.applyRootMotion;
		PlayableGraph graph = default(PlayableGraph);
		try
		{
			if (AntiSlideTime.Value > 0.0001f)
			{
				((MonoBehaviour)this).StartCoroutine(AntiSlideRoutine(player, AntiSlideTime.Value));
			}
			animator.applyRootMotion = false;
			graph = PlayableGraph.Create("ShieldBashGraph");
			AnimatorControllerPlayable controllerPlayable = AnimatorControllerPlayable.Create(graph, animator.runtimeAnimatorController);
			AnimationClipPlayable clipPlayable = AnimationClipPlayable.Create(graph, clip);
			((AnimationClipPlayable)(ref clipPlayable)).SetApplyFootIK(false);
			((AnimationClipPlayable)(ref clipPlayable)).SetApplyPlayableIK(false);
			AnimationLayerMixerPlayable mixer = AnimationLayerMixerPlayable.Create(graph, 2);
			((PlayableGraph)(ref graph)).Connect<AnimatorControllerPlayable, AnimationLayerMixerPlayable>(controllerPlayable, 0, mixer, 0);
			((PlayableGraph)(ref graph)).Connect<AnimationClipPlayable, AnimationLayerMixerPlayable>(clipPlayable, 0, mixer, 1);
			PlayableExtensions.SetInputWeight<AnimationLayerMixerPlayable>(mixer, 0, 0f);
			PlayableExtensions.SetInputWeight<AnimationLayerMixerPlayable>(mixer, 1, 1f);
			AnimationPlayableOutput output = AnimationPlayableOutput.Create(graph, "ShieldBashOutput", animator);
			PlayableOutputExtensions.SetSourcePlayable<AnimationPlayableOutput, AnimationLayerMixerPlayable>(output, mixer);
			((PlayableGraph)(ref graph)).Play();
			float hitAt = Mathf.Clamp(HitDelay.Value, 0.01f, Mathf.Max(0.01f, clip.length));
			yield return (object)new WaitForSeconds(hitAt);
			if ((Object)(object)player != (Object)null)
			{
				if (applyDamage)
				{
					ApplyBashDamageAndSfx(player);
				}
				else
				{
					PlayRemoteBashSfx(player);
				}
			}
			float remain = Mathf.Max(0.01f, clip.length - hitAt);
			yield return (object)new WaitForSeconds(remain);
		}
		finally
		{
			if (((PlayableGraph)(ref graph)).IsValid())
			{
				((PlayableGraph)(ref graph)).Destroy();
			}
			if ((Object)(object)animator != (Object)null)
			{
				animator.applyRootMotion = prevRootMotion;
			}
			if (applyDamage)
			{
				_isBashing = false;
			}
		}
	}

	private void BroadcastBashVisual(Player player)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Expected O, but got Unknown
		ZNetView zNetView = GetZNetView((Character)player);
		if ((Object)(object)zNetView == (Object)null || !zNetView.IsValid() || !zNetView.IsOwner())
		{
			return;
		}
		try
		{
			zNetView.InvokeRPC(ZNetView.Everybody, "ShieldBash_PlayVisual", Array.Empty<object>());
		}
		catch (Exception ex)
		{
			if (DebugLog != null && DebugLog.Value)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[ShieldBash] RPC send failed: " + ex.Message));
			}
		}
	}

	internal void RegisterPlayerRpc(Player player)
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Expected O, but got Unknown
		if ((Object)(object)player == (Object)null)
		{
			return;
		}
		ZNetView zNetView = GetZNetView((Character)player);
		if ((Object)(object)zNetView == (Object)null || !zNetView.IsValid())
		{
			return;
		}
		try
		{
			zNetView.Register("ShieldBash_PlayVisual", (Action<long>)delegate(long sender)
			{
				RpcPlayRemoteBashVisual(player, sender);
			});
		}
		catch
		{
		}
	}

	private void RpcPlayRemoteBashVisual(Player player, long sender)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Expected O, but got Unknown
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Expected O, but got Unknown
		if ((Object)(object)player == (Object)null)
		{
			return;
		}
		ZNetView zNetView = GetZNetView((Character)player);
		if (!((Object)(object)zNetView == (Object)null) && zNetView.IsValid() && !zNetView.IsOwner() && !((Object)(object)_bashClip == (Object)null))
		{
			Animator animator = GetAnimator((Character)player);
			if (!((Object)(object)animator == (Object)null))
			{
				((MonoBehaviour)this).StartCoroutine(DoBash(player, animator, _bashClip, applyDamage: false));
			}
		}
	}

	private void PlayRemoteBashSfx(Player player)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: 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_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//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_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)player == (Object)null))
		{
			Vector3 pos = ((Component)player).transform.position + ((Component)player).transform.forward * 0.6f + Vector3.up * 1f;
			PlayLocalMissAt(player, pos, Mathf.Max(0f, MissSfxVolume.Value), 1f);
		}
	}

	private IEnumerator AntiSlideRoutine(Player player, float duration)
	{
		if ((Object)(object)player == (Object)null)
		{
			yield break;
		}
		Rigidbody body;
		try
		{
			body = GetCharacterBody((Character)(object)player);
		}
		catch
		{
			body = null;
		}
		if (!((Object)(object)body == (Object)null) && !body.isKinematic)
		{
			float t = 0f;
			SetMoveDirZero(player);
			body.linearVelocity = Vector3.zero;
			while (t < duration && !((Object)(object)player == (Object)null) && !((Object)(object)body == (Object)null))
			{
				Vector3 v = body.linearVelocity;
				v.x = 0f;
				v.z = 0f;
				body.linearVelocity = v;
				SetMoveDirZero(player);
				t += Time.deltaTime;
				yield return null;
			}
		}
	}

	private static void SetMoveDirZero(Player player)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)player == (Object)null || CharacterMoveDirField == null)
		{
			return;
		}
		try
		{
			CharacterMoveDirField.SetValue(player, Vector3.zero);
		}
		catch
		{
		}
	}

	private float ComputeStaminaCost(Player player, ItemData shield)
	{
		float num = 0f;
		if (shield != null && shield.m_shared != null)
		{
			int num2 = Mathf.Max(1, shield.m_quality);
			num = shield.m_shared.m_blockPower + shield.m_shared.m_blockPowerPerLevel * (float)(num2 - 1);
		}
		float blockingSkillFactor = GetBlockingSkillFactor(player);
		float num3 = Mathf.Max(0f, BaseStaminaCost.Value) + num * Mathf.Max(0f, BlockPowerStaminaScale.Value);
		float num4 = blockingSkillFactor * Mathf.Clamp01(SkillStaminaReduction.Value);
		float num5 = num3 * (1f - num4);
		float num6 = Mathf.Max(0f, MinStaminaCost.Value);
		float num7 = Mathf.Max(num6, MaxStaminaCost.Value);
		return Mathf.Clamp(num5, num6, num7);
	}

	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)(object)player == (Object)null)
		{
			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 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 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;
		_hitOnceCount++;
		return true;
	}

	private static Vector3 GetSafeHitPoint(Collider col, Vector3 nearPoint, Vector3 fallback)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//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_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//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_0047: 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_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: 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)
		if ((Object)(object)col == (Object)null)
		{
			return fallback;
		}
		Vector3 val = col.ClosestPointOnBounds(nearPoint);
		if (float.IsNaN(val.x))
		{
			return fallback;
		}
		if (float.IsInfinity(val.x))
		{
			return fallback;
		}
		return val;
	}

	private void ApplyBashDamageAndSfx(Player player)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: 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_0203: Unknown result type (might be due to invalid IL or missing references)
		//IL_0208: Unknown result type (might be due to invalid IL or missing references)
		//IL_020d: 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_0211: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0220: Unknown result type (might be due to invalid IL or missing references)
		//IL_0225: Unknown result type (might be due to invalid IL or missing references)
		//IL_0237: Unknown result type (might be due to invalid IL or missing references)
		//IL_0239: Unknown result type (might be due to invalid IL or missing references)
		//IL_0259: Unknown result type (might be due to invalid IL or missing references)
		//IL_025b: Unknown result type (might be due to invalid IL or missing references)
		//IL_027b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0280: Unknown result type (might be due to invalid IL or missing references)
		//IL_0287: 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_07c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_07cb: 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_07df: 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_07f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0822: Unknown result type (might be due to invalid IL or missing references)
		//IL_0669: Unknown result type (might be due to invalid IL or missing references)
		//IL_066b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0671: Unknown result type (might be due to invalid IL or missing references)
		//IL_0673: Unknown result type (might be due to invalid IL or missing references)
		//IL_067d: Unknown result type (might be due to invalid IL or missing references)
		//IL_07aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_06a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_06a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0376: Unknown result type (might be due to invalid IL or missing references)
		//IL_037b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0385: Unknown result type (might be due to invalid IL or missing references)
		//IL_038a: Unknown result type (might be due to invalid IL or missing references)
		//IL_038f: 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_0393: 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_03ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_03be: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f7: Expected O, but got Unknown
		//IL_04fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0506: Unknown result type (might be due to invalid IL or missing references)
		//IL_0508: Unknown result type (might be due to invalid IL or missing references)
		//IL_0516: Unknown result type (might be due to invalid IL or missing references)
		//IL_0521: Unknown result type (might be due to invalid IL or missing references)
		//IL_0526: Unknown result type (might be due to invalid IL or missing references)
		//IL_052b: Unknown result type (might be due to invalid IL or missing references)
		//IL_052f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0534: Unknown result type (might be due to invalid IL or missing references)
		//IL_0420: Unknown result type (might be due to invalid IL or missing references)
		//IL_0426: Unknown result type (might be due to invalid IL or missing references)
		//IL_0428: Unknown result type (might be due to invalid IL or missing references)
		//IL_0604: Unknown result type (might be due to invalid IL or missing references)
		//IL_0606: Unknown result type (might be due to invalid IL or missing references)
		//IL_0642: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)player == (Object)null)
		{
			return;
		}
		HitOnceReset();
		ItemData leftItem = GetLeftItem((Humanoid)player);
		float num = ComputeShieldBaseDamage(leftItem);
		float num2 = DamageRandomMin.Value;
		float num3 = DamageRandomMax.Value;
		if (num2 > num3)
		{
			float num4 = num2;
			num2 = num3;
			num3 = num4;
		}
		float num5 = Random.Range(num2, num3);
		float blockingSkillFactor = GetBlockingSkillFactor(player);
		float num6 = ApplySkillAndRandom(num, blockingSkillFactor, num5);
		float randMul = ((!WorldDamageUseRandom.Value) ? 1f : num5);
		float num7 = ApplySkillAndRandom(num, blockingSkillFactor, randMul) * Mathf.Clamp(WorldDamageScale.Value, 0f, 5f);
		float num8 = Mathf.Clamp01(Mathf.InverseLerp(MinDamage.Value, MaxDamage.Value, num6));
		float num9 = Mathf.Lerp(HitSfxVolumeMin.Value, HitSfxVolumeMax.Value, num8);
		float num10 = Mathf.Max(0f, MissSfxVolume.Value);
		GetMaterialMix(leftItem, out var volMul, out var pitchMul);
		float num11 = Random.Range(Mathf.Min(RandomVolJitterMin.Value, RandomVolJitterMax.Value), Mathf.Max(RandomVolJitterMin.Value, RandomVolJitterMax.Value));
		float num12 = 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 num13 = Physics.OverlapCapsuleNonAlloc(val3, val4, Radius.Value, _overlapCols, overlapMask, (QueryTriggerInteraction)2);
		int num14 = 0;
		Vector3 pos = val;
		int losChecks = 0;
		int num15 = Mathf.Clamp(MaxLoSRaycastsPerBash.Value, 0, 64);
		Vector3 nearPoint = ((Component)player).transform.position + forward * 0.5f;
		for (int i = 0; i < num13; i++)
		{
			Collider val5 = _overlapCols[i];
			if ((Object)(object)val5 == (Object)null)
			{
				continue;
			}
			Character componentInParent = ((Component)val5).GetComponentInParent<Character>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				if ((object)componentInParent == 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)
				{
					Player val6 = (Player)(object)((componentInParent is Player) ? componentInParent : null);
					if ((Object)(object)val6 != (Object)null)
					{
						continue;
					}
				}
				Vector3 val7 = ((Component)componentInParent).transform.position + Vector3.up * 1.1f;
				Vector3 val8 = val7 - val;
				float magnitude = ((Vector3)(ref val8)).magnitude;
				if (magnitude < 0.001f)
				{
					continue;
				}
				Vector3 val9 = val8 / magnitude;
				float num16 = Vector3.Dot(forward, val9);
				if (num16 < cosHalfAngle)
				{
					continue;
				}
				if (LineOfSightCheck.Value && num15 > 0 && losChecks < num15)
				{
					losChecks++;
					int worldLosMask = GetWorldLosMask();
					RaycastHit val10 = default(RaycastHit);
					if (Physics.Raycast(val, val9, ref val10, magnitude, worldLosMask, (QueryTriggerInteraction)1))
					{
						Character val11 = null;
						if ((Object)(object)((RaycastHit)(ref val10)).collider != (Object)null)
						{
							val11 = ((Component)((RaycastHit)(ref val10)).collider).GetComponentInParent<Character>();
						}
						if (val11 != componentInParent)
						{
							continue;
						}
					}
				}
				if (HitOnceTryAdd(((Object)((Component)componentInParent).gameObject).GetInstanceID()))
				{
					float num17 = Mathf.Clamp(num6, MinDamage.Value, MaxDamage.Value);
					Vector3 safeHitPoint = GetSafeHitPoint(val5, nearPoint, val7);
					float num18 = 0f;
					if (DebugLogDamageAfterArmor.Value)
					{
						num18 = componentInParent.GetHealth();
					}
					HitData val12 = new HitData();
					val12.m_attacker = ((Character)player).GetZDOID();
					val12.m_point = safeHitPoint;
					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;
					val12.m_damage.m_blunt = num17;
					componentInParent.Damage(val12);
					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} (damage={3:0.0}) hp {4:0.0}->{5:0.0}", "ShieldBash", ((Object)componentInParent).name, num19, num17, num18, health));
					}
					num14++;
					if (num14 == 1)
					{
						pos = safeHitPoint;
					}
					if (PlayHitSfxPerTarget.Value)
					{
						float volumeMul = Mathf.Max(0f, num9 * volMul * num11);
						float pitchMul2 = Mathf.Max(0.01f, pitchMul * num12);
						PlayLocalHitAt(player, safeHitPoint, volumeMul, pitchMul2);
					}
				}
			}
			else
			{
				if (!DamageWorldObjects.Value)
				{
					continue;
				}
				Vector3 hitPoint = val;
				if (TryDamageWorldObject(val5, player, val, forward, cosHalfAngle, ref losChecks, num15, num7, nearPoint, out hitPoint))
				{
					num14++;
					if (num14 == 1)
					{
						pos = hitPoint;
					}
					if (PlayHitSfxPerTarget.Value)
					{
						float volumeMul2 = Mathf.Max(0f, num9 * volMul * num11);
						float pitchMul3 = Mathf.Max(0.01f, pitchMul * num12);
						PlayLocalHitAt(player, hitPoint, volumeMul2, pitchMul3);
					}
				}
			}
		}
		if (!PlayHitSfxPerTarget.Value)
		{
			if (num14 > 0)
			{
				float num20 = 0f;
				if (num14 > 1)
				{
					float num21 = MultiHitBonusMin.Value;
					float num22 = MultiHitBonusMax.Value;
					if (num21 > num22)
					{
						float num23 = num21;
						num21 = num22;
						num22 = num23;
					}
					num20 = Random.Range(num21, num22);
				}
				float volumeMul3 = Mathf.Max(0f, (num9 + num20) * volMul * num11);
				float pitchMul4 = Mathf.Max(0.01f, pitchMul * num12);
				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, num10 * volMul * num11);
				float pitchMul5 = Mathf.Max(0.01f, 1.02f * pitchMul * num12);
				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}, char={4:0.0}, world={5:0.0}, hits={6}, LoS={7}/{8}, overlap={9}", "ShieldBash", num, blockingSkillFactor, num5, num6, num7, num14, losChecks, num15, num13));
		}
	}

	private bool TryDamageWorldObject(Collider col, Player player, Vector3 origin, Vector3 forward, float cosHalf, ref int losChecks, int maxLos, float worldDamage, Vector3 nearPoint, 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_011a: 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_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_0306: Unknown result type (might be due to invalid IL or missing references)
		//IL_0308: Unknown result type (might be due to invalid IL or missing references)
		//IL_030a: Unknown result type (might be due to invalid IL or missing references)
		//IL_030f: 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_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: 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_0369: Expected O, but got Unknown
		//IL_036c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0371: Unknown result type (might be due to invalid IL or missing references)
		//IL_037a: Unknown result type (might be due to invalid IL or missing references)
		//IL_037f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0386: Unknown result type (might be due to invalid IL or missing references)
		//IL_0388: Unknown result type (might be due to invalid IL or missing references)
		hitPoint = origin;
		if ((Object)(object)col == (Object)null)
		{
			return false;
		}
		if ((Object)(object)player == (Object)null)
		{
			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 = null;
		if ((Object)(object)componentInParent != (Object)null)
		{
			val = (Component)(object)componentInParent;
		}
		else if ((Object)(object)componentInParent2 != (Object)null)
		{
			val = (Component)(object)componentInParent2;
		}
		else if ((Object)(object)componentInParent3 != (Object)null)
		{
			val = (Component)(object)componentInParent3;
		}
		else if ((Object)(object)componentInParent4 != (Object)null)
		{
			val = (Component)(object)componentInParent4;
		}
		else if ((Object)(object)componentInParent5 != (Object)null)
		{
			val = (Component)(object)componentInParent5;
		}
		else if ((Object)(object)componentInParent6 != (Object)null)
		{
			val = (Component)(object)componentInParent6;
		}
		if ((Object)(object)val == (Object)null)
		{
			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;
		if (Vector3.Dot(forward, val3) < 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))
			{
				Component val5 = null;
				if ((Object)(object)((RaycastHit)(ref val4)).collider != (Object)null)
				{
					TreeBase componentInParent7 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<TreeBase>();
					if ((Object)(object)componentInParent7 != (Object)null)
					{
						val5 = (Component)(object)componentInParent7;
					}
					else
					{
						TreeLog componentInParent8 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<TreeLog>();
						if ((Object)(object)componentInParent8 != (Object)null)
						{
							val5 = (Component)(object)componentInParent8;
						}
						else
						{
							MineRock componentInParent9 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<MineRock>();
							if ((Object)(object)componentInParent9 != (Object)null)
							{
								val5 = (Component)(object)componentInParent9;
							}
							else
							{
								MineRock5 componentInParent10 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<MineRock5>();
								if ((Object)(object)componentInParent10 != (Object)null)
								{
									val5 = (Component)(object)componentInParent10;
								}
								else
								{
									Destructible componentInParent11 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<Destructible>();
									if ((Object)(object)componentInParent11 != (Object)null)
									{
										val5 = (Component)(object)componentInParent11;
									}
									else
									{
										WearNTear componentInParent12 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<WearNTear>();
										if ((Object)(object)componentInParent12 != (Object)null)
										{
											val5 = (Component)(object)componentInParent12;
										}
									}
								}
							}
						}
					}
				}
				if (val5 != val)
				{
					return false;
				}
			}
		}
		hitPoint = GetSafeHitPoint(col, nearPoint, center);
		bool flag = false;
		if ((Object)(object)componentInParent != (Object)null)
		{
			flag = true;
		}
		if ((Object)(object)componentInParent2 != (Object)null)
		{
			flag = true;
		}
		bool flag2 = false;
		if ((Object)(object)componentInParent3 != (Object)null)
		{
			flag2 = true;
		}
		if ((Object)(object)componentInParent4 != (Object)null)
		{
			flag2 = true;
		}
		HitData val6 = new HitData();
		val6.m_attacker = ((Character)player).GetZDOID();
		val6.m_point = hitPoint;
		val6.m_dir = val3;
		val6.m_pushForce = 0f;
		float num = Mathf.Max(0f, worldDamage);
		if (flag)
		{
			val6.m_damage.m_chop = num;
		}
		else if (flag2)
		{
			val6.m_damage.m_pickaxe = num;
		}
		else
		{
			val6.m_damage.m_blunt = num;
		}
		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 = "";
		text = ((shield == null) ? "" : ((shield.m_shared == null) ? "" : ((shield.m_shared.m_name != null) ? 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 = false;
		if (!flag)
		{
			flag2 = 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 player)
	{
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Expected O, but got Unknown
		if ((Object)(object)player == (Object)null)
		{
			return null;
		}
		if ((Object)(object)_localSfxSource != (Object)null && (Object)(object)((Component)_localSfxSource).gameObject != (Object)null)
		{
			Transform transform = ((Component)_localSfxSource).transform;
			if ((Object)(object)transform != (Object)null && transform.IsChildOf(((Component)player).transform))
			{
				return _localSfxSource;
			}
		}
		try
		{
			if ((Object)(object)_localSfxSource != (Object)null && (Object)(object)((Component)_localSfxSource).gameObject != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_localSfxSource).gameObject);
			}
		}
		catch
		{
		}
		GameObject val = new GameObject("ShieldBash_LocalSFX_Source");
		val.transform.SetParent(((Component)player).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_0009: 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_0009: 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_003b: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)player == (Object)null) && !((Object)(object)clip == (Object)null))
		{
			AudioSource orCreateLocalSfxSource = GetOrCreateLocalSfxSource(player);
			if (!((Object)(object)orCreateLocalSfxSource == (Object)null))
			{
				((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 = null;
		string text2 = null;
		try
		{
			text = Assembly.GetExecutingAssembly().Location;
			text2 = Path.GetDirectoryName(text);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[ShieldBash] Could not resolve DLL location: " + ex.Message));
		}
		List<string> list = new List<string>();
		AddBundleCandidates(list, text2);
		AddBundleCandidates(list, Path.Combine(text2 ?? string.Empty, "Assets"));
		AddBundleCandidates(list, Path.Combine(Paths.PluginPath, "ShieldBash"));
		AddBundleCandidates(list, Path.Combine(Paths.PluginPath, "ShieldBash", "Assets"));
		AddBundleCandidates(list, Paths.PluginPath);
		string text3 = null;
		for (int i = 0; i < list.Count; i++)
		{
			string text4 = list[i];
			if (!string.IsNullOrEmpty(text4) && File.Exists(text4))
			{
				text3 = text4;
				break;
			}
		}
		if (text3 == null && !string.IsNullOrEmpty(text2) && Directory.Exists(text2))
		{
			try
			{
				string[] files = Directory.GetFiles(text2, "*", SearchOption.AllDirectories);
				for (int i = 0; i < files.Length; i++)
				{
					string fileName = Path.GetFileName(files[i]);
					if (fileName.Equals("shieldbashbundle", StringComparison.OrdinalIgnoreCase) || fileName.Equals("shieldbashbundle.bundle", StringComparison.OrdinalIgnoreCase))
					{
						text3 = files[i];
						break;
					}
				}
			}
			catch (Exception ex2)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[ShieldBash] Bundle fallback search failed: " + ex2.Message));
			}
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[ShieldBash] DLL: " + (text ?? "unknown")));
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[ShieldBash] AssetBundle: " + (text3 ?? "NOT FOUND")));
		if (text3 == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] Put 'shieldbashbundle' next to ShieldBash.dll or into an Assets subfolder.");
			return false;
		}
		AssetBundle val = null;
		try
		{
			val = AssetBundle.LoadFromFile(text3);
			if ((Object)(object)val == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] Unity returned null while loading the AssetBundle. Rebuild it with Unity 6000.0.61f1 for StandaloneWindows64.");
				return false;
			}
			string[] allAssetNames = val.GetAllAssetNames();
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[ShieldBash] Bundle contains " + allAssetNames.Length + " assets."));
			_bashClip = FindAnimationClip(val, "AttackShield01");
			_hitClip = FindAudioClip(val, HitClipName.Value);
			_missClip = FindAudioClip(val, MissClipName.Value);
			if ((Object)(object)_bashClip == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] AnimationClip 'AttackShield01' was not found in the AssetBundle.");
				((BaseUnityPlugin)this).Logger.LogError((object)("[ShieldBash] Assets:\n - " + string.Join("\n - ", allAssetNames)));
				return false;
			}
			if ((Object)(object)_hitClip == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[ShieldBash] Hit AudioClip was not found: " + HitClipName.Value));
			}
			if ((Object)(object)_missClip == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[ShieldBash] Miss AudioClip was not found: " + MissClipName.Value));
			}
			return true;
		}
		catch (Exception ex3)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[ShieldBash] AssetBundle load exception: " + ex3));
			return false;
		}
		finally
		{
			if ((Object)(object)val != (Object)null)
			{
				val.Unload(false);
			}
		}
	}

	private static void AddBundleCandidates(List<string> candidates, string directory)
	{
		if (!string.IsNullOrEmpty(directory))
		{
			candidates.Add(Path.Combine(directory, "shieldbashbundle"));
			candidates.Add(Path.Combine(directory, "shieldbashbundle.bundle"));
		}
	}

	private static AnimationClip FindAnimationClip(AssetBundle bundle, string preferredName)
	{
		AnimationClip[] array = bundle.LoadAllAssets<AnimationClip>();
		if (array == null || array.Length == 0)
		{
			return null;
		}
		foreach (AnimationClip val in array)
		{
			if ((Object)(object)val != (Object)null && ((Object)val).name.Equals(preferredName, StringComparison.OrdinalIgnoreCase))
			{
				return val;
			}
		}
		return null;
	}

	private static AudioClip FindAudioClip(AssetBundle bundle, string preferredName)
	{
		AudioClip[] array = bundle.LoadAllAssets<AudioClip>();
		if (array == null || array.Length == 0)
		{
			return null;
		}
		string value = (preferredName ?? string.Empty).Trim();
		foreach (AudioClip val in array)
		{
			if ((Object)(object)val != (Object)null && ((Object)val).name.Equals(value, StringComparison.OrdinalIgnoreCase))
			{
				return val;
			}
		}
		return null;
	}

	private ZNetView GetZNetView(Character character)
	{
		if ((Object)(object)character == (Object)null || CharacterNViewField == null)
		{
			return null;
		}
		try
		{
			object? value = CharacterNViewField.GetValue(character);
			return (ZNetView)((value is ZNetView) ? value : null);
		}
		catch
		{
			return null;
		}
	}

	private Animator GetAnimator(Character character)
	{
		if ((Object)(object)character == (Object)null || CharacterAnimatorField == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] Character.m_animator was not found.");
			return null;
		}
		try
		{
			object? value = CharacterAnimatorField.GetValue(character);
			return (Animator)((value is Animator) ? value : null);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[ShieldBash] Cannot read Character.m_animator: " + ex.Message));
			return null;
		}
	}

	private Rigidbody GetCharacterBody(Character character)
	{
		if ((Object)(object)character == (Object)null || CharacterBodyField == null)
		{
			return null;
		}
		try
		{
			object? value = CharacterBodyField.GetValue(character);
			return (Rigidbody)((value is Rigidbody) ? value : null);
		}
		catch
		{
			return null;
		}
	}

	private ItemData GetLeftItem(Humanoid humanoid)
	{
		if ((Object)(object)humanoid == (Object)null || HumanoidLeftItemField == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] Humanoid.m_leftItem was not found.");
			return null;
		}
		try
		{
			object? value = HumanoidLeftItemField.GetValue(humanoid);
			return (ItemData)((value is ItemData) ? value : null);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[ShieldBash] Cannot read Humanoid.m_leftItem: " + ex.Message));
			return null;
		}
	}

	private static void EnsureLocalizationReflection()
	{
		if (_locRefReady)
		{
			return;
		}
		_locRefReady = true;
		try
		{
			_locType = AccessTools.TypeByName("Localization");
			if (!(_locType == null))
			{
				_locInstanceProp = _locType.GetProperty("instance", BindingFlags.Static | BindingFlags.Public);
				_locGetSelectedLanguage = _locType.GetMethod("GetSelectedLanguage", BindingFlags.Instance | BindingFlags.Public);
			}
		}
		catch
		{
			_locType = null;
			_locInstanceProp = null;
			_locGetSelectedLanguage = null;
		}
	}

	private static string GetGameLanguage()
	{
		EnsureLocalizationReflection();
		if (_locInstanceProp == null || _locGetSelectedLanguage == null)
		{
			return null;
		}
		try
		{
			object value = _locInstanceProp.GetValue(null, null);
			if (value == null)
			{
				return null;
			}
			return _locGetSelectedLanguage.Invoke(value, null) as string;
		}
		catch
		{
			return null;
		}
	}

	private static bool IsRussianUi()
	{
		string gameLanguage = GetGameLanguage();
		if (string.IsNullOrEmpty(gameLanguage))
		{
			return false;
		}
		gameLanguage = gameLanguage.ToLowerInvariant();
		return gameLanguage.Contains("russian") || gameLanguage.StartsWith("ru");
	}

	internal string BuildTooltipLineForShield(ItemData item)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Invalid comparison between Unknown and I4
		if (item == null || item.m_shared == null)
		{
			return null;
		}
		if ((int)item.m_shared.m_itemType != 5)
		{
			return null;
		}
		Player localPlayer = Player.m_localPlayer;
		float blockingSkillFactor = GetBlockingSkillFactor(localPlayer);
		float baseDamage = ComputeShieldBaseDamage(item);
		float num = DamageRandomMin.Value;
		float num2 = DamageRandomMax.Value;
		if (num > num2)
		{
			float num3 = num;
			num = num2;
			num2 = num3;
		}
		float num4 = ApplySkillAndRandom(baseDamage, blockingSkillFactor, num);
		float num5 = ApplySkillAndRandom(baseDamage, blockingSkillFactor, num2);
		float num6 = ComputeStaminaCost(localPlayer, item);
		if (IsRussianUi())
		{
			return $"\nУдар щитом: {num4:0}–{num5:0} (дробящий)\nВыносливость: {num6:0.#}\n";
		}
		return $"\nShield Bash: {num4:0}–{num5:0} (blunt)\nStamina: {num6:0.#}\n";
	}
}