From c88a087c7e7ae0034f56c39d0f72ae1a4a8ac26e Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Wed, 22 Apr 2020 20:31:35 -0400 Subject: [PATCH] Implemented Pako, Arcane Retriever --- .../src/mage/cards/p/PakoArcaneRetriever.java | 124 ++++++++++++++++++ .../src/mage/sets/Commander2020Edition.java | 1 + .../main/java/mage/counters/CounterType.java | 1 + 3 files changed, 126 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/p/PakoArcaneRetriever.java diff --git a/Mage.Sets/src/mage/cards/p/PakoArcaneRetriever.java b/Mage.Sets/src/mage/cards/p/PakoArcaneRetriever.java new file mode 100644 index 0000000000..85a7e10407 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PakoArcaneRetriever.java @@ -0,0 +1,124 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.HasteAbility; +import mage.abilities.keyword.PartnerWithAbility; +import mage.cards.*; +import mage.constants.*; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.watchers.Watcher; + +import java.util.*; + +/** + * @author TheElk801 + */ +public final class PakoArcaneRetriever extends CardImpl { + + public PakoArcaneRetriever(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.ELEMENTAL); + this.subtype.add(SubType.HOUND); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Partner with Haldan, Avid Arcanist + this.addAbility(new PartnerWithAbility("Haldan, Avid Arcanist")); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Whenever Pako, Arcane Retriever attacks, exile the top card of each player's library and put a fetch counter on each of them. Put a +1/+1 counter on Pako for each noncreature card exiled this way. + this.addAbility(new AttacksTriggeredAbility(new PakoArcaneRetrieverEffect(), false)); + } + + private PakoArcaneRetriever(final PakoArcaneRetriever card) { + super(card); + } + + @Override + public PakoArcaneRetriever copy() { + return new PakoArcaneRetriever(this); + } +} + +class PakoArcaneRetrieverEffect extends OneShotEffect { + + PakoArcaneRetrieverEffect() { + super(Outcome.Benefit); + staticText = "exile the top card of each player's library and put a fetch counter on each of them. " + + "Put a +1/+1 counter on {this} for each noncreature card exiled this way."; + } + + private PakoArcaneRetrieverEffect(final PakoArcaneRetrieverEffect effect) { + super(effect); + } + + @Override + public PakoArcaneRetrieverEffect copy() { + return new PakoArcaneRetrieverEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + Cards cards = new CardsImpl(); + game.getState() + .getPlayersInRange(controller.getId(), game) + .stream() + .map(game::getPlayer) + .map(Player::getLibrary) + .map(library -> library.getFromTop(game)) + .forEach(cards::add); + controller.moveCards(cards, Zone.EXILED, source, game); + cards.removeIf(cardId -> game.getState().getZone(cardId) != Zone.EXILED); + int counters = cards.count(StaticFilters.FILTER_CARD_NON_CREATURE, game); + if (cards.isEmpty()) { + return true; + } + cards.getCards(game).stream().forEach(card -> card.addCounters(CounterType.FETCH.createInstance(), source, game)); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent == null || counters == 0) { + return true; + } + return permanent.addCounters(CounterType.P1P1.createInstance(counters), source, game); + } +} + +class PakoArcaneRetrieverWatcher extends Watcher { + + private final Map> playerMap = new HashMap(); + + PakoArcaneRetrieverWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + } + + public void addCard(UUID playerId, Card card, Game game) { + playerMap.computeIfAbsent(playerId, u -> new HashSet()).add(new MageObjectReference(card, game)); + } + + public boolean checkCard(UUID playerId, Card card, Game game) { + return playerMap + .computeIfAbsent(playerId, u -> new HashSet()) + .stream() + .anyMatch(mageObjectReference -> mageObjectReference.refersTo(card, game)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/Commander2020Edition.java b/Mage.Sets/src/mage/sets/Commander2020Edition.java index 14baae31cf..83f8d1f20e 100644 --- a/Mage.Sets/src/mage/sets/Commander2020Edition.java +++ b/Mage.Sets/src/mage/sets/Commander2020Edition.java @@ -234,6 +234,7 @@ public final class Commander2020Edition extends ExpansionSet { cards.add(new SetCardInfo("Otrimi, the Ever-Playful", 12, Rarity.MYTHIC, mage.cards.o.OtrimiTheEverPlayful.class)); cards.add(new SetCardInfo("Outpost Siege", 157, Rarity.RARE, mage.cards.o.OutpostSiege.class)); cards.add(new SetCardInfo("Painful Truths", 134, Rarity.RARE, mage.cards.p.PainfulTruths.class)); + cards.add(new SetCardInfo("Pako, Arcane Retriever", 13, Rarity.MYTHIC, mage.cards.p.PakoArcaneRetriever.class)); cards.add(new SetCardInfo("Parasitic Impetus", 46, Rarity.UNCOMMON, mage.cards.p.ParasiticImpetus.class)); cards.add(new SetCardInfo("Path of Ancestry", 298, Rarity.COMMON, mage.cards.p.PathOfAncestry.class)); cards.add(new SetCardInfo("Portal Mage", 122, Rarity.RARE, mage.cards.p.PortalMage.class)); diff --git a/Mage/src/main/java/mage/counters/CounterType.java b/Mage/src/main/java/mage/counters/CounterType.java index cd3c79be8c..f5a30d359f 100644 --- a/Mage/src/main/java/mage/counters/CounterType.java +++ b/Mage/src/main/java/mage/counters/CounterType.java @@ -49,6 +49,7 @@ public enum CounterType { FADE("fade"), FATE("fate"), FEATHER("feather"), + FETCH("fetch"), FILIBUSTER("filibuster"), FIRST_STRIKE("first strike"), FLOOD("flood"),