diff --git a/Mage.Sets/src/mage/cards/d/DeepAnalysis.java b/Mage.Sets/src/mage/cards/d/DeepAnalysis.java index 7d186198370..2ad4b705318 100644 --- a/Mage.Sets/src/mage/cards/d/DeepAnalysis.java +++ b/Mage.Sets/src/mage/cards/d/DeepAnalysis.java @@ -28,9 +28,6 @@ package mage.cards.d; import java.util.UUID; -import mage.abilities.costs.Cost; -import mage.abilities.costs.Costs; -import mage.abilities.costs.CostsImpl; import mage.abilities.costs.common.PayLifeCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.DrawCardTargetEffect; @@ -48,18 +45,16 @@ import mage.target.TargetPlayer; public class DeepAnalysis extends CardImpl { public DeepAnalysis(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{U}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U}"); // Target player draws two cards. this.getSpellAbility().addEffect(new DrawCardTargetEffect(2)); this.getSpellAbility().addTarget(new TargetPlayer()); // Flashback-{1}{U}, Pay 3 life. - Costs costs = new CostsImpl<>(); - costs.add(new ManaCostsImpl("{1}{U}")); - costs.add(new PayLifeCost(3)); - this.addAbility(new FlashbackAbility(costs, TimingRule.SORCERY)); + FlashbackAbility ability = new FlashbackAbility(new ManaCostsImpl("{1}{U}"), TimingRule.SORCERY); + ability.addCost(new PayLifeCost(3)); + this.addAbility(ability); } public DeepAnalysis(final DeepAnalysis card) { diff --git a/Mage.Sets/src/mage/cards/m/MizzixOfTheIzmagnus.java b/Mage.Sets/src/mage/cards/m/MizzixOfTheIzmagnus.java index d1e431b69cf..ce9a178b8d1 100644 --- a/Mage.Sets/src/mage/cards/m/MizzixOfTheIzmagnus.java +++ b/Mage.Sets/src/mage/cards/m/MizzixOfTheIzmagnus.java @@ -41,7 +41,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.counters.CounterType; -import mage.filter.common.FilterInstantOrSorceryCard; +import mage.filter.StaticFilters; import mage.filter.common.FilterInstantOrSorcerySpell; import mage.filter.predicate.Predicate; import mage.game.Game; @@ -62,7 +62,7 @@ public class MizzixOfTheIzmagnus extends CardImpl { } public MizzixOfTheIzmagnus(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{R}"); addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.GOBLIN); this.subtype.add(SubType.WIZARD); @@ -136,11 +136,11 @@ class MizzixOfTheIzmagnusCostReductionEffect extends CostModificationEffectImpl if (abilityToModify instanceof SpellAbility && abilityToModify.getControllerId().equals(source.getControllerId())) { Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); if (spell != null) { - return new FilterInstantOrSorceryCard().match(spell, source.getSourceId(), source.getControllerId(), game); - } else { - // used at least for flashback ability because Flashback ability doesn't use stack or for getPlayables where spell is not cast yet + return StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY.match(spell, source.getSourceId(), source.getControllerId(), game); + } else if (((SpellAbility) abilityToModify).isCheckPlayableMode()) { + // Spell is not on the stack yet, but possible playable spells are determined Card sourceCard = game.getCard(abilityToModify.getSourceId()); - return sourceCard != null && new FilterInstantOrSorceryCard().match(sourceCard, source.getSourceId(), source.getControllerId(), game); + return sourceCard != null && StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY.match(sourceCard, source.getSourceId(), source.getControllerId(), game); } } return false; 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 02bf64326b3..fd574695830 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 @@ -30,6 +30,7 @@ package org.mage.test.cards.abilities.keywords; import mage.abilities.keyword.TrampleAbility; import mage.constants.PhaseStep; import mage.constants.Zone; +import mage.counters.CounterType; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -580,4 +581,35 @@ public class FlashbackTest extends CardTestPlayerBase { assertLife(playerA, 20); } + + /** + * Test cost reduction with mixed flashback costs + */ + @Test + public void testReduceMixedFlashbackCosts() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 5); + + // Whenever you cast an instant or sorcery spell with converted mana cost greater than the number of experience counters you have, you get an experience counter. + // Instant and sorcery spells you cast cost {1} less to cast for each experience counter you have. + addCard(Zone.BATTLEFIELD, playerA, "Mizzix of the Izmagnus");// 2/2 + + // Target player draws two cards. + // Flashback-{1}{U}, Pay 3 life. + addCard(Zone.HAND, playerA, "Deep Analysis"); // {3}{U} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Deep Analysis"); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Flashback"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Deep Analysis", 0); + assertExileCount(playerA, "Deep Analysis", 1); + assertHandCount(playerA, 4); + + assertCounterCount(playerA, CounterType.EXPERIENCE, 2); + + assertLife(playerA, 17); + + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/MizzixOfTheIzmagnusTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/MizzixOfTheIzmagnusTest.java index 3d5c58d10b8..4aa99bbe7f6 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/MizzixOfTheIzmagnusTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/MizzixOfTheIzmagnusTest.java @@ -120,4 +120,36 @@ public class MizzixOfTheIzmagnusTest extends CardTestPlayerBase { assertLife(playerB, 17); } + + /** + * Test to reduce Flashback costs + */ + @Test + public void testReduceFlashbackCosts() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + + // Whenever you cast an instant or sorcery spell with converted mana cost greater than the number of experience counters you have, you get an experience counter. + // Instant and sorcery spells you cast cost {1} less to cast for each experience counter you have. + addCard(Zone.BATTLEFIELD, playerA, "Mizzix of the Izmagnus");// 2/2 + + // Engulfing Flames deals 1 damage to target creature. It can't be regenerated this turn. + // Flashback {3}{R} (You may cast this card from your graveyard for its flashback cost. Then exile it.) + addCard(Zone.HAND, playerA, "Engulfing Flames"); // {R} + + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion");// 2/2 + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Engulfing Flames", "Silvercoat Lion"); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Flashback", "Silvercoat Lion"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Engulfing Flames", 0); + assertExileCount(playerA, "Engulfing Flames", 1); + + assertGraveyardCount(playerB, "Silvercoat Lion", 1); + + assertCounterCount(playerA, CounterType.EXPERIENCE, 1); + + } } diff --git a/Mage/src/main/java/mage/filter/StaticFilters.java b/Mage/src/main/java/mage/filter/StaticFilters.java index 27a367e88cb..97546761d2e 100644 --- a/Mage/src/main/java/mage/filter/StaticFilters.java +++ b/Mage/src/main/java/mage/filter/StaticFilters.java @@ -74,6 +74,12 @@ public final class StaticFilters { FILTER_CARD_A_NON_LAND.setLockedFilter(true); } + public static final FilterInstantOrSorceryCard FILTER_CARD_INSTANT_OR_SORCERY = new FilterInstantOrSorceryCard(); + + static { + FILTER_CARD_INSTANT_OR_SORCERY.setLockedFilter(true); + } + public static final FilterPermanent FILTER_PERMANENT = new FilterPermanent(); static { @@ -236,7 +242,7 @@ public final class StaticFilters { static { FILTER_BASIC_LAND_CARD.setLockedFilter(true); } - + // Used for sacrifice targets that don't need the "you control" text public static final FilterControlledLandPermanent FILTER_CONTROLLED_LAND_SHORT_TEXT = new FilterControlledLandPermanent("a land");