static void Prefix(RuleCheckTargetFlatFooted __instance)
        {
            bool ignore_initiative = (__instance.Target.Get <UnitPartNotFlatFootedBeforeInitiative>()?.active()).GetValueOrDefault();
            bool is_flat_footed    = __instance.ForceFlatFooted ||
                                     !__instance.Target.CombatState.CanActInCombat && !__instance.IgnoreVisibility && !ignore_initiative ||
                                     (__instance.Target.Descriptor.State.IsHelpless ||
                                      __instance.Target.Descriptor.State.HasCondition(UnitCondition.Stunned) ||
                                      !__instance.Target.Memory.Contains(__instance.Initiator) && !__instance.IgnoreVisibility) ||
                                     (UnitPartConcealment.Calculate(__instance.Target, __instance.Initiator, false) == Concealment.Total && !__instance.IgnoreConcealment ||
                                      __instance.Target.Descriptor.State.HasCondition(UnitCondition.LoseDexterityToAC)) ||
                                     ((__instance.Target.Descriptor.State.HasCondition(UnitCondition.Shaken) ||
                                       __instance.Target.Descriptor.State.HasCondition(UnitCondition.Frightened)) &&
                                      (bool)__instance.Initiator.Descriptor.State.Features.ShatterDefenses);

            //TODO: fix shatter defenses not to apply on first hit
            var tr = Harmony12.Traverse.Create(__instance);

            tr.Property("IsFlatFooted").SetValue(is_flat_footed);
        }
        static bool Prefix(UnitEntityData unit, UnitEntityData enemy, ref bool __result)
        {
            __result = false;
            if (!unit.Descriptor.State.CanAct)
            {
                return(false);
            }
            WeaponSlot threatHand = unit.GetThreatHand();

            if (threatHand == null || !unit.IsReach(enemy, threatHand))
            {
                var aoo_part = unit.Get <UnitPartSpecialAttackOfOportunity>();
                if (aoo_part == null || !aoo_part.canMakeAoo(enemy))
                {
                    return(false);
                }
            }
            __result = UnitPartConcealment.Calculate(unit, enemy, false) != Concealment.Total;
            return(false);
        }