From c5cbdcf68fcc52c6b9068d52b9ee33d71b57cc0d Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 20 Feb 2018 17:57:23 +0100 Subject: [PATCH] * Fixed some target pointer handling (fixes #4540). --- .../src/mage/cards/a/ActOfAuthority.java | 6 +-- .../src/mage/cards/b/BackFromTheBrink.java | 2 +- .../src/mage/cards/b/BarrinsUnmaking.java | 6 +-- Mage.Sets/src/mage/cards/m/MimicVat.java | 34 +++++++-------- .../mage/test/cards/copy/MimicVatTest.java | 43 +++++++++++++++++++ 5 files changed, 66 insertions(+), 25 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/ActOfAuthority.java b/Mage.Sets/src/mage/cards/a/ActOfAuthority.java index 3a0f108245a..913dc43fbba 100644 --- a/Mage.Sets/src/mage/cards/a/ActOfAuthority.java +++ b/Mage.Sets/src/mage/cards/a/ActOfAuthority.java @@ -27,6 +27,7 @@ */ package mage.cards.a; +import java.util.UUID; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; @@ -44,8 +45,6 @@ import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; -import java.util.UUID; - /** * * @author LevelX2 @@ -53,8 +52,7 @@ import java.util.UUID; public class ActOfAuthority extends CardImpl { public ActOfAuthority(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}{W}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{W}"); // When Act of Authority enters the battlefield, you may exile target artifact or enchantment. Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetEffect(), true); diff --git a/Mage.Sets/src/mage/cards/b/BackFromTheBrink.java b/Mage.Sets/src/mage/cards/b/BackFromTheBrink.java index 6e92e76df4d..b887c7b5a27 100644 --- a/Mage.Sets/src/mage/cards/b/BackFromTheBrink.java +++ b/Mage.Sets/src/mage/cards/b/BackFromTheBrink.java @@ -103,7 +103,7 @@ class BackFromTheBrinkCost extends CostImpl { if (controller != null) { Card card = controller.getGraveyard().get(targets.getFirstTarget(), game); if (card != null && controller.moveCards(card, Zone.EXILED, ability, game)) { - ability.getEffects().get(0).setTargetPointer(new FixedTarget(card.getId())); + ability.getEffects().get(0).setTargetPointer(new FixedTarget(card.getId(), game.getState().getZoneChangeCounter(card.getId()))); paid = card.getManaCost().pay(ability, game, sourceId, controllerId, noMana); } } diff --git a/Mage.Sets/src/mage/cards/b/BarrinsUnmaking.java b/Mage.Sets/src/mage/cards/b/BarrinsUnmaking.java index 2ef729a53cc..ec6af647eea 100644 --- a/Mage.Sets/src/mage/cards/b/BarrinsUnmaking.java +++ b/Mage.Sets/src/mage/cards/b/BarrinsUnmaking.java @@ -52,7 +52,7 @@ public class BarrinsUnmaking extends CardImpl { public BarrinsUnmaking(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); - // Return target permanent to its owner's hand if that permanent shares a color with the most common color among all permanents or a color tied for most common. + // Return target permanent to its owner's hand if that permanent shares a color with the most common color among all permanents or a color tied for most common. this.getSpellAbility().addEffect(new BarrinsUnmakingEffect()); this.getSpellAbility().addTarget(new TargetPermanent()); } @@ -85,12 +85,12 @@ class BarrinsUnmakingEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getFirstTarget()); + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (permanent != null) { Condition condition = new MostCommonColorCondition(permanent.getColor(game)); if (condition.apply(game, source)) { Effect effect = new ReturnToHandTargetEffect(); - effect.setTargetPointer(new FixedTarget(permanent.getId())); + effect.setTargetPointer(new FixedTarget(permanent, game)); return effect.apply(game, source); } } diff --git a/Mage.Sets/src/mage/cards/m/MimicVat.java b/Mage.Sets/src/mage/cards/m/MimicVat.java index 8fd4c37ba9d..9f5b5636112 100644 --- a/Mage.Sets/src/mage/cards/m/MimicVat.java +++ b/Mage.Sets/src/mage/cards/m/MimicVat.java @@ -38,8 +38,8 @@ import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbil import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.CreateTokenCopyTargetEffect; +import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -122,7 +122,7 @@ class MimicVatTriggeredAbility extends TriggeredAbilityImpl { && !(permanent instanceof PermanentToken) && permanent.isCreature()) { - getEffects().get(0).setTargetPointer(new FixedTarget(permanent.getId())); + getEffects().get(0).setTargetPointer(new FixedTarget(permanent.getId(), game)); return true; } return false; @@ -152,22 +152,22 @@ class MimicVatEffect extends OneShotEffect { if (controller == null || permanent == null) { return false; } - // return older cards to graveyard - Set toGraveyard = new HashSet<>(); - for (UUID imprintedId : permanent.getImprinted()) { - Card card = game.getCard(imprintedId); - if (card != null) { - toGraveyard.add(card); - } - } - controller.moveCards(toGraveyard, Zone.GRAVEYARD, source, game); - permanent.clearImprinted(game); - // Imprint a new one - Card card = game.getCard(getTargetPointer().getFirst(game, source)); - if (card != null) { - controller.moveCardsToExile(card, source, game, true, source.getSourceId(), permanent.getName() + " (Imprint)"); - permanent.imprint(card.getId(), game); + Card newCard = game.getCard(getTargetPointer().getFirst(game, source)); + if (newCard != null) { + // return older cards to graveyard + Set toGraveyard = new HashSet<>(); + for (UUID imprintedId : permanent.getImprinted()) { + Card card = game.getCard(imprintedId); + if (card != null) { + toGraveyard.add(card); + } + } + controller.moveCards(toGraveyard, Zone.GRAVEYARD, source, game); + permanent.clearImprinted(game); + + controller.moveCardsToExile(newCard, source, game, true, source.getSourceId(), permanent.getName() + " (Imprint)"); + permanent.imprint(newCard.getId(), game); } return true; diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/MimicVatTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/MimicVatTest.java index b708a3d6c9a..73f7b9eacb9 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/MimicVatTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/MimicVatTest.java @@ -111,4 +111,47 @@ public class MimicVatTest extends CardTestPlayerBase { } + /** + * Player A has Mimic Vat and plays Sidisi, Undead Vizier and exploits. + * Player N responds to Mimic Vat Trigger with Shred Memory, exiling Sidisi. + * Sidisi gets exiled but then xmage allows player A to imprint the + * creature, which shouldn't be possible. + */ + @Test + public void TestExileFails() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + // Imprint - Whenever a nontoken creature dies, you may exile that card. If you do, return each other card exiled with Mimic Vat to its owner's graveyard. + // {3}, {T}: Create a token that's a copy of a card exiled with Mimic Vat. It gains haste. Exile it at the beginning of the next end step. + addCard(Zone.BATTLEFIELD, playerA, "Mimic Vat", 1); // Artifact {3} + + addCard(Zone.HAND, playerA, "Lightning Bolt", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2); + // Exile up to four target cards from a single graveyard. + // Transmute {1}{B}{B} + addCard(Zone.HAND, playerB, "Shred Memory", 1); // Instant {1}{B} + + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Silvercoat Lion"); + setChoice(playerA, "Yes"); + setChoice(playerA, "Silvercoat Lion"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Shred Memory", "Silvercoat Lion", "Whenever a nontoken creature dies"); + setChoice(playerA, "Yes"); + + activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}, {T}: Create a token that's a copy of a card exiled with "); + setChoice(playerA, "Yes"); + setChoice(playerA, "Silvercoat Lion"); + + setStopAt(3, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Lightning Bolt", 1); + assertGraveyardCount(playerB, "Shred Memory", 1); + + assertExileCount(playerB, "Silvercoat Lion", 1); + assertPermanentCount(playerA, "Silvercoat Lion", 0); + + } }