From 6f461f9669c1c01c5f4d9097f51ca7e4871389a5 Mon Sep 17 00:00:00 2001 From: RJayz Date: Fri, 26 Aug 2022 21:19:40 +0200 Subject: [PATCH] [CLB] Implemented Neera, Wild Mage (#9415) --- Mage.Sets/src/mage/cards/n/NeeraWildMage.java | 121 ++++++++++++++++++ .../CommanderLegendsBattleForBaldursGate.java | 1 + .../cards/single/clb/NeeraWildMageTest.java | 50 ++++++++ 3 files changed, 172 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/n/NeeraWildMage.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/clb/NeeraWildMageTest.java diff --git a/Mage.Sets/src/mage/cards/n/NeeraWildMage.java b/Mage.Sets/src/mage/cards/n/NeeraWildMage.java new file mode 100644 index 00000000000..c301ea856b9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NeeraWildMage.java @@ -0,0 +1,121 @@ +package mage.cards.n; + +import mage.ApprovingObject; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +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.SuperType; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author rjayz + */ +public final class NeeraWildMage extends CardImpl { + + public NeeraWildMage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}{R}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ELF); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(2); + this.toughness = new MageInt(7); + + // Whenever you cast a spell, you may put it on the bottom of its owner's library. + // If you do, reveal cards from the top of your library until you reveal a nonland card. + // You may cast that card without paying its mana cost. + // Then put the rest on the bottom of your library in a random order. + // This ability triggers only once each turn. + this.addAbility(new SpellCastControllerTriggeredAbility(new NeeraWildMageEffect(), StaticFilters.FILTER_SPELL_A, + true, true).setTriggersOnce(true)); + } + + private NeeraWildMage(final NeeraWildMage card) { + super(card); + } + + @Override + public NeeraWildMage copy() { + return new NeeraWildMage(this); + } +} + +class NeeraWildMageEffect extends OneShotEffect { + + public NeeraWildMageEffect() { + super(Outcome.Neutral); + staticText = "you may put it on the bottom of its owner's library. If you do, reveal cards from the top of your library until you reveal a nonland card. You may cast that card without paying its mana cost. Then put the rest on the bottom of your library in a random order. This ability triggers only once each turn."; + } + + public NeeraWildMageEffect(final NeeraWildMageEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source)); + if (spell == null) { + return false; + } + + Player spellController = game.getPlayer(spell.getControllerId()); + if (spellController == null) { + return false; + } + + if(!spellController.putCardsOnBottomOfLibrary(spell, game, source, true)) { + return false; + } + + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null || controller.getLibrary() == null || !controller.getLibrary().hasCards()) { + return false; + } + + CardsImpl toReveal = new CardsImpl(); + Card eligibleCard = null; + for (Card card : controller.getLibrary().getCards(game)) { + toReveal.add(card); + if (!card.isLand(game)) { + eligibleCard = card; + break; + } + } + + controller.revealCards(source, toReveal, game); + if (eligibleCard != null + && controller.chooseUse(Outcome.PlayForFree, "Cast " + eligibleCard.getLogName() + " without paying its mana cost?", source, game)) { + game.getState().setValue("PlayFromNotOwnHandZone" + eligibleCard.getId(), Boolean.TRUE); + boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(eligibleCard, game, true), + game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + eligibleCard.getId(), null); + if (cardWasCast) { + toReveal.remove(eligibleCard); + } + } + + controller.putCardsOnBottomOfLibrary(toReveal, game, source, false); + + return true; + } + + @Override + public NeeraWildMageEffect copy() { + return new NeeraWildMageEffect(this); + } + +} diff --git a/Mage.Sets/src/mage/sets/CommanderLegendsBattleForBaldursGate.java b/Mage.Sets/src/mage/sets/CommanderLegendsBattleForBaldursGate.java index a819e13927e..7907642986b 100644 --- a/Mage.Sets/src/mage/sets/CommanderLegendsBattleForBaldursGate.java +++ b/Mage.Sets/src/mage/sets/CommanderLegendsBattleForBaldursGate.java @@ -404,6 +404,7 @@ public final class CommanderLegendsBattleForBaldursGate extends ExpansionSet { cards.add(new SetCardInfo("Nature's Lore", 244, Rarity.COMMON, mage.cards.n.NaturesLore.class)); cards.add(new SetCardInfo("Nautiloid Ship", 328, Rarity.MYTHIC, mage.cards.n.NautiloidShip.class)); cards.add(new SetCardInfo("Navigation Orb", 329, Rarity.COMMON, mage.cards.n.NavigationOrb.class)); + cards.add(new SetCardInfo("Neera, Wild Mage", 288, Rarity.RARE, mage.cards.n.NeeraWildMage.class)); cards.add(new SetCardInfo("Nefarious Imp", 137, Rarity.COMMON, mage.cards.n.NefariousImp.class)); cards.add(new SetCardInfo("Nemesis Phoenix", 189, Rarity.UNCOMMON, mage.cards.n.NemesisPhoenix.class)); cards.add(new SetCardInfo("Nemesis of Reason", 850, Rarity.RARE, mage.cards.n.NemesisOfReason.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/clb/NeeraWildMageTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/clb/NeeraWildMageTest.java new file mode 100644 index 00000000000..1a2a64e5ad3 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/clb/NeeraWildMageTest.java @@ -0,0 +1,50 @@ +package org.mage.test.cards.single.clb; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author rjayz + */ +public class NeeraWildMageTest extends CardTestPlayerBase { + + @Test + public void TestNeeraWildMage() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 1); + + // Whenever you cast a spell, you may put it on the bottom of its owner's library. + // If you do, reveal cards from the top of your library until you reveal a nonland card. + // You may cast that card without paying its mana cost. + // Then put the rest on the bottom of your library in a random order. + // This ability triggers only once each turn. + addCard(Zone.BATTLEFIELD, playerA, "Neera, Wild Mage", 1); + + addCard(Zone.HAND, playerA, "Consider"); + + playerA.getLibrary().clear(); + addCard(Zone.LIBRARY, playerA, "Mental Note"); + addCard(Zone.LIBRARY, playerA, "Island"); + addCard(Zone.LIBRARY, playerA, "Island"); + skipInitShuffling(); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Consider"); + // Choose to use Neera's ability + setChoice(playerA, true); + // Do not cast Mental Note revealed with Neera's ability + setChoice(playerA, false); + + setStopAt(3, PhaseStep.BEGIN_COMBAT); + execute(); + + // Consider was not cast so should be on top of the deck after resolving Neera's ability + // On turn 3 it will be drawn by player A + assertHandCount(playerA, 1); + assertHandCount(playerA, "Consider", 1); + assertLibraryCount(playerA, 3); + assertLibraryCount(playerA, "Mental Note", 1); + assertLibraryCount(playerA, "Island", 2); + } +}