Adding targets (Part 1/3) (#13680)

Adds target and/or target adjuster to cards whose abilities have the word "target", cards A-G.
Creates SourceDealsNoncombatDamageToOpponentTriggeredAbility and DefineByTriggerTargetAdjuster
This commit is contained in:
ssk97 2025-06-17 22:35:49 -07:00 committed by GitHub
parent 6d3bd7a19f
commit 9ce5dd212a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 355 additions and 729 deletions

View file

@ -5,7 +5,9 @@ import mage.MageInt;
import mage.abilities.Ability; 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.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.hint.ValueHint;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -13,9 +15,9 @@ import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.FilterCard; import mage.filter.common.FilterControlledPermanent;
import mage.filter.common.FilterCreatureCard;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetCardInOpponentsGraveyard; import mage.target.common.TargetCardInOpponentsGraveyard;
@ -37,7 +39,10 @@ public final class AgadeemOccultist extends CardImpl {
this.toughness = new MageInt(2); this.toughness = new MageInt(2);
// {tap}: Put target creature card from an opponent's graveyard onto the battlefield under your control if its converted mana cost is less than or equal to the number of Allies you control. // {tap}: Put target creature card from an opponent's graveyard onto the battlefield under your control if its converted mana cost is less than or equal to the number of Allies you control.
this.addAbility(new SimpleActivatedAbility(new AgadeemOccultistEffect(), new TapSourceCost())); Ability ability = new SimpleActivatedAbility(new AgadeemOccultistEffect(), new TapSourceCost());
ability.addTarget(new TargetCardInOpponentsGraveyard(new FilterCreatureCard("target creature card from an opponent's graveyard")));
ability.addHint(new ValueHint("Allies you control", new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.ALLY))));
this.addAbility(ability);
} }
@ -50,7 +55,6 @@ public final class AgadeemOccultist extends CardImpl {
return new AgadeemOccultist(this); return new AgadeemOccultist(this);
} }
} }
class AgadeemOccultistEffect extends OneShotEffect { class AgadeemOccultistEffect extends OneShotEffect {
AgadeemOccultistEffect() { AgadeemOccultistEffect() {
@ -70,26 +74,12 @@ class AgadeemOccultistEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
int allycount = 0;
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) {
if (permanent.hasSubtype(SubType.ALLY, game)) {
allycount++;
}
}
FilterCard filter = new FilterCard("creature card in an opponent's graveyard");
filter.add(CardType.CREATURE.getPredicate());
TargetCardInOpponentsGraveyard target = new TargetCardInOpponentsGraveyard(1, 1, filter);
if (controller != null) { if (controller != null) {
if (target.canChoose(source.getControllerId(), source, game) Card card = game.getCard(source.getFirstTarget());
&& controller.choose(Outcome.GainControl, target, source, game)) { if (card != null) {
if (!target.getTargets().isEmpty()) { int allycount = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.ALLY)).calculate(game, source, this);
Card card = game.getCard(target.getFirstTarget()); if (card.getManaValue() <= allycount) {
if (card != null) { return controller.moveCards(card, Zone.BATTLEFIELD, source, game);
if (card.getManaValue() <= allycount) {
return controller.moveCards(card, Zone.BATTLEFIELD, source, game);
}
}
} }
} }
return true; return true;

View file

@ -1,21 +1,20 @@
package mage.cards.a; package mage.cards.a;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.effects.common.combat.MustBeBlockedByTargetSourceEffect; import mage.abilities.effects.common.combat.MustBeBlockedByTargetSourceEffect;
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.SetTargetPointer;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
import java.util.UUID;
/** /**
* *
@ -32,7 +31,11 @@ public final class AvalancheTusker extends CardImpl {
this.toughness = new MageInt(4); this.toughness = new MageInt(4);
// Whenever Avalanche Tusker attacks, target creature defending player controls blocks it this turn if able. // Whenever Avalanche Tusker attacks, target creature defending player controls blocks it this turn if able.
this.addAbility(new AvalancheTuskerAbility()); Ability ability = new AttacksTriggeredAbility(new MustBeBlockedByTargetSourceEffect(Duration.EndOfCombat)
.setText("target creature defending player controls blocks it this combat if able"), false, null, SetTargetPointer.PLAYER);
ability.addTarget(new TargetCreaturePermanent());
ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
this.addAbility(ability);
} }
private AvalancheTusker(final AvalancheTusker card) { private AvalancheTusker(final AvalancheTusker card) {
@ -44,44 +47,3 @@ public final class AvalancheTusker extends CardImpl {
return new AvalancheTusker(this); return new AvalancheTusker(this);
} }
} }
class AvalancheTuskerAbility extends TriggeredAbilityImpl {
public AvalancheTuskerAbility() {
super(Zone.BATTLEFIELD, new MustBeBlockedByTargetSourceEffect(Duration.EndOfCombat), false);
}
private AvalancheTuskerAbility(final AvalancheTuskerAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ATTACKER_DECLARED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getSourceId().equals(this.getSourceId())) {
FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls");
UUID defenderId = game.getCombat().getDefendingPlayerId(sourceId, game);
filter.add(new ControllerIdPredicate(defenderId));
this.getTargets().clear();
TargetCreaturePermanent target = new TargetCreaturePermanent(filter);
this.addTarget(target);
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever {this} attacks, target creature defending player controls blocks it this combat if able.";
}
@Override
public AvalancheTuskerAbility copy() {
return new AvalancheTuskerAbility(this);
}
}

View file

@ -1,31 +1,34 @@
package mage.cards.b; package mage.cards.b;
import mage.MageInt; import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect;
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.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterNonlandPermanent; import mage.filter.common.FilterNonlandPermanent;
import mage.filter.predicate.Predicates; import mage.filter.predicate.ObjectSourcePlayer;
import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.game.Controllable;
import mage.game.Game; import mage.game.Game;
import mage.game.events.DamagedEvent; import mage.target.Target;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.targetadjustment.GenericTargetAdjuster;
import mage.target.targetpointer.FirstTargetPointer;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
/** /**
* @author TheElk801 * @author TheElk801
*/ */
public final class BladegriffPrototype extends CardImpl { public final class BladegriffPrototype extends CardImpl {
static FilterNonlandPermanent filter = new FilterNonlandPermanent("nonland permanent of that player's choice that one of your opponents controls");
static{
filter.add(BladegriffSourceOpponentControlsPredicate.instance);
}
public BladegriffPrototype(UUID ownerId, CardSetInfo setInfo) { public BladegriffPrototype(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}"); super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}");
@ -38,7 +41,10 @@ public final class BladegriffPrototype extends CardImpl {
this.addAbility(FlyingAbility.getInstance()); this.addAbility(FlyingAbility.getInstance());
// Whenever Bladegriff Prototype deals combat damage to a player, destroy target nonland permanent of that player's choice that one of your opponents controls. // Whenever Bladegriff Prototype deals combat damage to a player, destroy target nonland permanent of that player's choice that one of your opponents controls.
this.addAbility(new BladegriffPrototypeAbility()); Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new DestroyTargetEffect(), false, true);
ability.addTarget(new TargetPermanent(filter));
ability.setTargetAdjuster(new ThatPlayersChoiceTargetAdjuster());
this.addAbility(ability);
} }
private BladegriffPrototype(final BladegriffPrototype card) { private BladegriffPrototype(final BladegriffPrototype card) {
@ -50,55 +56,26 @@ public final class BladegriffPrototype extends CardImpl {
return new BladegriffPrototype(this); return new BladegriffPrototype(this);
} }
} }
enum BladegriffSourceOpponentControlsPredicate implements ObjectSourcePlayerPredicate<Controllable> {
class BladegriffPrototypeAbility extends TriggeredAbilityImpl { instance;
BladegriffPrototypeAbility() {
super(Zone.BATTLEFIELD, new DestroyTargetEffect(), false);
}
private BladegriffPrototypeAbility(final BladegriffPrototypeAbility ability) {
super(ability);
}
@Override @Override
public BladegriffPrototypeAbility copy() { public boolean apply(ObjectSourcePlayer<Controllable> input, Game game) {
return new BladegriffPrototypeAbility(this); Controllable object = input.getObject();
} UUID playerId = input.getSource().getControllerId();
@Override return !object.isControlledBy(playerId)
public boolean checkEventType(GameEvent event, Game game) { && game.getPlayer(playerId).hasOpponent(object.getControllerId(), game);
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; }
} }
@Override class ThatPlayersChoiceTargetAdjuster extends GenericTargetAdjuster {
public boolean checkTrigger(GameEvent event, Game game) { @Override
Player player = game.getPlayer(getControllerId()); public void adjustTargets(Ability ability, Game game) {
if (player == null UUID opponentId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability);
|| !event.getSourceId().equals(this.sourceId) ability.getTargets().clear();
|| !((DamagedEvent) event).isCombatDamage()) { ability.getAllEffects().setTargetPointer(new FirstTargetPointer());
return false; Target newTarget = blueprintTarget.copy();
} newTarget.setTargetController(opponentId);
FilterPermanent filter = new FilterNonlandPermanent( ability.addTarget(newTarget);
"nonland permanent controlled by an opponent of " + player.getName()
);
filter.add(Predicates.or(
game.getOpponents(getControllerId())
.stream()
.map(ControllerIdPredicate::new)
.collect(Collectors.toSet())
));
TargetPermanent target = new TargetPermanent(filter);
target.setTargetController(event.getPlayerId());
this.getTargets().clear();
this.addTarget(target);
return true;
}
@Override
public String getRule() {
return "Whenever {this} deals combat damage to a player, " +
"destroy target nonland permanent of that player's choice " +
"that one of your opponents controls.";
} }
} }

View file

@ -3,21 +3,21 @@ package mage.cards.c;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.SpellAbility; import mage.abilities.SpellAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.SourceDealsNoncombatDamageToOpponentTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.effects.common.cost.CostModificationEffectImpl;
import mage.abilities.keyword.TrampleAbility; import mage.abilities.keyword.TrampleAbility;
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.common.FilterCreatureOrPlaneswalkerPermanent; import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.events.DamagedPlayerEvent; import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
import mage.util.CardUtil; import mage.util.CardUtil;
import mage.watchers.Watcher; import mage.watchers.Watcher;
@ -46,7 +46,10 @@ public final class ChandrasIncinerator extends CardImpl {
this.addAbility(TrampleAbility.getInstance()); this.addAbility(TrampleAbility.getInstance());
// Whenever a source you control deals noncombat damage to an opponent, Chandra's Incinerator deals that much damage to target creature or planeswalker that player controls. // Whenever a source you control deals noncombat damage to an opponent, Chandra's Incinerator deals that much damage to target creature or planeswalker that player controls.
this.addAbility(new ChandrasIncineratorTriggeredAbility()); Ability ability = new SourceDealsNoncombatDamageToOpponentTriggeredAbility(new DamageTargetEffect(SavedDamageValue.MUCH), SetTargetPointer.PLAYER);
ability.addTarget(new TargetPermanent(new FilterCreatureOrPlaneswalkerPermanent("creature or planeswalker that player controls")));
ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
this.addAbility(ability);
} }
private ChandrasIncinerator(final ChandrasIncinerator card) { private ChandrasIncinerator(final ChandrasIncinerator card) {
@ -123,47 +126,3 @@ class ChandrasIncineratorWatcher extends Watcher {
return damageMap.getOrDefault(playerId, 0); return damageMap.getOrDefault(playerId, 0);
} }
} }
class ChandrasIncineratorTriggeredAbility extends TriggeredAbilityImpl {
ChandrasIncineratorTriggeredAbility() {
super(Zone.BATTLEFIELD, null);
}
private ChandrasIncineratorTriggeredAbility(final ChandrasIncineratorTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
DamagedPlayerEvent dEvent = (DamagedPlayerEvent) event;
if (dEvent.isCombatDamage()
|| !game.getOpponents(event.getTargetId()).contains(getControllerId())
|| !game.getControllerId(event.getSourceId()).equals(getControllerId())) {
return false;
}
this.getEffects().clear();
this.addEffect(new DamageTargetEffect(event.getAmount()));
FilterPermanent filter = new FilterCreatureOrPlaneswalkerPermanent("creature or planeswalker");
filter.add(new ControllerIdPredicate(event.getTargetId()));
this.getTargets().clear();
this.addTarget(new TargetPermanent(filter));
return true;
}
@Override
public ChandrasIncineratorTriggeredAbility copy() {
return new ChandrasIncineratorTriggeredAbility(this);
}
@Override
public String getRule() {
return "Whenever a source you control deals noncombat damage to an opponent, " +
"{this} deals that much damage to target creature or planeswalker that player controls.";
}
}

