[WHO] added Ace's Baseball Bat, consolidate related code (#11387)

* TalruumPiper use MustBeBlockedByAllSourceEffect

* Both of Bident Of Thassa's abilities can be made generic

* Goblin Diplomats use generic class (with custom text)

* create MustBeBlockedByAtLeastOneAttachedEffect common effect

* Add Ace's Baseball Bat
This commit is contained in:
ssk97 2023-11-04 03:19:21 -07:00 committed by GitHub
parent 0fbeb10d17
commit 52bb2c5d71
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 225 additions and 280 deletions

View file

@ -0,0 +1,86 @@
package mage.cards.a;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.Condition;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.combat.MustBeBlockedByAtLeastOneAttachedEffect;
import mage.abilities.effects.common.continuous.BoostEquippedEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.keyword.EquipAbility;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
/**
* @author notgreat
*/
public final class AcesBaseballBat extends CardImpl {
private static final FilterControlledCreaturePermanent filterLegendary
= new FilterControlledCreaturePermanent("legendary creature");
static {
filterLegendary.add(SuperType.LEGENDARY.getPredicate());
}
private static final FilterControlledCreaturePermanent filterDalek
= new FilterControlledCreaturePermanent("a Dalek");
static {
filterDalek.add(SubType.DALEK.getPredicate());
}
public AcesBaseballBat(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.EQUIPMENT);
// Equipped creature gets +3/+0
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(3, 0)));
// As long as equipped creature is attacking, it has first strike and must be blocked by a Dalek if able.
Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect(
new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT),
AttachedToAttackingCondition.instance, "As long as equipped creature is attacking, it has first strike"));
ability.addEffect(new MustBeBlockedByAtLeastOneAttachedEffect(filterDalek).concatBy("and"));
this.addAbility(ability);
// Equip legendary creature (1)
this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(1), new TargetControlledCreaturePermanent(filterLegendary), false));
// Equip {3}
this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(3), false));
}
private AcesBaseballBat(final AcesBaseballBat card) {
super(card);
}
@Override
public AcesBaseballBat copy() {
return new AcesBaseballBat(this);
}
}
enum AttachedToAttackingCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
Permanent attachment = game.getPermanent(source.getSourceId());
if (attachment == null || attachment.getAttachedTo() == null) {
return false;
}
Permanent attachedTo = game.getPermanent(attachment.getAttachedTo());
if (attachedTo == null) {
return false;
}
return attachedTo.isAttacking();
}
}

View file

