mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
Modal double-faced cards - fixed game error on usage with some replacement effects (example: Diluvian Primordial, closes #12176) (#12184)
This commit is contained in:
parent
1ae48593a8
commit
36d6547bf8
10 changed files with 339 additions and 38 deletions
|
|
@ -40,10 +40,7 @@ public final class DiluvianPrimordial extends CardImpl {
|
||||||
// Flying
|
// Flying
|
||||||
this.addAbility(FlyingAbility.getInstance());
|
this.addAbility(FlyingAbility.getInstance());
|
||||||
|
|
||||||
// When Diluvian Primordial enters the battlefield, for each opponent,
|
// When Diluvian Primordial enters the battlefield, for each opponent, you may cast up to one target instant or sorcery card from that player's graveyard without paying its mana cost. If a card cast this way would be put into a graveyard this turn, exile it instead.
|
||||||
// you may cast up to one target instant or sorcery card from that
|
|
||||||
// player's graveyard without paying its mana cost. If a card cast this way
|
|
||||||
// would be put into a graveyard this turn, exile it instead.
|
|
||||||
Ability ability = new EntersBattlefieldTriggeredAbility(new DiluvianPrimordialEffect(), false);
|
Ability ability = new EntersBattlefieldTriggeredAbility(new DiluvianPrimordialEffect(), false);
|
||||||
ability.setTargetAdjuster(DiluvianPrimordialAdjuster.instance);
|
ability.setTargetAdjuster(DiluvianPrimordialAdjuster.instance);
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package org.mage.test.cards.cost.splitcards;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Susucr
|
||||||
|
*/
|
||||||
|
public class SplitCardsReboundTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
@Ignore // Cast Through Time is broken on Split Cards.
|
||||||
|
@Test
|
||||||
|
public void test_FireIce() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Cast Through Time"); // Instant and sorcery spells you control have rebound.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp");
|
||||||
|
addCard(Zone.HAND, playerA, "Fire // Ice");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fire");
|
||||||
|
addTargetAmount(playerA, playerB, 2);
|
||||||
|
|
||||||
|
checkExileCount("in exile", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Fire // Ice", 1);
|
||||||
|
|
||||||
|
setChoice(playerA, true); // yes to Rebound trigger
|
||||||
|
setChoice(playerA, "Cast Ice"); // choose the side to cast
|
||||||
|
addTarget(playerA, "Mountain");
|
||||||
|
|
||||||
|
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerB, 20 - 2);
|
||||||
|
assertGraveyardCount(playerA, "Fire // Ice", 1);
|
||||||
|
assertTapped("Mountain", true);
|
||||||
|
assertTapped("Swamp", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
package org.mage.test.cards.single.gtc;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.player.TestPlayer;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Susucr
|
||||||
|
*/
|
||||||
|
public class DiluvianPrimordialTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link mage.cards.d.DiluvianPrimordial Diluvian Primordial} {5}{U}{U}
|
||||||
|
* Creature — Avatar
|
||||||
|
* Flying
|
||||||
|
* When Diluvian Primordial enters the battlefield, for each opponent, you may cast up to one target instant or sorcery card from that player’s graveyard without paying its mana cost. If a spell cast this way would be put into a graveyard, exile it instead.
|
||||||
|
* 5/5
|
||||||
|
*/
|
||||||
|
private static final String primordial = "Diluvian Primordial";
|
||||||
|
|
||||||
|
// Bug: NPE on casting Valakut Awakening
|
||||||
|
@Test
|
||||||
|
public void test_MDFC() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
addCard(Zone.HAND, playerA, primordial);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 7);
|
||||||
|
addCard(Zone.GRAVEYARD, playerB, "Valakut Awakening"); // MDFC Instant / Land
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, primordial);
|
||||||
|
addTarget(playerA, "Valakut Awakening");
|
||||||
|
setChoice(playerA, true); // Yes to "You may"
|
||||||
|
setChoice(playerA, TestPlayer.CHOICE_SKIP); // No choice for Awakening's effect
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertExileCount(playerB, "Valakut Awakening", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Split() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
addCard(Zone.HAND, playerA, primordial);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 7);
|
||||||
|
addCard(Zone.GRAVEYARD, playerB, "Fire // Ice");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, primordial);
|
||||||
|
addTarget(playerA, "Fire // Ice");
|
||||||
|
setChoice(playerA, true); // Yes to "You may"
|
||||||
|
setChoice(playerA, "Cast Ice"); // Choose what part of the card to cast
|
||||||
|
addTarget(playerA, primordial);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertExileCount(playerB, "Fire // Ice", 1);
|
||||||
|
assertTapped(primordial, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Adventure() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
addCard(Zone.HAND, playerA, primordial);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 7);
|
||||||
|
addCard(Zone.GRAVEYARD, playerB, "Twice Upon a Time"); // Adventure with Sorcery on main face
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, primordial);
|
||||||
|
addTarget(playerA, "Twice Upon a Time");
|
||||||
|
setChoice(playerA, true); // Yes to "You may"
|
||||||
|
setChoice(playerA, "Cast Unlikely Meeting"); // Cast Adventure side
|
||||||
|
addTarget(playerA, TestPlayer.TARGET_SKIP); // not searching for a Doctor
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertExileCount(playerB, "Twice Upon a Time", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,13 +1,21 @@
|
||||||
|
|
||||||
package org.mage.test.cards.triggers;
|
package org.mage.test.cards.triggers;
|
||||||
|
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.cards.ModalDoubleFacedCard;
|
||||||
import mage.constants.PhaseStep;
|
import mage.constants.PhaseStep;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.players.Player;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public class ReturnToHandEffectsTest extends CardTestPlayerBase {
|
public class ReturnToHandEffectsTest extends CardTestPlayerBase {
|
||||||
|
|
@ -80,6 +88,91 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assumes there is exactly 1 permanent with the cardName, and checks its permanent zcc and card zcc
|
||||||
|
*/
|
||||||
|
private void checkZCCPermanent(String info, Player player, Game game, String cardName, int permanentZCC, int cardZCC, boolean checkMDFC, int leftZCC, int rightZCC) {
|
||||||
|
Optional<Permanent> optPermanent = game
|
||||||
|
.getBattlefield()
|
||||||
|
.getAllActivePermanents()
|
||||||
|
.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(p -> p.getName().equals(cardName))
|
||||||
|
.findFirst();
|
||||||
|
if (!optPermanent.isPresent()) {
|
||||||
|
Assert.fail(info + " — no permanent named \"" + cardName + "\" found on battlefield");
|
||||||
|
}
|
||||||
|
Permanent permanent = optPermanent.get();
|
||||||
|
Assert.assertEquals(info + " — permanent zcc for \"" + cardName + "\"", permanentZCC, permanent.getZoneChangeCounter(game));
|
||||||
|
Card card = game.getCard(permanent.getId()).getMainCard();
|
||||||
|
if (card == null) {
|
||||||
|
Assert.fail(info + " — missing card for permanent \"" + cardName + "\"");
|
||||||
|
}
|
||||||
|
Assert.assertEquals(info + " — card zcc for \"" + cardName + "\"", cardZCC, card.getZoneChangeCounter(game));
|
||||||
|
if (checkMDFC) {
|
||||||
|
Assert.assertEquals(info + " — left card zcc for \"" + cardName + "\"", leftZCC, ((ModalDoubleFacedCard) card).getLeftHalfCard().getZoneChangeCounter(game));
|
||||||
|
Assert.assertEquals(info + " — right card zcc for \"" + cardName + "\"", rightZCC, ((ModalDoubleFacedCard) card).getRightHalfCard().getZoneChangeCounter(game));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkZCCNormalPermanent(String info, Player player, Game game, String cardName, int permanentZCC, int cardZCC) {
|
||||||
|
checkZCCPermanent(info, player, game, cardName, permanentZCC, cardZCC, false, cardZCC, cardZCC);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkZCCMDFCPermanent(String info, Player player, Game game, String cardName, int permanentZCC, int mainCardZCC, int leftCardZCC, int rightCardZCC) {
|
||||||
|
checkZCCPermanent(info, player, game, cardName, permanentZCC, mainCardZCC, true, leftCardZCC, rightCardZCC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assumes there is exactly 1 card in player's graveyard with the cardName, and checks its card zcc
|
||||||
|
*/
|
||||||
|
private void checkZCCCardInGraveyard(String info, Player player, Game game, String cardName, int cardZCC) {
|
||||||
|
Optional<Card> optCard = game
|
||||||
|
.getPlayer(player.getId())
|
||||||
|
.getGraveyard()
|
||||||
|
.getCards(game)
|
||||||
|
.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(p -> p.getName().equals(cardName))
|
||||||
|
.findFirst();
|
||||||
|
if (!optCard.isPresent()) {
|
||||||
|
Assert.fail(info + " — no card named \"" + cardName + "\" found in graveyard");
|
||||||
|
}
|
||||||
|
Card card = optCard.get();
|
||||||
|
Assert.assertEquals(info + " — card zcc for \"" + cardName + "\"", cardZCC, card.getZoneChangeCounter(game));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assumes there is exactly 1 card in player's hand with the cardName, and checks its card zcc
|
||||||
|
*/
|
||||||
|
private void checkZCCCardInHand(String info, Player player, Game game, String cardName, int cardZCC, boolean checkMDFC, int leftZCC, int rightZCC) {
|
||||||
|
Optional<Card> optCard = game
|
||||||
|
.getPlayer(player.getId())
|
||||||
|
.getHand()
|
||||||
|
.getCards(game)
|
||||||
|
.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(p -> p.getName().equals(cardName))
|
||||||
|
.findFirst();
|
||||||
|
if (!optCard.isPresent()) {
|
||||||
|
Assert.fail(info + " — no card named \"" + cardName + "\" found in hand");
|
||||||
|
}
|
||||||
|
Card card = optCard.get();
|
||||||
|
Assert.assertEquals(info + " — card zcc for \"" + cardName + "\"", cardZCC, card.getZoneChangeCounter(game));
|
||||||
|
if (checkMDFC) {
|
||||||
|
Assert.assertEquals(info + " — left card zcc for \"" + cardName + "\"", leftZCC, ((ModalDoubleFacedCard) card).getLeftHalfCard().getZoneChangeCounter(game));
|
||||||
|
Assert.assertEquals(info + " — right card zcc for \"" + cardName + "\"", rightZCC, ((ModalDoubleFacedCard) card).getRightHalfCard().getZoneChangeCounter(game));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkZCCNormalCardInHand(String info, Player player, Game game, String cardName, int cardZCC) {
|
||||||
|
checkZCCCardInHand(info, player, game, cardName, cardZCC, false, cardZCC, cardZCC);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkZCCMDFCCardInHand(String info, Player player, Game game, String cardName, int mainZCC, int leftZCC, int rightZCC) {
|
||||||
|
checkZCCCardInHand(info, player, game, cardName, mainZCC, true, leftZCC, rightZCC);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testZendikon() {
|
public void testZendikon() {
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||||
|
|
@ -90,12 +183,17 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mountain");
|
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mountain");
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wind Zendikon", "Mountain");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wind Zendikon", "Mountain");
|
||||||
|
|
||||||
|
runCode("1: check zcc permanent", 1, PhaseStep.BEGIN_COMBAT, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCNormalPermanent(info, player, game, "Mountain", 2, 2));
|
||||||
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Mountain");
|
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Mountain");
|
||||||
|
|
||||||
|
runCode("2: check zcc card", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCNormalCardInHand(info, player, game, "Mountain", 4));
|
||||||
|
|
||||||
setStrictChooseMode(true);
|
setStrictChooseMode(true);
|
||||||
setStopAt(1, PhaseStep.END_TURN);
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
// ZCC is 2 for perm, 3 for card
|
|
||||||
|
|
||||||
assertGraveyardCount(playerA, "Disfigure", 1);
|
assertGraveyardCount(playerA, "Disfigure", 1);
|
||||||
assertGraveyardCount(playerA, "Wind Zendikon", 1);
|
assertGraveyardCount(playerA, "Wind Zendikon", 1);
|
||||||
|
|
@ -114,12 +212,19 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
|
||||||
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tangled Vale");
|
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tangled Vale");
|
||||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wind Zendikon", "Tangled Vale");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wind Zendikon", "Tangled Vale");
|
||||||
|
|
||||||
|
// TODO: investigate why MDFC zcc moves separatedly.
|
||||||
|
runCode("1: check zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCMDFCPermanent(info, player, game, "Tangled Vale", 2, 1, 1, 2));
|
||||||
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Tangled Vale");
|
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Tangled Vale");
|
||||||
|
|
||||||
|
// TODO: investigate why MDFC zcc moves separatedly.
|
||||||
|
runCode("2: check zcc card", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCMDFCCardInHand(info, player, game, "Tangled Florahedron", 2, 2, 4));
|
||||||
|
|
||||||
setStrictChooseMode(true);
|
setStrictChooseMode(true);
|
||||||
setStopAt(1, PhaseStep.END_TURN);
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
// ZCC is 2 for perm, 1 for card (?!)
|
|
||||||
|
|
||||||
assertGraveyardCount(playerA, "Disfigure", 1);
|
assertGraveyardCount(playerA, "Disfigure", 1);
|
||||||
assertGraveyardCount(playerA, "Wind Zendikon", 1);
|
assertGraveyardCount(playerA, "Wind Zendikon", 1);
|
||||||
|
|
@ -138,12 +243,19 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
|
||||||
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Riverglide Pathway");
|
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Riverglide Pathway");
|
||||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wind Zendikon", "Riverglide Pathway");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wind Zendikon", "Riverglide Pathway");
|
||||||
|
|
||||||
|
// TODO: investigate why MDFC zcc moves separatedly.
|
||||||
|
runCode("1: check zcc pre disfigure", 1, PhaseStep.BEGIN_COMBAT, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCMDFCPermanent(info, player, game, "Riverglide Pathway", 2, 1, 2, 1));
|
||||||
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Riverglide Pathway");
|
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Riverglide Pathway");
|
||||||
|
|
||||||
|
// TODO: investigate why MDFC zcc moves separatedly.
|
||||||
|
runCode("2: check zcc post disfigure", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCMDFCCardInHand(info, player, game, "Riverglide Pathway", 2, 4, 2));
|
||||||
|
|
||||||
setStrictChooseMode(true);
|
setStrictChooseMode(true);
|
||||||
setStopAt(1, PhaseStep.END_TURN);
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
// ZCC is 2 for perm, 1 for card (?!)
|
|
||||||
|
|
||||||
assertGraveyardCount(playerA, "Disfigure", 1);
|
assertGraveyardCount(playerA, "Disfigure", 1);
|
||||||
assertGraveyardCount(playerA, "Wind Zendikon", 1);
|
assertGraveyardCount(playerA, "Wind Zendikon", 1);
|
||||||
|
|
@ -162,12 +274,19 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
|
||||||
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lavaglide Pathway");
|
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lavaglide Pathway");
|
||||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wind Zendikon", "Lavaglide Pathway");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wind Zendikon", "Lavaglide Pathway");
|
||||||
|
|
||||||
|
// TODO: investigate why MDFC zcc moves separatedly.
|
||||||
|
runCode("1: check zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCMDFCPermanent(info, player, game, "Lavaglide Pathway", 2, 1, 1, 2));
|
||||||
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Lavaglide Pathway");
|
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Lavaglide Pathway");
|
||||||
|
|
||||||
|
// TODO: investigate why MDFC zcc moves separatedly.
|
||||||
|
runCode("2: check zcc card", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCMDFCCardInHand(info, player, game, "Riverglide Pathway", 2, 2, 4));
|
||||||
|
|
||||||
setStrictChooseMode(true);
|
setStrictChooseMode(true);
|
||||||
setStopAt(1, PhaseStep.END_TURN);
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
// ZCC is 2 for perm, 1 for card (?!)
|
|
||||||
|
|
||||||
assertGraveyardCount(playerA, "Disfigure", 1);
|
assertGraveyardCount(playerA, "Disfigure", 1);
|
||||||
assertGraveyardCount(playerA, "Wind Zendikon", 1);
|
assertGraveyardCount(playerA, "Wind Zendikon", 1);
|
||||||
|
|
@ -186,12 +305,17 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dryad Sophisticate");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dryad Sophisticate");
|
||||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Demonic Vigor", "Dryad Sophisticate");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Demonic Vigor", "Dryad Sophisticate");
|
||||||
|
|
||||||
|
runCode("1: check zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCNormalPermanent(info, player, game, "Dryad Sophisticate", 3, 3));
|
||||||
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Dryad Sophisticate");
|
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Dryad Sophisticate");
|
||||||
|
|
||||||
|
runCode("2: check zcc card", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCNormalCardInHand(info, player, game, "Dryad Sophisticate", 5));
|
||||||
|
|
||||||
setStrictChooseMode(true);
|
setStrictChooseMode(true);
|
||||||
setStopAt(1, PhaseStep.END_TURN);
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
// ZCC is 3 for perm, 4 for card
|
|
||||||
|
|
||||||
assertGraveyardCount(playerA, "Disfigure", 1);
|
assertGraveyardCount(playerA, "Disfigure", 1);
|
||||||
assertGraveyardCount(playerA, "Demonic Vigor", 1);
|
assertGraveyardCount(playerA, "Demonic Vigor", 1);
|
||||||
|
|
@ -210,12 +334,19 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tangled Florahedron");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tangled Florahedron");
|
||||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Demonic Vigor", "Tangled Florahedron");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Demonic Vigor", "Tangled Florahedron");
|
||||||
|
|
||||||
|
// TODO: investigate why MDFC zcc moves separatedly.
|
||||||
|
runCode("1: check zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCMDFCPermanent(info, player, game, "Tangled Florahedron", 3, 2, 3, 2));
|
||||||
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Tangled Florahedron");
|
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Tangled Florahedron");
|
||||||
|
|
||||||
|
// TODO: investigate why MDFC zcc moves separatedly.
|
||||||
|
runCode("2: check zcc card", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCMDFCCardInHand(info, player, game, "Tangled Florahedron", 3, 5, 3));
|
||||||
|
|
||||||
setStrictChooseMode(true);
|
setStrictChooseMode(true);
|
||||||
setStopAt(1, PhaseStep.END_TURN);
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
// ZCC is 3 for perm, 2 for card (?!)
|
|
||||||
|
|
||||||
assertGraveyardCount(playerA, "Disfigure", 1);
|
assertGraveyardCount(playerA, "Disfigure", 1);
|
||||||
assertGraveyardCount(playerA, "Demonic Vigor", 1);
|
assertGraveyardCount(playerA, "Demonic Vigor", 1);
|
||||||
|
|
@ -234,18 +365,26 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dryad Sophisticate");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dryad Sophisticate");
|
||||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Demonic Vigor", "Dryad Sophisticate");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Demonic Vigor", "Dryad Sophisticate");
|
||||||
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Dryad Sophisticate");
|
|
||||||
|
runCode("1: check zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCNormalPermanent(info, player, game, "Dryad Sophisticate", 3, 3));
|
||||||
|
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Dryad Sophisticate", true);
|
||||||
|
runCode("2: check zcc card", 1, PhaseStep.BEGIN_COMBAT, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCNormalCardInHand(info, player, game, "Dryad Sophisticate", 5));
|
||||||
|
|
||||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Dryad Sophisticate");
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Dryad Sophisticate");
|
||||||
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
|
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Demonic Vigor", "Dryad Sophisticate");
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Demonic Vigor", "Dryad Sophisticate");
|
||||||
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
|
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Disfigure", "Dryad Sophisticate");
|
runCode("3: check zcc", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCNormalPermanent(info, player, game, "Dryad Sophisticate", 7, 7));
|
||||||
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Disfigure", "Dryad Sophisticate", true);
|
||||||
|
runCode("4: check zcc card", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCNormalCardInHand(info, player, game, "Dryad Sophisticate", 9));
|
||||||
|
|
||||||
setStrictChooseMode(true);
|
setStrictChooseMode(true);
|
||||||
setStopAt(1, PhaseStep.END_TURN);
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
// ZCC is 7 for perm, 8 for card
|
|
||||||
|
|
||||||
assertGraveyardCount(playerA, "Disfigure", 2);
|
assertGraveyardCount(playerA, "Disfigure", 2);
|
||||||
assertGraveyardCount(playerA, "Demonic Vigor", 2);
|
assertGraveyardCount(playerA, "Demonic Vigor", 2);
|
||||||
|
|
@ -264,18 +403,29 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tangled Florahedron");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tangled Florahedron");
|
||||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Demonic Vigor", "Tangled Florahedron");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Demonic Vigor", "Tangled Florahedron");
|
||||||
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Tangled Florahedron");
|
// TODO: investigate why MDFC zcc moves separatedly.
|
||||||
|
runCode("1: check zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCMDFCPermanent(info, player, game, "Tangled Florahedron", 3, 2, 3, 2));
|
||||||
|
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Tangled Florahedron", true);
|
||||||
|
// TODO: investigate why MDFC zcc moves separatedly.
|
||||||
|
runCode("2: check zcc card", 1, PhaseStep.BEGIN_COMBAT, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCMDFCCardInHand(info, player, game, "Tangled Florahedron", 3, 5, 3));
|
||||||
|
|
||||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Tangled Florahedron");
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Tangled Florahedron");
|
||||||
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
|
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Demonic Vigor", "Tangled Florahedron");
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Demonic Vigor", "Tangled Florahedron", true);
|
||||||
|
// TODO: investigate why MDFC zcc moves separatedly.
|
||||||
|
runCode("3: check zcc", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCMDFCPermanent(info, player, game, "Tangled Florahedron", 7, 4, 7, 4));
|
||||||
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
|
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Disfigure", "Tangled Florahedron");
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Disfigure", "Tangled Florahedron", true);
|
||||||
|
// TODO: investigate why MDFC zcc moves separatedly.
|
||||||
|
runCode("4: check zcc card", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCMDFCCardInHand(info, player, game, "Tangled Florahedron", 5, 9, 5));
|
||||||
|
|
||||||
setStrictChooseMode(true);
|
setStrictChooseMode(true);
|
||||||
setStopAt(1, PhaseStep.END_TURN);
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
// ZCC is 7 for perm, 4 for card (?!)
|
|
||||||
|
|
||||||
assertGraveyardCount(playerA, "Disfigure", 2);
|
assertGraveyardCount(playerA, "Disfigure", 2);
|
||||||
assertGraveyardCount(playerA, "Demonic Vigor", 2);
|
assertGraveyardCount(playerA, "Demonic Vigor", 2);
|
||||||
|
|
@ -291,22 +441,30 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
|
||||||
addCard(Zone.HAND, playerA, "Demonic Vigor");
|
addCard(Zone.HAND, playerA, "Demonic Vigor");
|
||||||
addCard(Zone.HAND, playerA, "Disfigure");
|
addCard(Zone.HAND, playerA, "Disfigure");
|
||||||
addCard(Zone.HAND, playerA, "Makeshift Mannequin");
|
addCard(Zone.HAND, playerA, "Makeshift Mannequin");
|
||||||
addCard(Zone.HAND, playerA, "Coat with Venom");
|
addCard(Zone.HAND, playerA, "Coat with Venom"); // target for triggering the Makeshift Mannequin's sacrifice
|
||||||
setStrictChooseMode(true);
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Carrion Feeder");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Carrion Feeder");
|
||||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Demonic Vigor", "Carrion Feeder");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Demonic Vigor", "Carrion Feeder", true);
|
||||||
|
runCode("1: check zcc", 1, PhaseStep.PRECOMBAT_MAIN, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCNormalPermanent(info, player, game, "Carrion Feeder", 3, 3));
|
||||||
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Carrion Feeder");
|
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Carrion Feeder");
|
||||||
waitStackResolved(1, PhaseStep.BEGIN_COMBAT, 1);
|
waitStackResolved(1, PhaseStep.BEGIN_COMBAT, 1);
|
||||||
|
runCode("2: check graveyard zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCCardInGraveyard(info, player, game, "Carrion Feeder", 4));
|
||||||
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Makeshift Mannequin", "Carrion Feeder");
|
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Makeshift Mannequin", "Carrion Feeder");
|
||||||
waitStackResolved(1, PhaseStep.BEGIN_COMBAT, 1);
|
waitStackResolved(1, PhaseStep.BEGIN_COMBAT, 1);
|
||||||
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Coat with Venom", "Carrion Feeder");
|
runCode("3: check zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCNormalPermanent(info, player, game, "Carrion Feeder", 5, 5));
|
||||||
|
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Coat with Venom", "Carrion Feeder", true);
|
||||||
|
runCode("4: check graveyard zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
|
||||||
|
(String info, Player player, Game game) -> checkZCCCardInGraveyard(info, player, game, "Carrion Feeder", 6));
|
||||||
|
|
||||||
setStrictChooseMode(true);
|
setStrictChooseMode(true);
|
||||||
setStopAt(1, PhaseStep.END_TURN);
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
// ZCC is 3 for perm, 6 for card, so should not return
|
// Vigor tries to return the Carrion Feeder card with zcc 4, so 6 doesn't return.
|
||||||
|
|
||||||
assertGraveyardCount(playerA, "Disfigure", 1);
|
assertGraveyardCount(playerA, "Disfigure", 1);
|
||||||
assertGraveyardCount(playerA, "Demonic Vigor", 1);
|
assertGraveyardCount(playerA, "Demonic Vigor", 1);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package mage.abilities.effects.common;
|
package mage.abilities.effects.common;
|
||||||
|
|
||||||
import mage.ApprovingObject;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.Mode;
|
import mage.abilities.Mode;
|
||||||
import mage.abilities.effects.ContinuousEffect;
|
import mage.abilities.effects.ContinuousEffect;
|
||||||
|
|
@ -115,8 +114,7 @@ public class MayCastTargetCardEffect extends OneShotEffect {
|
||||||
|
|
||||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||||
boolean noMana = manaAdjustment == CastManaAdjustment.WITHOUT_PAYING_MANA_COST;
|
boolean noMana = manaAdjustment == CastManaAdjustment.WITHOUT_PAYING_MANA_COST;
|
||||||
controller.cast(controller.chooseAbilityForCast(card, game, noMana),
|
CardUtil.castSingle(controller, source, game, card, noMana, null);
|
||||||
game, noMana, new ApprovingObject(source, game));
|
|
||||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||||
} else {
|
} else {
|
||||||
// TODO: support (and add tests!) for the non-NONE manaAdjustment
|
// TODO: support (and add tests!) for the non-NONE manaAdjustment
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package mage.abilities.effects.common.replacement;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.ReplacementEffectImpl;
|
import mage.abilities.effects.ReplacementEffectImpl;
|
||||||
|
import mage.cards.Card;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
|
|
@ -50,9 +51,21 @@ public class ThatSpellGraveyardExileReplacementEffect extends ReplacementEffectI
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||||
return zEvent.getToZone() == Zone.GRAVEYARD
|
if (zEvent.getToZone() != Zone.GRAVEYARD) {
|
||||||
&& zEvent.getTargetId().equals(((FixedTarget) getTargetPointer()).getTarget())
|
return false;
|
||||||
&& ((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1
|
}
|
||||||
== game.getState().getZoneChangeCounter(zEvent.getTargetId());
|
Card cardMoving = game.getCard(zEvent.getTargetId());
|
||||||
|
Card cardTarget = game.getCard(((FixedTarget) getTargetPointer()).getTarget());
|
||||||
|
if (cardMoving == null || cardTarget == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// for MDFC.
|
||||||
|
Card mainCardMoving = cardMoving.getMainCard();
|
||||||
|
Card mainCardTarget = cardTarget.getMainCard();
|
||||||
|
return mainCardMoving != null
|
||||||
|
&& mainCardTarget != null
|
||||||
|
&& mainCardMoving.getId().equals(mainCardTarget.getId())
|
||||||
|
&& ((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1
|
||||||
|
== game.getState().getZoneChangeCounter(mainCardMoving.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,8 @@ public abstract class AdventureCard extends CardImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean moveToZone(Zone toZone, Ability source, Game game, boolean flag, List<UUID> appliedEffects) {
|
public boolean moveToZone(Zone toZone, Ability source, Game game, boolean flag, List<UUID> appliedEffects) {
|
||||||
if (super.moveToZone(toZone, source, game, flag, appliedEffects)) {
|
if (super.moveToZone(toZone, source, game, flag, appliedEffects)) {
|
||||||
game.getState().setZone(getSpellCard().getId(), toZone);
|
Zone currentZone = game.getState().getZone(getId());
|
||||||
|
game.getState().setZone(getSpellCard().getId(), currentZone);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,8 @@ public abstract class ModalDoubleFacedCard extends CardImpl implements CardWithH
|
||||||
@Override
|
@Override
|
||||||
public boolean moveToZone(Zone toZone, Ability source, Game game, boolean flag, List<UUID> appliedEffects) {
|
public boolean moveToZone(Zone toZone, Ability source, Game game, boolean flag, List<UUID> appliedEffects) {
|
||||||
if (super.moveToZone(toZone, source, game, flag, appliedEffects)) {
|
if (super.moveToZone(toZone, source, game, flag, appliedEffects)) {
|
||||||
setSideZones(toZone, game);
|
Zone currentZone = game.getState().getZone(getId());
|
||||||
|
setSideZones(currentZone, game);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -131,7 +132,8 @@ public abstract class ModalDoubleFacedCard extends CardImpl implements CardWithH
|
||||||
@Override
|
@Override
|
||||||
public boolean moveToExile(UUID exileId, String name, Ability source, Game game, List<UUID> appliedEffects) {
|
public boolean moveToExile(UUID exileId, String name, Ability source, Game game, List<UUID> appliedEffects) {
|
||||||
if (super.moveToExile(exileId, name, source, game, appliedEffects)) {
|
if (super.moveToExile(exileId, name, source, game, appliedEffects)) {
|
||||||
setSideZones(Zone.EXILED, game);
|
Zone currentZone = game.getState().getZone(getId());
|
||||||
|
setSideZones(currentZone, game);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -233,10 +235,12 @@ public abstract class ModalDoubleFacedCard extends CardImpl implements CardWithH
|
||||||
case MODAL_RIGHT:
|
case MODAL_RIGHT:
|
||||||
return this.rightHalfCard.cast(game, fromZone, ability, controllerId);
|
return this.rightHalfCard.cast(game, fromZone, ability, controllerId);
|
||||||
default:
|
default:
|
||||||
if (this.leftHalfCard.getSpellAbility() != null)
|
if (this.leftHalfCard.getSpellAbility() != null) {
|
||||||
this.leftHalfCard.getSpellAbility().setControllerId(controllerId);
|
this.leftHalfCard.getSpellAbility().setControllerId(controllerId);
|
||||||
if (this.rightHalfCard.getSpellAbility() != null)
|
}
|
||||||
|
if (this.rightHalfCard.getSpellAbility() != null) {
|
||||||
this.rightHalfCard.getSpellAbility().setControllerId(controllerId);
|
this.rightHalfCard.getSpellAbility().setControllerId(controllerId);
|
||||||
|
}
|
||||||
return super.cast(game, fromZone, ability, controllerId);
|
return super.cast(game, fromZone, ability, controllerId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,8 +77,9 @@ public abstract class SplitCard extends CardImpl implements CardWithHalves {
|
||||||
@Override
|
@Override
|
||||||
public boolean moveToZone(Zone toZone, Ability source, Game game, boolean flag, List<UUID> appliedEffects) {
|
public boolean moveToZone(Zone toZone, Ability source, Game game, boolean flag, List<UUID> appliedEffects) {
|
||||||
if (super.moveToZone(toZone, source, game, flag, appliedEffects)) {
|
if (super.moveToZone(toZone, source, game, flag, appliedEffects)) {
|
||||||
game.getState().setZone(getLeftHalfCard().getId(), toZone);
|
Zone currentZone = game.getState().getZone(getId());
|
||||||
game.getState().setZone(getRightHalfCard().getId(), toZone);
|
game.getState().setZone(getLeftHalfCard().getId(), currentZone);
|
||||||
|
game.getState().setZone(getRightHalfCard().getId(), currentZone);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -1494,6 +1494,10 @@ public final class CardUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void castSingle(Player player, Ability source, Game game, Card card, ManaCostsImpl<ManaCost> manaCost) {
|
public static void castSingle(Player player, Ability source, Game game, Card card, ManaCostsImpl<ManaCost> manaCost) {
|
||||||
|
castSingle(player, source, game, card, false, manaCost);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void castSingle(Player player, Ability source, Game game, Card card, boolean noMana, ManaCostsImpl<ManaCost> manaCost) {
|
||||||
// handle split-cards
|
// handle split-cards
|
||||||
if (card instanceof SplitCard) {
|
if (card instanceof SplitCard) {
|
||||||
SplitCardHalf leftHalfCard = ((SplitCard) card).getLeftHalfCard();
|
SplitCardHalf leftHalfCard = ((SplitCard) card).getLeftHalfCard();
|
||||||
|
|
@ -1560,8 +1564,8 @@ public final class CardUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
// cast it
|
// cast it
|
||||||
player.cast(player.chooseAbilityForCast(card.getMainCard(), game, false),
|
player.cast(player.chooseAbilityForCast(card.getMainCard(), game, noMana),
|
||||||
game, false, new ApprovingObject(source, game));
|
game, noMana, new ApprovingObject(source, game));
|
||||||
|
|
||||||
// turn off effect after cast on every possible card-face
|
// turn off effect after cast on every possible card-face
|
||||||
if (card instanceof SplitCard) {
|
if (card instanceof SplitCard) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue