Merge branch 'master' into omniscience-fix

This commit is contained in:
Oleg Agafonov 2020-11-01 10:14:50 +01:00 committed by GitHub
commit b3cc1f49a7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
389 changed files with 9467 additions and 5524 deletions

View file

@ -204,15 +204,32 @@ public class TestCardRenderDialog extends MageDialog {
game.addPlayer(playerOpponent, deck);
List<CardView> cardViews = new ArrayList<>();
///*
/* // test morphed
cardViews.add(createPermanentCard(game, playerYou.getId(), "RNA", "263", 0, 0, 0, false)); // mountain
cardViews.add(createPermanentCard(game, playerYou.getId(), "RNA", "185", 0, 0, 0, true)); // Judith, the Scourge Diva
//*/
cardViews.add(createHandCard(game, playerYou.getId(), "DIS", "153")); // Odds // Ends (split card)
cardViews.add(createHandCard(game, playerYou.getId(), "ELD", "38")); // Animating Faerie (adventure card)
cardViews.add(createFaceDownCard(game, playerOpponent.getId(), "ELD", "38", false, false, false)); // face down
cardViews.add(createFaceDownCard(game, playerOpponent.getId(), "ELD", "38", true, false, true)); // morphed
cardViews.add(createFaceDownCard(game, playerOpponent.getId(), "ELD", "38", false, true, false)); // manifested
//*/
/* //test emblems
cardViews.add(createPermanentCard(game, playerYou.getId(), "RNA", "78", 125, 89, 0, false)); // Noxious Groodion
cardViews.add(createPermanentCard(game, playerYou.getId(), "RNA", "14", 3, 5, 2, false)); // Knight of Sorrows
cardViews.add(createPermanentCard(game, playerYou.getId(), "DKA", "140", 5, 2, 2, false)); // Huntmaster of the Fells, transforms
cardViews.add(createPermanentCard(game, playerYou.getId(), "RNA", "221", 0, 0, 0, false)); // Bedeck // Bedazzle
cardViews.add(createPermanentCard(game, playerYou.getId(), "XLN", "234", 0, 0, 0, false)); // Conqueror's Galleon
cardViews.add(createEmblem(new AjaniAdversaryOfTyrantsEmblem())); // Emblem Ajani
cardViews.add(createPlane(new AkoumPlane())); // Plane - Akoum
//*/
//* //test split, transform and mdf in hands
cardViews.add(createHandCard(game, playerYou.getId(), "SOI", "97")); // Accursed Witch
cardViews.add(createHandCard(game, playerYou.getId(), "UMA", "225")); // Fire // Ice
cardViews.add(createHandCard(game, playerYou.getId(), "ELD", "14")); // Giant Killer
cardViews.add(createHandCard(game, playerYou.getId(), "ZNR", "134")); // Akoum Warrior
//*/
// duplicate cards
if (checkBoxGenerateManyCards.isSelected()) {
@ -226,17 +243,6 @@ public class TestCardRenderDialog extends MageDialog {
}
}
/*
cardViews.add(createPermanentCard(game, playerYou.getId(), "RNA", "78", 125, 89, 0, false)); // Noxious Groodion
cardViews.add(createPermanentCard(game, playerYou.getId(), "RNA", "14", 3, 5, 2, false)); // Knight of Sorrows
cardViews.add(createPermanentCard(game, playerYou.getId(), "DKA", "140", 5, 2, 2, false)); // Huntmaster of the Fells, transforms
cardViews.add(createPermanentCard(game, playerYou.getId(), "RNA", "221", 0, 0, 0, false)); // Bedeck // Bedazzle
cardViews.add(createPermanentCard(game, playerYou.getId(), "XLN", "234", 0, 0, 0, false)); // Conqueror's Galleon
cardViews.add(createEmblem(new AjaniAdversaryOfTyrantsEmblem())); // Emblem Ajani
cardViews.add(createPlane(new AkoumPlane())); // Plane - Akoum
//*/
BigCard big = new BigCard();
CardsView view = new CardsView(cardViews);
cardsPanel.loadCards(view, big, game.getId());

View file

@ -579,7 +579,10 @@ public class MageActionCallback implements ActionCallback {
break;
case ALTERNATE:
if (cardView.getAlternateName() != null) {
if (cardView instanceof PermanentView && !cardView.isFlipCard() && !cardView.canTransform() && ((PermanentView) cardView).isCopy()) {
if (cardView instanceof PermanentView
&& !cardView.isFlipCard()
&& !cardView.canTransform()
&& ((PermanentView) cardView).isCopy()) {
image = ImageCache.getImageOriginal(((PermanentView) cardView).getOriginal());
} else {
image = ImageCache.getImageOriginalAlternateName(cardView);

View file

@ -819,9 +819,12 @@ public abstract class CardPanel extends MagePermanent implements MouseListener,
this.setTemporary(null);
}
}
// switch card names for render
String temp = this.getGameCard().getAlternateName();
this.getGameCard().setAlternateName(this.getGameCard().getOriginalName());
this.getGameCard().setOriginalName(temp);
updateArtImage();
}

View file

@ -86,9 +86,9 @@ public enum ScryfallImageSource implements CardImageSource {
}
}
// double faced card
// double faced cards (modal double faces cards too)
// the front face can be downloaded normally
// the back face is prepared beforehand
// the back face is prepared before hand
if (baseUrl == null && card.isTwoFacedCard() && !card.isSecondSide()) {
baseUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet(), isToken) + "/"
+ card.getCollectorId() + "/" + localizedCode + "?format=image";

View file

@ -449,12 +449,30 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
if (card.getFlipCardName() == null || card.getFlipCardName().trim().isEmpty()) {
throw new IllegalStateException("Flipped card can't have empty name.");
}
CardDownloadData cardDownloadData = new CardDownloadData(card.getFlipCardName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", "", false, card.isDoubleFaced(), card.isNightCard());
CardDownloadData cardDownloadData = new CardDownloadData(
card.getFlipCardName(),
card.getSetCode(),
card.getCardNumber(),
card.usesVariousArt(),
0, "", "", false, card.isDoubleFaced(), card.isNightCard());
cardDownloadData.setFlipCard(true);
cardDownloadData.setFlippedSide(true);
cardDownloadData.setType2(isType2);
allCardsUrls.add(cardDownloadData);
}
if (card.isModalDoubleFacesCard()) {
if (card.getModalDoubleFacesSecondSideName() == null || card.getModalDoubleFacesSecondSideName().trim().isEmpty()) {
throw new IllegalStateException("MDF card can't have empty name.");
}
CardDownloadData cardDownloadData = new CardDownloadData(
card.getModalDoubleFacesSecondSideName(),
card.getSetCode(),
card.getCardNumber(),
card.usesVariousArt(),
0, "", "", false, true, true);
cardDownloadData.setType2(isType2);
allCardsUrls.add(cardDownloadData);
}
} else if (card.getCardNumber().isEmpty() || "0".equals(card.getCardNumber())) {
logger.error("Card has no collector ID and won't be sent to client: " + card.getName());
} else if (card.getSetCode().isEmpty()) {

View file

@ -1,8 +1,6 @@
package mage.view;
import com.google.gson.annotations.Expose;
import java.util.*;
import java.util.stream.Collectors;
import mage.MageObject;
import mage.ObjectColor;
import mage.abilities.Abilities;
@ -31,6 +29,9 @@ import mage.target.Targets;
import mage.util.CardUtil;
import mage.util.SubTypeList;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author BetaSteward_at_googlemail.com
*/
@ -75,7 +76,7 @@ public class CardView extends SimpleCardView {
protected CardView ability;
protected int type;
protected boolean transformable;
protected boolean transformable; // can toggle one card side to another (transformable cards, modal double faces)
protected CardView secondCardFace;
protected boolean transformed;
@ -95,6 +96,8 @@ public class CardView extends SimpleCardView {
protected List<String> rightSplitRules;
protected String rightSplitTypeLine;
protected boolean isModalDoubleFacesCard;
protected ArtRect artRect = ArtRect.NORMAL;
protected List<UUID> targets;
@ -187,6 +190,8 @@ public class CardView extends SimpleCardView {
this.rightSplitRules = cardView.rightSplitRules == null ? null : new ArrayList<>(cardView.rightSplitRules);
this.rightSplitTypeLine = cardView.rightSplitTypeLine;
this.isModalDoubleFacesCard = cardView.isModalDoubleFacesCard;
this.artRect = cardView.artRect;
this.targets = cardView.targets == null ? null : new ArrayList<>(cardView.targets);
this.pairedCard = cardView.pairedCard;
@ -299,7 +304,7 @@ public class CardView extends SimpleCardView {
}
SplitCard splitCard = null;
if (card.isSplitCard()) {
if (card instanceof SplitCard) {
splitCard = (SplitCard) card;
rotate = (card.getSpellAbility().getSpellAbilityType()) != SpellAbilityType.SPLIT_AFTERMATH;
} else if (card instanceof Spell) {
@ -316,6 +321,10 @@ public class CardView extends SimpleCardView {
case SPLIT_RIGHT:
rotate = true;
break;
case MODAL_LEFT:
case MODAL_RIGHT:
rotate = false;
break;
}
}
@ -334,6 +343,12 @@ public class CardView extends SimpleCardView {
fullCardName = card.getName(); // split card contains full name as normal
this.manaCostLeft = splitCard.getLeftHalfCard().getManaCost().getSymbols();
this.manaCostRight = splitCard.getRightHalfCard().getManaCost().getSymbols();
} else if (card instanceof ModalDoubleFacesCard) {
this.isModalDoubleFacesCard = true;
ModalDoubleFacesCard mainCard = ((ModalDoubleFacesCard) card);
fullCardName = mainCard.getLeftHalfCard().getName() + MockCard.MODAL_DOUBLE_FACES_NAME_SEPARATOR + mainCard.getRightHalfCard().getName();
this.manaCostLeft = mainCard.getLeftHalfCard().getManaCost().getSymbols();
this.manaCostRight = mainCard.getRightHalfCard().getManaCost().getSymbols();
} else if (card instanceof AdventureCard) {
AdventureCard adventureCard = ((AdventureCard) card);
AdventureCardSpell adventureCardSpell = ((AdventureCardSpell) adventureCard.getSpellCard());
@ -402,7 +417,6 @@ public class CardView extends SimpleCardView {
this.subTypes = card.getSubtype(game);
this.superTypes = card.getSuperType();
this.color = card.getColor(game);
this.transformable = card.isTransformable();
this.flipCard = card.isFlipCard();
this.faceDown = !showFaceUp;
@ -421,7 +435,7 @@ public class CardView extends SimpleCardView {
this.tokenDescriptor = card.getTokenDescriptor();
}
//
// set code und card number for token copies to get the image
// set code and card number for token copies to get the image
this.rules = card.getRules(game);
this.type = ((PermanentToken) card).getToken().getTokenType();
} else {
@ -429,18 +443,30 @@ public class CardView extends SimpleCardView {
this.isToken = false;
}
// transformable, double faces cards
this.transformable = card.isTransformable();
Card secondSideCard = card.getSecondCardFace();
if (secondSideCard != null) {
this.secondCardFace = new CardView(secondSideCard);
this.alternateName = secondCardFace.getName();
this.originalName = card.getName();
}
this.flipCard = card.isFlipCard();
if (card.isFlipCard() && card.getFlipCardName() != null) {
this.alternateName = card.getFlipCardName();
this.originalName = card.getName();
}
if (card instanceof ModalDoubleFacesCard) {
this.transformable = true; // enable GUI day/night button
ModalDoubleFacesCard mdfCard = (ModalDoubleFacesCard) card;
this.secondCardFace = new CardView(mdfCard.getRightHalfCard());
this.alternateName = mdfCard.getRightHalfCard().getName();
this.originalName = card.getName();
}
if (card instanceof Spell) {
this.mageObjectType = MageObjectType.SPELL;
Spell spell = (Spell) card;
@ -455,6 +481,7 @@ public class CardView extends SimpleCardView {
// Determine what part of the art to slice out for spells on the stack which originate
// from a split, fuse, or aftermath split card.
// Modal double faces cards draws as normal cards
SpellAbilityType ty = spell.getSpellAbility().getSpellAbilityType();
if (ty == SpellAbilityType.SPLIT_RIGHT || ty == SpellAbilityType.SPLIT_LEFT || ty == SpellAbilityType.SPLIT_FUSED) {
// Needs a special art rect
@ -871,7 +898,7 @@ public class CardView extends SimpleCardView {
}
/**
* Name of the other side (transform), flipped, or copying card name.
* Name of the other side (transform), flipped, modal double faces card or copying card name.
*
* @return name
*/

View file

@ -1,9 +1,6 @@
package mage.deck;
import mage.cards.Card;
import mage.cards.ExpansionSet;
import mage.cards.Sets;
import mage.cards.SplitCard;
import mage.cards.*;
import mage.cards.decks.Constructed;
import mage.cards.decks.Deck;
import mage.cards.decks.DeckValidatorErrorType;
@ -199,21 +196,27 @@ public class TinyLeaders extends Constructed {
return false;
}
//905.5b - Converted mana cost must be 3 or less
// 906.5b
// Each card must have a converted mana cost of three or less. Cards with {x} in their mana cost count X
// as zero for this purpose. Split cards are legal only if both of their halves would be legal independently.
List<Integer> costs = new ArrayList<>();
if (card instanceof SplitCard) {
if (((SplitCard) card).getLeftHalfCard().getManaCost().convertedManaCost() > 3) {
addError(DeckValidatorErrorType.OTHER, card.getName(), "Invalid cost (" + ((SplitCard) card).getLeftHalfCard().getManaCost().convertedManaCost() + ')', true);
return false;
}
if (((SplitCard) card).getRightHalfCard().getManaCost().convertedManaCost() > 3) {
addError(DeckValidatorErrorType.OTHER, card.getName(), "Invalid cost (" + ((SplitCard) card).getRightHalfCard().getManaCost().convertedManaCost() + ')', true);
return false;
}
} else if (card.getManaCost().convertedManaCost() > 3) {
addError(DeckValidatorErrorType.OTHER, card.getName(), "Invalid cost (" + card.getManaCost().convertedManaCost() + ')', true);
return false;
costs.add(((SplitCard) card).getLeftHalfCard().getManaCost().convertedManaCost());
costs.add(((SplitCard) card).getRightHalfCard().getManaCost().convertedManaCost());
} else if (card instanceof ModalDoubleFacesCard) {
costs.add(((ModalDoubleFacesCard) card).getLeftHalfCard().getManaCost().convertedManaCost());
costs.add(((ModalDoubleFacesCard) card).getRightHalfCard().getManaCost().convertedManaCost());
} else {
costs.add(card.getManaCost().convertedManaCost());
}
return true;
return costs.stream().allMatch(cost -> {
if (cost > 3) {
addError(DeckValidatorErrorType.OTHER, card.getName(), "Invalid cost (" + cost + ')', true);
return false;
}
return true;
});
}
/**

View file

@ -1,42 +0,0 @@
package mage.cards.a;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.effects.common.TapSourceUnlessPaysEffect;
import mage.abilities.mana.BlackManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AgadeemTheUndercrypt extends CardImpl {
public AgadeemTheUndercrypt(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
this.modalDFC = true;
this.nightCard = true;
// As Agadeem, the Undercrypt enters the battlefield, you may pay 3 life. If you don't, it enters the battlefield tapped.
this.addAbility(new AsEntersBattlefieldAbility(
new TapSourceUnlessPaysEffect(new PayLifeCost(3)),
"you may pay 3 life. If you don't, it enters the battlefield tapped"
));
// {T}: Add {B}.
this.addAbility(new BlackManaAbility());
}
private AgadeemTheUndercrypt(final AgadeemTheUndercrypt card) {
super(card);
}
@Override
public AgadeemTheUndercrypt copy() {
return new AgadeemTheUndercrypt(this);
}
}

View file

@ -2,11 +2,16 @@ package mage.cards.a;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.abilities.effects.common.TapSourceUnlessPaysEffect;
import mage.abilities.mana.BlackManaAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.ModalDoubleFacesCard;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreatureCard;
import mage.game.Game;
@ -18,22 +23,39 @@ import java.util.UUID;
import java.util.stream.Collectors;
/**
* @author TheElk801
* @author JayDi85
*/
public final class AgadeemsAwakening extends CardImpl {
public final class AgadeemsAwakening extends ModalDoubleFacesCard {
public AgadeemsAwakening(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}{B}{B}");
super(ownerId, setInfo,
new CardType[]{CardType.SORCERY}, new SubType[]{}, "{X}{B}{B}{B}",
"Agadeem, the Undercrypt", new CardType[]{CardType.LAND}, new SubType[]{}, ""
);
this.modalDFC = true;
this.secondSideCardClazz = mage.cards.a.AgadeemTheUndercrypt.class;
// 1.
// Agadeem's Awakening
// Sorcery
// Return from your graveyard to the battlefield any number of target creature cards that each have a different converted mana cost X or less.
this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect().setText(
this.getLeftHalfCard().getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect().setText(
"return from your graveyard to the battlefield any number of target creature cards " +
"that each have a different converted mana cost X or less"
));
this.getSpellAbility().setTargetAdjuster(AgadeemsAwakeningAdjuster.instance);
this.getLeftHalfCard().getSpellAbility().setTargetAdjuster(AgadeemsAwakeningAdjuster.instance);
// 2.
// Agadeem, the Undercrypt
// Land
// As Agadeem, the Undercrypt enters the battlefield, you may pay 3 life. If you don't, it enters the battlefield tapped.
this.getRightHalfCard().addAbility(new AsEntersBattlefieldAbility(
new TapSourceUnlessPaysEffect(new PayLifeCost(3)),
"you may pay 3 life. If you don't, it enters the battlefield tapped"
));
// {T}: Add {B}.
this.getRightHalfCard().addAbility(new BlackManaAbility());
}
private AgadeemsAwakening(final AgadeemsAwakening card) {

View file

@ -1,28 +1,22 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BlocksSourceTriggeredAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.LoseAbilitySourceEffect;
import mage.constants.SubType;
import mage.abilities.keyword.DefenderAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class AgelessSentinels extends CardImpl {
@ -43,7 +37,7 @@ public final class AgelessSentinels extends CardImpl {
// When Ageless Sentinels blocks, it becomes a Bird Giant, and it loses defender.
Ability ability = new BlocksSourceTriggeredAbility(new AgelessSentinelsEffect(), false, false, true);
Effect effect = new LoseAbilitySourceEffect(DefenderAbility.getInstance(), Duration.WhileOnBattlefield);
effect.setText("and it loses defender");
effect.setText(", and it loses defender");
ability.addEffect(effect);
this.addAbility(ability);
}
@ -60,8 +54,8 @@ public final class AgelessSentinels extends CardImpl {
private class AgelessSentinelsEffect extends ContinuousEffectImpl {
public AgelessSentinelsEffect() {
super(Duration.WhileOnBattlefield, Outcome.BecomeCreature);
staticText = "it becomes a Bird Giant,";
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature);
staticText = "it becomes a Bird Giant";
}
public AgelessSentinelsEffect(final AgelessSentinelsEffect effect) {
@ -74,27 +68,16 @@ public final class AgelessSentinels extends CardImpl {
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent == null) {
return false;
}
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
permanent.getSubtype(game).clear();
permanent.getSubtype(game).add(SubType.BIRD, SubType.GIANT);
}
break;
}
permanent.removeAllCreatureTypes(game);
permanent.addSubType(game, SubType.BIRD, SubType.GIANT);
return true;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.TypeChangingEffects_4;

View file

@ -1,37 +0,0 @@
package mage.cards.a;
import mage.abilities.common.EntersBattlefieldTappedAbility;
import mage.abilities.mana.RedManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AkoumTeeth extends CardImpl {
public AkoumTeeth(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
this.modalDFC = true;
this.nightCard = true;
// Akoum Teeth enters the battlefield tapped.
this.addAbility(new EntersBattlefieldTappedAbility());
// {T}: Add {R}.
this.addAbility(new RedManaAbility());
}
private AkoumTeeth(final AkoumTeeth card) {
super(card);
}
@Override
public AkoumTeeth copy() {
return new AkoumTeeth(this);
}
}

View file

@ -1,32 +1,44 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTappedAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.abilities.mana.RedManaAbility;
import mage.cards.CardSetInfo;
import mage.cards.ModalDoubleFacesCard;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
* @author JayDi85
*/
public final class AkoumWarrior extends CardImpl {
public final class AkoumWarrior extends ModalDoubleFacesCard {
public AkoumWarrior(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}");
super(ownerId, setInfo,
new CardType[]{CardType.CREATURE}, new SubType[]{SubType.MINOTAUR, SubType.WARRIOR}, "{5}{R}",
"Akoum Teeth", new CardType[]{CardType.LAND}, new SubType[]{}, ""
);
this.subtype.add(SubType.MINOTAUR);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(4);
this.toughness = new MageInt(5);
this.modalDFC = true;
this.secondSideCardClazz = mage.cards.a.AkoumTeeth.class;
// 1.
// Akoum Warrior
// Creature Minotaur Warrior
this.getLeftHalfCard().setPT(new MageInt(4), new MageInt(5));
// Trample
this.addAbility(TrampleAbility.getInstance());
this.getLeftHalfCard().addAbility(TrampleAbility.getInstance());
// 2.
// Akoum Teeth
// Land
// Akoum Teeth enters the battlefield tapped.
this.getRightHalfCard().addAbility(new EntersBattlefieldTappedAbility());
// {T}: Add {R}.
this.getRightHalfCard().addAbility(new RedManaAbility());
}
private AkoumWarrior(final AkoumWarrior card) {

View file

@ -61,7 +61,7 @@ class AlphaStatusDynamicValue implements DynamicValue {
if (enchanted != null) {
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, game)) {
if (!permanent.getId().equals(enchanted.getId())) {
if (enchanted.shareSubtypes(permanent, game)) {
if (enchanted.shareCreatureTypes(permanent, game)) {
xValue += 2;
}
}

View file

@ -0,0 +1,99 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AmarethTheLustrous extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("another permanent");
static {
filter.add(AnotherPredicate.instance);
}
public AmarethTheLustrous(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{U}{W}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.DRAGON);
this.power = new MageInt(6);
this.toughness = new MageInt(6);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Whenever another permanent enters the battlefield under your control, look at the top card of your library. If it shares a card type with that permanent, you may reveal that card and put it into your hand.
this.addAbility(new EntersBattlefieldControlledTriggeredAbility(new AmarethTheLustrousEffect(), filter));
}
private AmarethTheLustrous(final AmarethTheLustrous card) {
super(card);
}
@Override
public AmarethTheLustrous copy() {
return new AmarethTheLustrous(this);
}
}
class AmarethTheLustrousEffect extends OneShotEffect {
AmarethTheLustrousEffect() {
super(Outcome.Benefit);
staticText = "look at the top card of your library. If it shares a card type with that permanent, " +
"you may reveal that card and put it into your hand";
}
private AmarethTheLustrousEffect(final AmarethTheLustrousEffect effect) {
super(effect);
}
@Override
public AmarethTheLustrousEffect copy() {
return new AmarethTheLustrousEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Card card = player.getLibrary().getFromTop(game);
if (card == null) {
return false;
}
player.lookAtCards("Top card of library", card, game);
Object obj = getValue("permanentEnteringBattlefield");
Permanent permanent = null;
if (obj instanceof Permanent) {
permanent = (Permanent) obj;
}
if (permanent == null
|| card.getCardType().stream().noneMatch(permanent.getCardType()::contains)
|| !player.chooseUse(Outcome.DrawCard, "Reveal " + card.getName() + " and put it into your hand?", source, game)) {
return false;
}
player.revealCards(source, new CardsImpl(card), game);
player.moveCards(card, Zone.HAND, source, game);
return true;
}
}

View file

@ -7,6 +7,7 @@ import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.effects.common.continuous.GainAllCreatureTypesTargetEffect;
import mage.abilities.effects.common.continuous.LoseAllCreatureTypesTargetEffect;
import mage.abilities.keyword.ChangelingAbility;
import mage.cards.CardImpl;
@ -27,13 +28,13 @@ public final class AmoeboidChangeling extends CardImpl {
this.toughness = new MageInt(1);
// Changeling
this.setIsAllCreatureTypes(true);
this.addAbility(ChangelingAbility.getInstance());
// {tap}: Target creature gains all creature types until end of turn.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
new GainAbilityTargetEffect(ChangelingAbility.getInstance(), Duration.EndOfTurn, null, false, Layer.TypeChangingEffects_4, SubLayer.NA), new TapSourceCost());
Ability ability = new SimpleActivatedAbility(
new GainAllCreatureTypesTargetEffect(Duration.EndOfTurn), new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
// {tap}: Target creature loses all creature types until end of turn.

View file

@ -3,12 +3,10 @@ package mage.cards.a;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.BoostEquippedEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.keyword.ChangelingAbility;
import mage.abilities.effects.common.continuous.GainAllCreatureTypesAttachedEffect;
import mage.abilities.keyword.EquipAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.SubType;
@ -26,9 +24,7 @@ public final class AmorphousAxe extends CardImpl {
// Equipped creature gets +3/+0 and is every creature type.
Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(3, 0));
ability.addEffect(new GainAbilityAttachedEffect(
ChangelingAbility.getInstance(), AttachmentType.EQUIPMENT
).setText("and is every creature type"));
ability.addEffect(new GainAllCreatureTypesAttachedEffect());
this.addAbility(ability);
// Equip {3}

View file

@ -0,0 +1,95 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.EncoreAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.SalamnderWarriorToken;
import mage.players.Player;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AmphinMutineer extends CardImpl {
private static final FilterPermanent filter = new FilterCreaturePermanent("non-Salamander creature");
static {
filter.add(Predicates.not(SubType.SALAMANDER.getPredicate()));
}
public AmphinMutineer(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");
this.subtype.add(SubType.SALAMANDER);
this.subtype.add(SubType.PIRATE);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// When Amphin Mutineer enters the battlefield, exile up to one target non-Salamander creature. That creature's controller creates a 4/3 blue Salamander Warrior creature token.
Ability ability = new EntersBattlefieldTriggeredAbility(new AmphinMutineerEffect());
ability.addTarget(new TargetPermanent(0, 1, filter, false));
this.addAbility(ability);
// Encore {4}{U}{U}
this.addAbility(new EncoreAbility(new ManaCostsImpl<>("{4}{U}{U}")));
}
private AmphinMutineer(final AmphinMutineer card) {
super(card);
}
@Override
public AmphinMutineer copy() {
return new AmphinMutineer(this);
}
}
class AmphinMutineerEffect extends OneShotEffect {
AmphinMutineerEffect() {
super(Outcome.Benefit);
staticText = "exile up to one target non-Salamander creature. " +
"That creature's controller creates a 4/3 blue Salamander Warrior creature token";
}
private AmphinMutineerEffect(final AmphinMutineerEffect effect) {
super(effect);
}
@Override
public AmphinMutineerEffect copy() {
return new AmphinMutineerEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent == null) {
return false;
}
Player player = game.getPlayer(permanent.getControllerId());
if (player == null) {
return false;
}
player.moveCards(permanent, Zone.EXILED, source, game);
new SalamnderWarriorToken().putOntoBattlefield(1, game, source.getSourceId(), player.getId());
return true;
}
}

View file

@ -0,0 +1,46 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.keyword.CascadeAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class ApexDevastator extends CardImpl {
public ApexDevastator(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{8}{G}{G}");
this.subtype.add(SubType.HYDRA);
this.subtype.add(SubType.CHIMERA);
this.power = new MageInt(10);
this.toughness = new MageInt(10);
// Cascade
this.addAbility(new CascadeAbility(false));
// Cascade
this.addAbility(new CascadeAbility(false));
// Cascade
this.addAbility(new CascadeAbility(false));
// Cascade
this.addAbility(new CascadeAbility());
}
private ApexDevastator(final ApexDevastator card) {
super(card);
}
@Override
public ApexDevastator copy() {
return new ApexDevastator(this);
}
}

View file

@ -116,8 +116,8 @@ class ConspyEffect extends ContinuousEffectImpl {
List<Permanent> creatures = game.getBattlefield().getAllActivePermanents(
new FilterControlledCreaturePermanent(), source.getControllerId(), game);
for (Permanent creature : creatures) {
if (creature != null && !creature.hasSubtype(subType, game)) {
creature.getSubtype(game).add(subType);
if (creature != null) {
creature.addSubType(game, subType);
}
}
return true;

View file

@ -0,0 +1,91 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.BecomesMonarchSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.game.Game;
import mage.game.events.GameEvent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class ArchonOfCoronation extends CardImpl {
public ArchonOfCoronation(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{W}");
this.subtype.add(SubType.ARCHON);
this.power = new MageInt(5);
this.toughness = new MageInt(5);
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Archon of Coronation enters the battlefield, you become the monarch.
this.addAbility(new EntersBattlefieldTriggeredAbility(new BecomesMonarchSourceEffect()));
// As long as you're the monarch, damage doesn't cause you to lose life.
this.addAbility(new SimpleStaticAbility(new ArchonOfCoronationEffect()));
}
private ArchonOfCoronation(final ArchonOfCoronation card) {
super(card);
}
@Override
public ArchonOfCoronation copy() {
return new ArchonOfCoronation(this);
}
}
class ArchonOfCoronationEffect extends ReplacementEffectImpl {
ArchonOfCoronationEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit);
staticText = "As long as you're the monarch, damage doesn't cause you to lose life. " +
"<i>(When a creature deals combat damage to you, its controller still becomes the monarch.)</i>";
}
private ArchonOfCoronationEffect(final ArchonOfCoronationEffect effect) {
super(effect);
}
@Override
public ArchonOfCoronationEffect copy() {
return new ArchonOfCoronationEffect(this);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGE_CAUSES_LIFE_LOSS;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return source.isControlledBy(event.getPlayerId())
&& source.isControlledBy(game.getMonarchId());
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
event.setAmount(0);
return false;
}
}

View file

@ -1,42 +1,37 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.EntersBattlefieldTappedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.SourceHasCounterCondition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.TapSourceEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.effects.common.counter.RemoveCounterSourceEffect;
import mage.abilities.mana.SimpleManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Layer;
import static mage.constants.Layer.TypeChangingEffects_4;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.constants.*;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.UUID;
/**
*
* @author spjspj
*/
public final class ArixmethesSlumberingIsle extends CardImpl {
private static final Condition condition
= new SourceHasCounterCondition(CounterType.SLUMBER, 1, Integer.MAX_VALUE);
public ArixmethesSlumberingIsle(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{U}");
@ -46,15 +41,18 @@ public final class ArixmethesSlumberingIsle extends CardImpl {
this.toughness = new MageInt(12);
// Arixmethes, Slumbering Isle enters the battlefield tapped with five slumber counters on it.
this.addAbility(new EntersBattlefieldTappedAbility());
Effect effect = new AddCountersSourceEffect(CounterType.SLUMBER.createInstance(5));
this.addAbility(new EntersBattlefieldAbility(effect, "with five slumber counters"));
Ability ability = new EntersBattlefieldAbility(
new TapSourceEffect(true), false, null,
"{this} enters the battlefield tapped with five slumber counters on it", null
);
ability.addEffect(new AddCountersSourceEffect(CounterType.SLUMBER.createInstance(5)));
this.addAbility(ability);
// As long as Arixmethes, Slumbering Isle has a slumber counter on it, it's a land.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(
new ArixmethesIsLandEffect(),
new SourceHasCounterCondition(CounterType.SLUMBER, 1, Integer.MAX_VALUE),
"As long as {this} has a slumber counter on it, it's a land")));
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
new ArixmethesIsLandEffect(), condition,
"As long as {this} has a slumber counter on it, it's a land"
)));
// Whenever you cast a spell, you may remove a slumber counter from Arixmethes.
this.addAbility(new SpellCastControllerTriggeredAbility(new RemoveCounterSourceEffect(CounterType.SLUMBER.createInstance(1)), true));
@ -75,44 +73,28 @@ public final class ArixmethesSlumberingIsle extends CardImpl {
class ArixmethesIsLandEffect extends ContinuousEffectImpl {
public ArixmethesIsLandEffect() {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
this.staticText = "As long as {this} has a slumber counter on it, it's a land";
ArixmethesIsLandEffect() {
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment);
}
public ArixmethesIsLandEffect(final ArixmethesIsLandEffect effect) {
private ArixmethesIsLandEffect(final ArixmethesIsLandEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public ArixmethesIsLandEffect copy() {
return new ArixmethesIsLandEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
switch (layer) {
case TypeChangingEffects_4:
permanent.getCardType().clear();
permanent.addCardType(CardType.LAND);
permanent.getSubtype(game).clear();
break;
}
return true;
if (permanent == null) {
return false;
}
return false;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.TypeChangingEffects_4;
permanent.getCardType().clear();
permanent.addCardType(CardType.LAND);
permanent.removeAllSubTypes(game);
return true;
}
}

View file

@ -0,0 +1,92 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.costs.common.DiscardCardCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DoWhenCostPaid;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.keyword.PartnerAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class ArmixFiligreeThrasher extends CardImpl {
public ArmixFiligreeThrasher(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}{B}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.GOLEM);
this.power = new MageInt(3);
this.toughness = new MageInt(2);
// Whenever Armix, Filigree Thrasher attacks, you may discard a card. When you do, target creature defending player controls gets -X/-X until end of turn, where X is the number of artifacts you control plus the number of artifact cards in your graveyard.
ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
new BoostTargetEffect(
ArmixFiligreeThrasherValue.instance,
ArmixFiligreeThrasherValue.instance,
Duration.EndOfTurn, true
), false, "target creature defending player controls gets -X/-X until end of turn, " +
"where X is the number of artifacts you control plus the number of artifact cards in your graveyard"
);
this.addAbility(new AttacksTriggeredAbility(new DoWhenCostPaid(
ability, new DiscardCardCost(), "Discard a card?"
), false));
// Partner
this.addAbility(PartnerAbility.getInstance());
}
private ArmixFiligreeThrasher(final ArmixFiligreeThrasher card) {
super(card);
}
@Override
public ArmixFiligreeThrasher copy() {
return new ArmixFiligreeThrasher(this);
}
}
enum ArmixFiligreeThrasherValue implements DynamicValue {
instance;
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
Player player = game.getPlayer(sourceAbility.getControllerId());
if (player == null) {
return 0;
}
return -(player.getGraveyard().count(
StaticFilters.FILTER_CARD_ARTIFACT, player.getId(), game
) + game.getBattlefield().count(
StaticFilters.FILTER_PERMANENT_ARTIFACT,
sourceAbility.getSourceId(),
sourceAbility.getControllerId(), game
));
}
@Override
public ArmixFiligreeThrasherValue copy() {
return instance;
}
@Override
public String getMessage() {
return "";
}
}

View file

@ -90,7 +90,7 @@ class AshayaSoulOfTheWildEffect extends ContinuousEffectImpl {
permanent.addCardType(CardType.LAND);
}
if (!permanent.hasSubtype(SubType.FOREST, game)) {
permanent.getSubtype(game).add(SubType.FOREST);
permanent.addSubType(game, SubType.FOREST);
if (!permanent.getAbilities(game).containsClass(GreenManaAbility.class)) {
permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game);
}

View file

@ -1,7 +1,6 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
@ -24,8 +23,9 @@ import mage.target.common.TargetOpponent;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class AshiokNightmareWeaver extends CardImpl {
@ -149,7 +149,7 @@ class AshiokNightmareWeaverPutIntoPlayEffect extends OneShotEffect {
class AshiokNightmareWeaverAddTypeEffect extends ContinuousEffectImpl {
public AshiokNightmareWeaverAddTypeEffect() {
super(Duration.Custom, Outcome.Neutral);
super(Duration.Custom, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral);
staticText = "That creature is a Nightmare in addition to its other types";
}
@ -162,34 +162,16 @@ class AshiokNightmareWeaverAddTypeEffect extends ContinuousEffectImpl {
return new AshiokNightmareWeaverAddTypeEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Permanent creature = game.getPermanent(this.getTargetPointer().getFirst(game, source));
if (creature != null) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
creature.getSubtype(game).add(SubType.NIGHTMARE);
}
break;
}
return true;
} else {
this.used = true;
}
return false;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
Permanent creature = game.getPermanent(this.getTargetPointer().getFirst(game, source));
if (creature == null) {
this.used = true;
return false;
}
creature.addSubType(game, SubType.NIGHTMARE);
return true;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.TypeChangingEffects_4;
}
}
class AshiokNightmareWeaverExileAllEffect extends OneShotEffect {

View file

@ -1,6 +1,5 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -12,7 +11,6 @@ import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.filter.FilterCard;
@ -23,9 +21,11 @@ import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetCardInHand;
import mage.target.common.TargetCardInLibrary;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class AssemblyHall extends CardImpl {
@ -84,7 +84,7 @@ class AssemblyHallEffect extends OneShotEffect {
return false;
}
controller.revealCards("from hand :" + sourceObject.getName(), new CardsImpl(cardToReveal), game);
String nameToSearch = cardToReveal.isSplitCard() ? ((SplitCard) cardToReveal).getLeftHalfCard().getName() : cardToReveal.getName();
String nameToSearch = CardUtil.getCardNameForSameNameSearch(cardToReveal);
FilterCard filterCard = new FilterCard("card named " + nameToSearch);
filterCard.add(new NamePredicate(nameToSearch));
return new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filterCard), true, true).apply(game, source);

View file

@ -0,0 +1,57 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect;
import mage.abilities.keyword.CascadeAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterSpell;
import mage.filter.predicate.mageobject.AbilityPredicate;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AuroraPhoenix extends CardImpl {
private static final FilterSpell filter = new FilterSpell("spell with cascade");
static {
filter.add(new AbilityPredicate(CascadeAbility.class));
}
public AuroraPhoenix(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}");
this.subtype.add(SubType.PHOENIX);
this.power = new MageInt(5);
this.toughness = new MageInt(3);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Cascade
this.addAbility(new CascadeAbility());
// Whenever you cast a spell with cascade, return Aurora Phoenix from your graveyard to your hand.
this.addAbility(new SpellCastControllerTriggeredAbility(
Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(),
filter, false, false
));
}
private AuroraPhoenix(final AuroraPhoenix card) {
super(card);
}
@Override
public AuroraPhoenix copy() {
return new AuroraPhoenix(this);
}
}

View file

@ -0,0 +1,74 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AvernaTheChaosBloom extends CardImpl {
public AvernaTheChaosBloom(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{U}{R}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.ELEMENTAL);
this.subtype.add(SubType.SHAMAN);
this.power = new MageInt(4);
this.toughness = new MageInt(2);
// As you cascade, you may put a land card from among the exiled cards onto the battlefield tapped.
this.addAbility(new SimpleStaticAbility(new AvernaTheChaosBloomReplacementEffect()));
}
private AvernaTheChaosBloom(final AvernaTheChaosBloom card) {
super(card);
}
@Override
public AvernaTheChaosBloom copy() {
return new AvernaTheChaosBloom(this);
}
}
class AvernaTheChaosBloomReplacementEffect extends ReplacementEffectImpl {
AvernaTheChaosBloomReplacementEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit);
staticText = "As you cascade, you may put a land card from among the exiled cards onto the battlefield tapped.";
}
private AvernaTheChaosBloomReplacementEffect(final AvernaTheChaosBloomReplacementEffect effect) {
super(effect);
}
@Override
public AvernaTheChaosBloomReplacementEffect copy() {
return new AvernaTheChaosBloomReplacementEffect(this);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.CASCADE_LAND;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return event.getPlayerId().equals(source.getControllerId());
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
event.setAmount(event.getAmount() + 1);
return false;
}
}

View file

@ -22,6 +22,7 @@ public final class AvianChangeling extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(2);
this.setIsAllCreatureTypes(true);
this.addAbility(ChangelingAbility.getInstance());
this.addAbility(FlyingAbility.getInstance());
}

View file

@ -1,27 +1,44 @@
package mage.cards.b;
import mage.abilities.common.EntersBattlefieldTappedAbility;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
import mage.cards.CardImpl;
import mage.abilities.mana.GreenManaAbility;
import mage.cards.CardSetInfo;
import mage.cards.ModalDoubleFacesCard;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.target.common.TargetCardInYourGraveyard;
import java.util.UUID;
/**
* @author TheElk801
* @author JayDi85
*/
public final class BalaGedRecovery extends CardImpl {
public final class BalaGedRecovery extends ModalDoubleFacesCard {
public BalaGedRecovery(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}");
super(ownerId, setInfo,
new CardType[]{CardType.SORCERY}, new SubType[]{}, "{2}{G}",
"Bala Ged Sanctuary", new CardType[]{CardType.LAND}, new SubType[]{}, ""
);
this.modalDFC = true;
this.secondSideCardClazz = mage.cards.b.BalaGedSanctuary.class;
// 1.
// Bala Ged Recovery
// Sorcery
// Return target card from your graveyard to your hand.
this.getSpellAbility().addEffect(new ReturnFromGraveyardToHandTargetEffect());
this.getSpellAbility().addTarget(new TargetCardInYourGraveyard());
this.getLeftHalfCard().getSpellAbility().addEffect(new ReturnFromGraveyardToHandTargetEffect());
this.getLeftHalfCard().getSpellAbility().addTarget(new TargetCardInYourGraveyard());
// 2.
// Bala Ged Sanctuary
// Land
// Bala Ged Sanctuary enters the battlefield tapped.
this.getRightHalfCard().addAbility(new EntersBattlefieldTappedAbility());
// {T}: Add {G}.
this.getRightHalfCard().addAbility(new GreenManaAbility());
}
private BalaGedRecovery(final BalaGedRecovery card) {

View file

@ -1,37 +0,0 @@
package mage.cards.b;
import mage.abilities.common.EntersBattlefieldTappedAbility;
import mage.abilities.mana.GreenManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BalaGedSanctuary extends CardImpl {
public BalaGedSanctuary(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
this.modalDFC = true;
this.nightCard = true;
// Bala Ged Sanctuary enters the battlefield tapped.
this.addAbility(new EntersBattlefieldTappedAbility());
// {T}: Add {G}.
this.addAbility(new GreenManaAbility());
}
private BalaGedSanctuary(final BalaGedSanctuary card) {
super(card);
}
@Override
public BalaGedSanctuary copy() {
return new BalaGedSanctuary(this);
}
}

View file

@ -1,37 +0,0 @@
package mage.cards.b;
import mage.abilities.common.EntersBattlefieldTappedAbility;
import mage.abilities.mana.BlueManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BeyeenCoast extends CardImpl {
public BeyeenCoast(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
this.modalDFC = true;
this.nightCard = true;
// Beyeen Coast enters the battlefield tapped.
this.addAbility(new EntersBattlefieldTappedAbility());
// {T}: Add {U}.
this.addAbility(new BlueManaAbility());
}
private BeyeenCoast(final BeyeenCoast card) {
super(card);
}
@Override
public BeyeenCoast copy() {
return new BeyeenCoast(this);
}
}

View file

@ -1,26 +1,43 @@
package mage.cards.b;
import mage.abilities.common.EntersBattlefieldTappedAbility;
import mage.abilities.effects.common.continuous.BoostOpponentsEffect;
import mage.cards.CardImpl;
import mage.abilities.mana.BlueManaAbility;
import mage.cards.CardSetInfo;
import mage.cards.ModalDoubleFacesCard;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
* @author JayDi85
*/
public final class BeyeenVeil extends CardImpl {
public final class BeyeenVeil extends ModalDoubleFacesCard {
public BeyeenVeil(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
super(ownerId, setInfo,
new CardType[]{CardType.INSTANT}, new SubType[]{}, "{1}{U}",
"Beyeen Coast", new CardType[]{CardType.LAND}, new SubType[]{}, ""
);
this.modalDFC = true;
this.secondSideCardClazz = mage.cards.b.BeyeenCoast.class;
// 1.
// Beyeen Veil
// Instant
// Creatures your opponents control get -2/-0 until end of turn.
this.getSpellAbility().addEffect(new BoostOpponentsEffect(-2, 0, Duration.EndOfTurn));
this.getLeftHalfCard().getSpellAbility().addEffect(new BoostOpponentsEffect(-2, 0, Duration.EndOfTurn));
// 2.
// Beyeen Coast
// Land
// Beyeen Coast enters the battlefield tapped.
this.getRightHalfCard().addAbility(new EntersBattlefieldTappedAbility());
// {T}: Add {U}.
this.getRightHalfCard().addAbility(new BlueManaAbility());
}
private BeyeenVeil(final BeyeenVeil card) {

View file

@ -1,37 +0,0 @@
package mage.cards.b;
import mage.abilities.common.EntersBattlefieldTappedAbility;
import mage.abilities.mana.BlackManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BlackbloomBog extends CardImpl {
public BlackbloomBog(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
this.modalDFC = true;
this.nightCard = true;
// Blackbloom Bog enters the battlefield tapped.
this.addAbility(new EntersBattlefieldTappedAbility());
// {T}: Add {B}.
this.addAbility(new BlackManaAbility());
}
private BlackbloomBog(final BlackbloomBog card) {
super(card);
}
@Override
public BlackbloomBog copy() {
return new BlackbloomBog(this);
}
}

View file

@ -1,13 +1,15 @@
package mage.cards.b;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTappedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.CardsInOpponentGraveyardCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.keyword.MenaceAbility;
import mage.cards.CardImpl;
import mage.abilities.mana.BlackManaAbility;
import mage.cards.CardSetInfo;
import mage.cards.ModalDoubleFacesCard;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
@ -15,30 +17,40 @@ import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
* @author JayDi85
*/
public final class BlackbloomRogue extends CardImpl {
public final class BlackbloomRogue extends ModalDoubleFacesCard {
public BlackbloomRogue(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
super(ownerId, setInfo,
new CardType[]{CardType.CREATURE}, new SubType[]{SubType.HUMAN, SubType.ROGUE}, "{2}{B}",
"Blackbloom Bog", new CardType[]{CardType.LAND}, new SubType[]{}, ""
);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.ROGUE);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
this.modalDFC = true;
this.secondSideCardClazz = mage.cards.b.BlackbloomBog.class;
// 1.
// Blackbloom Rogue {2}{B}
// Creature Human Rogue
this.getLeftHalfCard().setPT(new MageInt(2), new MageInt(3));
// Menace
this.addAbility(new MenaceAbility());
this.getLeftHalfCard().addAbility(new MenaceAbility());
// Blackbloom Rogue gets +3/+0 as long as an opponent has eight or more cards in their graveyard.
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
this.getLeftHalfCard().addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
new BoostSourceEffect(3, 0, Duration.WhileOnBattlefield),
CardsInOpponentGraveyardCondition.EIGHT, "{this} gets +3/+0 as long as " +
"an opponent has eight or more cards in their graveyard"
)).addHint(CardsInOpponentGraveyardCondition.EIGHT.getHint()));
// 2.
// Blackbloom Bog
// Land
// Blackbloom Bog enters the battlefield tapped.
this.getRightHalfCard().addAbility(new EntersBattlefieldTappedAbility());
// {T}: Add {B}.
this.getRightHalfCard().addAbility(new BlackManaAbility());
}
private BlackbloomRogue(final BlackbloomRogue card) {

View file

@ -1,10 +1,7 @@
package mage.cards.b;
import java.util.UUID;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.effects.common.continuous.GainAllCreatureTypesTargetEffect;
import mage.abilities.keyword.ChangelingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -13,26 +10,27 @@ import mage.constants.Duration;
import mage.constants.SubType;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class BladesOfVelisVel extends CardImpl {
public BladesOfVelisVel(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.TRIBAL,CardType.INSTANT},"{1}{R}");
super(ownerId, setInfo, new CardType[]{CardType.TRIBAL, CardType.INSTANT}, "{1}{R}");
this.subtype.add(SubType.SHAPESHIFTER);
// Changeling
this.setIsAllCreatureTypes(true);
this.addAbility(ChangelingAbility.getInstance());
// Up to two target creatures each get +2/+0 and gain all creature types until end of turn.
Effect effect = new BoostTargetEffect(2,0, Duration.EndOfTurn);
effect.setText("Up to two target creatures each get +2/+0");
this.getSpellAbility().addEffect(effect);
effect = new GainAbilityTargetEffect(ChangelingAbility.getInstance(), Duration.EndOfTurn, "and gain all creature types until end of turn");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetCreaturePermanent(0,2));
this.getSpellAbility().addEffect(new BoostTargetEffect(2, 0, Duration.EndOfTurn)
.setText("Up to two target creatures each get +2/+0"));
this.getSpellAbility().addEffect(new GainAllCreatureTypesTargetEffect(Duration.EndOfTurn)
.setText("and gain all creature types until end of turn"));
this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 2));
}
public BladesOfVelisVel(final BladesOfVelisVel card) {

View file

@ -72,7 +72,7 @@ public final class BloodMoon extends CardImpl {
// So the ability removing has to be done before Layer 6
// Lands have their mana ability intrinsically, so that is added in layer 4
land.getSubtype(game).removeAll(SubType.getLandTypes());
land.getSubtype(game).add(SubType.MOUNTAIN);
land.addSubType(game, SubType.MOUNTAIN);
land.removeAllAbilities(source.getSourceId(), game);
land.addAbility(new RedManaAbility(), source.getSourceId(), game);
break;

View file

@ -85,7 +85,7 @@ class BludgeonBrawlAddSubtypeEffect extends ContinuousEffectImpl {
List<Permanent> permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game);
for (Permanent permanent : permanents) {
if (permanent != null) {
permanent.getSubtype(game).add(SubType.EQUIPMENT);
permanent.addSubType(game, SubType.EQUIPMENT);
affectedPermanents.add(permanent.getId());
}
}

View file

@ -105,22 +105,39 @@ class BolassCitadelPlayTheTopCardEffect extends AsThoughEffectImpl {
if (topCard == null || !topCard.getId().equals(objectIdToCast)) {
return false;
}
if (!topCard.isLand()) {
if (topCard instanceof SplitCard) {
SplitCardHalf leftCard = ((SplitCard) topCard).getLeftHalfCard();
PayLifeCost lifeCost = new PayLifeCost(leftCard.getSpellAbility().getManaCosts().convertedManaCost());
Costs leftCosts = new CostsImpl();
leftCosts.add(lifeCost);
leftCosts.addAll(leftCard.getSpellAbility().getCosts());
player.setCastSourceIdWithAlternateMana(leftCard.getId(), null, leftCosts);
SplitCardHalf rightCard = ((SplitCard) topCard).getRightHalfCard();
lifeCost = new PayLifeCost(rightCard.getSpellAbility().getManaCosts().convertedManaCost());
Costs rightCosts = new CostsImpl();
rightCosts.add(lifeCost);
rightCosts.addAll(rightCard.getSpellAbility().getCosts());
player.setCastSourceIdWithAlternateMana(rightCard.getId(), null, rightCosts);
if (topCard instanceof SplitCard || topCard instanceof ModalDoubleFacesCard) {
// double faces cards
Card card1;
Card card2;
if (topCard instanceof SplitCard) {
card1 = ((SplitCard) topCard).getLeftHalfCard();
card2 = ((SplitCard) topCard).getRightHalfCard();
} else {
card1 = ((ModalDoubleFacesCard) topCard).getLeftHalfCard();
card2 = ((ModalDoubleFacesCard) topCard).getRightHalfCard();
}
// left
if (!card1.isLand()) {
PayLifeCost lifeCost = new PayLifeCost(card1.getSpellAbility().getManaCosts().convertedManaCost());
Costs newCosts = new CostsImpl();
newCosts.add(lifeCost);
newCosts.addAll(card1.getSpellAbility().getCosts());
player.setCastSourceIdWithAlternateMana(card1.getId(), null, newCosts);
}
// right
if (!card2.isLand()) {
PayLifeCost lifeCost = new PayLifeCost(card2.getSpellAbility().getManaCosts().convertedManaCost());
Costs newCosts = new CostsImpl();
newCosts.add(lifeCost);
newCosts.addAll(card2.getSpellAbility().getCosts());
player.setCastSourceIdWithAlternateMana(card2.getId(), null, newCosts);
}
} else {
// other single face cards
if (!topCard.isLand()) {
if (affectedAbility == null) {
affectedAbility = topCard.getSpellAbility();
} else {
@ -134,7 +151,6 @@ class BolassCitadelPlayTheTopCardEffect extends AsThoughEffectImpl {
}
}
return true;
}
return false;
}

View file

@ -1,33 +0,0 @@
package mage.cards.b;
import mage.abilities.mana.WhiteManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BoulderloftPathway extends CardImpl {
public BoulderloftPathway(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
this.modalDFC = true;
this.nightCard = true;
// {T}: Add {W}.
this.addAbility(new WhiteManaAbility());
}
private BoulderloftPathway(final BoulderloftPathway card) {
super(card);
}
@Override
public BoulderloftPathway copy() {
return new BoulderloftPathway(this);
}
}

View file

@ -1,25 +1,38 @@
package mage.cards.b;
import mage.abilities.mana.GreenManaAbility;
import mage.cards.CardImpl;
import mage.abilities.mana.WhiteManaAbility;
import mage.cards.CardSetInfo;
import mage.cards.ModalDoubleFacesCard;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
* @author JayDi85
*/
public final class BranchloftPathway extends CardImpl {
public final class BranchloftPathway extends ModalDoubleFacesCard {
public BranchloftPathway(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
super(ownerId, setInfo,
new CardType[]{CardType.LAND}, new SubType[]{}, "",
"Boulderloft Pathway", new CardType[]{CardType.LAND}, new SubType[]{}, ""
);
this.modalDFC = true;
this.secondSideCardClazz = mage.cards.b.BoulderloftPathway.class;
// 1.
// Branchloft Pathway
// Land
// {T}: Add {G}.
this.addAbility(new GreenManaAbility());
this.getLeftHalfCard().addAbility(new GreenManaAbility());
// 2.
// Boulderloft Pathway
// Land
// {T}: Add {W}.
this.getRightHalfCard().addAbility(new WhiteManaAbility());
}
private BranchloftPathway(final BranchloftPathway card) {

View file

@ -1,25 +1,38 @@
package mage.cards.b;
import mage.abilities.mana.BlackManaAbility;
import mage.abilities.mana.WhiteManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.ModalDoubleFacesCard;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
* @author JayDi85
*/
public final class BrightclimbPathway extends CardImpl {
public final class BrightclimbPathway extends ModalDoubleFacesCard {
public BrightclimbPathway(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
super(ownerId, setInfo,
new CardType[]{CardType.LAND}, new SubType[]{}, "",
"Grimclimb Pathway", new CardType[]{CardType.LAND}, new SubType[]{}, ""
);
this.modalDFC = true;
this.secondSideCardClazz = mage.cards.g.GrimclimbPathway.class;
// 1.
// Brightclimb Pathway
// Land
// {T}: Add {W}.
this.addAbility(new WhiteManaAbility());
this.getLeftHalfCard().addAbility(new WhiteManaAbility());
// 2.
// Grimclimb Pathway
// Land
// {T}: Add {B}.
this.getRightHalfCard().addAbility(new BlackManaAbility());
}
private BrightclimbPathway(final BrightclimbPathway card) {

View file

@ -0,0 +1,94 @@
package mage.cards.b;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.abilities.keyword.PartnerAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.target.common.TargetNonlandPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BrinelinTheMoonKraken extends CardImpl {
public BrinelinTheMoonKraken(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{U}{U}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.KRAKEN);
this.power = new MageInt(6);
this.toughness = new MageInt(8);
// When Brinelin, the Moon Kraken enters the battlefield or whenever you cast a spell with converted mana cost 6 or greater, you may return target nonland permanent to its owner's hand.
this.addAbility(new BrinelinTheMoonKrakenTriggeredAbility());
// Partner
this.addAbility(PartnerAbility.getInstance());
}
private BrinelinTheMoonKraken(final BrinelinTheMoonKraken card) {
super(card);
}
@Override
public BrinelinTheMoonKraken copy() {
return new BrinelinTheMoonKraken(this);
}
}
class BrinelinTheMoonKrakenTriggeredAbility extends TriggeredAbilityImpl {
BrinelinTheMoonKrakenTriggeredAbility() {
super(Zone.ALL, new ReturnToHandTargetEffect(), true);
this.addTarget(new TargetNonlandPermanent());
}
private BrinelinTheMoonKrakenTriggeredAbility(final BrinelinTheMoonKrakenTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SPELL_CAST
|| event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
switch (event.getType()) {
case SPELL_CAST:
if (!event.getPlayerId().equals(this.getControllerId())
|| game.getPermanent(getSourceId()) == null) {
return false;
}
Spell spell = game.getSpellOrLKIStack(event.getTargetId());
return spell != null && spell.getConvertedManaCost() >= 6;
case ENTERS_THE_BATTLEFIELD:
return event.getTargetId().equals(getSourceId());
default:
return false;
}
}
@Override
public String getRule() {
return "When {this} enters the battlefield or whenever you cast a spell with converted mana cost " +
"6 or greater, you may return target nonland permanent to its owner's hand.";
}
@Override
public BrinelinTheMoonKrakenTriggeredAbility copy() {
return new BrinelinTheMoonKrakenTriggeredAbility(this);
}
}

View file

@ -144,8 +144,8 @@ class BronzehideLionContinuousEffect extends ContinuousEffectImpl {
case TypeChangingEffects_4:
lion.getCardType().clear();
lion.addCardType(CardType.ENCHANTMENT);
lion.getSubtype(game).clear();
lion.getSubtype(game).add(SubType.AURA);
lion.removeAllSubTypes(game);
lion.addSubType(game, SubType.AURA);
break;
case AbilityAddingRemovingEffects_6:
List<Ability> toRemove = new ArrayList<>();

View file

@ -30,6 +30,7 @@ public final class CairnWanderer extends CardImpl {
this.toughness = new MageInt(4);
// Changeling
this.setIsAllCreatureTypes(true);
this.addAbility(ChangelingAbility.getInstance());
// As long as a creature card with flying is in a graveyard, Cairn Wanderer has flying. The same is true for fear, first strike, double strike, deathtouch, haste, landwalk, lifelink, protection, reach, trample, shroud, and vigilance.

View file

@ -1,12 +1,9 @@
package mage.cards.c;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.OnEventTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.keyword.ChangelingAbility;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.*;
import mage.constants.CardType;
@ -15,27 +12,24 @@ import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.Predicate;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.TargetPermanent;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCreaturePermanent;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
*
* @author North
*/
public final class CallToTheKindred extends CardImpl {
public CallToTheKindred(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{U}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}");
this.subtype.add(SubType.AURA);
// Enchant creature
@ -43,6 +37,7 @@ public final class CallToTheKindred extends CardImpl {
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
// At the beginning of your upkeep, you may look at the top five cards of your library.
// If you do, you may put a creature card that shares a creature type with enchanted creature from among them onto the battlefield,
// then you put the rest of those cards on the bottom of your library in any order.
@ -61,12 +56,14 @@ public final class CallToTheKindred extends CardImpl {
class CallToTheKindredEffect extends OneShotEffect {
public CallToTheKindredEffect() {
CallToTheKindredEffect() {
super(Outcome.PutCreatureInPlay);
this.staticText = "look at the top five cards of your library. If you do, you may put a creature card that shares a creature type with enchanted creature from among them onto the battlefield, then you put the rest of those cards on the bottom of your library in any order";
this.staticText = "look at the top five cards of your library. If you do, you may put a creature card " +
"that shares a creature type with enchanted creature from among them onto the battlefield, " +
"then you put the rest of those cards on the bottom of your library in any order";
}
public CallToTheKindredEffect(final CallToTheKindredEffect effect) {
private CallToTheKindredEffect(final CallToTheKindredEffect effect) {
super(effect);
}
@ -90,36 +87,33 @@ class CallToTheKindredEffect extends OneShotEffect {
}
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 5));
controller.lookAtCards(enchantment.getIdName(), cards, game);
FilterCreatureCard filter = new FilterCreatureCard();
filter.add(new CallToTheKindredPredicate(creature));
if (!creature.getAbilities().contains(ChangelingAbility.getInstance())) {
StringBuilder sb = new StringBuilder("creature card with at least one subtype from: ");
List<Predicate<MageObject>> subtypes = new ArrayList<>();
for (SubType subtype : creature.getSubtype(game)) {
subtypes.add(subtype.getPredicate());
sb.append(subtype).append(", ");
}
filter.add(Predicates.or(subtypes));
sb.delete(sb.length() - 2, sb.length());
filter.setMessage(sb.toString());
} else {
filter.setMessage("creature card that shares a creature type with enchanted creature");
}
if (cards.count(filter, game) > 0 && controller.chooseUse(Outcome.DrawCard, "Do you wish to put a creature card onto the battlefield?", source, game)) {
TargetCard target = new TargetCard(Zone.LIBRARY, filter);
if (controller.choose(Outcome.PutCreatureInPlay, cards, target, game)) {
Card card = cards.get(target.getFirstTarget(), game);
if (card != null) {
cards.remove(card);
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
}
if (cards.count(filter, game) > 0) {
TargetCard target = new TargetCardInLibrary(0, 1, filter);
controller.choose(Outcome.PutCreatureInPlay, cards, target, game);
Card card = cards.get(target.getFirstTarget(), game);
if (card != null) {
cards.remove(card);
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
}
}
controller.putCardsOnBottomOfLibrary(cards, game, source, true);
return true;
}
}
class CallToTheKindredPredicate implements Predicate<Card> {
private final Permanent permanent;
CallToTheKindredPredicate(Permanent permanent) {
this.permanent = permanent;
}
@Override
public boolean apply(Card input, Game game) {
return permanent != null && input != null && permanent.shareCreatureTypes(input, game);
}
}

View file

@ -1,7 +1,6 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -21,8 +20,9 @@ import mage.game.permanent.Permanent;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public final class CaptivatingVampire extends CardImpl {
@ -37,7 +37,7 @@ public final class CaptivatingVampire extends CardImpl {
}
public CaptivatingVampire(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}{B}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{B}");
this.subtype.add(SubType.VAMPIRE);
this.power = new MageInt(2);
@ -90,11 +90,7 @@ class CaptivatingVampireEffect extends ContinuousEffectImpl {
}
break;
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
if (!permanent.hasSubtype(SubType.VAMPIRE, game)) {
permanent.getSubtype(game).add(SubType.VAMPIRE);
}
}
permanent.addSubType(game, SubType.VAMPIRE);
break;
}
return true;

View file

@ -1,7 +1,5 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageObject;
import mage.ObjectColor;
import mage.abilities.Ability;
@ -18,14 +16,15 @@ import mage.filter.common.FilterLandPermanent;
import mage.filter.common.FilterNonlandPermanent;
import mage.game.Game;
import mage.game.command.CommandObject;
import mage.game.command.Commander;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.players.ManaPoolItem;
import mage.players.Player;
import mage.game.command.Commander;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class CelestialDawn extends CardImpl {
@ -89,8 +88,8 @@ class CelestialDawnToPlainsEffect extends ContinuousEffectImpl {
land.addAbility(new WhiteManaAbility(), source.getSourceId(), game);
break;
case TypeChangingEffects_4:
land.getSubtype(game).clear();
land.getSubtype(game).add(SubType.PLAINS);
land.getSubtype(game).removeAll(SubType.getLandTypes());
land.addSubType(game, SubType.PLAINS);
break;
}
}

View file

@ -31,6 +31,7 @@ public final class ChameleonColossus extends CardImpl {
this.toughness = new MageInt(4);
// Changeling (This card is every creature type at all times.)
this.setIsAllCreatureTypes(true);
this.addAbility(ChangelingAbility.getInstance());
// Protection from black

View file

@ -24,6 +24,7 @@ public final class ChangelingBerserker extends CardImpl {
this.toughness = new MageInt(3);
// Changeling
this.setIsAllCreatureTypes(true);
this.addAbility(ChangelingAbility.getInstance());
// Haste

View file

@ -24,6 +24,7 @@ public final class ChangelingHero extends CardImpl {
this.toughness = new MageInt(4);
// Changeling
this.setIsAllCreatureTypes(true);
this.addAbility(ChangelingAbility.getInstance());
// Champion a creature

View file

@ -24,6 +24,7 @@ public final class ChangelingOutcast extends CardImpl {
this.toughness = new MageInt(1);
// Changeling
this.setIsAllCreatureTypes(true);
this.addAbility(ChangelingAbility.getInstance());
// Changeling Outcast can't block and can't be blocked.

View file

@ -22,6 +22,7 @@ public final class ChangelingSentinel extends CardImpl {
this.power = new MageInt(3);
this.toughness = new MageInt(2);
this.setIsAllCreatureTypes(true);
this.addAbility(ChangelingAbility.getInstance());
this.addAbility(VigilanceAbility.getInstance());
}

View file

@ -23,6 +23,7 @@ public final class ChangelingTitan extends CardImpl {
this.toughness = new MageInt(7);
// Changeling
this.setIsAllCreatureTypes(true);
this.addAbility(ChangelingAbility.getInstance());
// Champion a creature

View file

@ -1,7 +1,5 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
@ -15,17 +13,18 @@ import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.UUID;
/**
*
* @author Plopman
*/
public final class ChimericCoils extends CardImpl {
public ChimericCoils(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}");
// {X}{1}: Chimeric Coils becomes an X/X Construct artifact creature. Sacrifice it at the beginning of thhe next end step.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChimericCoilsEffect(), new ManaCostsImpl("{X}{1}"));
Ability ability = new SimpleActivatedAbility(new ChimericCoilsEffect(), new ManaCostsImpl("{X}{1}"));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new SacrificeSourceEffect())));
this.addAbility(ability);
}
@ -43,8 +42,8 @@ public final class ChimericCoils extends CardImpl {
class ChimericCoilsEffect extends ContinuousEffectImpl {
public ChimericCoilsEffect() {
super(Duration.EndOfTurn, Outcome.BecomeCreature);
setText();
super(Duration.Custom, Outcome.BecomeCreature);
staticText = "{this} becomes an X/X Construct artifact creature";
}
public ChimericCoilsEffect(final ChimericCoilsEffect effect) {
@ -59,24 +58,28 @@ class ChimericCoilsEffect extends ContinuousEffectImpl {
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
permanent.addCardType(CardType.CREATURE);
permanent.getSubtype(game).add(SubType.CONSTRUCT);
}
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
int xValue = source.getManaCostsToPay().getX();
permanent.getPower().setValue(xValue);
permanent.getToughness().setValue(xValue);
}
}
return true;
if (permanent == null) {
return false;
}
return false;
switch (layer) {
case TypeChangingEffects_4:
if (!permanent.isArtifact()) {
permanent.addCardType(CardType.ARTIFACT);
}
if (!permanent.isCreature()) {
permanent.addCardType(CardType.CREATURE);
}
permanent.removeAllCreatureTypes(game);
permanent.addSubType(game, SubType.CONSTRUCT);
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
int xValue = source.getManaCostsToPay().getX();
permanent.getPower().setValue(xValue);
permanent.getToughness().setValue(xValue);
}
}
return true;
}
@Override
@ -84,10 +87,6 @@ class ChimericCoilsEffect extends ContinuousEffectImpl {
return false;
}
private void setText() {
staticText = duration.toString() + " {this} becomes an X/X Construct artifact creature";
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.PTChangingEffects_7 || layer == Layer.TypeChangingEffects_4;

View file

@ -1,7 +1,5 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
@ -12,17 +10,18 @@ import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.UUID;
/**
*
* @author Backfir3
*/
public final class ChimericStaff extends CardImpl {
public ChimericStaff(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
// {X}: Chimeric Staff becomes an X/X Construct artifact creature until end of turn.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChimericStaffEffect(), new ManaCostsImpl("{X}")));
this.addAbility(new SimpleActivatedAbility(new ChimericStaffEffect(), new ManaCostsImpl("{X}")));
}
public ChimericStaff(final ChimericStaff card) {
@ -39,7 +38,7 @@ class ChimericStaffEffect extends ContinuousEffectImpl {
public ChimericStaffEffect() {
super(Duration.EndOfTurn, Outcome.BecomeCreature);
setText();
staticText = "{this} becomes an X/X Construct artifact creature until end of turn";
}
public ChimericStaffEffect(final ChimericStaffEffect effect) {
@ -54,26 +53,28 @@ class ChimericStaffEffect extends ContinuousEffectImpl {
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
permanent.addCardType(CardType.CREATURE);
permanent.getSubtype(game).add(SubType.CONSTRUCT);
}
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
int xValue = source.getManaCostsToPay().getX();
if (xValue != 0) {
permanent.getPower().setValue(xValue);
permanent.getToughness().setValue(xValue);
}
}
}
return true;
if (permanent == null) {
return false;
}
return false;
switch (layer) {
case TypeChangingEffects_4:
if (!permanent.isArtifact()) {
permanent.addCardType(CardType.ARTIFACT);
}
if (!permanent.isCreature()) {
permanent.addCardType(CardType.CREATURE);
}
permanent.removeAllCreatureTypes(game);
permanent.addSubType(game, SubType.CONSTRUCT);
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
int xValue = source.getManaCostsToPay().getX();
permanent.getPower().setValue(xValue);
permanent.getToughness().setValue(xValue);
}
}
return true;
}
@Override
@ -81,10 +82,6 @@ class ChimericStaffEffect extends ContinuousEffectImpl {
return false;
}
private void setText() {
staticText = duration.toString() + " {this} becomes an X/X Construct artifact creature";
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.PTChangingEffects_7 || layer == Layer.TypeChangingEffects_4;

View file

@ -1,25 +1,38 @@
package mage.cards.c;
import mage.abilities.mana.BlackManaAbility;
import mage.abilities.mana.BlueManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.ModalDoubleFacesCard;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
* @author JayDi85
*/
public final class ClearwaterPathway extends CardImpl {
public final class ClearwaterPathway extends ModalDoubleFacesCard {
public ClearwaterPathway(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
super(ownerId, setInfo,
new CardType[]{CardType.LAND}, new SubType[]{}, "",
"Murkwater Pathway", new CardType[]{CardType.LAND}, new SubType[]{}, ""
);
this.modalDFC = true;
this.secondSideCardClazz = mage.cards.m.MurkwaterPathway.class;
// 1.
// Clearwater Pathway
// Land
// {T}: Add {U}.
this.addAbility(new BlueManaAbility());
this.getLeftHalfCard().addAbility(new BlueManaAbility());
// 2.
// Murkwater Pathway
// Land
// {T}: Add {B}.
this.getRightHalfCard().addAbility(new BlackManaAbility());
}
private ClearwaterPathway(final ClearwaterPathway card) {

View file

@ -0,0 +1,64 @@
package mage.cards.c;
import mage.MageInt;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.keyword.EncoreAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.permanent.DefendingPlayerControlsPredicate;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class CoastlineMarauders extends CardImpl {
private static final FilterPermanent filter = new FilterLandPermanent();
static {
filter.add(DefendingPlayerControlsPredicate.instance);
}
private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter);
public CoastlineMarauders(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.PIRATE);
this.power = new MageInt(0);
this.toughness = new MageInt(3);
// Trample
this.addAbility(TrampleAbility.getInstance());
// Whenever Coastline Marauders attacks, it gets +1/+0 until end of turn for each land defending player controls.
this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect(
xValue, StaticValue.get(0), Duration.EndOfTurn, true
).setText("it gets +1/+0 until end of turn for each land defending player controls"), false));
// Encore {4}{R}{R}
this.addAbility(new EncoreAbility(new ManaCostsImpl<>("{4}{R}{R}")));
}
private CoastlineMarauders(final CoastlineMarauders card) {
super(card);
}
@Override
public CoastlineMarauders copy() {
return new CoastlineMarauders(this);
}
}

View file

@ -1,28 +1,26 @@
package mage.cards.c;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.keyword.ChangelingAbility;
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.util.SubTypeList;
import java.util.List;
import java.util.UUID;
/**
*
* @author North
*/
public final class CoatOfArms extends CardImpl {
public CoatOfArms(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{5}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}");
// Each creature gets +1/+1 for each other creature on the battlefield that shares at least one creature type with it.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CoatOfArmsEffect()));
@ -40,7 +38,7 @@ public final class CoatOfArms extends CardImpl {
class CoatOfArmsEffect extends ContinuousEffectImpl {
public CoatOfArmsEffect() {
public CoatOfArmsEffect() {
super(Duration.WhileOnBattlefield, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature);
this.staticText = "Each creature gets +1/+1 for each other creature on the battlefield that shares at least one creature type with it";
}
@ -56,7 +54,9 @@ class CoatOfArmsEffect extends ContinuousEffectImpl {
@Override
public boolean apply(Game game, Ability source) {
List<Permanent> permanents = game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game);
List<Permanent> permanents = game.getBattlefield().getActivePermanents(
StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game
);
for (Permanent permanent : permanents) {
int amount = getAmount(permanents, permanent, game);
permanent.addPower(amount);
@ -67,20 +67,9 @@ class CoatOfArmsEffect extends ContinuousEffectImpl {
private int getAmount(List<Permanent> permanents, Permanent target, Game game) {
int amount = 0;
SubTypeList targetSubtype = target.getSubtype(game);
if (target.getAbilities().contains(ChangelingAbility.getInstance()) || target.isAllCreatureTypes()) {
return permanents.size() - 1;
}
for (Permanent permanent : permanents) {
if (!permanent.getId().equals(target.getId())) {
for (SubType subtype : targetSubtype) {
if (subtype.getSubTypeSet() == SubTypeSet.CreatureType) {
if (permanent.hasSubtype(subtype, game)) {
amount++;
break;
}
}
}
if (!permanent.getId().equals(target.getId()) && permanent.shareCreatureTypes(target, game)) {
amount++;
}
}
return amount;

View file

@ -77,7 +77,7 @@ public final class Conversion extends CardImpl {
case TypeChangingEffects_4:
if (land.getSubtype(game).contains(SubType.MOUNTAIN)) {
land.getSubtype(game).removeAll(SubType.getLandTypes());
land.getSubtype(game).add(SubType.PLAINS);
land.addSubType(game, SubType.PLAINS);
land.removeAllAbilities(source.getSourceId(), game);
land.addAbility(new WhiteManaAbility(), source.getSourceId(), game);
break;

View file

@ -1,7 +1,5 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
@ -18,8 +16,9 @@ import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import mage.target.common.TargetLandPermanent;
import java.util.UUID;
/**
*
* @author North
*/
public final class ConvincingMirage extends CardImpl {
@ -32,8 +31,10 @@ public final class ConvincingMirage extends CardImpl {
TargetPermanent auraTarget = new TargetLandPermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment));
// As Convincing Mirage enters the battlefield, choose a basic land type.
this.addAbility(new AsEntersBattlefieldAbility(new ChooseBasicLandTypeEffect(Outcome.Neutral)));
// Enchanted land is the chosen type.
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
@ -53,7 +54,7 @@ public final class ConvincingMirage extends CardImpl {
class ConvincingMirageContinousEffect extends ContinuousEffectImpl {
public ConvincingMirageContinousEffect() {
super(Duration.WhileOnBattlefield, Outcome.Neutral);
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral);
staticText = "Enchanted land is the chosen type";
}
@ -67,53 +68,59 @@ class ConvincingMirageContinousEffect extends ContinuousEffectImpl {
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Permanent enchantment = game.getPermanent(source.getSourceId());
public void init(Ability source, Game game) {
super.init(source, game);
SubType choice = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + ChooseBasicLandTypeEffect.VALUE_KEY));
if (enchantment != null && enchantment.getAttachedTo() != null && choice != null) {
Permanent land = game.getPermanent(enchantment.getAttachedTo());
if (land != null) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
land.getSubtype(game).clear();
land.getSubtype(game).add(choice);
}
break;
case AbilityAddingRemovingEffects_6:
if (sublayer == SubLayer.NA) {
land.getAbilities().clear();
if (choice.equals(SubType.FOREST)) {
land.addAbility(new GreenManaAbility(), source.getSourceId(), game);
}
if (choice.equals(SubType.PLAINS)) {
land.addAbility(new WhiteManaAbility(), source.getSourceId(), game);
}
if (choice.equals(SubType.MOUNTAIN)) {
land.addAbility(new RedManaAbility(), source.getSourceId(), game);
}
if (choice.equals(SubType.ISLAND)) {
land.addAbility(new BlueManaAbility(), source.getSourceId(), game);
}
if (choice.equals(SubType.SWAMP)) {
land.addAbility(new BlackManaAbility(), source.getSourceId(), game);
}
}
break;
}
return true;
}
switch (choice) {
case FOREST:
dependencyTypes.add(DependencyType.BecomeForest);
break;
case PLAINS:
dependencyTypes.add(DependencyType.BecomePlains);
break;
case MOUNTAIN:
dependencyTypes.add(DependencyType.BecomeMountain);
break;
case ISLAND:
dependencyTypes.add(DependencyType.BecomeIsland);
break;
case SWAMP:
dependencyTypes.add(DependencyType.BecomeSwamp);
break;
}
return false;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4;
Permanent enchantment = game.getPermanent(source.getSourceId());
SubType choice = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + ChooseBasicLandTypeEffect.VALUE_KEY));
if (enchantment == null || enchantment.getAttachedTo() == null || choice == null) {
return false;
}
Permanent land = game.getPermanent(enchantment.getAttachedTo());
if (land == null) {
return false;
}
land.getSubtype(game).removeAll(SubType.getLandTypes());
land.addSubType(game, choice);
land.removeAllAbilities(source.getSourceId(), game);
switch (choice) {
case FOREST:
land.addAbility(new GreenManaAbility(), source.getSourceId(), game);
break;
case PLAINS:
land.addAbility(new WhiteManaAbility(), source.getSourceId(), game);
break;
case MOUNTAIN:
land.addAbility(new RedManaAbility(), source.getSourceId(), game);
break;
case ISLAND:
land.addAbility(new BlueManaAbility(), source.getSourceId(), game);
break;
case SWAMP:
land.addAbility(new BlackManaAbility(), source.getSourceId(), game);
break;
}
return true;
}
}

View file

@ -0,0 +1,57 @@
package mage.cards.c;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.common.MonarchIsSourceControllerCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.BecomesMonarchSourceEffect;
import mage.abilities.effects.common.PutCardFromHandOntoBattlefieldEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.filter.FilterCard;
import mage.filter.StaticFilters;
import mage.filter.predicate.Predicates;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class CourtOfBounty extends CardImpl {
private static final FilterCard filter = new FilterCard("a creature or land card");
static {
filter.add(Predicates.or(
CardType.CREATURE.getPredicate(),
CardType.LAND.getPredicate()
));
}
public CourtOfBounty(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}{G}");
// When Court of Bounty enters the battlefield, you become the monarch.
this.addAbility(new EntersBattlefieldTriggeredAbility(new BecomesMonarchSourceEffect()));
// At the beginning of your upkeep, you may put a land card from your hand onto the battlefield. If you're the monarch, instead you may put a creature or land card from your hand onto the battlefield.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ConditionalOneShotEffect(
new PutCardFromHandOntoBattlefieldEffect(filter),
new PutCardFromHandOntoBattlefieldEffect(StaticFilters.FILTER_CARD_LAND_A),
MonarchIsSourceControllerCondition.instance, "you may put a land card " +
"from your hand onto the battlefield. If you're the monarch, " +
"instead you may put a creature or land card from your hand onto the battlefield"
), TargetController.YOU, false));
}
private CourtOfBounty(final CourtOfBounty card) {
super(card);
}
@Override
public CourtOfBounty copy() {
return new CourtOfBounty(this);
}
}

View file

@ -0,0 +1,84 @@
package mage.cards.c;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.BecomesMonarchSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.game.Game;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPlayer;
import java.util.Collection;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* @author TheElk801
*/
public final class CourtOfCunning extends CardImpl {
public CourtOfCunning(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}{U}");
// When Court of Cunning enters the battlefield, you become the monarch.
this.addAbility(new EntersBattlefieldTriggeredAbility(new BecomesMonarchSourceEffect()));
// At the beginning of your upkeep, any number of target players each mill two cards. If you're the monarch, each of those players mills ten cards instead.
Ability ability = new BeginningOfUpkeepTriggeredAbility(
new CourtOfCunningEffect(), TargetController.YOU, false
);
ability.addTarget(new TargetPlayer(0, Integer.MAX_VALUE, false));
this.addAbility(ability);
}
private CourtOfCunning(final CourtOfCunning card) {
super(card);
}
@Override
public CourtOfCunning copy() {
return new CourtOfCunning(this);
}
}
class CourtOfCunningEffect extends OneShotEffect {
CourtOfCunningEffect() {
super(Outcome.Benefit);
staticText = "any number of target players each mill two cards. " +
"If you're the monarch, each of those players mills ten cards instead";
}
private CourtOfCunningEffect(final CourtOfCunningEffect effect) {
super(effect);
}
@Override
public CourtOfCunningEffect copy() {
return new CourtOfCunningEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
boolean isMonarch = source.isControlledBy(game.getMonarchId());
for (Player player : source
.getTargets()
.stream()
.map(Target::getTargets)
.flatMap(Collection::stream)
.map(game::getPlayer)
.filter(Objects::nonNull)
.collect(Collectors.toList())) {
player.millCards(isMonarch ? 10 : 2, source, game);
}
return true;
}
}

View file

@ -0,0 +1,45 @@
package mage.cards.c;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.common.MonarchIsSourceControllerCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.BecomesMonarchSourceEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.game.permanent.token.AngelToken;
import mage.game.permanent.token.SpiritWhiteToken;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class CourtOfGrace extends CardImpl {
public CourtOfGrace(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}");
// When Court of Grace enters the battlefield, you become the monarch.
this.addAbility(new EntersBattlefieldTriggeredAbility(new BecomesMonarchSourceEffect()));
// At the beginning of your upkeep, create a 1/1 white Spirit creature token with flying. If you're the monarch, create a 4/4 white Angel creature token with flying instead.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ConditionalOneShotEffect(
new CreateTokenEffect(new AngelToken()), new CreateTokenEffect(new SpiritWhiteToken()),
MonarchIsSourceControllerCondition.instance, "create a 1/1 white Spirit creature token with flying. " +
"If you're the monarch, create a 4/4 white Angel creature token with flying instead"
), TargetController.YOU, false));
}
private CourtOfGrace(final CourtOfGrace card) {
super(card);
}
@Override
public CourtOfGrace copy() {
return new CourtOfGrace(this);
}
}

View file

@ -23,7 +23,7 @@ public final class CradleToGrave extends CardImpl {
static {
filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK)));
filter.add(new EnteredThisTurnPredicate());
filter.add(EnteredThisTurnPredicate.instance);
}
public CradleToGrave(UUID ownerId, CardSetInfo setInfo) {

View file

@ -1,26 +1,40 @@
package mage.cards.c;
import mage.abilities.keyword.TransformAbility;
import mage.abilities.mana.GreenManaAbility;
import mage.abilities.mana.RedManaAbility;
import mage.cards.CardSetInfo;
import mage.cards.ModalDoubleFacesCard;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
import mage.abilities.keyword.TransformAbility;
import mage.abilities.mana.RedManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
/**
* @author TheElk801
* @author JayDi85
*/
public final class CragcrownPathway extends CardImpl {
public final class CragcrownPathway extends ModalDoubleFacesCard {
public CragcrownPathway(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
super(ownerId, setInfo,
new CardType[]{CardType.LAND}, new SubType[]{}, "",
"Timbercrown Pathway", new CardType[]{CardType.LAND}, new SubType[]{}, ""
);
this.secondSideCardClazz = mage.cards.t.TimbercrownPathway.class;
// 1.
// Cragcrown Pathway
// Land
// {T}: Add {R}.
this.addAbility(new RedManaAbility());
this.addAbility(new TransformAbility());
this.getLeftHalfCard().addAbility(new RedManaAbility());
this.getLeftHalfCard().addAbility(new TransformAbility());
// 2.
// Timbercrown Pathway
// Land
// {T}: Add {G}.
this.getRightHalfCard().addAbility(new GreenManaAbility());
}
private CragcrownPathway(final CragcrownPathway card) {

View file

@ -1,25 +1,26 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlashbackAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.choices.ChoiceCardType;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.TimingRule;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
import java.util.Arrays;
import java.util.UUID;
import java.util.stream.Collectors;
/**
*
* @author nantuko
*/
public final class CreepingRenaissance extends CardImpl {
@ -58,40 +59,27 @@ class CreepingRenaissanceEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Choice typeChoice = new ChoiceImpl();
typeChoice.setMessage("Choose permanent type");
typeChoice.getChoices().add(CardType.ARTIFACT.toString());
typeChoice.getChoices().add(CardType.CREATURE.toString());
typeChoice.getChoices().add(CardType.ENCHANTMENT.toString());
typeChoice.getChoices().add(CardType.LAND.toString());
typeChoice.getChoices().add(CardType.PLANESWALKER.toString());
if (controller.choose(Outcome.ReturnToHand, typeChoice, game)) {
String typeName = typeChoice.getChoice();
CardType chosenType = null;
for (CardType cardType : CardType.values()) {
if (cardType.toString().equals(typeName)) {
chosenType = cardType;
}
}
if (chosenType != null) {
for (Card card : controller.getGraveyard().getCards(game)) {
if (card.getCardType().contains(chosenType)) {
card.moveToZone(Zone.HAND, source.getSourceId(), game, false);
}
}
return true;
}
}
if (controller == null) {
return false;
}
return false;
Choice typeChoice = new ChoiceCardType(true, Arrays.stream(CardType.values()).filter(CardType::isPermanentType).collect(Collectors.toList()));
typeChoice.setMessage("Choose a permanent type");
if (!controller.choose(Outcome.ReturnToHand, typeChoice, game)) {
return false;
}
String typeName = typeChoice.getChoice();
CardType chosenType = CardType.fromString(typeChoice.getChoice());
if (chosenType == null) {
return false;
}
FilterCard filter = new FilterCard(chosenType.toString().toLowerCase() + " card");
filter.add(chosenType.getPredicate());
return controller.moveCards(controller.getGraveyard().getCards(filter, source.getSourceId(), controller.getId(), game), Zone.HAND, source, game);
}
@Override
public CreepingRenaissanceEffect copy() {
return new CreepingRenaissanceEffect(this);
}
}

View file

@ -28,6 +28,7 @@ public final class CribSwap extends CardImpl {
this.subtype.add(SubType.SHAPESHIFTER);
// Changeling
this.setIsAllCreatureTypes(true);
this.addAbility(ChangelingAbility.getInstance());
// Exile target creature. Its controller creates a 1/1 colorless Shapeshifter creature token with changeling.
this.getSpellAbility().addEffect(new ExileTargetEffect());

View file

@ -1,52 +1,40 @@
package mage.cards.c;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.PutCardFromHandOntoBattlefieldEffect;
import mage.abilities.keyword.ChangelingAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.Predicate;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetControlledPermanent;
import java.util.ArrayList;
import java.util.List;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
*
* @author spjspj
*/
public final class CrypticGateway extends CardImpl {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control");
static {
filter.add(Predicates.not(TappedPredicate.instance));
}
TargetControlledPermanent target;
public CrypticGateway(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}");
// Tap two untapped creatures you control: You may put a creature card from your hand that shares a creature type with each creature tapped this way onto the battlefield.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CrypticGatewayEffect(), new CrypticGatewayCost(new TargetControlledPermanent(filter))));
this.addAbility(new SimpleActivatedAbility(new CrypticGatewayEffect(), new CrypticGatewayCost()));
}
public CrypticGateway(final CrypticGateway card) {
@ -61,29 +49,28 @@ public final class CrypticGateway extends CardImpl {
class CrypticGatewayCost extends CostImpl {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control");
private UUID targetCreatureId = null;
private UUID targetCreatureId2 = null;
TargetControlledPermanent target;
private static final FilterControlledCreaturePermanent filter
= new FilterControlledCreaturePermanent("untapped creatures you control");
static {
filter.add(Predicates.not(TappedPredicate.instance));
}
public CrypticGatewayCost(TargetControlledPermanent target) {
this.target = target;
private final TargetControlledPermanent target = new TargetControlledPermanent(2, filter);
private CrypticGatewayPredicate predicate;
public CrypticGatewayCost() {
this.text = "Tap two untapped creatures you control";
}
public CrypticGatewayCost(final CrypticGatewayCost cost) {
super(cost);
this.target = cost.target.copy();
}
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
int numTargets = 0;
Set<Permanent> permanents = new HashSet<>();
while (numTargets < 2 && target.choose(Outcome.Tap, controllerId, sourceId, game)) {
for (UUID targetId : target.getTargets()) {
Permanent permanent = game.getPermanent(targetId);
@ -94,16 +81,13 @@ class CrypticGatewayCost extends CostImpl {
if (paid) {
numTargets++;
target.clearChosen();
}
for (Effect effect : ability.getEffects()) {
if (targetCreatureId == null) {
targetCreatureId = permanent.getId();
} else if (targetCreatureId2 == null) {
targetCreatureId2 = permanent.getId();
}
permanents.add(permanent);
}
}
}
if (paid) {
this.predicate = new CrypticGatewayPredicate(permanents);
}
return paid;
}
@ -112,18 +96,14 @@ class CrypticGatewayCost extends CostImpl {
return target.canChoose(controllerId, game);
}
public CrypticGatewayPredicate getPredicate() {
return predicate;
}
@Override
public CrypticGatewayCost copy() {
return new CrypticGatewayCost(this);
}
public UUID getTargetCreatureId() {
return targetCreatureId;
}
public UUID getTargetCreatureId2() {
return targetCreatureId2;
}
}
class CrypticGatewayEffect extends OneShotEffect {
@ -147,59 +127,33 @@ class CrypticGatewayEffect extends OneShotEffect {
if (source.getCosts() == null) {
return false;
}
FilterCard filter = new FilterCreatureCard("creature card from your hand that shares a creature type with each creature tapped this way");
for (Cost cost : source.getCosts()) {
if (cost instanceof CrypticGatewayCost) {
UUID id = ((CrypticGatewayCost) cost).getTargetCreatureId();
UUID id2 = ((CrypticGatewayCost) cost).getTargetCreatureId2();
Permanent creature = game.getPermanentOrLKIBattlefield(id);
Permanent creature2 = game.getPermanentOrLKIBattlefield(id2);
if (creature == null || creature2 == null) {
return false;
}
boolean commonSubType = false;
boolean changeling = false;
boolean changeling2 = false;
if (creature.getAbilities().containsKey(ChangelingAbility.getInstance().getId()) || creature.isAllCreatureTypes()) {
changeling = true;
}
if (creature2.getAbilities().containsKey(ChangelingAbility.getInstance().getId()) || creature2.isAllCreatureTypes()) {
changeling2 = true;
}
List<SubType.SubTypePredicate> subtypes = new ArrayList<>();
for (SubType subtype : creature.getSubtype(game)) {
if (creature2.hasSubtype(subtype, game) || changeling2) {
subtypes.add(subtype.getPredicate());
commonSubType = true;
}
}
for (SubType subtype : creature2.getSubtype(game)) {
if (creature.hasSubtype(subtype, game) || changeling) {
subtypes.add(subtype.getPredicate());
commonSubType = true;
}
}
if (changeling && changeling2) {
filter = new FilterCreatureCard("creature card from your hand that shares a creature type with each creature tapped this way");
} else if (commonSubType) {
filter.add(Predicates.or(subtypes));
}
if (commonSubType) {
PutCardFromHandOntoBattlefieldEffect putIntoPlay = new PutCardFromHandOntoBattlefieldEffect(filter);
putIntoPlay.apply(game, source);
}
Predicate predicate = ((CrypticGatewayCost) cost).getPredicate();
filter.add(predicate);
return new PutCardFromHandOntoBattlefieldEffect(filter).apply(game, source);
}
}
return false;
}
}
class CrypticGatewayPredicate implements Predicate<Card> {
private final Set<Permanent> permanents = new HashSet<>();
CrypticGatewayPredicate(Set<Permanent> permanents) {
this.permanents.addAll(permanents);
}
@Override
public boolean apply(Card input, Game game) {
for (Permanent permanent : permanents) {
if (!permanent.shareCreatureTypes(input, game)) {
return false;
}
}
return true;
}
}

View file

@ -0,0 +1,46 @@
package mage.cards.d;
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.MultipliedValue;
import mage.abilities.dynamicvalue.common.CardsInControllerHandCount;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class DemonicLore extends CardImpl {
private static final DynamicValue xValue = new MultipliedValue(CardsInControllerHandCount.instance, 2);
public DemonicLore(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}");
// When Demonic Lore enters the battlefield, draw three cards.
this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(3)));
// At the beginning of your end step, you lose 2 life for each card in your hand.
this.addAbility(new BeginningOfEndStepTriggeredAbility(
new LoseLifeSourceControllerEffect(xValue)
.setText("you lose 2 life for each card in your hand"),
TargetController.YOU, false
));
}
private DemonicLore(final DemonicLore card) {
super(card);
}
@Override
public DemonicLore copy() {
return new DemonicLore(this);
}
}

View file

@ -79,7 +79,7 @@ class DescendantsPathEffect extends OneShotEffect {
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent();
boolean found = false;
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) {
if (card.shareSubtypes(permanent, game)) {
if (card.shareCreatureTypes(permanent, game)) {
found = true;
break;
}

View file

@ -1,4 +1,3 @@
package mage.cards.d;
import mage.ObjectColor;
@ -11,7 +10,6 @@ import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
@ -27,13 +25,12 @@ import mage.target.common.TargetCardInHand;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class DisruptingShoal extends CardImpl {
public DisruptingShoal(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{U}{U}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{U}{U}");
this.subtype.add(SubType.ARCANE);
// You may exile a blue card with converted mana cost X from your hand rather than pay Disrupting Shoal's mana cost.
@ -86,16 +83,7 @@ class DisruptingShoalCounterTargetEffect extends OneShotEffect {
for (Cost cost : sourceAbility.getCosts()) {
if (cost.isPaid() && cost instanceof ExileFromHandCost) {
for (Card card : ((ExileFromHandCost) cost).getCards()) {
if (card instanceof SplitCard) {
if (((SplitCard) card).getLeftHalfCard().getConvertedManaCost() == amount) {
return true;
}
if (((SplitCard) card).getRightHalfCard().getConvertedManaCost() == amount) {
return true;
}
} else if (card.getConvertedManaCost() == amount) {
return true;
}
return card.getConvertedManaCost() == amount;
}
return false;
}

View file

@ -1,8 +1,5 @@
package mage.cards.d;
import java.util.UUID;
import java.util.regex.Pattern;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
@ -11,18 +8,21 @@ import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.ModalDoubleFacesCard;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SpellAbilityType;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicate;
import mage.game.Game;
import mage.game.stack.Spell;
import mage.target.TargetPermanent;
import java.util.UUID;
import java.util.regex.Pattern;
/**
*
* @author L_J
*/
public final class DoubleHeader extends CardImpl {
@ -34,7 +34,7 @@ public final class DoubleHeader extends CardImpl {
}
public DoubleHeader(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}{U}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}");
this.subtype.add(SubType.DRAKE);
this.power = new MageInt(2);
@ -68,14 +68,16 @@ class DoubleHeaderPredicate implements Predicate<MageObject> {
public boolean apply(MageObject input, Game game) {
String name = input.getName();
if (input instanceof SplitCard) {
return hasTwoWords(((SplitCard)input).getLeftHalfCard().getName()) || hasTwoWords(((SplitCard)input).getRightHalfCard().getName());
} else if (input instanceof Spell && ((Spell) input).getSpellAbility().getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED){
SplitCard card = (SplitCard) ((Spell)input).getCard();
return hasTwoWords(((SplitCard) input).getLeftHalfCard().getName()) || hasTwoWords(((SplitCard) input).getRightHalfCard().getName());
} else if (input instanceof ModalDoubleFacesCard) {
return hasTwoWords(((ModalDoubleFacesCard) input).getLeftHalfCard().getName()) || hasTwoWords(((ModalDoubleFacesCard) input).getRightHalfCard().getName());
} else if (input instanceof Spell && ((Spell) input).getSpellAbility().getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED) {
SplitCard card = (SplitCard) ((Spell) input).getCard();
return hasTwoWords(card.getLeftHalfCard().getName()) || hasTwoWords(card.getRightHalfCard().getName());
} else {
if (name.contains(" // ")) {
String leftName = name.substring(0, name.indexOf(" // "));
String rightName = name.substring(name.indexOf(" // ") + 4, name.length());
String rightName = name.substring(name.indexOf(" // ") + 4);
return hasTwoWords(leftName) || hasTwoWords(rightName);
} else {
return hasTwoWords(name);

View file

@ -1,20 +1,31 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.keyword.ChangelingAbility;
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.InfoEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
import java.util.UUID;
/**
*
* @author vereena42 & L_J
*/
public final class DrJuliusJumblemorph extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("a host");
static {
filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, -1));
}
public DrJuliusJumblemorph(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{W}");
this.addSuperType(SuperType.LEGENDARY);
@ -22,10 +33,17 @@ public final class DrJuliusJumblemorph extends CardImpl {
this.toughness = new MageInt(4);
// Dr. Julius Jumblemorph is every creature type (even if this card isn't on the battlefield).
this.addAbility(ChangelingAbility.getInstance());
this.setIsAllCreatureTypes(true);
this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect(
"{this} is every creature type <i>(even if this card isn't on the battlefield)</i>."
)));
// Whenever a host enters the battlefield under your control, you may search your library and/or graveyard for a card with augment and combine it with that host. If you search your library this way, shuffle it.
// TODO: Host currently isn't implemented, so this ability currently would never trigger
this.addAbility(new EntersBattlefieldControlledTriggeredAbility(
new InfoEffect("you may search your library and/or graveyard for a card with augment " +
"and combine it with that host. If you search your library this way, shuffle it."), filter
));
}
public DrJuliusJumblemorph(final DrJuliusJumblemorph card) {

View file

@ -48,7 +48,7 @@ public final class Dragonshift extends CardImpl {
.withColor("UR")
.withSubType(SubType.DRAGON)
.withAbility(FlyingAbility.getInstance()),
null, filter, Duration.EndOfTurn, true));
null, filter, Duration.EndOfTurn, true, false, true));
this.addAbility(ability);
}

View file

@ -1,7 +1,6 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -19,14 +18,15 @@ import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*/
public final class DragonsoulKnight extends CardImpl {
public DragonsoulKnight(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.KNIGHT);
@ -37,12 +37,12 @@ public final class DragonsoulKnight extends CardImpl {
this.addAbility(FirstStrikeAbility.getInstance());
// {W}{U}{B}{R}{G}: Until end of turn, Dragonsoul Knight becomes a Dragon, gets +5/+3, and gains flying and trample.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DragonsoulKnightEffect(), new ManaCostsImpl("{W}{U}{B}{R}{G}"));
Ability ability = new SimpleActivatedAbility(new DragonsoulKnightEffect(), new ManaCostsImpl("{W}{U}{B}{R}{G}"));
Effect effect = new BoostSourceEffect(5, 3, Duration.EndOfTurn);
effect.setText("gets +5/+3");
effect.setText(", gets +5/+3");
ability.addEffect(effect);
effect = new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn);
effect.setText("and gains flying");
effect.setText(", and gains flying");
ability.addEffect(effect);
effect = new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.EndOfTurn);
effect.setText("and trample");
@ -60,14 +60,14 @@ public final class DragonsoulKnight extends CardImpl {
return new DragonsoulKnight(this);
}
private class DragonsoulKnightEffect extends ContinuousEffectImpl {
private static class DragonsoulKnightEffect extends ContinuousEffectImpl {
public DragonsoulKnightEffect() {
super(Duration.EndOfTurn, Outcome.BecomeCreature);
setText();
private DragonsoulKnightEffect() {
super(Duration.EndOfTurn, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature);
staticText = "Until end of turn, {this} becomes a Dragon";
}
public DragonsoulKnightEffect(final DragonsoulKnightEffect effect) {
private DragonsoulKnightEffect(final DragonsoulKnightEffect effect) {
super(effect);
}
@ -77,34 +77,14 @@ public final class DragonsoulKnight extends CardImpl {
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent == null) {
return false;
}
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
permanent.getSubtype(game).clear();
permanent.getSubtype(game).add(SubType.DRAGON);
}
break;
}
permanent.removeAllCreatureTypes(game);
permanent.addSubType(game, SubType.DRAGON);
return true;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
private void setText() {
staticText = "Until end of turn, {this} becomes a Dragon, ";
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.TypeChangingEffects_4;
}
}
}

View file

@ -16,7 +16,6 @@ import mage.game.permanent.Permanent;
import java.util.UUID;
/**
*
* @author brikr
*/
public final class DralnusCrusade extends CardImpl {
@ -53,9 +52,7 @@ class DralnusCrusadeEffect extends ContinuousEffectImpl {
for (Permanent permanent : game.getState().getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE_GOBLINS, source.getControllerId(), source.getSourceId(), game)) {
switch (layer) {
case TypeChangingEffects_4:
if (!permanent.hasSubtype(SubType.ZOMBIE, game)) {
permanent.getSubtype(game).add(SubType.ZOMBIE);
}
permanent.addSubType(game, SubType.ZOMBIE);
break;
case ColorChangingEffects_5:
permanent.getColor(game).setColor(ObjectColor.BLACK);

View file

@ -123,9 +123,7 @@ class DranaTheLastBloodchiefSubtypeEffect extends ContinuousEffectImpl {
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Permanent creature = mor.getPermanent(game);
if (creature != null) {
if (!creature.hasSubtype(SubType.VAMPIRE, game)) {
creature.getSubtype(game).add(SubType.VAMPIRE);
}
creature.addSubType(game, SubType.VAMPIRE);
return true;
} else {
this.used = true;

View file

@ -26,6 +26,7 @@ public final class EgoErasure extends CardImpl {
this.subtype.add(SubType.SHAPESHIFTER);
// Changeling
this.setIsAllCreatureTypes(true);
this.addAbility(ChangelingAbility.getInstance());
//Creatures target player controls get -2/+0 and lose all creature types until end of turn.
@ -76,7 +77,7 @@ class EgoErasureLoseEffect extends ContinuousEffectImpl {
for (Iterator<MageObjectReference> it = affectedObjectList.iterator(); it.hasNext(); ) {
Permanent permanent = it.next().getPermanent(game);
if (permanent != null) {
permanent.getSubtype(game).retainAll(SubType.getLandTypes());
permanent.removeAllCreatureTypes(game);
} else {
it.remove();
}

View file

@ -0,0 +1,86 @@
package mage.cards.e;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.PartnerAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class EligethCrossroadsAugur extends CardImpl {
public EligethCrossroadsAugur(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}{U}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.SPHINX);
this.power = new MageInt(5);
this.toughness = new MageInt(6);
// Flying
this.addAbility(FlyingAbility.getInstance());
// If you would scry a number of cards, draw that many cards instead.
this.addAbility(new SimpleStaticAbility(new EligethCrossroadsAugurReplacementEffect()));
// Partner
this.addAbility(PartnerAbility.getInstance());
}
private EligethCrossroadsAugur(final EligethCrossroadsAugur card) {
super(card);
}
@Override
public EligethCrossroadsAugur copy() {
return new EligethCrossroadsAugur(this);
}
}
class EligethCrossroadsAugurReplacementEffect extends ReplacementEffectImpl {
EligethCrossroadsAugurReplacementEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit);
staticText = "If you would scry a number of cards, draw that many cards instead.";
}
private EligethCrossroadsAugurReplacementEffect(final EligethCrossroadsAugurReplacementEffect effect) {
super(effect);
}
@Override
public EligethCrossroadsAugurReplacementEffect copy() {
return new EligethCrossroadsAugurReplacementEffect(this);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SURVEIL;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return source.isControlledBy(event.getPlayerId());
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
player.drawCards(event.getAmount(), event.getSourceId(), game);
return true;
}
}

View file

@ -1,8 +1,5 @@
package mage.cards.e;
import java.util.Iterator;
import java.util.UUID;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -17,14 +14,15 @@ import mage.cards.CardSetInfo;
import mage.choices.Choice;
import mage.choices.ChoiceBasicLandType;
import mage.constants.*;
import mage.filter.common.FilterControlledLandPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import java.util.Iterator;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*/
public final class ElsewhereFlask extends CardImpl {
@ -36,7 +34,7 @@ public final class ElsewhereFlask extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)));
// Sacrifice Elsewhere Flask: Choose a basic land type. Each land you control becomes that type until end of turn.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ElsewhereFlaskEffect(), new SacrificeSourceCost()));
this.addAbility(new SimpleActivatedAbility(new ElsewhereFlaskEffect(), new SacrificeSourceCost()));
}
public ElsewhereFlask(final ElsewhereFlask card) {
@ -80,13 +78,11 @@ class ElsewhereFlaskEffect extends OneShotEffect {
class ElsewhereFlaskContinuousEffect extends ContinuousEffectImpl {
private static final FilterControlledPermanent filter = new FilterControlledLandPermanent();
public ElsewhereFlaskContinuousEffect() {
super(Duration.EndOfTurn, Outcome.Neutral);
ElsewhereFlaskContinuousEffect() {
super(Duration.EndOfTurn, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral);
}
public ElsewhereFlaskContinuousEffect(final ElsewhereFlaskContinuousEffect effect) {
private ElsewhereFlaskContinuousEffect(final ElsewhereFlaskContinuousEffect effect) {
super(effect);
}
@ -98,64 +94,68 @@ class ElsewhereFlaskContinuousEffect extends ContinuousEffectImpl {
@Override
public void init(Ability source, Game game) {
super.init(source, game);
if (this.affectedObjectsSet) {
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) {
affectedObjectList.add(new MageObjectReference(permanent, game));
}
}
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
SubType choice = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + "_ElsewhereFlask"));
if (choice != null) {
for (Iterator<MageObjectReference> it = affectedObjectList.iterator(); it.hasNext();) {
Permanent land = it.next().getPermanent(game);
if (land != null) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
land.getSubtype(game).clear();
land.getSubtype(game).add(choice);
}
break;
case AbilityAddingRemovingEffects_6:
if (sublayer == SubLayer.NA) {
land.getAbilities().clear();
if (choice.equals(SubType.FOREST)) {
land.addAbility(new GreenManaAbility(), source.getSourceId(), game);
}
if (choice.equals(SubType.PLAINS)) {
land.addAbility(new WhiteManaAbility(), source.getSourceId(), game);
}
if (choice.equals(SubType.MOUNTAIN)) {
land.addAbility(new RedManaAbility(), source.getSourceId(), game);
}
if (choice.equals(SubType.ISLAND)) {
land.addAbility(new BlueManaAbility(), source.getSourceId(), game);
}
if (choice.equals(SubType.SWAMP)) {
land.addAbility(new BlackManaAbility(), source.getSourceId(), game);
}
}
break;
}
} else {
it.remove();
}
}
return true;
switch (choice) {
case FOREST:
dependencyTypes.add(DependencyType.BecomeForest);
break;
case PLAINS:
dependencyTypes.add(DependencyType.BecomePlains);
break;
case MOUNTAIN:
dependencyTypes.add(DependencyType.BecomeMountain);
break;
case ISLAND:
dependencyTypes.add(DependencyType.BecomeIsland);
break;
case SWAMP:
dependencyTypes.add(DependencyType.BecomeSwamp);
break;
}
if (this.affectedObjectsSet) {
game.getBattlefield()
.getActivePermanents(
StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND,
source.getControllerId(), source.getSourceId(), game
).stream()
.map(permanent -> new MageObjectReference(permanent, game))
.forEach(affectedObjectList::add);
}
return false;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4;
SubType choice = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + "_ElsewhereFlask"));
if (choice == null) {
return false;
}
for (Iterator<MageObjectReference> it = affectedObjectList.iterator(); it.hasNext(); ) {
Permanent land = it.next().getPermanent(game);
if (land == null) {
it.remove();
continue;
}
land.getSubtype(game).removeAll(SubType.getLandTypes());
land.addSubType(game, choice);
land.removeAllAbilities(source.getSourceId(), game);
switch (choice) {
case FOREST:
land.addAbility(new GreenManaAbility(), source.getSourceId(), game);
break;
case PLAINS:
land.addAbility(new WhiteManaAbility(), source.getSourceId(), game);
break;
case MOUNTAIN:
land.addAbility(new RedManaAbility(), source.getSourceId(), game);
break;
case ISLAND:
land.addAbility(new BlueManaAbility(), source.getSourceId(), game);
break;
case SWAMP:
land.addAbility(new BlackManaAbility(), source.getSourceId(), game);
break;
}
}
return true;
}
}

View file

@ -0,0 +1,107 @@
package mage.cards.e;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.BecomesMonarchSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class EmberwildeCaptain extends CardImpl {
public EmberwildeCaptain(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
this.subtype.add(SubType.DJINN);
this.subtype.add(SubType.PIRATE);
this.power = new MageInt(4);
this.toughness = new MageInt(2);
// When Emberwilde Captain enters the battlefield, you become the monarch.
this.addAbility(new EntersBattlefieldTriggeredAbility(new BecomesMonarchSourceEffect()));
// Whenever an opponent attacks you while you're the monarch, Emberwilde Captain deals damage to that player equal to the number of cards in their hand.
this.addAbility(new EmberwildeCaptainTriggeredAbility());
}
private EmberwildeCaptain(final EmberwildeCaptain card) {
super(card);
}
@Override
public EmberwildeCaptain copy() {
return new EmberwildeCaptain(this);
}
}
class EmberwildeCaptainTriggeredAbility extends TriggeredAbilityImpl {
public EmberwildeCaptainTriggeredAbility() {
super(Zone.BATTLEFIELD, new EmberwildeCaptainEffect(), false);
}
public EmberwildeCaptainTriggeredAbility(final EmberwildeCaptainTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return game.getCombat().getDefenders().contains(getControllerId())
&& getSourceId().equals(game.getMonarchId());
}
@Override
public String getRule() {
return "Whenever an opponent attacks you while you're the monarch, " +
"{this} deals damage to that player equal to the number of cards in their hand.";
}
@Override
public EmberwildeCaptainTriggeredAbility copy() {
return new EmberwildeCaptainTriggeredAbility(this);
}
}
class EmberwildeCaptainEffect extends OneShotEffect {
EmberwildeCaptainEffect() {
super(Outcome.Benefit);
}
private EmberwildeCaptainEffect(final EmberwildeCaptainEffect effect) {
super(effect);
}
@Override
public EmberwildeCaptainEffect copy() {
return new EmberwildeCaptainEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(game.getActivePlayerId());
if (player == null || player.getHand().size() < 1) {
return false;
}
return player.damage(player.getHand().size(), source.getSourceId(), game) > 0;
}
}

View file

@ -1,42 +0,0 @@
package mage.cards.e;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.effects.common.TapSourceUnlessPaysEffect;
import mage.abilities.mana.WhiteManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class EmeriaShatteredSkyclave extends CardImpl {
public EmeriaShatteredSkyclave(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
this.modalDFC = true;
this.nightCard = true;
// As Emeria, Shattered Skyclave enters the battlefield, you may pay 3 life. If you don't, it enters the battlefield tapped.
this.addAbility(new AsEntersBattlefieldAbility(
new TapSourceUnlessPaysEffect(new PayLifeCost(3)),
"you may pay 3 life. If you don't, it enters the battlefield tapped"
));
// {T}: Add {W}.
this.addAbility(new WhiteManaAbility());
}
private EmeriaShatteredSkyclave(final EmeriaShatteredSkyclave card) {
super(card);
}
@Override
public EmeriaShatteredSkyclave copy() {
return new EmeriaShatteredSkyclave(this);
}
}

View file

@ -1,10 +1,14 @@
package mage.cards.e;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.TapSourceUnlessPaysEffect;
import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
import mage.abilities.keyword.IndestructibleAbility;
import mage.cards.CardImpl;
import mage.abilities.mana.WhiteManaAbility;
import mage.cards.CardSetInfo;
import mage.cards.ModalDoubleFacesCard;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
@ -16,9 +20,9 @@ import mage.game.permanent.token.AngelWarriorToken;
import java.util.UUID;
/**
* @author TheElk801
* @author JayDi85
*/
public final class EmeriasCall extends CardImpl {
public final class EmeriasCall extends ModalDoubleFacesCard {
private static final FilterPermanent filter
= new FilterControlledCreaturePermanent("Non-Angel creatures you control");
@ -28,14 +32,34 @@ public final class EmeriasCall extends CardImpl {
}
public EmeriasCall(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{W}{W}{W}");
super(ownerId, setInfo,
new CardType[]{CardType.SORCERY}, new SubType[]{}, "{4}{W}{W}{W}",
"Emeria, Shattered Skyclave", new CardType[]{CardType.LAND}, new SubType[]{}, ""
);
// 1.
// Emeria's Call
// Sorcery
// Create two 4/4 white Angel Warrior creature tokens with flying. Non-Angel creatures you control gain indestructible until your next turn.
this.getSpellAbility().addEffect(new CreateTokenEffect(new AngelWarriorToken(), 2));
this.getSpellAbility().addEffect(new GainAbilityAllEffect(
this.getLeftHalfCard().getSpellAbility().addEffect(new CreateTokenEffect(new AngelWarriorToken(), 2));
this.getLeftHalfCard().getSpellAbility().addEffect(new GainAbilityAllEffect(
IndestructibleAbility.getInstance(),
Duration.UntilYourNextTurn, filter
));
// 2.
// Emeria, Shattered Skyclave
// Land
// As Emeria, Shattered Skyclave enters the battlefield, you may pay 3 life. If you don't, it enters the battlefield tapped.
this.getRightHalfCard().addAbility(new AsEntersBattlefieldAbility(
new TapSourceUnlessPaysEffect(new PayLifeCost(3)),
"you may pay 3 life. If you don't, it enters the battlefield tapped"
));
// {T}: Add {W}.
this.getRightHalfCard().addAbility(new WhiteManaAbility());
}
private EmeriasCall(final EmeriasCall card) {

View file

@ -1,19 +1,18 @@
package mage.cards.e;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.Effect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*/
public final class EnchantedEvening extends CardImpl {
@ -22,11 +21,7 @@ public final class EnchantedEvening extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W/U}{W/U}");
// All permanents are enchantments in addition to their other types.
Effect effect = new EnchangedEveningEffect(CardType.ENCHANTMENT,
Duration.WhileOnBattlefield, new FilterPermanent());
effect.setText("All permanents are enchantments in addition to their other types");
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
this.addAbility(new SimpleStaticAbility(new EnchangedEveningEffect()));
}
public EnchantedEvening(final EnchantedEvening card) {
@ -39,31 +34,27 @@ public final class EnchantedEvening extends CardImpl {
}
// need to be enclosed class for dependent check of continuous effects
static class EnchangedEveningEffect extends ContinuousEffectImpl {
private static class EnchangedEveningEffect extends ContinuousEffectImpl {
private final CardType addedCardType;
private final FilterPermanent filter;
public EnchangedEveningEffect(CardType addedCardType, Duration duration, FilterPermanent filter) {
super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit);
this.addedCardType = addedCardType;
this.filter = filter;
private EnchangedEveningEffect() {
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit);
this.dependencyTypes.add(DependencyType.EnchantmentAddingRemoving);
this.dependencyTypes.add(DependencyType.AuraAddingRemoving);
this.staticText = "All permanents are enchantments in addition to their other types";
}
public EnchangedEveningEffect(final EnchangedEveningEffect effect) {
private EnchangedEveningEffect(final EnchangedEveningEffect effect) {
super(effect);
this.addedCardType = effect.addedCardType;
this.filter = effect.filter;
}
@Override
public boolean apply(Game game, Ability source) {
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, game)) {
if (permanent != null
&& !permanent.getCardType().contains(addedCardType)) {
permanent.addCardType(addedCardType);
for (Permanent permanent : game.getBattlefield().getActivePermanents(
StaticFilters.FILTER_PERMANENT, source.getControllerId(),
source.getSourceId(), game
)) {
if (permanent != null) {
permanent.addCardType(CardType.ENCHANTMENT);
}
}
return true;

View file

@ -9,8 +9,8 @@ import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.costs.mana.VariableManaCost;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.mana.ManaEffect;
import mage.abilities.effects.common.discard.DiscardTargetEffect;
import mage.abilities.effects.mana.ManaEffect;
import mage.abilities.hint.common.MyTurnHint;
import mage.abilities.mana.ActivatedManaAbilityImpl;
import mage.cards.CardImpl;
@ -127,7 +127,7 @@ class ChimericStaffEffect extends ContinuousEffectImpl {
public ChimericStaffEffect() {
super(Duration.EndOfTurn, Outcome.BecomeCreature);
setText();
staticText = "{this} becomes an X/X Construct artifact creature until end of turn";
}
public ChimericStaffEffect(final ChimericStaffEffect effect) {
@ -142,26 +142,28 @@ class ChimericStaffEffect extends ContinuousEffectImpl {
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
permanent.addCardType(CardType.CREATURE);
permanent.getSubtype(game).add(SubType.CONSTRUCT);
}
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
int xValue = source.getManaCostsToPay().getX();
if (xValue != 0) {
permanent.getPower().setValue(xValue);
permanent.getToughness().setValue(xValue);
}
}
}
return true;
if (permanent == null) {
return false;
}
return false;
switch (layer) {
case TypeChangingEffects_4:
if (!permanent.isArtifact()) {
permanent.addCardType(CardType.ARTIFACT);
}
if (!permanent.isCreature()) {
permanent.addCardType(CardType.CREATURE);
}
permanent.removeAllCreatureTypes(game);
permanent.addSubType(game, SubType.CONSTRUCT);
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
int xValue = source.getManaCostsToPay().getX();
permanent.getPower().setValue(xValue);
permanent.getToughness().setValue(xValue);
}
}
return true;
}
@Override
@ -169,10 +171,6 @@ class ChimericStaffEffect extends ContinuousEffectImpl {
return false;
}
private void setText() {
staticText = duration.toString() + " {this} becomes an X/X Construct artifact creature";
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.PTChangingEffects_7 || layer == Layer.TypeChangingEffects_4;

View file

@ -1,8 +1,5 @@
package mage.cards.e;
import java.util.UUID;
import mage.MageObject;
import mage.Mana;
import mage.abilities.Ability;
@ -13,14 +10,11 @@ import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.dynamicvalue.common.CreaturesYouControlCount;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.abilities.mana.SimpleManaAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
@ -35,24 +29,25 @@ import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetControlledPermanent;
import java.util.UUID;
/**
*
* @author Ketsuban
*/
public final class EverythingamajigE extends CardImpl {
public EverythingamajigE(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{5}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}");
// Zuran Orb
// Sacrifice a land: You gain 2 life.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainLifeEffect(2), new SacrificeTargetCost(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_LAND_SHORT_TEXT))));
// Ashnod's Altar
// Sacrifice a creature: Add {C}{C} to your mana pool.
SacrificeTargetCost cost = new SacrificeTargetCost(new TargetControlledCreaturePermanent(StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT));
this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD,
new BasicManaEffect(Mana.ColorlessMana(2), CreaturesYouControlCount.instance),
this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD,
new BasicManaEffect(Mana.ColorlessMana(2), CreaturesYouControlCount.instance),
cost));
// Urza's Hot Tub
@ -117,21 +112,23 @@ class UrzasHotTubPredicate implements Predicate<MageObject> {
public boolean apply(MageObject input, Game game) {
String name = input.getName();
if (input instanceof SplitCard) {
return sharesWordWithName(((SplitCard)input).getLeftHalfCard().getName()) || sharesWordWithName(((SplitCard)input).getRightHalfCard().getName());
} else if (input instanceof Spell && ((Spell) input).getSpellAbility().getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED){
SplitCard card = (SplitCard) ((Spell)input).getCard();
return sharesWordWithName(((SplitCard) input).getLeftHalfCard().getName()) || sharesWordWithName(((SplitCard) input).getRightHalfCard().getName());
} else if (input instanceof ModalDoubleFacesCard) {
return sharesWordWithName(((ModalDoubleFacesCard) input).getLeftHalfCard().getName()) || sharesWordWithName(((ModalDoubleFacesCard) input).getRightHalfCard().getName());
} else if (input instanceof Spell && ((Spell) input).getSpellAbility().getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED) {
SplitCard card = (SplitCard) ((Spell) input).getCard();
return sharesWordWithName(card.getLeftHalfCard().getName()) || sharesWordWithName(card.getRightHalfCard().getName());
} else {
if (name.contains(" // ")) {
String leftName = name.substring(0, name.indexOf(" // "));
String rightName = name.substring(name.indexOf(" // ") + 4, name.length());
String rightName = name.substring(name.indexOf(" // ") + 4);
return sharesWordWithName(leftName) || sharesWordWithName(rightName);
} else {
return sharesWordWithName(name);
}
}
}
private boolean sharesWordWithName(String str) {
if (referenceName == null || referenceName.equals("")) {
return false;

View file

@ -0,0 +1,44 @@
package mage.cards.e;
import mage.MageInt;
import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.EncoreAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.game.permanent.token.ElfToken;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class ExquisiteHuntmaster extends CardImpl {
public ExquisiteHuntmaster(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
this.subtype.add(SubType.ELF);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(4);
this.toughness = new MageInt(2);
// When Exquisite Huntmaster dies, create a 1/1 green Elf Warrior creature token.
this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new ElfToken())));
// Encore {4}{B}
this.addAbility(new EncoreAbility(new ManaCostsImpl<>("{4}{B}")));
}
private ExquisiteHuntmaster(final ExquisiteHuntmaster card) {
super(card);
}
@Override
public ExquisiteHuntmaster copy() {
return new ExquisiteHuntmaster(this);
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.e;
import java.util.List;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
@ -9,7 +7,6 @@ import mage.abilities.keyword.SplitSecondAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SuperType;
@ -22,19 +19,22 @@ import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInGraveyard;
import mage.target.common.TargetCardInLibrary;
import mage.util.CardUtil;
import java.util.List;
import java.util.UUID;
/**
*
* @author jonubuu
*/
public final class Extirpate extends CardImpl {
private static final FilterCard filter = new FilterCard("card in a graveyard other than a basic land card");
static {
filter.add(Predicates.not(Predicates.and(CardType.LAND.getPredicate(), SuperType.BASIC.getPredicate())));
}
public Extirpate(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}");
@ -46,11 +46,11 @@ public final class Extirpate extends CardImpl {
this.getSpellAbility().addEffect(new ExtirpateEffect());
this.getSpellAbility().addTarget(new TargetCardInGraveyard(filter));
}
public Extirpate(final Extirpate card) {
super(card);
}
@Override
public Extirpate copy() {
return new Extirpate(this);
@ -58,7 +58,7 @@ public final class Extirpate extends CardImpl {
}
class ExtirpateEffect extends OneShotEffect {
public ExtirpateEffect() {
super(Outcome.Exile);
this.staticText = "Choose target card in a graveyard other than "
@ -66,16 +66,16 @@ class ExtirpateEffect extends OneShotEffect {
+ "and library for any number of cards with the same name "
+ "as that card and exile them. Then that player shuffles their library";
}
public ExtirpateEffect(final ExtirpateEffect effect) {
super(effect);
}
@Override
public ExtirpateEffect copy() {
return new ExtirpateEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
@ -90,7 +90,7 @@ class ExtirpateEffect extends OneShotEffect {
// Exile all cards with the same name
// Building a card filter with the name
FilterCard filterNamedCard = new FilterCard();
String nameToSearch = chosenCard.isSplitCard() ? ((SplitCard) chosenCard).getLeftHalfCard().getName() : chosenCard.getName();
String nameToSearch = CardUtil.getCardNameForSameNameSearch(chosenCard);
filterNamedCard.add(new NamePredicate(nameToSearch));
// The cards you're searching for must be found and exiled if they're in the graveyard because it's a public zone.
@ -133,5 +133,5 @@ class ExtirpateEffect extends OneShotEffect {
}
return false;
}
}

View file

@ -1,5 +1,6 @@
package mage.cards.e;
import mage.ApprovingObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
@ -21,7 +22,6 @@ import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author spjspj
@ -127,9 +127,12 @@ class EyeOfTheStormEffect1 extends OneShotEffect {
// Check if owner of card is still in game
card = game.getCard(uuid);
if (card != null && game.getPlayer(card.getOwnerId()) != null) {
if (card.isSplitCard()) {
if (card instanceof SplitCard) {
copiedCards.add(((SplitCard) card).getLeftHalfCard());
copiedCards.add(((SplitCard) card).getRightHalfCard());
} else if (card instanceof ModalDoubleFacesCard) {
copiedCards.add(((ModalDoubleFacesCard) card).getLeftHalfCard());
copiedCards.add(((ModalDoubleFacesCard) card).getRightHalfCard());
} else {
copiedCards.add(card);
}

View file

@ -0,0 +1,43 @@
package mage.cards.e;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.MillCardsControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.game.permanent.token.ElfToken;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class EyeblightCullers extends CardImpl {
public EyeblightCullers(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}");
this.subtype.add(SubType.ELF);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// When Eyeblight Cullers dies, create three 1/1 green Elf Warrior creature tokens, then mill three cards.
Ability ability = new DiesSourceTriggeredAbility(new CreateTokenEffect(new ElfToken(), 3));
ability.addEffect(new MillCardsControllerEffect(3).concatBy(", then"));
this.addAbility(ability);
}
private EyeblightCullers(final EyeblightCullers card) {
super(card);
}
@Override
public EyeblightCullers copy() {
return new EyeblightCullers(this);
}
}

View file

@ -62,13 +62,13 @@ class FacesOfThePastEffect extends OneShotEffect {
if (controller != null) {
if (controller.chooseUse(outcome, "Tap all untapped creatures that share a creature type with " + targetPermanent.getLogName() + "? (Otherwise, untaps all tapped)", source, game)) {
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, game)) {
if (!permanent.isTapped() && targetPermanent.shareSubtypes(permanent, game)) {
if (!permanent.isTapped() && targetPermanent.shareCreatureTypes(permanent, game)) {
permanent.tap(game);
}
}
} else {
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, game)) {
if (permanent.isTapped() && targetPermanent.shareSubtypes(permanent, game)) {
if (permanent.isTapped() && targetPermanent.shareCreatureTypes(permanent, game)) {
permanent.untap(game);
}
}

View file

@ -0,0 +1,69 @@
package mage.cards.f;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.Condition;
import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.BecomesMonarchSourceEffect;
import mage.abilities.effects.common.DontUntapInControllersUntapStepEnchantedEffect;
import mage.abilities.effects.common.TapEnchantedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.game.Game;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class FallFromFavor extends CardImpl {
public FallFromFavor(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}");
this.subtype.add(SubType.AURA);
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// When Fall from Favor enters the battlefield, tap enchanted creature and you become the monarch.
ability = new EntersBattlefieldTriggeredAbility(new TapEnchantedEffect());
ability.addEffect(new BecomesMonarchSourceEffect().concatBy("and"));
this.addAbility(ability);
// Enchanted creature doesn't untap during its controller's untap step unless that player is the monarch.
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousRuleModifyingEffect(
new DontUntapInControllersUntapStepEnchantedEffect(), FallFromFavorCondition.instance
).setText("enchanted creature doesn't untap during its controller's untap step unless that player is the monarch")));
}
private FallFromFavor(final FallFromFavor card) {
super(card);
}
@Override
public FallFromFavor copy() {
return new FallFromFavor(this);
}
}
enum FallFromFavorCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
return game.getActivePlayerId().equals(game.getActivePlayerId());
}
}

View file

@ -27,6 +27,7 @@ public final class FireBellyChangeling extends CardImpl {
this.toughness = new MageInt(1);
// Changeling
this.setIsAllCreatureTypes(true);
this.addAbility(ChangelingAbility.getInstance());
// {R}: Fire-Belly Changeling gets +1/+0 until end of turn. Activate this ability no more than twice each turn.

View file

@ -62,7 +62,7 @@ class ScryTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.SCRY;
return event.getType() == EventType.SCRIED;
}
@Override

View file

@ -30,7 +30,7 @@ public final class ForceOfDespair extends CardImpl {
static {
filter.add(new ColorPredicate(ObjectColor.BLACK));
filter2.add(new EnteredThisTurnPredicate());
filter2.add(EnteredThisTurnPredicate.instance);
}
public ForceOfDespair(UUID ownerId, CardSetInfo setInfo) {

View file

@ -0,0 +1,36 @@
package mage.cards.f;
import mage.abilities.effects.common.CounterTargetEffect;
import mage.abilities.keyword.CascadeAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.TargetSpell;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class ForcefulDenial extends CardImpl {
public ForcefulDenial(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{U}{U}");
// Cascade
this.addAbility(new CascadeAbility());
// Counter target spell.
this.getSpellAbility().addEffect(new CounterTargetEffect());
this.getSpellAbility().addTarget(new TargetSpell());
}
private ForcefulDenial(final ForcefulDenial card) {
super(card);
}
@Override
public ForcefulDenial copy() {
return new ForcefulDenial(this);
}
}

View file

@ -30,7 +30,7 @@ public final class ForgeOfHeroes extends CardImpl {
static {
filter.add(CommanderPredicate.instance);
filter.add(new EnteredThisTurnPredicate());
filter.add(EnteredThisTurnPredicate.instance);
}
public ForgeOfHeroes(UUID ownerId, CardSetInfo setInfo) {

View file

@ -22,6 +22,7 @@ public final class GameTrailChangeling extends CardImpl {
this.power = new MageInt(4);
this.toughness = new MageInt(4);
this.setIsAllCreatureTypes(true);
this.addAbility(ChangelingAbility.getInstance());
this.addAbility(TrampleAbility.getInstance());
}

View file

@ -0,0 +1,61 @@
package mage.cards.g;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.FilterCard;
import mage.filter.common.FilterControlledEnchantmentPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.common.FilterEnchantmentCard;
import mage.target.common.TargetCardInYourGraveyard;
import mage.target.common.TargetControlledPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class GhenArcanumWeaver extends CardImpl {
private static final FilterControlledPermanent filter
= new FilterControlledEnchantmentPermanent("an enchantment");
private static final FilterCard filter2
= new FilterEnchantmentCard("enchantment card from your graveyard");
public GhenArcanumWeaver(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{W}{B}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WIZARD);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// {R}{W}{B}, {T}, Sacrifice an enchantment: Return target enchantment card from your graveyard to the battlefield.
Ability ability = new SimpleActivatedAbility(
new ReturnFromGraveyardToBattlefieldTargetEffect(), new ManaCostsImpl("{R}{W}{B}")
);
ability.addCost(new TapSourceCost());
ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter)));
ability.addTarget(new TargetCardInYourGraveyard(filter2));
this.addAbility(ability);
}
private GhenArcanumWeaver(final GhenArcanumWeaver card) {
super(card);
}
@Override
public GhenArcanumWeaver copy() {
return new GhenArcanumWeaver(this);
}
}

View file

@ -0,0 +1,125 @@
package mage.cards.g;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.common.SimpleEvasionAbility;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect;
import mage.abilities.keyword.PartnerAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicate;
import mage.filter.predicate.mageobject.ToughnessPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.target.common.TargetCardInGraveyard;
import mage.watchers.Watcher;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class GhostOfRamirezDePietro extends CardImpl {
private static final FilterCreaturePermanent filter
= new FilterCreaturePermanent("creatures with toughness 3 or greater");
private static final FilterCard filter2
= new FilterCard("card in a graveyard that was discarded or put there from a library this turn");
static {
filter.add(new ToughnessPredicate(ComparisonType.MORE_THAN, 2));
filter2.add(GhostOfRamirezDePietroPredicate.instance);
}
public GhostOfRamirezDePietro(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.PIRATE);
this.subtype.add(SubType.SPIRIT);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// Ghost of Ramirez DePietro can't be blocked by creatures with toughness 3 or greater.
this.addAbility(new SimpleEvasionAbility(
new CantBeBlockedByCreaturesSourceEffect(filter, Duration.WhileOnBattlefield)
));
// Whenever Ghost of Ramirez DePietro deals combat damage to a player, choose up to one target card in a graveyard that was discarded or put there from a library this turn. Put that card into its owner's hand.
Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(
new ReturnFromGraveyardToHandTargetEffect()
.setText("choose up to one target card in a graveyard that was discarded " +
"or put there from a library this turn. Put that card into its owner's hand"),
false
);
ability.addTarget(new TargetCardInGraveyard(filter2));
this.addAbility(ability, new GhostOfRamirezDePietroWatcher());
// Partner
this.addAbility(PartnerAbility.getInstance());
}
private GhostOfRamirezDePietro(final GhostOfRamirezDePietro card) {
super(card);
}
@Override
public GhostOfRamirezDePietro copy() {
return new GhostOfRamirezDePietro(this);
}
}
enum GhostOfRamirezDePietroPredicate implements Predicate<Card> {
instance;
@Override
public boolean apply(Card input, Game game) {
GhostOfRamirezDePietroWatcher watcher = game.getState().getWatcher(GhostOfRamirezDePietroWatcher.class);
return watcher != null && watcher.checkCard(input, game);
}
}
class GhostOfRamirezDePietroWatcher extends Watcher {
private final Set<MageObjectReference> morSet = new HashSet<>();
GhostOfRamirezDePietroWatcher() {
super(WatcherScope.GAME);
}
@Override
public void watch(GameEvent event, Game game) {
switch (event.getType()) {
case ZONE_CHANGE:
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.getFromZone() != Zone.LIBRARY
|| zEvent.getToZone() != Zone.GRAVEYARD) {
break;
}
case DISCARDED_CARD:
morSet.add(new MageObjectReference(event.getTargetId(), game));
default:
break;
}
}
@Override
public void reset() {
super.reset();
morSet.clear();
}
boolean checkCard(Card card, Game game) {
return morSet.stream().anyMatch(mor -> mor.refersTo(card, game));
}
}

Some files were not shown because too many files have changed in this diff Show more