From a544b3d0bc3bb0052394f30f92d93399ba341d77 Mon Sep 17 00:00:00 2001 From: Steven Knipe Date: Thu, 12 Sep 2024 18:53:31 -0700 Subject: [PATCH] Portent of Calamity --- .../src/mage/cards/p/PortentOfCalamity.java | 133 ++++++++++++++++++ Mage.Sets/src/mage/sets/Bloomburrow.java | 1 + 2 files changed, 134 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/p/PortentOfCalamity.java diff --git a/Mage.Sets/src/mage/cards/p/PortentOfCalamity.java b/Mage.Sets/src/mage/cards/p/PortentOfCalamity.java new file mode 100644 index 00000000000..c5c9b6eb05a --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PortentOfCalamity.java @@ -0,0 +1,133 @@ +package mage.cards.p; + +import mage.abilities.Ability; +import mage.abilities.assignment.common.CardTypeAssignment; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; +import mage.cards.*; +import mage.constants.CardType; +import mage.constants.CastManaAdjustment; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetCardInLibrary; +import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; + +import java.util.Arrays; +import java.util.UUID; + +/** + * @author notgreat + */ +public final class PortentOfCalamity extends CardImpl { + + public PortentOfCalamity(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{U}"); + + + // Reveal the top X cards of your library. For each card type, you may exile a card of that type from among them. Put the rest into your graveyard. You may cast a spell from among the exiled cards without paying its mana cost if you exiled four or more cards this way. Then put the rest of the exiled cards into your hand. + this.getSpellAbility().addEffect(new PortentOfCalamityEffect()); + } + + private PortentOfCalamity(final PortentOfCalamity card) { + super(card); + } + + @Override + public PortentOfCalamity copy() { + return new PortentOfCalamity(this); + } +} + +//Based on Atraxa, Grand Unifier +class PortentOfCalamityEffect extends OneShotEffect { + + PortentOfCalamityEffect() { + super(Outcome.Benefit); + staticText = "Reveal the top X cards of your library. For each card type, you may exile a card of that type from among them. " + + "Put the rest into your graveyard. You may cast a spell from among the exiled cards without paying its mana cost " + + "if you exiled four or more cards this way. Then put the rest of the exiled cards into your hand"; + } + + private PortentOfCalamityEffect(final PortentOfCalamityEffect effect) { + super(effect); + } + + @Override + public PortentOfCalamityEffect copy() { + return new PortentOfCalamityEffect(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, CardUtil.getSourceCostsTag(game, source, "X", 0))); + player.revealCards(source, cards, game); + + TargetCard target = new PortentOfCalamityTarget(); + player.choose(Outcome.DrawCard, cards, target, source, game); + Cards chosen = new CardsImpl(target.getTargets()); + player.moveCards(chosen, Zone.EXILED, source, game); + cards.retainZone(Zone.LIBRARY, game); + player.moveCards(cards, Zone.GRAVEYARD, source, game); + + if (chosen.size() >= 4){ + TargetCard freeCast = new TargetCard(0, 1, Zone.EXILED, StaticFilters.FILTER_CARD); + player.choose(Outcome.PlayForFree, chosen, freeCast, source, game); + Effect effect = new MayCastTargetCardEffect(CastManaAdjustment.WITHOUT_PAYING_MANA_COST); + effect.setTargetPointer(new FixedTarget(freeCast.getFirstTarget())); + effect.apply(game, source); + } + chosen.retainZone(Zone.EXILED, game); + player.moveCards(chosen, Zone.HAND, source, game); + return true; + } +} + +class PortentOfCalamityTarget extends TargetCardInLibrary { + + private static final FilterCard filter + = new FilterCard("a card of each card type"); + + private static final CardTypeAssignment cardTypeAssigner + = new CardTypeAssignment(Arrays.stream(CardType.values()).toArray(CardType[]::new)); + + PortentOfCalamityTarget() { + super(0, Integer.MAX_VALUE, filter); + } + + private PortentOfCalamityTarget(final PortentOfCalamityTarget target) { + super(target); + } + + @Override + public PortentOfCalamityTarget copy() { + return new PortentOfCalamityTarget(this); + } + + @Override + public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) { + if (!super.canTarget(playerId, id, source, game)) { + return false; + } + Card card = game.getCard(id); + if (card == null) { + return false; + } + if (this.getTargets().isEmpty()) { + return true; + } + Cards cards = new CardsImpl(this.getTargets()); + cards.add(card); + return cardTypeAssigner.getRoleCount(cards, game) >= cards.size(); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/Bloomburrow.java b/Mage.Sets/src/mage/sets/Bloomburrow.java index c3ebff10808..98980722b06 100644 --- a/Mage.Sets/src/mage/sets/Bloomburrow.java +++ b/Mage.Sets/src/mage/sets/Bloomburrow.java @@ -191,6 +191,7 @@ public final class Bloomburrow extends ExpansionSet { cards.add(new SetCardInfo("Plumecreed Mentor", 228, Rarity.UNCOMMON, mage.cards.p.PlumecreedMentor.class)); cards.add(new SetCardInfo("Polliwallop", 189, Rarity.COMMON, mage.cards.p.Polliwallop.class)); cards.add(new SetCardInfo("Pond Prophet", 229, Rarity.COMMON, mage.cards.p.PondProphet.class)); + cards.add(new SetCardInfo("Portent of Calamity", 66, Rarity.RARE, mage.cards.p.PortentOfCalamity.class)); cards.add(new SetCardInfo("Psychic Whorl", 105, Rarity.COMMON, mage.cards.p.PsychicWhorl.class)); cards.add(new SetCardInfo("Quaketusk Boar", 146, Rarity.UNCOMMON, mage.cards.q.QuaketuskBoar.class)); cards.add(new SetCardInfo("Rabbit Response", 26, Rarity.COMMON, mage.cards.r.RabbitResponse.class));