mirror of
https://github.com/magefree/mage.git
synced 2025-12-21 02:52:02 -08:00
Attacks player with creatures triggered ability, Implement [BLC] Echoing Assault (#13764)
Create AttacksPlayerWithCreaturesTriggeredAbility, and tests for that ability via Soaring Lightbringer. Implement Echoing Assault.
This commit is contained in:
parent
a7258604c6
commit
1fe0d92c86
15 changed files with 404 additions and 371 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
package mage.cards.d;
|
package mage.cards.d;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.CreateTokenEffect;
|
import mage.abilities.effects.common.CreateTokenEffect;
|
||||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||||
|
|
@ -12,12 +12,11 @@ import mage.cards.CardSetInfo;
|
||||||
import mage.cards.Cards;
|
import mage.cards.Cards;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SetTargetPointer;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.constants.Zone;
|
import mage.filter.FilterPermanent;
|
||||||
import mage.game.Controllable;
|
import mage.filter.common.FilterControlledPermanent;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.DefenderAttackedEvent;
|
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.token.DemonToken;
|
import mage.game.permanent.token.DemonToken;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
|
@ -30,6 +29,7 @@ import java.util.UUID;
|
||||||
* @author TheElk801
|
* @author TheElk801
|
||||||
*/
|
*/
|
||||||
public final class DemonicCovenant extends CardImpl {
|
public final class DemonicCovenant extends CardImpl {
|
||||||
|
FilterPermanent filter = new FilterControlledPermanent(SubType.DEMON,"Demons you control");
|
||||||
|
|
||||||
public DemonicCovenant(UUID ownerId, CardSetInfo setInfo) {
|
public DemonicCovenant(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.KINDRED, CardType.ENCHANTMENT}, "{4}{B}{B}");
|
super(ownerId, setInfo, new CardType[]{CardType.KINDRED, CardType.ENCHANTMENT}, "{4}{B}{B}");
|
||||||
|
|
@ -37,12 +37,14 @@ public final class DemonicCovenant extends CardImpl {
|
||||||
this.subtype.add(SubType.DEMON);
|
this.subtype.add(SubType.DEMON);
|
||||||
|
|
||||||
// Whenever one or more Demons you control attack a player, you draw a card and lose 1 life.
|
// Whenever one or more Demons you control attack a player, you draw a card and lose 1 life.
|
||||||
this.addAbility(new DemonicCovenantTriggeredAbility());
|
Ability abilityAttack = new AttacksPlayerWithCreaturesTriggeredAbility(new DrawCardSourceControllerEffect(1, true), filter, SetTargetPointer.NONE);
|
||||||
|
abilityAttack.addEffect(new LoseLifeSourceControllerEffect(1).setText("and lose 1 life"));
|
||||||
|
this.addAbility(abilityAttack);
|
||||||
|
|
||||||
// At the beginning of your end step, create a 5/5 black Demon creature token with flying, then mill two cards. If two cards that share all their card types were milled this way, sacrifice Demonic Covenant.
|
// At the beginning of your end step, create a 5/5 black Demon creature token with flying, then mill two cards. If two cards that share all their card types were milled this way, sacrifice Demonic Covenant.
|
||||||
Ability ability = new BeginningOfEndStepTriggeredAbility(new CreateTokenEffect(new DemonToken()));
|
Ability abilityEndStep = new BeginningOfEndStepTriggeredAbility(new CreateTokenEffect(new DemonToken()));
|
||||||
ability.addEffect(new DemonicCovenantEffect());
|
abilityEndStep.addEffect(new DemonicCovenantEffect());
|
||||||
this.addAbility(ability);
|
this.addAbility(abilityEndStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DemonicCovenant(final DemonicCovenant card) {
|
private DemonicCovenant(final DemonicCovenant card) {
|
||||||
|
|
@ -55,40 +57,6 @@ public final class DemonicCovenant extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DemonicCovenantTriggeredAbility extends TriggeredAbilityImpl {
|
|
||||||
|
|
||||||
DemonicCovenantTriggeredAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1, true));
|
|
||||||
this.addEffect(new LoseLifeSourceControllerEffect(1).setText("and lose 1 life"));
|
|
||||||
this.setTriggerPhrase("Whenever one or more Demons you control attack a player, ");
|
|
||||||
}
|
|
||||||
|
|
||||||
private DemonicCovenantTriggeredAbility(final DemonicCovenantTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DemonicCovenantTriggeredAbility copy() {
|
|
||||||
return new DemonicCovenantTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
return game.getPlayer(event.getTargetId()) != null
|
|
||||||
&& ((DefenderAttackedEvent) event)
|
|
||||||
.getAttackers(game)
|
|
||||||
.stream()
|
|
||||||
.filter(permanent -> permanent.hasSubtype(SubType.DEMON, game))
|
|
||||||
.map(Controllable::getControllerId)
|
|
||||||
.anyMatch(this::isControlledBy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DemonicCovenantEffect extends OneShotEffect {
|
class DemonicCovenantEffect extends OneShotEffect {
|
||||||
|
|
||||||
DemonicCovenantEffect() {
|
DemonicCovenantEffect() {
|
||||||
|
|
|
||||||
107
Mage.Sets/src/mage/cards/e/EchoingAssault.java
Normal file
107
Mage.Sets/src/mage/cards/e/EchoingAssault.java
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
package mage.cards.e;
|
||||||
|
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
|
||||||
|
import mage.abilities.keyword.MenaceAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SetTargetPointer;
|
||||||
|
import mage.filter.FilterPermanent;
|
||||||
|
import mage.filter.StaticFilters;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.ObjectSourcePlayer;
|
||||||
|
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||||
|
import mage.filter.predicate.permanent.TokenPredicate;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.target.TargetPermanent;
|
||||||
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author notgreat
|
||||||
|
*/
|
||||||
|
public final class EchoingAssault extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterPermanent filter = new FilterCreaturePermanent("nontoken creature that's attacking that player");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(TokenPredicate.FALSE);
|
||||||
|
filter.add(EchoingAssaultPredicate.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EchoingAssault(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{R}");
|
||||||
|
|
||||||
|
|
||||||
|
// Creature tokens you control have menace.
|
||||||
|
this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect(
|
||||||
|
new MenaceAbility(false), Duration.WhileOnBattlefield, StaticFilters.FILTER_CREATURE_TOKENS
|
||||||
|
)));
|
||||||
|
|
||||||
|
// Whenever you attack a player, choose target nontoken creature that's attacking that player. Create a token that's a copy of that creature, except it's 1/1. The token enters tapped and attacking that player. Sacrifice it at the beginning of the next end step.
|
||||||
|
Ability ability = new AttacksPlayerWithCreaturesTriggeredAbility(new EchoingAssaultEffect(), SetTargetPointer.NONE);
|
||||||
|
ability.addTarget(new TargetPermanent(filter));
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
private EchoingAssault(final EchoingAssault card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EchoingAssault copy() {
|
||||||
|
return new EchoingAssault(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum EchoingAssaultPredicate implements ObjectSourcePlayerPredicate<Permanent> {
|
||||||
|
instance;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(ObjectSourcePlayer<Permanent> input, Game game) {
|
||||||
|
return CardUtil.getEffectValueFromAbility(input.getSource(), "playerAttacked", UUID.class)
|
||||||
|
.filter(uuid -> uuid.equals(game.getCombat().getDefenderId(input.getObject().getId())))
|
||||||
|
.isPresent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EchoingAssaultEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
EchoingAssaultEffect() {
|
||||||
|
super(Outcome.Benefit);
|
||||||
|
staticText = "choose target nontoken creature that's attacking that player. Create a token that's a copy of that creature, except it's 1/1. The token enters tapped and attacking that player. Sacrifice it at the beginning of the next end step.";
|
||||||
|
}
|
||||||
|
|
||||||
|
private EchoingAssaultEffect(final EchoingAssaultEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EchoingAssaultEffect copy() {
|
||||||
|
return new EchoingAssaultEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Object attackedPlayer = getValue("playerAttacked");
|
||||||
|
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||||
|
if (permanent == null || !(attackedPlayer instanceof UUID)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(null, null, false,
|
||||||
|
1, true, true, (UUID) attackedPlayer, 1, 1, false);
|
||||||
|
effect.setSavedPermanent(permanent);
|
||||||
|
effect.apply(game, source);
|
||||||
|
effect.sacrificeTokensCreatedAtNextEndStep(game, source);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@ package mage.cards.f;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
|
import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility;
|
||||||
import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility;
|
import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility;
|
||||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||||
import mage.abilities.effects.common.combat.GoadTargetEffect;
|
import mage.abilities.effects.common.combat.GoadTargetEffect;
|
||||||
|
|
@ -14,7 +14,7 @@ import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
import mage.filter.FilterPermanent;
|
import mage.filter.FilterPermanent;
|
||||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
import mage.filter.common.FilterControlledPermanent;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import mage.filter.predicate.Predicate;
|
import mage.filter.predicate.Predicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
|
@ -29,12 +29,11 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class FirkraagCunningInstigator extends CardImpl {
|
public final class FirkraagCunningInstigator extends CardImpl {
|
||||||
|
|
||||||
private static final FilterPermanent filter = new FilterCreaturePermanent();
|
private static final FilterPermanent filterHadToAttack = new FilterCreaturePermanent();
|
||||||
private static final FilterPermanent filterDragons = new FilterControlledCreaturePermanent("Dragons you control");
|
private static final FilterPermanent filterDragons = new FilterControlledPermanent(SubType.DRAGON, "Dragons you control");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(FirkraagCunningInstigatorPredicate.instance);
|
filterHadToAttack.add(FirkraagCunningInstigatorPredicate.instance);
|
||||||
filterDragons.add(SubType.DRAGON.getPredicate());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public FirkraagCunningInstigator(UUID ownerId, CardSetInfo setInfo) {
|
public FirkraagCunningInstigator(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
|
@ -52,7 +51,7 @@ public final class FirkraagCunningInstigator extends CardImpl {
|
||||||
this.addAbility(HasteAbility.getInstance());
|
this.addAbility(HasteAbility.getInstance());
|
||||||
|
|
||||||
// Whenever one or more Dragons you control attack an opponent, goad target creature that player controls.
|
// Whenever one or more Dragons you control attack an opponent, goad target creature that player controls.
|
||||||
Ability abilityGoad = new AttacksWithCreaturesTriggeredAbility(Zone.BATTLEFIELD, new GoadTargetEffect(), 1, filterDragons, true);
|
Ability abilityGoad = new AttacksPlayerWithCreaturesTriggeredAbility(new GoadTargetEffect(), 1, filterDragons, SetTargetPointer.PLAYER, true);
|
||||||
abilityGoad.addTarget(new TargetPermanent(new FilterCreaturePermanent("target creature that player controls")));
|
abilityGoad.addTarget(new TargetPermanent(new FilterCreaturePermanent("target creature that player controls")));
|
||||||
abilityGoad.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
|
abilityGoad.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
|
||||||
this.addAbility(abilityGoad);
|
this.addAbility(abilityGoad);
|
||||||
|
|
@ -61,7 +60,7 @@ public final class FirkraagCunningInstigator extends CardImpl {
|
||||||
Ability ability = new DealsDamageToAPlayerAllTriggeredAbility(
|
Ability ability = new DealsDamageToAPlayerAllTriggeredAbility(
|
||||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance())
|
new AddCountersSourceEffect(CounterType.P1P1.createInstance())
|
||||||
.setText("you put a +1/+1 counter on {this}"),
|
.setText("you put a +1/+1 counter on {this}"),
|
||||||
filter, false, SetTargetPointer.NONE,
|
filterHadToAttack, false, SetTargetPointer.NONE,
|
||||||
true, false, TargetController.OPPONENT
|
true, false, TargetController.OPPONENT
|
||||||
).setTriggerPhrase("Whenever a creature deals combat damage to one of your opponents, " +
|
).setTriggerPhrase("Whenever a creature deals combat damage to one of your opponents, " +
|
||||||
"if that creature had to attack this combat, ");
|
"if that creature had to attack this combat, ");
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package mage.cards.g;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
|
import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.dynamicvalue.DynamicValue;
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
||||||
|
|
@ -17,9 +17,10 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.filter.FilterPermanent;
|
import mage.filter.FilterPermanent;
|
||||||
|
import mage.filter.common.FilterControlledPermanent;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import mage.filter.predicate.permanent.AttackingPredicate;
|
import mage.filter.predicate.permanent.AttackingPredicate;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.TargetPermanent;
|
||||||
import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
|
import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -29,16 +30,17 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class GornogTheRedReaper extends CardImpl {
|
public final class GornogTheRedReaper extends CardImpl {
|
||||||
|
|
||||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.WARRIOR, "Attacking Warriors");
|
private static final FilterPermanent filterAttackWarrior = new FilterCreaturePermanent(SubType.WARRIOR, "Attacking Warriors");
|
||||||
private static final FilterPermanent filter2 = new FilterPermanent(SubType.COWARD, "Cowards your opponents control");
|
private static final FilterPermanent filterWarrior = new FilterControlledPermanent(SubType.WARRIOR, "Warriors you control");
|
||||||
|
private static final FilterPermanent filterCoward = new FilterPermanent(SubType.COWARD, "Cowards your opponents control");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(AttackingPredicate.instance);
|
filterAttackWarrior.add(AttackingPredicate.instance);
|
||||||
filter2.add(TargetController.OPPONENT.getControllerPredicate());
|
filterCoward.add(TargetController.OPPONENT.getControllerPredicate());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter2, null);
|
private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filterCoward, null);
|
||||||
private static final Hint hint = new ValueHint(filter2.getMessage(), xValue);
|
private static final Hint hint = new ValueHint(filterCoward.getMessage(), xValue);
|
||||||
|
|
||||||
public GornogTheRedReaper(UUID ownerId, CardSetInfo setInfo) {
|
public GornogTheRedReaper(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
|
||||||
|
|
@ -56,16 +58,16 @@ public final class GornogTheRedReaper extends CardImpl {
|
||||||
this.addAbility(new SimpleStaticAbility(new CowardsCantBlockWarriorsEffect()));
|
this.addAbility(new SimpleStaticAbility(new CowardsCantBlockWarriorsEffect()));
|
||||||
|
|
||||||
// Whenever one or more Warriors you control attack a player, target creature that player controls becomes a Coward.
|
// Whenever one or more Warriors you control attack a player, target creature that player controls becomes a Coward.
|
||||||
Ability ability = new AttacksWithCreaturesTriggeredAbility(Zone.BATTLEFIELD,
|
Ability ability = new AttacksPlayerWithCreaturesTriggeredAbility(
|
||||||
new BecomesCreatureTypeTargetEffect(Duration.EndOfGame, SubType.COWARD),
|
new BecomesCreatureTypeTargetEffect(Duration.EndOfGame, SubType.COWARD).setText("target creature that player controls becomes a Coward"),
|
||||||
1, filter, true);
|
filterWarrior, SetTargetPointer.PLAYER);
|
||||||
ability.addTarget(new TargetCreaturePermanent());
|
ability.addTarget(new TargetPermanent());
|
||||||
ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
|
ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
||||||
// Attacking Warriors you control get +X/+0, where X is the number of Cowards your opponents control.
|
// Attacking Warriors you control get +X/+0, where X is the number of Cowards your opponents control.
|
||||||
this.addAbility(new SimpleStaticAbility(new BoostControlledEffect(
|
this.addAbility(new SimpleStaticAbility(new BoostControlledEffect(
|
||||||
xValue, StaticValue.get(0), Duration.WhileOnBattlefield, filter, false
|
xValue, StaticValue.get(0), Duration.WhileOnBattlefield, filterAttackWarrior, false
|
||||||
)).addHint(hint));
|
)).addHint(hint));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,14 @@
|
||||||
package mage.cards.h;
|
package mage.cards.h;
|
||||||
|
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility;
|
||||||
import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
|
import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
|
||||||
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.PutCards;
|
import mage.constants.PutCards;
|
||||||
|
import mage.constants.SetTargetPointer;
|
||||||
import mage.constants.SuperType;
|
import mage.constants.SuperType;
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.filter.StaticFilters;
|
import mage.filter.StaticFilters;
|
||||||
import mage.game.Controllable;
|
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.events.DefenderAttackedEvent;
|
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -27,7 +23,9 @@ public final class HornOfTheMark extends CardImpl {
|
||||||
this.supertype.add(SuperType.LEGENDARY);
|
this.supertype.add(SuperType.LEGENDARY);
|
||||||
|
|
||||||
// Whenever two or more creatures you control attack a player, look at the top five cards of your library. You may reveal a creature card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.
|
// Whenever two or more creatures you control attack a player, look at the top five cards of your library. You may reveal a creature card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.
|
||||||
this.addAbility(new HornOfTheMarkTriggeredAbility());
|
this.addAbility(new AttacksPlayerWithCreaturesTriggeredAbility(
|
||||||
|
new LookLibraryAndPickControllerEffect(5, 1, StaticFilters.FILTER_CARD_CREATURE_A, PutCards.HAND, PutCards.BOTTOM_RANDOM),
|
||||||
|
2, StaticFilters.FILTER_CONTROLLED_CREATURES, SetTargetPointer.NONE, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
private HornOfTheMark(final HornOfTheMark card) {
|
private HornOfTheMark(final HornOfTheMark card) {
|
||||||
|
|
@ -39,39 +37,3 @@ public final class HornOfTheMark extends CardImpl {
|
||||||
return new HornOfTheMark(this);
|
return new HornOfTheMark(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HornOfTheMarkTriggeredAbility extends TriggeredAbilityImpl {
|
|
||||||
|
|
||||||
HornOfTheMarkTriggeredAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new LookLibraryAndPickControllerEffect(
|
|
||||||
5, 1, StaticFilters.FILTER_CARD_CREATURE_A, PutCards.HAND, PutCards.BOTTOM_RANDOM
|
|
||||||
));
|
|
||||||
this.setTriggerPhrase("Whenever two or more creatures you control attack a player, ");
|
|
||||||
}
|
|
||||||
|
|
||||||
private HornOfTheMarkTriggeredAbility(final HornOfTheMarkTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HornOfTheMarkTriggeredAbility copy() {
|
|
||||||
return new HornOfTheMarkTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
DefenderAttackedEvent dEvent = ((DefenderAttackedEvent) event);
|
|
||||||
return game.getPlayer(dEvent.getTargetId()) != null
|
|
||||||
&& dEvent
|
|
||||||
.getAttackers(game)
|
|
||||||
.stream()
|
|
||||||
.map(Controllable::getControllerId)
|
|
||||||
.filter(this::isControlledBy)
|
|
||||||
.count() >= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,20 @@
|
||||||
package mage.cards.k;
|
package mage.cards.k;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
|
import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility;
|
||||||
import mage.abilities.effects.common.*;
|
import mage.abilities.effects.common.*;
|
||||||
import mage.abilities.effects.common.combat.GoadTargetEffect;
|
import mage.abilities.effects.common.combat.GoadTargetEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.*;
|
||||||
import mage.constants.SubType;
|
|
||||||
import mage.constants.SuperType;
|
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.filter.FilterPermanent;
|
import mage.filter.FilterPermanent;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.players.Player;
|
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
|
import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
|
||||||
import mage.target.targetpointer.FixedTarget;
|
import mage.target.targetpointer.FixedTarget;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
@ -26,6 +24,7 @@ import java.util.UUID;
|
||||||
* @author TheElk801
|
* @author TheElk801
|
||||||
*/
|
*/
|
||||||
public final class KarazikarTheEyeTyrant extends CardImpl {
|
public final class KarazikarTheEyeTyrant extends CardImpl {
|
||||||
|
FilterPermanent filter = new FilterCreaturePermanent("creature that player controls");
|
||||||
|
|
||||||
public KarazikarTheEyeTyrant(UUID ownerId, CardSetInfo setInfo) {
|
public KarazikarTheEyeTyrant(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{R}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{R}");
|
||||||
|
|
@ -36,7 +35,11 @@ public final class KarazikarTheEyeTyrant extends CardImpl {
|
||||||
this.toughness = new MageInt(5);
|
this.toughness = new MageInt(5);
|
||||||
|
|
||||||
// Whenever you attack a player, tap target creature that player controls and goad it.
|
// Whenever you attack a player, tap target creature that player controls and goad it.
|
||||||
this.addAbility(new KarazikarTheEyeTyrantFirstTriggeredAbility());
|
Ability ability = new AttacksPlayerWithCreaturesTriggeredAbility(new TapTargetEffect(), SetTargetPointer.PLAYER);
|
||||||
|
ability.addEffect(new GoadTargetEffect().setText("goad it. " + GoadTargetEffect.goadReminderText).concatBy("and"));
|
||||||
|
ability.addTarget(new TargetPermanent(filter));
|
||||||
|
ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
|
||||||
|
this.addAbility(ability);
|
||||||
|
|
||||||
// Whenever an opponent attacks another one of your opponents, you and the attacking player each draw a card and lose 1 life.
|
// Whenever an opponent attacks another one of your opponents, you and the attacking player each draw a card and lose 1 life.
|
||||||
this.addAbility(new KarazikarTheEyeTyrantSecondTriggeredAbility());
|
this.addAbility(new KarazikarTheEyeTyrantSecondTriggeredAbility());
|
||||||
|
|
@ -52,49 +55,6 @@ public final class KarazikarTheEyeTyrant extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class KarazikarTheEyeTyrantFirstTriggeredAbility extends TriggeredAbilityImpl {
|
|
||||||
|
|
||||||
KarazikarTheEyeTyrantFirstTriggeredAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new TapTargetEffect(), false);
|
|
||||||
this.addEffect(new GoadTargetEffect());
|
|
||||||
}
|
|
||||||
|
|
||||||
private KarazikarTheEyeTyrantFirstTriggeredAbility(final KarazikarTheEyeTyrantFirstTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public KarazikarTheEyeTyrantFirstTriggeredAbility copy() {
|
|
||||||
return new KarazikarTheEyeTyrantFirstTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
if (!isControlledBy(event.getPlayerId())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Player player = game.getPlayer(event.getTargetId());
|
|
||||||
if (player == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
FilterPermanent filter = new FilterCreaturePermanent("creature controlled by " + player.getName());
|
|
||||||
filter.add(new ControllerIdPredicate(player.getId()));
|
|
||||||
this.getTargets().clear();
|
|
||||||
this.addTarget(new TargetPermanent(filter));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRule() {
|
|
||||||
return "Whenever you attack a player, tap target creature that player controls and goad it.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class KarazikarTheEyeTyrantSecondTriggeredAbility extends TriggeredAbilityImpl {
|
class KarazikarTheEyeTyrantSecondTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
KarazikarTheEyeTyrantSecondTriggeredAbility() {
|
KarazikarTheEyeTyrantSecondTriggeredAbility() {
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,18 @@
|
||||||
package mage.cards.l;
|
package mage.cards.l;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility;
|
||||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||||
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;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.filter.FilterPermanent;
|
import mage.filter.FilterPermanent;
|
||||||
|
import mage.filter.StaticFilters;
|
||||||
import mage.filter.common.FilterAttackingCreature;
|
import mage.filter.common.FilterAttackingCreature;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.Predicates;
|
||||||
import mage.filter.predicate.mageobject.AbilityPredicate;
|
import mage.filter.predicate.mageobject.AbilityPredicate;
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.events.DefenderAttackedEvent;
|
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -23,6 +22,12 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class LandrovalHorizonWitness extends CardImpl {
|
public final class LandrovalHorizonWitness extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterPermanent filter
|
||||||
|
= new FilterAttackingCreature("attacking creature without flying");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class)));
|
||||||
|
}
|
||||||
public LandrovalHorizonWitness(UUID ownerId, CardSetInfo setInfo) {
|
public LandrovalHorizonWitness(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}");
|
||||||
|
|
||||||
|
|
@ -36,7 +41,11 @@ public final class LandrovalHorizonWitness extends CardImpl {
|
||||||
this.addAbility(FlyingAbility.getInstance());
|
this.addAbility(FlyingAbility.getInstance());
|
||||||
|
|
||||||
// Whenever two or more creatures you control attack a player, target attacking creature without flying gains flying until end of turn.
|
// Whenever two or more creatures you control attack a player, target attacking creature without flying gains flying until end of turn.
|
||||||
this.addAbility(new LandrovalHorizonWitnessTriggeredAbility());
|
Ability ability = new AttacksPlayerWithCreaturesTriggeredAbility(
|
||||||
|
new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn),
|
||||||
|
2, StaticFilters.FILTER_CONTROLLED_CREATURES, SetTargetPointer.NONE, false);
|
||||||
|
ability.addTarget(new TargetPermanent(filter));
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LandrovalHorizonWitness(final LandrovalHorizonWitness card) {
|
private LandrovalHorizonWitness(final LandrovalHorizonWitness card) {
|
||||||
|
|
@ -48,40 +57,3 @@ public final class LandrovalHorizonWitness extends CardImpl {
|
||||||
return new LandrovalHorizonWitness(this);
|
return new LandrovalHorizonWitness(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LandrovalHorizonWitnessTriggeredAbility extends TriggeredAbilityImpl {
|
|
||||||
|
|
||||||
private static final FilterPermanent filter
|
|
||||||
= new FilterAttackingCreature("attacking creature without flying");
|
|
||||||
|
|
||||||
static {
|
|
||||||
filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class)));
|
|
||||||
}
|
|
||||||
|
|
||||||
LandrovalHorizonWitnessTriggeredAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn));
|
|
||||||
this.addTarget(new TargetPermanent(filter));
|
|
||||||
setTriggerPhrase("Whenever two or more creatures you control attack a player, ");
|
|
||||||
}
|
|
||||||
|
|
||||||
private LandrovalHorizonWitnessTriggeredAbility(final LandrovalHorizonWitnessTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LandrovalHorizonWitnessTriggeredAbility copy() {
|
|
||||||
return new LandrovalHorizonWitnessTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
return isControlledBy(event.getPlayerId())
|
|
||||||
&& game.getPlayer(event.getTargetId()) != null
|
|
||||||
&& ((DefenderAttackedEvent) event).getAttackers(game).size() >= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,16 @@
|
||||||
package mage.cards.m;
|
package mage.cards.m;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility;
|
||||||
import mage.abilities.effects.common.CreateTokenEffect;
|
import mage.abilities.effects.common.CreateTokenEffect;
|
||||||
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.SetTargetPointer;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.constants.SuperType;
|
import mage.constants.SuperType;
|
||||||
import mage.constants.Zone;
|
import mage.filter.FilterPermanent;
|
||||||
import mage.game.Game;
|
import mage.filter.common.FilterControlledPermanent;
|
||||||
import mage.game.events.DefenderAttackedEvent;
|
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.game.permanent.token.FoodToken;
|
import mage.game.permanent.token.FoodToken;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -20,6 +19,7 @@ import java.util.UUID;
|
||||||
* @author TheElk801
|
* @author TheElk801
|
||||||
*/
|
*/
|
||||||
public final class MeriadocBrandybuck extends CardImpl {
|
public final class MeriadocBrandybuck extends CardImpl {
|
||||||
|
FilterPermanent filter = new FilterControlledPermanent(SubType.HALFLING,"Halflings you control");
|
||||||
|
|
||||||
public MeriadocBrandybuck(UUID ownerId, CardSetInfo setInfo) {
|
public MeriadocBrandybuck(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
|
||||||
|
|
@ -31,7 +31,7 @@ public final class MeriadocBrandybuck extends CardImpl {
|
||||||
this.toughness = new MageInt(2);
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
// Whenever one or more Halflings you control attack a player, create a Food token.
|
// Whenever one or more Halflings you control attack a player, create a Food token.
|
||||||
this.addAbility(new MeriadocBrandybuckTriggeredAbility());
|
this.addAbility(new AttacksPlayerWithCreaturesTriggeredAbility(new CreateTokenEffect(new FoodToken()), filter, SetTargetPointer.NONE));
|
||||||
}
|
}
|
||||||
|
|
||||||
private MeriadocBrandybuck(final MeriadocBrandybuck card) {
|
private MeriadocBrandybuck(final MeriadocBrandybuck card) {
|
||||||
|
|
@ -43,35 +43,3 @@ public final class MeriadocBrandybuck extends CardImpl {
|
||||||
return new MeriadocBrandybuck(this);
|
return new MeriadocBrandybuck(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MeriadocBrandybuckTriggeredAbility extends TriggeredAbilityImpl {
|
|
||||||
|
|
||||||
MeriadocBrandybuckTriggeredAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new CreateTokenEffect(new FoodToken()));
|
|
||||||
setTriggerPhrase("Whenever one or more Halflings you control attack a player, ");
|
|
||||||
}
|
|
||||||
|
|
||||||
private MeriadocBrandybuckTriggeredAbility(final MeriadocBrandybuckTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MeriadocBrandybuckTriggeredAbility copy() {
|
|
||||||
return new MeriadocBrandybuckTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
return isControlledBy(event.getPlayerId())
|
|
||||||
&& game.getPlayer(event.getTargetId()) != null
|
|
||||||
&& ((DefenderAttackedEvent) event)
|
|
||||||
.getAttackers(game)
|
|
||||||
.stream()
|
|
||||||
.anyMatch(permanent -> permanent.hasSubtype(SubType.HALFLING, game));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package mage.cards.n;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
|
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
|
||||||
|
|
@ -12,11 +12,10 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.filter.FilterPermanent;
|
import mage.filter.FilterPermanent;
|
||||||
|
import mage.filter.common.FilterControlledPermanent;
|
||||||
import mage.filter.predicate.permanent.AttackingPredicate;
|
import mage.filter.predicate.permanent.AttackingPredicate;
|
||||||
import mage.filter.predicate.permanent.TokenPredicate;
|
import mage.filter.predicate.permanent.TokenPredicate;
|
||||||
import mage.game.Controllable;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.DefenderAttackedEvent;
|
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.PermanentToken;
|
import mage.game.permanent.PermanentToken;
|
||||||
|
|
@ -33,11 +32,13 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class NeyaliSunsVanguard extends CardImpl {
|
public final class NeyaliSunsVanguard extends CardImpl {
|
||||||
|
|
||||||
private static final FilterPermanent filter = new FilterPermanent("attacking tokens");
|
private static final FilterPermanent filterAttacking = new FilterPermanent("attacking tokens");
|
||||||
|
private static final FilterPermanent filterControlled = new FilterControlledPermanent("tokens you control");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(AttackingPredicate.instance);
|
filterAttacking.add(AttackingPredicate.instance);
|
||||||
filter.add(TokenPredicate.TRUE);
|
filterAttacking.add(TokenPredicate.TRUE);
|
||||||
|
filterControlled.add(TokenPredicate.TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NeyaliSunsVanguard(UUID ownerId, CardSetInfo setInfo) {
|
public NeyaliSunsVanguard(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
|
@ -51,11 +52,13 @@ public final class NeyaliSunsVanguard extends CardImpl {
|
||||||
|
|
||||||
// Attacking tokens you control have double strike.
|
// Attacking tokens you control have double strike.
|
||||||
this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect(
|
this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect(
|
||||||
DoubleStrikeAbility.getInstance(), Duration.WhileOnBattlefield, filter
|
DoubleStrikeAbility.getInstance(), Duration.WhileOnBattlefield, filterAttacking
|
||||||
)));
|
)));
|
||||||
|
|
||||||
// Whenever one or more tokens you control attack a player, exile the top card of your library. During any turn you attacked with a token, you may play that card.
|
// Whenever one or more tokens you control attack a player, exile the top card of your library. During any turn you attacked with a token, you may play that card.
|
||||||
this.addAbility(new NeyaliSunsVanguardTriggeredAbility());
|
Ability ability = new AttacksPlayerWithCreaturesTriggeredAbility(new NeyaliSunsVanguardEffect(), filterControlled, SetTargetPointer.NONE);
|
||||||
|
ability.addWatcher(new NeyaliSunsVanguardWatcher());
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private NeyaliSunsVanguard(final NeyaliSunsVanguard card) {
|
private NeyaliSunsVanguard(final NeyaliSunsVanguard card) {
|
||||||
|
|
@ -68,49 +71,11 @@ public final class NeyaliSunsVanguard extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NeyaliSunsVanguardTriggeredAbility extends TriggeredAbilityImpl {
|
|
||||||
|
|
||||||
NeyaliSunsVanguardTriggeredAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new NeyaliSunsVanguardEffect());
|
|
||||||
this.addWatcher(new NeyaliSunsVanguardWatcher());
|
|
||||||
}
|
|
||||||
|
|
||||||
private NeyaliSunsVanguardTriggeredAbility(final NeyaliSunsVanguardTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NeyaliSunsVanguardTriggeredAbility copy() {
|
|
||||||
return new NeyaliSunsVanguardTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
return game.getPlayer(event.getTargetId()) != null
|
|
||||||
&& ((DefenderAttackedEvent) event)
|
|
||||||
.getAttackers(game)
|
|
||||||
.stream()
|
|
||||||
.filter(PermanentToken.class::isInstance)
|
|
||||||
.map(Controllable::getControllerId)
|
|
||||||
.anyMatch(this::isControlledBy);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRule() {
|
|
||||||
return "Whenever one or more tokens you control attack a player, exile the top card of your library. " +
|
|
||||||
"During any turn you attacked with a token, you may play that card.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NeyaliSunsVanguardEffect extends OneShotEffect {
|
class NeyaliSunsVanguardEffect extends OneShotEffect {
|
||||||
|
|
||||||
NeyaliSunsVanguardEffect() {
|
NeyaliSunsVanguardEffect() {
|
||||||
super(Outcome.Benefit);
|
super(Outcome.Benefit);
|
||||||
|
this.setText("exile the top card of your library. During any turn you attacked with a token, you may play that card.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private NeyaliSunsVanguardEffect(final NeyaliSunsVanguardEffect effect) {
|
private NeyaliSunsVanguardEffect(final NeyaliSunsVanguardEffect effect) {
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
package mage.cards.o;
|
package mage.cards.o;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility;
|
||||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||||
import mage.abilities.keyword.FirstStrikeAbility;
|
import mage.abilities.keyword.FirstStrikeAbility;
|
||||||
import mage.abilities.keyword.MentorAbility;
|
import mage.abilities.keyword.MentorAbility;
|
||||||
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.SetTargetPointer;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.filter.FilterPermanent;
|
import mage.filter.FilterPermanent;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import mage.filter.predicate.ObjectSourcePlayer;
|
import mage.filter.predicate.ObjectSourcePlayer;
|
||||||
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
|
|
@ -27,6 +27,12 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class OrdruunMentor extends CardImpl {
|
public final class OrdruunMentor extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterPermanent filter = new FilterCreaturePermanent("creature that's attacking that player");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(OrdruunMentorPredicate.instance);
|
||||||
|
}
|
||||||
|
|
||||||
public OrdruunMentor(UUID ownerId, CardSetInfo setInfo) {
|
public OrdruunMentor(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R/W}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R/W}");
|
||||||
|
|
||||||
|
|
@ -39,7 +45,10 @@ public final class OrdruunMentor extends CardImpl {
|
||||||
this.addAbility(new MentorAbility());
|
this.addAbility(new MentorAbility());
|
||||||
|
|
||||||
// Whenever you attack a player, target creature that's attacking that player gains first strike until end of turn.
|
// Whenever you attack a player, target creature that's attacking that player gains first strike until end of turn.
|
||||||
this.addAbility(new OrdruunMentorTriggeredAbility());
|
Ability ability = new AttacksPlayerWithCreaturesTriggeredAbility(
|
||||||
|
new GainAbilityTargetEffect(FirstStrikeAbility.getInstance()), SetTargetPointer.NONE);
|
||||||
|
ability.addTarget(new TargetPermanent(filter));
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OrdruunMentor(final OrdruunMentor card) {
|
private OrdruunMentor(final OrdruunMentor card) {
|
||||||
|
|
@ -51,54 +60,13 @@ public final class OrdruunMentor extends CardImpl {
|
||||||
return new OrdruunMentor(this);
|
return new OrdruunMentor(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
enum OrdruunMentorPredicate implements ObjectSourcePlayerPredicate<Permanent> {
|
||||||
class OrdruunMentorTriggeredAbility extends TriggeredAbilityImpl {
|
|
||||||
|
|
||||||
private enum OrdruunMentorPredicate implements ObjectSourcePlayerPredicate<Permanent> {
|
|
||||||
instance;
|
instance;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(ObjectSourcePlayer<Permanent> input, Game game) {
|
public boolean apply(ObjectSourcePlayer<Permanent> input, Game game) {
|
||||||
return CardUtil.getEffectValueFromAbility(
|
return CardUtil.getEffectValueFromAbility(input.getSource(), "playerAttacked", UUID.class)
|
||||||
input.getSource(), "playerAttacked", UUID.class
|
|
||||||
)
|
|
||||||
.filter(uuid -> uuid.equals(game.getCombat().getDefenderId(input.getObject().getId())))
|
.filter(uuid -> uuid.equals(game.getCombat().getDefenderId(input.getObject().getId())))
|
||||||
.isPresent();
|
.isPresent();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static final FilterPermanent filter = new FilterCreaturePermanent("creature that's attacking that player");
|
|
||||||
|
|
||||||
static {
|
|
||||||
filter.add(OrdruunMentorPredicate.instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
OrdruunMentorTriggeredAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new GainAbilityTargetEffect(FirstStrikeAbility.getInstance()).setText(""));
|
|
||||||
this.setTriggerPhrase("Whenever you attack a player, ");
|
|
||||||
this.addTarget(new TargetPermanent(filter));
|
|
||||||
}
|
|
||||||
|
|
||||||
private OrdruunMentorTriggeredAbility(final OrdruunMentorTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public OrdruunMentorTriggeredAbility copy() {
|
|
||||||
return new OrdruunMentorTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
if (!isControlledBy(event.getPlayerId()) || game.getPlayer(event.getTargetId()) == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this.getEffects().setValue("playerAttacked", event.getTargetId());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package mage.cards.s;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
|
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
|
||||||
|
|
@ -13,9 +13,7 @@ import mage.constants.*;
|
||||||
import mage.filter.FilterPermanent;
|
import mage.filter.FilterPermanent;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.game.permanent.token.GlimmerToken;
|
import mage.game.permanent.token.GlimmerToken;
|
||||||
import mage.target.targetpointer.FixedTarget;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -47,7 +45,7 @@ public final class SoaringLightbringer extends CardImpl {
|
||||||
)));
|
)));
|
||||||
|
|
||||||
// Whenever you attack a player, create a 1/1 white Glimmer enchantment creature token that's tapped and attacking that player.
|
// Whenever you attack a player, create a 1/1 white Glimmer enchantment creature token that's tapped and attacking that player.
|
||||||
this.addAbility(new SoaringLightbringerTriggeredAbility());
|
this.addAbility(new AttacksPlayerWithCreaturesTriggeredAbility(new SoaringLightbringerEffect(), SetTargetPointer.PLAYER));
|
||||||
}
|
}
|
||||||
|
|
||||||
private SoaringLightbringer(final SoaringLightbringer card) {
|
private SoaringLightbringer(final SoaringLightbringer card) {
|
||||||
|
|
@ -60,37 +58,6 @@ public final class SoaringLightbringer extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SoaringLightbringerTriggeredAbility extends TriggeredAbilityImpl {
|
|
||||||
|
|
||||||
SoaringLightbringerTriggeredAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new SoaringLightbringerEffect());
|
|
||||||
setTriggerPhrase("Whenever you attack a player, ");
|
|
||||||
}
|
|
||||||
|
|
||||||
private SoaringLightbringerTriggeredAbility(final SoaringLightbringerTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SoaringLightbringerTriggeredAbility copy() {
|
|
||||||
return new SoaringLightbringerTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
if (!isControlledBy(event.getPlayerId()) || game.getPlayer(event.getTargetId()) == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId()));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SoaringLightbringerEffect extends OneShotEffect {
|
class SoaringLightbringerEffect extends OneShotEffect {
|
||||||
|
|
||||||
SoaringLightbringerEffect() {
|
SoaringLightbringerEffect() {
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@ public final class BloomburrowCommander extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Devilish Valet", 195, Rarity.RARE, mage.cards.d.DevilishValet.class));
|
cards.add(new SetCardInfo("Devilish Valet", 195, Rarity.RARE, mage.cards.d.DevilishValet.class));
|
||||||
cards.add(new SetCardInfo("Domri, Anarch of Bolas", 98, Rarity.RARE, mage.cards.d.DomriAnarchOfBolas.class));
|
cards.add(new SetCardInfo("Domri, Anarch of Bolas", 98, Rarity.RARE, mage.cards.d.DomriAnarchOfBolas.class));
|
||||||
cards.add(new SetCardInfo("Dusk // Dawn", 138, Rarity.RARE, mage.cards.d.DuskDawn.class));
|
cards.add(new SetCardInfo("Dusk // Dawn", 138, Rarity.RARE, mage.cards.d.DuskDawn.class));
|
||||||
|
cards.add(new SetCardInfo("Echoing Assault", 24, Rarity.RARE, mage.cards.e.EchoingAssault.class));
|
||||||
cards.add(new SetCardInfo("Elspeth, Sun's Champion", 97, Rarity.MYTHIC, mage.cards.e.ElspethSunsChampion.class));
|
cards.add(new SetCardInfo("Elspeth, Sun's Champion", 97, Rarity.MYTHIC, mage.cards.e.ElspethSunsChampion.class));
|
||||||
cards.add(new SetCardInfo("End-Raze Forerunners", 214, Rarity.RARE, mage.cards.e.EndRazeForerunners.class));
|
cards.add(new SetCardInfo("End-Raze Forerunners", 214, Rarity.RARE, mage.cards.e.EndRazeForerunners.class));
|
||||||
cards.add(new SetCardInfo("Esika's Chariot", 215, Rarity.RARE, mage.cards.e.EsikasChariot.class));
|
cards.add(new SetCardInfo("Esika's Chariot", 215, Rarity.RARE, mage.cards.e.EsikasChariot.class));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
package org.mage.test.cards.single.dsc;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestCommander4Players;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author notgreat
|
||||||
|
*/
|
||||||
|
public class SoaringLightbringerTest extends CardTestCommander4Players {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_AttacksDoubled() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Soaring Lightbringer");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||||
|
|
||||||
|
attack(1, playerA, "Soaring Lightbringer", playerB);
|
||||||
|
attack(1, playerA, "Memnite", playerB);
|
||||||
|
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertTappedCount("Glimmer Token", true, 1);
|
||||||
|
assertLife(playerB, 20 - 4 - 1 - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_AttacksTwo() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Soaring Lightbringer");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||||
|
|
||||||
|
attack(1, playerA, "Soaring Lightbringer", playerB);
|
||||||
|
attack(1, playerA, "Memnite", playerD);
|
||||||
|
|
||||||
|
setChoice(playerA, "Whenever"); // Order triggers
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertTappedCount("Glimmer Token", true, 2);
|
||||||
|
assertLife(playerB, 20 - 4 - 1);
|
||||||
|
assertLife(playerD, 20 - 1 - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_AttacksPlaneswalker() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerD, "Soaring Lightbringer");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerD, "Memnite");
|
||||||
|
addCard(Zone.HAND, playerA, "Nissa Revane");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nissa Revane");
|
||||||
|
attack(2, playerD, "Memnite", "Nissa Revane");
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(2, PhaseStep.END_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerD, "Glimmer Token", 0);
|
||||||
|
assertCounterCount("Nissa Revane", CounterType.LOYALTY, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_AttacksEnters() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Soaring Lightbringer");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Falconer Adept");
|
||||||
|
|
||||||
|
attack(1, playerA, "Falconer Adept", playerB);
|
||||||
|
setChoice(playerA, "Whenever"); // Order triggers
|
||||||
|
addTarget(playerA, playerC);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertTappedCount("Glimmer Token", true, 1);
|
||||||
|
assertTappedCount("Bird Token", true, 1);
|
||||||
|
assertLife(playerB, 20 - 2 - 1);
|
||||||
|
assertLife(playerC, 20 - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
package mage.abilities.common;
|
||||||
|
|
||||||
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.constants.SetTargetPointer;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.filter.FilterPermanent;
|
||||||
|
import mage.filter.StaticFilters;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.DefenderAttackedEvent;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.target.targetpointer.FixedTarget;
|
||||||
|
import mage.target.targetpointer.FixedTargets;
|
||||||
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* based heavily on AttacksWithCreaturesTriggeredAbility
|
||||||
|
* @author notgreat
|
||||||
|
*/
|
||||||
|
public class AttacksPlayerWithCreaturesTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
private final FilterPermanent filter;
|
||||||
|
private final int minAttackers;
|
||||||
|
private final boolean onlyOpponents;
|
||||||
|
private final SetTargetPointer setTargetPointer;
|
||||||
|
|
||||||
|
public AttacksPlayerWithCreaturesTriggeredAbility(Effect effect, SetTargetPointer setTargetPointer) {
|
||||||
|
this(effect, StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED, setTargetPointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttacksPlayerWithCreaturesTriggeredAbility(Effect effect, FilterPermanent filter, SetTargetPointer setTargetPointer) {
|
||||||
|
this(effect, 1, filter, setTargetPointer, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttacksPlayerWithCreaturesTriggeredAbility(Effect effect, int minAttackers, FilterPermanent filter, SetTargetPointer setTargetPointer, boolean onlyOpponents) {
|
||||||
|
this(Zone.BATTLEFIELD, effect, minAttackers, filter, setTargetPointer, onlyOpponents, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttacksPlayerWithCreaturesTriggeredAbility(Zone zone, Effect effect, int minAttackers, FilterPermanent filter, SetTargetPointer setTargetPointer, boolean onlyOpponents, boolean optional) {
|
||||||
|
super(zone, effect, optional);
|
||||||
|
this.filter = filter;
|
||||||
|
this.minAttackers = minAttackers;
|
||||||
|
this.onlyOpponents = onlyOpponents;
|
||||||
|
this.setTargetPointer = setTargetPointer;
|
||||||
|
if (minAttackers == 1 && StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED.equals(filter) && !onlyOpponents) {
|
||||||
|
setTriggerPhrase("Whenever you attack a player, ");
|
||||||
|
} else {
|
||||||
|
setTriggerPhrase("Whenever " + CardUtil.numberToText(minAttackers) + " or more " + filter.getMessage() +
|
||||||
|
" attack " + (onlyOpponents ? "an opponent" : "a player") + ", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AttacksPlayerWithCreaturesTriggeredAbility(final AttacksPlayerWithCreaturesTriggeredAbility ability) {
|
||||||
|
super(ability);
|
||||||
|
this.filter = ability.filter;
|
||||||
|
this.minAttackers = ability.minAttackers;
|
||||||
|
this.onlyOpponents = ability.onlyOpponents;
|
||||||
|
this.setTargetPointer = ability.setTargetPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AttacksPlayerWithCreaturesTriggeredAbility copy() {
|
||||||
|
return new AttacksPlayerWithCreaturesTriggeredAbility(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkEventType(GameEvent event, Game game) {
|
||||||
|
return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
|
Player player = game.getPlayer(getControllerId());
|
||||||
|
UUID attackedId = event.getTargetId();
|
||||||
|
if (player == null || game.getPlayer(attackedId) == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DefenderAttackedEvent attackedEvent = (DefenderAttackedEvent) event;
|
||||||
|
List<Permanent> attackers = attackedEvent.getAttackers(game).stream()
|
||||||
|
.filter(permanent -> filter.match(permanent, controllerId, this, game))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (attackers.size() < minAttackers || (onlyOpponents && !game.isOpponent(player, attackedId))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch (setTargetPointer){
|
||||||
|
case NONE:
|
||||||
|
break;
|
||||||
|
case PLAYER:
|
||||||
|
getEffects().setTargetPointer(new FixedTarget(attackedId));
|
||||||
|
break;
|
||||||
|
case PERMANENT:
|
||||||
|
getEffects().setTargetPointer(new FixedTargets(new ArrayList<>(attackers), game));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException("Unexpected setTargetPointer in AttacksPlayerWithCreaturesTriggeredAbility: " + setTargetPointer);
|
||||||
|
|
||||||
|
}
|
||||||
|
this.getEffects().setValue("playerAttacked",attackedId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -25,6 +25,7 @@ public class GoadTargetEffect extends ContinuousEffectImpl {
|
||||||
* turn of the controller of that spell or ability, that creature attacks
|
* turn of the controller of that spell or ability, that creature attacks
|
||||||
* each combat if able and attacks a player other than that player if able.
|
* each combat if able and attacks a player other than that player if able.
|
||||||
*/
|
*/
|
||||||
|
public static String goadReminderText = "<i>(Until your next turn, that creature attacks each combat if able and attacks a player other than you if able.)</i>";
|
||||||
public GoadTargetEffect() {
|
public GoadTargetEffect() {
|
||||||
this(Duration.UntilYourNextTurn);
|
this(Duration.UntilYourNextTurn);
|
||||||
}
|
}
|
||||||
|
|
@ -74,6 +75,6 @@ public class GoadTargetEffect extends ContinuousEffectImpl {
|
||||||
return staticText;
|
return staticText;
|
||||||
}
|
}
|
||||||
return "goad " + getTargetPointer().describeTargets(mode.getTargets(), "that creature")
|
return "goad " + getTargetPointer().describeTargets(mode.getTargets(), "that creature")
|
||||||
+ ". <i>(Until your next turn, that creature attacks each combat if able and attacks a player other than you if able.)</i>";
|
+ ". "+goadReminderText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue