forked from External/mage
Ready for review: Implement Craft mechanic (#11352)
* [LCI] Implement Spring-Loaded Sawblades / Bladewheel Chariot * [LCI] Implement Sunbird Standard / Sunbird Effigy * card filter needs to have an owner predicate * [LCI] Implement Throne of the Grim Captain / The Grim Captain * make default constructor for craft with artifact * dedupe some code * refactor constructors for simplicity * add currently failing test
This commit is contained in:
parent
0f7db0c69d
commit
bc4aa6931f
16 changed files with 884 additions and 8 deletions
60
Mage.Sets/src/mage/cards/b/BladewheelChariot.java
Normal file
60
Mage.Sets/src/mage/cards/b/BladewheelChariot.java
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.TapTargetCost;
|
||||
import mage.abilities.effects.common.continuous.AddCardTypeSourceEffect;
|
||||
import mage.abilities.keyword.CrewAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.common.FilterControlledArtifactPermanent;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
import mage.filter.predicate.permanent.TappedPredicate;
|
||||
import mage.target.common.TargetControlledPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class BladewheelChariot extends CardImpl {
|
||||
|
||||
private static final FilterControlledPermanent filter
|
||||
= new FilterControlledArtifactPermanent("other untapped artifacts you control");
|
||||
|
||||
static {
|
||||
filter.add(AnotherPredicate.instance);
|
||||
filter.add(TappedPredicate.UNTAPPED);
|
||||
}
|
||||
|
||||
public BladewheelChariot(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "");
|
||||
|
||||
this.subtype.add(SubType.VEHICLE);
|
||||
this.power = new MageInt(5);
|
||||
this.toughness = new MageInt(5);
|
||||
this.nightCard = true;
|
||||
this.color.setWhite(true);
|
||||
|
||||
// Tap two other untapped artifacts you control: Bladewheel Chariot becomes an artifact creature until end of turn.
|
||||
this.addAbility(new SimpleActivatedAbility(new AddCardTypeSourceEffect(
|
||||
Duration.EndOfTurn, CardType.ARTIFACT, CardType.CREATURE
|
||||
), new TapTargetCost(new TargetControlledPermanent(2, filter))));
|
||||
|
||||
// Crew 1
|
||||
this.addAbility(new CrewAbility(1));
|
||||
}
|
||||
|
||||
private BladewheelChariot(final BladewheelChariot card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BladewheelChariot copy() {
|
||||
return new BladewheelChariot(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ public final class FelidarGuardian extends CardImpl {
|
|||
|
||||
// When Felidar Guardian enters the battlefield, you may exile another target permanent you control, then return that card to the battlefield under its owner's control.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileThenReturnTargetEffect(false, true), true);
|
||||
ability.addTarget(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_PERMANENT));
|
||||
ability.addTarget(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_TARGET_PERMANENT));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ public final class KelpieGuide extends CardImpl {
|
|||
|
||||
// {T}: Untap another target permanent you control.
|
||||
Ability ability = new SimpleActivatedAbility(new UntapTargetEffect(), new TapSourceCost());
|
||||
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_PERMANENT));
|
||||
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_TARGET_PERMANENT));
|
||||
this.addAbility(ability);
|
||||
|
||||
// {T}: Tap target permanent. Activate only if you control eight or more lands.
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public final class OathOfTeferi extends CardImpl {
|
|||
|
||||
// When Oath of Teferi enters the battlefield, exile another target permanent you control. Return it to the battlefield under its owner's control at the beginning of the next end step.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileReturnBattlefieldNextEndStepTargetEffect().withTextThatCard(false));
|
||||
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_PERMANENT));
|
||||
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_TARGET_PERMANENT));
|
||||
this.addAbility(ability);
|
||||
|
||||
// You may activate the loyalty abilities of planeswalkers you control twice each turn rather than only once.
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ class SkySwallowerEffect extends OneShotEffect {
|
|||
return false;
|
||||
}
|
||||
return new GainControlAllEffect(Duration.Custom,
|
||||
StaticFilters.FILTER_CONTROLLED_ANOTHER_PERMANENT,
|
||||
StaticFilters.FILTER_CONTROLLED_ANOTHER_TARGET_PERMANENT,
|
||||
opponent.getId()
|
||||
).apply(game, source);
|
||||
}
|
||||
|
|
|
|||
54
Mage.Sets/src/mage/cards/s/SpringLoadedSawblades.java
Normal file
54
Mage.Sets/src/mage/cards/s/SpringLoadedSawblades.java
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.keyword.CraftAbility;
|
||||
import mage.abilities.keyword.FlashAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterOpponentsCreaturePermanent;
|
||||
import mage.filter.predicate.permanent.TappedPredicate;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class SpringLoadedSawblades extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter
|
||||
= new FilterOpponentsCreaturePermanent("tapped creature an opponent controls");
|
||||
|
||||
static {
|
||||
filter.add(TappedPredicate.TAPPED);
|
||||
}
|
||||
|
||||
public SpringLoadedSawblades(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{W}");
|
||||
this.secondSideCardClazz = mage.cards.b.BladewheelChariot.class;
|
||||
|
||||
// Flash
|
||||
this.addAbility(FlashAbility.getInstance());
|
||||
|
||||
// When Spring-Loaded Sawblades enters the battlefield, it deals 5 damage to target tapped creature an opponent controls.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(5, "it"));
|
||||
ability.addTarget(new TargetPermanent(filter));
|
||||
this.addAbility(ability);
|
||||
|
||||
// Craft with artifact {3}{W}
|
||||
this.addAbility(new CraftAbility("{3}{W}"));
|
||||
}
|
||||
|
||||
private SpringLoadedSawblades(final SpringLoadedSawblades card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpringLoadedSawblades copy() {
|
||||
return new SpringLoadedSawblades(this);
|
||||
}
|
||||
}
|
||||
192
Mage.Sets/src/mage/cards/s/SunbirdEffigy.java
Normal file
192
Mage.Sets/src/mage/cards/s/SunbirdEffigy.java
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.Mana;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.continuous.SetBasePowerToughnessSourceEffect;
|
||||
import mage.abilities.effects.mana.ManaEffect;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
import mage.abilities.mana.SimpleManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.ExileZone;
|
||||
import mage.game.Game;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class SunbirdEffigy extends CardImpl {
|
||||
|
||||
public SunbirdEffigy(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "");
|
||||
|
||||
this.subtype.add(SubType.BIRD);
|
||||
this.subtype.add(SubType.CONSTRUCT);
|
||||
this.power = new MageInt(0);
|
||||
this.toughness = new MageInt(0);
|
||||
this.nightCard = true;
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Vigilance
|
||||
this.addAbility(VigilanceAbility.getInstance());
|
||||
|
||||
// Haste
|
||||
this.addAbility(HasteAbility.getInstance());
|
||||
|
||||
// Sunbird Effigy's power and toughness are each equal to the number of colors among the exiled cards used to craft it.
|
||||
this.addAbility(new SimpleStaticAbility(
|
||||
Zone.ALL, new SetBasePowerToughnessSourceEffect(SunbirdEffigyValue.instance)
|
||||
).addHint(SunbirdEffigyHint.instance));
|
||||
|
||||
// {T}: For each color among the exiled cards used to craft Sunbird Effigy, add one mana of that color.
|
||||
this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new SunbirdEffigyEffect(), new TapSourceCost()));
|
||||
}
|
||||
|
||||
private SunbirdEffigy(final SunbirdEffigy card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SunbirdEffigy copy() {
|
||||
return new SunbirdEffigy(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum SunbirdEffigyValue implements DynamicValue {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
return Optional
|
||||
.ofNullable(getColor(game, sourceAbility))
|
||||
.filter(Objects::nonNull)
|
||||
.map(ObjectColor::getColorCount)
|
||||
.orElse(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SunbirdEffigyValue copy() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "colors among the exiled cards used to craft it";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "1";
|
||||
}
|
||||
|
||||
static ObjectColor getColor(Game game, Ability source) {
|
||||
ExileZone exileZone = game
|
||||
.getExile()
|
||||
.getExileZone(CardUtil.getExileZoneId(
|
||||
game,
|
||||
source.getSourceId(),
|
||||
game.getState().getZoneChangeCounter(source.getSourceId()) - 2
|
||||
));
|
||||
return exileZone == null ? null : exileZone
|
||||
.getCards(game)
|
||||
.stream()
|
||||
.map(card -> card.getColor(game))
|
||||
.reduce(new ObjectColor(), (c1, c2) -> c1.union(c2));
|
||||
}
|
||||
}
|
||||
|
||||
enum SunbirdEffigyHint implements Hint {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public String getText(Game game, Ability ability) {
|
||||
ObjectColor color = SunbirdEffigyValue.getColor(game, ability);
|
||||
if (color == null) {
|
||||
return null;
|
||||
}
|
||||
if (color.isColorless()) {
|
||||
return "No colors among exiled cards.";
|
||||
}
|
||||
return color
|
||||
.getColors()
|
||||
.stream()
|
||||
.map(ObjectColor::getDescription)
|
||||
.collect(Collectors.joining(", ", "Colors among exiled cards: ", ""));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hint copy() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
class SunbirdEffigyEffect extends ManaEffect {
|
||||
|
||||
public SunbirdEffigyEffect() {
|
||||
super();
|
||||
staticText = "for each color among the exiled cards used to craft {this}, add one mana of that color";
|
||||
}
|
||||
|
||||
private SunbirdEffigyEffect(final SunbirdEffigyEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SunbirdEffigyEffect copy() {
|
||||
return new SunbirdEffigyEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mana produceMana(Game game, Ability source) {
|
||||
Mana mana = new Mana();
|
||||
if (game == null) {
|
||||
return mana;
|
||||
}
|
||||
ExileZone exileZone = game
|
||||
.getExile()
|
||||
.getExileZone(CardUtil.getExileZoneId(game, source, -2));
|
||||
if (exileZone == null) {
|
||||
return mana;
|
||||
}
|
||||
ObjectColor color = exileZone
|
||||
.getCards(game)
|
||||
.stream()
|
||||
.map(card -> card.getColor(game))
|
||||
.reduce(new ObjectColor(), (c1, c2) -> c1.union(c2));
|
||||
if (color.isWhite()) {
|
||||
mana.increaseWhite();
|
||||
}
|
||||
if (color.isBlue()) {
|
||||
mana.increaseBlue();
|
||||
}
|
||||
if (color.isBlack()) {
|
||||
mana.increaseBlack();
|
||||
}
|
||||
if (color.isRed()) {
|
||||
mana.increaseRed();
|
||||
}
|
||||
if (color.isGreen()) {
|
||||
mana.increaseGreen();
|
||||
}
|
||||
return mana;
|
||||
}
|
||||
}
|
||||
38
Mage.Sets/src/mage/cards/s/SunbirdStandard.java
Normal file
38
Mage.Sets/src/mage/cards/s/SunbirdStandard.java
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.abilities.keyword.CraftAbility;
|
||||
import mage.abilities.mana.AnyColorManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class SunbirdStandard extends CardImpl {
|
||||
|
||||
public SunbirdStandard(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
|
||||
this.secondSideCardClazz = mage.cards.s.SunbirdEffigy.class;
|
||||
|
||||
// {T}: Add one mana of any color.
|
||||
this.addAbility(new AnyColorManaAbility());
|
||||
|
||||
// Craft with one or more {5}
|
||||
this.addAbility(new CraftAbility(
|
||||
"{5}", "one or more", "other permanents " +
|
||||
"you control and/or cards in your graveyard", 1, Integer.MAX_VALUE
|
||||
));
|
||||
}
|
||||
|
||||
private SunbirdStandard(final SunbirdStandard card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SunbirdStandard copy() {
|
||||
return new SunbirdStandard(this);
|
||||
}
|
||||
}
|
||||
112
Mage.Sets/src/mage/cards/t/TheGrimCaptain.java
Normal file
112
Mage.Sets/src/mage/cards/t/TheGrimCaptain.java
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
package mage.cards.t;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.SacrificeOpponentsEffect;
|
||||
import mage.abilities.keyword.HexproofAbility;
|
||||
import mage.abilities.keyword.LifelinkAbility;
|
||||
import mage.abilities.keyword.MenaceAbility;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class TheGrimCaptain extends CardImpl {
|
||||
|
||||
public TheGrimCaptain(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.SKELETON);
|
||||
this.subtype.add(SubType.SPIRIT);
|
||||
this.subtype.add(SubType.PIRATE);
|
||||
this.power = new MageInt(7);
|
||||
this.toughness = new MageInt(7);
|
||||
this.nightCard = true;
|
||||
this.color.setBlack(true);
|
||||
|
||||
// Menace
|
||||
this.addAbility(new MenaceAbility());
|
||||
|
||||
// Trample
|
||||
this.addAbility(TrampleAbility.getInstance());
|
||||
|
||||
// Lifelink
|
||||
this.addAbility(LifelinkAbility.getInstance());
|
||||
|
||||
// Hexproof
|
||||
this.addAbility(HexproofAbility.getInstance());
|
||||
|
||||
// Whenever The Grim Captain attacks, each opponent sacrifices a nonland permanent. Then you may put an exiled creature card used to craft The Grim Captain onto the battlefield under your control tapped and attacking.
|
||||
Ability ability = new AttacksTriggeredAbility(new SacrificeOpponentsEffect(StaticFilters.FILTER_PERMANENT_NON_LAND));
|
||||
ability.addEffect(new TheGrimCaptainEffect());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private TheGrimCaptain(final TheGrimCaptain card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TheGrimCaptain copy() {
|
||||
return new TheGrimCaptain(this);
|
||||
}
|
||||
}
|
||||
|
||||
class TheGrimCaptainEffect extends OneShotEffect {
|
||||
|
||||
TheGrimCaptainEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "Then you may put an exiled creature card used to craft {this} " +
|
||||
"onto the battlefield under your control tapped and attacking";
|
||||
}
|
||||
|
||||
private TheGrimCaptainEffect(final TheGrimCaptainEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TheGrimCaptainEffect copy() {
|
||||
return new TheGrimCaptainEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
TargetCard target = new TargetCardInExile(
|
||||
0, 1, StaticFilters.FILTER_CARD_CREATURE,
|
||||
CardUtil.getExileZoneId(game, source, -2)
|
||||
);
|
||||
target.withNotTarget(true);
|
||||
player.choose(outcome, target, source, game);
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card == null) {
|
||||
return false;
|
||||
}
|
||||
player.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null);
|
||||
Permanent permanent = game.getPermanent(card.getId());
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
game.getCombat().addAttackingCreature(card.getId(), game);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
111
Mage.Sets/src/mage/cards/t/ThroneOfTheGrimCaptain.java
Normal file
111
Mage.Sets/src/mage/cards/t/ThroneOfTheGrimCaptain.java
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
package mage.cards.t;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.dynamicvalue.common.SubTypeAssignment;
|
||||
import mage.abilities.effects.common.MillCardsControllerEffect;
|
||||
import mage.abilities.keyword.CraftAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.TargetController;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetCardInGraveyardBattlefieldOrStack;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class ThroneOfTheGrimCaptain extends CardImpl {
|
||||
|
||||
public ThroneOfTheGrimCaptain(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.secondSideCardClazz = mage.cards.t.TheGrimCaptain.class;
|
||||
|
||||
// {T}: Mill two cards.
|
||||
this.addAbility(new SimpleActivatedAbility(new MillCardsControllerEffect(2), new TapSourceCost()));
|
||||
|
||||
// Craft with a Dinosaur, a Merfolk, a Pirate, and a Vampire {4}
|
||||
this.addAbility(new CraftAbility("{4}", "a Dinosaur, a Merfolk, a Pirate, and a Vampire", new ThroneOfTheGrimCaptainTarget()));
|
||||
}
|
||||
|
||||
private ThroneOfTheGrimCaptain(final ThroneOfTheGrimCaptain card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThroneOfTheGrimCaptain copy() {
|
||||
return new ThroneOfTheGrimCaptain(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ThroneOfTheGrimCaptainTarget extends TargetCardInGraveyardBattlefieldOrStack {
|
||||
|
||||
private static final FilterCard filterCard =
|
||||
new FilterCard("a Dinosaur, a Merfolk, a Pirate, or Vampire card");
|
||||
private static final FilterPermanent filterPermanent =
|
||||
new FilterControlledPermanent("another Dinosaur, a Merfolk, a Pirate, or Vampire you control");
|
||||
private static final Predicate<MageObject> predicate = Predicates.or(
|
||||
SubType.PIRATE.getPredicate(),
|
||||
SubType.VAMPIRE.getPredicate(),
|
||||
SubType.DINOSAUR.getPredicate(),
|
||||
SubType.MERFOLK.getPredicate()
|
||||
);
|
||||
|
||||
static {
|
||||
filterCard.add(predicate);
|
||||
filterCard.add(TargetController.YOU.getOwnerPredicate());
|
||||
filterPermanent.add(predicate);
|
||||
filterPermanent.add(AnotherPredicate.instance);
|
||||
}
|
||||
|
||||
private static final SubTypeAssignment subtypeAssigner = new SubTypeAssignment(
|
||||
SubType.PIRATE, SubType.VAMPIRE, SubType.DINOSAUR, SubType.MERFOLK
|
||||
);
|
||||
|
||||
ThroneOfTheGrimCaptainTarget() {
|
||||
super(4, 4, filterCard, filterPermanent);
|
||||
}
|
||||
|
||||
private ThroneOfTheGrimCaptainTarget(final ThroneOfTheGrimCaptainTarget target) {
|
||||
super(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThroneOfTheGrimCaptainTarget copy() {
|
||||
return new ThroneOfTheGrimCaptainTarget(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) {
|
||||
if (!super.canTarget(playerId, id, source, game)) {
|
||||
return false;
|
||||
}
|
||||
Set<Card> cards = this.getTargets().stream().map(uuid -> {
|
||||
Permanent permanent = game.getPermanent(uuid);
|
||||
if (permanent != null) {
|
||||
return permanent;
|
||||
}
|
||||
return game.getCard(uuid);
|
||||
}).filter(Objects::nonNull).collect(Collectors.toSet());
|
||||
return subtypeAssigner.getRoleCount(cards, game) <= 4;
|
||||
}
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@ public final class TheLostCavernsOfIxalan extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Abuelo, Ancestral Echo", 219, Rarity.RARE, mage.cards.a.AbueloAncestralEcho.class));
|
||||
cards.add(new SetCardInfo("Amalia Benavides Aguirre", 221, Rarity.RARE, mage.cards.a.AmaliaBenavidesAguirre.class));
|
||||
cards.add(new SetCardInfo("Bartolome del Presidio", 224, Rarity.UNCOMMON, mage.cards.b.BartolomeDelPresidio.class));
|
||||
cards.add(new SetCardInfo("Bladewheel Chariot", 36, Rarity.UNCOMMON, mage.cards.b.BladewheelChariot.class));
|
||||
cards.add(new SetCardInfo("Breeches, Eager Pillager", 137, Rarity.RARE, mage.cards.b.BreechesEagerPillager.class));
|
||||
cards.add(new SetCardInfo("Captain Storm, Plunderer of Cosmium", 227, Rarity.UNCOMMON, mage.cards.c.CaptainStormPlundererOfCosmium.class));
|
||||
cards.add(new SetCardInfo("Careening Mine Cart", 247, Rarity.UNCOMMON, mage.cards.c.CareeningMineCart.class));
|
||||
|
|
@ -73,14 +74,19 @@ public final class TheLostCavernsOfIxalan extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Sanguine Evangelist", 34, Rarity.RARE, mage.cards.s.SanguineEvangelist.class));
|
||||
cards.add(new SetCardInfo("Skullcap Snail", 119, Rarity.COMMON, mage.cards.s.SkullcapSnail.class));
|
||||
cards.add(new SetCardInfo("Song of Stupefaction", 77, Rarity.COMMON, mage.cards.s.SongOfStupefaction.class));
|
||||
cards.add(new SetCardInfo("Spring-Loaded Sawblades", 36, Rarity.UNCOMMON, mage.cards.s.SpringLoadedSawblades.class));
|
||||
cards.add(new SetCardInfo("Spyglass Siren", 78, Rarity.UNCOMMON, mage.cards.s.SpyglassSiren.class));
|
||||
cards.add(new SetCardInfo("Sunbird Effigy", 262, Rarity.UNCOMMON, mage.cards.s.SunbirdEffigy.class));
|
||||
cards.add(new SetCardInfo("Sunbird Standard", 262, Rarity.UNCOMMON, mage.cards.s.SunbirdStandard.class));
|
||||
cards.add(new SetCardInfo("Swamp", 397, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Temple of Civilization", 26, Rarity.MYTHIC, mage.cards.t.TempleOfCivilization.class));
|
||||
cards.add(new SetCardInfo("Temple of Power", 158, Rarity.MYTHIC, mage.cards.t.TempleOfPower.class));
|
||||
cards.add(new SetCardInfo("The Grim Captain", 266, Rarity.RARE, mage.cards.t.TheGrimCaptain.class));
|
||||
cards.add(new SetCardInfo("The Belligerent", 225, Rarity.RARE, mage.cards.t.TheBelligerent.class));
|
||||
cards.add(new SetCardInfo("The Skullspore Nexus", 212, Rarity.MYTHIC, mage.cards.t.TheSkullsporeNexus.class));
|
||||
cards.add(new SetCardInfo("Thrashing Brontodon", 216, Rarity.UNCOMMON, mage.cards.t.ThrashingBrontodon.class));
|
||||
cards.add(new SetCardInfo("Threefold Thunderhulk", 265, Rarity.RARE, mage.cards.t.ThreefoldThunderhulk.class));
|
||||
cards.add(new SetCardInfo("Throne of the Grim Captain", 266, Rarity.RARE, mage.cards.t.ThroneOfTheGrimCaptain.class));
|
||||
cards.add(new SetCardInfo("Treasure Cove", 267, Rarity.RARE, mage.cards.t.TreasureCove.class));
|
||||
cards.add(new SetCardInfo("Treasure Map", 267, Rarity.RARE, mage.cards.t.TreasureMap.class));
|
||||
cards.add(new SetCardInfo("Vito, Fanatic of Aclazotz", 243, Rarity.MYTHIC, mage.cards.v.VitoFanaticOfAclazotz.class));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,112 @@
|
|||
package org.mage.test.cards.abilities.keywords;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class CraftTest extends CardTestPlayerBase {
|
||||
|
||||
private static final String sawblades = "Spring-Loaded Sawblades";
|
||||
private static final String chariot = "Bladewheel Chariot";
|
||||
private static final String relic = "Darksteel Relic";
|
||||
|
||||
@Test
|
||||
public void testExilePermanent() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
||||
addCard(Zone.BATTLEFIELD, playerA, sawblades);
|
||||
addCard(Zone.BATTLEFIELD, playerA, relic);
|
||||
|
||||
addTarget(playerA, relic);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Craft");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, sawblades, 0);
|
||||
assertPermanentCount(playerA, chariot, 1);
|
||||
assertPermanentCount(playerA, relic, 0);
|
||||
assertExileCount(playerA, relic, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExileCard() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
||||
addCard(Zone.BATTLEFIELD, playerA, sawblades);
|
||||
addCard(Zone.GRAVEYARD, playerA, relic);
|
||||
|
||||
addTarget(playerA, relic);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Craft");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, sawblades, 0);
|
||||
assertPermanentCount(playerA, chariot, 1);
|
||||
assertGraveyardCount(playerA, relic, 0);
|
||||
assertExileCount(playerA, relic, 1);
|
||||
}
|
||||
|
||||
private static final String standard = "Sunbird Standard";
|
||||
private static final String effigy = "Sunbird Effigy";
|
||||
private static final String thoctar = "Woolly Thoctar";
|
||||
private static final String watchwolf = "Watchwolf";
|
||||
private static final String yearling = "Cerodon Yearling";
|
||||
|
||||
@Test
|
||||
public void testEffigy() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, standard);
|
||||
addCard(Zone.BATTLEFIELD, playerA, thoctar);
|
||||
addCard(Zone.HAND, playerA, thoctar);
|
||||
|
||||
addTarget(playerA, thoctar);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Craft");
|
||||
|
||||
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: For each");
|
||||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, thoctar);
|
||||
|
||||
setStopAt(3, PhaseStep.END_TURN);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, standard, 0);
|
||||
assertPermanentCount(playerA, thoctar, 1);
|
||||
assertPowerToughness(playerA, effigy, 3, 3);
|
||||
}
|
||||
|
||||
@Ignore // test fails due to issue with test player target handling
|
||||
@Test
|
||||
public void testEffigyMultiple() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, standard);
|
||||
addCard(Zone.BATTLEFIELD, playerA, yearling);
|
||||
addCard(Zone.GRAVEYARD, playerA, watchwolf);
|
||||
addCard(Zone.HAND, playerA, thoctar);
|
||||
|
||||
addTarget(playerA, yearling);
|
||||
addTarget(playerA, watchwolf);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Craft");
|
||||
|
||||
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: For each");
|
||||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, thoctar);
|
||||
|
||||
setStopAt(3, PhaseStep.END_TURN);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, standard, 0);
|
||||
assertPermanentCount(playerA, thoctar, 1);
|
||||
assertPowerToughness(playerA, effigy, 3, 3);
|
||||
}
|
||||
}
|
||||
|
|
@ -56,8 +56,12 @@ public abstract class RoleAssignment<T> implements Serializable {
|
|||
}
|
||||
|
||||
public int getRoleCount(Cards cards, Game game) {
|
||||
return getRoleCount(cards.getCards(game), game);
|
||||
}
|
||||
|
||||
public int getRoleCount(Set<? extends Card> cards, Game game) {
|
||||
Map<UUID, Set<T>> attributeMap = new HashMap<>();
|
||||
cards.getCards(game).forEach(card -> attributeMap.put(card.getId(), this.makeSet(card, game)));
|
||||
cards.forEach(card -> attributeMap.put(card.getId(), this.makeSet(card, game)));
|
||||
if (attributeMap.size() < 2) {
|
||||
return attributeMap.size();
|
||||
}
|
||||
|
|
|
|||
176
Mage/src/main/java/mage/abilities/keyword/CraftAbility.java
Normal file
176
Mage/src/main/java/mage/abilities/keyword/CraftAbility.java
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
package mage.abilities.keyword;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbilityImpl;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.CostImpl;
|
||||
import mage.abilities.costs.common.ExileSourceCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterArtifactCard;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.common.FilterOwnedCard;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInGraveyardBattlefieldOrStack;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class CraftAbility extends ActivatedAbilityImpl {
|
||||
|
||||
private static final FilterCard artifactFilter = new FilterArtifactCard("artifact");
|
||||
|
||||
static {
|
||||
artifactFilter.add(TargetController.YOU.getOwnerPredicate());
|
||||
}
|
||||
|
||||
private final String description;
|
||||
private final String manaString;
|
||||
|
||||
public CraftAbility(String manaString) {
|
||||
this(manaString, "artifact", "another artifact you control or an artifact card from your graveyard", CardType.ARTIFACT.getPredicate());
|
||||
}
|
||||
|
||||
public CraftAbility(String manaString, String description, String targetDescription, Predicate<MageObject>... predicates) {
|
||||
this(manaString, description, targetDescription, 1, 1, predicates);
|
||||
}
|
||||
|
||||
public CraftAbility(String manaString, String description, String targetDescription, int minTargets, int maxTargets, Predicate<MageObject>... predicates) {
|
||||
this(manaString, description, makeTarget(minTargets, maxTargets, targetDescription, predicates));
|
||||
}
|
||||
|
||||
public CraftAbility(String manaString, String description, TargetCardInGraveyardBattlefieldOrStack target) {
|
||||
super(Zone.BATTLEFIELD, new CraftEffect(), new ManaCostsImpl<>(manaString));
|
||||
this.addCost(new ExileSourceCost());
|
||||
this.addCost(new CraftCost(target));
|
||||
this.addSubAbility(new TransformAbility());
|
||||
this.timing = TimingRule.SORCERY;
|
||||
this.manaString = manaString;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
private CraftAbility(final CraftAbility ability) {
|
||||
super(ability);
|
||||
this.manaString = ability.manaString;
|
||||
this.description = ability.description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CraftAbility copy() {
|
||||
return new CraftAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Craft with " + description + ' ' + manaString;
|
||||
}
|
||||
|
||||
private static TargetCardInGraveyardBattlefieldOrStack makeTarget(int minTargets, int maxTargets, String targetDescription, Predicate<MageObject>... predicates) {
|
||||
FilterPermanent filterPermanent = new FilterControlledPermanent();
|
||||
filterPermanent.add(AnotherPredicate.instance);
|
||||
FilterCard filterCard = new FilterOwnedCard();
|
||||
for (Predicate<MageObject> predicate : predicates) {
|
||||
filterPermanent.add(predicate);
|
||||
filterCard.add(predicate);
|
||||
}
|
||||
return new TargetCardInGraveyardBattlefieldOrStack(minTargets, maxTargets, filterCard, filterPermanent, targetDescription);
|
||||
}
|
||||
}
|
||||
|
||||
class CraftCost extends CostImpl {
|
||||
|
||||
private final TargetCardInGraveyardBattlefieldOrStack target;
|
||||
|
||||
CraftCost(TargetCardInGraveyardBattlefieldOrStack target) {
|
||||
super();
|
||||
this.target = target;
|
||||
target.withNotTarget(true);
|
||||
}
|
||||
|
||||
private CraftCost(final CraftCost cost) {
|
||||
super(cost);
|
||||
this.target = cost.target.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CraftCost copy() {
|
||||
return new CraftCost(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||
return target.canChoose(controllerId, source, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
paid = false;
|
||||
return paid;
|
||||
}
|
||||
player.chooseTarget(Outcome.Exile, target, source, game);
|
||||
Set<Card> cards = target
|
||||
.getTargets()
|
||||
.stream()
|
||||
.map(uuid -> {
|
||||
Permanent permanent = game.getPermanent(uuid);
|
||||
if (permanent != null) {
|
||||
return permanent;
|
||||
}
|
||||
return game.getCard(uuid);
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
player.moveCardsToExile(
|
||||
cards, source, game, true,
|
||||
CardUtil.getExileZoneId(game, source),
|
||||
CardUtil.getSourceName(game, source)
|
||||
);
|
||||
paid = true;
|
||||
return paid;
|
||||
}
|
||||
}
|
||||
|
||||
class CraftEffect extends OneShotEffect {
|
||||
|
||||
CraftEffect() {
|
||||
super(Outcome.Benefit);
|
||||
}
|
||||
|
||||
private CraftEffect(final CraftEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CraftEffect copy() {
|
||||
return new CraftEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
if (player == null || card == null || card.getZoneChangeCounter(game) != source.getSourceObjectZoneChangeCounter() + 1) {
|
||||
return false;
|
||||
}
|
||||
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
|
||||
player.moveCards(card, Zone.BATTLEFIELD, source, game);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -375,13 +375,20 @@ public final class StaticFilters {
|
|||
FILTER_CONTROLLED_A_PERMANENT.setLockedFilter(true);
|
||||
}
|
||||
|
||||
public static final FilterControlledPermanent FILTER_CONTROLLED_ANOTHER_PERMANENT = new FilterControlledPermanent("another target permanent you control");
|
||||
public static final FilterControlledPermanent FILTER_CONTROLLED_ANOTHER_PERMANENT = new FilterControlledPermanent("another permanent you control");
|
||||
|
||||
static {
|
||||
FILTER_CONTROLLED_ANOTHER_PERMANENT.add(AnotherPredicate.instance);
|
||||
FILTER_CONTROLLED_ANOTHER_PERMANENT.setLockedFilter(true);
|
||||
}
|
||||
|
||||
public static final FilterControlledPermanent FILTER_CONTROLLED_ANOTHER_TARGET_PERMANENT = new FilterControlledPermanent("another target permanent you control");
|
||||
|
||||
static {
|
||||
FILTER_CONTROLLED_ANOTHER_TARGET_PERMANENT.add(AnotherPredicate.instance);
|
||||
FILTER_CONTROLLED_ANOTHER_TARGET_PERMANENT.setLockedFilter(true);
|
||||
}
|
||||
|
||||
public static final FilterControlledPermanent FILTER_CONTROLLED_PERMANENTS = new FilterControlledPermanent("permanents you control");
|
||||
|
||||
static {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,11 @@ public class TargetCardInGraveyardBattlefieldOrStack extends TargetCard {
|
|||
protected final FilterSpell filterSpell;
|
||||
|
||||
public TargetCardInGraveyardBattlefieldOrStack(int minNumTargets, int maxNumTargets, FilterCard filterGraveyard, FilterPermanent filterBattlefield) {
|
||||
this(minNumTargets, maxNumTargets, filterGraveyard, filterBattlefield, defaultSpellFilter, null);
|
||||
this(minNumTargets, maxNumTargets, filterGraveyard, filterBattlefield, null);
|
||||
}
|
||||
|
||||
public TargetCardInGraveyardBattlefieldOrStack(int minNumTargets, int maxNumTargets, FilterCard filterGraveyard, FilterPermanent filterBattlefield, String targetName) {
|
||||
this(minNumTargets, maxNumTargets, filterGraveyard, filterBattlefield, defaultSpellFilter, targetName);
|
||||
}
|
||||
|
||||
public TargetCardInGraveyardBattlefieldOrStack(int minNumTargets, int maxNumTargets, FilterCard filterGraveyard, FilterPermanent filterBattlefield, FilterSpell filterSpell, String targetName) {
|
||||
|
|
@ -40,7 +44,7 @@ public class TargetCardInGraveyardBattlefieldOrStack extends TargetCard {
|
|||
this.filterPermanent = filterBattlefield;
|
||||
this.filterSpell = filterSpell;
|
||||
this.targetName = targetName != null ? targetName : filter.getMessage()
|
||||
+ " in a graveyard "
|
||||
+ " in a graveyard"
|
||||
+ (maxNumTargets > 1 ? " and/or " : " or ")
|
||||
+ this.filterPermanent.getMessage()
|
||||
+ " on the battlefield";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue