Simplify some instances of 'treetop ability'

This commit is contained in:
Alex W. Jackson 2022-01-02 03:34:01 -05:00
parent e4206169b2
commit 0b93dcdfaa
4 changed files with 58 additions and 149 deletions

View file

@ -2,19 +2,19 @@ package mage.cards.c;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.RestrictionEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.CantBeTargetedAttachedEffect;
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesAttachedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.ReachAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterObject;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.FilterStackObject;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.AbilityPredicate;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
@ -25,7 +25,17 @@ import java.util.UUID;
*/
public final class CanopyCover extends CardImpl {
private static final FilterObject filter = new FilterStackObject("spells or abilities your opponents control");
private static final FilterCreaturePermanent notFlyingorReachCreatures = new FilterCreaturePermanent("except by creatures with flying or reach");
private static final FilterStackObject filter = new FilterStackObject("spells or abilities your opponents control");
static {
notFlyingorReachCreatures.add(Predicates.not(
Predicates.or(
new AbilityPredicate(FlyingAbility.class),
new AbilityPredicate(ReachAbility.class)
)
));
}
public CanopyCover(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}");
@ -39,10 +49,10 @@ public final class CanopyCover extends CardImpl {
this.addAbility(ability);
// Enchanted creature can't be blocked except by creatures with flying or reach. (!this is a static ability of the enchantment)
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CanopyCoverEffect()));
this.addAbility(new SimpleStaticAbility(new CantBeBlockedByCreaturesAttachedEffect(Duration.WhileOnBattlefield, notFlyingorReachCreatures, AttachmentType.AURA)));
// Enchanted creature can't be the target of spells or abilities your opponents control.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeTargetedAttachedEffect(filter, Duration.WhileOnBattlefield, AttachmentType.AURA, TargetController.OPPONENT)));
this.addAbility(new SimpleStaticAbility(new CantBeTargetedAttachedEffect(filter, Duration.WhileOnBattlefield, AttachmentType.AURA, TargetController.OPPONENT)));
}
private CanopyCover(final CanopyCover card) {
@ -54,35 +64,3 @@ public final class CanopyCover extends CardImpl {
return new CanopyCover(this);
}
}
class CanopyCoverEffect extends RestrictionEffect {
public CanopyCoverEffect() {
super(Duration.WhileOnBattlefield);
staticText = "Enchanted creature can't be blocked except by creatures with flying or reach";
}
public CanopyCoverEffect(final CanopyCoverEffect 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) {
Permanent equipped = game.getPermanent(equipment.getAttachedTo());
return equipped != null && permanent.getId().equals(equipped.getId());
}
return false;
}
@Override
public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game, boolean canUseChooseDialogs) {
return blocker.getAbilities().contains(FlyingAbility.getInstance()) || blocker.getAbilities().contains(ReachAbility.getInstance());
}
@Override
public CanopyCoverEffect copy() {
return new CanopyCoverEffect(this);
}
}

View file

