From 77e61fe0566a8f8d8ccc5f5c06bc066c1592af1a Mon Sep 17 00:00:00 2001 From: Edoardo Mortara <34277835+FreaIsDead@users.noreply.github.com> Date: Wed, 24 Aug 2022 00:25:28 +0200 Subject: [PATCH] [CLB] Implement Banishment (#9400) --- Mage.Sets/src/mage/cards/b/Banishment.java | 107 ++++++++++++++++++ .../CommanderLegendsBattleForBaldursGate.java | 1 + .../single/clb/BanishmentInfluenceTest.java | 62 ++++++++++ 3 files changed, 170 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/Banishment.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/clb/BanishmentInfluenceTest.java diff --git a/Mage.Sets/src/mage/cards/b/Banishment.java b/Mage.Sets/src/mage/cards/b/Banishment.java new file mode 100644 index 0000000000..93ff0c997a --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/Banishment.java @@ -0,0 +1,107 @@ +package mage.cards.b; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.delayed.OnLeaveReturnExiledToBattlefieldAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.keyword.FlashAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterNonlandPermanent; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.util.CardUtil; + +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * + * @author freaisdead + */ +public final class Banishment extends CardImpl { + + private static final FilterNonlandPermanent filter = new FilterNonlandPermanent(); + + static { + filter.add(TargetController.OPPONENT.getControllerPredicate()); + } + + public Banishment(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); + + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // When Banishment enters the battlefield, exile target nonland permanent an opponent controls and all other nonland permanents your opponents control with the same name as that permanent until Banishment leaves the battlefield. + Ability ability = new EntersBattlefieldTriggeredAbility(new BanishmentEffect(), false); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + private Banishment(final Banishment card) { + super(card); + } + + @Override + public Banishment copy() { + return new Banishment(this); + } +} + + +class BanishmentEffect extends OneShotEffect { + + BanishmentEffect() { + super(Outcome.Benefit); + this.staticText = "exile target nonland permanent an opponent controls " + + "and all other nonland permanents your opponents control " + + "with the same name as that permanent until {this} leaves the battlefield"; + } + + private BanishmentEffect(final BanishmentEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + Permanent targeted = game.getPermanent(source.getFirstTarget()); + + if (permanent == null || controller == null || targeted == null) { + return false; + } + + FilterPermanent filter = new FilterNonlandPermanent(); + filter.add(new NamePredicate(targeted.getName())); + + Set toExile = game.getBattlefield().getAllActivePermanents(filter, game) + .stream().filter(p -> controller.hasOpponent(p.getControllerId(),game)) + .collect(Collectors.toCollection(LinkedHashSet::new)); + + if (!toExile.isEmpty()) { + controller.moveCardsToExile(toExile, source, game, true, CardUtil.getCardExileZoneId(game, source), permanent.getIdName()); + new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()).apply(game, source); + } + return true; + } + + @Override + public BanishmentEffect copy() { + return new BanishmentEffect(this); + } + +} \ 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 41f7770e31..a819e13927 100644 --- a/Mage.Sets/src/mage/sets/CommanderLegendsBattleForBaldursGate.java +++ b/Mage.Sets/src/mage/sets/CommanderLegendsBattleForBaldursGate.java @@ -67,6 +67,7 @@ public final class CommanderLegendsBattleForBaldursGate extends ExpansionSet { cards.add(new SetCardInfo("Band Together", 216, Rarity.COMMON, mage.cards.b.BandTogether.class)); cards.add(new SetCardInfo("Bane's Contingency", 57, Rarity.UNCOMMON, mage.cards.b.BanesContingency.class)); cards.add(new SetCardInfo("Bane's Invoker", 7, Rarity.COMMON, mage.cards.b.BanesInvoker.class)); + cards.add(new SetCardInfo("Banishment", 8, Rarity.UNCOMMON, mage.cards.b.Banishment.class)); cards.add(new SetCardInfo("Basilisk Collar", 300, Rarity.RARE, mage.cards.b.BasiliskCollar.class)); cards.add(new SetCardInfo("Basilisk Gate", 346, Rarity.COMMON, mage.cards.b.BasiliskGate.class)); cards.add(new SetCardInfo("Battle Angels of Tyr", 9, Rarity.MYTHIC, mage.cards.b.BattleAngelsOfTyr.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/clb/BanishmentInfluenceTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/clb/BanishmentInfluenceTest.java new file mode 100644 index 0000000000..5e02092070 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/clb/BanishmentInfluenceTest.java @@ -0,0 +1,62 @@ +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.CardTestMultiPlayerBase; + +public class BanishmentInfluenceTest extends CardTestMultiPlayerBase { + + @Test + public void testBanishment() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 4); + addCard(Zone.BATTLEFIELD, playerA, "Memnite", 4); + addCard(Zone.HAND, playerA, "Banishment", 1); + addCard(Zone.BATTLEFIELD, playerB, "Memnite", 1); + addCard(Zone.BATTLEFIELD, playerB, "Steel Overseer", 4); + addCard(Zone.BATTLEFIELD, playerC, "Memnite", 5); + addCard(Zone.BATTLEFIELD, playerC, "Steel Overseer", 1); + addCard(Zone.BATTLEFIELD, playerD, "Memnite", 5); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Banishment"); + addTarget(playerA, "Memnite"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "Memnite", 4); + assertPermanentCount(playerA, "Banishment", 1); + assertPermanentCount(playerB, "Memnite", 0); + assertPermanentCount(playerB, "Steel Overseer", 4); + assertPermanentCount(playerC, "Memnite", 5); + assertPermanentCount(playerC, "Steel Overseer", 1); + assertPermanentCount(playerD, "Memnite", 0); + } + + @Test + public void testDestroyBanishment() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 6); + addCard(Zone.HAND, playerA, "Banishment", 1); + addCard(Zone.HAND, playerA, "Disenchant", 1); + addCard(Zone.BATTLEFIELD, playerB, "Memnite", 1); + addCard(Zone.BATTLEFIELD, playerB, "Steel Overseer", 4); + addCard(Zone.BATTLEFIELD, playerC, "Memnite", 5); + addCard(Zone.BATTLEFIELD, playerC, "Steel Overseer", 1); + addCard(Zone.BATTLEFIELD, playerD, "Memnite", 5); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Banishment"); + addTarget(playerA, "Memnite"); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Disenchant"); + addTarget(playerA, "Banishment"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "Banishment", 0); + assertPermanentCount(playerB, "Memnite", 1); + assertPermanentCount(playerB, "Steel Overseer", 4); + assertPermanentCount(playerC, "Memnite", 5); + assertPermanentCount(playerC, "Steel Overseer", 1); + assertPermanentCount(playerD, "Memnite", 5); + } +}