diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/FlashbackTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/FlashbackTest.java index 946ded1e947..a6d6538bf99 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/FlashbackTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/FlashbackTest.java @@ -73,70 +73,68 @@ public class FlashbackTest extends CardTestPlayerBase { assertExileCount("Fracturing Gust", 1); } - /** - * - * Test Granting Flashback to spells with X in manacost which have targeting requirements depending on the choice of X - * + /** + * + * Test Granting Flashback to spells with X in manacost which have targeting + * requirements depending on the choice of X + * * Specific instance: Snapcaster Mage granting Flashback to Repeal */ @Test - public void testSnapcasterMageWithRepeal(){ + public void testSnapcasterMageWithRepeal() { addCard(Zone.BATTLEFIELD, playerA, "Island", 5); - addCard(Zone.HAND, playerA, "Snapcaster Mage",1); - addCard(Zone.GRAVEYARD, playerA, "Repeal",1); + addCard(Zone.HAND, playerA, "Snapcaster Mage", 1); + addCard(Zone.GRAVEYARD, playerA, "Repeal", 1); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage"); - setChoice(playerA, "Repeal"); - + setChoice(playerA, "Repeal"); + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback"); setChoice(playerA, "X=2"); addTarget(playerA, "Snapcaster Mage"); - + setStopAt(1, PhaseStep.END_TURN); - + execute(); - + assertPermanentCount(playerA, "Snapcaster Mage", 0); assertGraveyardCount(playerA, "Repeal", 0); assertExileCount("Repeal", 1); - + } - + /** - * - * Test Granting Flashback to spells with X in mana cost, where X has no influence on targeting requirements - * - * Specific instance: - * Snapcaser Mage granting Flashback to Blaze + * + * Test Granting Flashback to spells with X in mana cost, where X has no + * influence on targeting requirements + * + * Specific instance: Snapcaser Mage granting Flashback to Blaze */ @Test - public void testSnapcasterMageWithBlaze(){ + public void testSnapcasterMageWithBlaze() { addCard(Zone.BATTLEFIELD, playerA, "Island", 5); addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); - - addCard(Zone.HAND, playerA, "Snapcaster Mage",1); - addCard(Zone.GRAVEYARD, playerA, "Blaze",1); - + addCard(Zone.HAND, playerA, "Snapcaster Mage", 1); + addCard(Zone.GRAVEYARD, playerA, "Blaze", 1); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage"); - setChoice(playerA, "B laze"); - + setChoice(playerA, "B laze"); + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback"); setChoice(playerA, "X=1"); addTarget(playerA, "Snapcaster Mage"); - + setStopAt(1, PhaseStep.END_TURN); - + execute(); - + assertPermanentCount(playerA, "Snapcaster Mage", 0); assertGraveyardCount(playerA, "Blaze", 0); assertExileCount("Blaze", 1); - + } - - + /** * My opponent put Iona on the battlefield using Unburial Rites, but my game * log didn't show me the color he has chosen. @@ -369,4 +367,26 @@ public class FlashbackTest extends CardTestPlayerBase { } + /** + * Deep Analysis doesn't cost mana when flashbacked. + */ + @Test + public void testCombinedFlashbackCosts() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 2); + // Target player draws two cards. + // Flashback-{1}{U}, Pay 3 life. + addCard(Zone.GRAVEYARD, playerA, "Deep Analysis", 1); // Sorcery {3}{U} + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Flashback"); // Flashback Deep Analysis + addTarget(playerA, playerA); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Deep Analysis", 0); + assertLife(playerA, 17); + assertLife(playerB, 20); + assertHandCount(playerA, 2); + assertTappedCount("Island", true, 2); + + } } diff --git a/Mage/src/main/java/mage/abilities/keyword/FlashbackAbility.java b/Mage/src/main/java/mage/abilities/keyword/FlashbackAbility.java index 0ce6b3c490b..c32dc61b568 100644 --- a/Mage/src/main/java/mage/abilities/keyword/FlashbackAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/FlashbackAbility.java @@ -27,11 +27,14 @@ */ package mage.abilities.keyword; +import java.util.Iterator; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.costs.Cost; +import mage.abilities.costs.Costs; import mage.abilities.costs.VariableCost; +import mage.abilities.costs.mana.ManaCost; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.ReplacementEffectImpl; @@ -200,9 +203,30 @@ class FlashbackEffect extends OneShotEffect { spellAbility.getManaCosts().clear(); spellAbility.getManaCosts().addAll(source.getManaCosts()); // needed to get e.g. paid costs from Conflagrate + for (Cost cost : source.getCosts()) { - if (!(cost instanceof VariableCost)) { - spellAbility.getCosts().add(cost); + if (cost instanceof Costs) { + Costs listOfcosts = (Costs) cost; + for (Iterator itListOfcosts = listOfcosts.iterator(); itListOfcosts.hasNext();) { + Object singleCost = itListOfcosts.next(); + if (singleCost instanceof ManaCost) { + ((ManaCost) singleCost).clearPaid(); + spellAbility.getManaCosts().add((ManaCost) singleCost); + spellAbility.getManaCostsToPay().add((ManaCost) singleCost); + } else { + spellAbility.getCosts().add((Cost) singleCost); + } + } + + } + + if (!(cost instanceof VariableCost) && !(cost instanceof Costs)) { + if (cost instanceof ManaCost) { + spellAbility.getManaCosts().add((ManaCost) cost); + spellAbility.getManaCostsToPay().add((ManaCost) cost); + } else { + spellAbility.getCosts().add(cost); + } } } if (!game.isSimulation()) { @@ -217,8 +241,10 @@ class FlashbackEffect extends OneShotEffect { return false; } } + return false; } + } class FlashbackReplacementEffect extends ReplacementEffectImpl { diff --git a/Mage/src/main/java/mage/game/stack/Spell.java b/Mage/src/main/java/mage/game/stack/Spell.java index 47cac645506..b6bc9b98356 100644 --- a/Mage/src/main/java/mage/game/stack/Spell.java +++ b/Mage/src/main/java/mage/game/stack/Spell.java @@ -141,16 +141,20 @@ public class Spell extends StackObjImpl implements Card { if (!spellAbilities.get(0).activate(game, noMana)) { return false; } - // if there are more abilities (fused split spell) or first ability added new abilities (splice), activate the additional abilities - boolean ignoreAbility = true; - boolean payNoMana = noMana; - for (SpellAbility spellAbility : spellAbilities) { - // costs for spliced abilities were added to main spellAbility, so pay no mana for spliced abilities - payNoMana |= spellAbility.getSpellAbilityType().equals(SpellAbilityType.SPLICE); - if (ignoreAbility) { - ignoreAbility = false; - } else if (!spellAbility.activate(game, payNoMana)) { - return false; + if (spellAbilities.size() > 1) { + // if there are more abilities (fused split spell) or first ability added new abilities (splice), activate the additional abilities + boolean ignoreAbility = true; + boolean payNoMana = noMana; + for (SpellAbility spellAbility : spellAbilities) { + if (ignoreAbility) { + ignoreAbility = false; + } else { + // costs for spliced abilities were added to main spellAbility, so pay no mana for spliced abilities + payNoMana |= spellAbility.getSpellAbilityType().equals(SpellAbilityType.SPLICE); + if (!spellAbility.activate(game, payNoMana)) { + return false; + } + } } } return true; @@ -490,7 +494,7 @@ public class Spell extends StackObjImpl implements Card { public ObjectColor getColor(Game game) { return color; } - + @Override public ObjectColor getFrameColor(Game game) { return frameColor; @@ -536,7 +540,7 @@ public class Spell extends StackObjImpl implements Card { public MageInt getToughness() { return card.getToughness(); } - + @Override public int getStartingLoyalty() { return card.getStartingLoyalty(); @@ -595,7 +599,7 @@ public class Spell extends StackObjImpl implements Card { public String getTokenSetCode() { return card.getTokenSetCode(); } - + @Override public String getTokenDescriptor() { return card.getTokenDescriptor();