From ae3580a6c1f64b7dae1a24523869fc40f27c9b62 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Wed, 22 Apr 2020 20:49:58 -0400 Subject: [PATCH] Implemented Haldan, Avid Arcanist --- .../src/mage/cards/h/HaldanAvidArcanist.java | 122 ++++++++++++++++++ .../src/mage/cards/p/PakoArcaneRetriever.java | 17 ++- .../src/mage/sets/Commander2020Edition.java | 1 + 3 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/h/HaldanAvidArcanist.java diff --git a/Mage.Sets/src/mage/cards/h/HaldanAvidArcanist.java b/Mage.Sets/src/mage/cards/h/HaldanAvidArcanist.java new file mode 100644 index 0000000000..45451403a4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HaldanAvidArcanist.java @@ -0,0 +1,122 @@ +package mage.cards.h; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.AsThoughManaEffect; +import mage.abilities.keyword.PartnerWithAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.p.PakoArcaneRetriever; +import mage.constants.*; +import mage.counters.CounterType; +import mage.game.Game; +import mage.players.ManaPoolItem; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class HaldanAvidArcanist extends CardImpl { + + public HaldanAvidArcanist(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(1); + this.toughness = new MageInt(4); + + // Partner with Pako, Arcane Retriever + this.addAbility(new PartnerWithAbility("Pako, Arcane Retriever")); + + // You may play noncreature cards from exile with fetch counters on them if you exiled them, and you may spend mana as though it were mana of any color to cast those spells. + Ability ability = new SimpleStaticAbility(new HaldanAvidArcanistCastFromExileEffect()); + ability.addEffect(new HaldanAvidArcanistSpendAnyManaEffect()); + this.addAbility(ability, PakoArcaneRetriever.makeWatcher()); + } + + private HaldanAvidArcanist(final HaldanAvidArcanist card) { + super(card); + } + + @Override + public HaldanAvidArcanist copy() { + return new HaldanAvidArcanist(this); + } +} + +class HaldanAvidArcanistCastFromExileEffect extends AsThoughEffectImpl { + + HaldanAvidArcanistCastFromExileEffect() { + super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit); + staticText = "You may play noncreature cards from exile with fetch counters on them if you exiled them, and"; + } + + private HaldanAvidArcanistCastFromExileEffect(final HaldanAvidArcanistCastFromExileEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public HaldanAvidArcanistCastFromExileEffect copy() { + return new HaldanAvidArcanistCastFromExileEffect(this); + } + + @Override + public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { + if (!PakoArcaneRetriever.checkWatcher(affectedControllerId, game.getCard(sourceId), game) + || !source.isControlledBy(affectedControllerId) + || game.getState().getZone(sourceId) != Zone.EXILED) { + return false; + } + Card card = game.getCard(sourceId); + return card != null && !card.isCreature() && card.getCounters(game).containsKey(CounterType.FETCH); + } +} + +class HaldanAvidArcanistSpendAnyManaEffect extends AsThoughEffectImpl implements AsThoughManaEffect { + + HaldanAvidArcanistSpendAnyManaEffect() { + super(AsThoughEffectType.SPEND_OTHER_MANA, Duration.Custom, Outcome.Benefit); + staticText = "you may spend mana as though it were mana of any color to cast those spells"; + } + + private HaldanAvidArcanistSpendAnyManaEffect(final HaldanAvidArcanistSpendAnyManaEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public HaldanAvidArcanistSpendAnyManaEffect copy() { + return new HaldanAvidArcanistSpendAnyManaEffect(this); + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + if (!PakoArcaneRetriever.checkWatcher(affectedControllerId, game.getCard(objectId), game) + || !source.isControlledBy(affectedControllerId) + || game.getState().getZone(objectId) != Zone.EXILED) { + return false; + } + Card card = game.getCard(objectId); + return card != null && !card.isCreature() && card.getCounters(game).containsKey(CounterType.FETCH); + } + + @Override + public ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game) { + return mana.getFirstAvailable(); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/p/PakoArcaneRetriever.java b/Mage.Sets/src/mage/cards/p/PakoArcaneRetriever.java index 85a7e10407..8dc54259a5 100644 --- a/Mage.Sets/src/mage/cards/p/PakoArcaneRetriever.java +++ b/Mage.Sets/src/mage/cards/p/PakoArcaneRetriever.java @@ -40,7 +40,9 @@ public final class PakoArcaneRetriever extends CardImpl { 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)); + this.addAbility(new AttacksTriggeredAbility( + new PakoArcaneRetrieverEffect(), false + ), new PakoArcaneRetrieverWatcher()); } private PakoArcaneRetriever(final PakoArcaneRetriever card) { @@ -51,6 +53,15 @@ public final class PakoArcaneRetriever extends CardImpl { public PakoArcaneRetriever copy() { return new PakoArcaneRetriever(this); } + + public static PakoArcaneRetrieverWatcher makeWatcher() { + return new PakoArcaneRetrieverWatcher(); + } + + public static boolean checkWatcher(UUID playerId, Card card, Game game) { + PakoArcaneRetrieverWatcher watcher = game.getState().getWatcher(PakoArcaneRetrieverWatcher.class); + return watcher != null && watcher.checkCard(playerId, card, game); + } } class PakoArcaneRetrieverEffect extends OneShotEffect { @@ -111,11 +122,11 @@ class PakoArcaneRetrieverWatcher extends Watcher { public void watch(GameEvent event, Game game) { } - public void addCard(UUID playerId, Card card, Game game) { + 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) { + boolean checkCard(UUID playerId, Card card, Game game) { return playerMap .computeIfAbsent(playerId, u -> new HashSet()) .stream() diff --git a/Mage.Sets/src/mage/sets/Commander2020Edition.java b/Mage.Sets/src/mage/sets/Commander2020Edition.java index 83f8d1f20e..a1d1308486 100644 --- a/Mage.Sets/src/mage/sets/Commander2020Edition.java +++ b/Mage.Sets/src/mage/sets/Commander2020Edition.java @@ -153,6 +153,7 @@ public final class Commander2020Edition extends ExpansionSet { cards.add(new SetCardInfo("Grisly Salvage", 215, Rarity.COMMON, mage.cards.g.GrislySalvage.class)); cards.add(new SetCardInfo("Growth Spiral", 216, Rarity.COMMON, mage.cards.g.GrowthSpiral.class)); cards.add(new SetCardInfo("Gruul Turf", 279, Rarity.UNCOMMON, mage.cards.g.GruulTurf.class)); + cards.add(new SetCardInfo("Haldan, Avid Arcanist", 2, Rarity.MYTHIC, mage.cards.h.HaldanAvidArcanist.class)); cards.add(new SetCardInfo("Halimar Depths", 280, Rarity.COMMON, mage.cards.h.HalimarDepths.class)); cards.add(new SetCardInfo("Harmonize", 173, Rarity.UNCOMMON, mage.cards.h.Harmonize.class)); cards.add(new SetCardInfo("Harrow", 174, Rarity.COMMON, mage.cards.h.Harrow.class));