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();
shieldHealth.BuildExtendedCatch();
}
}
}
}
[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();
}
}
}
}
[HarmonyPatch(typeof(SurfaceBlock), "DoEffect", new Type[]
{
typeof(HitData),
typeof(GameObject)
})]
internal static class SurfaceBlockProjectHitPatch
{
private static void Prefix(ref HitData hit, GameObject projectile)
{
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
if (!Plugin.Enabled.Value || hit == null || (Object)(object)hit.collider == (Object)null)
{
return;
}
ShieldExtendedCatch component = ((Component)hit.collider).GetComponent<ShieldExtendedCatch>();
if ((Object)(object)component == (Object)null)
{
return;
}
Collider visibleCollider = component.visibleCollider;
if (!((Object)(object)visibleCollider == (Object)null) && visibleCollider.enabled)
{
Vector3 val = visibleCollider.ClosestPoint(hit.point);
hit.point = val;
if ((Object)(object)projectile != (Object)null)
{
projectile.transform.position = val;
}
}
}
}
[BepInPlugin("local.breakableshields", "BreakableShields", "2.0.0")]
public class Plugin : BaseUnityPlugin
{
public const string GUID = "local.breakableshields";
public const string Name = "BreakableShields";
public const string Version = "2.0.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;
internal static ConfigEntry<float> ExtendedCatchScale;
internal static ConfigEntry<float> BashBaseDamage;
internal static ConfigEntry<float> BashStaggerPerDamage;
private void Awake()
{
//IL_0192: 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", 200f, "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", 3f, "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.");
ExtendedCatchScale = ((BaseUnityPlugin)this).Config.Bind<float>("Catch", "ExtendedCatchScale", 1.3f, "Multiplier for the invisible catch collider. 1.3 = 30% larger catch zone around the visible shield. Hit positions on this zone are projected back onto the visible shield so arrows still appear to hit the shield.");
BashBaseDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Bash", "BashBaseDamage", 100f, "Fallback damage value used by the shield bash stagger calculation when the shield's own CollisionWeapon deals no damage.");
BashStaggerPerDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Bash", "BashStaggerPerDamage", 0.005f, "Stagger duration (seconds) per point of damage actually dealt by a shield bash. Default 0.005 means 100 damage = 0.5s. Stagger prevents movement and attacking, but does not ragdoll the target.");
new Harmony("local.breakableshields").PatchAll();
((BaseUnityPlugin)this).Logger.LogInfo((object)"BreakableShields 2.0.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 GameObject _extendedCatchGo;
private Collider _extendedCatchCollider;
private ShieldExtendedCatch _extendedCatchMarker;
private bool _catchBuilt;
private float _lastBashTime;
private static readonly MethodInfo DontWalkForMethod = typeof(DataHandler).GetMethod("DontWalkFor", BindingFlags.Instance | BindingFlags.NonPublic);
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>();
}
CollisionWeapon[] componentsInChildren = ((Component)this).GetComponentsInChildren<CollisionWeapon>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
if ((Object)(object)componentsInChildren[i] != (Object)null)
{
componentsInChildren[i].AddDealDamageAction((Action<Collision, float, Vector3>)OnBashDealDamage);
}
}
}
private void OnBashDealDamage(Collision collision, float damage, Vector3 direction)
{
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_014c: Unknown result type (might be due to invalid IL or missing references)
if (!Plugin.Enabled.Value || broken || collision == null || (Object)(object)collision.rigidbody == (Object)null)
{
return;
}
float num = damage;
if (num <= 0f)
{
num = Mathf.Max(0f, Plugin.BashBaseDamage.Value);
}
float num2 = Mathf.Max(0f, Plugin.BashStaggerPerDamage.Value);
float num3 = num * num2;
if (num3 <= 0f || Time.time - _lastBashTime < 0.25f)
{
return;
}
_lastBashTime = Time.time;
Unit val = ((Component)collision.rigidbody).GetComponentInParent<Unit>();
if ((Object)(object)val == (Object)null)
{
val = ((Component)collision.transform.root).GetComponent<Unit>();
}
if ((Object)(object)val == (Object)null)
{
return;
}
Unit val2 = null;
if ((Object)(object)_holdable != (Object)null && (Object)(object)_holdable.holderData != (Object)null)
{
val2 = ((Component)_holdable.holderData).GetComponentInParent<Unit>();
}
if ((Object)(object)val2 == (Object)null)
{
val2 = ((Component)this).GetComponentInParent<Unit>();
}
if ((Object)(object)val2 != (Object)null && (Object)(object)val2 == (Object)(object)val)
{
return;
}
if ((Object)(object)val2 != (Object)null)
{
TeamHolder component = ((Component)val2).GetComponent<TeamHolder>();
TeamHolder component2 = ((Component)val).GetComponent<TeamHolder>();
if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null && component.team == component2.team)
{
return;
}
}
Plugin.Dbg("[BreakableShields] Bash dealt " + num.ToString("0.#") + " dmg -> stagger " + num3.ToString("0.###") + "s on " + ((Object)((Component)val).gameObject).name);
ApplyStagger(val, num3);
}
private void Start()
{
InitStats();
if ((Object)(object)_holdable != (Object)null && _holdable.held)
{
BuildExtendedCatch();
}
}
private void Update()
{
if (_catchBuilt && !((Object)(object)_extendedCatchGo == (Object)null) && (Object)(object)_holdable != (Object)null && !_holdable.held)
{
DestroyExtendedCatch(allowRebuild: true);
}
}
private void OnDestroy()
{
DestroyExtendedCatch();
}
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_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Unknown result type (might be due to invalid IL or missing references)
//IL_0108: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Unknown result type (might be due to invalid IL or missing references)
//IL_0117: 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);
DestroyExtendedCatch();
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);
}
}
}
public void BuildExtendedCatch()
{
//IL_010b: Unknown result type (might be due to invalid IL or missing references)
//IL_0115: Expected O, but got Unknown
//IL_0137: Unknown result type (might be due to invalid IL or missing references)
//IL_014c: Unknown result type (might be due to invalid IL or missing references)
//IL_0152: 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_0167: Unknown result type (might be due to invalid IL or missing references)
//IL_016d: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
//IL_0178: Unknown result type (might be due to invalid IL or missing references)
//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
if (_catchBuilt || broken || (Object)(object)_blockMove == (Object)null)
{
return;
}
float num = Mathf.Max(1.01f, Plugin.ExtendedCatchScale.Value);
Collider val = null;
SurfaceBlock[] componentsInChildren = ((Component)this).GetComponentsInChildren<SurfaceBlock>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
if (!((Object)(object)componentsInChildren[i] == (Object)null))
{
Collider component = ((Component)componentsInChildren[i]).GetComponent<Collider>();
if ((Object)(object)component != (Object)null && component.enabled && !component.isTrigger)
{
val = component;
break;
}
}
}
if ((Object)(object)val == (Object)null)
{
Collider[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<Collider>(true);
for (int j = 0; j < componentsInChildren2.Length; j++)
{
if ((Object)(object)componentsInChildren2[j] != (Object)null && componentsInChildren2[j].enabled && !componentsInChildren2[j].isTrigger)
{
val = componentsInChildren2[j];
break;
}
}
}
if ((Object)(object)val == (Object)null)
{
Plugin.Dbg("[BreakableShields] ExtendedCatch skipped: no visible collider for " + ((Object)((Component)this).gameObject).name);
_catchBuilt = true;
return;
}
_extendedCatchGo = new GameObject("ShieldExtendedCatch");
_extendedCatchGo.transform.SetParent(((Component)val).transform, false);
_extendedCatchGo.transform.localRotation = Quaternion.identity;
_extendedCatchGo.transform.localScale = Vector3.one * num;
Vector3 forward = ((Component)val).transform.forward;
Bounds bounds = val.bounds;
float num2 = 2f * Mathf.Abs(Vector3.Dot(forward, ((Bounds)(ref bounds)).extents));
float num3 = (num - 1f) * 0.5f * Mathf.Max(num2, 0.01f);
Transform transform = _extendedCatchGo.transform;
bounds = val.bounds;
transform.position = ((Bounds)(ref bounds)).center + forward * num3;
Collider val2 = CopyColliderTo(val, _extendedCatchGo);
if ((Object)(object)val2 == (Object)null)
{
Object.Destroy((Object)(object)_extendedCatchGo);
_extendedCatchGo = null;
Plugin.Dbg("[BreakableShields] ExtendedCatch skipped: unsupported collider type " + ((object)val).GetType().Name + " on " + ((Object)((Component)this).gameObject).name);
_catchBuilt = true;
return;
}
val2.isTrigger = false;
_extendedCatchCollider = val2;
_extendedCatchMarker = _extendedCatchGo.AddComponent<ShieldExtendedCatch>();
_extendedCatchMarker.visibleCollider = val;
_extendedCatchGo.AddComponent<SurfaceBlock>().blockMove = _blockMove;
_catchBuilt = true;
Plugin.Dbg("[BreakableShields] ExtendedCatch built for " + ((Object)((Component)this).gameObject).name + " scale=" + num.ToString("0.##") + " outwardOffset=" + num3.ToString("0.###"));
}
private static Collider CopyColliderTo(Collider src, GameObject dstGo)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected O, but got Unknown
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: 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)
//IL_0051: Expected O, but got Unknown
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Expected O, but got Unknown
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Expected O, but got Unknown
//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)src == (Object)null || (Object)(object)dstGo == (Object)null)
{
return null;
}
if (src is BoxCollider)
{
BoxCollider val = (BoxCollider)src;
BoxCollider obj = dstGo.AddComponent<BoxCollider>();
obj.center = val.center;
obj.size = val.size;
return (Collider)(object)obj;
}
if (src is SphereCollider)
{
SphereCollider val2 = (SphereCollider)src;
SphereCollider obj2 = dstGo.AddComponent<SphereCollider>();
obj2.center = val2.center;
obj2.radius = val2.radius;
return (Collider)(object)obj2;
}
if (src is CapsuleCollider)
{
CapsuleCollider val3 = (CapsuleCollider)src;
CapsuleCollider obj3 = dstGo.AddComponent<CapsuleCollider>();
obj3.center = val3.center;
obj3.radius = val3.radius;
obj3.height = val3.height;
obj3.direction = val3.direction;
return (Collider)(object)obj3;
}
if (src is MeshCollider)
{
MeshCollider val4 = (MeshCollider)src;
MeshCollider obj4 = dstGo.AddComponent<MeshCollider>();
obj4.sharedMesh = val4.sharedMesh;
obj4.convex = val4.convex;
obj4.cookingOptions = val4.cookingOptions;
return (Collider)(object)obj4;
}
return null;
}
public void DestroyExtendedCatch(bool allowRebuild = false)
{
if ((Object)(object)_extendedCatchGo != (Object)null)
{
Object.Destroy((Object)(object)_extendedCatchGo);
_extendedCatchGo = null;
_extendedCatchCollider = null;
_extendedCatchMarker = null;
}
if (allowRebuild)
{
_catchBuilt = false;
}
}
public void ApplyStagger(Unit target, float duration)
{
if ((Object)(object)target == (Object)null || (Object)(object)target.data == (Object)null || duration <= 0f)
{
return;
}
DataHandler data = target.data;
MethodInfo dontWalkForMethod = DontWalkForMethod;
if (dontWalkForMethod != null)
{
try
{
dontWalkForMethod.Invoke(data, new object[1] { duration });
}
catch (Exception)
{
}
}
if ((Object)(object)data.weaponHandler != (Object)null)
{
data.weaponHandler.DelayAttackCounter(duration * 2f);
Weapon rightWeapon = data.weaponHandler.rightWeapon;
MeleeWeapon val = (MeleeWeapon)(object)((rightWeapon is MeleeWeapon) ? rightWeapon : null);
if (val != null)
{
val.StopSwing();
}
Weapon leftWeapon = data.weaponHandler.leftWeapon;
MeleeWeapon val2 = (MeleeWeapon)(object)((leftWeapon is MeleeWeapon) ? leftWeapon : null);
if (val2 != null)
{
val2.StopSwing();
}
}
}
}
public class ShieldExtendedCatch : MonoBehaviour
{
public Collider visibleCollider;
}
}