From 4c0f497fd309e7c0db4771c248ff842837f212f9 Mon Sep 17 00:00:00 2001 From: Matthew Wilson Date: Sun, 21 Jan 2024 09:42:58 +0200 Subject: [PATCH] [LCC] Implement Charismatic Conqueror (#11693) * [LCC] Implement Charismatic Conqueror --------- Co-authored-by: Matthew Wilson --- .../mage/cards/c/CharismaticConqueror.java | 108 ++++++++++++++++++ .../sets/LostCavernsOfIxalanCommander.java | 1 + .../single/lcc/CharismaticConquerorTest.java | 95 +++++++++++++++ 3 files changed, 204 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/c/CharismaticConqueror.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/lcc/CharismaticConquerorTest.java diff --git a/Mage.Sets/src/mage/cards/c/CharismaticConqueror.java b/Mage.Sets/src/mage/cards/c/CharismaticConqueror.java new file mode 100644 index 00000000000..65ca1959dff --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CharismaticConqueror.java @@ -0,0 +1,108 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldOpponentTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.constants.Outcome; +import mage.constants.SetTargetPointer; +import mage.constants.SubType; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.IxalanVampireToken; +import mage.players.Player; + +/** + * Charismatic Conqueror {1}{W} + * Creature - Vampire Soldier 2/2 + * Vigilance + * Whenever an artifact or creature enters the battlefield untapped and under an opponent's control, they may tap that permanent. If they don't, you create a 1/1 white Vampire creature token with lifelink. + * + * @author DominionSpy + */ +public final class CharismaticConqueror extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent(); + + static { + filter.add(Predicates.or( + CardType.ARTIFACT.getPredicate(), + CardType.CREATURE.getPredicate() + )); + filter.add(TappedPredicate.UNTAPPED); + } + + public CharismaticConqueror(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add(SubType.VAMPIRE); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Whenever an artifact or creature enters the battlefield untapped and under an opponent's control, they may tap that permanent. If they don't, you create a 1/1 white Vampire creature token with lifelink. + Ability ability = new EntersBattlefieldOpponentTriggeredAbility( + Zone.BATTLEFIELD, new CharismaticConquerorEffect(), filter, false, SetTargetPointer.PERMANENT + ).setTriggerPhrase("Whenever an artifact or creature enters the battlefield untapped and under an opponent's control, "); + this.addAbility(ability); + } + + private CharismaticConqueror(final CharismaticConqueror card) { + super(card); + } + + @Override + public CharismaticConqueror copy() { + return new CharismaticConqueror(this); + } +} + +class CharismaticConquerorEffect extends OneShotEffect { + + CharismaticConquerorEffect() { + super(Outcome.Benefit); + this.staticText = "they may tap that permanent. If they don't, you create a 1/1 white Vampire creature token with lifelink."; + } + + private CharismaticConquerorEffect(final CharismaticConquerorEffect effect) { + super(effect); + } + + @Override + public CharismaticConquerorEffect copy() { + return new CharismaticConquerorEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent != null && game.getPlayer(permanent.getControllerId()) != null) { + Player opponent = game.getPlayer(permanent.getControllerId()); + if (!permanent.isTapped() && + opponent.chooseUse(Outcome.Tap, "Tap " + permanent.getLogName(), source, game)) { + permanent.tap(source, game); + return false; + } + } + + return new CreateTokenEffect(new IxalanVampireToken()).apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/sets/LostCavernsOfIxalanCommander.java b/Mage.Sets/src/mage/sets/LostCavernsOfIxalanCommander.java index 2564b6dd520..1c14772d4c9 100644 --- a/Mage.Sets/src/mage/sets/LostCavernsOfIxalanCommander.java +++ b/Mage.Sets/src/mage/sets/LostCavernsOfIxalanCommander.java @@ -65,6 +65,7 @@ public final class LostCavernsOfIxalanCommander extends ExpansionSet { cards.add(new SetCardInfo("Champion of Dusk", 188, Rarity.RARE, mage.cards.c.ChampionOfDusk.class)); cards.add(new SetCardInfo("Chandra's Ignition", 220, Rarity.RARE, mage.cards.c.ChandrasIgnition.class)); cards.add(new SetCardInfo("Chaos Warp", 221, Rarity.RARE, mage.cards.c.ChaosWarp.class)); + cards.add(new SetCardInfo("Charismatic Conqueror", 70, Rarity.RARE, mage.cards.c.CharismaticConqueror.class)); cards.add(new SetCardInfo("Chimil, the Inner Sun", 106, Rarity.MYTHIC, mage.cards.c.ChimilTheInnerSun.class)); cards.add(new SetCardInfo("Choked Estuary", 322, Rarity.RARE, mage.cards.c.ChokedEstuary.class)); cards.add(new SetCardInfo("Chromatic Orrery", 107, Rarity.MYTHIC, mage.cards.c.ChromaticOrrery.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/lcc/CharismaticConquerorTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/lcc/CharismaticConquerorTest.java new file mode 100644 index 00000000000..3fce080c4f4 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/lcc/CharismaticConquerorTest.java @@ -0,0 +1,95 @@ +package org.mage.test.cards.single.lcc; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * Charismatic Conqueror {1}{W} + * Creature - Vampire Soldier 2/2 + * Vigilance + * Whenever an artifact or creature enters the battlefield untapped and under an opponent’s control, they may tap that permanent. If they don’t, you create a 1/1 white Vampire creature token with lifelink. + * + * @author DominionSpy + */ +public class CharismaticConquerorTest extends CardTestPlayerBase { + + private static final String charismaticConqueror = "Charismatic Conqueror"; + private static final String chaliceOfLife = "Chalice of Life"; + private static final String vampireToken = "Vampire Token"; + + @Test + public void test_ChooseToTap() { + addCard(Zone.BATTLEFIELD, playerB, charismaticConqueror); + + addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); + addCard(Zone.HAND, playerA, chaliceOfLife); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, chaliceOfLife); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, 1); + setChoice(playerA, true); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerB, vampireToken, 0); + } + + @Test + public void test_ChooseNotToTap() { + addCard(Zone.BATTLEFIELD, playerB, charismaticConqueror); + + addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); + addCard(Zone.HAND, playerA, chaliceOfLife); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, chaliceOfLife); + setChoice(playerA, false); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerB, vampireToken, 1); + } + + @Test + public void test_TapBeforeResolution() { + addCard(Zone.BATTLEFIELD, playerB, charismaticConqueror); + + addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); + addCard(Zone.HAND, playerA, chaliceOfLife); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, chaliceOfLife); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, 1); + // Activate Chalice of Life's ability while Charismatic Conqueror's trigger is on the stack + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerB, vampireToken, 1); + } + + @Test + public void test_DestroyBeforeResolution() { + addCard(Zone.BATTLEFIELD, playerB, charismaticConqueror); + + addCard(Zone.BATTLEFIELD, playerA, "Plains", 3 + 2); + addCard(Zone.HAND, playerA, chaliceOfLife); + addCard(Zone.HAND, playerA, "Divine Offering"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, chaliceOfLife); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, 1); + // Destroy Chalice of Life while Charismatic Conqueror's trigger is on the stack + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Divine Offering", chaliceOfLife); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerB, vampireToken, 1); + } +}