From 36309206a2d45097e35a2ea5ce7ce6a8b4853958 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Wed, 29 Jan 2025 00:42:33 +0400 Subject: [PATCH] Create copy effects - fixed that it can't copy second side of the modal double-faced card (close #11307, close #13269); --- .../ModalDoubleFacedCardsTest.java | 81 +++++++++++++++++++ .../util/functions/CopyTokenFunction.java | 3 +- 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/cost/modaldoublefaced/ModalDoubleFacedCardsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/cost/modaldoublefaced/ModalDoubleFacedCardsTest.java index 7fd088c4ec0..a229bb39472 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/cost/modaldoublefaced/ModalDoubleFacedCardsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/cost/modaldoublefaced/ModalDoubleFacedCardsTest.java @@ -982,6 +982,87 @@ public class ModalDoubleFacedCardsTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Birgi, God of Storytelling", 1); } + @Test + public void test_Copy_TokenFromPermanent_MainSide() { + addCard(Zone.HAND, playerA, "Akoum Warrior", 1); // {5}{R} + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 6); + // + // Demonstrate + // Create a token that's a copy of target permanent you control. + addCard(Zone.HAND, playerA, "Replication Technique", 1); // {4}{U} + addCard(Zone.BATTLEFIELD, playerA, "Island", 5); + + // cast mdf card (main side) + activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}", 6); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Akoum Warrior"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + // copy permanent + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Replication Technique"); + addTarget(playerA, "Akoum Warrior"); // to copy + setChoice(playerA, false); // ignore demonstrate + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + checkPermanentCount("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Akoum Warrior", 2); + runCode("must copy main side", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> { + PermanentToken permanent = (PermanentToken) game.getBattlefield().getAllPermanents() + .stream() + .filter(p -> p.getName().equals("Akoum Warrior")) + .filter(p -> p instanceof PermanentToken) + .findFirst() + .orElse(null); + Assert.assertNotNull(permanent); + Assert.assertEquals(info + " - name", "Akoum Warrior", permanent.getName()); + Assert.assertEquals(info + " - color", "R", permanent.getColor(game).toString()); + Assert.assertEquals(info + " - power", 4, permanent.getPower().getValue()); + Assert.assertEquals(info + " - toughness", 5, permanent.getToughness().getValue()); + Assert.assertEquals(info + " - card type", "[Creature]", permanent.getCardType(game).toString()); + Assert.assertEquals(info + " - card subtype", "[Minotaur, Warrior]", permanent.getSubtype(game).toString()); + }); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + } + + @Test + public void test_Copy_TokenFromPermanent_SecondSide() { + addCard(Zone.HAND, playerA, "Akoum Warrior", 1); + // + // Demonstrate + // Create a token that's a copy of target permanent you control. + addCard(Zone.HAND, playerA, "Replication Technique", 1); // {4}{U} + addCard(Zone.BATTLEFIELD, playerA, "Island", 5); + + // cast mdf card (second side) + playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Akoum Teeth"); + + // copy permanent + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Replication Technique"); + addTarget(playerA, "Akoum Teeth"); // to copy + setChoice(playerA, false); // ignore demonstrate + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + checkPermanentCount("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Akoum Teeth", 2); + runCode("must copy second side", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> { + PermanentToken permanent = (PermanentToken) game.getBattlefield().getAllPermanents() + .stream() + .filter(p -> p.getName().equals("Akoum Teeth")) + .filter(p -> p instanceof PermanentToken) + .findFirst() + .orElse(null); + Assert.assertNotNull(permanent); + Assert.assertEquals(info + " - name", "Akoum Teeth", permanent.getName()); + Assert.assertEquals(info + " - color", "", permanent.getColor(game).toString()); + Assert.assertEquals(info + " - power", 0, permanent.getPower().getValue()); + Assert.assertEquals(info + " - toughness", 0, permanent.getToughness().getValue()); + Assert.assertEquals(info + " - card type", "[Land]", permanent.getCardType(game).toString()); + Assert.assertEquals(info + " - card subtype", "[]", permanent.getSubtype(game).toString()); + }); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + } + @Test public void test_Copy_TokenFromCard_MustIgnoreSecondSide() { // bug: copied tokens of MDF cards has abilities from both sides diff --git a/Mage/src/main/java/mage/util/functions/CopyTokenFunction.java b/Mage/src/main/java/mage/util/functions/CopyTokenFunction.java index c5327cb7326..3b159398037 100644 --- a/Mage/src/main/java/mage/util/functions/CopyTokenFunction.java +++ b/Mage/src/main/java/mage/util/functions/CopyTokenFunction.java @@ -84,7 +84,8 @@ public class CopyTokenFunction { return; } - Card sourceObj = source.getMainCard(); + // must use real card side, e.g. half from MDFC (not main) + Card sourceObj = sourcePermanent.getCard(); target.setCopySourceCard(sourceObj); // main side copyToToken(target, sourceObj, game);