@ -3,23 +3,20 @@ package mage.cards.b;
import java.util.UUID; import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.RequirementEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.combat.AttacksIfAbleAllEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.SuperType; import mage.constants.SuperType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.constants.SetTargetPointer;
import mage.game.events.DamagedPlayerEvent; import mage.filter.StaticFilters;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
/** /**
* *
@ -33,9 +30,13 @@ public final class BidentOfThassa extends CardImpl {
// Whenever a creature you control deals combat damage to a player, you may draw a card. // Whenever a creature you control deals combat damage to a player, you may draw a card.
this.addAbility(new BidentOfThassaTriggeredAbility()); this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility(
new DrawCardSourceControllerEffect(1),
StaticFilters.FILTER_CONTROLLED_A_CREATURE,
true, SetTargetPointer.NONE, true
));
// {1}{U}, {T}: Creatures your opponents control attack this turn if able. // {1}{U}, {T}: Creatures your opponents control attack this turn if able.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BidentOfThassaMustAttackEffect(), new ManaCostsImpl<>("{1}{U}")); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AttacksIfAbleAllEffect(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURES,Duration.EndOfTurn), new ManaCostsImpl<>("{1}{U}"));
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
this.addAbility(ability); this.addAbility(ability);
} }
@ -49,76 +50,3 @@ public final class BidentOfThassa extends CardImpl {
return new BidentOfThassa(this); return new BidentOfThassa(this);
} }
} }
class BidentOfThassaTriggeredAbility extends TriggeredAbilityImpl {
public BidentOfThassaTriggeredAbility() {
super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), true);
}
private BidentOfThassaTriggeredAbility(final BidentOfThassaTriggeredAbility ability) {
super(ability);
}
@Override
public BidentOfThassaTriggeredAbility copy() {
return new BidentOfThassaTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (((DamagedPlayerEvent) event).isCombatDamage()) {
Permanent creature = game.getPermanent(event.getSourceId());
if (creature != null && creature.isControlledBy(controllerId)) {
return true;
}
}
return false;
}
@Override
public String getRule() {
return " Whenever a creature you control deals combat damage to a player, you may draw a card.";
}
}
class BidentOfThassaMustAttackEffect extends RequirementEffect {
public BidentOfThassaMustAttackEffect() {
super(Duration.EndOfTurn);
staticText = "Creatures your opponents control attack this turn if able";
}
private BidentOfThassaMustAttackEffect(final BidentOfThassaMustAttackEffect effect) {
super(effect);
}
@Override
public BidentOfThassaMustAttackEffect copy() {
return new BidentOfThassaMustAttackEffect(this);
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
if (game.getOpponents(source.getControllerId()).contains(permanent.getControllerId())) {
return true;
}
return false;
}
@Override
public boolean mustAttack(Game game) {
return true;
}
@Override
public boolean mustBlock(Game game) {
return false;
}
}

View file

@ -3,18 +3,16 @@ package mage.cards.g;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.RequirementEffect; import mage.abilities.effects.common.combat.AttacksIfAbleAllEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.filter.StaticFilters;
import mage.game.permanent.Permanent;
/** /**
* *
@ -30,7 +28,10 @@ public final class GoblinDiplomats extends CardImpl {
this.toughness = new MageInt(1); this.toughness = new MageInt(1);
// {T}: Each creature attacks this turn if able. // {T}: Each creature attacks this turn if able.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GoblinDiplomatsEffect(), new TapSourceCost())); this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD,
new AttacksIfAbleAllEffect(StaticFilters.FILTER_PERMANENT_ALL_CREATURES, Duration.EndOfTurn)
.setText("Each creature attacks this turn if able"),
new TapSourceCost()));
} }
@ -43,38 +44,3 @@ public final class GoblinDiplomats extends CardImpl {
return new GoblinDiplomats(this); return new GoblinDiplomats(this);
} }
} }
class GoblinDiplomatsEffect extends RequirementEffect {
public GoblinDiplomatsEffect() {
super(Duration.EndOfTurn);
this.staticText = "Each creature attacks this turn if able";
}
private GoblinDiplomatsEffect(final GoblinDiplomatsEffect effect) {
super(effect);
}
@Override
public GoblinDiplomatsEffect copy() {
return new GoblinDiplomatsEffect(this);
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
if (permanent != null) {
return true;
}
return false;
}
@Override
public boolean mustAttack(Game game) {
return true;
}
@Override
public boolean mustBlock(Game game) {
return false;
}
}

View file

@ -2,19 +2,16 @@ package mage.cards.p;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.RequirementEffect;
import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.combat.GoadAttachedEffect; import mage.abilities.effects.common.combat.GoadAttachedEffect;
import mage.abilities.effects.common.combat.MustBeBlockedByAtLeastOneAttachedEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect; import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.keyword.EnchantAbility; import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubType; import mage.constants.SubType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
@ -39,7 +36,7 @@ public final class PredatoryImpetus extends CardImpl {
// Enchanted creature gets +3/+3, must be blocked if able, and is goaded. // Enchanted creature gets +3/+3, must be blocked if able, and is goaded.
ability = new SimpleStaticAbility(new BoostEnchantedEffect(3, 3)); ability = new SimpleStaticAbility(new BoostEnchantedEffect(3, 3));
ability.addEffect(new PredatoryImpetusEffect()); ability.addEffect(new MustBeBlockedByAtLeastOneAttachedEffect().concatBy(","));
ability.addEffect(new GoadAttachedEffect().concatBy(",")); ability.addEffect(new GoadAttachedEffect().concatBy(","));
this.addAbility(ability); this.addAbility(ability);
} }
@ -53,52 +50,3 @@ public final class PredatoryImpetus extends CardImpl {
return new PredatoryImpetus(this); return new PredatoryImpetus(this);
} }
} }
class PredatoryImpetusEffect extends RequirementEffect {
PredatoryImpetusEffect() {
super(Duration.WhileOnBattlefield);
staticText = ", must be blocked if able";
}
private PredatoryImpetusEffect(final PredatoryImpetusEffect effect) {
super(effect);
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
Permanent attachment = game.getPermanent(source.getSourceId());
if (attachment == null || attachment.getAttachedTo() == null) {
return false;
}
Permanent attachedCreature = game.getPermanent(attachment.getAttachedTo());
return attachedCreature != null && attachedCreature.isAttacking()
&& permanent.canBlock(attachment.getAttachedTo(), game);
}
@Override
public boolean mustAttack(Game game) {
return false;
}
@Override
public boolean mustBlock(Game game) {
return false;
}
@Override
public UUID mustBlockAttackerIfElseUnblocked(Ability source, Game game) {
Permanent attachment = game.getPermanent(source.getSourceId());
return attachment == null ? null : attachment.getAttachedTo();
}
@Override
public int getMinNumberOfBlockers() {
return 1;
}
@Override
public PredatoryImpetusEffect copy() {
return new PredatoryImpetusEffect(this);
}
}

View file

@ -5,14 +5,13 @@ import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.RequirementEffect; import mage.abilities.effects.common.combat.MustBeBlockedByAtLeastOneAttachedEffect;
import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect;
import mage.abilities.keyword.EquipAbility; import mage.abilities.keyword.EquipAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.*; import mage.constants.*;
import mage.game.Game; import mage.filter.common.FilterCreaturePermanent;
import mage.game.permanent.Permanent;
/** /**
* *
@ -20,13 +19,19 @@ import mage.game.permanent.Permanent;
*/ */
public final class SlayersCleaver extends CardImpl { public final class SlayersCleaver extends CardImpl {
private static final FilterCreaturePermanent filter
= new FilterCreaturePermanent("an Eldrazi");
static {
filter.add(SubType.ELDRAZI.getPredicate());
}
public SlayersCleaver(UUID ownerId, CardSetInfo setInfo) { public SlayersCleaver(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}");
this.subtype.add(SubType.EQUIPMENT); this.subtype.add(SubType.EQUIPMENT);
// Equipped creature gets +3/+1 and must be blocked by an Eldrazi if able. // Equipped creature gets +3/+1 and must be blocked by an Eldrazi if able.
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(3, 1)); Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(3, 1));
ability.addEffect(new SlayersCleaverEffect()); ability.addEffect(new MustBeBlockedByAtLeastOneAttachedEffect(filter).concatBy("and"));
this.addAbility(ability); this.addAbility(ability);
// Equip {4} // Equip {4}
@ -42,55 +47,3 @@ public final class SlayersCleaver extends CardImpl {
return new SlayersCleaver(this); return new SlayersCleaver(this);
} }
} }
class SlayersCleaverEffect extends RequirementEffect {
public SlayersCleaverEffect() {
this(Duration.WhileOnBattlefield);
}
public SlayersCleaverEffect(Duration duration) {
super(duration);
staticText = "and must be blocked by an Eldrazi if able";
}
private SlayersCleaverEffect(final SlayersCleaverEffect effect) {
super(effect);
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
Permanent equipment = game.getPermanent(source.getSourceId());
if (equipment == null || equipment.getAttachedTo() == null) {
return false;
}
Permanent attachedCreature = game.getPermanent(equipment.getAttachedTo());
return attachedCreature != null && attachedCreature.isAttacking()
&& permanent.canBlock(equipment.getAttachedTo(), game) && permanent.hasSubtype(SubType.ELDRAZI, game);
}
@Override
public boolean mustAttack(Game game) {
return false;
}
@Override
public boolean mustBlock(Game game) {
return false;
}
@Override
public UUID mustBlockAttackerIfElseUnblocked(Ability source, Game game) {
Permanent equipment = game.getPermanent(source.getSourceId());
if (equipment != null) {
return equipment.getAttachedTo();
}
return null;
}
@Override
public SlayersCleaverEffect copy() {
return new SlayersCleaverEffect(this);
}
}

