mirror of
https://github.com/correl/mage.git
synced 2025-01-11 19:13:02 +00:00
Reworking effects which allow casting spells from a selection of cards (ready for review) (#8136)
* added function for casting spells with specific attributes from a selection of cards * updated cascade to use new method * refactored various cards to use new methods * added TestPlayer method * fixed a small error * text fix * broke out some repeated code * added missing notTarget setting * add additional retain zone check * some more cards refactored * more refactoring * added interface for split/modal cards * reworked spell casting methods * reworked multiple cast to prevent unnecessary dialogs * fixed test failures due to change in functionality * add AI code * small nonfunctional change * reworked Kaya, the Inexorable * added currently failing test * added more tests * updated Geode Golem implementation * fixed adventure/cascade interaction, added/updated tests * some nonfunctional refactoring * added interface for subcards * [AFC] Implemented Fevered Suspicion * [AFC] Implemented Extract Brain * [AFC] updated Arcane Endeavor implementation * [C17] reworked implementation of Izzet Chemister * [ZEN] reworked implemented of Chandra Ablaze * additional merge fix * [SLD] updated Eleven, the Mage * [NEO] Implemented Discover the Impossible * [NEO] Implemented The Dragon-Kami Reborn / Dragon-Kami's Egg * [NEO] Implemented Invoke Calamity * [AFR] Implemented Rod of Absorption * [VOC] Implemented Spectral Arcanist * [VOC] added additional printings * [NEO] added all variants * [SLD] updated implementation of Ken, Burning Brawler
This commit is contained in:
parent
7fb089db48
commit
bbb9382150
83 changed files with 2551 additions and 2059 deletions
|
@ -2986,7 +2986,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
|
||||
@Override
|
||||
public SpellAbility chooseAbilityForCast(Card card, Game game, boolean noMana) {
|
||||
Map<UUID, ActivatedAbility> useable = PlayerImpl.getCastableSpellAbilities(game, this.getId(), card, game.getState().getZone(card.getId()), noMana);
|
||||
Map<UUID, SpellAbility> useable = PlayerImpl.getCastableSpellAbilities(game, this.getId(), card, game.getState().getZone(card.getId()), noMana);
|
||||
return (SpellAbility) useable.values().stream().findFirst().orElse(null);
|
||||
}
|
||||
|
||||
|
|
|
@ -2185,10 +2185,10 @@ public class HumanPlayer extends PlayerImpl {
|
|||
MageObject object = game.getObject(card.getId()); // must be object to find real abilities (example: commander)
|
||||
if (object != null) {
|
||||
String message = "Choose ability to cast" + (noMana ? " for FREE" : "") + "<br>" + object.getLogName();
|
||||
LinkedHashMap<UUID, ActivatedAbility> useableAbilities = PlayerImpl.getCastableSpellAbilities(game, playerId, object, game.getState().getZone(object.getId()), noMana);
|
||||
LinkedHashMap<UUID, SpellAbility> useableAbilities = PlayerImpl.getCastableSpellAbilities(game, playerId, object, game.getState().getZone(object.getId()), noMana);
|
||||
if (useableAbilities != null
|
||||
&& useableAbilities.size() == 1) {
|
||||
return (SpellAbility) useableAbilities.values().iterator().next();
|
||||
return useableAbilities.values().iterator().next();
|
||||
} else if (useableAbilities != null
|
||||
&& !useableAbilities.isEmpty()) {
|
||||
|
||||
|
@ -2202,7 +2202,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
UUID responseId = getFixedResponseUUID(game);
|
||||
if (responseId != null) {
|
||||
if (useableAbilities.containsKey(responseId)) {
|
||||
return (SpellAbility) useableAbilities.get(responseId);
|
||||
return useableAbilities.get(responseId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
|
@ -10,20 +7,22 @@ import mage.abilities.costs.common.PayEnergyCost;
|
|||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect;
|
||||
import mage.cards.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.common.FilterNonlandCard;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author emerald000
|
||||
*/
|
||||
public final class AetherworksMarvel extends CardImpl {
|
||||
|
@ -35,13 +34,13 @@ public final class AetherworksMarvel extends CardImpl {
|
|||
// Whenever a permanent you control is put into a graveyard, you get {E}.
|
||||
this.addAbility(new PutIntoGraveFromBattlefieldAllTriggeredAbility(
|
||||
new GetEnergyCountersControllerEffect(1), false,
|
||||
new FilterControlledPermanent("a permanent you control"), false));
|
||||
StaticFilters.FILTER_CONTROLLED_A_PERMANENT, false
|
||||
));
|
||||
|
||||
// {T}, Pay {E}{E}{E}{E}{E}{E}: Look at the top six cards of your library.
|
||||
// You may cast a card from among them without paying its mana cost.
|
||||
// Put the rest on the bottom of your library in a random order.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
||||
new AetherworksMarvelEffect(), new TapSourceCost());
|
||||
Ability ability = new SimpleActivatedAbility(new AetherworksMarvelEffect(), new TapSourceCost());
|
||||
ability.addCost(new PayEnergyCost(6));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
@ -78,26 +77,13 @@ class AetherworksMarvelEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Set<Card> cardsSet = controller.getLibrary().getTopCards(game, 6);
|
||||
Cards cards = new CardsImpl(cardsSet);
|
||||
TargetCard target = new TargetCardInLibrary(0, 1,
|
||||
new FilterNonlandCard("card to cast without paying its mana cost"));
|
||||
if (controller.choose(Outcome.PlayForFree, cards, target, game)) {
|
||||
Card card = controller.getLibrary().getCard(target.getFirstTarget(), game);
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
if (cardWasCast) {
|
||||
cards.remove(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
controller.putCardsOnBottomOfLibrary(cards, game, source, false);
|
||||
return true;
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 6));
|
||||
CardUtil.castSpellWithAttributesForFree(controller, source, game, cards, StaticFilters.FILTER_CARD);
|
||||
cards.retainZone(Zone.LIBRARY, game);
|
||||
controller.putCardsOnBottomOfLibrary(cards, game, source, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.cost.CastWithoutPayingManaCostEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterInstantOrSorceryCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
@ -40,10 +42,6 @@ public final class ArcaneEndeavor extends CardImpl {
|
|||
|
||||
class ArcaneEndeavorEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterCard filter = new FilterInstantOrSorceryCard(
|
||||
"instant or sorcery card with mana value %mv or less from your hand"
|
||||
);
|
||||
|
||||
ArcaneEndeavorEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "roll two d8 and choose one result. Draw cards equal to that result. " +
|
||||
|
@ -82,7 +80,9 @@ class ArcaneEndeavorEffect extends OneShotEffect {
|
|||
second = firstResult;
|
||||
}
|
||||
player.drawCards(first, source, game);
|
||||
new CastWithoutPayingManaCostEffect(StaticValue.get(second), filter).apply(game, source);
|
||||
FilterCard filter = new FilterInstantOrSorceryCard();
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, second + 1));
|
||||
CardUtil.castSpellWithAttributesForFree(player, source, game, new CardsImpl(player.getHand()), filter);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,23 +1,26 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.LoyaltyAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.card.FaceDownPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.token.AshiokNightmareMuseToken;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
import mage.target.common.TargetNonlandPermanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
|
@ -95,6 +98,7 @@ class AshiokNightmareMuseCastEffect extends OneShotEffect {
|
|||
|
||||
static {
|
||||
filter.add(TargetController.OPPONENT.getOwnerPredicate());
|
||||
filter.add(Predicates.not(FaceDownPredicate.instance));
|
||||
}
|
||||
|
||||
AshiokNightmareMuseCastEffect() {
|
||||
|
@ -117,25 +121,10 @@ class AshiokNightmareMuseCastEffect extends OneShotEffect {
|
|||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
TargetCardInExile target = new TargetCardInExile(0, 3, filter, null);
|
||||
target.setNotTarget(true);
|
||||
if (!controller.chooseTarget(outcome, target, source, game)) { // method is fine, controller is still choosing the card
|
||||
return false;
|
||||
}
|
||||
for (UUID targetId : target.getTargets()) {
|
||||
if (targetId != null) {
|
||||
Card chosenCard = game.getCard(targetId);
|
||||
if (chosenCard != null
|
||||
&& game.getState().getZone(chosenCard.getId()) == Zone.EXILED // must be exiled
|
||||
&& game.getOpponents(controller.getId()).contains(chosenCard.getOwnerId()) // must be owned by an opponent
|
||||
&& controller.chooseUse(outcome, "Cast " + chosenCard.getName() + " without paying its mana cost?", source, game)) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + chosenCard.getId(), Boolean.TRUE);
|
||||
controller.cast(controller.chooseAbilityForCast(chosenCard, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + chosenCard.getId(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
CardUtil.castMultipleWithAttributeForFree(
|
||||
controller, source, game, new CardsImpl(game.getExile().getCards(filter, game)),
|
||||
StaticFilters.FILTER_CARD, 3
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,27 +1,34 @@
|
|||
|
||||
package mage.cards.b;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.effects.common.ReturnToHandTargetEffect;
|
||||
import mage.abilities.effects.common.cost.CastWithoutPayingManaCostEffect;
|
||||
import mage.abilities.effects.common.cost.CastFromHandForFreeEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fireshoes
|
||||
*/
|
||||
public final class BaralsExpertise extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent("artifacts and/or creatures");
|
||||
private static final FilterCard filter2 = new FilterCard("a spell with mana value 4 or less");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.or(CardType.ARTIFACT.getPredicate(),
|
||||
CardType.CREATURE.getPredicate()));
|
||||
filter.add(Predicates.or(
|
||||
CardType.ARTIFACT.getPredicate(),
|
||||
CardType.CREATURE.getPredicate()
|
||||
));
|
||||
filter2.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 5));
|
||||
}
|
||||
|
||||
public BaralsExpertise(UUID ownerId, CardSetInfo setInfo) {
|
||||
|
@ -32,7 +39,7 @@ public final class BaralsExpertise extends CardImpl {
|
|||
getSpellAbility().addTarget(new TargetPermanent(0, 3, filter, false));
|
||||
|
||||
// You may cast a card with converted mana cost 4 or less from your hand without paying its mana cost.
|
||||
getSpellAbility().addEffect(new CastWithoutPayingManaCostEffect(4).concatBy("<br>"));
|
||||
getSpellAbility().addEffect(new CastFromHandForFreeEffect(filter2).concatBy("<br>"));
|
||||
}
|
||||
|
||||
private BaralsExpertise(final BaralsExpertise card) {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.RemoveVariableCountersSourceCost;
|
||||
|
@ -10,13 +8,11 @@ import mage.abilities.costs.mana.GenericManaCost;
|
|||
import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterInstantOrSorceryCard;
|
||||
|
@ -24,10 +20,11 @@ import mage.filter.predicate.mageobject.ManaValuePredicate;
|
|||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public final class BrainInAJar extends CardImpl {
|
||||
|
@ -39,20 +36,17 @@ public final class BrainInAJar extends CardImpl {
|
|||
// cast an instant or sorcery card with converted mana costs equal
|
||||
// to the number of charge counters on Brain in a Jar from your
|
||||
// hand without paying its mana cost.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
||||
new AddCountersSourceEffect(CounterType.CHARGE.createInstance()),
|
||||
new GenericManaCost(1));
|
||||
Ability ability = new SimpleActivatedAbility(
|
||||
new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), new GenericManaCost(1)
|
||||
);
|
||||
ability.addEffect(new BrainInAJarCastEffect());
|
||||
ability.addCost(new TapSourceCost());
|
||||
this.addAbility(ability);
|
||||
|
||||
// {3}, {T}, Remove X charge counters from Brain in a Jar: Scry X.
|
||||
ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
||||
new BrainInAJarScryEffect(),
|
||||
new GenericManaCost(3));
|
||||
ability = new SimpleActivatedAbility(new BrainInAJarScryEffect(), new GenericManaCost(3));
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addCost(new RemoveVariableCountersSourceCost(
|
||||
CounterType.CHARGE.createInstance()));
|
||||
ability.addCost(new RemoveVariableCountersSourceCost(CounterType.CHARGE.createInstance()));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
@ -87,32 +81,14 @@ class BrainInAJarCastEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||
if (controller != null
|
||||
&& sourceObject != null) {
|
||||
int counters = sourceObject.getCounters(game).getCount(CounterType.CHARGE);
|
||||
FilterCard filter = new FilterInstantOrSorceryCard();
|
||||
filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, counters));
|
||||
int cardsToCast = controller.getHand().count(filter, source.getControllerId(),
|
||||
source.getSourceId(), game);
|
||||
if (cardsToCast > 0
|
||||
&& controller.chooseUse(Outcome.PlayForFree,
|
||||
"Cast an instant or sorcery card with mana values of "
|
||||
+ counters + " from your hand without paying its mana cost?",
|
||||
source, game)) {
|
||||
TargetCardInHand target = new TargetCardInHand(filter);
|
||||
controller.chooseTarget(outcome, target, source, game);
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
Permanent sourceObject = source.getSourcePermanentOrLKI(game);
|
||||
if (controller == null || sourceObject == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
int counters = sourceObject.getCounters(game).getCount(CounterType.CHARGE);
|
||||
FilterCard filter = new FilterInstantOrSorceryCard();
|
||||
filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, counters));
|
||||
return CardUtil.castSpellWithAttributesForFree(controller, source, game, controller.getHand(), filter);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,24 +1,19 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.continuous.MaximumHandSizeControllerEffect;
|
||||
import mage.abilities.effects.common.cost.CastWithoutPayingManaCostEffect;
|
||||
import mage.abilities.keyword.FriendsForeverAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
import org.apache.log4j.Logger;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -83,45 +78,10 @@ class CecilyHauntedMageEffect extends OneShotEffect {
|
|||
}
|
||||
player.drawCards(1, source, game);
|
||||
player.loseLife(1, game, source, false);
|
||||
if (player.getHand().size() < 11) {
|
||||
return true;
|
||||
}
|
||||
// TODO: change this to fit with changes made in https://github.com/magefree/mage/pull/8136 when merged
|
||||
Target target = new TargetCardInHand(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY);
|
||||
if (!target.canChoose(
|
||||
source.getSourceId(), player.getId(), game
|
||||
) || !player.chooseUse(
|
||||
Outcome.PlayForFree, "Cast an instant or sorcery spell " +
|
||||
"from your hand without paying its mana cost?", source, game
|
||||
)) {
|
||||
return true;
|
||||
}
|
||||
Card cardToCast = null;
|
||||
boolean cancel = false;
|
||||
while (player.canRespond()
|
||||
&& !cancel) {
|
||||
if (player.chooseTarget(Outcome.PlayForFree, target, source, game)) {
|
||||
cardToCast = game.getCard(target.getFirstTarget());
|
||||
if (cardToCast != null) {
|
||||
if (cardToCast.getSpellAbility() == null) {
|
||||
Logger.getLogger(CastWithoutPayingManaCostEffect.class).fatal("Card: "
|
||||
+ cardToCast.getName() + " is no land and has no spell ability!");
|
||||
cancel = true;
|
||||
}
|
||||
if (cardToCast.getSpellAbility().canChooseTarget(game, player.getId())) {
|
||||
cancel = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cancel = true;
|
||||
}
|
||||
}
|
||||
if (cardToCast != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + cardToCast.getId(), Boolean.TRUE);
|
||||
player.cast(player.chooseAbilityForCast(cardToCast, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + cardToCast.getId(), null);
|
||||
}
|
||||
return true;
|
||||
return player.getHand().size() < 11
|
||||
|| CardUtil.castSpellWithAttributesForFree(
|
||||
player, source, game, player.getHand().copy(),
|
||||
StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,23 +10,20 @@ import mage.abilities.effects.common.discard.DiscardHandAllEffect;
|
|||
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.SuperType;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterInstantOrSorceryCard;
|
||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetAnyTarget;
|
||||
import mage.target.common.TargetCardInGraveyard;
|
||||
import mage.target.common.TargetDiscard;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
|
||||
/**
|
||||
* @author North
|
||||
|
@ -138,6 +135,12 @@ class ChandraAblazeEffect2 extends OneShotEffect {
|
|||
|
||||
class ChandraAblazeEffect5 extends OneShotEffect {
|
||||
|
||||
private static final FilterCard filter = new FilterInstantOrSorceryCard();
|
||||
|
||||
static {
|
||||
filter.add(new ColorPredicate(ObjectColor.RED));
|
||||
}
|
||||
|
||||
public ChandraAblazeEffect5() {
|
||||
super(Outcome.PlayForFree);
|
||||
this.staticText = "Cast any number of red instant and/or sorcery cards from your graveyard without paying their mana costs";
|
||||
|
@ -154,33 +157,17 @@ class ChandraAblazeEffect5 extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
// Under this card's current oracle wording, it only casts red instant or sorcery cards
|
||||
// This may have been a mistake which could change in the future
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
FilterCard filter = new FilterCard("red instant or sorcery card from your graveyard to play");
|
||||
filter.add(new ColorPredicate(ObjectColor.RED));
|
||||
filter.add(Predicates.or(
|
||||
CardType.INSTANT.getPredicate(),
|
||||
CardType.SORCERY.getPredicate()));
|
||||
|
||||
String message = "Play red instant or sorcery card from your graveyard without paying its mana cost?";
|
||||
Set<Card> cards = player.getGraveyard().getCards(filter, game);
|
||||
TargetCardInGraveyard target = new TargetCardInGraveyard(filter);
|
||||
while (!cards.isEmpty() && player.chooseUse(outcome, message, source, game)) {
|
||||
target.clearChosen();
|
||||
if (player.choose(outcome, target, source.getSourceId(), game)) {
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
player.cast(player.chooseAbilityForCast(card, game, true), game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
|
||||
cards.remove(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
CardUtil.castMultipleWithAttributeForFree(
|
||||
player, source, game,
|
||||
new CardsImpl(player.getGraveyard().getCards(filter, game)),
|
||||
StaticFilters.FILTER_CARD
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.Outcome;
|
||||
|
@ -13,7 +14,7 @@ import mage.filter.FilterCard;
|
|||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -51,12 +52,6 @@ class CollectedConjuringEffect extends OneShotEffect {
|
|||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 4));
|
||||
}
|
||||
|
||||
private static final FilterCard filter2 = filter.copy();
|
||||
|
||||
static {
|
||||
filter2.setMessage("sorcery card with mana value 3 or less");
|
||||
}
|
||||
|
||||
CollectedConjuringEffect() {
|
||||
super(Outcome.PlayForFree);
|
||||
this.staticText = "exile the top six cards of your library. You may cast up to two sorcery spells " +
|
||||
|
@ -76,42 +71,12 @@ class CollectedConjuringEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (controller == null
|
||||
|| sourceObject == null) {
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 6));
|
||||
Cards cardsToChoose = new CardsImpl(cards);
|
||||
controller.moveCards(cards, Zone.EXILED, source, game);
|
||||
int cardsCast = 0;
|
||||
while (!cardsToChoose.getCards(filter, source.getSourceId(), source.getControllerId(), game).isEmpty()
|
||||
&& cardsCast < 2) {
|
||||
if (!controller.chooseUse(Outcome.PlayForFree, "Cast a card exiled with "
|
||||
+ sourceObject.getLogName() + " without paying its mana cost?", source, game)) {
|
||||
break;
|
||||
}
|
||||
TargetCard targetCard = new TargetCard(1, Zone.EXILED, filter2);
|
||||
if (!controller.choose(Outcome.PlayForFree, cardsToChoose, targetCard, game)) {
|
||||
continue;
|
||||
}
|
||||
Card card = game.getCard(targetCard.getFirstTarget());
|
||||
if (card == null) {
|
||||
continue;
|
||||
}
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
cardsToChoose.remove(card); // remove on non cast too (infinite freeze fix)
|
||||
if (cardWasCast) {
|
||||
cards.remove(card);
|
||||
cardsCast++;
|
||||
} else {
|
||||
game.informPlayer(controller, "You're not able to cast "
|
||||
+ card.getIdName() + " or you canceled the casting.");
|
||||
}
|
||||
}
|
||||
CardUtil.castMultipleWithAttributeForFree(controller, source, game, cards, filter, 2);
|
||||
controller.putCardsOnBottomOfLibrary(cards, game, source, false);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.FilterCard;
|
||||
|
@ -19,10 +15,13 @@ import mage.game.Game;
|
|||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetSpell;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward
|
||||
*/
|
||||
public final class Counterlash extends CardImpl {
|
||||
|
@ -50,9 +49,9 @@ class CounterlashEffect extends OneShotEffect {
|
|||
|
||||
public CounterlashEffect() {
|
||||
super(Outcome.Detriment);
|
||||
this.staticText = "Counter target spell. You may cast a nonland "
|
||||
+ "card in your hand that shares a card type with that "
|
||||
+ "spell without paying its mana cost";
|
||||
this.staticText = "Counter target spell. You may cast a spell "
|
||||
+ "that shares a card type with it from your hand "
|
||||
+ "without paying its mana cost";
|
||||
}
|
||||
|
||||
public CounterlashEffect(final CounterlashEffect effect) {
|
||||
|
@ -68,32 +67,21 @@ class CounterlashEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
StackObject stackObject = game.getStack().getStackObject(source.getFirstTarget());
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (stackObject != null
|
||||
&& controller != null) {
|
||||
game.getStack().counter(source.getFirstTarget(), source, game);
|
||||
if (controller.chooseUse(Outcome.PlayForFree, "Cast a nonland card in your hand that "
|
||||
+ "shares a card type with that spell without paying its mana cost?", source, game)) {
|
||||
FilterCard filter = new FilterCard();
|
||||
List<Predicate<MageObject>> types = new ArrayList<>();
|
||||
for (CardType type : stackObject.getCardType(game)) {
|
||||
if (type != CardType.LAND) {
|
||||
types.add(type.getPredicate());
|
||||
}
|
||||
}
|
||||
filter.add(Predicates.or(types));
|
||||
TargetCardInHand target = new TargetCardInHand(filter);
|
||||
if (controller.choose(Outcome.PutCardInPlay, target, source.getSourceId(), game)) {
|
||||
Card card = controller.getHand().get(target.getFirstTarget(), game);
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stackObject == null || controller == null) {
|
||||
return false;
|
||||
}
|
||||
Set<Predicate<MageObject>> predicates = stackObject
|
||||
.getCardType(game)
|
||||
.stream()
|
||||
.map(CardType::getPredicate)
|
||||
.collect(Collectors.toSet());
|
||||
game.getStack().counter(source.getFirstTarget(), source, game);
|
||||
if (predicates.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
FilterCard filter = new FilterCard();
|
||||
filter.add(Predicates.or(predicates));
|
||||
CardUtil.castSpellWithAttributesForFree(controller, source, game, new CardsImpl(controller.getHand()), filter);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,14 +4,17 @@ import mage.abilities.common.SimpleStaticAbility;
|
|||
import mage.abilities.condition.common.FullPartyCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.dynamicvalue.common.PartyCount;
|
||||
import mage.abilities.effects.common.cost.CastWithoutPayingManaCostEffect;
|
||||
import mage.abilities.effects.common.cost.CastFromHandForFreeEffect;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
|
||||
import mage.abilities.hint.common.PartyCountHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -21,6 +24,12 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class CovetedPrize extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("a spell with mana value 4 or less");
|
||||
|
||||
static {
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 5));
|
||||
}
|
||||
|
||||
public CovetedPrize(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B}");
|
||||
|
||||
|
@ -32,7 +41,7 @@ public final class CovetedPrize extends CardImpl {
|
|||
// Search your library for a card, put it into your hand, then shuffle your library. If you have a full party, you may cast a spell with converted mana cost 4 or less from your hand without paying its mana cost.
|
||||
this.getSpellAbility().addEffect(new SearchLibraryPutInHandEffect(new TargetCardInLibrary()));
|
||||
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
|
||||
new CastWithoutPayingManaCostEffect(4),
|
||||
new CastFromHandForFreeEffect(filter),
|
||||
FullPartyCondition.instance, "If you have a full party, " +
|
||||
"you may cast a spell with mana value 4 or less from your hand without paying its mana cost."
|
||||
));
|
||||
|
|
91
Mage.Sets/src/mage/cards/d/DiscoverTheImpossible.java
Normal file
91
Mage.Sets/src/mage/cards/d/DiscoverTheImpossible.java
Normal file
|
@ -0,0 +1,91 @@
|
|||
package mage.cards.d;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class DiscoverTheImpossible extends CardImpl {
|
||||
|
||||
public DiscoverTheImpossible(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}");
|
||||
|
||||
// Look at the top five cards of your library. Exile one of them face down and put the rest on the bottom of your library in a random order. You may cast the exiled card without paying its mana cost if it's an instant spell with mana value 2 or less. If you don't, put that card into your hand.
|
||||
this.getSpellAbility().addEffect(new DiscoverTheImpossibleEffect());
|
||||
}
|
||||
|
||||
private DiscoverTheImpossible(final DiscoverTheImpossible card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiscoverTheImpossible copy() {
|
||||
return new DiscoverTheImpossible(this);
|
||||
}
|
||||
}
|
||||
|
||||
class DiscoverTheImpossibleEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterCard filter = new FilterCard();
|
||||
|
||||
static {
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 3));
|
||||
}
|
||||
|
||||
DiscoverTheImpossibleEffect() {
|
||||
super(Outcome.PlayForFree);
|
||||
staticText = "look at the top five cards of your library. Exile one of them face down " +
|
||||
"and put the rest on the bottom of your library in a random order. " +
|
||||
"You may cast the exiled card without paying its mana cost if it's an instant spell " +
|
||||
"with mana value 2 or less. If you don't, put that card into your hand";
|
||||
}
|
||||
|
||||
private DiscoverTheImpossibleEffect(final DiscoverTheImpossibleEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiscoverTheImpossibleEffect copy() {
|
||||
return new DiscoverTheImpossibleEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 5));
|
||||
if (cards.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
TargetCard target = new TargetCardInLibrary();
|
||||
player.choose(outcome, cards, target, game);
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card == null) {
|
||||
player.putCardsOnBottomOfLibrary(card, game, source, false);
|
||||
return true;
|
||||
}
|
||||
player.moveCards(card, Zone.EXILED, source, game);
|
||||
card.setFaceDown(true, game);
|
||||
cards.retainZone(Zone.LIBRARY, game);
|
||||
player.putCardsOnBottomOfLibrary(cards, game, source, false);
|
||||
return CardUtil.castSpellWithAttributesForFree(player, source, game, new CardsImpl(card), filter)
|
||||
|| player.moveCards(card, Zone.HAND, source, game);
|
||||
}
|
||||
}
|
91
Mage.Sets/src/mage/cards/d/DragonKamisEgg.java
Normal file
91
Mage.Sets/src/mage/cards/d/DragonKamisEgg.java
Normal file
|
@ -0,0 +1,91 @@
|
|||
package mage.cards.d;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DiesThisOrAnotherCreatureTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class DragonKamisEgg extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterControlledPermanent(SubType.DRAGON);
|
||||
|
||||
public DragonKamisEgg(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "");
|
||||
|
||||
this.subtype.add(SubType.EGG);
|
||||
this.power = new MageInt(0);
|
||||
this.toughness = new MageInt(1);
|
||||
this.color.setGreen(true);
|
||||
this.nightCard = true;
|
||||
|
||||
// Whenever Dragon-Kami's Egg or a Dragon you control dies, you may cast a creature spell from among cards you own in exile with hatching counters on them without paying its mana cost.
|
||||
this.addAbility(new DiesThisOrAnotherCreatureTriggeredAbility(
|
||||
new DragonKamisEggEffect(), false, filter
|
||||
).setTriggerPhrase("Whenever {this} or a Dragon you control dies, "));
|
||||
}
|
||||
|
||||
private DragonKamisEgg(final DragonKamisEgg card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DragonKamisEgg copy() {
|
||||
return new DragonKamisEgg(this);
|
||||
}
|
||||
}
|
||||
|
||||
class DragonKamisEggEffect extends OneShotEffect {
|
||||
|
||||
DragonKamisEggEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "you may cast a creature spell from among cards you own in exile " +
|
||||
"with hatching counters on them without paying its mana cost";
|
||||
}
|
||||
|
||||
private DragonKamisEggEffect(final DragonKamisEggEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DragonKamisEggEffect copy() {
|
||||
return new DragonKamisEggEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
Cards cards = new CardsImpl();
|
||||
game.getExile()
|
||||
.getAllCards(game, player.getId())
|
||||
.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(card -> card.getCounters(game).containsKey(CounterType.HATCHLING))
|
||||
.forEach(cards::add);
|
||||
return !cards.isEmpty() && CardUtil.castSpellWithAttributesForFree(
|
||||
player, source, game, cards, StaticFilters.FILTER_CARD_CREATURE
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,12 +1,20 @@
|
|||
package mage.cards.e;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.effects.common.cost.CastWithoutPayingManaCostEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetAnyTarget;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -21,7 +29,7 @@ public final class Electrodominance extends CardImpl {
|
|||
// Electrodominance deals X damage to any target. You may cast a card with converted mana cost X or less from your hand without paying its mana cost.
|
||||
this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.REGULAR));
|
||||
this.getSpellAbility().addTarget(new TargetAnyTarget());
|
||||
this.getSpellAbility().addEffect(new CastWithoutPayingManaCostEffect(ManacostVariableValue.REGULAR));
|
||||
this.getSpellAbility().addEffect(new ElectrodominanceEffect());
|
||||
}
|
||||
|
||||
private Electrodominance(final Electrodominance card) {
|
||||
|
@ -33,3 +41,34 @@ public final class Electrodominance extends CardImpl {
|
|||
return new Electrodominance(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ElectrodominanceEffect extends OneShotEffect {
|
||||
|
||||
ElectrodominanceEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "You may cast a spell with mana value X " +
|
||||
"or less from your hand without paying its mana cost";
|
||||
}
|
||||
|
||||
private ElectrodominanceEffect(final ElectrodominanceEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElectrodominanceEffect copy() {
|
||||
return new ElectrodominanceEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
FilterCard filter = new FilterCard();
|
||||
filter.add(new ManaValuePredicate(
|
||||
ComparisonType.FEWER_THAN, source.getManaCostsToPay().getX() + 1
|
||||
));
|
||||
return CardUtil.castSpellWithAttributesForFree(controller, source, game, controller.getHand(), filter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,10 @@ package mage.cards.e;
|
|||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.Outcome;
|
||||
|
@ -11,13 +14,11 @@ import mage.constants.Zone;
|
|||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterInstantOrSorceryCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.ExileZone;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
|
@ -61,59 +62,16 @@ class EpicExperimentEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (controller != null && sourceObject != null) {
|
||||
// move cards from library to exile
|
||||
controller.moveCardsToExile(controller.getLibrary().getTopCards(game,
|
||||
source.getManaCostsToPay().getX()), source, game, true,
|
||||
source.getSourceId(), sourceObject.getIdName());
|
||||
// cast the possible cards without paying the mana
|
||||
ExileZone epicExperimentExileZone = game.getExile().getExileZone(source.getSourceId());
|
||||
FilterCard filter = new FilterInstantOrSorceryCard();
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN,
|
||||
source.getManaCostsToPay().getX() + 1));
|
||||
filter.setMessage("instant and sorcery cards with mana value "
|
||||
+ source.getManaCostsToPay().getX() + " or less");
|
||||
Cards cardsToCast = new CardsImpl();
|
||||
if (epicExperimentExileZone == null) {
|
||||
return true;
|
||||
}
|
||||
cardsToCast.addAll(epicExperimentExileZone.getCards(filter, source.getSourceId(),
|
||||
source.getControllerId(), game));
|
||||
while (controller.canRespond() && !cardsToCast.isEmpty()) {
|
||||
if (!controller.chooseUse(Outcome.PlayForFree, "Cast (another) a card exiled with "
|
||||
+ sourceObject.getLogName() + " without paying its mana cost?", source, game)) {
|
||||
break;
|
||||
}
|
||||
TargetCard targetCard = new TargetCard(1, Zone.EXILED, new FilterCard(
|
||||
"instant or sorcery card to cast for free"));
|
||||
if (controller.choose(Outcome.PlayForFree, cardsToCast, targetCard, game)) {
|
||||
Card card = game.getCard(targetCard.getFirstTarget());
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
if (!cardWasCast) {
|
||||
game.informPlayer(controller, "You're not able to cast "
|
||||
+ card.getIdName() + " or you canceled the casting.");
|
||||
}
|
||||
cardsToCast.remove(card);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// move cards not cast to graveyard
|
||||
ExileZone exileZone = game.getExile().getExileZone(source.getSourceId());
|
||||
if (exileZone != null) {
|
||||
controller.moveCards(exileZone.getCards(game), Zone.GRAVEYARD, source, game);
|
||||
}
|
||||
return true;
|
||||
if (controller == null || sourceObject == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, source.getManaCostsToPay().getX()));
|
||||
controller.moveCards(cards, Zone.EXILED, source, game);
|
||||
FilterCard filter = new FilterInstantOrSorceryCard();
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, source.getManaCostsToPay().getX() + 1));
|
||||
CardUtil.castMultipleWithAttributeForFree(controller, source, game, cards, filter);
|
||||
controller.moveCards(cards, Zone.GRAVEYARD, source, game);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,22 +1,20 @@
|
|||
package mage.cards.e;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterNonlandCard;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
|
||||
/**
|
||||
* @author ciaccona007 & L_J
|
||||
|
@ -34,7 +32,6 @@ public final class EtaliPrimalStorm extends CardImpl {
|
|||
// Whenever Etali, Primal Storm attacks, exile the top card of each player's library,
|
||||
// then you may cast any number of nonland cards exiled this way without paying their mana costs.
|
||||
this.addAbility(new AttacksTriggeredAbility(new EtaliPrimalStormEffect(), false));
|
||||
|
||||
}
|
||||
|
||||
private EtaliPrimalStorm(final EtaliPrimalStorm card) {
|
||||
|
@ -69,58 +66,19 @@ class EtaliPrimalStormEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (controller != null
|
||||
&& sourceObject != null) {
|
||||
// move cards from library to exile
|
||||
Set<Card> currentExiledCards = new HashSet<>();
|
||||
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
if (!player.getLibrary().getTopCards(game, 1).isEmpty()) {
|
||||
Card topCard = player.getLibrary().getFromTop(game);
|
||||
if (topCard != null) {
|
||||
if (filter.match(topCard, source.getSourceId(), source.getControllerId(), game)) {
|
||||
currentExiledCards.add(topCard);
|
||||
}
|
||||
controller.moveCardsToExile(topCard, source, game, true, source.getSourceId(), sourceObject.getIdName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cast the possible cards without paying the mana
|
||||
Cards cardsToCast = new CardsImpl();
|
||||
cardsToCast.addAll(currentExiledCards);
|
||||
boolean alreadyCast = false;
|
||||
while (controller.canRespond() && !cardsToCast.isEmpty()) {
|
||||
if (!controller.chooseUse(Outcome.PlayForFree, "Cast a"
|
||||
+ (alreadyCast ? "nother" : "") + " card exiled with "
|
||||
+ sourceObject.getLogName() + " without paying its mana cost?", source, game)) {
|
||||
break;
|
||||
}
|
||||
|
||||
TargetCard targetCard = new TargetCard(1, Zone.EXILED, new FilterCard("nonland card to cast for free"));
|
||||
if (!controller.choose(Outcome.PlayForFree, cardsToCast, targetCard, game)) {
|
||||
break;
|
||||
}
|
||||
|
||||
alreadyCast = true;
|
||||
Card card = game.getCard(targetCard.getFirstTarget());
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
if (!cardWasCast) {
|
||||
game.informPlayer(controller, "You're not able to cast "
|
||||
+ card.getIdName() + " or you canceled the casting.");
|
||||
}
|
||||
cardsToCast.remove(card);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
// move cards from library to exile
|
||||
Cards cards = new CardsImpl();
|
||||
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
cards.add(player.getLibrary().getFromTop(game));
|
||||
}
|
||||
}
|
||||
controller.moveCards(cards, Zone.EXILED, source, game);
|
||||
CardUtil.castMultipleWithAttributeForFree(controller, source, game, cards, filter);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
77
Mage.Sets/src/mage/cards/e/ExtractBrain.java
Normal file
77
Mage.Sets/src/mage/cards/e/ExtractBrain.java
Normal file
|
@ -0,0 +1,77 @@
|
|||
package mage.cards.e;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class ExtractBrain extends CardImpl {
|
||||
|
||||
public ExtractBrain(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{U}{B}");
|
||||
|
||||
// Target opponent chooses X cards from their hand. Look at those cards. You may cast a spell from among them without paying its mana cost.
|
||||
this.getSpellAbility().addEffect(new ExtractBrainEffect());
|
||||
this.getSpellAbility().addTarget(new TargetOpponent());
|
||||
}
|
||||
|
||||
private ExtractBrain(final ExtractBrain card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtractBrain copy() {
|
||||
return new ExtractBrain(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ExtractBrainEffect extends OneShotEffect {
|
||||
|
||||
ExtractBrainEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "target opponent chooses X cards from their hand. Look at those cards. " +
|
||||
"You may cast a spell from among them without paying its mana cost";
|
||||
}
|
||||
|
||||
private ExtractBrainEffect(final ExtractBrainEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtractBrainEffect copy() {
|
||||
return new ExtractBrainEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Player opponent = game.getPlayer(source.getFirstTarget());
|
||||
int xValue = source.getManaCostsToPay().getX();
|
||||
if (controller == null || opponent == null || opponent.getHand().isEmpty() || xValue < 1) {
|
||||
return false;
|
||||
}
|
||||
TargetCardInHand target = new TargetCardInHand(
|
||||
Math.min(opponent.getHand().size(), xValue), StaticFilters.FILTER_CARD
|
||||
);
|
||||
opponent.choose(Outcome.Detriment, opponent.getHand(), target, game);
|
||||
Cards cards = new CardsImpl(target.getTargets());
|
||||
controller.lookAtCards(source, null, cards, game);
|
||||
CardUtil.castSpellWithAttributesForFree(controller, source, game, cards, StaticFilters.FILTER_CARD);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -79,14 +79,10 @@ class FeatherTheRedeemedTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (!event.getPlayerId().equals(this.getControllerId())) {
|
||||
if (!isControlledBy(event.getPlayerId())) {
|
||||
return false;
|
||||
}
|
||||
Spell spell = game.getStack().getSpell(event.getTargetId());
|
||||
return checkSpell(spell, game);
|
||||
}
|
||||
|
||||
private boolean checkSpell(Spell spell, Game game) {
|
||||
if (spell == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -166,15 +162,15 @@ class FeatherTheRedeemedEffect extends ReplacementEffectImpl {
|
|||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
ZoneChangeEvent zEvent = ((ZoneChangeEvent) event);
|
||||
if (zEvent.getFromZone() == Zone.STACK
|
||||
&& zEvent.getToZone() == Zone.GRAVEYARD
|
||||
&& event.getSourceId() != null) {
|
||||
if (event.getSourceId().equals(event.getTargetId()) && mor.getZoneChangeCounter() == game.getState().getZoneChangeCounter(event.getSourceId())) {
|
||||
Spell spell = game.getStack().getSpell(mor.getSourceId());
|
||||
return spell != null && spell.isInstantOrSorcery(game);
|
||||
}
|
||||
if (zEvent.getFromZone() != Zone.STACK
|
||||
|| zEvent.getToZone() != Zone.GRAVEYARD
|
||||
|| event.getSourceId() == null
|
||||
|| !event.getSourceId().equals(event.getTargetId())
|
||||
|| mor.getZoneChangeCounter() != game.getState().getZoneChangeCounter(event.getSourceId())) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
Spell spell = game.getStack().getSpell(mor.getSourceId());
|
||||
return spell != null && spell.isInstantOrSorcery(game);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
88
Mage.Sets/src/mage/cards/f/FeveredSuspicion.java
Normal file
88
Mage.Sets/src/mage/cards/f/FeveredSuspicion.java
Normal file
|
@ -0,0 +1,88 @@
|
|||
package mage.cards.f;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.ReboundAbility;
|
||||
import mage.cards.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class FeveredSuspicion extends CardImpl {
|
||||
|
||||
public FeveredSuspicion(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{6}{B}{R}");
|
||||
|
||||
// Each opponent exiles cards from the top of their library until they exile a nonland card. You may cast any number of spells from among those nonland cards without paying their mana costs.
|
||||
this.getSpellAbility().addEffect(new FeveredSuspicionEffect());
|
||||
|
||||
// Rebound
|
||||
this.addAbility(new ReboundAbility());
|
||||
}
|
||||
|
||||
private FeveredSuspicion(final FeveredSuspicion card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeveredSuspicion copy() {
|
||||
return new FeveredSuspicion(this);
|
||||
}
|
||||
}
|
||||
|
||||
class FeveredSuspicionEffect extends OneShotEffect {
|
||||
|
||||
FeveredSuspicionEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "each opponent exiles cards from the top of their library until they exile a nonland card. " +
|
||||
"You may cast any number of spells from among those nonland cards without paying their mana costs";
|
||||
}
|
||||
|
||||
private FeveredSuspicionEffect(final FeveredSuspicionEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeveredSuspicionEffect copy() {
|
||||
return new FeveredSuspicionEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
Cards cards = new CardsImpl();
|
||||
Cards nonlands = new CardsImpl();
|
||||
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
|
||||
Player opponent = game.getPlayer(opponentId);
|
||||
if (opponent == null) {
|
||||
continue;
|
||||
}
|
||||
for (Card card : opponent.getLibrary().getCards(game)) {
|
||||
cards.add(card);
|
||||
if (!card.isLand(game)) {
|
||||
nonlands.add(card);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
controller.moveCards(cards, Zone.EXILED, source, game);
|
||||
nonlands.retainZone(Zone.EXILED, game);
|
||||
CardUtil.castMultipleWithAttributeForFree(
|
||||
controller, source, game, nonlands,
|
||||
StaticFilters.FILTER_CARD
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,22 +1,23 @@
|
|||
package mage.cards.g;
|
||||
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.CommanderCardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
@ -35,7 +36,7 @@ public final class GeodeGolem extends CardImpl {
|
|||
this.addAbility(TrampleAbility.getInstance());
|
||||
|
||||
// Whenever Geode Golem deals combat damage to a player, you may cast your commander from the command zone without paying its mana cost.
|
||||
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new GeodeGolemEffect(), true));
|
||||
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new GeodeGolemEffect(), false));
|
||||
}
|
||||
|
||||
private GeodeGolem(final GeodeGolem card) {
|
||||
|
@ -63,48 +64,13 @@ class GeodeGolemEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Card selectedCommander = null;
|
||||
|
||||
Set<Card> commandersInCommandZone = game.getCommanderCardsFromCommandZone(controller, CommanderCardType.COMMANDER_OR_OATHBREAKER);
|
||||
if (commandersInCommandZone.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// select from commanders
|
||||
if (commandersInCommandZone.size() == 1) {
|
||||
selectedCommander = commandersInCommandZone.stream().findFirst().get();
|
||||
} else {
|
||||
TargetCard target = new TargetCard(Zone.COMMAND, new FilterCard("commander to cast without mana cost"));
|
||||
target.setNotTarget(true);
|
||||
if (controller.canRespond()
|
||||
&& controller.choose(Outcome.PlayForFree, new CardsImpl(commandersInCommandZone), target, game)) {
|
||||
selectedCommander = commandersInCommandZone.stream()
|
||||
.filter(c -> c.getId().equals(target.getFirstTarget()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedCommander == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// commander tax applies as additional cost
|
||||
if (selectedCommander.getSpellAbility() != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + selectedCommander.getId(), Boolean.TRUE);
|
||||
Boolean commanderWasCast = controller.cast(controller.chooseAbilityForCast(selectedCommander, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + selectedCommander.getId(), null);
|
||||
return commanderWasCast;
|
||||
} else {
|
||||
// play commander as land is xmage feature, but mtg rules for text "cast commander" doesn't allow that
|
||||
// TODO: improve lands support for "cast your commander" (allow land play from mdf cards)?
|
||||
return controller.playLand(selectedCommander, game, true);
|
||||
}
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
Cards cards = new CardsImpl(game.getCommanderCardsFromCommandZone(
|
||||
controller, CommanderCardType.COMMANDER_OR_OATHBREAKER
|
||||
));
|
||||
return CardUtil.castSpellWithAttributesForFree(controller, source, game, cards, StaticFilters.FILTER_CARD);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,41 +1,44 @@
|
|||
package mage.cards.h;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DontUntapInControllersUntapStepAllEffect;
|
||||
import mage.cards.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterControlledLandPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.ExileZone;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
|
||||
/**
|
||||
* @author ciaccona007
|
||||
*/
|
||||
public final class HazoretsUndyingFury extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterControlledLandPermanent("Lands you control");
|
||||
|
||||
public HazoretsUndyingFury(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{R}{R}");
|
||||
|
||||
//Shuffle your library, then exile the top four cards.
|
||||
//You may cast any number of nonland cards with converted mana
|
||||
//cost 5 or less from among them without paying their mana costs.
|
||||
getSpellAbility().addEffect(new HazoretsUndyingFuryEffect());
|
||||
this.getSpellAbility().addEffect(new HazoretsUndyingFuryEffect());
|
||||
|
||||
//Land you control don't untap during your next untap step.
|
||||
this.getSpellAbility().addEffect(new DontUntapInControllersUntapStepAllEffect(
|
||||
Duration.UntilYourNextTurn, TargetController.YOU,
|
||||
new FilterControlledLandPermanent("Lands you control"))
|
||||
.setText("Lands you control don't untap during your next untap phase"));
|
||||
StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND
|
||||
).setText("Lands you control don't untap during your next untap phase"));
|
||||
}
|
||||
|
||||
private HazoretsUndyingFury(final HazoretsUndyingFury card) {
|
||||
|
@ -50,19 +53,17 @@ public final class HazoretsUndyingFury extends CardImpl {
|
|||
|
||||
class HazoretsUndyingFuryEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterCard filter = new FilterCard(
|
||||
"nonland cards with mana value 5 or less");
|
||||
private static final FilterCard filter = new FilterCard();
|
||||
|
||||
static {
|
||||
filter.add(Predicates.not(CardType.LAND.getPredicate()));
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 6));
|
||||
}
|
||||
|
||||
public HazoretsUndyingFuryEffect() {
|
||||
super(Outcome.PlayForFree);
|
||||
this.staticText = "Shuffle your library, then exile the top four cards. "
|
||||
+ "You may cast any number of nonland cards with mana value "
|
||||
+ "5 or less from among them without paying their mana costs";
|
||||
this.staticText = "Shuffle your library, then exile the top four cards. " +
|
||||
"You may cast any number of spells with mana value " +
|
||||
"5 or less from among them without paying their mana costs";
|
||||
}
|
||||
|
||||
public HazoretsUndyingFuryEffect(final HazoretsUndyingFuryEffect effect) {
|
||||
|
@ -77,46 +78,15 @@ class HazoretsUndyingFuryEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (controller != null
|
||||
&& sourceObject != null) {
|
||||
controller.shuffleLibrary(source, game);
|
||||
// move cards from library to exile
|
||||
controller.moveCardsToExile(controller.getLibrary().getTopCards(game, 4),
|
||||
source, game, true, source.getSourceId(), sourceObject.getIdName());
|
||||
// cast the possible cards without paying the mana
|
||||
ExileZone hazoretsUndyingFuryExileZone = game.getExile().getExileZone(source.getSourceId());
|
||||
Cards cardsToCast = new CardsImpl();
|
||||
if (hazoretsUndyingFuryExileZone == null) {
|
||||
return true;
|
||||
}
|
||||
cardsToCast.addAll(hazoretsUndyingFuryExileZone.getCards(filter,
|
||||
source.getSourceId(), source.getControllerId(), game));
|
||||
while (controller.canRespond() && !cardsToCast.isEmpty()) {
|
||||
if (!controller.chooseUse(Outcome.PlayForFree,
|
||||
"Cast (another) a card exiled with "
|
||||
+ sourceObject.getLogName() + " without paying its mana cost?", source, game)) {
|
||||
break;
|
||||
}
|
||||
TargetCard targetCard = new TargetCard(1, Zone.EXILED,
|
||||
new FilterCard("nonland card to cast for free"));
|
||||
if (controller.choose(Outcome.PlayForFree, cardsToCast, targetCard, game)) {
|
||||
Card card = game.getCard(targetCard.getFirstTarget());
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
cardsToCast.remove(card);
|
||||
if (!cardWasCast) {
|
||||
game.informPlayer(controller, "You're not able to cast "
|
||||
+ card.getIdName() + " or you canceled the casting.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
controller.shuffleLibrary(source, game);
|
||||
// move cards from library to exile
|
||||
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 4));
|
||||
controller.moveCards(cards, Zone.EXILED, source, game);
|
||||
// cast the possible cards without paying the mana
|
||||
CardUtil.castMultipleWithAttributeForFree(controller, source, game, cards, filter);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,24 @@
|
|||
package mage.cards.h;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterNonlandCard;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
|
||||
/**
|
||||
* @author jeffwadsworth & L_J
|
||||
|
@ -58,7 +56,7 @@ class HellcarverDemonEffect extends OneShotEffect {
|
|||
super(Outcome.PlayForFree);
|
||||
staticText = "sacrifice all other permanents you control and discard your hand. "
|
||||
+ "Exile the top six cards of your library. You may cast any number of "
|
||||
+ "nonland cards exiled this way without paying their mana costs.";
|
||||
+ "spells from among cards exiled this way without paying their mana costs";
|
||||
}
|
||||
|
||||
public HellcarverDemonEffect(final HellcarverDemonEffect effect) {
|
||||
|
@ -68,54 +66,25 @@ class HellcarverDemonEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||
if (controller != null && sourceObject != null) {
|
||||
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) {
|
||||
if (!Objects.equals(permanent, sourceObject)) {
|
||||
permanent.sacrifice(source, game);
|
||||
}
|
||||
}
|
||||
if (!controller.getHand().isEmpty()) {
|
||||
int cardsInHand = controller.getHand().size();
|
||||
controller.discard(cardsInHand, false, false, source, game);
|
||||
}
|
||||
// move cards from library to exile
|
||||
Set<Card> currentExiledCards = new HashSet<>();
|
||||
currentExiledCards.addAll(controller.getLibrary().getTopCards(game, 6));
|
||||
controller.moveCardsToExile(currentExiledCards, source, game, true,
|
||||
source.getSourceId(), sourceObject.getIdName());
|
||||
|
||||
// cast the possible cards without paying the mana
|
||||
Cards cardsToCast = new CardsImpl();
|
||||
cardsToCast.addAll(currentExiledCards);
|
||||
boolean alreadyCast = false;
|
||||
while (controller.canRespond() && !cardsToCast.isEmpty()) {
|
||||
if (!controller.chooseUse(outcome, "Cast a" + (alreadyCast ? "another" : "")
|
||||
+ " card exiled with " + sourceObject.getLogName()
|
||||
+ " without paying its mana cost?", source, game)) {
|
||||
break;
|
||||
}
|
||||
TargetCard targetCard = new TargetCard(1, Zone.EXILED,
|
||||
new FilterNonlandCard("nonland card to cast for free"));
|
||||
if (controller.choose(Outcome.PlayForFree, cardsToCast, targetCard, game)) {
|
||||
alreadyCast = true;
|
||||
Card card = game.getCard(targetCard.getFirstTarget());
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
cardsToCast.remove(card);
|
||||
if (!cardWasCast) {
|
||||
game.informPlayer(controller, "You're not able to cast "
|
||||
+ card.getIdName() + " or you canceled the casting.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
MageObjectReference sourceMor = new MageObjectReference(source);
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(
|
||||
StaticFilters.FILTER_CONTROLLED_PERMANENT,
|
||||
source.getControllerId(), source.getSourceId(), game
|
||||
)) {
|
||||
if (!sourceMor.refersTo(permanent, game)) {
|
||||
permanent.sacrifice(source, game);
|
||||
}
|
||||
}
|
||||
controller.discard(controller.getHand(), false, source, game);
|
||||
CardUtil.castMultipleWithAttributeForFree(
|
||||
controller, source, game, new CardsImpl(
|
||||
controller.getLibrary().getTopCards(game, 6)
|
||||
), StaticFilters.FILTER_CARD
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,25 +1,28 @@
|
|||
package mage.cards.i;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.common.FilterPermanentCard;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.TargetController;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author weirddan455
|
||||
*/
|
||||
public final class InSearchOfGreatness extends CardImpl {
|
||||
|
@ -30,8 +33,8 @@ public final class InSearchOfGreatness extends CardImpl {
|
|||
// At the beginning of your upkeep, you may cast a permanent spell from your hand with converted mana cost
|
||||
// equal to 1 plus the highest converted mana cost among other permanents you control
|
||||
// without paying its mana cost. If you don't, scry 1.
|
||||
this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new InSearchOfGreatnessEffect(),
|
||||
TargetController.YOU, false, false
|
||||
this.addAbility(new BeginningOfUpkeepTriggeredAbility(
|
||||
new InSearchOfGreatnessEffect(), TargetController.YOU, false
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -69,35 +72,19 @@ class InSearchOfGreatnessEffect extends OneShotEffect {
|
|||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
int cmc = 0;
|
||||
UUID permId = source.getSourceId();
|
||||
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(controller.getId())) {
|
||||
if (permanent != null && !permanent.getId().equals(permId)) {
|
||||
int permCmc = permanent.getManaValue();
|
||||
if (permCmc > cmc) {
|
||||
cmc = permCmc;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.chooseUse(outcome, "Cast a permanent spell from your hand with CMC equal to "
|
||||
+ ++cmc + "?", source, game)) {
|
||||
FilterPermanentCard filter = new FilterPermanentCard("permanent spell from your hand");
|
||||
filter.add(Predicates.not(CardType.LAND.getPredicate()));
|
||||
filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, cmc));
|
||||
TargetCardInHand target = new TargetCardInHand(filter);
|
||||
if (controller.chooseTarget(outcome, target, source, game)) {
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
if (cardWasCast) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return controller.scry(1, source, game);
|
||||
MageObjectReference sourceRef = new MageObjectReference(source);
|
||||
int manaValue = game
|
||||
.getBattlefield()
|
||||
.getActivePermanents(StaticFilters.FILTER_CONTROLLED_PERMANENT, controller.getId(), game)
|
||||
.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(permanent -> !sourceRef.refersTo(permanent, game))
|
||||
.mapToInt(MageObject::getManaValue)
|
||||
.sum();
|
||||
FilterCard filter = new FilterCard();
|
||||
filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, manaValue + 1));
|
||||
return CardUtil.castSpellWithAttributesForFree(
|
||||
controller, source, game, new CardsImpl(controller.getHand()), filter
|
||||
) || controller.scry(1, source, game);
|
||||
}
|
||||
}
|
||||
|
|
135
Mage.Sets/src/mage/cards/i/InvokeCalamity.java
Normal file
135
Mage.Sets/src/mage/cards/i/InvokeCalamity.java
Normal file
|
@ -0,0 +1,135 @@
|
|||
package mage.cards.i;
|
||||
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.abilities.effects.common.ExileSpellEffect;
|
||||
import mage.cards.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class InvokeCalamity extends CardImpl {
|
||||
|
||||
public InvokeCalamity(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}{R}{R}{R}");
|
||||
|
||||
// You may cast up to two instant and/or sorcery spells with total mana value 6 or less from your graveyard and/or hand without paying their mana costs. If those spells would be put into your graveyard, exile them instead. Exile Invoke Calamity.
|
||||
this.getSpellAbility().addEffect(new InvokeCalamityEffect());
|
||||
this.getSpellAbility().addEffect(new ExileSpellEffect());
|
||||
}
|
||||
|
||||
private InvokeCalamity(final InvokeCalamity card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InvokeCalamity copy() {
|
||||
return new InvokeCalamity(this);
|
||||
}
|
||||
}
|
||||
|
||||
class InvokeCalamityEffect extends OneShotEffect {
|
||||
|
||||
InvokeCalamityEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "you may cast up to two instant and/or sorcery spells " +
|
||||
"with total mana value 6 or less from your graveyard and/or hand without paying their mana costs. " +
|
||||
"If those spells would be put into your graveyard, exile them instead";
|
||||
}
|
||||
|
||||
private InvokeCalamityEffect(final InvokeCalamityEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InvokeCalamityEffect copy() {
|
||||
return new InvokeCalamityEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
Cards cards = new CardsImpl(player.getHand());
|
||||
cards.addAll(player.getGraveyard());
|
||||
CardUtil.castMultipleWithAttributeForFree(
|
||||
player, source, game, cards,
|
||||
StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY,
|
||||
2, new InvokeCalamityTracker()
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class InvokeCalamityTracker implements CardUtil.SpellCastTracker {
|
||||
|
||||
private int totalManaValue = 0;
|
||||
|
||||
@Override
|
||||
public boolean checkCard(Card card, Game game) {
|
||||
return card.getManaValue() + totalManaValue <= 6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCard(Card card, Ability source, Game game) {
|
||||
totalManaValue += card.getManaValue();
|
||||
game.addEffect(new InvokeCalamityReplacementEffect(card, game), source);
|
||||
}
|
||||
}
|
||||
|
||||
class InvokeCalamityReplacementEffect extends ReplacementEffectImpl {
|
||||
|
||||
private final MageObjectReference mor;
|
||||
|
||||
InvokeCalamityReplacementEffect(Card card, Game game) {
|
||||
super(Duration.EndOfTurn, Outcome.Exile);
|
||||
this.mor = new MageObjectReference(card.getMainCard(), game);
|
||||
}
|
||||
|
||||
private InvokeCalamityReplacementEffect(final InvokeCalamityReplacementEffect effect) {
|
||||
super(effect);
|
||||
this.mor = effect.mor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InvokeCalamityReplacementEffect copy() {
|
||||
return new InvokeCalamityReplacementEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Card card = mor.getCard(game);
|
||||
return controller != null
|
||||
&& card != null
|
||||
&& controller.moveCards(card, Zone.EXILED, source, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||
return zEvent.getToZone() == Zone.GRAVEYARD
|
||||
&& zEvent.getTargetId().equals(mor.getSourceId());
|
||||
}
|
||||
}
|
|
@ -9,37 +9,26 @@ import mage.abilities.costs.mana.ManaCostsImpl;
|
|||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.ExileTargetEffect;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.cards.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterOwnedCard;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.ExileZone;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
import mage.target.common.TargetCardInGraveyard;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class IzzetChemister extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterOwnedCard("instant or sorcery card from your graveyard");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.or(
|
||||
CardType.INSTANT.getPredicate(),
|
||||
CardType.SORCERY.getPredicate())
|
||||
);
|
||||
}
|
||||
|
||||
public IzzetChemister(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
|
||||
|
||||
|
@ -51,15 +40,16 @@ public final class IzzetChemister extends CardImpl {
|
|||
// Haste
|
||||
this.addAbility(HasteAbility.getInstance());
|
||||
|
||||
// R, T: Exile target instant or sorcery card from your graveyard.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect(this.getId(), this.getIdName()), new ManaCostsImpl("{R}"));
|
||||
// {R}, {T}: Exile target instant or sorcery card from your graveyard.
|
||||
Ability ability = new SimpleActivatedAbility(
|
||||
new ExileTargetEffect().setToSourceExileZone(true), new ManaCostsImpl<>("{R}")
|
||||
);
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addTarget(new TargetCard(Zone.GRAVEYARD, filter));
|
||||
ability.addTarget(new TargetCardInGraveyard(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY_FROM_YOUR_GRAVEYARD));
|
||||
this.addAbility(ability);
|
||||
|
||||
// 1R, T: Sacrifice Izzet Chemister: Cast any number of cards exiled with Izzet Chemister without paying their mana costs.
|
||||
IzzetChemisterCastFromExileEffect returnFromExileEffect = new IzzetChemisterCastFromExileEffect(this.getId(), "Cast any number of cards exiled with {this} without paying their mana costs.");
|
||||
ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, returnFromExileEffect, new ManaCostsImpl("{1}{R}"));
|
||||
// {1}{R}, {T}: Sacrifice Izzet Chemister: Cast any number of cards exiled with Izzet Chemister without paying their mana costs.
|
||||
ability = new SimpleActivatedAbility(new IzzetChemisterCastFromExileEffect(), new ManaCostsImpl<>("{1}{R}"));
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addCost(new SacrificeSourceCost());
|
||||
this.addAbility(ability);
|
||||
|
@ -77,17 +67,13 @@ public final class IzzetChemister extends CardImpl {
|
|||
|
||||
class IzzetChemisterCastFromExileEffect extends OneShotEffect {
|
||||
|
||||
private final UUID exileId;
|
||||
|
||||
public IzzetChemisterCastFromExileEffect(UUID exileId, String description) {
|
||||
public IzzetChemisterCastFromExileEffect() {
|
||||
super(Outcome.PlayForFree);
|
||||
this.exileId = exileId;
|
||||
this.setText(description);
|
||||
staticText = "cast any number of cards exiled with {this} without paying their mana costs";
|
||||
}
|
||||
|
||||
public IzzetChemisterCastFromExileEffect(final IzzetChemisterCastFromExileEffect effect) {
|
||||
super(effect);
|
||||
this.exileId = effect.exileId;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -97,38 +83,15 @@ class IzzetChemisterCastFromExileEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
ExileZone exile = game.getExile().getExileZone(exileId);
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
FilterCard filter = new FilterCard();
|
||||
if (controller != null
|
||||
&& exile != null) {
|
||||
Cards cardsToExile = new CardsImpl();
|
||||
cardsToExile.addAll(exile.getCards(game));
|
||||
OuterLoop:
|
||||
while (cardsToExile.count(filter, game) > 0) {
|
||||
if (!controller.canRespond()) {
|
||||
return false;
|
||||
}
|
||||
TargetCardInExile target = new TargetCardInExile(0, 1, filter, exileId, false);
|
||||
target.setNotTarget(true);
|
||||
while (controller.canRespond()
|
||||
&& cardsToExile.count(filter, game) > 0
|
||||
&& controller.choose(Outcome.PlayForFree, cardsToExile, target, game)) {
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
controller.cast(controller.chooseAbilityForCast(card, game, true), game, true,
|
||||
new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
cardsToExile.remove(card);
|
||||
} else {
|
||||
break OuterLoop;
|
||||
}
|
||||
target.clearChosen();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
ExileZone exile = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source));
|
||||
if (controller == null || exile == null || exile.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
CardUtil.castMultipleWithAttributeForFree(
|
||||
controller, source, game, new CardsImpl(exile),
|
||||
StaticFilters.FILTER_CARD
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,21 +5,20 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.*;
|
||||
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.StaticFilters;
|
||||
import mage.filter.common.FilterInstantOrSorceryCard;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
|
@ -75,44 +74,15 @@ class JaceMindseekerEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Cards cardsToCast = new CardsImpl();
|
||||
Player targetOpponent = game.getPlayer(targetPointer.getFirst(game, source));
|
||||
if (targetOpponent != null) {
|
||||
Set<Card> allCards = targetOpponent.millCards(5, source, game).getCards(game);
|
||||
for (Card card : allCards) {
|
||||
if (filter.match(card, game)) {
|
||||
Zone zone = game.getState().getZone(card.getId());
|
||||
// If the five cards are put into a public zone such as exile instead
|
||||
// of a graveyard (perhaps due to the ability of Rest in Peace),
|
||||
// you can cast one of those instant or sorcery cards from that zone.
|
||||
if (zone == Zone.GRAVEYARD
|
||||
|| zone == Zone.EXILED) {
|
||||
cardsToCast.add(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cast an instant or sorcery for free
|
||||
if (!cardsToCast.isEmpty()) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
TargetCard target = new TargetCard(Zone.GRAVEYARD, filter); // zone should be ignored here
|
||||
target.setNotTarget(true);
|
||||
if (controller.chooseUse(outcome, "Cast an instant or sorcery card from among them for free?", source, game)
|
||||
&& controller.choose(Outcome.PlayForFree, cardsToCast, target, game)) {
|
||||
Card card = cardsToCast.get(target.getFirstTarget(), game);
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Player opponent = game.getPlayer(source.getFirstTarget());
|
||||
if (controller == null || opponent == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
return CardUtil.castSpellWithAttributesForFree(
|
||||
controller, source, game,
|
||||
opponent.millCards(5, source, game),
|
||||
StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
package mage.cards.j;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
|
@ -11,27 +7,25 @@ import mage.abilities.common.AttacksTriggeredAbility;
|
|||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
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.SuperType;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.filter.common.FilterInstantOrSorceryCard;
|
||||
import mage.game.ExileZone;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.*;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
import mage.util.CardUtil;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public final class JelevaNephaliasScourge extends CardImpl {
|
||||
|
@ -112,8 +106,8 @@ class JelevaNephaliasCastEffect extends OneShotEffect {
|
|||
|
||||
public JelevaNephaliasCastEffect() {
|
||||
super(Outcome.PlayForFree);
|
||||
this.staticText = "you may cast an instant or sorcery card "
|
||||
+ "exiled with it without paying its mana cost";
|
||||
this.staticText = "you may cast an instant or sorcery spell " +
|
||||
"from among cards exiled with {this} without paying its mana cost";
|
||||
}
|
||||
|
||||
public JelevaNephaliasCastEffect(final JelevaNephaliasCastEffect effect) {
|
||||
|
@ -128,29 +122,14 @@ class JelevaNephaliasCastEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
ExileZone exileZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source));
|
||||
if (exileZone != null
|
||||
&& exileZone.count(new FilterInstantOrSorceryCard(), game) > 0) {
|
||||
if (controller.chooseUse(outcome, "Cast an instant or sorcery card from "
|
||||
+ "exile without paying its mana cost?", source, game)) {
|
||||
TargetCardInExile target = new TargetCardInExile(
|
||||
new FilterInstantOrSorceryCard(), CardUtil.getCardExileZoneId(game, source));
|
||||
if (controller.choose(Outcome.PlayForFree, exileZone, target, game)) {
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
return cardWasCast;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
Cards cards = new CardsImpl(game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source)));
|
||||
return CardUtil.castSpellWithAttributesForFree(
|
||||
controller, source, game, cards,
|
||||
StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,8 +149,8 @@ class JelevaNephaliasWatcher extends Watcher {
|
|||
for (StackObject stackObject : game.getStack()) {
|
||||
if (stackObject instanceof Spell) {
|
||||
Spell spell = (Spell) stackObject;
|
||||
manaSpendToCast.putIfAbsent(spell.getSourceId().toString()
|
||||
+ spell.getCard().getZoneChangeCounter(game),
|
||||
manaSpendToCast.putIfAbsent(spell.getSourceId().toString()
|
||||
+ spell.getCard().getZoneChangeCounter(game),
|
||||
spell.getSpellAbility().getManaCostsToPay().manaValue());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package mage.cards.k;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
|
@ -11,23 +9,21 @@ import mage.abilities.costs.common.TapSourceCost;
|
|||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.SearchEffect;
|
||||
import mage.cards.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.Zone;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public final class KahoMinamoHistorian extends CardImpl {
|
||||
|
@ -109,8 +105,8 @@ class KahoMinamoHistorianCastEffect extends OneShotEffect {
|
|||
|
||||
public KahoMinamoHistorianCastEffect() {
|
||||
super(Outcome.PlayForFree);
|
||||
this.staticText = "you may cast a card with mana value X "
|
||||
+ "exiled with {this} without paying its mana cost";
|
||||
this.staticText = "you may cast a spell with mana value X " +
|
||||
"from among cards exiled with {this} without paying its mana cost";
|
||||
}
|
||||
|
||||
public KahoMinamoHistorianCastEffect(final KahoMinamoHistorianCastEffect effect) {
|
||||
|
@ -125,24 +121,12 @@ class KahoMinamoHistorianCastEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
FilterCard filter = new FilterCard();
|
||||
filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, source.getManaCostsToPay().getX()));
|
||||
TargetCardInExile target = new TargetCardInExile(filter, CardUtil.getCardExileZoneId(game, source));
|
||||
Cards cards = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source));
|
||||
if (cards != null
|
||||
&& !cards.isEmpty()
|
||||
&& controller.choose(Outcome.PlayForFree, cards, target, game)) {
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
Cards cards = new CardsImpl(game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source)));
|
||||
if (controller == null || cards.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
FilterCard filter = new FilterCard();
|
||||
filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, source.getManaCostsToPay().getX()));
|
||||
return CardUtil.castSpellWithAttributesForFree(controller, source, game, cards, filter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,32 +1,39 @@
|
|||
|
||||
package mage.cards.k;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.effects.common.UntapTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
|
||||
import mage.abilities.effects.common.cost.CastWithoutPayingManaCostEffect;
|
||||
import mage.abilities.effects.common.cost.CastFromHandForFreeEffect;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fireshoes
|
||||
*/
|
||||
public final class KariZevsExpertise extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent("creature or Vehicle");
|
||||
private static final FilterCard filter2 = new FilterCard("a spell with mana value 2 or less");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.or(CardType.CREATURE.getPredicate(),
|
||||
SubType.VEHICLE.getPredicate()));
|
||||
filter.add(Predicates.or(
|
||||
CardType.CREATURE.getPredicate(),
|
||||
SubType.VEHICLE.getPredicate()
|
||||
));
|
||||
filter2.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 3));
|
||||
}
|
||||
|
||||
public KariZevsExpertise(UUID ownerId, CardSetInfo setInfo) {
|
||||
|
@ -36,10 +43,12 @@ public final class KariZevsExpertise extends CardImpl {
|
|||
this.getSpellAbility().addTarget(new TargetPermanent(filter));
|
||||
this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.EndOfTurn));
|
||||
this.getSpellAbility().addEffect(new UntapTargetEffect().setText("Untap it"));
|
||||
this.getSpellAbility().addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn).setText("It gains haste until end of turn"));
|
||||
this.getSpellAbility().addEffect(new GainAbilityTargetEffect(
|
||||
HasteAbility.getInstance(), Duration.EndOfTurn
|
||||
).setText("It gains haste until end of turn"));
|
||||
|
||||
// You may cast a card with converted mana cost 2 or less from your hand without paying its mana cost.
|
||||
this.getSpellAbility().addEffect(new CastWithoutPayingManaCostEffect(2).concatBy("<br>"));
|
||||
this.getSpellAbility().addEffect(new CastFromHandForFreeEffect(filter2).concatBy("<br>"));
|
||||
}
|
||||
|
||||
private KariZevsExpertise(final KariZevsExpertise card) {
|
||||
|
|
|
@ -5,17 +5,19 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.DealsCombatDamageTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
||||
import mage.abilities.effects.common.cost.CastWithoutPayingManaCostEffect;
|
||||
import mage.abilities.keyword.FirstStrikeAbility;
|
||||
import mage.abilities.keyword.ProwessAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -59,12 +61,6 @@ public final class KenBurningBrawler extends CardImpl {
|
|||
|
||||
class KenBurningBrawlerEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("sorcery spell");
|
||||
|
||||
static {
|
||||
filter.add(CardType.SORCERY.getPredicate());
|
||||
}
|
||||
|
||||
KenBurningBrawlerEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "you may cast a sorcery spell from your hand with mana value " +
|
||||
|
@ -82,8 +78,13 @@ class KenBurningBrawlerEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return new CastWithoutPayingManaCostEffect(
|
||||
StaticValue.get((Integer) getValue("damage")), filter
|
||||
).apply(game, source);
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null || player.getHand().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
FilterCard filter = new FilterCard();
|
||||
filter.add(CardType.SORCERY.getPredicate());
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 1 + (Integer) getValue("damage")));
|
||||
return CardUtil.castSpellWithAttributesForFree(player, source, game, new CardsImpl(player.getHand()), filter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,31 +1,24 @@
|
|||
package mage.cards.m;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.cost.CastFromHandForFreeEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
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.filter.FilterCard;
|
||||
import mage.filter.common.FilterNonlandCard;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
public final class MaelstromArchangel extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("a spell");
|
||||
|
||||
public MaelstromArchangel(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{U}{B}{R}{G}");
|
||||
this.subtype.add(SubType.ANGEL);
|
||||
|
@ -37,8 +30,7 @@ public final class MaelstromArchangel extends CardImpl {
|
|||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Whenever Maelstrom Archangel deals combat damage to a player, you may cast a nonland card from your hand without paying its mana cost.
|
||||
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new MaelstromArchangelCastEffect(), false));
|
||||
|
||||
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new CastFromHandForFreeEffect(filter), false));
|
||||
}
|
||||
|
||||
private MaelstromArchangel(final MaelstromArchangel card) {
|
||||
|
@ -50,53 +42,3 @@ public final class MaelstromArchangel extends CardImpl {
|
|||
return new MaelstromArchangel(this);
|
||||
}
|
||||
}
|
||||
|
||||
class MaelstromArchangelCastEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterCard filter = new FilterNonlandCard("spell from your hand");
|
||||
|
||||
public MaelstromArchangelCastEffect() {
|
||||
super(Outcome.PlayForFree);
|
||||
this.staticText = "you may cast a spell from your hand without paying its mana cost";
|
||||
}
|
||||
|
||||
public MaelstromArchangelCastEffect(final MaelstromArchangelCastEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MaelstromArchangelCastEffect copy() {
|
||||
return new MaelstromArchangelCastEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Target target = new TargetCardInHand(filter);
|
||||
if (target.canChoose(source.getSourceId(), controller.getId(), game)
|
||||
&& controller.chooseUse(outcome, "Cast a spell from your hand without paying its mana cost?", source, game)) {
|
||||
Card cardToCast = null;
|
||||
boolean cancel = false;
|
||||
while (controller.canRespond() && !cancel) {
|
||||
if (controller.chooseTarget(outcome, target, source, game)) {
|
||||
cardToCast = game.getCard(target.getFirstTarget());
|
||||
if (cardToCast != null && cardToCast.getSpellAbility().canChooseTarget(game, controller.getId())) {
|
||||
cancel = true;
|
||||
}
|
||||
} else {
|
||||
cancel = true;
|
||||
}
|
||||
}
|
||||
if (cardToCast != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + cardToCast.getId(), Boolean.TRUE);
|
||||
controller.cast(controller.chooseAbilityForCast(cardToCast, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + cardToCast.getId(), null);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,29 +1,25 @@
|
|||
|
||||
package mage.cards.m;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
public final class MindclawShaman extends CardImpl {
|
||||
|
@ -55,14 +51,6 @@ public final class MindclawShaman extends CardImpl {
|
|||
|
||||
class MindclawShamanEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("instant or sorcery card");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.or(
|
||||
CardType.INSTANT.getPredicate(),
|
||||
CardType.SORCERY.getPredicate()));
|
||||
}
|
||||
|
||||
public MindclawShamanEffect() {
|
||||
super(Outcome.PlayForFree);
|
||||
this.staticText = "target opponent reveals their hand. You may cast "
|
||||
|
@ -80,34 +68,15 @@ class MindclawShamanEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player targetOpponent = game.getPlayer(source.getFirstTarget());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (targetOpponent != null && sourceObject != null) {
|
||||
if (!targetOpponent.getHand().isEmpty()) {
|
||||
targetOpponent.revealCards(sourceObject.getName(), targetOpponent.getHand(), game);
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
TargetCard target = new TargetCard(Zone.HAND, filter);
|
||||
target.setNotTarget(true);
|
||||
if (controller.choose(Outcome.PlayForFree, targetOpponent.getHand(), target, game)) {
|
||||
Card chosenCard = targetOpponent.getHand().get(target.getFirstTarget(), game);
|
||||
if (chosenCard != null) {
|
||||
if (controller.chooseUse(Outcome.PlayForFree, "Cast the chosen card without "
|
||||
+ "paying its mana cost?", source, game)) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + chosenCard.getId(), Boolean.TRUE);
|
||||
controller.cast(controller.chooseAbilityForCast(chosenCard, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + chosenCard.getId(), null);
|
||||
} else {
|
||||
game.informPlayers(sourceObject.getLogName() + ": "
|
||||
+ controller.getLogName() + " canceled casting the card.");
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Player opponent = game.getPlayer(source.getFirstTarget());
|
||||
if (controller == null || opponent == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
opponent.revealCards(source, opponent.getHand(), game);
|
||||
return CardUtil.castSpellWithAttributesForFree(
|
||||
controller, source, game, new CardsImpl(opponent.getHand()),
|
||||
StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,24 @@
|
|||
package mage.cards.m;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterNonlandCard;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
public final class MindleechMass extends CardImpl {
|
||||
|
@ -39,7 +35,9 @@ public final class MindleechMass extends CardImpl {
|
|||
|
||||
// Whenever Mindleech Mass deals combat damage to a player, you may look at that
|
||||
// player's hand. If you do, you may cast a nonland card in it without paying that card's mana cost.
|
||||
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new MindleechMassEffect(), true, true));
|
||||
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(
|
||||
new MindleechMassEffect(), true, true
|
||||
));
|
||||
}
|
||||
|
||||
private MindleechMass(final MindleechMass card) {
|
||||
|
@ -56,8 +54,8 @@ class MindleechMassEffect extends OneShotEffect {
|
|||
|
||||
public MindleechMassEffect() {
|
||||
super(Outcome.PlayForFree);
|
||||
this.staticText = "you may look at that player's hand. If you do, "
|
||||
+ "you may cast a nonland card in it without paying that card's mana cost";
|
||||
this.staticText = "look at that player's hand. If you do, you " +
|
||||
"may cast a spell from among those cards without paying its mana cost";
|
||||
}
|
||||
|
||||
public MindleechMassEffect(final MindleechMassEffect effect) {
|
||||
|
@ -71,27 +69,15 @@ class MindleechMassEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (opponent != null && controller != null) {
|
||||
Cards cardsInHand = new CardsImpl();
|
||||
cardsInHand.addAll(opponent.getHand());
|
||||
opponent.revealCards("Opponents hand", cardsInHand, game);
|
||||
if (!cardsInHand.isEmpty()
|
||||
&& !cardsInHand.getCards(new FilterNonlandCard(), game).isEmpty()) {
|
||||
TargetCard target = new TargetCard(1, Zone.HAND, new FilterNonlandCard());
|
||||
if (controller.chooseTarget(Outcome.PlayForFree, cardsInHand, target, source, game)) {
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
if (controller == null || opponent == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
controller.lookAtCards(opponent.getName(), opponent.getHand(), game);
|
||||
return CardUtil.castSpellWithAttributesForFree(
|
||||
controller, source, game, new CardsImpl(opponent.getHand()),
|
||||
StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,22 @@
|
|||
package mage.cards.m;
|
||||
|
||||
import mage.ApprovingObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterInstantOrSorceryCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -60,36 +63,21 @@ class MuseVortexEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
int xValue = source.getManaCostsToPay().getX();
|
||||
if (player == null || xValue < 1) {
|
||||
return false;
|
||||
}
|
||||
int xValue = source.getManaCostsToPay().getX();
|
||||
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, xValue));
|
||||
controller.moveCards(cards, Zone.EXILED, source, game);
|
||||
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, xValue));
|
||||
player.moveCards(cards, Zone.EXILED, source, game);
|
||||
cards.retainZone(Zone.EXILED, game);
|
||||
FilterCard filter = new FilterInstantOrSorceryCard("an instant or sorcery card with mana value " + xValue + " or less");
|
||||
FilterCard filter = new FilterInstantOrSorceryCard();
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, xValue + 1));
|
||||
TargetCardInExile target = new TargetCardInExile(filter);
|
||||
target.setNotTarget(true);
|
||||
if (controller.choose(Outcome.Benefit, cards, target, game)) {
|
||||
Card card = cards.get(target.getFirstTarget(), game);
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
cards.remove(card);
|
||||
if (cardWasCast) {
|
||||
cards.remove(card);
|
||||
} else {
|
||||
game.informPlayer(controller, "You're not able to cast "
|
||||
+ card.getIdName() + " or you canceled the casting.");
|
||||
}
|
||||
controller.putCardsOnTopOfLibrary(cards, game, source, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
CardUtil.castSpellWithAttributesForFree(player, source, game, cards, filter);
|
||||
cards.retainZone(Zone.EXILED, game);
|
||||
player.moveCards(cards.getCards(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY, game), Zone.HAND, source, game);
|
||||
cards.retainZone(Zone.EXILED, game);
|
||||
player.putCardsOnBottomOfLibrary(cards, game, source, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,30 +5,23 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.abilities.effects.common.cost.CastFromHandForFreeEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterInstantOrSorceryCard;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.CardIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class OmnispellAdept extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterInstantOrSorceryCard("an instant or sorcery spell");
|
||||
|
||||
public OmnispellAdept(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}");
|
||||
|
||||
|
@ -40,7 +33,7 @@ public final class OmnispellAdept extends CardImpl {
|
|||
// {2}{U}, {T}: You may cast an instant or sorcery card from your hand
|
||||
// without paying its mana cost.
|
||||
Ability ability = new SimpleActivatedAbility(
|
||||
new OmnispellAdeptEffect(), new ManaCostsImpl("{2}{U}")
|
||||
new CastFromHandForFreeEffect(filter), new ManaCostsImpl<>("{2}{U}")
|
||||
);
|
||||
ability.addCost(new TapSourceCost());
|
||||
this.addAbility(ability);
|
||||
|
@ -55,65 +48,3 @@ public final class OmnispellAdept extends CardImpl {
|
|||
return new OmnispellAdept(this);
|
||||
}
|
||||
}
|
||||
|
||||
class OmnispellAdeptEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterCard filter = new FilterInstantOrSorceryCard(
|
||||
"instant or sorcery card from your hand");
|
||||
|
||||
public OmnispellAdeptEffect() {
|
||||
super(Outcome.PlayForFree);
|
||||
this.staticText = "you may cast an instant or sorcery card from your hand "
|
||||
+ "without paying its mana cost";
|
||||
}
|
||||
|
||||
public OmnispellAdeptEffect(final OmnispellAdeptEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OmnispellAdeptEffect copy() {
|
||||
return new OmnispellAdeptEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
FilterCard realFilter = filter.copy();
|
||||
Target target = new TargetCardInHand(realFilter);
|
||||
// choose one card until it possible to cast
|
||||
if (target.canChoose(source.getSourceId(), controller.getId(), game)
|
||||
&& controller.chooseUse(Outcome.PlayForFree, "Cast an instant or sorcery "
|
||||
+ "card from your hand without paying its mana cost?", source, game)) {
|
||||
Card cardToCast;
|
||||
while (controller.canRespond()
|
||||
&& controller.chooseTarget(Outcome.PlayForFree, target, source, game)) {
|
||||
cardToCast = game.getCard(target.getFirstTarget());
|
||||
if (cardToCast == null) {
|
||||
break;
|
||||
}
|
||||
realFilter.add(Predicates.not(new CardIdPredicate(cardToCast.getId()))); // remove card from choose dialog (infinite fix)
|
||||
|
||||
if (!cardToCast.getSpellAbility().canChooseTarget(game, controller.getId())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + cardToCast.getId(), Boolean.TRUE);
|
||||
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(cardToCast, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + cardToCast.getId(), null);
|
||||
|
||||
if (cardWasCast) {
|
||||
break;
|
||||
} else {
|
||||
game.informPlayer(controller, "You're not able to cast "
|
||||
+ cardToCast.getIdName() + " or you canceled the casting.");
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,31 +1,21 @@
|
|||
package mage.cards.o;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.common.TributeNotPaidCondition;
|
||||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.cost.CastFromHandForFreeEffect;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.abilities.keyword.TributeAbility;
|
||||
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.filter.FilterCard;
|
||||
import mage.filter.common.FilterInstantOrSorceryCard;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
import mage.filter.StaticFilters;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public final class OracleOfBones extends CardImpl {
|
||||
|
@ -44,10 +34,14 @@ public final class OracleOfBones extends CardImpl {
|
|||
this.addAbility(new TributeAbility(2));
|
||||
// When Oracle of Bones enters the battlefield, if tribute wasn't paid,
|
||||
// you may cast an instant or sorcery card from your hand without paying its mana cost.
|
||||
TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new OracleOfBonesCastEffect(), false);
|
||||
this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance,
|
||||
"When {this} enters the battlefield, if its tribute wasn't paid, "
|
||||
+ "you may cast an instant or sorcery card from your hand without paying its mana cost."));
|
||||
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
|
||||
new EntersBattlefieldTriggeredAbility(new CastFromHandForFreeEffect(
|
||||
StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY
|
||||
), false),
|
||||
TributeNotPaidCondition.instance, "When {this} enters the battlefield, " +
|
||||
"if its tribute wasn't paid, you may cast an instant or " +
|
||||
"sorcery spell from your hand without paying its mana cost."
|
||||
));
|
||||
}
|
||||
|
||||
private OracleOfBones(final OracleOfBones card) {
|
||||
|
@ -59,58 +53,3 @@ public final class OracleOfBones extends CardImpl {
|
|||
return new OracleOfBones(this);
|
||||
}
|
||||
}
|
||||
|
||||
class OracleOfBonesCastEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterCard filter = new FilterInstantOrSorceryCard(
|
||||
"instant or sorcery card from your hand");
|
||||
|
||||
public OracleOfBonesCastEffect() {
|
||||
super(Outcome.PlayForFree);
|
||||
this.staticText = "you may cast an instant or sorcery card "
|
||||
+ "from your hand without paying its mana cost";
|
||||
}
|
||||
|
||||
public OracleOfBonesCastEffect(final OracleOfBonesCastEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OracleOfBonesCastEffect copy() {
|
||||
return new OracleOfBonesCastEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Target target = new TargetCardInHand(filter);
|
||||
if (target.canChoose(source.getSourceId(), controller.getId(), game)
|
||||
&& controller.chooseUse(outcome, "Cast an instant or sorcery "
|
||||
+ "card from your hand without paying its mana cost?", source, game)) {
|
||||
Card cardToCast = null;
|
||||
boolean cancel = false;
|
||||
while (controller.canRespond()
|
||||
&& !cancel) {
|
||||
if (controller.chooseTarget(outcome, target, source, game)) {
|
||||
cardToCast = game.getCard(target.getFirstTarget());
|
||||
if (cardToCast != null
|
||||
&& cardToCast.getSpellAbility().canChooseTarget(game, controller.getId())) {
|
||||
cancel = true;
|
||||
}
|
||||
} else {
|
||||
cancel = true;
|
||||
}
|
||||
}
|
||||
if (cardToCast != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + cardToCast.getId(), Boolean.TRUE);
|
||||
controller.cast(controller.chooseAbilityForCast(cardToCast, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + cardToCast.getId(), null);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,14 +2,18 @@ package mage.cards.r;
|
|||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.cost.CastWithoutPayingManaCostEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetSpell;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -56,12 +60,17 @@ class ReinterpretEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Spell spell = game.getSpell(source.getFirstTarget());
|
||||
if (spell == null) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (spell == null || controller == null) {
|
||||
return false;
|
||||
}
|
||||
int manaValue = spell.getManaValue();
|
||||
game.getStack().counter(spell.getId(), source, game);
|
||||
new CastWithoutPayingManaCostEffect(manaValue).apply(game, source);
|
||||
spell.counter(source, game);
|
||||
FilterCard filter = new FilterCard();
|
||||
filter.add(new ManaValuePredicate(
|
||||
ComparisonType.FEWER_THAN, manaValue + 1
|
||||
));
|
||||
CardUtil.castSpellWithAttributesForFree(controller, source, game, controller.getHand(), filter);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,29 @@
|
|||
|
||||
package mage.cards.r;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.cost.CastWithoutPayingManaCostEffect;
|
||||
import mage.abilities.effects.common.cost.CastFromHandForFreeEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author fireshoes
|
||||
*/
|
||||
public final class RishkarsExpertise extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("a spell with mana value 5 or less");
|
||||
|
||||
static {
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 6));
|
||||
}
|
||||
|
||||
public RishkarsExpertise(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{G}{G}");
|
||||
|
||||
|
@ -24,7 +33,7 @@ public final class RishkarsExpertise extends CardImpl {
|
|||
this.getSpellAbility().addEffect(effect);
|
||||
|
||||
// You may cast a card with converted mana cost 5 or less from your hand without paying its mana cost.
|
||||
this.getSpellAbility().addEffect(new CastWithoutPayingManaCostEffect(5).concatBy("<br>"));
|
||||
this.getSpellAbility().addEffect(new CastFromHandForFreeEffect(filter).concatBy("<br>"));
|
||||
}
|
||||
|
||||
private RishkarsExpertise(final RishkarsExpertise card) {
|
||||
|
|
200
Mage.Sets/src/mage/cards/r/RodOfAbsorption.java
Normal file
200
Mage.Sets/src/mage/cards/r/RodOfAbsorption.java
Normal file
|
@ -0,0 +1,200 @@
|
|||
package mage.cards.r;
|
||||
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.cards.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class RodOfAbsorption extends CardImpl {
|
||||
|
||||
public RodOfAbsorption(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{U}");
|
||||
|
||||
// Whenever a player casts an instant or sorcery spell, exile it instead of putting it into a graveyard as it resolves.
|
||||
this.addAbility(new RodOfAbsorptionTriggeredAbility());
|
||||
|
||||
// {X}, {T}, Sacrifice Rod of Absorption: You may cast any number of spells from among cards exiled with Rod of Absorption with total mana value X or less without paying their mana costs.
|
||||
Ability ability = new SimpleActivatedAbility(new RodOfAbsorptionCastEffect(), new ManaCostsImpl<>("{X}"));
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addCost(new SacrificeSourceCost());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private RodOfAbsorption(final RodOfAbsorption card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RodOfAbsorption copy() {
|
||||
return new RodOfAbsorption(this);
|
||||
}
|
||||
}
|
||||
|
||||
class RodOfAbsorptionTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
RodOfAbsorptionTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, null, false);
|
||||
}
|
||||
|
||||
private RodOfAbsorptionTriggeredAbility(final RodOfAbsorptionTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RodOfAbsorptionTriggeredAbility copy() {
|
||||
return new RodOfAbsorptionTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.SPELL_CAST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Spell spell = game.getStack().getSpell(event.getTargetId());
|
||||
if (spell == null || !spell.isInstantOrSorcery(game)) {
|
||||
return false;
|
||||
}
|
||||
this.getEffects().clear();
|
||||
this.addEffect(new RodOfAbsorptionExileEffect(spell, game));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever a player casts an instant or sorcery spell, " +
|
||||
"exile it instead of putting it into a graveyard as it resolves.";
|
||||
}
|
||||
}
|
||||
|
||||
class RodOfAbsorptionExileEffect extends ReplacementEffectImpl {
|
||||
|
||||
private final MageObjectReference mor;
|
||||
|
||||
RodOfAbsorptionExileEffect(Spell spell, Game game) {
|
||||
super(Duration.WhileOnStack, Outcome.Benefit);
|
||||
this.mor = new MageObjectReference(spell, game);
|
||||
}
|
||||
|
||||
private RodOfAbsorptionExileEffect(final RodOfAbsorptionExileEffect effect) {
|
||||
super(effect);
|
||||
this.mor = effect.mor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
Spell sourceSpell = game.getStack().getSpell(event.getTargetId());
|
||||
if (sourceSpell == null || sourceSpell.isCopy()) {
|
||||
return false;
|
||||
}
|
||||
Player player = game.getPlayer(sourceSpell.getOwnerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
player.moveCardsToExile(
|
||||
sourceSpell, source, game, false,
|
||||
CardUtil.getExileZoneId(game, source),
|
||||
CardUtil.getSourceName(game, source)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
ZoneChangeEvent zEvent = ((ZoneChangeEvent) event);
|
||||
if (zEvent.getFromZone() != Zone.STACK
|
||||
|| zEvent.getToZone() != Zone.GRAVEYARD
|
||||
|| event.getSourceId() == null
|
||||
|| !event.getSourceId().equals(event.getTargetId())
|
||||
|| mor.getZoneChangeCounter() != game.getState().getZoneChangeCounter(event.getSourceId())) {
|
||||
return false;
|
||||
}
|
||||
Spell spell = game.getStack().getSpell(mor.getSourceId());
|
||||
return spell != null && spell.isInstantOrSorcery(game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RodOfAbsorptionExileEffect copy() {
|
||||
return new RodOfAbsorptionExileEffect(this);
|
||||
}
|
||||
}
|
||||
|
||||
class RodOfAbsorptionCastEffect extends OneShotEffect {
|
||||
|
||||
RodOfAbsorptionCastEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "you may cast any number of spells from among cards exiled with " +
|
||||
"{this} with total mana value X or less without paying their mana costs";
|
||||
}
|
||||
|
||||
private RodOfAbsorptionCastEffect(final RodOfAbsorptionCastEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RodOfAbsorptionCastEffect copy() {
|
||||
return new RodOfAbsorptionCastEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Cards cards = new CardsImpl(game.getExile().getExileZone(CardUtil.getExileZoneId(game, source)));
|
||||
if (player == null || cards.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
CardUtil.castMultipleWithAttributeForFree(
|
||||
player, source, game, cards, StaticFilters.FILTER_CARD, Integer.MAX_VALUE,
|
||||
new RodOfAbsorptionTracker(source.getManaCostsToPay().getX())
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class RodOfAbsorptionTracker implements CardUtil.SpellCastTracker {
|
||||
|
||||
private final int xValue;
|
||||
private int totalManaValue = 0;
|
||||
|
||||
RodOfAbsorptionTracker(int xValue) {
|
||||
this.xValue = xValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkCard(Card card, Game game) {
|
||||
return card.getManaValue() + totalManaValue <= xValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCard(Card card, Ability source, Game game) {
|
||||
totalManaValue += card.getManaValue();
|
||||
}
|
||||
}
|
|
@ -1,22 +1,18 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.predicate.ObjectSourcePlayer;
|
||||
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||
import mage.filter.predicate.Predicates;
|
||||
|
@ -27,11 +23,11 @@ import mage.game.stack.StackObject;
|
|||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.TargetSpell;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public final class ShellOfTheLastKappa extends CardImpl {
|
||||
|
@ -50,16 +46,18 @@ public final class ShellOfTheLastKappa extends CardImpl {
|
|||
addSuperType(SuperType.LEGENDARY);
|
||||
|
||||
// {3}, {tap}: Exile target instant or sorcery spell that targets you.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
||||
new ShellOfTheLastKappaEffect(), new ManaCostsImpl("{3}"));
|
||||
Ability ability = new SimpleActivatedAbility(
|
||||
new ShellOfTheLastKappaEffect(), new GenericManaCost(3)
|
||||
);
|
||||
ability.addCost(new TapSourceCost());
|
||||
Target target = new TargetSpell(filter);
|
||||
ability.addTarget(target);
|
||||
this.addAbility(ability);
|
||||
// {3}, {tap}, Sacrifice Shell of the Last Kappa: You may cast a card
|
||||
// exiled with Shell of the Last Kappa without paying its mana cost.
|
||||
ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
||||
new ShellOfTheLastKappaCastEffect(), new ManaCostsImpl("{3}"));
|
||||
ability = new SimpleActivatedAbility(
|
||||
new ShellOfTheLastKappaCastEffect(), new GenericManaCost(3)
|
||||
);
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addCost(new SacrificeSourceCost());
|
||||
this.addAbility(ability);
|
||||
|
@ -118,7 +116,7 @@ class ShellOfTheLastKappaCastEffect extends OneShotEffect {
|
|||
|
||||
public ShellOfTheLastKappaCastEffect() {
|
||||
super(Outcome.PlayForFree);
|
||||
this.staticText = "You may cast a card exiled with {this} without paying its mana cost";
|
||||
this.staticText = "You may cast a spell from among cards exiled with {this} without paying its mana cost";
|
||||
}
|
||||
|
||||
public ShellOfTheLastKappaCastEffect(final ShellOfTheLastKappaCastEffect effect) {
|
||||
|
@ -134,25 +132,11 @@ class ShellOfTheLastKappaCastEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||
if (controller != null
|
||||
&& sourcePermanent != null) {
|
||||
TargetCardInExile target = new TargetCardInExile(new FilterCard(),
|
||||
CardUtil.getExileZoneId(game, source.getSourceId(), sourcePermanent.getZoneChangeCounter(game)));
|
||||
if (controller.choose(Outcome.PlayForFree, game.getExile()
|
||||
.getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(),
|
||||
sourcePermanent.getZoneChangeCounter(game))), target, game)) {
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card != null
|
||||
&& controller.chooseUse(outcome, "Cast " + card.getLogName() + " without paying its mana cost?", source, game)) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
return cardWasCast;
|
||||
}
|
||||
}
|
||||
if (controller == null || sourcePermanent == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
Cards cards = new CardsImpl(game.getExile().getExileZone(CardUtil.getExileZoneId(game, source)));
|
||||
return CardUtil.castSpellWithAttributesForFree(controller, source, game, cards, StaticFilters.FILTER_CARD);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,21 +3,20 @@ package mage.cards.s;
|
|||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.NinjutsuAbility;
|
||||
import mage.cards.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
|
@ -56,8 +55,8 @@ class SilentBladeOniEffect extends OneShotEffect {
|
|||
|
||||
SilentBladeOniEffect() {
|
||||
super(Outcome.PlayForFree);
|
||||
this.staticText = "look at that player's hand. "
|
||||
+ "You may cast a nonland card in it without paying that card's mana cost";
|
||||
this.staticText = "look at that player's hand. You may cast a spell " +
|
||||
"from among those cards without paying its mana cost";
|
||||
}
|
||||
|
||||
private SilentBladeOniEffect(final SilentBladeOniEffect effect) {
|
||||
|
@ -71,32 +70,15 @@ class SilentBladeOniEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (opponent == null
|
||||
|| controller == null) {
|
||||
Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
if (controller == null || opponent == null) {
|
||||
return false;
|
||||
}
|
||||
Cards cardsInHand = new CardsImpl();
|
||||
cardsInHand.addAll(opponent.getHand());
|
||||
if (cardsInHand.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
TargetCard target = new TargetCard(
|
||||
0, 1, Zone.HAND, StaticFilters.FILTER_CARD_A_NON_LAND
|
||||
controller.lookAtCards(opponent.getName(), opponent.getHand(), game);
|
||||
return CardUtil.castSpellWithAttributesForFree(
|
||||
controller, source, game, new CardsImpl(opponent.getHand()),
|
||||
StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY
|
||||
);
|
||||
if (!controller.chooseUse(outcome, "Cast a card from " + opponent.getName() + "'s hand?", source, game)
|
||||
|| !controller.chooseTarget(outcome, cardsInHand, target, source, game)) {
|
||||
return true;
|
||||
}
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card == null) {
|
||||
return false;
|
||||
}
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
return cardWasCast;
|
||||
}
|
||||
}
|
||||
|
|
164
Mage.Sets/src/mage/cards/s/SpectralArcanist.java
Normal file
164
Mage.Sets/src/mage/cards/s/SpectralArcanist.java
Normal file
|
@ -0,0 +1,164 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.*;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.common.FilterInstantOrSorceryCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class SpectralArcanist extends CardImpl {
|
||||
|
||||
public SpectralArcanist(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");
|
||||
|
||||
this.subtype.add(SubType.SPIRIT);
|
||||
this.subtype.add(SubType.WIZARD);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// When Spectral Arcanist enters the battlefield, you may cast an instant or sorcery spell with mana value less than or equal to the number of Spirits you control from a graveyard without paying its mana cost. If that spell would be put into a graveyard, exile it instead.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new SpectralArcanistCastEffect())
|
||||
.addHint(SpectralArcanistCastEffect.getHint()));
|
||||
}
|
||||
|
||||
private SpectralArcanist(final SpectralArcanist card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpectralArcanist copy() {
|
||||
return new SpectralArcanist(this);
|
||||
}
|
||||
}
|
||||
|
||||
class SpectralArcanistCastEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterPermanent filter = new FilterControlledPermanent(SubType.SPIRIT);
|
||||
private static final Hint hint = new ValueHint("Spirits you control", new PermanentsOnBattlefieldCount(filter));
|
||||
|
||||
SpectralArcanistCastEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "you may cast an instant or sorcery spell with mana value less than or equal to " +
|
||||
"the number of Spirits you control from a graveyard without paying its mana cost. " +
|
||||
"If that spell would be put into a graveyard, exile it instead";
|
||||
}
|
||||
|
||||
private SpectralArcanistCastEffect(final SpectralArcanistCastEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpectralArcanistCastEffect copy() {
|
||||
return new SpectralArcanistCastEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
FilterCard filterCard = new FilterInstantOrSorceryCard();
|
||||
filterCard.add(new ManaValuePredicate(
|
||||
ComparisonType.FEWER_THAN,
|
||||
game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game)
|
||||
));
|
||||
Cards cards = new CardsImpl();
|
||||
game.getState()
|
||||
.getPlayersInRange(source.getControllerId(), game)
|
||||
.stream()
|
||||
.map(game::getPlayer)
|
||||
.filter(Objects::nonNull)
|
||||
.map(Player::getGraveyard)
|
||||
.forEach(cards::addAll);
|
||||
return CardUtil.castSpellWithAttributesForFree(
|
||||
player, source, game, cards, filterCard,
|
||||
SpectralArcanistTracker.instance
|
||||
);
|
||||
}
|
||||
|
||||
public static Hint getHint() {
|
||||
return hint;
|
||||
}
|
||||
}
|
||||
|
||||
enum SpectralArcanistTracker implements CardUtil.SpellCastTracker {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean checkCard(Card card, Game game) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCard(Card card, Ability source, Game game) {
|
||||
game.addEffect(new SpectralArcanistReplacementEffect(card, game), source);
|
||||
}
|
||||
}
|
||||
|
||||
class SpectralArcanistReplacementEffect extends ReplacementEffectImpl {
|
||||
|
||||
private final MageObjectReference mor;
|
||||
|
||||
SpectralArcanistReplacementEffect(Card card, Game game) {
|
||||
super(Duration.EndOfTurn, Outcome.Exile);
|
||||
this.mor = new MageObjectReference(card.getMainCard(), game);
|
||||
}
|
||||
|
||||
private SpectralArcanistReplacementEffect(final SpectralArcanistReplacementEffect effect) {
|
||||
super(effect);
|
||||
this.mor = effect.mor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpectralArcanistReplacementEffect copy() {
|
||||
return new SpectralArcanistReplacementEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Card card = mor.getCard(game);
|
||||
return controller != null
|
||||
&& card != null
|
||||
&& controller.moveCards(card, Zone.EXILED, source, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||
return zEvent.getToZone() == Zone.GRAVEYARD
|
||||
&& zEvent.getTargetId().equals(mor.getSourceId());
|
||||
}
|
||||
}
|
|
@ -1,29 +1,36 @@
|
|||
|
||||
|
||||
package mage.cards.s;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.cost.CastWithoutPayingManaCostEffect;
|
||||
import mage.abilities.effects.common.cost.CastFromHandForFreeEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.permanent.token.ServoToken;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author fireshoes
|
||||
*/
|
||||
public final class SramsExpertise extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("a spell with mana value 3 or less");
|
||||
|
||||
static {
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 4));
|
||||
}
|
||||
|
||||
public SramsExpertise(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{W}{W}");
|
||||
|
||||
|
||||
// Create three 1/1 colorless Servo artifact creature tokens.
|
||||
this.getSpellAbility().addEffect(new CreateTokenEffect(new ServoToken(), 3));
|
||||
|
||||
// You may cast a card with converted mana cost 3 or less from your hand without paying its mana cost.
|
||||
this.getSpellAbility().addEffect(new CastWithoutPayingManaCostEffect(3).concatBy("<br>"));
|
||||
this.getSpellAbility().addEffect(new CastFromHandForFreeEffect(filter).concatBy("<br>"));
|
||||
}
|
||||
|
||||
private SramsExpertise(final SramsExpertise card) {
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
|
@ -17,17 +13,17 @@ import mage.constants.ComparisonType;
|
|||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterNonlandCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author spjspj
|
||||
*/
|
||||
public final class SunbirdsInvocation extends CardImpl {
|
||||
|
@ -54,11 +50,11 @@ public final class SunbirdsInvocation extends CardImpl {
|
|||
|
||||
class SunbirdsInvocationTriggeredAbility extends SpellCastControllerTriggeredAbility {
|
||||
|
||||
public SunbirdsInvocationTriggeredAbility() {
|
||||
SunbirdsInvocationTriggeredAbility() {
|
||||
super(new SunbirdsInvocationEffect(), false);
|
||||
}
|
||||
|
||||
public SunbirdsInvocationTriggeredAbility(SunbirdsInvocationTriggeredAbility ability) {
|
||||
private SunbirdsInvocationTriggeredAbility(SunbirdsInvocationTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
|
@ -87,12 +83,10 @@ class SunbirdsInvocationTriggeredAbility extends SpellCastControllerTriggeredAbi
|
|||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever you cast a spell from your hand, "
|
||||
+ "reveal the top X cards of your library, "
|
||||
+ "where X is that spell's mana value. "
|
||||
+ "You may cast a card revealed this way with "
|
||||
+ "mana value X or less without paying its mana cost."
|
||||
+ " Put the rest on the bottom of your library in a random order.";
|
||||
return "Whenever you cast a spell from your hand, reveal the top X cards of your library, " +
|
||||
"where X is that spell's mana value. You may cast a spell with mana value X or less " +
|
||||
"from among cards revealed this way without paying its mana cost. " +
|
||||
"Put the rest on the bottom of your library in a random order.";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,10 +94,6 @@ class SunbirdsInvocationEffect extends OneShotEffect {
|
|||
|
||||
public SunbirdsInvocationEffect() {
|
||||
super(Outcome.PutCardInPlay);
|
||||
staticText = "reveal the top X cards of your library, where X is that "
|
||||
+ "spell's mana value. You may cast a card revealed this "
|
||||
+ "way with mana value X or less without paying its mana cost. "
|
||||
+ "Put the rest on the bottom of your library in a random order";
|
||||
}
|
||||
|
||||
public SunbirdsInvocationEffect(final SunbirdsInvocationEffect effect) {
|
||||
|
@ -113,9 +103,7 @@ class SunbirdsInvocationEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = game.getObject(source.getSourceId());
|
||||
if (controller == null
|
||||
|| sourceObject == null) {
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
Spell spell = game.getSpellOrLKIStack(this.getTargetPointer().getFirst(game, source));
|
||||
|
@ -124,29 +112,15 @@ class SunbirdsInvocationEffect extends OneShotEffect {
|
|||
}
|
||||
int xValue = spell.getManaValue();
|
||||
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, xValue));
|
||||
if (!cards.isEmpty()) {
|
||||
controller.revealCards(sourceObject.getIdName(), cards, game);
|
||||
|
||||
FilterCard filter = new FilterNonlandCard("card revealed this way with mana value " + xValue + " or less");
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, xValue + 1));
|
||||
TargetCard target = new TargetCard(1, Zone.LIBRARY, filter);
|
||||
|
||||
if (controller.chooseTarget(Outcome.PlayForFree, cards, target, source, game)) {
|
||||
Card card = cards.get(target.getFirstTarget(), game);
|
||||
if (card != null) {
|
||||
if (controller.chooseUse(Outcome.Benefit, "Cast " + card.getLogName() + " without paying its mana cost?", source, game)) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
if (cardWasCast) {
|
||||
cards.remove(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
controller.putCardsOnBottomOfLibrary(cards, game, source, false);
|
||||
if (cards.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
controller.revealCards(source, cards, game);
|
||||
FilterCard filter = new FilterCard();
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, xValue + 1));
|
||||
CardUtil.castSpellWithAttributesForFree(controller, source, game, cards, filter);
|
||||
cards.retainZone(Zone.LIBRARY, game);
|
||||
controller.putCardsOnBottomOfLibrary(cards, game, source, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,34 +1,29 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksTriggeredAbility;
|
||||
import mage.abilities.costs.OrCost;
|
||||
import mage.abilities.costs.common.RevealTargetFromHandCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.abilities.effects.common.cost.CastFromHandForFreeEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.filter.common.FilterInstantOrSorceryCard;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author weirddan455
|
||||
*/
|
||||
public final class SurtlandElementalist extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("a Giant card from your hand");
|
||||
private static final FilterCard filter2 = new FilterInstantOrSorceryCard("an instant or sorcery spell");
|
||||
|
||||
static {
|
||||
filter.add(SubType.GIANT.getPredicate());
|
||||
}
|
||||
|
@ -48,7 +43,7 @@ public final class SurtlandElementalist extends CardImpl {
|
|||
"reveal a Giant card from your hand or pay {2}"));
|
||||
|
||||
// Whenever Surtland Elementalist attacks, you may cast an instant or sorcery spell from your hand without paying its mana cost.
|
||||
this.addAbility(new AttacksTriggeredAbility(new SurtlandElementalistEffect(), true));
|
||||
this.addAbility(new AttacksTriggeredAbility(new CastFromHandForFreeEffect(filter2), true));
|
||||
}
|
||||
|
||||
private SurtlandElementalist(final SurtlandElementalist card) {
|
||||
|
@ -60,39 +55,3 @@ public final class SurtlandElementalist extends CardImpl {
|
|||
return new SurtlandElementalist(this);
|
||||
}
|
||||
}
|
||||
|
||||
class SurtlandElementalistEffect extends OneShotEffect {
|
||||
|
||||
public SurtlandElementalistEffect () {
|
||||
super(Outcome.PlayForFree);
|
||||
this.staticText = "cast an instant or sorcery spell from your hand without paying its mana cost";
|
||||
}
|
||||
|
||||
private SurtlandElementalistEffect(final SurtlandElementalistEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurtlandElementalistEffect copy() {
|
||||
return new SurtlandElementalistEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
TargetCardInHand target = new TargetCardInHand(0, 1, StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY);
|
||||
if (player.chooseTarget(Outcome.PlayForFree, target, source, game)) {
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
boolean cardWasCast = player.cast(player.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
return cardWasCast;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
|
@ -9,19 +8,17 @@ import mage.abilities.costs.mana.GenericManaCost;
|
|||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.cards.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.filter.common.FilterNonlandCard;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.*;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.token.IcyManalithToken;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
@ -47,7 +44,7 @@ public final class SvellaIceShaper extends CardImpl {
|
|||
this.addAbility(ability);
|
||||
|
||||
// {6}{R}{G}, {T}: Look at the top four cards of your library. You may cast a spell from among them without paying its mana cost. Put the rest on the bottom of your library in a random order.
|
||||
ability = new SimpleActivatedAbility(new SvellaIceShaperEffect(), new ManaCostsImpl("{6}{R}{G}"));
|
||||
ability = new SimpleActivatedAbility(new SvellaIceShaperEffect(), new ManaCostsImpl<>("{6}{R}{G}"));
|
||||
ability.addCost(new TapSourceCost());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
@ -86,23 +83,9 @@ class SvellaIceShaperEffect extends OneShotEffect {
|
|||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
Set<Card> cardsSet = controller.getLibrary().getTopCards(game, 4);
|
||||
Cards cards = new CardsImpl(cardsSet);
|
||||
TargetCard target = new TargetCardInLibrary(0, 1,
|
||||
new FilterNonlandCard("card to cast without paying its mana cost"));
|
||||
controller.choose(Outcome.PlayForFree, cards, target, game);
|
||||
Card card = controller.getLibrary().getCard(target.getFirstTarget(), game);
|
||||
if (card == null) {
|
||||
controller.putCardsOnBottomOfLibrary(cards, game, source, false);
|
||||
return true;
|
||||
}
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
if (cardWasCast) {
|
||||
cards.remove(card);
|
||||
}
|
||||
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 4));
|
||||
CardUtil.castSpellWithAttributesForFree(controller, source, game, cards, StaticFilters.FILTER_CARD);
|
||||
cards.retainZone(Zone.LIBRARY, game);
|
||||
controller.putCardsOnBottomOfLibrary(cards, game, source, false);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
package mage.cards.t;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.common.SpellMasteryCondition;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterInstantOrSorceryCard;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
|
@ -33,9 +34,8 @@ public final class TalentOfTheTelepath extends CardImpl {
|
|||
// <i>Spell mastery</i> — If there are two or more instant and/or
|
||||
// sorcery cards in your graveyard, you may cast up to two revealed instant
|
||||
// and/or sorcery cards instead of one.
|
||||
getSpellAbility().addEffect(new TalentOfTheTelepathEffect());
|
||||
getSpellAbility().addTarget(new TargetOpponent());
|
||||
|
||||
this.getSpellAbility().addEffect(new TalentOfTheTelepathEffect());
|
||||
this.getSpellAbility().addTarget(new TargetOpponent());
|
||||
}
|
||||
|
||||
private TalentOfTheTelepath(final TalentOfTheTelepath card) {
|
||||
|
@ -54,12 +54,12 @@ class TalentOfTheTelepathEffect extends OneShotEffect {
|
|||
|
||||
public TalentOfTheTelepathEffect() {
|
||||
super(Outcome.PlayForFree);
|
||||
this.staticText = "Target opponent reveals the top seven cards of their "
|
||||
+ "library. You may cast an instant or sorcery card from among them "
|
||||
+ "without paying its mana cost. Then that player puts the rest into their graveyard. "
|
||||
+ "<BR><i>Spell mastery</i> — If there are two or more instant "
|
||||
+ "and/or sorcery cards in your graveyard, you may cast up to two "
|
||||
+ "revealed instant and/or sorcery cards instead of one.";
|
||||
this.staticText = "Target opponent reveals the top seven cards of their " +
|
||||
"library. You may cast an instant or sorcery spell from among them " +
|
||||
"without paying its mana cost. Then that player puts the rest into their graveyard. "
|
||||
+ "<br><i>Spell mastery</i> — If there are two or more instant " +
|
||||
"and/or sorcery cards in your graveyard, you may cast up to two " +
|
||||
"instant and/or sorcery spells from among the revealed cards instead of one.";
|
||||
}
|
||||
|
||||
public TalentOfTheTelepathEffect(final TalentOfTheTelepathEffect effect) {
|
||||
|
@ -73,60 +73,19 @@ class TalentOfTheTelepathEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Cards cardsToCast = new CardsImpl();
|
||||
Player targetOpponent = game.getPlayer(targetPointer.getFirst(game, source));
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (targetOpponent != null && sourceObject != null) {
|
||||
Set<Card> allCards = targetOpponent.getLibrary().getTopCards(game, 7);
|
||||
Cards cards = new CardsImpl(allCards);
|
||||
targetOpponent.revealCards(sourceObject.getIdName() + " - "
|
||||
+ targetOpponent.getName() + "'s top library cards", cards, game);
|
||||
for (Card card : allCards) {
|
||||
if (filter.match(card, game)) {
|
||||
cardsToCast.add(card);
|
||||
}
|
||||
}
|
||||
// cast an instant or sorcery for free
|
||||
if (!cardsToCast.isEmpty()) {
|
||||
int numberOfSpells = 1;
|
||||
if (SpellMasteryCondition.instance.apply(game, source)) {
|
||||
numberOfSpells++;
|
||||
}
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
TargetCard target = new TargetCard(Zone.LIBRARY, filter); // zone should be ignored here
|
||||
target.setNotTarget(true);
|
||||
while (controller.canRespond()
|
||||
&& numberOfSpells > 0
|
||||
&& !cardsToCast.isEmpty()
|
||||
&& controller.chooseUse(outcome, "Cast an instant or sorcery card "
|
||||
+ "from among them for free?", source, game)
|
||||
&& controller.choose(Outcome.PlayForFree, cardsToCast, target, game)) {
|
||||
Card card = cardsToCast.get(target.getFirstTarget(), game);
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
cardsToCast.remove(card);
|
||||
if (cardWasCast) {
|
||||
numberOfSpells--;
|
||||
allCards.remove(card);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (!controller.canRespond()) {
|
||||
return false;
|
||||
}
|
||||
target.clearChosen();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
targetOpponent.moveCards(allCards, Zone.GRAVEYARD, source, game);
|
||||
return true;
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Player opponent = game.getPlayer(targetPointer.getFirst(game, source));
|
||||
if (controller == null || opponent == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
Cards cards = new CardsImpl(opponent.getLibrary().getTopCards(game, 7));
|
||||
opponent.revealCards(source, cards, game);
|
||||
CardUtil.castMultipleWithAttributeForFree(
|
||||
controller, source, game, cards, StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY,
|
||||
SpellMasteryCondition.instance.apply(game, source) ? 2 : 1
|
||||
);
|
||||
cards.retainZone(Zone.LIBRARY, game);
|
||||
opponent.moveCards(cards, Zone.GRAVEYARD, source, game);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
96
Mage.Sets/src/mage/cards/t/TheDragonKamiReborn.java
Normal file
96
Mage.Sets/src/mage/cards/t/TheDragonKamiReborn.java
Normal file
|
@ -0,0 +1,96 @@
|
|||
package mage.cards.t;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SagaAbility;
|
||||
import mage.abilities.effects.Effects;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.ExileSagaAndReturnTransformedEffect;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.keyword.TransformAbility;
|
||||
import mage.cards.*;
|
||||
import mage.constants.*;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class TheDragonKamiReborn extends CardImpl {
|
||||
|
||||
public TheDragonKamiReborn(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}");
|
||||
|
||||
this.subtype.add(SubType.SAGA);
|
||||
this.secondSideCardClazz = mage.cards.d.DragonKamisEgg.class;
|
||||
|
||||
// (As this Saga enters and after your draw step, add a lore counter.)
|
||||
SagaAbility sagaAbility = new SagaAbility(this);
|
||||
|
||||
// I, II — You gain 2 life. Look at the top three cards of your library. Exile one of them face down with a hatching counter on it, then put the rest on the bottom of your library in any order.
|
||||
sagaAbility.addChapterEffect(
|
||||
this, SagaChapter.CHAPTER_I, SagaChapter.CHAPTER_II,
|
||||
new Effects(new GainLifeEffect(2), new TheDragonKamiRebornEffect())
|
||||
);
|
||||
|
||||
// III — Exile this Saga, then return it to the battlefield transformed under your control.
|
||||
this.addAbility(new TransformAbility());
|
||||
sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_III, new ExileSagaAndReturnTransformedEffect());
|
||||
|
||||
this.addAbility(sagaAbility);
|
||||
}
|
||||
|
||||
private TheDragonKamiReborn(final TheDragonKamiReborn card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TheDragonKamiReborn copy() {
|
||||
return new TheDragonKamiReborn(this);
|
||||
}
|
||||
}
|
||||
|
||||
class TheDragonKamiRebornEffect extends OneShotEffect {
|
||||
|
||||
TheDragonKamiRebornEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "Look at the top three cards of your library. Exile one of them face down " +
|
||||
"with a hatching counter on it, then put the rest on the bottom of your library in any order";
|
||||
}
|
||||
|
||||
private TheDragonKamiRebornEffect(final TheDragonKamiRebornEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TheDragonKamiRebornEffect copy() {
|
||||
return new TheDragonKamiRebornEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 3));
|
||||
if (cards.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
TargetCard target = new TargetCardInLibrary();
|
||||
player.choose(outcome, cards, target, game);
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card != null) {
|
||||
player.moveCards(card, Zone.EXILED, source, game);
|
||||
card.setFaceDown(true, game);
|
||||
card.addCounters(CounterType.HATCHLING.createInstance(), source, game);
|
||||
}
|
||||
cards.retainZone(Zone.LIBRARY, game);
|
||||
player.putCardsOnBottomOfLibrary(card, game, source, true);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,47 +1,45 @@
|
|||
package mage.cards.t;
|
||||
|
||||
import mage.ApprovingObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.common.cost.CastFromHandForFreeEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterNonlandCard;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.NamePredicate;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.util.CardUtil;
|
||||
import mage.watchers.common.SpellsCastWatcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
public final class TwinningGlass extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterCard();
|
||||
|
||||
static {
|
||||
filter.add(TwinningGlassPredicate.instance);
|
||||
}
|
||||
|
||||
public TwinningGlass(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
|
||||
|
||||
// {1}, {T}: You may cast a nonland card from your hand without paying its mana cost if it has the same name as a spell that was cast this turn.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
||||
new TwinningGlassEffect(), new ManaCostsImpl("{1}"));
|
||||
Ability ability = new SimpleActivatedAbility(
|
||||
new CastFromHandForFreeEffect(filter).setText(
|
||||
"you may cast a spell from your hand without paying its mana cost " +
|
||||
"if it has the same name as a spell that was cast this turn"
|
||||
), new GenericManaCost(1)
|
||||
);
|
||||
ability.addCost(new TapSourceCost());
|
||||
this.addAbility(ability, new SpellsCastWatcher());
|
||||
|
||||
}
|
||||
|
||||
private TwinningGlass(final TwinningGlass card) {
|
||||
|
@ -54,67 +52,14 @@ public final class TwinningGlass extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class TwinningGlassEffect extends OneShotEffect {
|
||||
|
||||
public TwinningGlassEffect() {
|
||||
super(Outcome.PlayForFree);
|
||||
this.staticText = "You may cast a nonland card from your hand "
|
||||
+ "without paying its mana cost if it has the same name "
|
||||
+ "as a spell that was cast this turn";
|
||||
}
|
||||
|
||||
public TwinningGlassEffect(final TwinningGlassEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
enum TwinningGlassPredicate implements Predicate<Card> {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public TwinningGlassEffect copy() {
|
||||
return new TwinningGlassEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
List<Spell> spells = new ArrayList<>();
|
||||
Permanent twinningGlass = game.getPermanent(source.getSourceId());
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
public boolean apply(Card input, Game game) {
|
||||
SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class);
|
||||
if (twinningGlass == null) {
|
||||
twinningGlass = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD);
|
||||
}
|
||||
if (twinningGlass != null
|
||||
&& controller != null
|
||||
&& watcher != null) {
|
||||
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
|
||||
if (watcher.getSpellsCastThisTurn(playerId) != null) {
|
||||
for (Spell spell : watcher.getSpellsCastThisTurn(playerId)) {
|
||||
spells.add(spell);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (spells.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
List<NamePredicate> predicates = spells.stream()
|
||||
.map(Spell::getName)
|
||||
.filter(Objects::nonNull)
|
||||
.filter(s -> !s.isEmpty())
|
||||
.map(NamePredicate::new)
|
||||
.collect(Collectors.toList());
|
||||
FilterNonlandCard filterCard = new FilterNonlandCard("nonland card that was cast this turn");
|
||||
filterCard.add(Predicates.or(predicates));
|
||||
TargetCard target = new TargetCard(0, 1, Zone.HAND, filterCard);
|
||||
target.withChooseHint("free cast");
|
||||
if (controller.choose(Outcome.PlayForFree, controller.getHand(), target, game)) {
|
||||
Card chosenCard = game.getCard(target.getFirstTarget());
|
||||
if (chosenCard != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + chosenCard.getId(), Boolean.TRUE);
|
||||
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(chosenCard, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + chosenCard.getId(), null);
|
||||
return cardWasCast;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return watcher != null && watcher
|
||||
.getAllSpellsCastThisTurn()
|
||||
.anyMatch(spell -> CardUtil.haveSameNames(spell, input));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package mage.cards.v;
|
||||
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksTriggeredAbility;
|
||||
|
@ -8,7 +7,10 @@ import mage.abilities.effects.OneShotEffect;
|
|||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
import mage.cards.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterInstantOrSorceryCard;
|
||||
|
@ -16,10 +18,8 @@ import mage.filter.predicate.mageobject.ManaValuePredicate;
|
|||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
@ -84,26 +84,11 @@ class VelomachusLoreholdEffect extends OneShotEffect {
|
|||
if (controller == null || permanent == null) {
|
||||
return false;
|
||||
}
|
||||
Set<Card> cardsSet = controller.getLibrary().getTopCards(game, 7);
|
||||
Cards cards = new CardsImpl(cardsSet);
|
||||
FilterCard filter = new FilterInstantOrSorceryCard(
|
||||
"instant or sorcery card with mana value " + permanent.getPower().getValue() + " or less"
|
||||
);
|
||||
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 7));
|
||||
FilterCard filter = new FilterInstantOrSorceryCard();
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, permanent.getPower().getValue() + 1));
|
||||
TargetCard target = new TargetCardInLibrary(0, 1, filter);
|
||||
controller.choose(Outcome.PlayForFree, cards, target, game);
|
||||
Card card = controller.getLibrary().getCard(target.getFirstTarget(), game);
|
||||
if (card == null) {
|
||||
controller.putCardsOnBottomOfLibrary(cards, game, source, false);
|
||||
return true;
|
||||
}
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
if (cardWasCast) {
|
||||
cards.remove(card);
|
||||
}
|
||||
CardUtil.castSpellWithAttributesForFree(controller, source, game, cards, filter);
|
||||
cards.retainZone(Zone.LIBRARY, game);
|
||||
controller.putCardsOnBottomOfLibrary(cards, game, source, false);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
package mage.cards.v;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterNonlandCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
|
@ -30,9 +29,8 @@ public final class VillainousWealth extends CardImpl {
|
|||
|
||||
// Target opponent exiles the top X cards of their library. You may cast any number of nonland cards
|
||||
// with converted mana cost X or less from among them without paying their mana cost.
|
||||
this.getSpellAbility().addTarget(new TargetOpponent());
|
||||
this.getSpellAbility().addEffect(new VillainousWealthEffect());
|
||||
|
||||
this.getSpellAbility().addTarget(new TargetOpponent());
|
||||
}
|
||||
|
||||
private VillainousWealth(final VillainousWealth card) {
|
||||
|
@ -66,48 +64,16 @@ class VillainousWealthEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject mageObject = game.getObject(source.getSourceId());
|
||||
if (controller != null && mageObject != null) {
|
||||
Player player = game.getPlayer(targetPointer.getFirst(game, source));
|
||||
FilterCard filter = new FilterNonlandCard();
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, source.getManaCostsToPay().getX() + 1));
|
||||
UUID exileId = CardUtil.getCardExileZoneId(game, source);
|
||||
if (player != null) {
|
||||
Cards cardsToExile = new CardsImpl();
|
||||
cardsToExile.addAll(player.getLibrary().getTopCards(game, source.getManaCostsToPay().getX()));
|
||||
controller.moveCards(cardsToExile, Zone.EXILED, source, game);
|
||||
if (controller.chooseUse(Outcome.PlayForFree, "Cast cards exiled with " + mageObject.getLogName()
|
||||
+ " without paying its mana cost?", source, game)) {
|
||||
OuterLoop:
|
||||
while (cardsToExile.count(filter, game) > 0) {
|
||||
if (!controller.canRespond()) {
|
||||
return false;
|
||||
}
|
||||
TargetCardInExile target = new TargetCardInExile(0, 1, filter, exileId, false);
|
||||
target.setNotTarget(true);
|
||||
while (controller.canRespond()
|
||||
&& cardsToExile.count(filter, game) > 0
|
||||
&& controller.choose(Outcome.PlayForFree, cardsToExile, target, game)) {
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
if (cardWasCast) {
|
||||
cardsToExile.remove(card);
|
||||
}
|
||||
} else {
|
||||
break OuterLoop;
|
||||
}
|
||||
target.clearChosen();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
Player opponent = game.getPlayer(targetPointer.getFirst(game, source));
|
||||
int xValue = source.getManaCostsToPay().getX();
|
||||
if (controller == null || opponent == null || xValue < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
Cards cards = new CardsImpl(opponent.getLibrary().getTopCards(game, xValue));
|
||||
opponent.moveCards(cards, Zone.EXILED, source, game);
|
||||
FilterCard filter = new FilterCard();
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, source.getManaCostsToPay().getX() + 1));
|
||||
CardUtil.castMultipleWithAttributeForFree(controller, source, game, cards, filter);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,30 +1,25 @@
|
|||
package mage.cards.w;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.cost.CastFromHandForFreeEffect;
|
||||
import mage.abilities.keyword.AfflictAbility;
|
||||
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.filter.FilterCard;
|
||||
import mage.filter.common.FilterInstantOrSorceryCard;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author spjspj
|
||||
*/
|
||||
public final class WildfireEternal extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterInstantOrSorceryCard("an instant or sorcery spell");
|
||||
|
||||
public WildfireEternal(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
|
||||
|
||||
|
@ -35,10 +30,12 @@ public final class WildfireEternal extends CardImpl {
|
|||
this.toughness = new MageInt(4);
|
||||
|
||||
// Afflict 4
|
||||
addAbility(new AfflictAbility(4));
|
||||
this.addAbility(new AfflictAbility(4));
|
||||
|
||||
// Whenever Wildfire Eternal attacks and isn't blocked, you may cast an instant or sorcery card from your hand without paying its mana cost.
|
||||
this.addAbility(new AttacksAndIsNotBlockedTriggeredAbility(new WildfireEternalCastEffect(), false, true));
|
||||
this.addAbility(new AttacksAndIsNotBlockedTriggeredAbility(
|
||||
new CastFromHandForFreeEffect(filter), false, true
|
||||
));
|
||||
}
|
||||
|
||||
private WildfireEternal(final WildfireEternal card) {
|
||||
|
@ -50,45 +47,3 @@ public final class WildfireEternal extends CardImpl {
|
|||
return new WildfireEternal(this);
|
||||
}
|
||||
}
|
||||
|
||||
class WildfireEternalCastEffect extends OneShotEffect {
|
||||
|
||||
public WildfireEternalCastEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "you may cast an instant or sorcery card "
|
||||
+ "from your hand without paying its mana cost";
|
||||
}
|
||||
|
||||
public WildfireEternalCastEffect(final WildfireEternalCastEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WildfireEternalCastEffect copy() {
|
||||
return new WildfireEternalCastEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
FilterCard filter = new FilterInstantOrSorceryCard();
|
||||
int cardsToCast = controller.getHand().count(filter, source.getControllerId(), source.getSourceId(), game);
|
||||
if (cardsToCast > 0
|
||||
&& controller.chooseUse(outcome, "Cast an instant or sorcery card from your "
|
||||
+ "hand without paying its mana cost?", source, game)) {
|
||||
TargetCardInHand target = new TargetCardInHand(filter);
|
||||
controller.chooseTarget(outcome, target, source, game);
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
controller.cast(controller.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,29 +1,36 @@
|
|||
|
||||
|
||||
package mage.cards.y;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.effects.common.continuous.BoostAllEffect;
|
||||
import mage.abilities.effects.common.cost.CastWithoutPayingManaCostEffect;
|
||||
import mage.abilities.effects.common.cost.CastFromHandForFreeEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.Duration;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author fireshoes
|
||||
*/
|
||||
public final class YahennisExpertise extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("a spell with mana value 3 or less");
|
||||
|
||||
static {
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 4));
|
||||
}
|
||||
|
||||
public YahennisExpertise(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}{B}");
|
||||
|
||||
|
||||
// All creatures get -3/-3 until end of turn.
|
||||
this.getSpellAbility().addEffect(new BoostAllEffect(-3, -3, Duration.EndOfTurn));
|
||||
|
||||
// You may cast a card with converted mana cost 3 or less from your hand without paying its mana cost.
|
||||
this.getSpellAbility().addEffect(new CastWithoutPayingManaCostEffect(3).concatBy("<br>"));
|
||||
this.getSpellAbility().addEffect(new CastFromHandForFreeEffect(filter).concatBy("<br>"));
|
||||
}
|
||||
|
||||
private YahennisExpertise(final YahennisExpertise card) {
|
||||
|
|
|
@ -25,7 +25,8 @@ public final class CrimsonVowCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Anowon, the Ruin Sage", 118, Rarity.RARE, mage.cards.a.AnowonTheRuinSage.class));
|
||||
cards.add(new SetCardInfo("Arcane Denial", 102, Rarity.COMMON, mage.cards.a.ArcaneDenial.class));
|
||||
cards.add(new SetCardInfo("Arcane Signet", 159, Rarity.COMMON, mage.cards.a.ArcaneSignet.class));
|
||||
cards.add(new SetCardInfo("Arterial Alchemy", 23, Rarity.RARE, mage.cards.a.ArterialAlchemy.class));
|
||||
cards.add(new SetCardInfo("Arterial Alchemy", 23, Rarity.RARE, mage.cards.a.ArterialAlchemy.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Arterial Alchemy", 61, Rarity.RARE, mage.cards.a.ArterialAlchemy.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Avacyn's Judgment", 142, Rarity.RARE, mage.cards.a.AvacynsJudgment.class));
|
||||
cards.add(new SetCardInfo("Azorius Chancery", 171, Rarity.UNCOMMON, mage.cards.a.AzoriusChancery.class));
|
||||
cards.add(new SetCardInfo("Azorius Locket", 160, Rarity.COMMON, mage.cards.a.AzoriusLocket.class));
|
||||
|
@ -38,8 +39,10 @@ public final class CrimsonVowCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Bloodsworn Steward", 144, Rarity.RARE, mage.cards.b.BloodswornSteward.class));
|
||||
cards.add(new SetCardInfo("Bloodtracker", 122, Rarity.RARE, mage.cards.b.Bloodtracker.class));
|
||||
cards.add(new SetCardInfo("Boreas Charger", 79, Rarity.RARE, mage.cards.b.BoreasCharger.class));
|
||||
cards.add(new SetCardInfo("Breath of the Sleepless", 11, Rarity.RARE, mage.cards.b.BreathOfTheSleepless.class));
|
||||
cards.add(new SetCardInfo("Breathkeeper Seraph", 31, Rarity.RARE, mage.cards.b.BreathkeeperSeraph.class));
|
||||
cards.add(new SetCardInfo("Breath of the Sleepless", 11, Rarity.RARE, mage.cards.b.BreathOfTheSleepless.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Breath of the Sleepless", 49, Rarity.RARE, mage.cards.b.BreathOfTheSleepless.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Breathkeeper Seraph", 31, Rarity.RARE, mage.cards.b.BreathkeeperSeraph.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Breathkeeper Seraph", 69, Rarity.RARE, mage.cards.b.BreathkeeperSeraph.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Butcher of Malakir", 123, Rarity.RARE, mage.cards.b.ButcherOfMalakir.class));
|
||||
cards.add(new SetCardInfo("Bygone Bishop", 80, Rarity.RARE, mage.cards.b.BygoneBishop.class));
|
||||
cards.add(new SetCardInfo("Champion of Dusk", 124, Rarity.RARE, mage.cards.c.ChampionOfDusk.class));
|
||||
|
@ -48,22 +51,27 @@ public final class CrimsonVowCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Commander's Sphere", 163, Rarity.COMMON, mage.cards.c.CommandersSphere.class));
|
||||
cards.add(new SetCardInfo("Cordial Vampire", 125, Rarity.RARE, mage.cards.c.CordialVampire.class));
|
||||
cards.add(new SetCardInfo("Crimson Honor Guard", 145, Rarity.RARE, mage.cards.c.CrimsonHonorGuard.class));
|
||||
cards.add(new SetCardInfo("Crossway Troublemakers", 17, Rarity.RARE, mage.cards.c.CrosswayTroublemakers.class));
|
||||
cards.add(new SetCardInfo("Crossway Troublemakers", 17, Rarity.RARE, mage.cards.c.CrosswayTroublemakers.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Crossway Troublemakers", 55, Rarity.RARE, mage.cards.c.CrosswayTroublemakers.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Crush Contraband", 81, Rarity.UNCOMMON, mage.cards.c.CrushContraband.class));
|
||||
cards.add(new SetCardInfo("Custodi Soulbinders", 82, Rarity.RARE, mage.cards.c.CustodiSoulbinders.class));
|
||||
cards.add(new SetCardInfo("Custodi Squire", 83, Rarity.COMMON, mage.cards.c.CustodiSquire.class));
|
||||
cards.add(new SetCardInfo("Damnable Pact", 126, Rarity.RARE, mage.cards.d.DamnablePact.class));
|
||||
cards.add(new SetCardInfo("Dark Impostor", 127, Rarity.RARE, mage.cards.d.DarkImpostor.class));
|
||||
cards.add(new SetCardInfo("Darksteel Mutation", 84, Rarity.UNCOMMON, mage.cards.d.DarksteelMutation.class));
|
||||
cards.add(new SetCardInfo("Disorder in the Court", 29, Rarity.RARE, mage.cards.d.DisorderInTheCourt.class));
|
||||
cards.add(new SetCardInfo("Disorder in the Court", 29, Rarity.RARE, mage.cards.d.DisorderInTheCourt.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Disorder in the Court", 67, Rarity.RARE, mage.cards.d.DisorderInTheCourt.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Distant Melody", 103, Rarity.COMMON, mage.cards.d.DistantMelody.class));
|
||||
cards.add(new SetCardInfo("Donal, Herald of Wings", 3, Rarity.MYTHIC, mage.cards.d.DonalHeraldOfWings.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Donal, Herald of Wings", 41, Rarity.MYTHIC, mage.cards.d.DonalHeraldOfWings.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Doom Weaver", 34, Rarity.RARE, mage.cards.d.DoomWeaver.class));
|
||||
cards.add(new SetCardInfo("Doom Weaver", 34, Rarity.RARE, mage.cards.d.DoomWeaver.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Doom Weaver", 72, Rarity.RARE, mage.cards.d.DoomWeaver.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Dovin, Grand Arbiter", 153, Rarity.MYTHIC, mage.cards.d.DovinGrandArbiter.class));
|
||||
cards.add(new SetCardInfo("Drogskol Captain", 154, Rarity.UNCOMMON, mage.cards.d.DrogskolCaptain.class));
|
||||
cards.add(new SetCardInfo("Drogskol Reinforcements", 5, Rarity.RARE, mage.cards.d.DrogskolReinforcements.class));
|
||||
cards.add(new SetCardInfo("Ethereal Investigator", 12, Rarity.RARE, mage.cards.e.EtherealInvestigator.class));
|
||||
cards.add(new SetCardInfo("Drogskol Reinforcements", 43, Rarity.RARE, mage.cards.d.DrogskolReinforcements.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Drogskol Reinforcements", 5, Rarity.RARE, mage.cards.d.DrogskolReinforcements.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Ethereal Investigator", 12, Rarity.RARE, mage.cards.e.EtherealInvestigator.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Ethereal Investigator", 50, Rarity.RARE, mage.cards.e.EtherealInvestigator.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Exotic Orchard", 173, Rarity.RARE, mage.cards.e.ExoticOrchard.class));
|
||||
cards.add(new SetCardInfo("Falkenrath Gorger", 146, Rarity.RARE, mage.cards.f.FalkenrathGorger.class));
|
||||
cards.add(new SetCardInfo("Falkenrath Noble", 128, Rarity.UNCOMMON, mage.cards.f.FalkenrathNoble.class));
|
||||
|
@ -76,30 +84,42 @@ public final class CrimsonVowCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Geist of Saint Traft", 155, Rarity.MYTHIC, mage.cards.g.GeistOfSaintTraft.class));
|
||||
cards.add(new SetCardInfo("Ghostly Pilferer", 105, Rarity.RARE, mage.cards.g.GhostlyPilferer.class));
|
||||
cards.add(new SetCardInfo("Ghostly Prison", 87, Rarity.UNCOMMON, mage.cards.g.GhostlyPrison.class));
|
||||
cards.add(new SetCardInfo("Glass-Cast Heart", 18, Rarity.RARE, mage.cards.g.GlassCastHeart.class));
|
||||
cards.add(new SetCardInfo("Glass-Cast Heart", 18, Rarity.RARE, mage.cards.g.GlassCastHeart.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Glass-Cast Heart", 56, Rarity.RARE, mage.cards.g.GlassCastHeart.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Hallowed Spiritkeeper", 88, Rarity.RARE, mage.cards.h.HallowedSpiritkeeper.class));
|
||||
cards.add(new SetCardInfo("Hanged Executioner", 89, Rarity.RARE, mage.cards.h.HangedExecutioner.class));
|
||||
cards.add(new SetCardInfo("Haunted Library", 6, Rarity.RARE, mage.cards.h.HauntedLibrary.class));
|
||||
cards.add(new SetCardInfo("Haunting Imitation", 13, Rarity.RARE, mage.cards.h.HauntingImitation.class));
|
||||
cards.add(new SetCardInfo("Hollowhenge Overlord", 36, Rarity.RARE, mage.cards.h.HollowhengeOverlord.class));
|
||||
cards.add(new SetCardInfo("Imperious Mindbreaker", 33, Rarity.RARE, mage.cards.i.ImperiousMindbreaker.class));
|
||||
cards.add(new SetCardInfo("Imposing Grandeur", 24, Rarity.RARE, mage.cards.i.ImposingGrandeur.class));
|
||||
cards.add(new SetCardInfo("Haunted Library", 44, Rarity.RARE, mage.cards.h.HauntedLibrary.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Haunted Library", 6, Rarity.RARE, mage.cards.h.HauntedLibrary.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Haunting Imitation", 13, Rarity.RARE, mage.cards.h.HauntingImitation.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Haunting Imitation", 51, Rarity.RARE, mage.cards.h.HauntingImitation.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Hollowhenge Overlord", 36, Rarity.RARE, mage.cards.h.HollowhengeOverlord.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Hollowhenge Overlord", 74, Rarity.RARE, mage.cards.h.HollowhengeOverlord.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Imperious Mindbreaker", 33, Rarity.RARE, mage.cards.i.ImperiousMindbreaker.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Imperious Mindbreaker", 71, Rarity.RARE, mage.cards.i.ImperiousMindbreaker.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Imposing Grandeur", 24, Rarity.RARE, mage.cards.i.ImposingGrandeur.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Imposing Grandeur", 62, Rarity.RARE, mage.cards.i.ImposingGrandeur.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Imprisoned in the Moon", 106, Rarity.RARE, mage.cards.i.ImprisonedInTheMoon.class));
|
||||
cards.add(new SetCardInfo("Indulgent Aristocrat", 130, Rarity.UNCOMMON, mage.cards.i.IndulgentAristocrat.class));
|
||||
cards.add(new SetCardInfo("Kamber, the Plunderer", 19, Rarity.RARE, mage.cards.k.KamberThePlunderer.class));
|
||||
cards.add(new SetCardInfo("Kamber, the Plunderer", 19, Rarity.RARE, mage.cards.k.KamberThePlunderer.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kamber, the Plunderer", 57, Rarity.RARE, mage.cards.k.KamberThePlunderer.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kami of the Crescent Moon", 107, Rarity.RARE, mage.cards.k.KamiOfTheCrescentMoon.class));
|
||||
cards.add(new SetCardInfo("Karmic Guide", 90, Rarity.RARE, mage.cards.k.KarmicGuide.class));
|
||||
cards.add(new SetCardInfo("Kirtar's Wrath", 91, Rarity.RARE, mage.cards.k.KirtarsWrath.class));
|
||||
cards.add(new SetCardInfo("Knight of the White Orchid", 92, Rarity.RARE, mage.cards.k.KnightOfTheWhiteOrchid.class));
|
||||
cards.add(new SetCardInfo("Laurine, the Diversion", 25, Rarity.RARE, mage.cards.l.LaurineTheDiversion.class));
|
||||
cards.add(new SetCardInfo("Laurine, the Diversion", 25, Rarity.RARE, mage.cards.l.LaurineTheDiversion.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Laurine, the Diversion", 63, Rarity.RARE, mage.cards.l.LaurineTheDiversion.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Malakir Bloodwitch", 131, Rarity.RARE, mage.cards.m.MalakirBloodwitch.class));
|
||||
cards.add(new SetCardInfo("Marble Diamond", 165, Rarity.COMMON, mage.cards.m.MarbleDiamond.class));
|
||||
cards.add(new SetCardInfo("Markov Enforcer", 26, Rarity.RARE, mage.cards.m.MarkovEnforcer.class));
|
||||
cards.add(new SetCardInfo("Markov Enforcer", 26, Rarity.RARE, mage.cards.m.MarkovEnforcer.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Markov Enforcer", 64, Rarity.RARE, mage.cards.m.MarkovEnforcer.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mentor of the Meek", 93, Rarity.RARE, mage.cards.m.MentorOfTheMeek.class));
|
||||
cards.add(new SetCardInfo("Midnight Arsonist", 27, Rarity.RARE, mage.cards.m.MidnightArsonist.class));
|
||||
cards.add(new SetCardInfo("Midnight Arsonist", 27, Rarity.RARE, mage.cards.m.MidnightArsonist.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Midnight Arsonist", 65, Rarity.RARE, mage.cards.m.MidnightArsonist.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Midnight Clock", 108, Rarity.RARE, mage.cards.m.MidnightClock.class));
|
||||
cards.add(new SetCardInfo("Millicent, Restless Revenant", 1, Rarity.MYTHIC, mage.cards.m.MillicentRestlessRevenant.class));
|
||||
cards.add(new SetCardInfo("Mirage Phalanx", 35, Rarity.RARE, mage.cards.m.MiragePhalanx.class));
|
||||
cards.add(new SetCardInfo("Millicent, Restless Revenant", 1, Rarity.MYTHIC, mage.cards.m.MillicentRestlessRevenant.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Millicent, Restless Revenant", 39, Rarity.MYTHIC, mage.cards.m.MillicentRestlessRevenant.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mirage Phalanx", 35, Rarity.RARE, mage.cards.m.MiragePhalanx.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mirage Phalanx", 73, Rarity.RARE, mage.cards.m.MiragePhalanx.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mirror Entity", 94, Rarity.RARE, mage.cards.m.MirrorEntity.class));
|
||||
cards.add(new SetCardInfo("Mob Rule", 147, Rarity.RARE, mage.cards.m.MobRule.class));
|
||||
cards.add(new SetCardInfo("Molten Echoes", 148, Rarity.RARE, mage.cards.m.MoltenEchoes.class));
|
||||
|
@ -109,47 +129,57 @@ public final class CrimsonVowCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Necropolis Regent", 132, Rarity.MYTHIC, mage.cards.n.NecropolisRegent.class));
|
||||
cards.add(new SetCardInfo("Night's Whisper", 133, Rarity.COMMON, mage.cards.n.NightsWhisper.class));
|
||||
cards.add(new SetCardInfo("Nirkana Revenant", 134, Rarity.MYTHIC, mage.cards.n.NirkanaRevenant.class));
|
||||
cards.add(new SetCardInfo("Occult Epiphany", 14, Rarity.RARE, mage.cards.o.OccultEpiphany.class));
|
||||
cards.add(new SetCardInfo("Olivia's Wrath", 20, Rarity.RARE, mage.cards.o.OliviasWrath.class));
|
||||
cards.add(new SetCardInfo("Occult Epiphany", 14, Rarity.RARE, mage.cards.o.OccultEpiphany.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Occult Epiphany", 52, Rarity.RARE, mage.cards.o.OccultEpiphany.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Olivia's Wrath", 20, Rarity.RARE, mage.cards.o.OliviasWrath.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Olivia's Wrath", 58, Rarity.RARE, mage.cards.o.OliviasWrath.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Oyobi, Who Split the Heavens", 95, Rarity.RARE, mage.cards.o.OyobiWhoSplitTheHeavens.class));
|
||||
cards.add(new SetCardInfo("Path of Ancestry", 177, Rarity.COMMON, mage.cards.p.PathOfAncestry.class));
|
||||
cards.add(new SetCardInfo("Patron of the Vein", 135, Rarity.RARE, mage.cards.p.PatronOfTheVein.class));
|
||||
cards.add(new SetCardInfo("Port Town", 178, Rarity.RARE, mage.cards.p.PortTown.class));
|
||||
cards.add(new SetCardInfo("Prairie Stream", 179, Rarity.RARE, mage.cards.p.PrairieStream.class));
|
||||
cards.add(new SetCardInfo("Predators' Hour", 21, Rarity.RARE, mage.cards.p.PredatorsHour.class));
|
||||
cards.add(new SetCardInfo("Priest of the Blessed Graf", 7, Rarity.RARE, mage.cards.p.PriestOfTheBlessedGraf.class));
|
||||
cards.add(new SetCardInfo("Predators' Hour", 21, Rarity.RARE, mage.cards.p.PredatorsHour.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Predators' Hour", 59, Rarity.RARE, mage.cards.p.PredatorsHour.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Priest of the Blessed Graf", 45, Rarity.RARE, mage.cards.p.PriestOfTheBlessedGraf.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Priest of the Blessed Graf", 7, Rarity.RARE, mage.cards.p.PriestOfTheBlessedGraf.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Promise of Bunrei", 96, Rarity.RARE, mage.cards.p.PromiseOfBunrei.class));
|
||||
cards.add(new SetCardInfo("Rakdos Carnarium", 180, Rarity.UNCOMMON, mage.cards.r.RakdosCarnarium.class));
|
||||
cards.add(new SetCardInfo("Rakdos Carnarium", 180, Rarity.COMMON, mage.cards.r.RakdosCarnarium.class));
|
||||
cards.add(new SetCardInfo("Rakdos Charm", 156, Rarity.UNCOMMON, mage.cards.r.RakdosCharm.class));
|
||||
cards.add(new SetCardInfo("Rakdos Signet", 166, Rarity.UNCOMMON, mage.cards.r.RakdosSignet.class));
|
||||
cards.add(new SetCardInfo("Rakish Heir", 149, Rarity.UNCOMMON, mage.cards.r.RakishHeir.class));
|
||||
cards.add(new SetCardInfo("Rattlechains", 110, Rarity.RARE, mage.cards.r.Rattlechains.class));
|
||||
cards.add(new SetCardInfo("Reconnaissance Mission", 111, Rarity.UNCOMMON, mage.cards.r.ReconnaissanceMission.class));
|
||||
cards.add(new SetCardInfo("Remorseful Cleric", 97, Rarity.RARE, mage.cards.r.RemorsefulCleric.class));
|
||||
cards.add(new SetCardInfo("Rhoda, Geist Avenger", 8, Rarity.RARE, mage.cards.r.RhodaGeistAvenger.class));
|
||||
cards.add(new SetCardInfo("Rhoda, Geist Avenger", 46, Rarity.RARE, mage.cards.r.RhodaGeistAvenger.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Rhoda, Geist Avenger", 8, Rarity.RARE, mage.cards.r.RhodaGeistAvenger.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Sanctum Seeker", 136, Rarity.RARE, mage.cards.s.SanctumSeeker.class));
|
||||
cards.add(new SetCardInfo("Scion of Opulence", 28, Rarity.RARE, mage.cards.s.ScionOfOpulence.class));
|
||||
cards.add(new SetCardInfo("Scion of Opulence", 28, Rarity.RARE, mage.cards.s.ScionOfOpulence.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Scion of Opulence", 66, Rarity.RARE, mage.cards.s.ScionOfOpulence.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Shacklegeist", 112, Rarity.RARE, mage.cards.s.Shacklegeist.class));
|
||||
cards.add(new SetCardInfo("Shadowblood Ridge", 181, Rarity.RARE, mage.cards.s.ShadowbloodRidge.class));
|
||||
cards.add(new SetCardInfo("Shadowgrange Archfiend", 22, Rarity.RARE, mage.cards.s.ShadowgrangeArchfiend.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Shadowgrange Archfiend", 60, Rarity.RARE, mage.cards.s.ShadowgrangeArchfiend.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Sinister Waltz", 30, Rarity.RARE, mage.cards.s.SinisterWaltz.class));
|
||||
cards.add(new SetCardInfo("Sinister Waltz", 30, Rarity.RARE, mage.cards.s.SinisterWaltz.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Sinister Waltz", 68, Rarity.RARE, mage.cards.s.SinisterWaltz.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Sire of the Storm", 113, Rarity.UNCOMMON, mage.cards.s.SireOfTheStorm.class));
|
||||
cards.add(new SetCardInfo("Sky Diamond", 167, Rarity.COMMON, mage.cards.s.SkyDiamond.class));
|
||||
cards.add(new SetCardInfo("Skycloud Expanse", 182, Rarity.RARE, mage.cards.s.SkycloudExpanse.class));
|
||||
cards.add(new SetCardInfo("Smoldering Marsh", 183, Rarity.RARE, mage.cards.s.SmolderingMarsh.class));
|
||||
cards.add(new SetCardInfo("Sol Ring", 168, Rarity.UNCOMMON, mage.cards.s.SolRing.class));
|
||||
cards.add(new SetCardInfo("Spectral Arcanist", 15, Rarity.RARE, mage.cards.s.SpectralArcanist.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Spectral Arcanist", 53, Rarity.RARE, mage.cards.s.SpectralArcanist.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Spectral Sailor", 114, Rarity.UNCOMMON, mage.cards.s.SpectralSailor.class));
|
||||
cards.add(new SetCardInfo("Spectral Shepherd", 98, Rarity.UNCOMMON, mage.cards.s.SpectralShepherd.class));
|
||||
cards.add(new SetCardInfo("Stensia Masquerade", 150, Rarity.UNCOMMON, mage.cards.s.StensiaMasquerade.class));
|
||||
cards.add(new SetCardInfo("Storm of Souls", 9, Rarity.RARE, mage.cards.s.StormOfSouls.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Storm of Souls", 47, Rarity.RARE, mage.cards.s.StormOfSouls.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Storm of Souls", 9, Rarity.RARE, mage.cards.s.StormOfSouls.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Strefan, Maurer Progenitor", 2, Rarity.MYTHIC, mage.cards.s.StrefanMaurerProgenitor.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Strefan, Maurer Progenitor", 40, Rarity.MYTHIC, mage.cards.s.StrefanMaurerProgenitor.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Stromkirk Captain", 157, Rarity.UNCOMMON, mage.cards.s.StromkirkCaptain.class));
|
||||
cards.add(new SetCardInfo("Stromkirk Condemned", 137, Rarity.RARE, mage.cards.s.StromkirkCondemned.class));
|
||||
cards.add(new SetCardInfo("Stromkirk Occultist", 151, Rarity.RARE, mage.cards.s.StromkirkOccultist.class));
|
||||
cards.add(new SetCardInfo("Sudden Salvation", 10, Rarity.RARE, mage.cards.s.SuddenSalvation.class));
|
||||
cards.add(new SetCardInfo("Sudden Salvation", 10, Rarity.RARE, mage.cards.s.SuddenSalvation.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Sudden Salvation", 48, Rarity.RARE, mage.cards.s.SuddenSalvation.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Supreme Phantom", 115, Rarity.RARE, mage.cards.s.SupremePhantom.class));
|
||||
cards.add(new SetCardInfo("Swiftfoot Boots", 169, Rarity.UNCOMMON, mage.cards.s.SwiftfootBoots.class));
|
||||
cards.add(new SetCardInfo("Swords to Plowshares", 99, Rarity.UNCOMMON, mage.cards.s.SwordsToPlowshares.class));
|
||||
|
@ -157,12 +187,15 @@ public final class CrimsonVowCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Temple of Enlightenment", 185, Rarity.RARE, mage.cards.t.TempleOfEnlightenment.class));
|
||||
cards.add(new SetCardInfo("Temple of Malice", 186, Rarity.RARE, mage.cards.t.TempleOfMalice.class));
|
||||
cards.add(new SetCardInfo("Temple of the False God", 187, Rarity.UNCOMMON, mage.cards.t.TempleOfTheFalseGod.class));
|
||||
cards.add(new SetCardInfo("Thundering Mightmare", 37, Rarity.RARE, mage.cards.t.ThunderingMightmare.class));
|
||||
cards.add(new SetCardInfo("Timin, Youthful Geist", 16, Rarity.RARE, mage.cards.t.TiminYouthfulGeist.class));
|
||||
cards.add(new SetCardInfo("Thundering Mightmare", 37, Rarity.RARE, mage.cards.t.ThunderingMightmare.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Thundering Mightmare", 75, Rarity.RARE, mage.cards.t.ThunderingMightmare.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Timin, Youthful Geist", 16, Rarity.RARE, mage.cards.t.TiminYouthfulGeist.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Timin, Youthful Geist", 54, Rarity.RARE, mage.cards.t.TiminYouthfulGeist.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Timothar, Baron of Bats", 4, Rarity.MYTHIC, mage.cards.t.TimotharBaronOfBats.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Timothar, Baron of Bats", 42, Rarity.MYTHIC, mage.cards.t.TimotharBaronOfBats.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Twilight Drover", 100, Rarity.RARE, mage.cards.t.TwilightDrover.class));
|
||||
cards.add(new SetCardInfo("Umbris, Fear Manifest", 38, Rarity.MYTHIC, mage.cards.u.UmbrisFearManifest.class));
|
||||
cards.add(new SetCardInfo("Umbris, Fear Manifest", 38, Rarity.MYTHIC, mage.cards.u.UmbrisFearManifest.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Umbris, Fear Manifest", 76, Rarity.MYTHIC, mage.cards.u.UmbrisFearManifest.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Unclaimed Territory", 188, Rarity.UNCOMMON, mage.cards.u.UnclaimedTerritory.class));
|
||||
cards.add(new SetCardInfo("Underworld Connections", 138, Rarity.RARE, mage.cards.u.UnderworldConnections.class));
|
||||
cards.add(new SetCardInfo("Unstable Obelisk", 170, Rarity.UNCOMMON, mage.cards.u.UnstableObelisk.class));
|
||||
|
@ -171,7 +204,8 @@ public final class CrimsonVowCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Vampiric Dragon", 158, Rarity.RARE, mage.cards.v.VampiricDragon.class));
|
||||
cards.add(new SetCardInfo("Vandalblast", 152, Rarity.UNCOMMON, mage.cards.v.Vandalblast.class));
|
||||
cards.add(new SetCardInfo("Verity Circle", 116, Rarity.RARE, mage.cards.v.VerityCircle.class));
|
||||
cards.add(new SetCardInfo("Wedding Ring", 32, Rarity.MYTHIC, mage.cards.w.WeddingRing.class));
|
||||
cards.add(new SetCardInfo("Wedding Ring", 32, Rarity.MYTHIC, mage.cards.w.WeddingRing.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Wedding Ring", 70, Rarity.MYTHIC, mage.cards.w.WeddingRing.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Windborn Muse", 101, Rarity.RARE, mage.cards.w.WindbornMuse.class));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,8 +104,10 @@ public final class ForgottenRealmsCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Exotic Orchard", 236, Rarity.RARE, mage.cards.e.ExoticOrchard.class));
|
||||
cards.add(new SetCardInfo("Explore", 157, Rarity.COMMON, mage.cards.e.Explore.class));
|
||||
cards.add(new SetCardInfo("Explorer's Scope", 205, Rarity.COMMON, mage.cards.e.ExplorersScope.class));
|
||||
cards.add(new SetCardInfo("Extract Brain", 46, Rarity.RARE, mage.cards.e.ExtractBrain.class));
|
||||
cards.add(new SetCardInfo("Fellwar Stone", 206, Rarity.UNCOMMON, mage.cards.f.FellwarStone.class));
|
||||
cards.add(new SetCardInfo("Fertile Ground", 158, Rarity.COMMON, mage.cards.f.FertileGround.class));
|
||||
cards.add(new SetCardInfo("Fevered Suspicion", 47, Rarity.RARE, mage.cards.f.FeveredSuspicion.class));
|
||||
cards.add(new SetCardInfo("Fey Steed", 5, Rarity.RARE, mage.cards.f.FeySteed.class));
|
||||
cards.add(new SetCardInfo("Fiend of the Shadows", 99, Rarity.RARE, mage.cards.f.FiendOfTheShadows.class));
|
||||
cards.add(new SetCardInfo("Fiendlash", 31, Rarity.RARE, mage.cards.f.Fiendlash.class));
|
||||
|
@ -217,6 +219,7 @@ public final class ForgottenRealmsCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Rishkar's Expertise", 170, Rarity.RARE, mage.cards.r.RishkarsExpertise.class));
|
||||
cards.add(new SetCardInfo("Riverwise Augur", 93, Rarity.UNCOMMON, mage.cards.r.RiverwiseAugur.class));
|
||||
cards.add(new SetCardInfo("Robe of Stars", 11, Rarity.RARE, mage.cards.r.RobeOfStars.class));
|
||||
cards.add(new SetCardInfo("Rod of Absorption", 19, Rarity.RARE, mage.cards.r.RodOfAbsorption.class));
|
||||
cards.add(new SetCardInfo("Ronom Unicorn", 71, Rarity.COMMON, mage.cards.r.RonomUnicorn.class));
|
||||
cards.add(new SetCardInfo("Savage Ventmaw", 191, Rarity.UNCOMMON, mage.cards.s.SavageVentmaw.class));
|
||||
cards.add(new SetCardInfo("Scourge of Valkas", 137, Rarity.RARE, mage.cards.s.ScourgeOfValkas.class));
|
||||
|
|
|
@ -24,18 +24,26 @@ public final class KamigawaNeonDynasty extends ExpansionSet {
|
|||
|
||||
cards.add(new SetCardInfo("Acquisition Octopus", 44, Rarity.UNCOMMON, mage.cards.a.AcquisitionOctopus.class));
|
||||
cards.add(new SetCardInfo("Akki Ember-Keeper", 130, Rarity.COMMON, mage.cards.a.AkkiEmberKeeper.class));
|
||||
cards.add(new SetCardInfo("Akki Ronin", 131, Rarity.COMMON, mage.cards.a.AkkiRonin.class));
|
||||
cards.add(new SetCardInfo("Akki Ronin", 131, Rarity.COMMON, mage.cards.a.AkkiRonin.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Akki Ronin", 319, Rarity.COMMON, mage.cards.a.AkkiRonin.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Akki War Paint", 132, Rarity.COMMON, mage.cards.a.AkkiWarPaint.class));
|
||||
cards.add(new SetCardInfo("Ambitious Assault", 133, Rarity.COMMON, mage.cards.a.AmbitiousAssault.class));
|
||||
cards.add(new SetCardInfo("Ancestral Katana", 1, Rarity.COMMON, mage.cards.a.AncestralKatana.class));
|
||||
cards.add(new SetCardInfo("Anchor to Reality", 45, Rarity.UNCOMMON, mage.cards.a.AnchorToReality.class));
|
||||
cards.add(new SetCardInfo("Animus of Night's Reach", 109, Rarity.UNCOMMON, mage.cards.a.AnimusOfNightsReach.class));
|
||||
cards.add(new SetCardInfo("Ao, the Dawn Sky", 2, Rarity.MYTHIC, mage.cards.a.AoTheDawnSky.class));
|
||||
cards.add(new SetCardInfo("Architect of Restoration", 34, Rarity.RARE, mage.cards.a.ArchitectOfRestoration.class));
|
||||
cards.add(new SetCardInfo("Ao, the Dawn Sky", 2, Rarity.MYTHIC, mage.cards.a.AoTheDawnSky.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Ao, the Dawn Sky", 406, Rarity.MYTHIC, mage.cards.a.AoTheDawnSky.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Ao, the Dawn Sky", 433, Rarity.MYTHIC, mage.cards.a.AoTheDawnSky.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Architect of Restoration", 34, Rarity.RARE, mage.cards.a.ArchitectOfRestoration.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Architect of Restoration", 354, Rarity.RARE, mage.cards.a.ArchitectOfRestoration.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Architect of Restoration", 442, Rarity.RARE, mage.cards.a.ArchitectOfRestoration.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Armguard Familiar", 46, Rarity.COMMON, mage.cards.a.ArmguardFamiliar.class));
|
||||
cards.add(new SetCardInfo("Asari Captain", 215, Rarity.UNCOMMON, mage.cards.a.AsariCaptain.class));
|
||||
cards.add(new SetCardInfo("Asari Captain", 215, Rarity.UNCOMMON, mage.cards.a.AsariCaptain.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Asari Captain", 327, Rarity.UNCOMMON, mage.cards.a.AsariCaptain.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Assassin's Ink", 87, Rarity.UNCOMMON, mage.cards.a.AssassinsInk.class));
|
||||
cards.add(new SetCardInfo("Atsushi, the Blazing Sky", 134, Rarity.MYTHIC, mage.cards.a.AtsushiTheBlazingSky.class));
|
||||
cards.add(new SetCardInfo("Atsushi, the Blazing Sky", 134, Rarity.MYTHIC, mage.cards.a.AtsushiTheBlazingSky.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Atsushi, the Blazing Sky", 410, Rarity.MYTHIC, mage.cards.a.AtsushiTheBlazingSky.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Atsushi, the Blazing Sky", 463, Rarity.MYTHIC, mage.cards.a.AtsushiTheBlazingSky.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Automated Artificer", 239, Rarity.COMMON, mage.cards.a.AutomatedArtificer.class));
|
||||
cards.add(new SetCardInfo("Awakened Awareness", 47, Rarity.UNCOMMON, mage.cards.a.AwakenedAwareness.class));
|
||||
cards.add(new SetCardInfo("Azusa's Many Journeys", 172, Rarity.UNCOMMON, mage.cards.a.AzusasManyJourneys.class));
|
||||
|
@ -44,18 +52,28 @@ public final class KamigawaNeonDynasty extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Bearer of Memory", 174, Rarity.COMMON, mage.cards.b.BearerOfMemory.class));
|
||||
cards.add(new SetCardInfo("Befriending the Moths", 4, Rarity.COMMON, mage.cards.b.BefriendingTheMoths.class));
|
||||
cards.add(new SetCardInfo("Behold the Unspeakable", 48, Rarity.UNCOMMON, mage.cards.b.BeholdTheUnspeakable.class));
|
||||
cards.add(new SetCardInfo("Biting-Palm Ninja", 88, Rarity.RARE, mage.cards.b.BitingPalmNinja.class));
|
||||
cards.add(new SetCardInfo("Blade of the Oni", 89, Rarity.MYTHIC, mage.cards.b.BladeOfTheOni.class));
|
||||
cards.add(new SetCardInfo("Blade-Blizzard Kitsune", 5, Rarity.UNCOMMON, mage.cards.b.BladeBlizzardKitsune.class));
|
||||
cards.add(new SetCardInfo("Biting-Palm Ninja", 338, Rarity.RARE, mage.cards.b.BitingPalmNinja.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Biting-Palm Ninja", 452, Rarity.RARE, mage.cards.b.BitingPalmNinja.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Biting-Palm Ninja", 88, Rarity.RARE, mage.cards.b.BitingPalmNinja.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Blade of the Oni", 377, Rarity.MYTHIC, mage.cards.b.BladeOfTheOni.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Blade of the Oni", 420, Rarity.MYTHIC, mage.cards.b.BladeOfTheOni.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Blade of the Oni", 453, Rarity.MYTHIC, mage.cards.b.BladeOfTheOni.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Blade of the Oni", 89, Rarity.MYTHIC, mage.cards.b.BladeOfTheOni.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Blade-Blizzard Kitsune", 331, Rarity.UNCOMMON, mage.cards.b.BladeBlizzardKitsune.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Blade-Blizzard Kitsune", 5, Rarity.UNCOMMON, mage.cards.b.BladeBlizzardKitsune.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Bloodfell Caves", 264, Rarity.COMMON, mage.cards.b.BloodfellCaves.class));
|
||||
cards.add(new SetCardInfo("Blossom Prancer", 175, Rarity.UNCOMMON, mage.cards.b.BlossomPrancer.class));
|
||||
cards.add(new SetCardInfo("Blossoming Sands", 265, Rarity.COMMON, mage.cards.b.BlossomingSands.class));
|
||||
cards.add(new SetCardInfo("Boon of Boseiju", 176, Rarity.UNCOMMON, mage.cards.b.BoonOfBoseiju.class));
|
||||
cards.add(new SetCardInfo("Born to Drive", 6, Rarity.UNCOMMON, mage.cards.b.BornToDrive.class));
|
||||
cards.add(new SetCardInfo("Boseiju Reaches Skyward", 177, Rarity.UNCOMMON, mage.cards.b.BoseijuReachesSkyward.class));
|
||||
cards.add(new SetCardInfo("Boseiju, Who Endures", 266, Rarity.RARE, mage.cards.b.BoseijuWhoEndures.class));
|
||||
cards.add(new SetCardInfo("Boseiju, Who Endures", 266, Rarity.RARE, mage.cards.b.BoseijuWhoEndures.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Boseiju, Who Endures", 412, Rarity.RARE, mage.cards.b.BoseijuWhoEndures.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Boseiju, Who Endures", 501, Rarity.RARE, mage.cards.b.BoseijuWhoEndures.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Branch of Boseiju", 177, Rarity.UNCOMMON, mage.cards.b.BranchOfBoseiju.class));
|
||||
cards.add(new SetCardInfo("Brilliant Restoration", 7, Rarity.RARE, mage.cards.b.BrilliantRestoration.class));
|
||||
cards.add(new SetCardInfo("Brilliant Restoration", 363, Rarity.RARE, mage.cards.b.BrilliantRestoration.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Brilliant Restoration", 434, Rarity.RARE, mage.cards.b.BrilliantRestoration.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Brilliant Restoration", 7, Rarity.RARE, mage.cards.b.BrilliantRestoration.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Bronze Cudgels", 240, Rarity.UNCOMMON, mage.cards.b.BronzeCudgels.class));
|
||||
cards.add(new SetCardInfo("Bronzeplate Boar", 135, Rarity.UNCOMMON, mage.cards.b.BronzeplateBoar.class));
|
||||
cards.add(new SetCardInfo("Brute Suit", 241, Rarity.COMMON, mage.cards.b.BruteSuit.class));
|
||||
|
@ -63,45 +81,78 @@ public final class KamigawaNeonDynasty extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Chainflail Centipede", 90, Rarity.COMMON, mage.cards.c.ChainflailCentipede.class));
|
||||
cards.add(new SetCardInfo("Circuit Mender", 242, Rarity.UNCOMMON, mage.cards.c.CircuitMender.class));
|
||||
cards.add(new SetCardInfo("Clawing Torment", 91, Rarity.COMMON, mage.cards.c.ClawingTorment.class));
|
||||
cards.add(new SetCardInfo("Cloudsteel Kirin", 8, Rarity.RARE, mage.cards.c.CloudsteelKirin.class));
|
||||
cards.add(new SetCardInfo("Coiling Stalker", 179, Rarity.COMMON, mage.cards.c.CoilingStalker.class));
|
||||
cards.add(new SetCardInfo("Cloudsteel Kirin", 364, Rarity.RARE, mage.cards.c.CloudsteelKirin.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Cloudsteel Kirin", 435, Rarity.RARE, mage.cards.c.CloudsteelKirin.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Cloudsteel Kirin", 8, Rarity.RARE, mage.cards.c.CloudsteelKirin.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Coiling Stalker", 179, Rarity.COMMON, mage.cards.c.CoilingStalker.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Coiling Stalker", 346, Rarity.COMMON, mage.cards.c.CoilingStalker.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Colossal Skyturtle", 216, Rarity.UNCOMMON, mage.cards.c.ColossalSkyturtle.class));
|
||||
cards.add(new SetCardInfo("Commune with Spirits", 180, Rarity.COMMON, mage.cards.c.CommuneWithSpirits.class));
|
||||
cards.add(new SetCardInfo("Containment Construct", 243, Rarity.UNCOMMON, mage.cards.c.ContainmentConstruct.class));
|
||||
cards.add(new SetCardInfo("Covert Technician", 49, Rarity.UNCOMMON, mage.cards.c.CovertTechnician.class));
|
||||
cards.add(new SetCardInfo("Covert Technician", 332, Rarity.UNCOMMON, mage.cards.c.CovertTechnician.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Covert Technician", 49, Rarity.UNCOMMON, mage.cards.c.CovertTechnician.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Crackling Emergence", 136, Rarity.COMMON, mage.cards.c.CracklingEmergence.class));
|
||||
cards.add(new SetCardInfo("Debt to the Kami", 92, Rarity.COMMON, mage.cards.d.DebtToTheKami.class));
|
||||
cards.add(new SetCardInfo("Discover the Impossible", 50, Rarity.UNCOMMON, mage.cards.d.DiscoverTheImpossible.class));
|
||||
cards.add(new SetCardInfo("Dismal Backwater", 267, Rarity.COMMON, mage.cards.d.DismalBackwater.class));
|
||||
cards.add(new SetCardInfo("Disruption Protocol", 51, Rarity.COMMON, mage.cards.d.DisruptionProtocol.class));
|
||||
cards.add(new SetCardInfo("Dockside Chef", 93, Rarity.UNCOMMON, mage.cards.d.DocksideChef.class));
|
||||
cards.add(new SetCardInfo("Dokuchi Shadow-Walker", 94, Rarity.COMMON, mage.cards.d.DokuchiShadowWalker.class));
|
||||
cards.add(new SetCardInfo("Dokuchi Silencer", 95, Rarity.UNCOMMON, mage.cards.d.DokuchiSilencer.class));
|
||||
cards.add(new SetCardInfo("Dokuchi Shadow-Walker", 339, Rarity.COMMON, mage.cards.d.DokuchiShadowWalker.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Dokuchi Shadow-Walker", 94, Rarity.COMMON, mage.cards.d.DokuchiShadowWalker.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Dokuchi Silencer", 340, Rarity.UNCOMMON, mage.cards.d.DokuchiSilencer.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Dokuchi Silencer", 95, Rarity.UNCOMMON, mage.cards.d.DokuchiSilencer.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Dragon-Kami's Egg", 181, Rarity.RARE, mage.cards.d.DragonKamisEgg.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Dragon-Kami's Egg", 358, Rarity.RARE, mage.cards.d.DragonKamisEgg.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Dragon-Kami's Egg", 473, Rarity.RARE, mage.cards.d.DragonKamisEgg.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Dragonfly Suit", 9, Rarity.COMMON, mage.cards.d.DragonflySuit.class));
|
||||
cards.add(new SetCardInfo("Dragonspark Reactor", 137, Rarity.UNCOMMON, mage.cards.d.DragonsparkReactor.class));
|
||||
cards.add(new SetCardInfo("Dramatist's Puppet", 244, Rarity.COMMON, mage.cards.d.DramatistsPuppet.class));
|
||||
cards.add(new SetCardInfo("Eater of Virtue", 245, Rarity.RARE, mage.cards.e.EaterOfVirtue.class));
|
||||
cards.add(new SetCardInfo("Echo of Death's Wail", 124, Rarity.RARE, mage.cards.e.EchoOfDeathsWail.class));
|
||||
cards.add(new SetCardInfo("Eater of Virtue", 245, Rarity.RARE, mage.cards.e.EaterOfVirtue.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Eater of Virtue", 401, Rarity.RARE, mage.cards.e.EaterOfVirtue.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Eater of Virtue", 496, Rarity.RARE, mage.cards.e.EaterOfVirtue.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Echo of Death's Wail", 124, Rarity.RARE, mage.cards.e.EchoOfDeathsWail.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Echo of Death's Wail", 356, Rarity.RARE, mage.cards.e.EchoOfDeathsWail.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Echo of Death's Wail", 462, Rarity.RARE, mage.cards.e.EchoOfDeathsWail.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Ecologist's Terrarium", 246, Rarity.COMMON, mage.cards.e.EcologistsTerrarium.class));
|
||||
cards.add(new SetCardInfo("Eiganjo Exemplar", 10, Rarity.COMMON, mage.cards.e.EiganjoExemplar.class));
|
||||
cards.add(new SetCardInfo("Eiganjo Uprising", 217, Rarity.RARE, mage.cards.e.EiganjoUprising.class));
|
||||
cards.add(new SetCardInfo("Eiganjo, Seat of the Empire", 268, Rarity.RARE, mage.cards.e.EiganjoSeatOfTheEmpire.class));
|
||||
cards.add(new SetCardInfo("Eiganjo Exemplar", 10, Rarity.COMMON, mage.cards.e.EiganjoExemplar.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Eiganjo Exemplar", 309, Rarity.COMMON, mage.cards.e.EiganjoExemplar.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Eiganjo Uprising", 217, Rarity.RARE, mage.cards.e.EiganjoUprising.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Eiganjo Uprising", 396, Rarity.RARE, mage.cards.e.EiganjoUprising.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Eiganjo Uprising", 484, Rarity.RARE, mage.cards.e.EiganjoUprising.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Eiganjo, Seat of the Empire", 268, Rarity.RARE, mage.cards.e.EiganjoSeatOfTheEmpire.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Eiganjo, Seat of the Empire", 413, Rarity.RARE, mage.cards.e.EiganjoSeatOfTheEmpire.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Eiganjo, Seat of the Empire", 502, Rarity.RARE, mage.cards.e.EiganjoSeatOfTheEmpire.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Enormous Energy Blade", 96, Rarity.UNCOMMON, mage.cards.e.EnormousEnergyBlade.class));
|
||||
cards.add(new SetCardInfo("Enthusiastic Mechanaut", 218, Rarity.UNCOMMON, mage.cards.e.EnthusiasticMechanaut.class));
|
||||
cards.add(new SetCardInfo("Enthusiastic Mechanaut", 218, Rarity.UNCOMMON, mage.cards.e.EnthusiasticMechanaut.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Enthusiastic Mechanaut", 509, Rarity.UNCOMMON, mage.cards.e.EnthusiasticMechanaut.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Era of Enlightenment", 11, Rarity.COMMON, mage.cards.e.EraOfEnlightenment.class));
|
||||
cards.add(new SetCardInfo("Essence Capture", 52, Rarity.UNCOMMON, mage.cards.e.EssenceCapture.class));
|
||||
cards.add(new SetCardInfo("Etching of Kumano", 152, Rarity.UNCOMMON, mage.cards.e.EtchingOfKumano.class));
|
||||
cards.add(new SetCardInfo("Experimental Synthesizer", 138, Rarity.COMMON, mage.cards.e.ExperimentalSynthesizer.class));
|
||||
cards.add(new SetCardInfo("Explosive Entry", 139, Rarity.COMMON, mage.cards.e.ExplosiveEntry.class));
|
||||
cards.add(new SetCardInfo("Explosive Singularity", 140, Rarity.MYTHIC, mage.cards.e.ExplosiveSingularity.class));
|
||||
cards.add(new SetCardInfo("Fable of the Mirror-Breaker", 141, Rarity.RARE, mage.cards.f.FableOfTheMirrorBreaker.class));
|
||||
cards.add(new SetCardInfo("Explosive Singularity", 140, Rarity.MYTHIC, mage.cards.e.ExplosiveSingularity.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Explosive Singularity", 383, Rarity.MYTHIC, mage.cards.e.ExplosiveSingularity.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Explosive Singularity", 422, Rarity.MYTHIC, mage.cards.e.ExplosiveSingularity.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Explosive Singularity", 464, Rarity.MYTHIC, mage.cards.e.ExplosiveSingularity.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Fable of the Mirror-Breaker", 141, Rarity.RARE, mage.cards.f.FableOfTheMirrorBreaker.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Fable of the Mirror-Breaker", 357, Rarity.RARE, mage.cards.f.FableOfTheMirrorBreaker.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Fable of the Mirror-Breaker", 465, Rarity.RARE, mage.cards.f.FableOfTheMirrorBreaker.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Fade into Antiquity", 182, Rarity.COMMON, mage.cards.f.FadeIntoAntiquity.class));
|
||||
cards.add(new SetCardInfo("Fang of Shigeki", 183, Rarity.COMMON, mage.cards.f.FangOfShigeki.class));
|
||||
cards.add(new SetCardInfo("Farewell", 13, Rarity.RARE, mage.cards.f.Farewell.class));
|
||||
cards.add(new SetCardInfo("Fang of Shigeki", 183, Rarity.COMMON, mage.cards.f.FangOfShigeki.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Fang of Shigeki", 347, Rarity.COMMON, mage.cards.f.FangOfShigeki.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Farewell", 13, Rarity.RARE, mage.cards.f.Farewell.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Farewell", 365, Rarity.RARE, mage.cards.f.Farewell.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Farewell", 417, Rarity.RARE, mage.cards.f.Farewell.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Farewell", 436, Rarity.RARE, mage.cards.f.Farewell.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Favor of Jukai", 184, Rarity.COMMON, mage.cards.f.FavorOfJukai.class));
|
||||
cards.add(new SetCardInfo("Flame Discharge", 142, Rarity.UNCOMMON, mage.cards.f.FlameDischarge.class));
|
||||
cards.add(new SetCardInfo("Forest", 291, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Forest", 292, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Forest", 301, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS));
|
||||
cards.add(new SetCardInfo("Forest", 302, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS));
|
||||
cards.add(new SetCardInfo("Fragment of Konda", 12, Rarity.UNCOMMON, mage.cards.f.FragmentOfKonda.class));
|
||||
cards.add(new SetCardInfo("Futurist Operative", 53, Rarity.UNCOMMON, mage.cards.f.FuturistOperative.class));
|
||||
cards.add(new SetCardInfo("Futurist Operative", 333, Rarity.UNCOMMON, mage.cards.f.FuturistOperative.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Futurist Operative", 53, Rarity.UNCOMMON, mage.cards.f.FuturistOperative.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Futurist Sentinel", 54, Rarity.COMMON, mage.cards.f.FuturistSentinel.class));
|
||||
cards.add(new SetCardInfo("Generous Visitor", 185, Rarity.UNCOMMON, mage.cards.g.GenerousVisitor.class));
|
||||
cards.add(new SetCardInfo("Geothermal Kami", 186, Rarity.COMMON, mage.cards.g.GeothermalKami.class));
|
||||
|
@ -113,217 +164,413 @@ public final class KamigawaNeonDynasty extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Go-Shintai of Lost Wisdom", 55, Rarity.UNCOMMON, mage.cards.g.GoShintaiOfLostWisdom.class));
|
||||
cards.add(new SetCardInfo("Go-Shintai of Shared Purpose", 14, Rarity.UNCOMMON, mage.cards.g.GoShintaiOfSharedPurpose.class));
|
||||
cards.add(new SetCardInfo("Golden-Tail Disciple", 15, Rarity.COMMON, mage.cards.g.GoldenTailDisciple.class));
|
||||
cards.add(new SetCardInfo("Goro-Goro, Disciple of Ryusei", 145, Rarity.RARE, mage.cards.g.GoroGoroDiscipleOfRyusei.class));
|
||||
cards.add(new SetCardInfo("Goro-Goro, Disciple of Ryusei", 145, Rarity.RARE, mage.cards.g.GoroGoroDiscipleOfRyusei.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Goro-Goro, Disciple of Ryusei", 320, Rarity.RARE, mage.cards.g.GoroGoroDiscipleOfRyusei.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Goro-Goro, Disciple of Ryusei", 466, Rarity.RARE, mage.cards.g.GoroGoroDiscipleOfRyusei.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Grafted Growth", 188, Rarity.COMMON, mage.cards.g.GraftedGrowth.class));
|
||||
cards.add(new SetCardInfo("Gravelighter", 98, Rarity.UNCOMMON, mage.cards.g.Gravelighter.class));
|
||||
cards.add(new SetCardInfo("Greasefang, Okiba Boss", 220, Rarity.RARE, mage.cards.g.GreasefangOkibaBoss.class));
|
||||
cards.add(new SetCardInfo("Greasefang, Okiba Boss", 220, Rarity.RARE, mage.cards.g.GreasefangOkibaBoss.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Greasefang, Okiba Boss", 397, Rarity.RARE, mage.cards.g.GreasefangOkibaBoss.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Greasefang, Okiba Boss", 485, Rarity.RARE, mage.cards.g.GreasefangOkibaBoss.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Greater Tanuki", 189, Rarity.COMMON, mage.cards.g.GreaterTanuki.class));
|
||||
cards.add(new SetCardInfo("Guardians of Oboro", 56, Rarity.COMMON, mage.cards.g.GuardiansOfOboro.class));
|
||||
cards.add(new SetCardInfo("Guardians of Oboro", 317, Rarity.COMMON, mage.cards.g.GuardiansOfOboro.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Guardians of Oboro", 56, Rarity.COMMON, mage.cards.g.GuardiansOfOboro.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Hand of Enlightenment", 11, Rarity.COMMON, mage.cards.h.HandOfEnlightenment.class));
|
||||
cards.add(new SetCardInfo("Harmonious Emergence", 190, Rarity.COMMON, mage.cards.h.HarmoniousEmergence.class));
|
||||
cards.add(new SetCardInfo("Heiko Yamazaki, the General", 146, Rarity.UNCOMMON, mage.cards.h.HeikoYamazakiTheGeneral.class));
|
||||
cards.add(new SetCardInfo("Heir of the Ancient Fang", 191, Rarity.COMMON, mage.cards.h.HeirOfTheAncientFang.class));
|
||||
cards.add(new SetCardInfo("Hidetsugu Consumes All", 221, Rarity.MYTHIC, mage.cards.h.HidetsuguConsumesAll.class));
|
||||
cards.add(new SetCardInfo("Hidetsugu, Devouring Chaos", 99, Rarity.RARE, mage.cards.h.HidetsuguDevouringChaos.class));
|
||||
cards.add(new SetCardInfo("Heiko Yamazaki, the General", 146, Rarity.UNCOMMON, mage.cards.h.HeikoYamazakiTheGeneral.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Heiko Yamazaki, the General", 321, Rarity.UNCOMMON, mage.cards.h.HeikoYamazakiTheGeneral.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Heir of the Ancient Fang", 191, Rarity.COMMON, mage.cards.h.HeirOfTheAncientFang.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Heir of the Ancient Fang", 325, Rarity.COMMON, mage.cards.h.HeirOfTheAncientFang.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Hidetsugu Consumes All", 221, Rarity.MYTHIC, mage.cards.h.HidetsuguConsumesAll.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Hidetsugu Consumes All", 361, Rarity.MYTHIC, mage.cards.h.HidetsuguConsumesAll.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Hidetsugu Consumes All", 486, Rarity.MYTHIC, mage.cards.h.HidetsuguConsumesAll.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Hidetsugu, Devouring Chaos", 378, Rarity.RARE, mage.cards.h.HidetsuguDevouringChaos.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Hidetsugu, Devouring Chaos", 429, Rarity.RARE, mage.cards.h.HidetsuguDevouringChaos.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Hidetsugu, Devouring Chaos", 430, Rarity.RARE, mage.cards.h.HidetsuguDevouringChaos.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Hidetsugu, Devouring Chaos", 431, Rarity.RARE, mage.cards.h.HidetsuguDevouringChaos.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Hidetsugu, Devouring Chaos", 432, Rarity.RARE, mage.cards.h.HidetsuguDevouringChaos.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Hidetsugu, Devouring Chaos", 454, Rarity.RARE, mage.cards.h.HidetsuguDevouringChaos.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Hidetsugu, Devouring Chaos", 99, Rarity.RARE, mage.cards.h.HidetsuguDevouringChaos.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("High-Speed Hoverbike", 247, Rarity.UNCOMMON, mage.cards.h.HighSpeedHoverbike.class));
|
||||
cards.add(new SetCardInfo("Hinata, Dawn-Crowned", 222, Rarity.RARE, mage.cards.h.HinataDawnCrowned.class));
|
||||
cards.add(new SetCardInfo("Hinata, Dawn-Crowned", 222, Rarity.RARE, mage.cards.h.HinataDawnCrowned.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Hinata, Dawn-Crowned", 398, Rarity.RARE, mage.cards.h.HinataDawnCrowned.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Hinata, Dawn-Crowned", 487, Rarity.RARE, mage.cards.h.HinataDawnCrowned.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Historian's Wisdom", 192, Rarity.UNCOMMON, mage.cards.h.HistoriansWisdom.class));
|
||||
cards.add(new SetCardInfo("Hotshot Mechanic", 16, Rarity.UNCOMMON, mage.cards.h.HotshotMechanic.class));
|
||||
cards.add(new SetCardInfo("Imperial Moth", 4, Rarity.COMMON, mage.cards.i.ImperialMoth.class));
|
||||
cards.add(new SetCardInfo("Imperial Oath", 17, Rarity.COMMON, mage.cards.i.ImperialOath.class));
|
||||
cards.add(new SetCardInfo("Imperial Recovery Unit", 18, Rarity.UNCOMMON, mage.cards.i.ImperialRecoveryUnit.class));
|
||||
cards.add(new SetCardInfo("Imperial Subduer", 19, Rarity.COMMON, mage.cards.i.ImperialSubduer.class));
|
||||
cards.add(new SetCardInfo("Inkrise Infiltrator", 100, Rarity.COMMON, mage.cards.i.InkriseInfiltrator.class));
|
||||
cards.add(new SetCardInfo("Imperial Subduer", 19, Rarity.COMMON, mage.cards.i.ImperialSubduer.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Imperial Subduer", 310, Rarity.COMMON, mage.cards.i.ImperialSubduer.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Inkrise Infiltrator", 100, Rarity.COMMON, mage.cards.i.InkriseInfiltrator.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Inkrise Infiltrator", 341, Rarity.COMMON, mage.cards.i.InkriseInfiltrator.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Intercessor's Arrest", 20, Rarity.COMMON, mage.cards.i.IntercessorsArrest.class));
|
||||
cards.add(new SetCardInfo("Inventive Iteration", 57, Rarity.RARE, mage.cards.i.InventiveIteration.class));
|
||||
cards.add(new SetCardInfo("Inventive Iteration", 355, Rarity.RARE, mage.cards.i.InventiveIteration.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Inventive Iteration", 443, Rarity.RARE, mage.cards.i.InventiveIteration.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Inventive Iteration", 57, Rarity.RARE, mage.cards.i.InventiveIteration.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Invigorating Hot Spring", 223, Rarity.UNCOMMON, mage.cards.i.InvigoratingHotSpring.class));
|
||||
cards.add(new SetCardInfo("Invoke Despair", 101, Rarity.RARE, mage.cards.i.InvokeDespair.class));
|
||||
cards.add(new SetCardInfo("Invoke Justice", 21, Rarity.RARE, mage.cards.i.InvokeJustice.class));
|
||||
cards.add(new SetCardInfo("Invoke the Ancients", 193, Rarity.RARE, mage.cards.i.InvokeTheAncients.class));
|
||||
cards.add(new SetCardInfo("Invoke the Winds", 58, Rarity.RARE, mage.cards.i.InvokeTheWinds.class));
|
||||
cards.add(new SetCardInfo("Invoke Calamity", 147, Rarity.RARE, mage.cards.i.InvokeCalamity.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Invoke Calamity", 384, Rarity.RARE, mage.cards.i.InvokeCalamity.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Invoke Calamity", 467, Rarity.RARE, mage.cards.i.InvokeCalamity.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Invoke Despair", 101, Rarity.RARE, mage.cards.i.InvokeDespair.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Invoke Despair", 379, Rarity.RARE, mage.cards.i.InvokeDespair.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Invoke Despair", 455, Rarity.RARE, mage.cards.i.InvokeDespair.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Invoke Despair", 506, Rarity.RARE, mage.cards.i.InvokeDespair.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Invoke Justice", 21, Rarity.RARE, mage.cards.i.InvokeJustice.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Invoke Justice", 366, Rarity.RARE, mage.cards.i.InvokeJustice.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Invoke Justice", 437, Rarity.RARE, mage.cards.i.InvokeJustice.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Invoke the Ancients", 193, Rarity.RARE, mage.cards.i.InvokeTheAncients.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Invoke the Ancients", 390, Rarity.RARE, mage.cards.i.InvokeTheAncients.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Invoke the Ancients", 474, Rarity.RARE, mage.cards.i.InvokeTheAncients.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Invoke the Winds", 370, Rarity.RARE, mage.cards.i.InvokeTheWinds.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Invoke the Winds", 444, Rarity.RARE, mage.cards.i.InvokeTheWinds.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Invoke the Winds", 58, Rarity.RARE, mage.cards.i.InvokeTheWinds.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Iron Apprentice", 248, Rarity.COMMON, mage.cards.i.IronApprentice.class));
|
||||
cards.add(new SetCardInfo("Ironhoof Boar", 148, Rarity.COMMON, mage.cards.i.IronhoofBoar.class));
|
||||
cards.add(new SetCardInfo("Island", 285, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Isshin, Two Heavens as One", 224, Rarity.RARE, mage.cards.i.IsshinTwoHeavensAsOne.class));
|
||||
cards.add(new SetCardInfo("Jin-Gitaxias, Progress Tyrant", 59, Rarity.MYTHIC, mage.cards.j.JinGitaxiasProgressTyrant.class));
|
||||
cards.add(new SetCardInfo("Jugan Defends the Temple", 194, Rarity.MYTHIC, mage.cards.j.JuganDefendsTheTemple.class));
|
||||
cards.add(new SetCardInfo("Jukai Naturalist", 225, Rarity.UNCOMMON, mage.cards.j.JukaiNaturalist.class));
|
||||
cards.add(new SetCardInfo("Island", 286, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Island", 295, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS));
|
||||
cards.add(new SetCardInfo("Island", 296, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS));
|
||||
cards.add(new SetCardInfo("Isshin, Two Heavens as One", 224, Rarity.RARE, mage.cards.i.IsshinTwoHeavensAsOne.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Isshin, Two Heavens as One", 328, Rarity.RARE, mage.cards.i.IsshinTwoHeavensAsOne.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Isshin, Two Heavens as One", 488, Rarity.RARE, mage.cards.i.IsshinTwoHeavensAsOne.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Jin-Gitaxias, Progress Tyrant", 307, Rarity.MYTHIC, mage.cards.j.JinGitaxiasProgressTyrant.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Jin-Gitaxias, Progress Tyrant", 371, Rarity.MYTHIC, mage.cards.j.JinGitaxiasProgressTyrant.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Jin-Gitaxias, Progress Tyrant", 427, Rarity.MYTHIC, mage.cards.j.JinGitaxiasProgressTyrant.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Jin-Gitaxias, Progress Tyrant", 445, Rarity.MYTHIC, mage.cards.j.JinGitaxiasProgressTyrant.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Jin-Gitaxias, Progress Tyrant", 59, Rarity.MYTHIC, mage.cards.j.JinGitaxiasProgressTyrant.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Jugan Defends the Temple", 194, Rarity.MYTHIC, mage.cards.j.JuganDefendsTheTemple.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Jugan Defends the Temple", 359, Rarity.MYTHIC, mage.cards.j.JuganDefendsTheTemple.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Jugan Defends the Temple", 475, Rarity.MYTHIC, mage.cards.j.JuganDefendsTheTemple.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Jukai Naturalist", 225, Rarity.UNCOMMON, mage.cards.j.JukaiNaturalist.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Jukai Naturalist", 510, Rarity.UNCOMMON, mage.cards.j.JukaiNaturalist.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Jukai Preserver", 195, Rarity.COMMON, mage.cards.j.JukaiPreserver.class));
|
||||
cards.add(new SetCardInfo("Jukai Trainee", 196, Rarity.COMMON, mage.cards.j.JukaiTrainee.class));
|
||||
cards.add(new SetCardInfo("Jukai Trainee", 196, Rarity.COMMON, mage.cards.j.JukaiTrainee.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Jukai Trainee", 326, Rarity.COMMON, mage.cards.j.JukaiTrainee.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Jungle Hollow", 269, Rarity.COMMON, mage.cards.j.JungleHollow.class));
|
||||
cards.add(new SetCardInfo("Junji, the Midnight Sky", 102, Rarity.MYTHIC, mage.cards.j.JunjiTheMidnightSky.class));
|
||||
cards.add(new SetCardInfo("Kairi, the Swirling Sky", 60, Rarity.MYTHIC, mage.cards.k.KairiTheSwirlingSky.class));
|
||||
cards.add(new SetCardInfo("Kaito Shizuki", 226, Rarity.MYTHIC, mage.cards.k.KaitoShizuki.class));
|
||||
cards.add(new SetCardInfo("Junji, the Midnight Sky", 102, Rarity.MYTHIC, mage.cards.j.JunjiTheMidnightSky.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Junji, the Midnight Sky", 409, Rarity.MYTHIC, mage.cards.j.JunjiTheMidnightSky.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Junji, the Midnight Sky", 456, Rarity.MYTHIC, mage.cards.j.JunjiTheMidnightSky.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kairi, the Swirling Sky", 408, Rarity.MYTHIC, mage.cards.k.KairiTheSwirlingSky.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kairi, the Swirling Sky", 446, Rarity.MYTHIC, mage.cards.k.KairiTheSwirlingSky.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kairi, the Swirling Sky", 60, Rarity.MYTHIC, mage.cards.k.KairiTheSwirlingSky.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kaito Shizuki", 226, Rarity.MYTHIC, mage.cards.k.KaitoShizuki.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kaito Shizuki", 305, Rarity.MYTHIC, mage.cards.k.KaitoShizuki.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kaito Shizuki", 350, Rarity.MYTHIC, mage.cards.k.KaitoShizuki.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kaito Shizuki", 424, Rarity.MYTHIC, mage.cards.k.KaitoShizuki.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kaito's Pursuit", 103, Rarity.COMMON, mage.cards.k.KaitosPursuit.class));
|
||||
cards.add(new SetCardInfo("Kami of Industry", 149, Rarity.COMMON, mage.cards.k.KamiOfIndustry.class));
|
||||
cards.add(new SetCardInfo("Kami of Restless Shadows", 104, Rarity.COMMON, mage.cards.k.KamiOfRestlessShadows.class));
|
||||
cards.add(new SetCardInfo("Kami of Terrible Secrets", 105, Rarity.COMMON, mage.cards.k.KamiOfTerribleSecrets.class));
|
||||
cards.add(new SetCardInfo("Kami of Transience", 197, Rarity.RARE, mage.cards.k.KamiOfTransience.class));
|
||||
cards.add(new SetCardInfo("Kami of Transience", 197, Rarity.RARE, mage.cards.k.KamiOfTransience.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kami of Transience", 391, Rarity.RARE, mage.cards.k.KamiOfTransience.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kami of Transience", 476, Rarity.RARE, mage.cards.k.KamiOfTransience.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kami's Flare", 150, Rarity.COMMON, mage.cards.k.KamisFlare.class));
|
||||
cards.add(new SetCardInfo("Kappa Tech-Wrecker", 198, Rarity.UNCOMMON, mage.cards.k.KappaTechWrecker.class));
|
||||
cards.add(new SetCardInfo("Kappa Tech-Wrecker", 198, Rarity.UNCOMMON, mage.cards.k.KappaTechWrecker.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kappa Tech-Wrecker", 348, Rarity.UNCOMMON, mage.cards.k.KappaTechWrecker.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kindled Fury", 151, Rarity.COMMON, mage.cards.k.KindledFury.class));
|
||||
cards.add(new SetCardInfo("Kirin-Touched Orochi", 212, Rarity.RARE, mage.cards.k.KirinTouchedOrochi.class));
|
||||
cards.add(new SetCardInfo("Kirin-Touched Orochi", 212, Rarity.RARE, mage.cards.k.KirinTouchedOrochi.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kirin-Touched Orochi", 360, Rarity.RARE, mage.cards.k.KirinTouchedOrochi.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kirin-Touched Orochi", 482, Rarity.RARE, mage.cards.k.KirinTouchedOrochi.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kitsune Ace", 22, Rarity.COMMON, mage.cards.k.KitsuneAce.class));
|
||||
cards.add(new SetCardInfo("Kodama of the West Tree", 199, Rarity.MYTHIC, mage.cards.k.KodamaOfTheWestTree.class));
|
||||
cards.add(new SetCardInfo("Kotose, the Silent Spider", 351, Rarity.RARE, mage.cards.k.KotoseTheSilentSpider.class));
|
||||
cards.add(new SetCardInfo("Kodama of the West Tree", 199, Rarity.MYTHIC, mage.cards.k.KodamaOfTheWestTree.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kodama of the West Tree", 392, Rarity.MYTHIC, mage.cards.k.KodamaOfTheWestTree.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kodama of the West Tree", 423, Rarity.MYTHIC, mage.cards.k.KodamaOfTheWestTree.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kodama of the West Tree", 477, Rarity.MYTHIC, mage.cards.k.KodamaOfTheWestTree.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kotose, the Silent Spider", 228, Rarity.RARE, mage.cards.k.KotoseTheSilentSpider.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kotose, the Silent Spider", 351, Rarity.RARE, mage.cards.k.KotoseTheSilentSpider.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kotose, the Silent Spider", 490, Rarity.RARE, mage.cards.k.KotoseTheSilentSpider.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kumano Faces Kakkazan", 152, Rarity.UNCOMMON, mage.cards.k.KumanoFacesKakkazan.class));
|
||||
cards.add(new SetCardInfo("Kura, the Boundless Sky", 200, Rarity.MYTHIC, mage.cards.k.KuraTheBoundlessSky.class));
|
||||
cards.add(new SetCardInfo("Kyodai, Soul of Kamigawa", 23, Rarity.RARE, mage.cards.k.KyodaiSoulOfKamigawa.class));
|
||||
cards.add(new SetCardInfo("Kura, the Boundless Sky", 200, Rarity.MYTHIC, mage.cards.k.KuraTheBoundlessSky.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kura, the Boundless Sky", 411, Rarity.MYTHIC, mage.cards.k.KuraTheBoundlessSky.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kura, the Boundless Sky", 478, Rarity.MYTHIC, mage.cards.k.KuraTheBoundlessSky.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kyodai, Soul of Kamigawa", 23, Rarity.RARE, mage.cards.k.KyodaiSoulOfKamigawa.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kyodai, Soul of Kamigawa", 407, Rarity.RARE, mage.cards.k.KyodaiSoulOfKamigawa.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kyodai, Soul of Kamigawa", 438, Rarity.RARE, mage.cards.k.KyodaiSoulOfKamigawa.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Leech Gauntlet", 106, Rarity.UNCOMMON, mage.cards.l.LeechGauntlet.class));
|
||||
cards.add(new SetCardInfo("Lethal Exploit", 107, Rarity.COMMON, mage.cards.l.LethalExploit.class));
|
||||
cards.add(new SetCardInfo("Life of Toshiro Umezawa", 108, Rarity.UNCOMMON, mage.cards.l.LifeOfToshiroUmezawa.class));
|
||||
cards.add(new SetCardInfo("Light the Way", 24, Rarity.COMMON, mage.cards.l.LightTheWay.class));
|
||||
cards.add(new SetCardInfo("Light-Paws, Emperor's Voice", 25, Rarity.RARE, mage.cards.l.LightPawsEmperorsVoice.class));
|
||||
cards.add(new SetCardInfo("Light-Paws, Emperor's Voice", 25, Rarity.RARE, mage.cards.l.LightPawsEmperorsVoice.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Light-Paws, Emperor's Voice", 367, Rarity.RARE, mage.cards.l.LightPawsEmperorsVoice.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Light-Paws, Emperor's Voice", 439, Rarity.RARE, mage.cards.l.LightPawsEmperorsVoice.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Likeness of the Seeker", 172, Rarity.UNCOMMON, mage.cards.l.LikenessOfTheSeeker.class));
|
||||
cards.add(new SetCardInfo("Lion Sash", 26, Rarity.RARE, mage.cards.l.LionSash.class));
|
||||
cards.add(new SetCardInfo("Living Breakthrough", 57, Rarity.RARE, mage.cards.l.LivingBreakthrough.class));
|
||||
cards.add(new SetCardInfo("Lizard Blades", 153, Rarity.RARE, mage.cards.l.LizardBlades.class));
|
||||
cards.add(new SetCardInfo("Lion Sash", 26, Rarity.RARE, mage.cards.l.LionSash.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Lion Sash", 368, Rarity.RARE, mage.cards.l.LionSash.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Lion Sash", 440, Rarity.RARE, mage.cards.l.LionSash.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Living Breakthrough", 355, Rarity.RARE, mage.cards.l.LivingBreakthrough.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Living Breakthrough", 443, Rarity.RARE, mage.cards.l.LivingBreakthrough.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Living Breakthrough", 57, Rarity.RARE, mage.cards.l.LivingBreakthrough.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Lizard Blades", 153, Rarity.RARE, mage.cards.l.LizardBlades.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Lizard Blades", 385, Rarity.RARE, mage.cards.l.LizardBlades.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Lizard Blades", 468, Rarity.RARE, mage.cards.l.LizardBlades.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Lucky Offering", 27, Rarity.COMMON, mage.cards.l.LuckyOffering.class));
|
||||
cards.add(new SetCardInfo("Malicious Malfunction", 110, Rarity.UNCOMMON, mage.cards.m.MaliciousMalfunction.class));
|
||||
cards.add(new SetCardInfo("March of Burgeoning Life", 201, Rarity.RARE, mage.cards.m.MarchOfBurgeoningLife.class));
|
||||
cards.add(new SetCardInfo("March of Otherworldly Light", 28, Rarity.RARE, mage.cards.m.MarchOfOtherworldlyLight.class));
|
||||
cards.add(new SetCardInfo("March of Reckless Joy", 154, Rarity.RARE, mage.cards.m.MarchOfRecklessJoy.class));
|
||||
cards.add(new SetCardInfo("March of Swirling Mist", 61, Rarity.RARE, mage.cards.m.MarchOfSwirlingMist.class));
|
||||
cards.add(new SetCardInfo("March of Wretched Sorrow", 111, Rarity.RARE, mage.cards.m.MarchOfWretchedSorrow.class));
|
||||
cards.add(new SetCardInfo("March of Burgeoning Life", 201, Rarity.RARE, mage.cards.m.MarchOfBurgeoningLife.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("March of Burgeoning Life", 393, Rarity.RARE, mage.cards.m.MarchOfBurgeoningLife.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("March of Burgeoning Life", 479, Rarity.RARE, mage.cards.m.MarchOfBurgeoningLife.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("March of Otherworldly Light", 28, Rarity.RARE, mage.cards.m.MarchOfOtherworldlyLight.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("March of Otherworldly Light", 369, Rarity.RARE, mage.cards.m.MarchOfOtherworldlyLight.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("March of Otherworldly Light", 441, Rarity.RARE, mage.cards.m.MarchOfOtherworldlyLight.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("March of Reckless Joy", 154, Rarity.RARE, mage.cards.m.MarchOfRecklessJoy.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("March of Reckless Joy", 386, Rarity.RARE, mage.cards.m.MarchOfRecklessJoy.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("March of Reckless Joy", 469, Rarity.RARE, mage.cards.m.MarchOfRecklessJoy.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("March of Swirling Mist", 372, Rarity.RARE, mage.cards.m.MarchOfSwirlingMist.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("March of Swirling Mist", 447, Rarity.RARE, mage.cards.m.MarchOfSwirlingMist.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("March of Swirling Mist", 61, Rarity.RARE, mage.cards.m.MarchOfSwirlingMist.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("March of Wretched Sorrow", 111, Rarity.RARE, mage.cards.m.MarchOfWretchedSorrow.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("March of Wretched Sorrow", 380, Rarity.RARE, mage.cards.m.MarchOfWretchedSorrow.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("March of Wretched Sorrow", 457, Rarity.RARE, mage.cards.m.MarchOfWretchedSorrow.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Master's Rebuke", 202, Rarity.COMMON, mage.cards.m.MastersRebuke.class));
|
||||
cards.add(new SetCardInfo("Mech Hangar", 270, Rarity.UNCOMMON, mage.cards.m.MechHangar.class));
|
||||
cards.add(new SetCardInfo("Mechtitan Core", 249, Rarity.RARE, mage.cards.m.MechtitanCore.class));
|
||||
cards.add(new SetCardInfo("Mechtitan Core", 249, Rarity.RARE, mage.cards.m.MechtitanCore.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mechtitan Core", 402, Rarity.RARE, mage.cards.m.MechtitanCore.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mechtitan Core", 497, Rarity.RARE, mage.cards.m.MechtitanCore.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Memory of Toshiro", 108, Rarity.UNCOMMON, mage.cards.m.MemoryOfToshiro.class));
|
||||
cards.add(new SetCardInfo("Michiko's Reign of Truth", 29, Rarity.UNCOMMON, mage.cards.m.MichikosReignOfTruth.class));
|
||||
cards.add(new SetCardInfo("Mindlink Mech", 62, Rarity.RARE, mage.cards.m.MindlinkMech.class));
|
||||
cards.add(new SetCardInfo("Mirror Box", 250, Rarity.RARE, mage.cards.m.MirrorBox.class));
|
||||
cards.add(new SetCardInfo("Mindlink Mech", 373, Rarity.RARE, mage.cards.m.MindlinkMech.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mindlink Mech", 448, Rarity.RARE, mage.cards.m.MindlinkMech.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mindlink Mech", 62, Rarity.RARE, mage.cards.m.MindlinkMech.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mirror Box", 250, Rarity.RARE, mage.cards.m.MirrorBox.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mirror Box", 403, Rarity.RARE, mage.cards.m.MirrorBox.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mirror Box", 498, Rarity.RARE, mage.cards.m.MirrorBox.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mirrorshell Crab", 63, Rarity.COMMON, mage.cards.m.MirrorshellCrab.class));
|
||||
cards.add(new SetCardInfo("Mnemonic Sphere", 64, Rarity.COMMON, mage.cards.m.MnemonicSphere.class));
|
||||
cards.add(new SetCardInfo("Mobilizer Mech", 65, Rarity.UNCOMMON, mage.cards.m.MobilizerMech.class));
|
||||
cards.add(new SetCardInfo("Moon-Circuit Hacker", 67, Rarity.COMMON, mage.cards.m.MoonCircuitHacker.class));
|
||||
cards.add(new SetCardInfo("Moon-Circuit Hacker", 334, Rarity.COMMON, mage.cards.m.MoonCircuitHacker.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Moon-Circuit Hacker", 67, Rarity.COMMON, mage.cards.m.MoonCircuitHacker.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Moonfolk Puzzlemaker", 68, Rarity.COMMON, mage.cards.m.MoonfolkPuzzlemaker.class));
|
||||
cards.add(new SetCardInfo("Moonsnare Prototype", 69, Rarity.COMMON, mage.cards.m.MoonsnarePrototype.class));
|
||||
cards.add(new SetCardInfo("Moonsnare Specialist", 70, Rarity.COMMON, mage.cards.m.MoonsnareSpecialist.class));
|
||||
cards.add(new SetCardInfo("Moonsnare Specialist", 335, Rarity.COMMON, mage.cards.m.MoonsnareSpecialist.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Moonsnare Specialist", 70, Rarity.COMMON, mage.cards.m.MoonsnareSpecialist.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mothrider Patrol", 30, Rarity.COMMON, mage.cards.m.MothriderPatrol.class));
|
||||
cards.add(new SetCardInfo("Mountain", 289, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mukotai Ambusher", 112, Rarity.COMMON, mage.cards.m.MukotaiAmbusher.class));
|
||||
cards.add(new SetCardInfo("Mukotai Soulripper", 113, Rarity.RARE, mage.cards.m.MukotaiSoulripper.class));
|
||||
cards.add(new SetCardInfo("Mountain", 290, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mountain", 299, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mountain", 300, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mukotai Ambusher", 112, Rarity.COMMON, mage.cards.m.MukotaiAmbusher.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mukotai Ambusher", 342, Rarity.COMMON, mage.cards.m.MukotaiAmbusher.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mukotai Soulripper", 113, Rarity.RARE, mage.cards.m.MukotaiSoulripper.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mukotai Soulripper", 381, Rarity.RARE, mage.cards.m.MukotaiSoulripper.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mukotai Soulripper", 458, Rarity.RARE, mage.cards.m.MukotaiSoulripper.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Nameless Conqueror", 162, Rarity.COMMON, mage.cards.n.NamelessConqueror.class));
|
||||
cards.add(new SetCardInfo("Naomi, Pillar of Order", 229, Rarity.UNCOMMON, mage.cards.n.NaomiPillarOfOrder.class));
|
||||
cards.add(new SetCardInfo("Nashi, Moon Sage's Scion", 114, Rarity.MYTHIC, mage.cards.n.NashiMoonSagesScion.class));
|
||||
cards.add(new SetCardInfo("Nashi, Moon Sage's Scion", 114, Rarity.MYTHIC, mage.cards.n.NashiMoonSagesScion.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Nashi, Moon Sage's Scion", 343, Rarity.MYTHIC, mage.cards.n.NashiMoonSagesScion.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Nashi, Moon Sage's Scion", 421, Rarity.MYTHIC, mage.cards.n.NashiMoonSagesScion.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Nashi, Moon Sage's Scion", 459, Rarity.MYTHIC, mage.cards.n.NashiMoonSagesScion.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Network Disruptor", 71, Rarity.COMMON, mage.cards.n.NetworkDisruptor.class));
|
||||
cards.add(new SetCardInfo("Network Terminal", 251, Rarity.COMMON, mage.cards.n.NetworkTerminal.class));
|
||||
cards.add(new SetCardInfo("Nezumi Bladeblesser", 115, Rarity.COMMON, mage.cards.n.NezumiBladeblesser.class));
|
||||
cards.add(new SetCardInfo("Nezumi Prowler", 116, Rarity.UNCOMMON, mage.cards.n.NezumiProwler.class));
|
||||
cards.add(new SetCardInfo("Nezumi Bladeblesser", 115, Rarity.COMMON, mage.cards.n.NezumiBladeblesser.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Nezumi Bladeblesser", 318, Rarity.COMMON, mage.cards.n.NezumiBladeblesser.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Nezumi Prowler", 116, Rarity.UNCOMMON, mage.cards.n.NezumiProwler.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Nezumi Prowler", 344, Rarity.UNCOMMON, mage.cards.n.NezumiProwler.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Nezumi Road Captain", 117, Rarity.COMMON, mage.cards.n.NezumiRoadCaptain.class));
|
||||
cards.add(new SetCardInfo("Ninja's Kunai", 252, Rarity.COMMON, mage.cards.n.NinjasKunai.class));
|
||||
cards.add(new SetCardInfo("Norika Yamazaki, the Poet", 31, Rarity.UNCOMMON, mage.cards.n.NorikaYamazakiThePoet.class));
|
||||
cards.add(new SetCardInfo("O-Kagachi Made Manifest", 227, Rarity.MYTHIC, mage.cards.o.OKagachiMadeManifest.class));
|
||||
cards.add(new SetCardInfo("Ogre-Head Helm", 155, Rarity.RARE, mage.cards.o.OgreHeadHelm.class));
|
||||
cards.add(new SetCardInfo("Norika Yamazaki, the Poet", 31, Rarity.UNCOMMON, mage.cards.n.NorikaYamazakiThePoet.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Norika Yamazaki, the Poet", 311, Rarity.UNCOMMON, mage.cards.n.NorikaYamazakiThePoet.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("O-Kagachi Made Manifest", 227, Rarity.MYTHIC, mage.cards.o.OKagachiMadeManifest.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("O-Kagachi Made Manifest", 362, Rarity.MYTHIC, mage.cards.o.OKagachiMadeManifest.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("O-Kagachi Made Manifest", 489, Rarity.MYTHIC, mage.cards.o.OKagachiMadeManifest.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Ogre-Head Helm", 155, Rarity.RARE, mage.cards.o.OgreHeadHelm.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Ogre-Head Helm", 387, Rarity.RARE, mage.cards.o.OgreHeadHelm.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Ogre-Head Helm", 470, Rarity.RARE, mage.cards.o.OgreHeadHelm.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Okiba Reckoner Raid", 117, Rarity.COMMON, mage.cards.o.OkibaReckonerRaid.class));
|
||||
cards.add(new SetCardInfo("Okiba Salvage", 118, Rarity.UNCOMMON, mage.cards.o.OkibaSalvage.class));
|
||||
cards.add(new SetCardInfo("Oni-Cult Anvil", 230, Rarity.UNCOMMON, mage.cards.o.OniCultAnvil.class));
|
||||
cards.add(new SetCardInfo("Orochi Merge-Keeper", 203, Rarity.UNCOMMON, mage.cards.o.OrochiMergeKeeper.class));
|
||||
cards.add(new SetCardInfo("Otawara, Soaring City", 271, Rarity.RARE, mage.cards.o.OtawaraSoaringCity.class));
|
||||
cards.add(new SetCardInfo("Otawara, Soaring City", 271, Rarity.RARE, mage.cards.o.OtawaraSoaringCity.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Otawara, Soaring City", 414, Rarity.RARE, mage.cards.o.OtawaraSoaringCity.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Otawara, Soaring City", 503, Rarity.RARE, mage.cards.o.OtawaraSoaringCity.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Papercraft Decoy", 253, Rarity.COMMON, mage.cards.p.PapercraftDecoy.class));
|
||||
cards.add(new SetCardInfo("Patchwork Automaton", 254, Rarity.UNCOMMON, mage.cards.p.PatchworkAutomaton.class));
|
||||
cards.add(new SetCardInfo("Peerless Samurai", 156, Rarity.COMMON, mage.cards.p.PeerlessSamurai.class));
|
||||
cards.add(new SetCardInfo("Peerless Samurai", 156, Rarity.COMMON, mage.cards.p.PeerlessSamurai.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Peerless Samurai", 322, Rarity.COMMON, mage.cards.p.PeerlessSamurai.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Plains", 283, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Plains", 284, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Plains", 293, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS));
|
||||
cards.add(new SetCardInfo("Plains", 294, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS));
|
||||
cards.add(new SetCardInfo("Planar Incision", 72, Rarity.COMMON, mage.cards.p.PlanarIncision.class));
|
||||
cards.add(new SetCardInfo("Portrait of Michiko", 29, Rarity.UNCOMMON, mage.cards.p.PortraitOfMichiko.class));
|
||||
cards.add(new SetCardInfo("Prodigy's Prototype", 231, Rarity.UNCOMMON, mage.cards.p.ProdigysPrototype.class));
|
||||
cards.add(new SetCardInfo("Prosperous Thief", 73, Rarity.UNCOMMON, mage.cards.p.ProsperousThief.class));
|
||||
cards.add(new SetCardInfo("Prosperous Thief", 336, Rarity.UNCOMMON, mage.cards.p.ProsperousThief.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Prosperous Thief", 73, Rarity.UNCOMMON, mage.cards.p.ProsperousThief.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Rabbit Battery", 157, Rarity.UNCOMMON, mage.cards.r.RabbitBattery.class));
|
||||
cards.add(new SetCardInfo("Raiyuu, Storm's Edge", 232, Rarity.RARE, mage.cards.r.RaiyuuStormsEdge.class));
|
||||
cards.add(new SetCardInfo("Raiyuu, Storm's Edge", 232, Rarity.RARE, mage.cards.r.RaiyuuStormsEdge.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Raiyuu, Storm's Edge", 329, Rarity.RARE, mage.cards.r.RaiyuuStormsEdge.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Raiyuu, Storm's Edge", 491, Rarity.RARE, mage.cards.r.RaiyuuStormsEdge.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Reality Heist", 75, Rarity.UNCOMMON, mage.cards.r.RealityHeist.class));
|
||||
cards.add(new SetCardInfo("Reckoner Bankbuster", 255, Rarity.RARE, mage.cards.r.ReckonerBankbuster.class));
|
||||
cards.add(new SetCardInfo("Reckoner Bankbuster", 255, Rarity.RARE, mage.cards.r.ReckonerBankbuster.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Reckoner Bankbuster", 404, Rarity.RARE, mage.cards.r.ReckonerBankbuster.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Reckoner Bankbuster", 499, Rarity.RARE, mage.cards.r.ReckonerBankbuster.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Reckoner Shakedown", 119, Rarity.COMMON, mage.cards.r.ReckonerShakedown.class));
|
||||
cards.add(new SetCardInfo("Reckoner's Bargain", 120, Rarity.COMMON, mage.cards.r.ReckonersBargain.class));
|
||||
cards.add(new SetCardInfo("Reflection of Kiki-Jiki", 141, Rarity.RARE, mage.cards.r.ReflectionOfKikiJiki.class));
|
||||
cards.add(new SetCardInfo("Reflection of Kiki-Jiki", 141, Rarity.RARE, mage.cards.r.ReflectionOfKikiJiki.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Reflection of Kiki-Jiki", 357, Rarity.RARE, mage.cards.r.ReflectionOfKikiJiki.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Reflection of Kiki-Jiki", 465, Rarity.RARE, mage.cards.r.ReflectionOfKikiJiki.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Regent's Authority", 32, Rarity.COMMON, mage.cards.r.RegentsAuthority.class));
|
||||
cards.add(new SetCardInfo("Reinforced Ronin", 158, Rarity.UNCOMMON, mage.cards.r.ReinforcedRonin.class));
|
||||
cards.add(new SetCardInfo("Reinforced Ronin", 158, Rarity.UNCOMMON, mage.cards.r.ReinforcedRonin.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Reinforced Ronin", 323, Rarity.UNCOMMON, mage.cards.r.ReinforcedRonin.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Reito Sentinel", 256, Rarity.UNCOMMON, mage.cards.r.ReitoSentinel.class));
|
||||
cards.add(new SetCardInfo("Remnant of the Rising Star", 194, Rarity.MYTHIC, mage.cards.r.RemnantOfTheRisingStar.class));
|
||||
cards.add(new SetCardInfo("Remnant of the Rising Star", 194, Rarity.MYTHIC, mage.cards.r.RemnantOfTheRisingStar.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Remnant of the Rising Star", 359, Rarity.MYTHIC, mage.cards.r.RemnantOfTheRisingStar.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Remnant of the Rising Star", 475, Rarity.MYTHIC, mage.cards.r.RemnantOfTheRisingStar.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Repel the Vile", 33, Rarity.COMMON, mage.cards.r.RepelTheVile.class));
|
||||
cards.add(new SetCardInfo("Replication Specialist", 76, Rarity.UNCOMMON, mage.cards.r.ReplicationSpecialist.class));
|
||||
cards.add(new SetCardInfo("Return to Action", 121, Rarity.COMMON, mage.cards.r.ReturnToAction.class));
|
||||
cards.add(new SetCardInfo("Risona, Asari Commander", 233, Rarity.RARE, mage.cards.r.RisonaAsariCommander.class));
|
||||
cards.add(new SetCardInfo("Risona, Asari Commander", 233, Rarity.RARE, mage.cards.r.RisonaAsariCommander.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Risona, Asari Commander", 330, Rarity.RARE, mage.cards.r.RisonaAsariCommander.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Risona, Asari Commander", 425, Rarity.RARE, mage.cards.r.RisonaAsariCommander.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Risona, Asari Commander", 492, Rarity.RARE, mage.cards.r.RisonaAsariCommander.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Roadside Reliquary", 272, Rarity.UNCOMMON, mage.cards.r.RoadsideReliquary.class));
|
||||
cards.add(new SetCardInfo("Roaring Earth", 204, Rarity.UNCOMMON, mage.cards.r.RoaringEarth.class));
|
||||
cards.add(new SetCardInfo("Rugged Highlands", 273, Rarity.COMMON, mage.cards.r.RuggedHighlands.class));
|
||||
cards.add(new SetCardInfo("Runaway Trash-Bot", 257, Rarity.UNCOMMON, mage.cards.r.RunawayTrashBot.class));
|
||||
cards.add(new SetCardInfo("Saiba Trespassers", 77, Rarity.COMMON, mage.cards.s.SaibaTrespassers.class));
|
||||
cards.add(new SetCardInfo("Satoru Umezawa", 234, Rarity.RARE, mage.cards.s.SatoruUmezawa.class));
|
||||
cards.add(new SetCardInfo("Satsuki, the Living Lore", 235, Rarity.RARE, mage.cards.s.SatsukiTheLivingLore.class));
|
||||
cards.add(new SetCardInfo("Satoru Umezawa", 234, Rarity.RARE, mage.cards.s.SatoruUmezawa.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Satoru Umezawa", 352, Rarity.RARE, mage.cards.s.SatoruUmezawa.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Satoru Umezawa", 426, Rarity.RARE, mage.cards.s.SatoruUmezawa.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Satoru Umezawa", 493, Rarity.RARE, mage.cards.s.SatoruUmezawa.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Satoru Umezawa", 507, Rarity.RARE, mage.cards.s.SatoruUmezawa.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Satsuki, the Living Lore", 235, Rarity.RARE, mage.cards.s.SatsukiTheLivingLore.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Satsuki, the Living Lore", 399, Rarity.RARE, mage.cards.s.SatsukiTheLivingLore.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Satsuki, the Living Lore", 494, Rarity.RARE, mage.cards.s.SatsukiTheLivingLore.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Scoured Barrens", 274, Rarity.COMMON, mage.cards.s.ScouredBarrens.class));
|
||||
cards.add(new SetCardInfo("Scrap Welder", 159, Rarity.RARE, mage.cards.s.ScrapWelder.class));
|
||||
cards.add(new SetCardInfo("Scrap Welder", 159, Rarity.RARE, mage.cards.s.ScrapWelder.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Scrap Welder", 388, Rarity.RARE, mage.cards.s.ScrapWelder.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Scrap Welder", 471, Rarity.RARE, mage.cards.s.ScrapWelder.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Scrapyard Steelbreaker", 160, Rarity.COMMON, mage.cards.s.ScrapyardSteelbreaker.class));
|
||||
cards.add(new SetCardInfo("Searchlight Companion", 258, Rarity.COMMON, mage.cards.s.SearchlightCompanion.class));
|
||||
cards.add(new SetCardInfo("Season of Renewal", 205, Rarity.COMMON, mage.cards.s.SeasonOfRenewal.class));
|
||||
cards.add(new SetCardInfo("Secluded Courtyard", 275, Rarity.UNCOMMON, mage.cards.s.SecludedCourtyard.class));
|
||||
cards.add(new SetCardInfo("Secluded Courtyard", 275, Rarity.UNCOMMON, mage.cards.s.SecludedCourtyard.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Secluded Courtyard", 512, Rarity.UNCOMMON, mage.cards.s.SecludedCourtyard.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Seismic Wave", 161, Rarity.UNCOMMON, mage.cards.s.SeismicWave.class));
|
||||
cards.add(new SetCardInfo("Selfless Samurai", 35, Rarity.UNCOMMON, mage.cards.s.SelflessSamurai.class));
|
||||
cards.add(new SetCardInfo("Selfless Samurai", 312, Rarity.UNCOMMON, mage.cards.s.SelflessSamurai.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Selfless Samurai", 35, Rarity.UNCOMMON, mage.cards.s.SelflessSamurai.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Seshiro's Living Legacy", 210, Rarity.COMMON, mage.cards.s.SeshirosLivingLegacy.class));
|
||||
cards.add(new SetCardInfo("Seven-Tail Mentor", 36, Rarity.COMMON, mage.cards.s.SevenTailMentor.class));
|
||||
cards.add(new SetCardInfo("Shigeki, Jukai Visionary", 206, Rarity.RARE, mage.cards.s.ShigekiJukaiVisionary.class));
|
||||
cards.add(new SetCardInfo("Seven-Tail Mentor", 313, Rarity.COMMON, mage.cards.s.SevenTailMentor.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Seven-Tail Mentor", 36, Rarity.COMMON, mage.cards.s.SevenTailMentor.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Shigeki, Jukai Visionary", 206, Rarity.RARE, mage.cards.s.ShigekiJukaiVisionary.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Shigeki, Jukai Visionary", 394, Rarity.RARE, mage.cards.s.ShigekiJukaiVisionary.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Shigeki, Jukai Visionary", 480, Rarity.RARE, mage.cards.s.ShigekiJukaiVisionary.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Short Circuit", 78, Rarity.COMMON, mage.cards.s.ShortCircuit.class));
|
||||
cards.add(new SetCardInfo("Shrine Steward", 259, Rarity.COMMON, mage.cards.s.ShrineSteward.class));
|
||||
cards.add(new SetCardInfo("Silver-Fur Master", 236, Rarity.UNCOMMON, mage.cards.s.SilverFurMaster.class));
|
||||
cards.add(new SetCardInfo("Silver-Fur Master", 236, Rarity.UNCOMMON, mage.cards.s.SilverFurMaster.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Silver-Fur Master", 353, Rarity.UNCOMMON, mage.cards.s.SilverFurMaster.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Silver-Fur Master", 511, Rarity.UNCOMMON, mage.cards.s.SilverFurMaster.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Simian Sling", 163, Rarity.COMMON, mage.cards.s.SimianSling.class));
|
||||
cards.add(new SetCardInfo("Sky-Blessed Samurai", 37, Rarity.UNCOMMON, mage.cards.s.SkyBlessedSamurai.class));
|
||||
cards.add(new SetCardInfo("Sky-Blessed Samurai", 314, Rarity.UNCOMMON, mage.cards.s.SkyBlessedSamurai.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Sky-Blessed Samurai", 37, Rarity.UNCOMMON, mage.cards.s.SkyBlessedSamurai.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Skyswimmer Koi", 79, Rarity.COMMON, mage.cards.s.SkyswimmerKoi.class));
|
||||
cards.add(new SetCardInfo("Sokenzan Smelter", 164, Rarity.UNCOMMON, mage.cards.s.SokenzanSmelter.class));
|
||||
cards.add(new SetCardInfo("Sokenzan, Crucible of Defiance", 276, Rarity.RARE, mage.cards.s.SokenzanCrucibleOfDefiance.class));
|
||||
cards.add(new SetCardInfo("Soul Transfer", 122, Rarity.RARE, mage.cards.s.SoulTransfer.class));
|
||||
cards.add(new SetCardInfo("Sokenzan, Crucible of Defiance", 276, Rarity.RARE, mage.cards.s.SokenzanCrucibleOfDefiance.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Sokenzan, Crucible of Defiance", 415, Rarity.RARE, mage.cards.s.SokenzanCrucibleOfDefiance.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Sokenzan, Crucible of Defiance", 504, Rarity.RARE, mage.cards.s.SokenzanCrucibleOfDefiance.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Soul Transfer", 122, Rarity.RARE, mage.cards.s.SoulTransfer.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Soul Transfer", 382, Rarity.RARE, mage.cards.s.SoulTransfer.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Soul Transfer", 460, Rarity.RARE, mage.cards.s.SoulTransfer.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Spell Pierce", 80, Rarity.COMMON, mage.cards.s.SpellPierce.class));
|
||||
cards.add(new SetCardInfo("Spinning Wheel Kick", 207, Rarity.UNCOMMON, mage.cards.s.SpinningWheelKick.class));
|
||||
cards.add(new SetCardInfo("Spirit-Sister's Call", 237, Rarity.MYTHIC, mage.cards.s.SpiritSistersCall.class));
|
||||
cards.add(new SetCardInfo("Spirited Companion", 38, Rarity.COMMON, mage.cards.s.SpiritedCompanion.class));
|
||||
cards.add(new SetCardInfo("Spring-Leaf Avenger", 208, Rarity.RARE, mage.cards.s.SpringLeafAvenger.class));
|
||||
cards.add(new SetCardInfo("Spirit-Sister's Call", 237, Rarity.MYTHIC, mage.cards.s.SpiritSistersCall.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Spirit-Sister's Call", 400, Rarity.MYTHIC, mage.cards.s.SpiritSistersCall.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Spirit-Sister's Call", 495, Rarity.MYTHIC, mage.cards.s.SpiritSistersCall.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Spirited Companion", 38, Rarity.COMMON, mage.cards.s.SpiritedCompanion.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Spirited Companion", 508, Rarity.COMMON, mage.cards.s.SpiritedCompanion.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Spring-Leaf Avenger", 208, Rarity.RARE, mage.cards.s.SpringLeafAvenger.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Spring-Leaf Avenger", 349, Rarity.RARE, mage.cards.s.SpringLeafAvenger.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Spring-Leaf Avenger", 481, Rarity.RARE, mage.cards.s.SpringLeafAvenger.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Storyweave", 209, Rarity.UNCOMMON, mage.cards.s.Storyweave.class));
|
||||
cards.add(new SetCardInfo("Suit Up", 81, Rarity.COMMON, mage.cards.s.SuitUp.class));
|
||||
cards.add(new SetCardInfo("Sunblade Samurai", 39, Rarity.COMMON, mage.cards.s.SunbladeSamurai.class));
|
||||
cards.add(new SetCardInfo("Surgehacker Mech", 260, Rarity.RARE, mage.cards.s.SurgehackerMech.class));
|
||||
cards.add(new SetCardInfo("Sunblade Samurai", 315, Rarity.COMMON, mage.cards.s.SunbladeSamurai.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Sunblade Samurai", 39, Rarity.COMMON, mage.cards.s.SunbladeSamurai.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Surgehacker Mech", 260, Rarity.RARE, mage.cards.s.SurgehackerMech.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Surgehacker Mech", 405, Rarity.RARE, mage.cards.s.SurgehackerMech.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Surgehacker Mech", 500, Rarity.RARE, mage.cards.s.SurgehackerMech.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Swamp", 287, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Swamp", 288, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Swamp", 297, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS));
|
||||
cards.add(new SetCardInfo("Swamp", 298, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS));
|
||||
cards.add(new SetCardInfo("Swiftwater Cliffs", 277, Rarity.COMMON, mage.cards.s.SwiftwaterCliffs.class));
|
||||
cards.add(new SetCardInfo("Takenuma, Abandoned Mire", 278, Rarity.RARE, mage.cards.t.TakenumaAbandonedMire.class));
|
||||
cards.add(new SetCardInfo("Takenuma, Abandoned Mire", 278, Rarity.RARE, mage.cards.t.TakenumaAbandonedMire.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Takenuma, Abandoned Mire", 416, Rarity.RARE, mage.cards.t.TakenumaAbandonedMire.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Takenuma, Abandoned Mire", 505, Rarity.RARE, mage.cards.t.TakenumaAbandonedMire.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tales of Master Seshiro", 210, Rarity.COMMON, mage.cards.t.TalesOfMasterSeshiro.class));
|
||||
cards.add(new SetCardInfo("Tameshi, Reality Architect", 82, Rarity.RARE, mage.cards.t.TameshiRealityArchitect.class));
|
||||
cards.add(new SetCardInfo("Tameshi, Reality Architect", 375, Rarity.RARE, mage.cards.t.TameshiRealityArchitect.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tameshi, Reality Architect", 450, Rarity.RARE, mage.cards.t.TameshiRealityArchitect.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tameshi, Reality Architect", 82, Rarity.RARE, mage.cards.t.TameshiRealityArchitect.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tamiyo's Compleation", 83, Rarity.COMMON, mage.cards.t.TamiyosCompleation.class));
|
||||
cards.add(new SetCardInfo("Tamiyo's Safekeeping", 211, Rarity.COMMON, mage.cards.t.TamiyosSafekeeping.class));
|
||||
cards.add(new SetCardInfo("Tamiyo, Compleated Sage", 238, Rarity.MYTHIC, mage.cards.t.TamiyoCompleatedSage.class));
|
||||
cards.add(new SetCardInfo("Tatsunari, Toad Rider", 123, Rarity.RARE, mage.cards.t.TatsunariToadRider.class));
|
||||
cards.add(new SetCardInfo("Teachings of the Kirin", 212, Rarity.RARE, mage.cards.t.TeachingsOfTheKirin.class));
|
||||
cards.add(new SetCardInfo("Tamiyo, Compleated Sage", 238, Rarity.MYTHIC, mage.cards.t.TamiyoCompleatedSage.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tamiyo, Compleated Sage", 306, Rarity.MYTHIC, mage.cards.t.TamiyoCompleatedSage.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tamiyo, Compleated Sage", 308, Rarity.MYTHIC, mage.cards.t.TamiyoCompleatedSage.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tamiyo, Compleated Sage", 428, Rarity.MYTHIC, mage.cards.t.TamiyoCompleatedSage.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tatsunari, Toad Rider", 123, Rarity.RARE, mage.cards.t.TatsunariToadRider.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tatsunari, Toad Rider", 345, Rarity.RARE, mage.cards.t.TatsunariToadRider.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tatsunari, Toad Rider", 461, Rarity.RARE, mage.cards.t.TatsunariToadRider.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Teachings of the Kirin", 212, Rarity.RARE, mage.cards.t.TeachingsOfTheKirin.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Teachings of the Kirin", 360, Rarity.RARE, mage.cards.t.TeachingsOfTheKirin.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Teachings of the Kirin", 482, Rarity.RARE, mage.cards.t.TeachingsOfTheKirin.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tempered in Solitude", 165, Rarity.UNCOMMON, mage.cards.t.TemperedInSolitude.class));
|
||||
cards.add(new SetCardInfo("Tezzeret, Betrayer of Flesh", 84, Rarity.MYTHIC, mage.cards.t.TezzeretBetrayerOfFlesh.class));
|
||||
cards.add(new SetCardInfo("Tezzeret, Betrayer of Flesh", 304, Rarity.MYTHIC, mage.cards.t.TezzeretBetrayerOfFlesh.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tezzeret, Betrayer of Flesh", 376, Rarity.MYTHIC, mage.cards.t.TezzeretBetrayerOfFlesh.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tezzeret, Betrayer of Flesh", 419, Rarity.MYTHIC, mage.cards.t.TezzeretBetrayerOfFlesh.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tezzeret, Betrayer of Flesh", 84, Rarity.MYTHIC, mage.cards.t.TezzeretBetrayerOfFlesh.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Dragon-Kami Reborn", 181, Rarity.RARE, mage.cards.t.TheDragonKamiReborn.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Dragon-Kami Reborn", 358, Rarity.RARE, mage.cards.t.TheDragonKamiReborn.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Dragon-Kami Reborn", 473, Rarity.RARE, mage.cards.t.TheDragonKamiReborn.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Fall of Lord Konda", 12, Rarity.UNCOMMON, mage.cards.t.TheFallOfLordKonda.class));
|
||||
cards.add(new SetCardInfo("The Kami War", 227, Rarity.MYTHIC, mage.cards.t.TheKamiWar.class));
|
||||
cards.add(new SetCardInfo("The Kami War", 227, Rarity.MYTHIC, mage.cards.t.TheKamiWar.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Kami War", 362, Rarity.MYTHIC, mage.cards.t.TheKamiWar.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Kami War", 489, Rarity.MYTHIC, mage.cards.t.TheKamiWar.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Long Reach of Night", 109, Rarity.UNCOMMON, mage.cards.t.TheLongReachOfNight.class));
|
||||
cards.add(new SetCardInfo("The Modern Age", 66, Rarity.COMMON, mage.cards.t.TheModernAge.class));
|
||||
cards.add(new SetCardInfo("The Reality Chip", 74, Rarity.RARE, mage.cards.t.TheRealityChip.class));
|
||||
cards.add(new SetCardInfo("The Restoration of Eiganjo", 34, Rarity.RARE, mage.cards.t.TheRestorationOfEiganjo.class));
|
||||
cards.add(new SetCardInfo("The Reality Chip", 374, Rarity.RARE, mage.cards.t.TheRealityChip.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Reality Chip", 449, Rarity.RARE, mage.cards.t.TheRealityChip.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Reality Chip", 74, Rarity.RARE, mage.cards.t.TheRealityChip.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Restoration of Eiganjo", 34, Rarity.RARE, mage.cards.t.TheRestorationOfEiganjo.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Restoration of Eiganjo", 354, Rarity.RARE, mage.cards.t.TheRestorationOfEiganjo.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Restoration of Eiganjo", 442, Rarity.RARE, mage.cards.t.TheRestorationOfEiganjo.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Shattered States Era", 162, Rarity.COMMON, mage.cards.t.TheShatteredStatesEra.class));
|
||||
cards.add(new SetCardInfo("The Wandering Emperor", 42, Rarity.MYTHIC, mage.cards.t.TheWanderingEmperor.class));
|
||||
cards.add(new SetCardInfo("The Wandering Emperor", 303, Rarity.MYTHIC, mage.cards.t.TheWanderingEmperor.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Wandering Emperor", 316, Rarity.MYTHIC, mage.cards.t.TheWanderingEmperor.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Wandering Emperor", 418, Rarity.MYTHIC, mage.cards.t.TheWanderingEmperor.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Wandering Emperor", 42, Rarity.MYTHIC, mage.cards.t.TheWanderingEmperor.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Thirst for Knowledge", 85, Rarity.UNCOMMON, mage.cards.t.ThirstForKnowledge.class));
|
||||
cards.add(new SetCardInfo("Thornwood Falls", 279, Rarity.COMMON, mage.cards.t.ThornwoodFalls.class));
|
||||
cards.add(new SetCardInfo("Thousand-Faced Shadow", 86, Rarity.RARE, mage.cards.t.ThousandFacedShadow.class));
|
||||
cards.add(new SetCardInfo("Thundering Raiju", 166, Rarity.RARE, mage.cards.t.ThunderingRaiju.class));
|
||||
cards.add(new SetCardInfo("Thousand-Faced Shadow", 337, Rarity.RARE, mage.cards.t.ThousandFacedShadow.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Thousand-Faced Shadow", 451, Rarity.RARE, mage.cards.t.ThousandFacedShadow.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Thousand-Faced Shadow", 86, Rarity.RARE, mage.cards.t.ThousandFacedShadow.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Thundering Raiju", 166, Rarity.RARE, mage.cards.t.ThunderingRaiju.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Thundering Raiju", 389, Rarity.RARE, mage.cards.t.ThunderingRaiju.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Thundering Raiju", 472, Rarity.RARE, mage.cards.t.ThunderingRaiju.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Thundersteel Colossus", 261, Rarity.COMMON, mage.cards.t.ThundersteelColossus.class));
|
||||
cards.add(new SetCardInfo("Touch the Spirit Realm", 40, Rarity.UNCOMMON, mage.cards.t.TouchTheSpiritRealm.class));
|
||||
cards.add(new SetCardInfo("Towashi Guide-Bot", 262, Rarity.UNCOMMON, mage.cards.t.TowashiGuideBot.class));
|
||||
cards.add(new SetCardInfo("Towashi Songshaper", 167, Rarity.COMMON, mage.cards.t.TowashiSongshaper.class));
|
||||
cards.add(new SetCardInfo("Tranquil Cove", 280, Rarity.COMMON, mage.cards.t.TranquilCove.class));
|
||||
cards.add(new SetCardInfo("Tribute to Horobi", 124, Rarity.RARE, mage.cards.t.TributeToHorobi.class));
|
||||
cards.add(new SetCardInfo("Tribute to Horobi", 124, Rarity.RARE, mage.cards.t.TributeToHorobi.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tribute to Horobi", 356, Rarity.RARE, mage.cards.t.TributeToHorobi.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tribute to Horobi", 462, Rarity.RARE, mage.cards.t.TributeToHorobi.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Twinshot Sniper", 168, Rarity.UNCOMMON, mage.cards.t.TwinshotSniper.class));
|
||||
cards.add(new SetCardInfo("Twisted Embrace", 125, Rarity.COMMON, mage.cards.t.TwistedEmbrace.class));
|
||||
cards.add(new SetCardInfo("Uncharted Haven", 281, Rarity.COMMON, mage.cards.u.UnchartedHaven.class));
|
||||
cards.add(new SetCardInfo("Undercity Scrounger", 126, Rarity.COMMON, mage.cards.u.UndercityScrounger.class));
|
||||
cards.add(new SetCardInfo("Unforgiving One", 127, Rarity.UNCOMMON, mage.cards.u.UnforgivingOne.class));
|
||||
cards.add(new SetCardInfo("Unstoppable Ogre", 169, Rarity.COMMON, mage.cards.u.UnstoppableOgre.class));
|
||||
cards.add(new SetCardInfo("Upriser Renegade", 170, Rarity.UNCOMMON, mage.cards.u.UpriserRenegade.class));
|
||||
cards.add(new SetCardInfo("Upriser Renegade", 170, Rarity.UNCOMMON, mage.cards.u.UpriserRenegade.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Upriser Renegade", 324, Rarity.UNCOMMON, mage.cards.u.UpriserRenegade.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Vector Glider", 66, Rarity.COMMON, mage.cards.v.VectorGlider.class));
|
||||
cards.add(new SetCardInfo("Vessel of the All-Consuming", 221, Rarity.MYTHIC, mage.cards.v.VesselOfTheAllConsuming.class));
|
||||
cards.add(new SetCardInfo("Vessel of the All-Consuming", 221, Rarity.MYTHIC, mage.cards.v.VesselOfTheAllConsuming.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Vessel of the All-Consuming", 361, Rarity.MYTHIC, mage.cards.v.VesselOfTheAllConsuming.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Vessel of the All-Consuming", 486, Rarity.MYTHIC, mage.cards.v.VesselOfTheAllConsuming.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Virus Beetle", 128, Rarity.COMMON, mage.cards.v.VirusBeetle.class));
|
||||
cards.add(new SetCardInfo("Vision of the Unspeakable", 48, Rarity.UNCOMMON, mage.cards.v.VisionOfTheUnspeakable.class));
|
||||
cards.add(new SetCardInfo("Voltage Surge", 171, Rarity.COMMON, mage.cards.v.VoltageSurge.class));
|
||||
cards.add(new SetCardInfo("Walking Skyscraper", 263, Rarity.UNCOMMON, mage.cards.w.WalkingSkyscraper.class));
|
||||
cards.add(new SetCardInfo("Wanderer's Intervention", 41, Rarity.COMMON, mage.cards.w.WanderersIntervention.class));
|
||||
cards.add(new SetCardInfo("Weaver of Harmony", 213, Rarity.RARE, mage.cards.w.WeaverOfHarmony.class));
|
||||
cards.add(new SetCardInfo("Weaver of Harmony", 213, Rarity.RARE, mage.cards.w.WeaverOfHarmony.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Weaver of Harmony", 395, Rarity.RARE, mage.cards.w.WeaverOfHarmony.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Weaver of Harmony", 483, Rarity.RARE, mage.cards.w.WeaverOfHarmony.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Webspinner Cuff", 214, Rarity.UNCOMMON, mage.cards.w.WebspinnerCuff.class));
|
||||
cards.add(new SetCardInfo("When We Were Young", 43, Rarity.UNCOMMON, mage.cards.w.WhenWeWereYoung.class));
|
||||
cards.add(new SetCardInfo("Wind-Scarred Crag", 282, Rarity.COMMON, mage.cards.w.WindScarredCrag.class));
|
||||
|
|
|
@ -143,7 +143,7 @@ public class BuybackTest extends CardTestPlayerBase {
|
|||
// bolt 2 - cast (R) and copy as free cast (R), return reiterate with buyback (RRR)
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerA);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}, {T}:");
|
||||
setChoice(playerA, "Reiterate"); // free cast
|
||||
setChoice(playerA, true); // cast for free
|
||||
setChoice(playerA, true); // use buyback
|
||||
addTarget(playerA, "Lightning Bolt"); // copy target
|
||||
setChoice(playerA, false); // same bolt's target
|
||||
|
|
|
@ -670,7 +670,6 @@ public class KickerTest extends CardTestPlayerBase {
|
|||
// attack and prepare free cast, use kicker
|
||||
attack(1, playerA, "Etali, Primal Storm", playerB);
|
||||
setChoice(playerA, true); // cast for free
|
||||
setChoice(playerA, "Ardent Soldier"); // cast for free
|
||||
setChoice(playerA, true); // use kicker
|
||||
|
||||
setStrictChooseMode(true);
|
||||
|
@ -703,7 +702,6 @@ public class KickerTest extends CardTestPlayerBase {
|
|||
// attack and prepare free cast
|
||||
attack(1, playerA, "Etali, Primal Storm", playerB);
|
||||
setChoice(playerA, true); // cast for free
|
||||
setChoice(playerA, "Thieving Skydiver"); // cast for free
|
||||
setChoice(playerA, true); // use kicker
|
||||
setChoiceAmount(playerA, 2); // X=2 for Kicker X
|
||||
addTarget(playerA, "Brain in a Jar"); // kicker's target (take control of artifact)
|
||||
|
|
|
@ -766,4 +766,122 @@ public class AdventureCardsTest extends CardTestPlayerBase {
|
|||
execute();
|
||||
assertAllCommandsUsed();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Cascade_CuriousPair() {
|
||||
// If a player cascades into Curious Pair with Bloodbraid Elf they can cast either spell
|
||||
removeAllCardsFromLibrary(playerA);
|
||||
skipInitShuffling();
|
||||
|
||||
// Cascade
|
||||
addCard(Zone.HAND, playerA, "Bloodbraid Elf"); // {2}{R}{G}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
|
||||
//
|
||||
addCard(Zone.LIBRARY, playerA, "Swamp", 2);
|
||||
addCard(Zone.LIBRARY, playerA, "Curious Pair", 1);
|
||||
addCard(Zone.LIBRARY, playerA, "Island", 2);
|
||||
|
||||
// play elf with cascade
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bloodbraid Elf");
|
||||
setChoice(playerA, true); // use free cast
|
||||
setChoice(playerA, "Cast Treats to Share"); // can cast either
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Curious Pair", 0);
|
||||
assertPermanentCount(playerA, "Food", 1);
|
||||
assertExileCount(playerA, "Curious Pair", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Cascade_FlaxenIntruder() {
|
||||
// If a player cascades into Flaxen Intruder with Bloodbraid Elf they shouldn't be able to cast Welcome Home
|
||||
removeAllCardsFromLibrary(playerA);
|
||||
skipInitShuffling();
|
||||
|
||||
// Cascade
|
||||
addCard(Zone.HAND, playerA, "Bloodbraid Elf"); // {2}{R}{G}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
|
||||
//
|
||||
addCard(Zone.LIBRARY, playerA, "Swamp", 2);
|
||||
addCard(Zone.LIBRARY, playerA, "Flaxen Intruder", 1);
|
||||
addCard(Zone.LIBRARY, playerA, "Island", 2);
|
||||
|
||||
// play elf with cascade
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bloodbraid Elf");
|
||||
setChoice(playerA, true); // use free cast
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Flaxen Intruder", 1);
|
||||
assertPermanentCount(playerA, "Bear", 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_SramsExpertise_CuriousPair() {
|
||||
addCard(Zone.HAND, playerA, "Sram's Expertise");
|
||||
addCard(Zone.HAND, playerA, "Curious Pair");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sram's Expertise");
|
||||
setChoice(playerA, true); // use free cast
|
||||
setChoice(playerA, "Cast Treats to Share");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Curious Pair", 0);
|
||||
assertPermanentCount(playerA, "Food", 1);
|
||||
assertPermanentCount(playerA, "Servo", 3);
|
||||
assertExileCount(playerA, "Curious Pair", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_SramsExpertise_FlaxenIntruder() {
|
||||
addCard(Zone.HAND, playerA, "Sram's Expertise");
|
||||
addCard(Zone.HAND, playerA, "Flaxen Intruder");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sram's Expertise");
|
||||
setChoice(playerA, true); // use free cast
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Flaxen Intruder", 1);
|
||||
assertPermanentCount(playerA, "Bear", 0);
|
||||
assertPermanentCount(playerA, "Servo", 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_SramsExpertise_LonesomeUnicorn() {
|
||||
addCard(Zone.HAND, playerA, "Sram's Expertise");
|
||||
addCard(Zone.HAND, playerA, "Lonesome Unicorn");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sram's Expertise");
|
||||
setChoice(playerA, true); // use free cast
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Lonesome Unicorn", 0);
|
||||
assertPermanentCount(playerA, "Knight", 1);
|
||||
assertPermanentCount(playerA, "Servo", 3);
|
||||
assertExileCount(playerA, "Lonesome Unicorn", 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -866,6 +866,44 @@ public class ModalDoubleFacesCardsTest extends CardTestPlayerBase {
|
|||
assertPermanentCount(playerA, "The Omenkeel", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_SramsExpertise_ValkiGodOfLies() {
|
||||
addCard(Zone.HAND, playerA, "Sram's Expertise");
|
||||
addCard(Zone.HAND, playerA, "Valki, God of Lies");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sram's Expertise");
|
||||
setChoice(playerA, true); // use free cast
|
||||
setChoice(playerA, TestPlayer.CHOICE_SKIP); // no choices for valki's etb exile
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Valki, God of Lies", 1);
|
||||
assertPermanentCount(playerA, "Servo", 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_SramsExpertise_CosimaGodOfTheVoyage() {
|
||||
addCard(Zone.HAND, playerA, "Sram's Expertise");
|
||||
addCard(Zone.HAND, playerA, "Cosima, God of the Voyage");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sram's Expertise");
|
||||
setChoice(playerA, true); // use free cast
|
||||
setChoice(playerA, "Cast The Omenkeel"); // can cast any side here
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "The Omenkeel", 1);
|
||||
assertPermanentCount(playerA, "Servo", 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Copy_AsSpell() {
|
||||
addCard(Zone.HAND, playerA, "Akoum Warrior", 1); // {5}{R}
|
||||
|
@ -1000,4 +1038,4 @@ public class ModalDoubleFacesCardsTest extends CardTestPlayerBase {
|
|||
execute();
|
||||
assertAllCommandsUsed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ public class CastSplitCardsFromOtherZonesTest extends CardTestPlayerBase {
|
|||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mindclaw Shaman");
|
||||
addTarget(playerA, playerB);
|
||||
setChoice(playerA, "Wear // Tear"); // select card
|
||||
setChoice(playerA, true); // confirm to cast
|
||||
setChoice(playerA, "Cast Tear"); // select tear side
|
||||
addTarget(playerA, "Sanguine Bond"); // target for tear
|
||||
|
@ -67,7 +66,6 @@ public class CastSplitCardsFromOtherZonesTest extends CardTestPlayerBase {
|
|||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mindclaw Shaman");
|
||||
addTarget(playerA, playerB);
|
||||
setChoice(playerA, "Wear // Tear"); // select card
|
||||
setChoice(playerA, true); // confirm to cast
|
||||
setChoice(playerA, "Cast Wear"); // select wear side
|
||||
addTarget(playerA, "Icy Manipulator"); // target for wear
|
||||
|
@ -100,7 +98,6 @@ public class CastSplitCardsFromOtherZonesTest extends CardTestPlayerBase {
|
|||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mindclaw Shaman");
|
||||
addTarget(playerA, playerB);
|
||||
setChoice(playerA, "Wear // Tear"); // select card
|
||||
setChoice(playerA, true); // confirm to cast
|
||||
setChoice(playerA, "Cast fused Wear // Tear"); // select fused
|
||||
addTarget(playerA, "Icy Manipulator"); // target for wear
|
||||
|
@ -137,7 +134,6 @@ public class CastSplitCardsFromOtherZonesTest extends CardTestPlayerBase {
|
|||
|
||||
attack(2, playerB, "Etali, Primal Storm");
|
||||
setChoice(playerB, true); // free cast
|
||||
setChoice(playerB, "Fire // Ice"); // card to cast
|
||||
setChoice(playerB, "Cast Fire"); // ability to cast
|
||||
addTargetAmount(playerB, "Silvercoat Lion", 2);
|
||||
|
||||
|
|
|
@ -4364,19 +4364,17 @@ public class TestPlayer implements Player {
|
|||
@Override
|
||||
public SpellAbility chooseAbilityForCast(Card card, Game game, boolean noMana) {
|
||||
assertAliasSupportInChoices(false);
|
||||
|
||||
MageObject object = game.getObject(card.getId()); // must be object to find real abilities (example: commander)
|
||||
Map<UUID, ActivatedAbility> useable = PlayerImpl.getCastableSpellAbilities(game, this.getId(), object, game.getState().getZone(object.getId()), noMana);
|
||||
String allInfo = useable.values().stream().map(Object::toString).collect(Collectors.joining("\n"));
|
||||
Map<UUID, SpellAbility> useable = PlayerImpl.getCastableSpellAbilities(game, this.getId(), object, game.getState().getZone(object.getId()), noMana);
|
||||
if (useable.size() == 1) {
|
||||
return (SpellAbility) useable.values().iterator().next();
|
||||
return useable.values().iterator().next();
|
||||
}
|
||||
|
||||
if (!choices.isEmpty()) {
|
||||
for (ActivatedAbility ability : useable.values()) {
|
||||
for (SpellAbility ability : useable.values()) {
|
||||
if (ability.toString().startsWith(choices.get(0))) {
|
||||
choices.remove(0);
|
||||
return (SpellAbility) ability;
|
||||
return ability;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4384,6 +4382,7 @@ public class TestPlayer implements Player {
|
|||
//Assert.fail("Wrong choice");
|
||||
}
|
||||
|
||||
String allInfo = useable.values().stream().map(Object::toString).collect(Collectors.joining("\n"));
|
||||
this.chooseStrictModeFailed("choice", game, getInfo(card) + " - can't select ability to cast.\n" + "Card's abilities:\n" + allInfo);
|
||||
return computerPlayer.chooseAbilityForCast(card, game, noMana);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import mage.abilities.costs.VariableCost;
|
|||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.VariableManaCost;
|
||||
import mage.abilities.keyword.FlashAbility;
|
||||
import mage.cards.AdventureCardSpell;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.constants.*;
|
||||
|
@ -69,7 +70,7 @@ public class SpellAbility extends ActivatedAbilityImpl {
|
|||
// forced to cast (can be part id or main id)
|
||||
Set<UUID> idsToCheck = new HashSet<>();
|
||||
idsToCheck.add(object.getId());
|
||||
if (object instanceof Card) {
|
||||
if (object instanceof Card && !(object instanceof AdventureCardSpell)) {
|
||||
idsToCheck.add(((Card) object).getMainCard().getId());
|
||||
}
|
||||
for (UUID idToCheck : idsToCheck) {
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package mage.abilities.effects.common.cost;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
* @author fireshoes - Original Code
|
||||
* @author JRHerlehy - Implement as seperate class
|
||||
* <p>
|
||||
* Allows player to choose to cast as card from hand without paying its mana
|
||||
* cost.
|
||||
* </p>
|
||||
*/
|
||||
public class CastFromHandForFreeEffect extends OneShotEffect {
|
||||
|
||||
private final FilterCard filter;
|
||||
|
||||
public CastFromHandForFreeEffect(FilterCard filter) {
|
||||
super(Outcome.PlayForFree);
|
||||
this.filter = filter;
|
||||
this.staticText = "you may cast " + filter.getMessage() + " from your hand without paying its mana cost";
|
||||
}
|
||||
|
||||
public CastFromHandForFreeEffect(final CastFromHandForFreeEffect effect) {
|
||||
super(effect);
|
||||
this.filter = effect.filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
return CardUtil.castSpellWithAttributesForFree(controller, source, game, new CardsImpl(controller.getHand()), filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CastFromHandForFreeEffect copy() {
|
||||
return new CastFromHandForFreeEffect(this);
|
||||
}
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
package mage.abilities.effects.common.cost;
|
||||
|
||||
import mage.ApprovingObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterNonlandCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
import mage.util.CardUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* @author fireshoes - Original Code
|
||||
* @author JRHerlehy - Implement as seperate class
|
||||
* <p>
|
||||
* Allows player to choose to cast as card from hand without paying its mana
|
||||
* cost.
|
||||
* </p>
|
||||
* TODO: this doesn't work correctly with MDFCs or Adventures (see https://github.com/magefree/mage/issues/7742)
|
||||
*/
|
||||
public class CastWithoutPayingManaCostEffect extends OneShotEffect {
|
||||
|
||||
private final DynamicValue manaCost;
|
||||
private final FilterCard filter;
|
||||
private static final FilterCard defaultFilter
|
||||
= new FilterNonlandCard("card with mana value %mv or less from your hand");
|
||||
|
||||
/**
|
||||
* @param maxCost Maximum converted mana cost for this effect to apply to
|
||||
*/
|
||||
public CastWithoutPayingManaCostEffect(int maxCost) {
|
||||
this(StaticValue.get(maxCost));
|
||||
}
|
||||
|
||||
public CastWithoutPayingManaCostEffect(DynamicValue maxCost) {
|
||||
this(maxCost, defaultFilter);
|
||||
}
|
||||
|
||||
public CastWithoutPayingManaCostEffect(DynamicValue maxCost, FilterCard filter) {
|
||||
super(Outcome.PlayForFree);
|
||||
this.manaCost = maxCost;
|
||||
this.filter = filter;
|
||||
this.staticText = "you may cast a spell with mana value "
|
||||
+ maxCost + " or less from your hand without paying its mana cost";
|
||||
}
|
||||
|
||||
public CastWithoutPayingManaCostEffect(final CastWithoutPayingManaCostEffect effect) {
|
||||
super(effect);
|
||||
this.manaCost = effect.manaCost;
|
||||
this.filter = effect.filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
int cmc = manaCost.calculate(game, source, this);
|
||||
FilterCard filter = this.filter.copy();
|
||||
filter.setMessage(filter.getMessage().replace("%mv", "" + cmc));
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, cmc + 1));
|
||||
Target target = new TargetCardInHand(filter);
|
||||
if (!target.canChoose(
|
||||
source.getSourceId(), controller.getId(), game
|
||||
) || !controller.chooseUse(
|
||||
Outcome.PlayForFree,
|
||||
"Cast " + CardUtil.addArticle(filter.getMessage())
|
||||
+ " without paying its mana cost?", source, game
|
||||
)) {
|
||||
return true;
|
||||
}
|
||||
Card cardToCast = null;
|
||||
boolean cancel = false;
|
||||
while (controller.canRespond()
|
||||
&& !cancel) {
|
||||
if (controller.chooseTarget(Outcome.PlayForFree, target, source, game)) {
|
||||
cardToCast = game.getCard(target.getFirstTarget());
|
||||
if (cardToCast != null) {
|
||||
if (cardToCast.getSpellAbility() == null) {
|
||||
Logger.getLogger(CastWithoutPayingManaCostEffect.class).fatal("Card: "
|
||||
+ cardToCast.getName() + " is no land and has no spell ability!");
|
||||
cancel = true;
|
||||
}
|
||||
if (cardToCast.getSpellAbility().canChooseTarget(game, controller.getId())) {
|
||||
cancel = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cancel = true;
|
||||
}
|
||||
}
|
||||
if (cardToCast != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + cardToCast.getId(), Boolean.TRUE);
|
||||
controller.cast(controller.chooseAbilityForCast(cardToCast, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + cardToCast.getId(), null);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CastWithoutPayingManaCostEffect copy() {
|
||||
return new CastWithoutPayingManaCostEffect(this);
|
||||
}
|
||||
}
|
|
@ -6,8 +6,7 @@ import mage.abilities.effects.AsThoughEffectImpl;
|
|||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.ModalDoubleFacesCardHalf;
|
||||
import mage.cards.SplitCardHalf;
|
||||
import mage.cards.SubCard;
|
||||
import mage.constants.AsThoughEffectType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
|
@ -156,12 +155,8 @@ class AftermathExileAsResolvesFromGraveyard extends ReplacementEffectImpl {
|
|||
// wants to do that in the future.
|
||||
UUID sourceId = source.getSourceId();
|
||||
Card sourceCard = game.getCard(source.getSourceId());
|
||||
if (sourceCard instanceof SplitCardHalf) {
|
||||
sourceCard = ((SplitCardHalf) sourceCard).getParentCard();
|
||||
sourceId = sourceCard.getId();
|
||||
}
|
||||
if (sourceCard instanceof ModalDoubleFacesCardHalf) {
|
||||
sourceCard = ((ModalDoubleFacesCardHalf) sourceCard).getParentCard();
|
||||
if (sourceCard instanceof SubCard) {
|
||||
sourceCard = ((SubCard<?>) sourceCard).getParentCard();
|
||||
sourceId = sourceCard.getId();
|
||||
}
|
||||
|
||||
|
@ -178,11 +173,8 @@ class AftermathExileAsResolvesFromGraveyard extends ReplacementEffectImpl {
|
|||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
Card sourceCard = game.getCard(source.getSourceId());
|
||||
if (sourceCard instanceof SplitCardHalf) {
|
||||
sourceCard = ((SplitCardHalf) sourceCard).getParentCard();
|
||||
}
|
||||
if (sourceCard instanceof ModalDoubleFacesCardHalf) {
|
||||
sourceCard = ((ModalDoubleFacesCardHalf) sourceCard).getParentCard();
|
||||
if (sourceCard instanceof SubCard) {
|
||||
sourceCard = ((SubCard<?>) sourceCard).getParentCard();
|
||||
}
|
||||
if (sourceCard != null) {
|
||||
Player player = game.getPlayer(sourceCard.getOwnerId());
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
package mage.abilities.keyword;
|
||||
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.*;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
* Cascade A keyword ability that may let a player cast a random extra spell for
|
||||
|
@ -152,45 +152,12 @@ class CascadeEffect extends OneShotEffect {
|
|||
}
|
||||
|
||||
// You may cast that spell without paying its mana cost if its converted mana cost is less than this spell's converted mana cost.
|
||||
List<Card> partsToCast = new ArrayList<>();
|
||||
if (cardToCast != null) {
|
||||
if (cardToCast instanceof SplitCard) {
|
||||
partsToCast.add(((SplitCard) cardToCast).getLeftHalfCard());
|
||||
partsToCast.add(((SplitCard) cardToCast).getRightHalfCard());
|
||||
partsToCast.add(cardToCast);
|
||||
} else if (cardToCast instanceof AdventureCard) {
|
||||
partsToCast.add(((AdventureCard) cardToCast).getSpellCard());
|
||||
partsToCast.add(cardToCast);
|
||||
} else if (cardToCast instanceof ModalDoubleFacesCard) {
|
||||
partsToCast.add(((ModalDoubleFacesCard) cardToCast).getLeftHalfCard());
|
||||
partsToCast.add(((ModalDoubleFacesCard) cardToCast).getRightHalfCard());
|
||||
} else {
|
||||
partsToCast.add(cardToCast);
|
||||
}
|
||||
// remove too big cmc
|
||||
partsToCast.removeIf(card -> card.getManaValue() >= sourceCost);
|
||||
// remove non spells
|
||||
partsToCast.removeIf(card -> card.getSpellAbility() == null);
|
||||
}
|
||||
|
||||
String partsInfo = partsToCast.stream()
|
||||
.map(MageObject::getIdName)
|
||||
.collect(Collectors.joining(" or "));
|
||||
if (cardToCast != null
|
||||
&& partsToCast.size() > 0
|
||||
&& controller.chooseUse(outcome, "Cast spell without paying its mana cost (" + partsInfo + ")?", source, game)) {
|
||||
try {
|
||||
// enable free cast for all compatible parts
|
||||
partsToCast.forEach(card -> game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE));
|
||||
controller.cast(controller.chooseAbilityForCast(cardToCast, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
} finally {
|
||||
partsToCast.forEach(card -> game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null));
|
||||
}
|
||||
}
|
||||
FilterCard filter = new FilterCard();
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, sourceCost + 1));
|
||||
CardUtil.castSpellWithAttributesForFree(controller, source, game, new CardsImpl(cardToCast), filter);
|
||||
|
||||
// Then put all cards exiled this way that weren't cast on the bottom of your library in a random order.
|
||||
cardsToExile.removeIf(uuid -> game.getState().getZone(uuid) != Zone.EXILED);
|
||||
cardsToExile.retainZone(Zone.EXILED, game);
|
||||
return controller.putCardsOnBottomOfLibrary(cardsToExile, game, source, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import mage.abilities.AbilitiesImpl;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
|
@ -13,7 +14,7 @@ import java.util.List;
|
|||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
* @author phulin
|
||||
*/
|
||||
public abstract class AdventureCard extends CardImpl {
|
||||
|
||||
|
@ -90,13 +91,11 @@ public abstract class AdventureCard extends CardImpl {
|
|||
|
||||
@Override
|
||||
public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId) {
|
||||
switch (ability.getSpellAbilityType()) {
|
||||
case ADVENTURE_SPELL:
|
||||
return this.getSpellCard().cast(game, fromZone, ability, controllerId);
|
||||
default:
|
||||
this.getSpellCard().getSpellAbility().setControllerId(controllerId);
|
||||
return super.cast(game, fromZone, ability, controllerId);
|
||||
if (ability.getSpellAbilityType() == SpellAbilityType.ADVENTURE_SPELL) {
|
||||
return this.getSpellCard().cast(game, fromZone, ability, controllerId);
|
||||
}
|
||||
this.getSpellCard().getSpellAbility().setControllerId(controllerId);
|
||||
return super.cast(game, fromZone, ability, controllerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,15 +1,10 @@
|
|||
package mage.cards;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author phulin
|
||||
*/
|
||||
public interface AdventureCardSpell extends Card {
|
||||
public interface AdventureCardSpell extends SubCard<AdventureCard> {
|
||||
|
||||
@Override
|
||||
AdventureCardSpell copy();
|
||||
|
||||
void setParentCard(AdventureCard card);
|
||||
|
||||
AdventureCard getParentCard();
|
||||
}
|
||||
|
|
11
Mage/src/main/java/mage/cards/CardWithHalves.java
Normal file
11
Mage/src/main/java/mage/cards/CardWithHalves.java
Normal file
|
@ -0,0 +1,11 @@
|
|||
package mage.cards;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public interface CardWithHalves extends Card {
|
||||
|
||||
Card getLeftHalfCard();
|
||||
|
||||
Card getRightHalfCard();
|
||||
}
|
|
@ -45,4 +45,6 @@ public interface Cards extends Set<UUID>, Serializable {
|
|||
Cards copy();
|
||||
|
||||
void retainZone(Zone zone, Game game);
|
||||
|
||||
void removeZone(Zone zone, Game game);
|
||||
}
|
||||
|
|
|
@ -210,4 +210,9 @@ public class CardsImpl extends LinkedHashSet<UUID> implements Cards, Serializabl
|
|||
public void retainZone(Zone zone, Game game) {
|
||||
removeIf(uuid -> game.getState().getZone(uuid) != zone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeZone(Zone zone, Game game) {
|
||||
removeIf(uuid -> game.getState().getZone(uuid) == zone);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import java.util.UUID;
|
|||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public abstract class ModalDoubleFacesCard extends CardImpl {
|
||||
public abstract class ModalDoubleFacesCard extends CardImpl implements CardWithHalves {
|
||||
|
||||
protected Card leftHalfCard; // main card in all zone
|
||||
protected Card rightHalfCard; // second side card, can be only in stack and battlefield zones
|
||||
|
|
|
@ -5,15 +5,11 @@ import mage.MageInt;
|
|||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public interface ModalDoubleFacesCardHalf extends Card {
|
||||
public interface ModalDoubleFacesCardHalf extends SubCard<ModalDoubleFacesCard> {
|
||||
|
||||
@Override
|
||||
ModalDoubleFacesCardHalf copy();
|
||||
|
||||
void setParentCard(ModalDoubleFacesCard card);
|
||||
|
||||
ModalDoubleFacesCard getParentCard();
|
||||
|
||||
void setPT(int power, int toughness);
|
||||
|
||||
void setPT(MageInt power, MageInt toughness);
|
||||
|
|
|
@ -18,7 +18,7 @@ import java.util.UUID;
|
|||
/**
|
||||
* @author LevelX2
|
||||
*/
|
||||
public abstract class SplitCard extends CardImpl {
|
||||
public abstract class SplitCard extends CardImpl implements CardWithHalves {
|
||||
|
||||
protected Card leftHalfCard;
|
||||
protected Card rightHalfCard;
|
||||
|
|
|
@ -3,12 +3,8 @@ package mage.cards;
|
|||
/**
|
||||
* @author LevelX2
|
||||
*/
|
||||
public interface SplitCardHalf extends Card {
|
||||
public interface SplitCardHalf extends SubCard<SplitCard> {
|
||||
|
||||
@Override
|
||||
SplitCardHalf copy();
|
||||
|
||||
void setParentCard(SplitCard card);
|
||||
|
||||
SplitCard getParentCard();
|
||||
}
|
||||
|
|
8
Mage/src/main/java/mage/cards/SubCard.java
Normal file
8
Mage/src/main/java/mage/cards/SubCard.java
Normal file
|
@ -0,0 +1,8 @@
|
|||
package mage.cards;
|
||||
|
||||
public interface SubCard<T extends Card> extends Card {
|
||||
|
||||
void setParentCard(T card);
|
||||
|
||||
T getParentCard();
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package mage.filter.predicate.mageobject;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.cards.ModalDoubleFacesCard;
|
||||
import mage.cards.CardWithHalves;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.filter.predicate.Predicate;
|
||||
|
@ -34,13 +34,9 @@ public class NamePredicate implements Predicate<MageObject> {
|
|||
// If a player names a card, the player may name either half of a split card, but not both.
|
||||
// A split card has the chosen name if one of its two names matches the chosen name.
|
||||
// Same for modal double faces cards
|
||||
if (input instanceof SplitCard) {
|
||||
return CardUtil.haveSameNames(name, ((SplitCard) input).getLeftHalfCard().getName(), this.ignoreMtgRuleForEmptyNames) ||
|
||||
CardUtil.haveSameNames(name, ((SplitCard) input).getRightHalfCard().getName(), this.ignoreMtgRuleForEmptyNames) ||
|
||||
CardUtil.haveSameNames(name, input.getName(), this.ignoreMtgRuleForEmptyNames);
|
||||
} else if (input instanceof ModalDoubleFacesCard) {
|
||||
return CardUtil.haveSameNames(name, ((ModalDoubleFacesCard) input).getLeftHalfCard().getName(), this.ignoreMtgRuleForEmptyNames) ||
|
||||
CardUtil.haveSameNames(name, ((ModalDoubleFacesCard) input).getRightHalfCard().getName(), this.ignoreMtgRuleForEmptyNames) ||
|
||||
if (input instanceof CardWithHalves) {
|
||||
return CardUtil.haveSameNames(name, ((CardWithHalves) input).getLeftHalfCard().getName(), this.ignoreMtgRuleForEmptyNames) ||
|
||||
CardUtil.haveSameNames(name, ((CardWithHalves) input).getRightHalfCard().getName(), this.ignoreMtgRuleForEmptyNames) ||
|
||||
CardUtil.haveSameNames(name, input.getName(), this.ignoreMtgRuleForEmptyNames);
|
||||
} else if (input instanceof Spell && ((Spell) input).getSpellAbility().getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED) {
|
||||
SplitCard card = (SplitCard) ((Spell) input).getCard();
|
||||
|
|
|
@ -1,48 +1,51 @@
|
|||
package mage.game.command.emblems;
|
||||
|
||||
import mage.ApprovingObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.choices.Choice;
|
||||
import mage.choices.ChoiceImpl;
|
||||
import mage.constants.*;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterOwnedCard;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.game.Game;
|
||||
import mage.game.command.Emblem;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author weirddan455
|
||||
*/
|
||||
public class KayaTheInexorableEmblem extends Emblem {
|
||||
public class KayaTheInexorableEmblem extends Emblem {
|
||||
|
||||
// −7: You get an emblem with "At the beginning of your upkeep, you may cast a legendary spell from your hand, from your graveyard, or from among cards you own in exile without paying its mana cost."
|
||||
public KayaTheInexorableEmblem() {
|
||||
|
||||
this.setName("Emblem Kaya");
|
||||
this.setExpansionSetCodeForImage("KHM");
|
||||
this.getAbilities().add(new BeginningOfUpkeepTriggeredAbility(Zone.COMMAND, new KayaTheInexorableEmblemEffect(), TargetController.YOU, true, false));
|
||||
this.getAbilities().add(new BeginningOfUpkeepTriggeredAbility(
|
||||
Zone.COMMAND, new KayaTheInexorableEmblemEffect(),
|
||||
TargetController.YOU, true, false
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
class KayaTheInexorableEmblemEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterOwnedCard filter = new FilterOwnedCard();
|
||||
private static final FilterCard filter = new FilterOwnedCard();
|
||||
private static final FilterCard filter2 = new FilterCard();
|
||||
private static final Set<String> choices = new LinkedHashSet<>();
|
||||
|
||||
static {
|
||||
filter.add(SuperType.LEGENDARY.getPredicate());
|
||||
filter.add(Predicates.not(CardType.LAND.getPredicate()));
|
||||
filter2.add(SuperType.LEGENDARY.getPredicate());
|
||||
choices.add("Hand");
|
||||
choices.add("Graveyard");
|
||||
choices.add("Exile");
|
||||
|
@ -50,7 +53,8 @@ class KayaTheInexorableEmblemEffect extends OneShotEffect {
|
|||
|
||||
public KayaTheInexorableEmblemEffect() {
|
||||
super(Outcome.PlayForFree);
|
||||
this.staticText = "cast a legendary spell from your hand, from your graveyard, or from among cards you own in exile without paying its mana cost";
|
||||
this.staticText = "cast a legendary spell from your hand, from your graveyard, " +
|
||||
"or from among cards you own in exile without paying its mana cost";
|
||||
}
|
||||
|
||||
private KayaTheInexorableEmblemEffect(final KayaTheInexorableEmblemEffect effect) {
|
||||
|
@ -65,40 +69,26 @@ class KayaTheInexorableEmblemEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
Choice zoneChoice = new ChoiceImpl(true);
|
||||
zoneChoice.setMessage("Cast a legendary spell from hand, graveyard, or exile");
|
||||
zoneChoice.setChoices(choices);
|
||||
zoneChoice.clearChoice();
|
||||
if (player.choose(Outcome.PlayForFree, zoneChoice, game)) {
|
||||
TargetCard target = null;
|
||||
switch (zoneChoice.getChoice()) {
|
||||
case "Hand":
|
||||
target = new TargetCardInHand(0, 1, filter);
|
||||
target.setTargetName("legendary spell from your hand");
|
||||
break;
|
||||
case "Graveyard":
|
||||
target = new TargetCardInYourGraveyard(0, 1, filter, true);
|
||||
target.setTargetName("legendary spell from your graveyard");
|
||||
break;
|
||||
case "Exile":
|
||||
target = new TargetCardInExile(0, 1, filter, null, true);
|
||||
target.setNotTarget(true);
|
||||
target.setTargetName("legendary spell you own in exile");
|
||||
break;
|
||||
}
|
||||
if (target != null && player.chooseTarget(Outcome.PlayForFree, target, source, game)) {
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card != null) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
boolean cardWasCast = player.cast(player.chooseAbilityForCast(card, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
return cardWasCast;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
Choice zoneChoice = new ChoiceImpl(true);
|
||||
zoneChoice.setMessage("Cast a legendary spell from hand, graveyard, or exile");
|
||||
zoneChoice.setChoices(choices);
|
||||
zoneChoice.clearChoice();
|
||||
player.choose(Outcome.PlayForFree, zoneChoice, game);
|
||||
Cards cards = new CardsImpl();
|
||||
switch (zoneChoice.getChoice()) {
|
||||
case "Hand":
|
||||
cards.addAll(player.getHand());
|
||||
break;
|
||||
case "Graveyard":
|
||||
cards.addAll(player.getGraveyard());
|
||||
break;
|
||||
case "Exile":
|
||||
cards.addAll(game.getExile().getCards(filter, game));
|
||||
break;
|
||||
}
|
||||
return CardUtil.castSpellWithAttributesForFree(player, source, game, cards, filter2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1571,72 +1571,75 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
* @param noMana
|
||||
* @return
|
||||
*/
|
||||
public static LinkedHashMap<UUID, ActivatedAbility> getCastableSpellAbilities(Game game, UUID playerId, MageObject object, Zone zone, boolean noMana) {
|
||||
public static LinkedHashMap<UUID, SpellAbility> getCastableSpellAbilities(Game game, UUID playerId, MageObject object, Zone zone, boolean noMana) {
|
||||
// it uses simple check from spellCanBeActivatedRegularlyNow
|
||||
// reason: no approved info here (e.g. forced to choose spell ability from cast card)
|
||||
LinkedHashMap<UUID, ActivatedAbility> useable = new LinkedHashMap<>();
|
||||
LinkedHashMap<UUID, SpellAbility> useable = new LinkedHashMap<>();
|
||||
Abilities<Ability> allAbilities;
|
||||
if (object instanceof Card) {
|
||||
allAbilities = ((Card) object).getAbilities(game);
|
||||
} else {
|
||||
allAbilities = object.getAbilities();
|
||||
}
|
||||
|
||||
for (Ability ability : allAbilities) {
|
||||
if (ability instanceof SpellAbility) {
|
||||
SpellAbility spellAbility = (SpellAbility) ability;
|
||||
|
||||
switch (spellAbility.getSpellAbilityType()) {
|
||||
case BASE_ALTERNATE:
|
||||
// rules:
|
||||
// If you cast a spell “without paying its mana cost,” you can’t choose to cast it for
|
||||
// any alternative costs. You can, however, pay additional costs, such as kicker costs.
|
||||
// If the card has any mandatory additional costs, those must be paid to cast the spell.
|
||||
// (2021-02-05)
|
||||
if (!noMana) {
|
||||
if (spellAbility.spellCanBeActivatedRegularlyNow(playerId, game)) {
|
||||
useable.put(spellAbility.getId(), spellAbility); // example: Chandra, Torch of Defiance +1 loyal ability
|
||||
}
|
||||
return useable;
|
||||
for (SpellAbility spellAbility : allAbilities
|
||||
.stream()
|
||||
.filter(SpellAbility.class::isInstance)
|
||||
.map(SpellAbility.class::cast)
|
||||
.collect(Collectors.toList())) {
|
||||
switch (spellAbility.getSpellAbilityType()) {
|
||||
case BASE_ALTERNATE:
|
||||
// rules:
|
||||
// If you cast a spell “without paying its mana cost,” you can’t choose to cast it for
|
||||
// any alternative costs. You can, however, pay additional costs, such as kicker costs.
|
||||
// If the card has any mandatory additional costs, those must be paid to cast the spell.
|
||||
// (2021-02-05)
|
||||
if (!noMana) {
|
||||
if (spellAbility.spellCanBeActivatedRegularlyNow(playerId, game)) {
|
||||
useable.put(spellAbility.getId(), spellAbility); // example: Chandra, Torch of Defiance +1 loyal ability
|
||||
}
|
||||
break;
|
||||
case SPLIT_FUSED:
|
||||
// rules:
|
||||
// If you cast a split card with fuse from your hand without paying its mana cost,
|
||||
// you can choose to use its fuse ability and cast both halves without paying their mana costs.
|
||||
if (zone == Zone.HAND) {
|
||||
if (spellAbility.canChooseTarget(game, playerId)) {
|
||||
useable.put(spellAbility.getId(), spellAbility);
|
||||
}
|
||||
}
|
||||
case SPLIT:
|
||||
if (((SplitCard) object).getLeftHalfCard().getSpellAbility().canChooseTarget(game, playerId)) {
|
||||
useable.put(((SplitCard) object).getLeftHalfCard().getSpellAbility().getId(),
|
||||
((SplitCard) object).getLeftHalfCard().getSpellAbility());
|
||||
return useable;
|
||||
}
|
||||
break;
|
||||
case SPLIT_FUSED:
|
||||
// rules:
|
||||
// If you cast a split card with fuse from your hand without paying its mana cost,
|
||||
// you can choose to use its fuse ability and cast both halves without paying their mana costs.
|
||||
if (zone == Zone.HAND) {
|
||||
if (spellAbility.canChooseTarget(game, playerId)) {
|
||||
useable.put(spellAbility.getId(), spellAbility);
|
||||
}
|
||||
}
|
||||
case SPLIT:
|
||||
if (((SplitCard) object).getLeftHalfCard().getSpellAbility().canChooseTarget(game, playerId)) {
|
||||
useable.put(
|
||||
((SplitCard) object).getLeftHalfCard().getSpellAbility().getId(),
|
||||
((SplitCard) object).getLeftHalfCard().getSpellAbility()
|
||||
);
|
||||
}
|
||||
if (((SplitCard) object).getRightHalfCard().getSpellAbility().canChooseTarget(game, playerId)) {
|
||||
useable.put(
|
||||
((SplitCard) object).getRightHalfCard().getSpellAbility().getId(),
|
||||
((SplitCard) object).getRightHalfCard().getSpellAbility()
|
||||
);
|
||||
}
|
||||
return useable;
|
||||
case SPLIT_AFTERMATH:
|
||||
if (zone == Zone.GRAVEYARD) {
|
||||
if (((SplitCard) object).getRightHalfCard().getSpellAbility().canChooseTarget(game, playerId)) {
|
||||
useable.put(((SplitCard) object).getRightHalfCard().getSpellAbility().getId(),
|
||||
((SplitCard) object).getRightHalfCard().getSpellAbility());
|
||||
}
|
||||
return useable;
|
||||
case SPLIT_AFTERMATH:
|
||||
if (zone == Zone.GRAVEYARD) {
|
||||
if (((SplitCard) object).getRightHalfCard().getSpellAbility().canChooseTarget(game, playerId)) {
|
||||
useable.put(((SplitCard) object).getRightHalfCard().getSpellAbility().getId(),
|
||||
((SplitCard) object).getRightHalfCard().getSpellAbility());
|
||||
}
|
||||
} else {
|
||||
if (((SplitCard) object).getLeftHalfCard().getSpellAbility().canChooseTarget(game, playerId)) {
|
||||
useable.put(((SplitCard) object).getLeftHalfCard().getSpellAbility().getId(),
|
||||
((SplitCard) object).getLeftHalfCard().getSpellAbility());
|
||||
}
|
||||
} else {
|
||||
if (((SplitCard) object).getLeftHalfCard().getSpellAbility().canChooseTarget(game, playerId)) {
|
||||
useable.put(((SplitCard) object).getLeftHalfCard().getSpellAbility().getId(),
|
||||
((SplitCard) object).getLeftHalfCard().getSpellAbility());
|
||||
}
|
||||
return useable;
|
||||
default:
|
||||
if (spellAbility.spellCanBeActivatedRegularlyNow(playerId, game)) {
|
||||
useable.put(spellAbility.getId(), spellAbility);
|
||||
}
|
||||
}
|
||||
}
|
||||
return useable;
|
||||
default:
|
||||
if (spellAbility.spellCanBeActivatedRegularlyNow(playerId, game)) {
|
||||
useable.put(spellAbility.getId(), spellAbility);
|
||||
}
|
||||
}
|
||||
}
|
||||
return useable;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package mage.util;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageObject;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Abilities;
|
||||
|
@ -23,6 +24,7 @@ import mage.cards.*;
|
|||
import mage.constants.*;
|
||||
import mage.counters.Counter;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.mageobject.NamePredicate;
|
||||
import mage.game.CardState;
|
||||
import mage.game.Game;
|
||||
|
@ -36,6 +38,7 @@ import mage.game.permanent.token.Token;
|
|||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.functions.CopyTokenFunction;
|
||||
import org.apache.log4j.Logger;
|
||||
|
@ -1196,6 +1199,126 @@ public final class CardUtil {
|
|||
}
|
||||
}
|
||||
|
||||
public interface SpellCastTracker {
|
||||
|
||||
boolean checkCard(Card card, Game game);
|
||||
|
||||
void addCard(Card card, Ability source, Game game);
|
||||
}
|
||||
|
||||
private static List<Card> getCastableComponents(Card cardToCast, FilterCard filter, UUID sourceId, UUID playerId, Game game, SpellCastTracker spellCastTracker) {
|
||||
List<Card> cards = new ArrayList<>();
|
||||
if (cardToCast instanceof CardWithHalves) {
|
||||
cards.add(((CardWithHalves) cardToCast).getLeftHalfCard());
|
||||
cards.add(((CardWithHalves) cardToCast).getRightHalfCard());
|
||||
} else if (cardToCast instanceof AdventureCard) {
|
||||
cards.add(cardToCast);
|
||||
cards.add(((AdventureCard) cardToCast).getSpellCard());
|
||||
} else {
|
||||
cards.add(cardToCast);
|
||||
}
|
||||
cards.removeIf(Objects::isNull);
|
||||
cards.removeIf(card -> !filter.match(card, sourceId, playerId, game));
|
||||
if (spellCastTracker != null) {
|
||||
cards.removeIf(card -> spellCastTracker.checkCard(card, game));
|
||||
}
|
||||
return cards;
|
||||
}
|
||||
|
||||
private static final FilterCard defaultFilter = new FilterCard("card to cast");
|
||||
|
||||
public static boolean castSpellWithAttributesForFree(Player player, Ability source, Game game, Cards cards, FilterCard filter) {
|
||||
return castSpellWithAttributesForFree(player, source, game, cards, filter, null);
|
||||
}
|
||||
|
||||
public static boolean castSpellWithAttributesForFree(Player player, Ability source, Game game, Cards cards, FilterCard filter, SpellCastTracker spellCastTracker) {
|
||||
Map<UUID, List<Card>> cardMap = new HashMap<>();
|
||||
for (Card card : cards.getCards(game)) {
|
||||
List<Card> castableComponents = getCastableComponents(card, filter, source.getSourceId(), player.getId(), game, spellCastTracker);
|
||||
if (!castableComponents.isEmpty()) {
|
||||
cardMap.put(card.getId(), castableComponents);
|
||||
}
|
||||
}
|
||||
Card cardToCast;
|
||||
switch (cardMap.size()) {
|
||||
case 0:
|
||||
return false;
|
||||
case 1:
|
||||
cardToCast = cards.get(cardMap.keySet().stream().findFirst().orElse(null), game);
|
||||
break;
|
||||
default:
|
||||
Cards castableCards = new CardsImpl(cardMap.keySet());
|
||||
TargetCard target = new TargetCard(0, 1, Zone.ALL, defaultFilter);
|
||||
target.setNotTarget(true);
|
||||
player.choose(Outcome.PlayForFree, castableCards, target, game);
|
||||
cardToCast = castableCards.get(target.getFirstTarget(), game);
|
||||
}
|
||||
if (cardToCast == null) {
|
||||
return false;
|
||||
}
|
||||
List<Card> partsToCast = cardMap.get(cardToCast.getId());
|
||||
String partsInfo = partsToCast
|
||||
.stream()
|
||||
.map(MageObject::getIdName)
|
||||
.collect(Collectors.joining(" or "));
|
||||
if (cardToCast == null
|
||||
|| partsToCast.size() < 1
|
||||
|| !player.chooseUse(
|
||||
Outcome.PlayForFree, "Cast spell without paying its mana cost (" + partsInfo + ")?", source, game
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
partsToCast.forEach(card -> game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE));
|
||||
boolean result = player.cast(
|
||||
player.chooseAbilityForCast(cardToCast, game, true),
|
||||
game, true, new ApprovingObject(source, game)
|
||||
);
|
||||
partsToCast.forEach(card -> game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null));
|
||||
if (result && spellCastTracker != null) {
|
||||
spellCastTracker.addCard(cardToCast, source, game);
|
||||
}
|
||||
if (player.isComputer() && !result) {
|
||||
cards.remove(cardToCast);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean checkForPlayable(Cards cards, FilterCard filter, UUID sourceId, UUID playerId, Game game, SpellCastTracker spellCastTracker) {
|
||||
return cards
|
||||
.getCards(game)
|
||||
.stream()
|
||||
.anyMatch(card -> !getCastableComponents(card, filter, sourceId, playerId, game, spellCastTracker).isEmpty());
|
||||
}
|
||||
|
||||
public static void castMultipleWithAttributeForFree(Player player, Ability source, Game game, Cards cards, FilterCard filter) {
|
||||
castMultipleWithAttributeForFree(player, source, game, cards, filter, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static void castMultipleWithAttributeForFree(Player player, Ability source, Game game, Cards cards, FilterCard filter, int maxSpells) {
|
||||
castMultipleWithAttributeForFree(player, source, game, cards, filter, maxSpells, null);
|
||||
}
|
||||
|
||||
public static void castMultipleWithAttributeForFree(Player player, Ability source, Game game, Cards cards, FilterCard filter, int maxSpells, SpellCastTracker spellCastTracker) {
|
||||
if (maxSpells == 1) {
|
||||
CardUtil.castSpellWithAttributesForFree(player, source, game, cards, filter);
|
||||
return;
|
||||
}
|
||||
int spellsCast = 0;
|
||||
cards.removeZone(Zone.STACK, game);
|
||||
while (player.canRespond() && spellsCast < maxSpells && !cards.isEmpty()) {
|
||||
if (CardUtil.castSpellWithAttributesForFree(player, source, game, cards, filter, spellCastTracker)) {
|
||||
spellsCast++;
|
||||
cards.removeZone(Zone.STACK, game);
|
||||
} else if (!checkForPlayable(
|
||||
cards, filter, source.getSourceId(), player.getId(), game, spellCastTracker
|
||||
) || !player.chooseUse(
|
||||
Outcome.PlayForFree, "Continue casting spells?", source, game
|
||||
)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pay life in effects
|
||||
*
|
||||
|
|
|
@ -13,6 +13,7 @@ import mage.game.stack.Spell;
|
|||
import mage.watchers.Watcher;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
|
@ -59,6 +60,10 @@ public class SpellsCastWatcher extends Watcher {
|
|||
spellsCastFromGraveyard.clear();
|
||||
}
|
||||
|
||||
public Stream<Spell> getAllSpellsCastThisTurn() {
|
||||
return spellsCast.values().stream().flatMap(Collection::stream);
|
||||
}
|
||||
|
||||
public List<Spell> getSpellsCastThisTurn(UUID playerId) {
|
||||
return spellsCast.computeIfAbsent(playerId, x -> new ArrayList<>());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue