Decompiled source of BreakableShields v1.2.0

BreakableShields.dll

Decompiled 3 days ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Landfall.TABS;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("BreakableShields")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BreakableShields")]
[assembly: AssemblyTitle("BreakableShields")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BreakableShields
{
	[HarmonyPatch(typeof(Holdable), "Start")]
	internal static class HoldableStartPatch
	{
		private static void Postfix(Holdable __instance)
		{
			if (Plugin.Enabled.Value && !((Object)(object)__instance == (Object)null))
			{
				ShieldHealth.EnsureOn(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Holdable), "WasGrabbed")]
	internal static class HoldableGrabPatch
	{
		private static void Postfix(Holdable __instance)
		{
			if (Plugin.Enabled.Value && !((Object)(object)__instance == (Object)null))
			{
				ShieldHealth shieldHealth = ShieldHealth.EnsureOn(__instance);
				if ((Object)(object)shieldHealth != (Object)null)
				{
					shieldHealth.InitStats();
					shieldHealth.TryApplyHolderHealth();
				}
			}
		}
	}
	[HarmonyPatch(typeof(BlockMove), "ProjectileBlock")]
	internal static class BlockMoveProjectilePatch
	{
		private static void Postfix(BlockMove __instance, GameObject projectile, HitData hit, bool __result)
		{
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Enabled.Value || !__result || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			ShieldHealth shieldHealth = ((Component)__instance).GetComponentInParent<ShieldHealth>();
			if ((Object)(object)shieldHealth == (Object)null && (Object)(object)__instance.rig != (Object)null)
			{
				shieldHealth = ((Component)__instance.rig).GetComponentInParent<ShieldHealth>();
			}
			if ((Object)(object)shieldHealth == (Object)null)
			{
				DataHandler componentInChildren = ((Component)((Component)__instance).transform.root).GetComponentInChildren<DataHandler>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					HoldingHandler component = ((Component)componentInChildren).GetComponent<HoldingHandler>();
					if ((Object)(object)component != (Object)null)
					{
						if ((Object)(object)component.leftObject != (Object)null)
						{
							shieldHealth = ((Component)component.leftObject).GetComponent<ShieldHealth>() ?? ShieldHealth.EnsureOn(component.leftObject);
						}
						if ((Object)(object)shieldHealth == (Object)null && (Object)(object)component.rightObject != (Object)null)
						{
							shieldHealth = ((Component)component.rightObject).GetComponent<ShieldHealth>() ?? ShieldHealth.EnsureOn(component.rightObject);
						}
					}
				}
			}
			if (!((Object)(object)shieldHealth == (Object)null) && !shieldHealth.broken)
			{
				float num = 0f;
				ProjectileHit val = (((Object)(object)projectile != (Object)null) ? projectile.GetComponent<ProjectileHit>() : null);
				if ((Object)(object)val != (Object)null)
				{
					num = val.damage;
				}
				if (num <= 0f)
				{
					num = 25f;
				}
				num *= Plugin.ProjectileDamageMultiplier.Value;
				Vector3 direction = ((hit != null) ? (-hit.normal) : Vector3.forward);
				Unit damager = null;
				TeamHolder val2 = (((Object)(object)projectile != (Object)null) ? projectile.GetComponent<TeamHolder>() : null);
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2.spawner != (Object)null)
				{
					damager = val2.spawner.GetComponentInParent<Unit>();
				}
				shieldHealth.ApplyDamage(num, direction, damager, "ProjectileBlock");
			}
		}
	}
	[HarmonyPatch(typeof(CollisionWeapon), "OnCollisionEnter")]
	internal static class CollisionWeaponShieldPatch
	{
		private static void Prefix(CollisionWeapon __instance, Collision collision)
		{
			//IL_00bb: 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)
			if (!Plugin.Enabled.Value || (Object)(object)__instance == (Object)null || collision == null || (Object)(object)collision.rigidbody == (Object)null)
			{
				return;
			}
			Holdable componentInParent = ((Component)collision.rigidbody).GetComponentInParent<Holdable>();
			if ((Object)(object)componentInParent == (Object)null || !componentInParent.held || !ShieldHealth.IsShieldObject(((Component)componentInParent).gameObject))
			{
				return;
			}
			if ((Object)(object)componentInParent.holderData != (Object)null)
			{
				Unit componentInParent2 = ((Component)__instance).GetComponentInParent<Unit>();
				if ((Object)(object)componentInParent2 == (Object)null)
				{
					Holdable component = ((Component)__instance).GetComponent<Holdable>();
					if ((Object)(object)component != (Object)null && (Object)(object)component.holderData != (Object)null)
					{
						componentInParent2 = ((Component)component.holderData).GetComponentInParent<Unit>();
					}
				}
				Unit componentInParent3 = ((Component)componentInParent.holderData).GetComponentInParent<Unit>();
				if ((Object)(object)componentInParent2 != (Object)null && (Object)(object)componentInParent3 != (Object)null && componentInParent2.Team == componentInParent3.Team)
				{
					return;
				}
			}
			ShieldHealth.EnsureOn(componentInParent);
		}
	}
	[HarmonyPatch(typeof(ShieldHealth), "TakeDamage")]
	internal static class ShieldTakeDamageMultPatch
	{
		private static void Prefix(ref float damage)
		{
			if (Plugin.Enabled.Value)
			{
				damage *= Plugin.MeleeDamageMultiplier.Value;
			}
		}
	}
	[HarmonyPatch(typeof(WeaponHandler), "Start")]
	internal static class WeaponHandlerStartPatch
	{
		private static void Postfix(WeaponHandler __instance)
		{
			if (Plugin.Enabled.Value && !((Object)(object)__instance == (Object)null))
			{
				TryAttach(__instance.leftWeapon);
				TryAttach(__instance.rightWeapon);
			}
		}

		private static void TryAttach(Weapon weapon)
		{
			if ((Object)(object)weapon == (Object)null)
			{
				return;
			}
			Holdable component = ((Component)weapon).GetComponent<Holdable>();
			if ((Object)(object)component != (Object)null)
			{
				ShieldHealth shieldHealth = ShieldHealth.EnsureOn(component);
				if ((Object)(object)shieldHealth != (Object)null)
				{
					shieldHealth.TryApplyHolderHealth();
				}
			}
		}
	}
	[BepInPlugin("local.breakableshields", "BreakableShields", "1.2.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "local.breakableshields";

		public const string Name = "BreakableShields";

		public const string Version = "1.2.0";

		internal static Plugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<float> BaseHealth;

		internal static ConfigEntry<float> HolderHealthMultiplier;

		internal static ConfigEntry<float> MeleeDamageMultiplier;

		internal static ConfigEntry<float> ProjectileDamageMultiplier;

		internal static ConfigEntry<bool> BreakDropsShield;

		internal static ConfigEntry<bool> DisableBlockOnBreak;

		internal static ConfigEntry<bool> DebugLog;

		private void Awake()
		{
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable breakable shields.");
			DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLog", false, "Log shield attach/damage/break events.");
			BaseHealth = ((BaseUnityPlugin)this).Config.Bind<float>("Health", "BaseHealth", 400f, "Base shield HP. Final = BaseHealth + HolderHealthMultiplier * holder max HP.");
			HolderHealthMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Health", "HolderHealthMultiplier", 3f, "Shield HP adds this * holder's maxHealth.");
			MeleeDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "MeleeDamageMultiplier", 1f, "Multiplier for melee damage applied to shields.");
			ProjectileDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "ProjectileDamageMultiplier", 1f, "Multiplier for projectile damage applied to shields.");
			BreakDropsShield = ((BaseUnityPlugin)this).Config.Bind<bool>("Break", "DropOnBreak", true, "Drop the shield from the unit's hands when HP reaches 0.");
			DisableBlockOnBreak = ((BaseUnityPlugin)this).Config.Bind<bool>("Break", "DisableBlockOnBreak", true, "Disable projectile blocking when the shield breaks.");
			new Harmony("local.breakableshields").PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"BreakableShields 1.2.0 loaded.");
		}

		internal static void Dbg(string msg)
		{
			if (DebugLog != null && DebugLog.Value)
			{
				Log.LogInfo((object)msg);
			}
		}
	}
	public class ShieldHealth : Damagable
	{
		public float maxHealth = 400f;

		public float health = 400f;

		public bool broken;

		private Holdable _holdable;

		private BlockMove _blockMove;

		private BlockMoveHealth _blockMoveHealth;

		private Rigidbody _rig;

		private bool _initialized;

		private bool _statsFromHolderApplied;

		private static readonly FieldInfo LeftHandJointField = typeof(HoldingHandler).GetField("leftHandJoint", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo RightHandJointField = typeof(HoldingHandler).GetField("rightHandJoint", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo UnitApiField = typeof(WeaponHandler).GetField("m_unitAPI", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo WhUnitField = typeof(WeaponHandler).GetField("unit", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo WhDataField = typeof(WeaponHandler).GetField("data", BindingFlags.Instance | BindingFlags.NonPublic);

		public static bool IsShieldObject(GameObject go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return false;
			}
			if ((Object)(object)go.GetComponentInChildren<BlockMove>(true) != (Object)null)
			{
				return true;
			}
			if ((Object)(object)go.GetComponentInChildren<SurfaceBlock>(true) != (Object)null)
			{
				return true;
			}
			string name = ((Object)go).name;
			if (string.IsNullOrEmpty(name))
			{
				return false;
			}
			name = name.ToLowerInvariant();
			if (!name.Contains("shield") && !name.Contains("buckler"))
			{
				return name.Contains("pavise");
			}
			return true;
		}

		public static ShieldHealth EnsureOn(Holdable holdable)
		{
			if ((Object)(object)holdable == (Object)null)
			{
				return null;
			}
			ShieldHealth component = ((Component)holdable).GetComponent<ShieldHealth>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			if (!IsShieldObject(((Component)holdable).gameObject))
			{
				return null;
			}
			return ((Component)holdable).gameObject.AddComponent<ShieldHealth>();
		}

		private void Awake()
		{
			_holdable = ((Component)this).GetComponent<Holdable>();
			_blockMove = ((Component)this).GetComponentInChildren<BlockMove>(true);
			_blockMoveHealth = ((Component)this).GetComponentInChildren<BlockMoveHealth>(true);
			_rig = ((Component)this).GetComponent<Rigidbody>();
			if ((Object)(object)_rig == (Object)null)
			{
				_rig = ((Component)this).GetComponentInChildren<Rigidbody>();
			}
		}

		private void Start()
		{
			InitStats();
		}

		public void InitStats()
		{
			if (!_initialized)
			{
				_initialized = true;
				maxHealth = Mathf.Max(1f, Plugin.BaseHealth.Value);
				health = maxHealth;
				if ((Object)(object)_blockMoveHealth != (Object)null)
				{
					((Behaviour)_blockMoveHealth).enabled = false;
				}
				TryApplyHolderHealth();
				Plugin.Dbg("[BreakableShields] Init " + ((Object)((Component)this).gameObject).name + " HP=" + maxHealth);
			}
		}

		public void TryApplyHolderHealth()
		{
			if (!broken && !_statsFromHolderApplied && !((Object)(object)_holdable == (Object)null) && !((Object)(object)_holdable.holderData == (Object)null))
			{
				float num = _holdable.holderData.maxHealth;
				if (num <= 0f)
				{
					num = _holdable.holderData.health;
				}
				if (!(num <= 0f))
				{
					float num2 = Plugin.BaseHealth.Value + Plugin.HolderHealthMultiplier.Value * num;
					maxHealth = Mathf.Max(1f, num2);
					health = maxHealth;
					_statsFromHolderApplied = true;
					Plugin.Dbg("[BreakableShields] Stats from holder " + ((Object)((Component)this).gameObject).name + " holderHP=" + num + " shieldHP=" + maxHealth);
				}
			}
		}

		public override void TakeDamage(float damage, Vector3 direction, Unit damager = null, DamageType damageType = (DamageType)0)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			ApplyDamage(damage, direction, damager, "TakeDamage");
		}

		public void ApplyDamage(float damage, Vector3 direction, Unit damager, string source)
		{
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Enabled.Value || broken)
			{
				return;
			}
			if (!_initialized)
			{
				InitStats();
			}
			if (!_statsFromHolderApplied)
			{
				TryApplyHolderHealth();
			}
			if (!(damage <= 0f) && !float.IsNaN(damage) && !float.IsInfinity(damage) && (!((Object)(object)_holdable != (Object)null) || _holdable.held || broken))
			{
				health -= damage;
				Plugin.Dbg("[BreakableShields] " + ((Object)((Component)this).gameObject).name + " -" + damage.ToString("0.#") + " via " + source + " => " + health.ToString("0.#") + "/" + maxHealth.ToString("0.#"));
				if (health <= 0f)
				{
					Break(direction, damager);
				}
			}
		}

		public void Break(Vector3 direction, Unit damager)
		{
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: 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)
			if (broken)
			{
				return;
			}
			broken = true;
			health = 0f;
			Plugin.Dbg("[BreakableShields] BREAK " + ((Object)((Component)this).gameObject).name);
			if (Plugin.DisableBlockOnBreak.Value)
			{
				if ((Object)(object)_blockMove != (Object)null)
				{
					_blockMove.SetDisabled();
				}
				SurfaceBlock[] componentsInChildren = ((Component)this).GetComponentsInChildren<SurfaceBlock>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					((Behaviour)componentsInChildren[i]).enabled = false;
				}
			}
			if (!((Object)((Component)this).gameObject).name.EndsWith("_Broken"))
			{
				((Object)((Component)this).gameObject).name = ((Object)((Component)this).gameObject).name + "_Broken";
			}
			if (Plugin.BreakDropsShield.Value)
			{
				ForceDropCompletely();
			}
			if ((Object)(object)_rig != (Object)null)
			{
				_rig.isKinematic = false;
				if (((Vector3)(ref direction)).sqrMagnitude > 0.01f)
				{
					_rig.AddForce(((Vector3)(ref direction)).normalized * 8f + Vector3.up * 2f, (ForceMode)1);
				}
			}
		}

		public void ForceDropCompletely()
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Invalid comparison between Unknown and I4
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Invalid comparison between Unknown and I4
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_holdable == (Object)null)
			{
				return;
			}
			HoldingHandler val = null;
			DataHandler holderData = _holdable.holderData;
			if ((Object)(object)holderData != (Object)null)
			{
				val = ((Component)holderData).GetComponent<HoldingHandler>();
			}
			if ((Object)(object)val == (Object)null && (Object)(object)_holdable.holdingHandler != (Object)null)
			{
				val = _holdable.holdingHandler;
			}
			bool ignoreDissarm = _holdable.ignoreDissarm;
			_holdable.ignoreDissarm = false;
			try
			{
				bool flag = false;
				bool flag2 = false;
				if ((Object)(object)val != (Object)null)
				{
					bool flag3 = (Object)(object)val.rightObject == (Object)(object)_holdable;
					bool flag4 = (Object)(object)val.leftObject == (Object)(object)_holdable;
					bool flag5 = flag3 && (int)val.leftHandActivity == 1;
					bool flag6 = flag4 && (int)val.rightHandActivity == 2;
					if (!flag3 && !flag4)
					{
						WeaponHandler component = ((Component)val).GetComponent<WeaponHandler>();
						if ((Object)(object)component != (Object)null)
						{
							if ((Object)(object)component.leftWeapon != (Object)null && (Object)(object)((Component)component.leftWeapon).gameObject == (Object)(object)((Component)this).gameObject)
							{
								component.leftWeapon = null;
								flag = true;
							}
							if ((Object)(object)component.rightWeapon != (Object)null && (Object)(object)((Component)component.rightWeapon).gameObject == (Object)(object)((Component)this).gameObject)
							{
								component.rightWeapon = null;
								flag2 = true;
							}
						}
						val.LetGoOfWeapon(((Component)this).gameObject);
						if (_holdable.held)
						{
							_holdable.WasDropped();
						}
					}
					else
					{
						if (_holdable.held)
						{
							_holdable.WasDropped();
						}
						flag2 = flag3 || flag6;
						flag = flag4 || flag5;
						if (flag2)
						{
							val.rightHandActivity = (HandActivity)0;
						}
						if (flag)
						{
							val.leftHandActivity = (HandActivity)0;
						}
						DestroyJointField(val, RightHandJointField, flag2);
						DestroyJointField(val, LeftHandJointField, flag);
						if (flag3)
						{
							if ((Object)(object)_holdable.rig != (Object)null)
							{
								_holdable.rig.isKinematic = false;
							}
							if ((Object)(object)((Component)_holdable).GetComponent<SetInterpolation>() == (Object)null)
							{
								((Component)_holdable).gameObject.AddComponent<SetInterpolation>();
							}
							val.rightObject = null;
						}
						if (flag4)
						{
							if ((Object)(object)_holdable.rig != (Object)null)
							{
								_holdable.rig.isKinematic = false;
							}
							if ((Object)(object)((Component)_holdable).GetComponent<SetInterpolation>() == (Object)null)
							{
								((Component)_holdable).gameObject.AddComponent<SetInterpolation>();
							}
							val.leftObject = null;
						}
						if ((Object)(object)_holdable.rig != (Object)null)
						{
							_holdable.rig.isKinematic = false;
						}
						WeaponHandler component2 = ((Component)val).GetComponent<WeaponHandler>();
						if ((Object)(object)component2 != (Object)null)
						{
							if ((Object)(object)component2.leftWeapon != (Object)null && (Object)(object)((Component)component2.leftWeapon).gameObject == (Object)(object)((Component)this).gameObject)
							{
								component2.leftWeapon = null;
								flag = true;
							}
							if ((Object)(object)component2.rightWeapon != (Object)null && (Object)(object)((Component)component2.rightWeapon).gameObject == (Object)(object)((Component)this).gameObject)
							{
								component2.rightWeapon = null;
								flag2 = true;
							}
						}
					}
					ReenableHandColliders(val, flag, flag2);
					WeaponHandler component3 = ((Component)val).GetComponent<WeaponHandler>();
					if ((Object)(object)component3 != (Object)null)
					{
						EquipFistsForFreedHands(component3, flag, flag2);
					}
				}
				else if (_holdable.held)
				{
					_holdable.WasDropped();
					if ((Object)(object)_holdable.rig != (Object)null)
					{
						_holdable.rig.isKinematic = false;
					}
				}
				if ((Object)(object)holderData != (Object)null)
				{
					BreakJointsToHolder(((Component)holderData).transform.root);
				}
			}
			finally
			{
				_holdable.ignoreDissarm = ignoreDissarm;
			}
		}

		private static void EquipFistsForFreedHands(WeaponHandler wh, bool left, bool right)
		{
			if ((Object)(object)wh == (Object)null || (!left && !right))
			{
				return;
			}
			DataHandler val = (DataHandler)((WhDataField != null) ? ((object)/*isinst with value type is only supported in some contexts*/) : ((object)((Component)wh).GetComponent<DataHandler>()));
			if ((Object)(object)val != (Object)null && val.Dead)
			{
				return;
			}
			GameObject fistRefernce = wh.fistRefernce;
			if ((Object)(object)fistRefernce == (Object)null)
			{
				if ((Object)(object)wh.leftWeapon == (Object)null && (Object)(object)wh.rightWeapon == (Object)null)
				{
					wh.UseHands();
				}
				return;
			}
			MeleeWeapon component = fistRefernce.GetComponent<MeleeWeapon>();
			CollisionWeapon component2 = fistRefernce.GetComponent<CollisionWeapon>();
			CollisionSound component3 = fistRefernce.GetComponent<CollisionSound>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
			{
				if ((Object)(object)wh.leftWeapon == (Object)null && (Object)(object)wh.rightWeapon == (Object)null)
				{
					wh.UseHands();
				}
				return;
			}
			Unit val2 = (Unit)((WhUnitField != null) ? ((object)/*isinst with value type is only supported in some contexts*/) : ((object)((Component)wh).GetComponentInParent<Unit>()));
			object obj = ((UnitApiField != null) ? UnitApiField.GetValue(wh) : null);
			if (obj == null && (Object)(object)val2 != (Object)null)
			{
				Component[] components = ((Component)val2).GetComponents<Component>();
				for (int i = 0; i < components.Length; i++)
				{
					if ((Object)(object)components[i] != (Object)null && ((object)components[i]).GetType().Name == "UnitAPI")
					{
						obj = components[i];
						break;
					}
				}
			}
			if (right && (Object)(object)wh.rightWeapon == (Object)null)
			{
				HandRight componentInChildren = ((Component)wh).GetComponentInChildren<HandRight>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					MeleeWeapon val3 = EnsureFistOnHand(((Component)componentInChildren).gameObject, component, component2, component3);
					wh.SetWeapon((Weapon)(object)val3, (HandType)0);
					Plugin.Dbg("[BreakableShields] Equipped fist on RIGHT hand");
				}
			}
			if (left && (Object)(object)wh.leftWeapon == (Object)null)
			{
				HandLeft componentInChildren2 = ((Component)wh).GetComponentInChildren<HandLeft>();
				if ((Object)(object)componentInChildren2 != (Object)null)
				{
					MeleeWeapon val4 = EnsureFistOnHand(((Component)componentInChildren2).gameObject, component, component2, component3);
					wh.SetWeapon((Weapon)(object)val4, (HandType)1);
					Plugin.Dbg("[BreakableShields] Equipped fist on LEFT hand");
				}
			}
			Weapon val5 = null;
			if ((Object)(object)wh.rightWeapon != (Object)null && !IsFistWeapon(wh.rightWeapon))
			{
				val5 = wh.rightWeapon;
			}
			else if ((Object)(object)wh.leftWeapon != (Object)null && !IsFistWeapon(wh.leftWeapon))
			{
				val5 = wh.leftWeapon;
			}
			else if ((Object)(object)wh.rightWeapon != (Object)null)
			{
				val5 = wh.rightWeapon;
			}
			else if ((Object)(object)wh.leftWeapon != (Object)null)
			{
				val5 = wh.leftWeapon;
			}
			if ((Object)(object)val2 != (Object)null && (Object)(object)val5 != (Object)null)
			{
				val2.m_AttackDistance = val5.maxRange;
				val2.m_PreferedDistance = val5.maxRange - 0.3f;
			}
			if (obj != null)
			{
				MethodInfo method = obj.GetType().GetMethod("UpdateECSValues", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (method != null)
				{
					method.Invoke(obj, null);
				}
			}
		}

		private static bool IsFistWeapon(Weapon weapon)
		{
			if ((Object)(object)weapon == (Object)null)
			{
				return false;
			}
			if (!((Object)(object)((Component)weapon).GetComponent<HandLeft>() != (Object)null) && !((Object)(object)((Component)weapon).GetComponent<HandRight>() != (Object)null) && !((Object)(object)((Component)weapon).GetComponentInParent<HandLeft>() != (Object)null))
			{
				return (Object)(object)((Component)weapon).GetComponentInParent<HandRight>() != (Object)null;
			}
			return true;
		}

		private static MeleeWeapon EnsureFistOnHand(GameObject handGo, MeleeWeapon srcMelee, CollisionWeapon srcCol, CollisionSound srcSound)
		{
			MeleeWeapon component = handGo.GetComponent<MeleeWeapon>();
			CollisionWeapon component2 = handGo.GetComponent<CollisionWeapon>();
			if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null)
			{
				CopyMeleeStats(component, srcMelee);
				CopyCollisionStats(component2, srcCol);
				return component;
			}
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			if ((Object)(object)component2 != (Object)null)
			{
				Object.Destroy((Object)(object)component2);
			}
			MeleeWeapon obj = handGo.AddComponent<MeleeWeapon>();
			CollisionWeapon dst = handGo.AddComponent<CollisionWeapon>();
			if ((Object)(object)srcSound != (Object)null)
			{
				CollisionSound val = handGo.GetComponent<CollisionSound>();
				if ((Object)(object)val == (Object)null)
				{
					val = handGo.AddComponent<CollisionSound>();
				}
				val.SoundEffectRef = srcSound.SoundEffectRef;
			}
			CopyMeleeStats(obj, srcMelee);
			CopyCollisionStats(dst, srcCol);
			return obj;
		}

		private static void CopyMeleeStats(MeleeWeapon dst, MeleeWeapon src)
		{
			dst.forceCurve = src.forceCurve;
			dst.curveForce = src.curveForce;
			((Weapon)dst).internalCooldown = ((Weapon)src).internalCooldown;
			((Weapon)dst).maxRange = ((Weapon)src).maxRange;
			dst.setDirectionContinious = src.setDirectionContinious;
			dst.SoundRef = src.SoundRef;
			dst.soundDelay = src.soundDelay;
			dst.canDealDamageOutSideOfSwing = true;
			dst.canDealDamage = true;
		}

		private static void CopyCollisionStats(CollisionWeapon dst, CollisionWeapon src)
		{
			dst.impactMultiplier = src.impactMultiplier;
			dst.damage = src.damage;
			dst.onImpactForce = src.onImpactForce;
		}

		private static void ReenableHandColliders(HoldingHandler hh, bool left, bool right)
		{
			if ((Object)(object)hh == (Object)null)
			{
				return;
			}
			if (right)
			{
				HandRight componentInChildren = ((Component)hh).GetComponentInChildren<HandRight>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					Collider[] componentsInChildren = ((Component)componentInChildren).GetComponentsInChildren<Collider>(true);
					for (int i = 0; i < componentsInChildren.Length; i++)
					{
						componentsInChildren[i].enabled = true;
					}
					Rigidbody component = ((Component)componentInChildren).GetComponent<Rigidbody>();
					if ((Object)(object)component != (Object)null)
					{
						component.isKinematic = false;
					}
				}
			}
			if (!left)
			{
				return;
			}
			HandLeft componentInChildren2 = ((Component)hh).GetComponentInChildren<HandLeft>();
			if ((Object)(object)componentInChildren2 != (Object)null)
			{
				Collider[] componentsInChildren2 = ((Component)componentInChildren2).GetComponentsInChildren<Collider>(true);
				for (int j = 0; j < componentsInChildren2.Length; j++)
				{
					componentsInChildren2[j].enabled = true;
				}
				Rigidbody component2 = ((Component)componentInChildren2).GetComponent<Rigidbody>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.isKinematic = false;
				}
			}
		}

		private static void DestroyJointField(HoldingHandler hh, FieldInfo field, bool should)
		{
			if (should && !(field == null))
			{
				object? value = field.GetValue(hh);
				ConfigurableJoint val = (ConfigurableJoint)((value is ConfigurableJoint) ? value : null);
				if (val != null && (Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
					field.SetValue(hh, null);
				}
			}
		}

		private void BreakJointsToHolder(Transform holderRoot)
		{
			if ((Object)(object)holderRoot == (Object)null)
			{
				return;
			}
			ConfigurableJoint[] componentsInChildren = ((Component)this).GetComponentsInChildren<ConfigurableJoint>(true);
			foreach (ConfigurableJoint val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Rigidbody connectedBody = ((Joint)val).connectedBody;
					if ((Object)(object)connectedBody != (Object)null && (Object)(object)((Component)connectedBody).transform.root == (Object)(object)holderRoot)
					{
						Object.Destroy((Object)(object)val);
					}
				}
			}
			ConfigurableJoint[] componentsInChildren2 = ((Component)holderRoot).GetComponentsInChildren<ConfigurableJoint>(true);
			foreach (ConfigurableJoint val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Joint)val2).connectedBody == (Object)null) && ((Object)(object)((Component)((Joint)val2).connectedBody).transform == (Object)(object)((Component)this).transform || ((Component)((Joint)val2).connectedBody).transform.IsChildOf(((Component)this).transform)))
				{
					Object.Destroy((Object)(object)val2);
				}
			}
		}
	}
}