From b035d85f983ddfd9e39ead3ff084e4c5dd6fd21f Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 16 Mar 2018 15:06:15 +0100 Subject: [PATCH] * Fixed a problem that triggered abilities that face down permanents got from other sourced did not trigger (fixes #4571). --- .../src/mage/cards/e/EndlessWhispers.java | 2 +- .../cards/abilities/keywords/MorphTest.java | 41 +++++++++++++++++++ .../mage/abilities/TriggeredAbilities.java | 31 ++++++++------ 3 files changed, 60 insertions(+), 14 deletions(-) diff --git a/Mage.Sets/src/mage/cards/e/EndlessWhispers.java b/Mage.Sets/src/mage/cards/e/EndlessWhispers.java index 36e78b8071d..c7976f063ea 100644 --- a/Mage.Sets/src/mage/cards/e/EndlessWhispers.java +++ b/Mage.Sets/src/mage/cards/e/EndlessWhispers.java @@ -56,7 +56,7 @@ import mage.target.common.TargetOpponent; public class EndlessWhispers extends CardImpl { public EndlessWhispers(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}"); // Each creature has "When this creature dies, choose target opponent. That player puts this card from its owner's graveyard onto the battlefield under his or her control at the beginning of the next end step." DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnSourceToBattlefieldEffect()); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java index 8c8733d57dc..045c436d8e4 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java @@ -853,4 +853,45 @@ public class MorphTest extends CardTestPlayerBase { assertTappedCount("Island", true, 3); } + + /** + * If you have Endless Whispers in play and a morph creature dies, it should + * be returned to play face up at end of turn under the control of an + * opponent. + */ + @Test + public void testMorphEndlessWhispers() { + /* + Quicksilver Dragon {4}{U}{U} + Creature - Dragon + 5/5 + Flying + {U}: If target spell has only one target and that target is Quicksilver Dragon, change that spell's target to another creature. + Morph {4}{U} + */ + addCard(Zone.HAND, playerA, "Quicksilver Dragon"); + addCard(Zone.BATTLEFIELD, playerA, "Island", 3); + + // Each creature has "When this creature dies, choose target opponent. That player puts this card from its owner's graveyard + // onto the battlefield under his or her control at the beginning of the next end step." + addCard(Zone.BATTLEFIELD, playerA, "Endless Whispers", 1); + + addCard(Zone.HAND, playerB, "Lightning Bolt"); + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Quicksilver Dragon"); + setChoice(playerA, "Yes"); // cast it face down as 2/2 creature + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", ""); + + setStopAt(2, PhaseStep.UPKEEP); + execute(); + + assertGraveyardCount(playerB, "Lightning Bolt", 1); + assertGraveyardCount(playerA, "Quicksilver Dragon", 0); + + assertPermanentCount(playerA, "Quicksilver Dragon", 0); + assertPermanentCount(playerB, "Quicksilver Dragon", 1); + + } } diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbilities.java b/Mage/src/main/java/mage/abilities/TriggeredAbilities.java index 5feca7f7afb..c04367f5576 100644 --- a/Mage/src/main/java/mage/abilities/TriggeredAbilities.java +++ b/Mage/src/main/java/mage/abilities/TriggeredAbilities.java @@ -28,6 +28,8 @@ */ package mage.abilities; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import mage.MageObject; import mage.constants.Zone; import mage.game.Game; @@ -36,15 +38,12 @@ import mage.game.events.NumberOfTriggersEvent; import mage.game.permanent.Permanent; import mage.game.stack.Spell; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - /** * @author BetaSteward_at_googlemail.com - *

- * This class uses ConcurrentHashMap to avoid ConcurrentModificationExceptions. - * See ticket https://github.com/magefree/mage/issues/966 and - * https://github.com/magefree/mage/issues/473 + *

+ * This class uses ConcurrentHashMap to avoid ConcurrentModificationExceptions. + * See ticket https://github.com/magefree/mage/issues/966 and + * https://github.com/magefree/mage/issues/473 */ public class TriggeredAbilities extends ConcurrentHashMap { @@ -63,7 +62,7 @@ public class TriggeredAbilities extends ConcurrentHashMap it = this.values().iterator(); it.hasNext(); ) { + for (Iterator it = this.values().iterator(); it.hasNext();) { TriggeredAbility ability = it.next(); if (ability instanceof StateTriggeredAbility && ((StateTriggeredAbility) ability).canTrigger(game)) { checkTrigger(ability, null, game); @@ -72,7 +71,7 @@ public class TriggeredAbilities extends ConcurrentHashMap it = this.values().iterator(); it.hasNext(); ) { + for (Iterator it = this.values().iterator(); it.hasNext();) { TriggeredAbility ability = it.next(); if (ability.checkEventType(event, game)) { checkTrigger(ability, event, game); @@ -98,7 +97,10 @@ public class TriggeredAbilities extends ConcurrentHashMap so it should work + && !ability.getWorksFaceDown()) { // the ability is declared to work also face down + // Not all triggered abilities of face down creatures work if they are faced down return; } controllerSet = true; @@ -130,8 +132,8 @@ public class TriggeredAbilities extends ConcurrentHashMap key.endsWith(sourceId.toString())); } @@ -171,6 +172,10 @@ public class TriggeredAbilities extends ConcurrentHashMap