@ -1,9 +1,8 @@
package mage.cards.s;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.RestrictionEffect;
import mage.abilities.common.SimpleEvasionAbility;
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.HexproofAbility;
import mage.cards.CardImpl;
@ -11,9 +10,9 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.AbilityPredicate;
import java.util.UUID;
@ -22,6 +21,12 @@ import java.util.UUID;
*/
public final class SilhanaLedgewalker extends CardImpl {
private static final FilterCreaturePermanent onlyFlyingCreatures = new FilterCreaturePermanent("except by creatures with flying");
static {
onlyFlyingCreatures.add(Predicates.not(new AbilityPredicate(FlyingAbility.class)));
}
public SilhanaLedgewalker(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
this.subtype.add(SubType.ELF);
@ -34,7 +39,7 @@ public final class SilhanaLedgewalker extends CardImpl {
this.addAbility(HexproofAbility.getInstance());
// Silhana Ledgewalker can't be blocked except by creatures with flying.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SilhanaLedgewalkerEffect()));
this.addAbility(new SimpleEvasionAbility(new CantBeBlockedByCreaturesSourceEffect(onlyFlyingCreatures, Duration.WhileOnBattlefield)));
}
private SilhanaLedgewalker(final SilhanaLedgewalker card) {
@ -45,32 +50,4 @@ public final class SilhanaLedgewalker extends CardImpl {
public SilhanaLedgewalker copy() {
return new SilhanaLedgewalker(this);
}
}
class SilhanaLedgewalkerEffect extends RestrictionEffect {
public SilhanaLedgewalkerEffect() {
super(Duration.WhileOnBattlefield);
staticText = "{this} can't be blocked except by creatures with flying";
}
public SilhanaLedgewalkerEffect(final SilhanaLedgewalkerEffect effect) {
super(effect);
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
return source.getSourceId().equals(permanent.getId());
}
@Override
public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game, boolean canUseChooseDialogs) {
return blocker.getAbilities().contains(FlyingAbility.getInstance());
}
@Override
public SilhanaLedgewalkerEffect copy() {
return new SilhanaLedgewalkerEffect(this);
}
}

View file

@ -1,9 +1,8 @@
package mage.cards.s;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.RestrictionEffect;
import mage.abilities.common.SimpleEvasionAbility;
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.ReachAbility;
import mage.cards.CardImpl;
@ -11,9 +10,9 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.AbilityPredicate;
import java.util.UUID;
@ -22,6 +21,17 @@ import java.util.UUID;
*/
public final class SpireTracer extends CardImpl {
private static final FilterCreaturePermanent notFlyingorReachCreatures = new FilterCreaturePermanent("except by creatures with flying or reach");
static {
notFlyingorReachCreatures.add(Predicates.not(
Predicates.or(
new AbilityPredicate(FlyingAbility.class),
new AbilityPredicate(ReachAbility.class)
)
));
}
public SpireTracer(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}");
this.subtype.add(SubType.ELF);
@ -31,7 +41,7 @@ public final class SpireTracer extends CardImpl {
this.toughness = new MageInt(1);
// Spire Tracer can't be blocked except by creatures with flying or reach.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeBlockedExceptByCreaturesWithFlyingOrReachEffect()));
this.addAbility(new SimpleEvasionAbility(new CantBeBlockedByCreaturesSourceEffect(notFlyingorReachCreatures, Duration.WhileOnBattlefield)));
}
@ -44,31 +54,3 @@ public final class SpireTracer extends CardImpl {
return new SpireTracer(this);
}
}
class CantBeBlockedExceptByCreaturesWithFlyingOrReachEffect extends RestrictionEffect {
public CantBeBlockedExceptByCreaturesWithFlyingOrReachEffect() {
super(Duration.WhileOnBattlefield);
staticText = "{this} can't be blocked except by creatures with flying or reach";
}
public CantBeBlockedExceptByCreaturesWithFlyingOrReachEffect(final CantBeBlockedExceptByCreaturesWithFlyingOrReachEffect effect) {
super(effect);
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
return permanent.getId().equals(source.getSourceId());
}
@Override
public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game, boolean canUseChooseDialogs) {
return blocker.getAbilities().containsKey(FlyingAbility.getInstance().getId())
|| blocker.getAbilities().containsKey(ReachAbility.getInstance().getId());
}
@Override
public CantBeBlockedExceptByCreaturesWithFlyingOrReachEffect copy() {
return new CantBeBlockedExceptByCreaturesWithFlyingOrReachEffect(this);
}
}

View file

@ -2,8 +2,8 @@ package mage.cards.t;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.RestrictionEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesAttachedEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.abilities.keyword.FlyingAbility;
@ -11,8 +11,9 @@ import mage.abilities.keyword.ReachAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.AbilityPredicate;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
@ -23,6 +24,12 @@ import java.util.UUID;
*/
public final class TreetopBracers extends CardImpl {
private static final FilterCreaturePermanent onlyFlyingCreatures = new FilterCreaturePermanent("except by creatures with flying");
static {
onlyFlyingCreatures.add(Predicates.not(new AbilityPredicate(FlyingAbility.class)));
}
public TreetopBracers(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}");
this.subtype.add(SubType.AURA);
@ -35,8 +42,8 @@ public final class TreetopBracers extends CardImpl {
this.addAbility(ability);
// Enchanted creature gets +1/+1 and can't be blocked except by creatures with flying.
ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(1, 1, Duration.WhileOnBattlefield));
ability.addEffect(new TreetopBracersRestrictEffect());
ability = new SimpleStaticAbility(new BoostEnchantedEffect(1, 1, Duration.WhileOnBattlefield));
ability.addEffect(new CantBeBlockedByCreaturesAttachedEffect(Duration.WhileOnBattlefield, onlyFlyingCreatures, AttachmentType.AURA).setText("and can't be blocked except by creatures with flying"));
this.addAbility(ability);
}
@ -49,38 +56,3 @@ public final class TreetopBracers extends CardImpl {
return new TreetopBracers(this);
}
}
class TreetopBracersRestrictEffect extends RestrictionEffect {
public TreetopBracersRestrictEffect() {
super(Duration.WhileOnBattlefield);
staticText = "and can't be blocked except by creatures with flying";
}
public TreetopBracersRestrictEffect(final TreetopBracersRestrictEffect 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) {
Permanent equipped = game.getPermanent(equipment.getAttachedTo());
return equipped != null
&& permanent != null
&& permanent.getId().equals(equipped.getId());
}
return false;
}
@Override
public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game, boolean canUseChooseDialogs) {
return blocker.getAbilities().contains(FlyingAbility.getInstance()) || blocker.getAbilities().contains(ReachAbility.getInstance());
}
@Override
public TreetopBracersRestrictEffect copy() {
return new TreetopBracersRestrictEffect(this);
}
}