View file

@ -1,7 +1,8 @@
package mage.cards.c; package mage.cards.c;
import mage.MageInt; import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.Ability;
import mage.abilities.common.SourceDealsNoncombatDamageToOpponentTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.keyword.DoubleStrikeAbility; import mage.abilities.keyword.DoubleStrikeAbility;
@ -10,13 +11,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import java.util.Objects;
import java.util.UUID; import java.util.UUID;
/** /**
@ -33,7 +28,9 @@ public final class ChandrasPyreling extends CardImpl {
this.toughness = new MageInt(3); this.toughness = new MageInt(3);
// Whenever a source you control deals noncombat damage to an opponent, Chandra's Pyreling gets +1/+0 and gains double strike until end of turn. // Whenever a source you control deals noncombat damage to an opponent, Chandra's Pyreling gets +1/+0 and gains double strike until end of turn.
this.addAbility(new ChandrasPyrelingAbility()); Ability ability = new SourceDealsNoncombatDamageToOpponentTriggeredAbility(new BoostSourceEffect(1, 0, Duration.EndOfTurn).setText(" this creature gets +1/+0"));
ability.addEffect(new GainAbilitySourceEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn).setText("gains double strike until end of turn").concatBy("and"));
this.addAbility(ability);
} }
private ChandrasPyreling(final ChandrasPyreling card) { private ChandrasPyreling(final ChandrasPyreling card) {
@ -45,38 +42,3 @@ public final class ChandrasPyreling extends CardImpl {
return new ChandrasPyreling(this); return new ChandrasPyreling(this);
} }
} }
class ChandrasPyrelingAbility extends TriggeredAbilityImpl {
ChandrasPyrelingAbility() {
super(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn));
addEffect(new GainAbilitySourceEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn));
}
private ChandrasPyrelingAbility(final ChandrasPyrelingAbility ability) {
super(ability);
}
@Override
public ChandrasPyrelingAbility copy() {
return new ChandrasPyrelingAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event;
return !damageEvent.isCombatDamage()
&& game.getOpponents(controllerId).contains(event.getTargetId())
&& Objects.equals(controllerId, game.getControllerId(event.getSourceId()));
}
@Override
public String getRule() {
return "Whenever a source you control deals noncombat damage to an opponent, {this} gets +1/+0 and gains double strike until end of turn.";
}
}

View file

@ -2,13 +2,17 @@ package mage.cards.c;
import mage.MageInt; import mage.MageInt;
import mage.MageObjectReference; import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.DiesThisOrAnotherTriggeredAbility; import mage.abilities.common.DiesThisOrAnotherTriggeredAbility;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
import mage.abilities.keyword.ReachAbility; import mage.abilities.keyword.ReachAbility;
import mage.abilities.keyword.VigilanceAbility; import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.*; import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreatureCard;
@ -16,10 +20,10 @@ import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.MageObjectReferencePredicate; import mage.filter.predicate.mageobject.MageObjectReferencePredicate;
import mage.filter.predicate.mageobject.ToughnessPredicate; import mage.filter.predicate.mageobject.ToughnessPredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.Target;
import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCardInYourGraveyard;
import mage.target.targetadjustment.GenericTargetAdjuster;
import java.util.UUID; import java.util.UUID;
@ -44,7 +48,10 @@ public final class ColfenorTheLastYew extends CardImpl {
this.addAbility(ReachAbility.getInstance()); this.addAbility(ReachAbility.getInstance());
// Whenever Colfenor, the Last Yew or another creature you control dies, return up to one other target creature card with lesser toughness from your graveyard to your hand. // Whenever Colfenor, the Last Yew or another creature you control dies, return up to one other target creature card with lesser toughness from your graveyard to your hand.
this.addAbility(new ColfenorTheLastYewTriggeredAbility()); Ability ability = new DiesThisOrAnotherTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect(), false, StaticFilters.FILTER_CONTROLLED_CREATURE);
ability.addTarget(new TargetCardInYourGraveyard(0, 1, new FilterCreatureCard("other target creature card with lesser toughness")));
ability.setTargetAdjuster(new ColfenorTheLastYewTargetAdjuster());
this.addAbility(ability);
} }
private ColfenorTheLastYew(final ColfenorTheLastYew card) { private ColfenorTheLastYew(final ColfenorTheLastYew card) {
@ -56,43 +63,15 @@ public final class ColfenorTheLastYew extends CardImpl {
return new ColfenorTheLastYew(this); return new ColfenorTheLastYew(this);
} }
} }
class ColfenorTheLastYewTargetAdjuster extends GenericTargetAdjuster {
class ColfenorTheLastYewTriggeredAbility extends DiesThisOrAnotherTriggeredAbility {
ColfenorTheLastYewTriggeredAbility() {
super(new ReturnFromGraveyardToHandTargetEffect(), false, StaticFilters.FILTER_CONTROLLED_CREATURE);
}
private ColfenorTheLastYewTriggeredAbility(final ColfenorTheLastYewTriggeredAbility ability) {
super(ability);
}
@Override @Override
public DiesThisOrAnotherTriggeredAbility copy() { public void adjustTargets(Ability ability, Game game) {
return new ColfenorTheLastYewTriggeredAbility(this); Permanent permanent = (Permanent)ability.getEffects().get(0).getValue("creatureDied");
} ability.getTargets().clear();
Target newTarget = blueprintTarget.copy();
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!super.checkTrigger(event, game)) {
return false;
}
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
Permanent permanent = zEvent.getTarget();
if (permanent == null) {
return false;
}
FilterCard filterCard = new FilterCreatureCard("creature card with toughness less than " + permanent.getToughness().getValue()); FilterCard filterCard = new FilterCreatureCard("creature card with toughness less than " + permanent.getToughness().getValue());
filterCard.add(new ToughnessPredicate(ComparisonType.FEWER_THAN, permanent.getToughness().getValue())); filterCard.add(new ToughnessPredicate(ComparisonType.FEWER_THAN, permanent.getToughness().getValue()));
filterCard.add(Predicates.not(new MageObjectReferencePredicate(new MageObjectReference(permanent, game)))); filterCard.add(Predicates.not(new MageObjectReferencePredicate(new MageObjectReference(permanent, game))));
this.getTargets().clear(); ability.addTarget(newTarget);
this.addTarget(new TargetCardInYourGraveyard(0, 1, filterCard));
return true;
}
@Override
public String getRule() {
return "Whenever {this} or another creature you control dies, return up to one other target creature card " +
"with lesser toughness from your graveyard to your hand.";
} }
} }

View file

@ -1,20 +1,19 @@
package mage.cards.d; package mage.cards.d;
import java.util.UUID; import mage.abilities.Ability;
import mage.abilities.common.DiesCreatureTriggeredAbility;
import mage.MageObject; import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect;
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.Zone;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
/** /**
* *
@ -23,10 +22,13 @@ import mage.target.common.TargetControlledCreaturePermanent;
public final class DeathsPresence extends CardImpl { public final class DeathsPresence extends CardImpl {
public DeathsPresence(UUID ownerId, CardSetInfo setInfo) { public DeathsPresence(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{5}{G}"); super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{5}{G}");
// Whenever a creature you control dies, put X +1/+1 counters on target creature you control, where X is the power of the creature that died. // Whenever a creature you control dies, put X +1/+1 counters on target creature you control, where X is the power of the creature that died.
this.addAbility(new DeathsPresenceTriggeredAbility()); this.addAbility(new DiesCreatureTriggeredAbility(
new AddCountersTargetEffect(CounterType.P1P1.createInstance(), DeathsPresenceDiedPermanentPowerCount.instance)
.setText("put X +1/+1 counters on target creature you control, where X is the power of the creature that died"),
false, StaticFilters.FILTER_CONTROLLED_CREATURE));
} }
private DeathsPresence(final DeathsPresence card) { private DeathsPresence(final DeathsPresence card) {
@ -39,50 +41,31 @@ public final class DeathsPresence extends CardImpl {
} }
} }
class DeathsPresenceTriggeredAbility extends TriggeredAbilityImpl { enum DeathsPresenceDiedPermanentPowerCount implements DynamicValue {
instance;
public DeathsPresenceTriggeredAbility() {
super(Zone.BATTLEFIELD, null);
setLeavesTheBattlefieldTrigger(true);
}
private DeathsPresenceTriggeredAbility(final DeathsPresenceTriggeredAbility ability) {
super(ability);
}
@Override @Override
public DeathsPresenceTriggeredAbility copy() { public int calculate(Game game, Ability sourceAbility, Effect effect) {
return new DeathsPresenceTriggeredAbility(this); Permanent targetPermanent = (Permanent) effect.getValue("creatureDied");
} if (targetPermanent != null) {
return targetPermanent.getPower().getValue();
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
ZoneChangeEvent zoneChangeEvent = (ZoneChangeEvent) event;
if (zoneChangeEvent.isDiesEvent()) {
Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
if (permanent != null && permanent.isControlledBy(this.getControllerId()) && permanent.isCreature(game)) {
this.getTargets().clear();
this.addTarget(new TargetControlledCreaturePermanent());
this.getEffects().clear();
this.addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance(permanent.getPower().getValue())));
return true;
}
} }
return false;
return 0;
} }
@Override @Override
public String getRule() { public DeathsPresenceDiedPermanentPowerCount copy() {
return "Whenever a creature you control dies, put X +1/+1 counters on target creature you control, where X is the power of the creature that died."; return DeathsPresenceDiedPermanentPowerCount.instance;
} }
@Override @Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) { public String toString() {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game); return "X";
}
@Override
public String getMessage() {
return "its power";
} }
} }

View file

@ -10,13 +10,11 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterLandPermanent;
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.target.Target; import mage.target.common.TargetLandPermanent;
import mage.target.TargetPermanent; import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID; import java.util.UUID;
@ -53,6 +51,8 @@ class DeusOfCalamityTriggeredAbility extends TriggeredAbilityImpl {
public DeusOfCalamityTriggeredAbility() { public DeusOfCalamityTriggeredAbility() {
super(Zone.BATTLEFIELD, new DestroyTargetEffect(), false); super(Zone.BATTLEFIELD, new DestroyTargetEffect(), false);
addTarget(new TargetLandPermanent());
setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
} }
private DeusOfCalamityTriggeredAbility(final DeusOfCalamityTriggeredAbility ability) { private DeusOfCalamityTriggeredAbility(final DeusOfCalamityTriggeredAbility ability) {
@ -74,11 +74,7 @@ class DeusOfCalamityTriggeredAbility extends TriggeredAbilityImpl {
if (event.getSourceId().equals(this.getSourceId()) if (event.getSourceId().equals(this.getSourceId())
&& event.getAmount() > 5 && event.getAmount() > 5
&& game.getOpponents(this.getControllerId()).contains(event.getTargetId())) { && game.getOpponents(this.getControllerId()).contains(event.getTargetId())) {
FilterPermanent filter = new FilterLandPermanent("land of the damaged player"); this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game));
filter.add(new ControllerIdPredicate(event.getTargetId()));
Target target = new TargetPermanent(filter);
this.getTargets().clear();
this.addTarget(target);
return true; return true;
} }
return false; return false;

View file

@ -1,19 +1,16 @@
package mage.cards.d; package mage.cards.d;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.effects.OneShotEffect; import mage.abilities.dynamicvalue.common.CountersSourceCount;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.constants.SubType; import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
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.Outcome; import mage.constants.SubType;
import mage.constants.WatcherScope; import mage.constants.WatcherScope;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.filter.FilterOpponent; import mage.filter.FilterOpponent;
@ -21,16 +18,23 @@ 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.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.target.TargetPlayer; import mage.target.TargetPlayer;
import mage.watchers.Watcher; import mage.watchers.Watcher;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/** /**
*
* @author jeffwadsworth * @author jeffwadsworth
*/ */
public final class DiseasedVermin extends CardImpl { public final class DiseasedVermin extends CardImpl {
static final FilterOpponent filter = new FilterOpponent("player previously dealt damage by {this}");
static {
filter.add(new DiseasedVerminPredicate());
}
public DiseasedVermin(UUID ownerId, CardSetInfo setInfo) { public DiseasedVermin(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
@ -46,12 +50,11 @@ public final class DiseasedVermin extends CardImpl {
false)); false));
// At the beginning of your upkeep, Diseased Vermin deals X damage to target opponent previously dealt damage by it, where X is the number of infection counters on it. // At the beginning of your upkeep, Diseased Vermin deals X damage to target opponent previously dealt damage by it, where X is the number of infection counters on it.
Ability ability = new BeginningOfUpkeepTriggeredAbility( Ability ability = new BeginningOfUpkeepTriggeredAbility(new DamageTargetEffect(new CountersSourceCount(CounterType.INFECTION))
new DiseasedVerminEffect() .setText("{this} deals X damage to target opponent previously dealt damage by it, where X is the number of infection counters on it"));
); ability.addTarget(new TargetPlayer(filter));
ability.addWatcher(new DiseasedVerminWatcher()); ability.addWatcher(new DiseasedVerminWatcher());
this.addAbility(ability); this.addAbility(ability);
} }
private DiseasedVermin(final DiseasedVermin card) { private DiseasedVermin(final DiseasedVermin card) {
@ -64,51 +67,6 @@ public final class DiseasedVermin extends CardImpl {
} }
} }
class DiseasedVerminEffect extends OneShotEffect {
static final FilterOpponent filter = new FilterOpponent("player previously dealt damage by {this}");
static {
filter.add(new DiseasedVerminPredicate());
}
public DiseasedVerminEffect() {
super(Outcome.Benefit);
this.staticText = "{this} deals X damage to target opponent previously dealt damage by it, where X is the number of infection counters on it";
}
private DiseasedVerminEffect(final DiseasedVerminEffect effect) {
super(effect);
}
@Override
public DiseasedVerminEffect copy() {
return new DiseasedVerminEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent != null
&& controller != null) {
TargetPlayer targetOpponent = new TargetPlayer(1, 1, false, filter);
if (targetOpponent.canChoose(controller.getId(), source, game)
&& controller.choose(Outcome.Damage, targetOpponent, source, game)) {
Player opponent = game.getPlayer(targetOpponent.getFirstTarget());
if (opponent != null
&& sourcePermanent.getCounters(game).getCount(CounterType.INFECTION) > 0) {
opponent.damage(
sourcePermanent.getCounters(game).getCount(CounterType.INFECTION),
source.getSourceId(), source, game, false, true);
return true;
}
}
}
return false;
}
}
class DiseasedVerminPredicate implements ObjectSourcePlayerPredicate<Player> { class DiseasedVerminPredicate implements ObjectSourcePlayerPredicate<Player> {
@Override @Override

View file

@ -1,8 +1,9 @@
package mage.cards.f; package mage.cards.f;
import mage.MageInt; import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.TriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SourceDealsNoncombatDamageToOpponentTriggeredAbility;
import mage.abilities.condition.common.DeliriumCondition; import mage.abilities.condition.common.DeliriumCondition;
import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount;
import mage.abilities.dynamicvalue.common.SavedDamageValue; import mage.abilities.dynamicvalue.common.SavedDamageValue;
@ -11,13 +12,9 @@ import mage.abilities.effects.common.DamageTargetEffect;
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.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
import mage.game.events.DamagedEvent;
import mage.game.events.GameEvent;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
import java.util.UUID; import java.util.UUID;
@ -39,7 +36,13 @@ public final class FearOfBurningAlive extends CardImpl {
)); ));
// Delirium -- Whenever a source you control deals noncombat damage to an opponent, if there are four or more card types among cards in your graveyard, Fear of Burning Alive deals that amount of damage to target creature that player controls. // Delirium -- Whenever a source you control deals noncombat damage to an opponent, if there are four or more card types among cards in your graveyard, Fear of Burning Alive deals that amount of damage to target creature that player controls.
this.addAbility(new FearOfBurningAliveTriggeredAbility()); TriggeredAbility ability = new SourceDealsNoncombatDamageToOpponentTriggeredAbility(new DamageTargetEffect(SavedDamageValue.AMOUNT), SetTargetPointer.PLAYER);
ability.addTarget(new TargetPermanent(new FilterCreaturePermanent("creature that player controls")));
ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
ability.withInterveningIf(DeliriumCondition.instance);
ability.setAbilityWord(AbilityWord.DELIRIUM);
ability.addHint(CardTypesInGraveyardCount.YOU.getHint());
this.addAbility(ability);
} }
private FearOfBurningAlive(final FearOfBurningAlive card) { private FearOfBurningAlive(final FearOfBurningAlive card) {
@ -51,49 +54,3 @@ public final class FearOfBurningAlive extends CardImpl {
return new FearOfBurningAlive(this); return new FearOfBurningAlive(this);
} }
} }
class FearOfBurningAliveTriggeredAbility extends TriggeredAbilityImpl {
FearOfBurningAliveTriggeredAbility() {
super(Zone.BATTLEFIELD, new DamageTargetEffect(SavedDamageValue.MANY)
.setText("{this} deals that amount of damage to target creature that player controls"));
this.setTriggerPhrase("Whenever a source you control deals noncombat damage to an opponent, " +
"if there are four or more card types among cards in your graveyard, ");
this.setAbilityWord(AbilityWord.DELIRIUM);
this.addHint(CardTypesInGraveyardCount.YOU.getHint());
}
private FearOfBurningAliveTriggeredAbility(final FearOfBurningAliveTriggeredAbility ability) {
super(ability);
}
@Override
public FearOfBurningAliveTriggeredAbility copy() {
return new FearOfBurningAliveTriggeredAbility(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 (((DamagedEvent) event).isCombatDamage()
|| !isControlledBy(game.getControllerId(event.getSourceId()))
|| !game.getOpponents(getControllerId()).contains(event.getTargetId())) {
return false;
}
this.getEffects().setValue("damage", event.getAmount());
FilterPermanent filter = new FilterCreaturePermanent();
filter.add(new ControllerIdPredicate(event.getTargetId()));
this.getTargets().clear();
this.addTarget(new TargetPermanent(filter));
return true;
}
@Override
public boolean checkInterveningIfClause(Game game) {
return DeliriumCondition.instance.apply(game, this);
}
}

View file

@ -15,10 +15,8 @@ import mage.constants.*;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.common.FilterArtifactOrEnchantmentPermanent; import mage.filter.common.FilterArtifactOrEnchantmentPermanent;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
import java.util.UUID; import java.util.UUID;
@ -52,7 +50,10 @@ public final class FelineSovereign extends CardImpl {
this.addAbility(ability); this.addAbility(ability);
// Whenever one or more Cats you control deal combat damage to a player, destroy up to one target artifact or enchantment that player controls. // Whenever one or more Cats you control deal combat damage to a player, destroy up to one target artifact or enchantment that player controls.
this.addAbility(new FelineSovereignTriggeredAbility()); Ability ability2 = new OneOrMoreCombatDamagePlayerTriggeredAbility(new DestroyTargetEffect(), SetTargetPointer.PLAYER, filterCat, false);
ability2.addTarget(new TargetPermanent(0, 1, new FilterArtifactOrEnchantmentPermanent("artifact or enchantment that player controls")));
ability2.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
this.addAbility(ability2);
} }
private FelineSovereign(final FelineSovereign card) { private FelineSovereign(final FelineSovereign card) {
@ -64,34 +65,3 @@ public final class FelineSovereign extends CardImpl {
return new FelineSovereign(this); return new FelineSovereign(this);
} }
} }
class FelineSovereignTriggeredAbility extends OneOrMoreCombatDamagePlayerTriggeredAbility {
private static final FilterCreaturePermanent catFilter = new FilterCreaturePermanent(SubType.CAT, "Cats");
FelineSovereignTriggeredAbility() {
super(new DestroyTargetEffect().setText("destroy up to one target artifact or enchantment that player controls"), catFilter);
}
private FelineSovereignTriggeredAbility(final FelineSovereignTriggeredAbility ability) {
super(ability);
}
@Override
public FelineSovereignTriggeredAbility copy() {
return new FelineSovereignTriggeredAbility(this);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!super.checkTrigger(event, game)) {
return false;
}
this.getTargets().clear();
FilterArtifactOrEnchantmentPermanent filter = new FilterArtifactOrEnchantmentPermanent();
filter.add(new ControllerIdPredicate(event.getTargetId()));
this.addTarget(new TargetPermanent(0, 1, filter, false));
return true;
}
}

