From 4168e2714a5f946846ae59eea9eab40ba3697468 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Mon, 6 Jul 2020 11:17:09 +0400 Subject: [PATCH] Controlled spells gain ability -- fixed that gained cost modification effects doesn't allow to cast cards without mana (example: Inspiring Statuary, see #6698); --- Mage.Sets/src/mage/cards/c/ChiefEngineer.java | 9 ++--- .../src/mage/cards/d/DomriChaosBringer.java | 4 +- .../src/mage/cards/i/InspiringStatuary.java | 9 ++--- .../src/mage/cards/m/MycosynthGolem.java | 9 ++--- .../cards/t/TezzeretMasterOfTheBridge.java | 3 +- .../src/mage/cards/t/TheFirstSliver.java | 4 +- .../src/mage/cards/t/ThrummingStone.java | 10 ++--- .../modification/CostReduceForEachTest.java | 24 ++++++++++++ .../GainAbilityControlledSpellsEffect.java | 37 ++++++++++++++----- 9 files changed, 74 insertions(+), 35 deletions(-) diff --git a/Mage.Sets/src/mage/cards/c/ChiefEngineer.java b/Mage.Sets/src/mage/cards/c/ChiefEngineer.java index b3874a1050a..0ab1bec46fa 100644 --- a/Mage.Sets/src/mage/cards/c/ChiefEngineer.java +++ b/Mage.Sets/src/mage/cards/c/ChiefEngineer.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.continuous.GainAbilityControlledSpellsEffect; @@ -11,10 +9,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.common.FilterArtifactSpell; +import mage.filter.common.FilterArtifactCard; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class ChiefEngineer extends CardImpl { @@ -28,7 +27,7 @@ public final class ChiefEngineer extends CardImpl { this.toughness = new MageInt(3); // Artifact spells you cast have convoke. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledSpellsEffect(new ConvokeAbility(), new FilterArtifactSpell("Artifact spells you cast")))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledSpellsEffect(new ConvokeAbility(), new FilterArtifactCard("Artifact spells you cast")))); } diff --git a/Mage.Sets/src/mage/cards/d/DomriChaosBringer.java b/Mage.Sets/src/mage/cards/d/DomriChaosBringer.java index 5ed58faaa1f..f69f3872ff0 100644 --- a/Mage.Sets/src/mage/cards/d/DomriChaosBringer.java +++ b/Mage.Sets/src/mage/cards/d/DomriChaosBringer.java @@ -17,7 +17,7 @@ import mage.abilities.keyword.RiotAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.FilterSpell; +import mage.filter.FilterCard; import mage.filter.StaticFilters; import mage.filter.predicate.mageobject.CardIdPredicate; import mage.game.Game; @@ -137,7 +137,7 @@ class DomriChaosBringerTriggeredAbility extends DelayedTriggeredAbility { return false; } this.getEffects().clear(); - FilterSpell filter = new FilterSpell(); + FilterCard filter = new FilterCard(); filter.add(new CardIdPredicate(event.getTargetId())); this.addEffect(new GainAbilityControlledSpellsEffect(new RiotAbility(), filter)); return true; diff --git a/Mage.Sets/src/mage/cards/i/InspiringStatuary.java b/Mage.Sets/src/mage/cards/i/InspiringStatuary.java index 104c79b3b61..04471a83bef 100644 --- a/Mage.Sets/src/mage/cards/i/InspiringStatuary.java +++ b/Mage.Sets/src/mage/cards/i/InspiringStatuary.java @@ -1,7 +1,5 @@ - package mage.cards.i; -import java.util.UUID; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.continuous.GainAbilityControlledSpellsEffect; import mage.abilities.keyword.ImproviseAbility; @@ -9,16 +7,17 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; -import mage.filter.FilterSpell; +import mage.filter.FilterCard; import mage.filter.predicate.Predicates; +import java.util.UUID; + /** - * * @author Styxo */ public final class InspiringStatuary extends CardImpl { - private static final FilterSpell filter = new FilterSpell("non-artifact spells you cast"); + private static final FilterCard filter = new FilterCard("non-artifact spells you cast"); static { filter.add(Predicates.not(CardType.ARTIFACT.getPredicate())); diff --git a/Mage.Sets/src/mage/cards/m/MycosynthGolem.java b/Mage.Sets/src/mage/cards/m/MycosynthGolem.java index d9b8d149ceb..9d984922516 100644 --- a/Mage.Sets/src/mage/cards/m/MycosynthGolem.java +++ b/Mage.Sets/src/mage/cards/m/MycosynthGolem.java @@ -1,7 +1,5 @@ - package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.continuous.GainAbilityControlledSpellsEffect; @@ -11,15 +9,16 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.FilterSpell; +import mage.filter.FilterCard; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class MycosynthGolem extends CardImpl { - private static final FilterSpell filter = new FilterSpell("Artifact creature spells"); + private static final FilterCard filter = new FilterCard("Artifact creature spells"); static { filter.add(CardType.ARTIFACT.getPredicate()); diff --git a/Mage.Sets/src/mage/cards/t/TezzeretMasterOfTheBridge.java b/Mage.Sets/src/mage/cards/t/TezzeretMasterOfTheBridge.java index 0b528fc1666..2493c99a923 100644 --- a/Mage.Sets/src/mage/cards/t/TezzeretMasterOfTheBridge.java +++ b/Mage.Sets/src/mage/cards/t/TezzeretMasterOfTheBridge.java @@ -13,7 +13,6 @@ import mage.abilities.keyword.AffinityForArtifactsAbility; import mage.cards.*; import mage.constants.*; import mage.filter.FilterCard; -import mage.filter.FilterSpell; import mage.filter.StaticFilters; import mage.filter.common.FilterArtifactCard; import mage.filter.predicate.Predicates; @@ -28,7 +27,7 @@ import java.util.UUID; */ public final class TezzeretMasterOfTheBridge extends CardImpl { - private static final FilterSpell filter = new FilterSpell("creature and planeswalker spells"); + private static final FilterCard filter = new FilterCard("creature and planeswalker spells"); static { filter.add(Predicates.or( diff --git a/Mage.Sets/src/mage/cards/t/TheFirstSliver.java b/Mage.Sets/src/mage/cards/t/TheFirstSliver.java index 77fc4d84cd3..d3381480e41 100644 --- a/Mage.Sets/src/mage/cards/t/TheFirstSliver.java +++ b/Mage.Sets/src/mage/cards/t/TheFirstSliver.java @@ -9,7 +9,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.filter.FilterSpell; +import mage.filter.FilterCard; import java.util.UUID; @@ -18,7 +18,7 @@ import java.util.UUID; */ public final class TheFirstSliver extends CardImpl { - private static final FilterSpell filter = new FilterSpell("Sliver spells you cast"); + private static final FilterCard filter = new FilterCard("Sliver spells you cast"); static { filter.add(SubType.SLIVER.getPredicate()); diff --git a/Mage.Sets/src/mage/cards/t/ThrummingStone.java b/Mage.Sets/src/mage/cards/t/ThrummingStone.java index b6679721536..26900a31a5e 100644 --- a/Mage.Sets/src/mage/cards/t/ThrummingStone.java +++ b/Mage.Sets/src/mage/cards/t/ThrummingStone.java @@ -1,7 +1,5 @@ - package mage.cards.t; -import java.util.UUID; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.continuous.GainAbilityControlledSpellsEffect; import mage.abilities.keyword.RippleAbility; @@ -10,7 +8,9 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SuperType; import mage.constants.Zone; -import mage.filter.FilterSpell; +import mage.filter.FilterCard; + +import java.util.UUID; /** * @author klayhamn @@ -21,8 +21,8 @@ public final class ThrummingStone extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}"); addSuperType(SuperType.LEGENDARY); - // spells you cast have Ripple 4 - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledSpellsEffect(new RippleAbility(4), new FilterSpell("spells")))); + // Spells you cast have Ripple 4 + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledSpellsEffect(new RippleAbility(4), new FilterCard("Spells")))); } public ThrummingStone(final ThrummingStone card) { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/CostReduceForEachTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/CostReduceForEachTest.java index 7d7e7be62d6..0128bbeb5e1 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/CostReduceForEachTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/CostReduceForEachTest.java @@ -10,6 +10,8 @@ import org.mage.test.serverside.base.CardTestPlayerBaseWithAIHelps; */ public class CostReduceForEachTest extends CardTestPlayerBaseWithAIHelps { + // tests for https://github.com/magefree/mage/issues/6698 + @Test public void test_AncientStoneIdol_Attacking() { // {10} @@ -244,4 +246,26 @@ public class CostReduceForEachTest extends CardTestPlayerBaseWithAIHelps { assertPermanentCount(playerA, "Balduvian Bears", 1); } + + @Test + public void test_InspiringStatuary_PayByArtifacts() { + // {3} + // Nonartifact spells you cast have improvise. (Your artifacts can help cast those spells. Each artifact you + // tap after you’re done activating mana abilities pays for {1}.) + addCard(Zone.BATTLEFIELD, playerA, "Inspiring Statuary", 5); + // + addCard(Zone.HAND, playerA, "Keeper of Tresserhorn", 1); // {5}{B} + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6 - 5); // 5 mana from artifact + + checkPlayableAbility("can play", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Keeper of Tresserhorn", true); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Keeper of Tresserhorn"); + addTarget(playerA, "Inspiring Statuary", 5); // as pay + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertPermanentCount(playerA, "Keeper of Tresserhorn", 1); + } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControlledSpellsEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControlledSpellsEffect.java index 424c996c1a1..62daa0db0eb 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControlledSpellsEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControlledSpellsEffect.java @@ -1,13 +1,13 @@ - package mage.abilities.effects.common.continuous; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; +import mage.cards.Card; import mage.constants.Duration; import mage.constants.Layer; import mage.constants.Outcome; import mage.constants.SubLayer; -import mage.filter.FilterSpell; +import mage.filter.FilterCard; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.stack.Spell; @@ -15,15 +15,14 @@ import mage.game.stack.StackObject; import mage.players.Player; /** - * * @author Styxo */ public class GainAbilityControlledSpellsEffect extends ContinuousEffectImpl { private final Ability ability; - private final FilterSpell filter; + private final FilterCard filter; - public GainAbilityControlledSpellsEffect(Ability ability, FilterSpell filter) { + public GainAbilityControlledSpellsEffect(Ability ability, FilterCard filter) { super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); this.ability = ability; this.filter = filter; @@ -46,13 +45,33 @@ public class GainAbilityControlledSpellsEffect extends ContinuousEffectImpl { Player player = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getSourceId()); if (player != null && permanent != null) { + for (Card card : game.getExile().getAllCards(game)) { + if (card.isOwnedBy(source.getControllerId()) && filter.match(card, game)) { + game.getState().addOtherAbility(card, ability); + } + } + for (Card card : player.getLibrary().getCards(game)) { + if (filter.match(card, game)) { + game.getState().addOtherAbility(card, ability); + } + } + for (Card card : player.getHand().getCards(game)) { + if (filter.match(card, game)) { + game.getState().addOtherAbility(card, ability); + } + } + for (Card card : player.getGraveyard().getCards(game)) { + if (filter.match(card, game)) { + game.getState().addOtherAbility(card, ability); + } + } for (StackObject stackObject : game.getStack()) { // only spells cast, so no copies of spells if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.isControlledBy(source.getControllerId())) { - Spell spell = (Spell) stackObject; - if (filter.match(spell, game)) { - if (!spell.hasAbility(ability, game)) { - game.getState().addOtherAbility(spell.getCard(), ability); + Card card = game.getCard(stackObject.getSourceId()); + if (card != null && filter.match(card, game)) { + if (!card.hasAbility(ability, game)) { + game.getState().addOtherAbility(card, ability); } } }