View file

@ -3,9 +3,8 @@ package mage.cards.t;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.RequirementEffect; import mage.abilities.effects.common.combat.MustBeBlockedByAllSourceEffect;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -13,8 +12,8 @@ import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.filter.common.FilterCreaturePermanent;
import mage.game.permanent.Permanent; import mage.filter.predicate.mageobject.AbilityPredicate;
/** /**
* *
@ -22,6 +21,12 @@ import mage.game.permanent.Permanent;
*/ */
public final class TalruumPiper extends CardImpl { public final class TalruumPiper extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures with flying");
static {
filter.add(new AbilityPredicate(FlyingAbility.class));
}
public TalruumPiper(UUID ownerId, CardSetInfo setInfo) { public TalruumPiper(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{R}"); super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{R}");
this.subtype.add(SubType.MINOTAUR); this.subtype.add(SubType.MINOTAUR);
@ -29,7 +34,7 @@ public final class TalruumPiper extends CardImpl {
this.toughness = new MageInt(3); this.toughness = new MageInt(3);
// All creatures with flying able to block Talruum Piper do so. // All creatures with flying able to block Talruum Piper do so.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new TalruumPiperEffect())); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MustBeBlockedByAllSourceEffect(Duration.WhileOnBattlefield, filter)));
} }
private TalruumPiper(final TalruumPiper card) { private TalruumPiper(final TalruumPiper card) {
@ -41,45 +46,3 @@ public final class TalruumPiper extends CardImpl {
return new TalruumPiper(this); return new TalruumPiper(this);
} }
} }
class TalruumPiperEffect extends RequirementEffect {
public TalruumPiperEffect() {
super(Duration.WhileOnBattlefield);
staticText = "All creatures with flying able to block {this} do so";
}
private TalruumPiperEffect(final TalruumPiperEffect effect) {
super(effect);
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
Permanent sourceCreature = game.getPermanent(source.getSourceId());
if (sourceCreature != null && sourceCreature.isAttacking()) {
return permanent.getAbilities().contains(FlyingAbility.getInstance())
&& permanent.canBlock(source.getSourceId(), game);
}
return false;
}
@Override
public boolean mustAttack(Game game) {
return false;
}
@Override
public boolean mustBlock(Game game) {
return true;
}
@Override
public UUID mustBlockAttacker(Ability source, Game game) {
return source.getSourceId();
}
@Override
public TalruumPiperEffect copy() {
return new TalruumPiperEffect(this);
}
}