View file

@ -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.TriggeredAbilityImpl; import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
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,14 +14,13 @@ 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.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicate; import mage.filter.predicate.Predicate;
import mage.filter.predicate.permanent.ControllerIdPredicate;
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.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
import java.util.UUID; import java.util.UUID;
@ -31,9 +30,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 filter = new FilterCreaturePermanent();
private static final FilterPermanent filterDragons = new FilterControlledCreaturePermanent("Dragons you control");
static { static {
filter.add(FirkraagCunningInstigatorPredicate.instance); filter.add(FirkraagCunningInstigatorPredicate.instance);
filterDragons.add(SubType.DRAGON.getPredicate());
} }
public FirkraagCunningInstigator(UUID ownerId, CardSetInfo setInfo) { public FirkraagCunningInstigator(UUID ownerId, CardSetInfo setInfo) {
@ -51,7 +52,10 @@ 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.
this.addAbility(new FirkraagCunningInstigatorTriggeredAbility()); Ability abilityGoad = new AttacksWithCreaturesTriggeredAbility(Zone.BATTLEFIELD, new GoadTargetEffect(), 1, filterDragons, true);
abilityGoad.addTarget(new TargetPermanent(new FilterCreaturePermanent("target creature that player controls")));
abilityGoad.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
this.addAbility(abilityGoad);
// Whenever a creature deals combat damage to one of your opponents, if that creature had to attack this combat, you put a +1/+1 counter on Firkraag, Cunning Instigator and you draw a card. // Whenever a creature deals combat damage to one of your opponents, if that creature had to attack this combat, you put a +1/+1 counter on Firkraag, Cunning Instigator and you draw a card.
Ability ability = new DealsDamageToAPlayerAllTriggeredAbility( Ability ability = new DealsDamageToAPlayerAllTriggeredAbility(
@ -88,48 +92,3 @@ enum FirkraagCunningInstigatorPredicate implements Predicate<Permanent> {
.anyMatch(input.getId()::equals); .anyMatch(input.getId()::equals);
} }
} }
class FirkraagCunningInstigatorTriggeredAbility extends TriggeredAbilityImpl {
FirkraagCunningInstigatorTriggeredAbility() {
super(Zone.BATTLEFIELD, new GoadTargetEffect());
}
private FirkraagCunningInstigatorTriggeredAbility(final FirkraagCunningInstigatorTriggeredAbility ability) {
super(ability);
}
@Override
public FirkraagCunningInstigatorTriggeredAbility copy() {
return new FirkraagCunningInstigatorTriggeredAbility(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 (this.isControlledBy(event.getPlayerId())
&& game.getOpponents(this.getControllerId()).contains(event.getTargetId())
&& ((DefenderAttackedEvent) event)
.getAttackers(game)
.stream()
.anyMatch(permanent -> permanent.hasSubtype(SubType.DRAGON, game))) {
this.getTargets().clear();
FilterPermanent filter = new FilterCreaturePermanent(
"creature controlled by " + game.getPlayer(event.getTargetId()).getName()
);
filter.add(new ControllerIdPredicate(event.getTargetId()));
this.addTarget(new TargetPermanent(filter));
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever one or more Dragons you control attack an opponent, goad target creature that player controls.";
}
}

View file

@ -1,20 +1,17 @@
package mage.cards.f; package mage.cards.f;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.HasteAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubType; import mage.constants.SubType;
import mage.abilities.keyword.TrampleAbility;
import mage.abilities.keyword.HasteAbility;
import mage.constants.CardType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.filter.FilterCard; import mage.filter.FilterCard;
@ -24,6 +21,11 @@ import mage.game.events.GameEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetCardInGraveyard;
import mage.target.targetadjustment.DefineByTriggerTargetAdjuster;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/** /**
* *
@ -64,6 +66,7 @@ class FroghemothTriggeredAbility extends DealsCombatDamageToAPlayerTriggeredAbil
public FroghemothTriggeredAbility() { public FroghemothTriggeredAbility() {
super(new FroghemothEffect(), false); super(new FroghemothEffect(), false);
setTargetAdjuster(DefineByTriggerTargetAdjuster.instance);
} }
private FroghemothTriggeredAbility(final FroghemothTriggeredAbility ability) { private FroghemothTriggeredAbility(final FroghemothTriggeredAbility ability) {

View file

@ -15,6 +15,7 @@ import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.stack.Spell; import mage.game.stack.Spell;
import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCardInYourGraveyard;
import mage.target.targetadjustment.DefineByTriggerTargetAdjuster;
import mage.watchers.common.CastFromHandWatcher; import mage.watchers.common.CastFromHandWatcher;
import java.util.UUID; import java.util.UUID;
@ -71,6 +72,7 @@ class GaleWaterdeepProdigyTriggeredAbility extends SpellCastControllerTriggeredA
false false
); );
addWatcher(new CastFromHandWatcher()); addWatcher(new CastFromHandWatcher());
setTargetAdjuster(DefineByTriggerTargetAdjuster.instance);
} }
private GaleWaterdeepProdigyTriggeredAbility(final GaleWaterdeepProdigyTriggeredAbility ability) { private GaleWaterdeepProdigyTriggeredAbility(final GaleWaterdeepProdigyTriggeredAbility ability) {

View file

@ -1,29 +1,23 @@
package mage.cards.g; package mage.cards.g;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.Ability;
import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect; import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect;
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.Duration; import mage.constants.Duration;
import mage.constants.Zone; import mage.constants.SetTargetPointer;
import mage.filter.FilterPermanent; import mage.constants.SubType;
import mage.filter.common.FilterArtifactPermanent; import mage.target.common.TargetArtifactPermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
import mage.game.Game;
import mage.game.combat.CombatGroup; import java.util.UUID;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.Target;
import mage.target.TargetPermanent;
/** /**
* *
@ -40,14 +34,13 @@ public final class GoblinVandal extends CardImpl {
this.toughness = new MageInt(1); this.toughness = new MageInt(1);
// Whenever Goblin Vandal attacks and isn't blocked, you may pay {R}. If you do, destroy target artifact defending player controls and Goblin Vandal assigns no combat damage this turn. // Whenever Goblin Vandal attacks and isn't blocked, you may pay {R}. If you do, destroy target artifact defending player controls and Goblin Vandal assigns no combat damage this turn.
Effect effect = new DestroyTargetEffect(); DoIfCostPaid effect = new DoIfCostPaid(new DestroyTargetEffect().setText("destroy target artifact defending player controls"),
effect.setText("destroy target artifact defending player controls"); new ManaCostsImpl<>("{R}"), "Pay {R} to destroy artifact of defending player?");
DoIfCostPaid effect2 = new DoIfCostPaid(effect, new ManaCostsImpl<>("{R}"), "Pay {R} to destroy artifact of defending player?"); effect.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn).setText("and {this} assigns no combat damage this turn"));
effect = new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn); Ability ability = new AttacksAndIsNotBlockedTriggeredAbility(effect, false, SetTargetPointer.PLAYER);
effect.setText("and {this} assigns no combat damage this turn"); ability.addTarget(new TargetArtifactPermanent());
effect2.addEffect(effect); ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
this.addAbility(new GoblinVandalTriggeredAbility(effect2)); this.addAbility(ability);
} }
private GoblinVandal(final GoblinVandal card) { private GoblinVandal(final GoblinVandal card) {
@ -59,47 +52,3 @@ public final class GoblinVandal extends CardImpl {
return new GoblinVandal(this); return new GoblinVandal(this);
} }
} }
class GoblinVandalTriggeredAbility extends TriggeredAbilityImpl {
public GoblinVandalTriggeredAbility(Effect effect) {
super(Zone.BATTLEFIELD, effect, false );
}
private GoblinVandalTriggeredAbility(final GoblinVandalTriggeredAbility ability) {
super(ability);
}
@Override
public GoblinVandalTriggeredAbility copy() {
return new GoblinVandalTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DECLARED_BLOCKERS;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent sourcePermanent = game.getPermanent(getSourceId());
if (sourcePermanent.isAttacking()) {
for (CombatGroup combatGroup: game.getCombat().getGroups()) {
if (combatGroup.getBlockers().isEmpty() && combatGroup.getAttackers().contains(getSourceId())) {
UUID defendingPlayerId = game.getCombat().getDefendingPlayerId(getSourceId(), game);
FilterPermanent filter = new FilterArtifactPermanent();
filter.add(new ControllerIdPredicate(defendingPlayerId));
Target target = new TargetPermanent(filter);
this.addTarget(target);
return true;
}
}
}
return false;
}
@Override
public String getRule() {
return "Whenever {this} attacks and isn't blocked, you may pay {R}. If you do, destroy target artifact defending player controls and {this} assigns no combat damage this turn.";
}
}

View file

@ -1,7 +1,8 @@
package mage.cards.g; package mage.cards.g;
import mage.MageInt; import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.Ability;
import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
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;
@ -18,11 +19,8 @@ import mage.constants.*;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.AttackingPredicate; import mage.filter.predicate.permanent.AttackingPredicate;
import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.target.common.TargetCreaturePermanent;
import mage.game.Game; import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
import mage.game.events.DefenderAttackedEvent;
import mage.game.events.GameEvent;
import mage.target.TargetPermanent;
import java.util.UUID; import java.util.UUID;
@ -58,7 +56,12 @@ 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.
this.addAbility(new GornogTheRedReaperTriggeredAbility()); Ability ability = new AttacksWithCreaturesTriggeredAbility(Zone.BATTLEFIELD,
new BecomesCreatureTypeTargetEffect(Duration.EndOfGame, SubType.COWARD),
1, filter, true);
ability.addTarget(new TargetCreaturePermanent());
ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
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(
@ -75,42 +78,3 @@ public final class GornogTheRedReaper extends CardImpl {
return new GornogTheRedReaper(this); return new GornogTheRedReaper(this);
} }
} }
class GornogTheRedReaperTriggeredAbility extends TriggeredAbilityImpl {
GornogTheRedReaperTriggeredAbility() {
super(Zone.BATTLEFIELD, new BecomesCreatureTypeTargetEffect(Duration.EndOfGame, SubType.COWARD)
.setText("target creature that player controls becomes a Coward"));
this.setTriggerPhrase("Whenever one or more Warriors you control attack a player, ");
}
private GornogTheRedReaperTriggeredAbility(final GornogTheRedReaperTriggeredAbility ability) {
super(ability);
}
@Override
public GornogTheRedReaperTriggeredAbility copy() {
return new GornogTheRedReaperTriggeredAbility(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 (game.getPlayer(event.getTargetId()) == null
|| ((DefenderAttackedEvent) event)
.getAttackers(game)
.stream()
.noneMatch(p -> p.hasSubtype(SubType.WARRIOR, game) && p.isControlledBy(getControllerId()))) {
return false;
}
FilterPermanent filter = new FilterCreaturePermanent("creature controlled by defending player");
filter.add(new ControllerIdPredicate(event.getTargetId()));
this.getTargets().clear();
this.addTarget(new TargetPermanent(filter));
return true;
}
}

View file

@ -20,6 +20,7 @@ import mage.game.events.GameEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import mage.target.targetadjustment.DefineByTriggerTargetAdjuster;
import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil; import mage.util.CardUtil;
@ -69,6 +70,7 @@ class GrenzoHavocRaiserTriggeredAbility extends TriggeredAbilityImpl {
public GrenzoHavocRaiserTriggeredAbility(Effect effect) { public GrenzoHavocRaiserTriggeredAbility(Effect effect) {
super(Zone.BATTLEFIELD, effect, false); super(Zone.BATTLEFIELD, effect, false);
setTriggerPhrase("Whenever a creature you control deals combat damage to a player, "); setTriggerPhrase("Whenever a creature you control deals combat damage to a player, ");
setTargetAdjuster(DefineByTriggerTargetAdjuster.instance);
} }
private GrenzoHavocRaiserTriggeredAbility(final GrenzoHavocRaiserTriggeredAbility ability) { private GrenzoHavocRaiserTriggeredAbility(final GrenzoHavocRaiserTriggeredAbility ability) {

View file

@ -1,16 +1,19 @@
package mage.cards.g; package mage.cards.g;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.ReturnToHandChosenControlledPermanentEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect;
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.filter.common.FilterControlledPermanent; import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.mageobject.HistoricPredicate;
import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.filter.predicate.mageobject.HistoricPredicate;
import mage.target.TargetPermanent;
import java.util.UUID;
/** /**
* *
@ -32,8 +35,11 @@ public final class GuardiansOfKoilos extends CardImpl {
this.toughness = new MageInt(4); this.toughness = new MageInt(4);
// When Guardians of Koilos enters the battlefield, you may return another target historic permanent you control to its owner's hand. // When Guardians of Koilos enters the battlefield, you may return another target historic permanent you control to its owner's hand.
this.addAbility(new EntersBattlefieldTriggeredAbility(new ReturnToHandChosenControlledPermanentEffect(filter) Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()
.setText("you may return another target historic permanent you control to its owner's hand. <i>(Artifacts, legendaries, and Sagas are historic.)</i>"), true)); .setText("you may return another target historic permanent you control to its owner's hand. <i>(Artifacts, legendaries, and Sagas are historic.)</i>"),
true);
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
} }
private GuardiansOfKoilos(final GuardiansOfKoilos card) { private GuardiansOfKoilos(final GuardiansOfKoilos card) {

View file

@ -1,21 +1,21 @@
package mage.cards.n; package mage.cards.n;
import java.util.Objects;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.SourceDealsNoncombatDamageToOpponentTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedDamageValue; import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.continuous.MaximumHandSizeControllerEffect; import mage.abilities.effects.common.continuous.MaximumHandSizeControllerEffect;
import mage.constants.*;
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.game.Game; import mage.constants.CardType;
import mage.game.events.DamagedPlayerEvent; import mage.constants.Duration;
import mage.game.events.GameEvent; import mage.constants.SubType;
import mage.constants.SuperType;
import java.util.UUID;
/** /**
* *
@ -40,7 +40,7 @@ public final class NivMizzetVisionary extends CardImpl {
this.addAbility(new SimpleStaticAbility(effect)); this.addAbility(new SimpleStaticAbility(effect));
// Whenever a source you control deals noncombat damage to an opponent, you draw that many cards. // Whenever a source you control deals noncombat damage to an opponent, you draw that many cards.
this.addAbility(new NivMizzetVisionaryAbility()); this.addAbility(new SourceDealsNoncombatDamageToOpponentTriggeredAbility(new DrawCardSourceControllerEffect(SavedDamageValue.MANY, true)));
} }
private NivMizzetVisionary(final NivMizzetVisionary card) { private NivMizzetVisionary(final NivMizzetVisionary card) {
@ -52,41 +52,3 @@ public final class NivMizzetVisionary extends CardImpl {
return new NivMizzetVisionary(this); return new NivMizzetVisionary(this);
} }
} }
class NivMizzetVisionaryAbility extends TriggeredAbilityImpl {
NivMizzetVisionaryAbility() {
super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(SavedDamageValue.MANY));
}
private NivMizzetVisionaryAbility(final NivMizzetVisionaryAbility ability) {
super(ability);
}
@Override
public NivMizzetVisionaryAbility copy() {
return new NivMizzetVisionaryAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event;
if (damageEvent.isCombatDamage()
|| !game.getOpponents(controllerId).contains(event.getTargetId())
|| !Objects.equals(controllerId, game.getControllerId(event.getSourceId()))) {
return false;
}
getAllEffects().setValue("damage", event.getAmount());
return true;
}
@Override
public String getRule() {
return "Whenever a source you control deals noncombat damage to an opponent, you draw that many cards.";
}
}

View file

@ -1,16 +1,14 @@
package mage.cards.v; package mage.cards.v;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SourceDealsNoncombatDamageToOpponentTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect; import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect;
import mage.cards.AdventureCard; import mage.cards.AdventureCard;
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.Zone; import mage.constants.SetTargetPointer;
import mage.game.Game;
import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.target.common.TargetAnyTarget; import mage.target.common.TargetAnyTarget;
import java.util.UUID; import java.util.UUID;
@ -24,7 +22,10 @@ public final class VirtueOfCourage extends AdventureCard {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, new CardType[]{CardType.INSTANT}, "{3}{R}{R}", "Embereth Blaze", "{1}{R}"); super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, new CardType[]{CardType.INSTANT}, "{3}{R}{R}", "Embereth Blaze", "{1}{R}");
// Whenever a source you control deals noncombat damage to an opponent, you may exile that many cards from the top of your library. You may play those cards this turn. // Whenever a source you control deals noncombat damage to an opponent, you may exile that many cards from the top of your library. You may play those cards this turn.
this.addAbility(new VirtueOfCourageTriggeredAbility()); this.addAbility(new SourceDealsNoncombatDamageToOpponentTriggeredAbility(
new ExileTopXMayPlayUntilEffect(SavedDamageValue.MANY, false, Duration.EndOfTurn)
.setText("you may exile that many cards from the top of your library. You may play those cards this turn.")
, true, SetTargetPointer.NONE));
// Embereth Blaze // Embereth Blaze
// Embereth Blaze deals 2 damage to any target. // Embereth Blaze deals 2 damage to any target.
@ -43,44 +44,3 @@ public final class VirtueOfCourage extends AdventureCard {
return new VirtueOfCourage(this); return new VirtueOfCourage(this);
} }
} }
class VirtueOfCourageTriggeredAbility extends TriggeredAbilityImpl {
VirtueOfCourageTriggeredAbility() {
super(Zone.BATTLEFIELD, null, true);
}
private VirtueOfCourageTriggeredAbility(final VirtueOfCourageTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
DamagedPlayerEvent dEvent = (DamagedPlayerEvent) event;
if (dEvent.isCombatDamage()
|| !game.getOpponents(getControllerId()).contains(event.getTargetId())
|| !game.getControllerId(event.getSourceId()).equals(getControllerId())) {
return false;
}
this.getEffects().clear();
this.addEffect(new ExileTopXMayPlayUntilEffect(event.getAmount(), Duration.EndOfTurn));
return true;
}
@Override
public VirtueOfCourageTriggeredAbility copy() {
return new VirtueOfCourageTriggeredAbility(this);
}
@Override
public String getRule() {
return "whenever a source you control deals noncombat damage to an opponent, "
+ "you may exile that many cards from the top of your library. "
+ "You may play those cards this turn.";
}
}

View file

@ -0,0 +1,41 @@
package org.mage.test.cards.single.otc;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class BladegriffPrototypeTest extends CardTestPlayerBase {
private static final String griff = "Bladegriff Prototype";
@Test
public void test_CanTargetOwn() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerB, "Squire");
addCard(Zone.BATTLEFIELD, playerA, griff);
attack(1, playerA, griff);
addTarget(playerB, "Squire");
setStopAt(1, PhaseStep.END_COMBAT);
execute();
assertGraveyardCount(playerB, "Squire", 1);
}
@Test(expected=AssertionError.class)
public void test_CantTargetYours() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerB, "Squire");
addCard(Zone.BATTLEFIELD, playerA, griff);
attack(1, playerA, griff);
addTarget(playerB, griff);
setStopAt(1, PhaseStep.END_COMBAT);
execute();
}
}

View file

@ -85,7 +85,7 @@ public class VerifyCardDataTest {
private static final Logger logger = Logger.getLogger(VerifyCardDataTest.class); private static final Logger logger = Logger.getLogger(VerifyCardDataTest.class);
private static String FULL_ABILITIES_CHECK_SET_CODES = "BLC"; // check ability text due mtgjson, can use multiple sets like MAT;CMD or * for all private static String FULL_ABILITIES_CHECK_SET_CODES = "*"; // check ability text due mtgjson, can use multiple sets like MAT;CMD or * for all
private static boolean CHECK_ONLY_ABILITIES_TEXT = false; // use when checking text locally, suppresses unnecessary checks and output messages private static boolean CHECK_ONLY_ABILITIES_TEXT = false; // use when checking text locally, suppresses unnecessary checks and output messages
private static final boolean CHECK_COPYABLE_FIELDS = true; // disable for better verify test performance private static final boolean CHECK_COPYABLE_FIELDS = true; // disable for better verify test performance

View file

@ -0,0 +1,66 @@
package mage.abilities.common;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.constants.SetTargetPointer;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
/**
* @author notgreat
*/
public class SourceDealsNoncombatDamageToOpponentTriggeredAbility extends TriggeredAbilityImpl {
SetTargetPointer setTargetPointer;
public SourceDealsNoncombatDamageToOpponentTriggeredAbility(Effect effect) {
this(effect, SetTargetPointer.NONE);
}
public SourceDealsNoncombatDamageToOpponentTriggeredAbility(Effect effect, SetTargetPointer setTargetPointer) {
this(effect, false, setTargetPointer);
}
public SourceDealsNoncombatDamageToOpponentTriggeredAbility(Effect effect, boolean optional, SetTargetPointer setTargetPointer) {
super(Zone.BATTLEFIELD, effect, optional);
this.setTargetPointer = setTargetPointer;
setTriggerPhrase("Whenever a source you control deals noncombat damage to an opponent, ");
}
protected SourceDealsNoncombatDamageToOpponentTriggeredAbility(final SourceDealsNoncombatDamageToOpponentTriggeredAbility ability) {
super(ability);
setTargetPointer = ability.setTargetPointer;
}
@Override
public SourceDealsNoncombatDamageToOpponentTriggeredAbility copy() {
return new SourceDealsNoncombatDamageToOpponentTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Player opponent = game.getPlayer(event.getTargetId());
DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event;
if (opponent == null || !game.isOpponent(opponent, getControllerId())
|| !isControlledBy(game.getControllerId(event.getSourceId()))
|| damageEvent.isCombatDamage()) {
return false;
}
int damageAmount = event.getAmount();
if (damageAmount < 1) {
return false;
}
this.getEffects().setValue("damage", damageAmount);
if (setTargetPointer == SetTargetPointer.PLAYER) {
getEffects().setTargetPointer(new FixedTarget(event.getSourceId()));
}
return true;
}
}

View file

@ -10,7 +10,8 @@ import mage.game.Game;
*/ */
public enum SavedDamageValue implements DynamicValue { public enum SavedDamageValue implements DynamicValue {
MANY("many"), MANY("many"),
MUCH("much"); MUCH("much"),
AMOUNT("amount of");
private final String message; private final String message;

View file

@ -0,0 +1,18 @@
package mage.target.targetadjustment;
import mage.abilities.Ability;
import mage.game.Game;
/**
* Use this to indicate that the targets are dynamically added via the Ability directly
* While still satisfying the Verify target check
*
* @author notgreat
*/
public enum DefineByTriggerTargetAdjuster implements TargetAdjuster{
instance;
@Override
public void adjustTargets(Ability ability, Game game){
//Do nothing
}
}