From 6e246ded6ad2fb803304c484b8f7cd37d7b89523 Mon Sep 17 00:00:00 2001 From: RJayz Date: Sat, 27 Aug 2022 23:37:40 +0200 Subject: [PATCH] [CLB] Implemented Scion of Halaster (#9417) --- .../src/mage/cards/s/ScionOfHalaster.java | 92 ++++++++++++++++ .../CommanderLegendsBattleForBaldursGate.java | 1 + .../cards/single/clb/ScionOfHalasterTest.java | 102 ++++++++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/ScionOfHalaster.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/clb/ScionOfHalasterTest.java diff --git a/Mage.Sets/src/mage/cards/s/ScionOfHalaster.java b/Mage.Sets/src/mage/cards/s/ScionOfHalaster.java new file mode 100644 index 0000000000..9357d53e38 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ScionOfHalaster.java @@ -0,0 +1,92 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.abilities.effects.common.LookLibraryControllerEffect; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.players.Player; +import mage.watchers.common.CardsDrawnThisTurnWatcher; + +import java.util.UUID; + +/** + * @author Rjayz + */ +public final class ScionOfHalaster extends CardImpl { + + public ScionOfHalaster(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.BACKGROUND); + + // Commander creatures you own have "The first time you would draw a card each turn, instead look at the top two cards of your library. Put one of them into your graveyard and the other back on top of your library. Then draw a card." + this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect( + new SimpleStaticAbility(new ScionOfHalasterReplacementEffect()), + Duration.WhileOnBattlefield, StaticFilters.FILTER_CREATURES_OWNED_COMMANDER + )), new CardsDrawnThisTurnWatcher()); + } + + private ScionOfHalaster(final ScionOfHalaster card) { + super(card); + } + + @Override + public ScionOfHalaster copy() { + return new ScionOfHalaster(this); + } +} + +class ScionOfHalasterReplacementEffect extends ReplacementEffectImpl { + + ScionOfHalasterReplacementEffect() { + super(Duration.WhileOnBattlefield, Outcome.Neutral); + staticText = "The first time you would draw a card each turn, instead look at the top two cards of your library. Put one of them into your graveyard and the other back on top of your library. Then draw a card"; + } + + ScionOfHalasterReplacementEffect(final mage.cards.s.ScionOfHalasterReplacementEffect effect) { + super(effect); + } + + @Override + public mage.cards.s.ScionOfHalasterReplacementEffect copy() { + return new mage.cards.s.ScionOfHalasterReplacementEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + new LookLibraryAndPickControllerEffect(2, 1, LookLibraryControllerEffect.PutCards.GRAVEYARD, LookLibraryControllerEffect.PutCards.TOP_ANY).apply(game, source); + Player you = game.getPlayer(event.getPlayerId()); + if (you != null) { + you.drawCards(1, source, game, event); + } + return true; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DRAW_CARD; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (!event.getPlayerId().equals(source.getControllerId())) { + return false; + } + CardsDrawnThisTurnWatcher watcher = game.getState().getWatcher(CardsDrawnThisTurnWatcher.class); + return watcher != null && watcher.getCardsDrawnThisTurn(event.getPlayerId()) == 0; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/CommanderLegendsBattleForBaldursGate.java b/Mage.Sets/src/mage/sets/CommanderLegendsBattleForBaldursGate.java index 7907642986..191c8539d1 100644 --- a/Mage.Sets/src/mage/sets/CommanderLegendsBattleForBaldursGate.java +++ b/Mage.Sets/src/mage/sets/CommanderLegendsBattleForBaldursGate.java @@ -494,6 +494,7 @@ public final class CommanderLegendsBattleForBaldursGate extends ExpansionSet { cards.add(new SetCardInfo("Sarevok's Tome", 685, Rarity.RARE, mage.cards.s.SarevoksTome.class)); cards.add(new SetCardInfo("Sarevok, Deathbringer", 144, Rarity.UNCOMMON, mage.cards.s.SarevokDeathbringer.class)); cards.add(new SetCardInfo("Scaled Nurturer", 252, Rarity.COMMON, mage.cards.s.ScaledNurturer.class)); + cards.add(new SetCardInfo("Scion of Halaster", 145, Rarity.COMMON, mage.cards.s.ScionOfHalaster.class)); cards.add(new SetCardInfo("Scouting Hawk", 41, Rarity.COMMON, mage.cards.s.ScoutingHawk.class)); cards.add(new SetCardInfo("Sculpted Sunburst", 42, Rarity.RARE, mage.cards.s.SculptedSunburst.class)); cards.add(new SetCardInfo("Sea Gate", 359, Rarity.COMMON, mage.cards.s.SeaGate.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/clb/ScionOfHalasterTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/clb/ScionOfHalasterTest.java new file mode 100644 index 0000000000..beb2dff25a --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/clb/ScionOfHalasterTest.java @@ -0,0 +1,102 @@ +package org.mage.test.cards.single.clb; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.GameException; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestCommanderDuelBase; + +import java.io.FileNotFoundException; + +/** + * + * @author Rjayz + */ +public class ScionOfHalasterTest extends CardTestCommanderDuelBase { + + @Override + protected Game createNewGameAndPlayers() throws GameException, FileNotFoundException { + setDecknamePlayerA("CommanderDuel_Partners.dck"); // Commander = Ishai, Ojutai Dragonspeaker and Thrasios, Triton Hero + return super.createNewGameAndPlayers(); + } + + @Test + public void TestScionOfHalaster() { + addCard(Zone.BATTLEFIELD, playerA, "Scion of Halaster", 1); + + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + addCard(Zone.BATTLEFIELD, playerA, "Island", 4); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); + + // Cast commander so Scion of Halaster takes effect + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Thrasios, Triton Hero"); + + playerA.getLibrary().clear(); + addCard(Zone.LIBRARY, playerA, "Lightning Bolt"); + addCard(Zone.LIBRARY, playerA, "Mountain"); + skipInitShuffling(); + + setStrictChooseMode(true); + + // Choose to put Mountain in the graveyard with Scion of Halaster's effect on Thrasios, Triton Hero + addTarget(playerA, "Mountain"); + + // Continue to turn 3 so we get to Player A's draw step + setStopAt(3, PhaseStep.PRECOMBAT_MAIN); + execute(); + + // Lightning Bolt in library stays on top and will be drawn + assertLibraryCount(playerA, 0); + assertHandCount(playerA, 1); + assertHandCount(playerA, "Lightning Bolt", 1); + assertGraveyardCount(playerA, 1); + assertGraveyardCount(playerA, "Mountain", 1); + } + + /** + * Test if Scion of Halaster's effect correctly replaces itself when there are multiple commander creatures who have it. + * For example, when a commander deck has two partner commanders and both are on the battlefield. + */ + @Test + public void TestScionOfHalaster_withPartnerCommanders() { + addCard(Zone.BATTLEFIELD, playerA, "Scion of Halaster", 1); + + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + addCard(Zone.BATTLEFIELD, playerA, "Island", 4); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); + + // Cast both partner commanders, Scion of Halaster grants its ability to both of them + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Thrasios, Triton Hero", true); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ishai, Ojutai Dragonspeaker"); + + playerA.getLibrary().clear(); + addCard(Zone.LIBRARY, playerA, "Lightning Bolt"); + addCard(Zone.LIBRARY, playerA, "Island"); + addCard(Zone.LIBRARY, playerA, "Mountain"); + skipInitShuffling(); + + setStrictChooseMode(true); + + // Choose for Thrasios, Triton Hero's replacement effect granted by Scion of Halaster to apply first + setChoice(playerA, "Thrasios, Triton Hero"); + + // Choose to put Mountain in the graveyard with Scion of Halaster's effect on Thrasios, Triton Hero + addTarget(playerA, "Mountain"); + + // Choose to put Island in the graveyard with Scion of Halaster's effect on Ishai, Ojutai Dragonspeaker + addTarget(playerA, "Island"); + + // Continue to turn 3 so we get to Player A's draw step + setStopAt(3, PhaseStep.PRECOMBAT_MAIN); + execute(); + + // Lightning Bolt in library stays on top and will be drawn + assertLibraryCount(playerA, 0); + assertHandCount(playerA, 1); + assertHandCount(playerA, "Lightning Bolt", 1); + assertGraveyardCount(playerA, 2); + assertGraveyardCount(playerA, "Mountain", 1); + assertGraveyardCount(playerA, "Island", 1); + } +}