View file

@ -19,6 +19,7 @@ public final class DoctorWho extends ExpansionSet {
super("Doctor Who", "WHO", ExpansionSet.buildDate(2023, 10, 13), SetType.SUPPLEMENTAL); super("Doctor Who", "WHO", ExpansionSet.buildDate(2023, 10, 13), SetType.SUPPLEMENTAL);
cards.add(new SetCardInfo("Ace, Fearless Rebel", 98, Rarity.RARE, mage.cards.a.AceFearlessRebel.class)); cards.add(new SetCardInfo("Ace, Fearless Rebel", 98, Rarity.RARE, mage.cards.a.AceFearlessRebel.class));
cards.add(new SetCardInfo("Ace's Baseball Bat", 170, Rarity.RARE, mage.cards.a.AcesBaseballBat.class));
cards.add(new SetCardInfo("Adric, Mathematical Genius", 33, Rarity.RARE, mage.cards.a.AdricMathematicalGenius.class)); cards.add(new SetCardInfo("Adric, Mathematical Genius", 33, Rarity.RARE, mage.cards.a.AdricMathematicalGenius.class));
cards.add(new SetCardInfo("Alistair, the Brigadier", 112, Rarity.RARE, mage.cards.a.AlistairTheBrigadier.class)); cards.add(new SetCardInfo("Alistair, the Brigadier", 112, Rarity.RARE, mage.cards.a.AlistairTheBrigadier.class));
cards.add(new SetCardInfo("All of History, All at Once", 34, Rarity.RARE, mage.cards.a.AllOfHistoryAllAtOnce.class)); cards.add(new SetCardInfo("All of History, All at Once", 34, Rarity.RARE, mage.cards.a.AllOfHistoryAllAtOnce.class));

View file

@ -13,7 +13,6 @@ import mage.game.permanent.Permanent;
public enum AttachedToTappedCondition implements Condition { public enum AttachedToTappedCondition implements Condition {
instance; instance;
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Permanent attachment = game.getPermanent(source.getSourceId()); Permanent attachment = game.getPermanent(source.getSourceId());

View file

@ -0,0 +1,101 @@
package mage.abilities.effects.common.combat;
import mage.abilities.Ability;
import mage.abilities.effects.RequirementEffect;
import mage.constants.Duration;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.UUID;
/**
* <p>
* <p>
* http://tappedout.net/mtg-questions/must-be-blocked-if-able-effect-makes-other-attacking-creatures-essentially-unblockable/
* <p>
* When you Declare Blockers, you choose an arrangement for your blockers, then
* check to see if there are any restrictions or requirements.
* <p>
* If any restrictions are violated, the block is illegal. (For example, trying
* to block with Sightless Ghoul) If any requirements are violated, the least
* possible number of requirements must be violated, otherwise the block is
* illegal. (For example, your opponent control two creatures that he has cast
* Deadly Allure on, but you control only one creature. Blocking either one will
* violate a requirement, "This creature must be blocked this turn if able", but
* it will also violate the least possible number of requirements, thus it is
* legal.) If the block is illegal, the game state backs up and you declare
* blockers again. (Note that while you can, in some cases, circumvent
* requirements such as "This creature must be blocked" or "This creature must
* block any attacking creature" you can never circumvent restrictions: "This
* creature can't block" or "Only one creature may block this turn.") Because
* you declare ALL your blockers at once, THEN check for
* restrictions/requirements, you may block Deadly Allure'd creatures with only
* one creature, if you choose. This still works with Lure: This card sets up a
* requirement that ALL creatures must block it if able. Any block that violates
* more than the minimum number of requirements is still illegal.
*
* @author notgreat
*/
public class MustBeBlockedByAtLeastOneAttachedEffect extends RequirementEffect {
private final FilterPermanent filter;
public MustBeBlockedByAtLeastOneAttachedEffect() {
this((FilterPermanent)null);
}
public MustBeBlockedByAtLeastOneAttachedEffect(FilterPermanent filter) {
super(Duration.WhileOnBattlefield);
this.filter = filter;
if (filter == null) {
staticText = "must be blocked if able";
} else {
staticText = "must be blocked by "+(filter.getMessage())+" if able";
}
}
protected MustBeBlockedByAtLeastOneAttachedEffect(final MustBeBlockedByAtLeastOneAttachedEffect effect) {
super(effect);
filter = effect.filter;
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
Permanent attachment = game.getPermanent(source.getSourceId());
if (attachment == null || attachment.getAttachedTo() == null) {
return false;
}
Permanent attachedCreature = game.getPermanent(attachment.getAttachedTo());
if (attachedCreature != null && attachedCreature.isAttacking()
&& permanent.canBlock(attachment.getAttachedTo(), game)){
return (filter == null || filter.match(permanent, attachment.getControllerId(), source, game));
}
return false;
}
@Override
public boolean mustAttack(Game game) {
return false;
}
@Override
public boolean mustBlock(Game game) {
return false;
}
@Override
public UUID mustBlockAttackerIfElseUnblocked(Ability source, Game game) {
Permanent attachment = game.getPermanent(source.getSourceId());
return attachment == null ? null : attachment.getAttachedTo();
}
@Override
public int getMinNumberOfBlockers() {
return filter == null ? 1 : 0;
}
@Override
public MustBeBlockedByAtLeastOneAttachedEffect copy() {
return new MustBeBlockedByAtLeastOneAttachedEffect(this);
}
}