diff --git a/Mage.Sets/src/mage/cards/a/AllosaurusShepherd.java b/Mage.Sets/src/mage/cards/a/AllosaurusShepherd.java index 803dec39d7c..a151fe7e1bf 100644 --- a/Mage.Sets/src/mage/cards/a/AllosaurusShepherd.java +++ b/Mage.Sets/src/mage/cards/a/AllosaurusShepherd.java @@ -12,13 +12,15 @@ import mage.abilities.effects.common.continuous.CreaturesBecomeOtherTypeEffect; import mage.abilities.effects.common.continuous.SetBasePowerToughnessAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; import mage.filter.FilterPermanent; +import mage.filter.FilterSpell; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; import java.util.UUID; -import mage.filter.FilterSpell; public class AllosaurusShepherd extends CardImpl { @@ -43,7 +45,7 @@ public class AllosaurusShepherd extends CardImpl { //Green spells you control can't be countered. this.addAbility(new SimpleStaticAbility( - new CantBeCounteredControlledEffect(greenSpellsFilter, null, Duration.WhileOnBattlefield))); + new CantBeCounteredControlledEffect(greenSpellsFilter, Duration.WhileOnBattlefield))); //4GG: Until end of turn, each Elf creature you control has base power and toughness 5/5 // and becomes a Dinosaur in addition to its other creature types. diff --git a/Mage.Sets/src/mage/cards/b/BenevolentGeist.java b/Mage.Sets/src/mage/cards/b/BenevolentGeist.java index 814302e5078..d74cbeb9eb5 100644 --- a/Mage.Sets/src/mage/cards/b/BenevolentGeist.java +++ b/Mage.Sets/src/mage/cards/b/BenevolentGeist.java @@ -35,7 +35,7 @@ public final class BenevolentGeist extends CardImpl { // Noncreature spells you control can't be countered. this.addAbility(new SimpleStaticAbility(new CantBeCounteredControlledEffect( - StaticFilters.FILTER_SPELLS_NON_CREATURE, null, Duration.WhileOnBattlefield + StaticFilters.FILTER_SPELLS_NON_CREATURE, Duration.WhileOnBattlefield ))); // If Benevolent Geist would be put into a graveyard from anywhere, exile it instead. diff --git a/Mage.Sets/src/mage/cards/c/ChimilTheInnerSun.java b/Mage.Sets/src/mage/cards/c/ChimilTheInnerSun.java index 38fc82643f5..b4655a087c4 100644 --- a/Mage.Sets/src/mage/cards/c/ChimilTheInnerSun.java +++ b/Mage.Sets/src/mage/cards/c/ChimilTheInnerSun.java @@ -27,7 +27,7 @@ public final class ChimilTheInnerSun extends CardImpl { // Spells you control can't be countered. this.addAbility(new SimpleStaticAbility( - new CantBeCounteredControlledEffect(filter, null, Duration.WhileOnBattlefield) + new CantBeCounteredControlledEffect(filter, Duration.WhileOnBattlefield) )); // At the beginning of your end step, discover 5. diff --git a/Mage.Sets/src/mage/cards/d/DestinySpinner.java b/Mage.Sets/src/mage/cards/d/DestinySpinner.java index b520c321f56..d6219c5f349 100644 --- a/Mage.Sets/src/mage/cards/d/DestinySpinner.java +++ b/Mage.Sets/src/mage/cards/d/DestinySpinner.java @@ -51,7 +51,7 @@ public final class DestinySpinner extends CardImpl { // Creature and enchantment spells you control can't be countered. this.addAbility(new SimpleStaticAbility(new CantBeCounteredControlledEffect( - filter, null, Duration.WhileOnBattlefield + filter, Duration.WhileOnBattlefield ))); // {3}{G}: Target land you control becomes an X/X Elemental creature with trample and haste until end of turn, where X is the number of enchantments you control. It's still a land. diff --git a/Mage.Sets/src/mage/cards/p/ProwlingSerpopard.java b/Mage.Sets/src/mage/cards/p/ProwlingSerpopard.java index 7764ad489a0..4f939194d59 100644 --- a/Mage.Sets/src/mage/cards/p/ProwlingSerpopard.java +++ b/Mage.Sets/src/mage/cards/p/ProwlingSerpopard.java @@ -1,7 +1,6 @@ package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.CantBeCounteredSourceAbility; import mage.abilities.common.SimpleStaticAbility; @@ -9,13 +8,13 @@ import mage.abilities.effects.common.CantBeCounteredControlledEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; import mage.filter.FilterSpell; +import java.util.UUID; + /** - * * @author fireshoes */ public final class ProwlingSerpopard extends CardImpl { @@ -38,7 +37,7 @@ public final class ProwlingSerpopard extends CardImpl { this.addAbility(new CantBeCounteredSourceAbility()); // Creature spells you control can't be countered. - this.addAbility(new SimpleStaticAbility(new CantBeCounteredControlledEffect(filterTarget, null, Duration.WhileOnBattlefield))); + this.addAbility(new SimpleStaticAbility(new CantBeCounteredControlledEffect(filterTarget, Duration.WhileOnBattlefield))); } private ProwlingSerpopard(final ProwlingSerpopard card) { diff --git a/Mage.Sets/src/mage/cards/r/RhythmOfTheWild.java b/Mage.Sets/src/mage/cards/r/RhythmOfTheWild.java index b1c2390c7ef..d72a6fd9845 100644 --- a/Mage.Sets/src/mage/cards/r/RhythmOfTheWild.java +++ b/Mage.Sets/src/mage/cards/r/RhythmOfTheWild.java @@ -46,7 +46,7 @@ public final class RhythmOfTheWild extends CardImpl { // Creature spells you control can't be countered. this.addAbility(new SimpleStaticAbility(new CantBeCounteredControlledEffect( - filter, null, Duration.WhileOnBattlefield + filter, Duration.WhileOnBattlefield ))); // Nontoken creatures you control have riot. diff --git a/Mage.Sets/src/mage/cards/s/SphinxOfTheFinalWord.java b/Mage.Sets/src/mage/cards/s/SphinxOfTheFinalWord.java index 851e3815f3f..82c17b73310 100644 --- a/Mage.Sets/src/mage/cards/s/SphinxOfTheFinalWord.java +++ b/Mage.Sets/src/mage/cards/s/SphinxOfTheFinalWord.java @@ -1,7 +1,6 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.CantBeCounteredSourceAbility; import mage.abilities.common.SimpleStaticAbility; @@ -11,42 +10,42 @@ import mage.abilities.keyword.HexproofAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; import mage.filter.FilterSpell; import mage.filter.predicate.Predicates; +import java.util.UUID; + /** - * * @author fireshoes */ public final class SphinxOfTheFinalWord extends CardImpl { - + private static final FilterSpell filterTarget = new FilterSpell("Instant and sorcery spells you control"); static { filterTarget.add(Predicates.or(CardType.INSTANT.getPredicate(), (CardType.SORCERY.getPredicate()))); } - + public SphinxOfTheFinalWord(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{U}{U}"); this.subtype.add(SubType.SPHINX); this.power = new MageInt(5); this.toughness = new MageInt(5); // Sphinx of the Final Word can't be countered. this.addAbility(new CantBeCounteredSourceAbility()); - + // Flying this.addAbility(FlyingAbility.getInstance()); - + // Hexproof this.addAbility(HexproofAbility.getInstance()); - + // Instant and sorcery spells you control can't be countered. - this.addAbility(new SimpleStaticAbility(new CantBeCounteredControlledEffect(filterTarget, null, Duration.WhileOnBattlefield))); + this.addAbility(new SimpleStaticAbility(new CantBeCounteredControlledEffect(filterTarget, Duration.WhileOnBattlefield))); } private SphinxOfTheFinalWord(final SphinxOfTheFinalWord card) { diff --git a/Mage.Sets/src/mage/cards/s/SurrakDragonclaw.java b/Mage.Sets/src/mage/cards/s/SurrakDragonclaw.java index e800d7898d1..7f17e5ef1c5 100644 --- a/Mage.Sets/src/mage/cards/s/SurrakDragonclaw.java +++ b/Mage.Sets/src/mage/cards/s/SurrakDragonclaw.java @@ -1,7 +1,6 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.CantBeCounteredSourceAbility; import mage.abilities.common.SimpleStaticAbility; @@ -12,15 +11,15 @@ import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; +import mage.constants.SubType; import mage.constants.SuperType; -import mage.constants.Zone; import mage.filter.FilterSpell; import mage.filter.StaticFilters; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SurrakDragonclaw extends CardImpl { @@ -47,7 +46,7 @@ public final class SurrakDragonclaw extends CardImpl { this.addAbility(new CantBeCounteredSourceAbility()); // Creature spells you control can't be countered. - this.addAbility(new SimpleStaticAbility(new CantBeCounteredControlledEffect(filterTarget, null, Duration.WhileOnBattlefield))); + this.addAbility(new SimpleStaticAbility(new CantBeCounteredControlledEffect(filterTarget, Duration.WhileOnBattlefield))); // Other creatures you control have trample. this.addAbility(new SimpleStaticAbility( diff --git a/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java b/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java index 0dfd4b2c825..68cf65183b4 100644 --- a/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java +++ b/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java @@ -1,6 +1,5 @@ package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; @@ -22,7 +21,8 @@ import mage.game.events.GameEvent; import mage.game.stack.Spell; import mage.players.Player; import mage.target.targetpointer.FixedTarget; -import mage.watchers.common.AttackedThisTurnWatcher; + +import java.util.UUID; /** * @author spjspj @@ -51,7 +51,7 @@ public final class TaigamOjutaiMaster extends CardImpl { this.toughness = new MageInt(4); // Instant, sorcery, and Dragon spells you control can't be countered. - this.addAbility(new SimpleStaticAbility(new CantBeCounteredControlledEffect(filter, null, Duration.WhileOnBattlefield))); + this.addAbility(new SimpleStaticAbility(new CantBeCounteredControlledEffect(filter, Duration.WhileOnBattlefield))); // Whenever you cast an instant or sorcery spell from your hand, if Taigam, Ojutai Master attacked this turn, that spell gains rebound. Ability ability = new ConditionalInterveningIfTriggeredAbility(new TaigamOjutaiMasterTriggeredAbility(), diff --git a/Mage.Sets/src/mage/cards/t/ThryxTheSuddenStorm.java b/Mage.Sets/src/mage/cards/t/ThryxTheSuddenStorm.java index d93b05c56a2..2f2eeddca6a 100644 --- a/Mage.Sets/src/mage/cards/t/ThryxTheSuddenStorm.java +++ b/Mage.Sets/src/mage/cards/t/ThryxTheSuddenStorm.java @@ -1,6 +1,5 @@ package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -16,6 +15,8 @@ import mage.filter.FilterSpell; import mage.filter.predicate.Predicate; import mage.filter.predicate.mageobject.ManaValuePredicate; +import java.util.UUID; + /** * @author TheElk801 */ @@ -48,7 +49,7 @@ public final class ThryxTheSuddenStorm extends CardImpl { // Spells you cast with converted mana cost 5 or greater cost {1} less to cast and can't be countered. Ability ability = new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1)); ability.addEffect(new CantBeCounteredControlledEffect( - filter2, null, Duration.WhileOnBattlefield + filter2, Duration.WhileOnBattlefield ).setText("and can't be countered")); this.addAbility(ability); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/m11/AutumnsVeilTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/m11/AutumnsVeilTest.java new file mode 100644 index 00000000000..30e945ae8a8 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/m11/AutumnsVeilTest.java @@ -0,0 +1,63 @@ +package org.mage.test.cards.single.m11; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class AutumnsVeilTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.a.AutumnsVeil Autumn's Veil} {G} + * Instant + * Spells you control can’t be countered by blue or black spells this turn, and creatures you control can’t be the targets of blue or black spells this turn. + */ + private static final String veil = "Autumn's Veil"; + + @Test + public void test_BlueCounter() { + addCard(Zone.HAND, playerA, veil, 1); + addCard(Zone.HAND, playerA, "Elvish Mystic", 1); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + + addCard(Zone.HAND, playerB, "Counterspell"); + addCard(Zone.BATTLEFIELD, playerB, "Island", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, veil, true); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Elvish Mystic"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Counterspell", "Elvish Mystic", "Elvish Mystic"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Elvish Mystic", 1); + assertGraveyardCount(playerB, "Counterspell", 1); + } + + @Test + public void test_WhiteCounter() { + addCard(Zone.HAND, playerA, veil, 1); + addCard(Zone.HAND, playerA, "Elvish Mystic", 1); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + + addCard(Zone.HAND, playerB, "Mana Tithe"); + addCard(Zone.BATTLEFIELD, playerB, "Plains", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, veil, true); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Elvish Mystic"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Mana Tithe", "Elvish Mystic", "Elvish Mystic"); + + setChoice(playerA, false); // can't pay the Tithe Tax + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertGraveyardCount(playerA, "Elvish Mystic", 1); + assertGraveyardCount(playerB, "Mana Tithe", 1); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/CantBeCounteredControlledEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CantBeCounteredControlledEffect.java index f050ad42afa..472c5c4f743 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CantBeCounteredControlledEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CantBeCounteredControlledEffect.java @@ -1,40 +1,40 @@ package mage.abilities.effects.common; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.constants.Duration; import mage.constants.Outcome; -import mage.filter.FilterObject; import mage.filter.FilterSpell; +import mage.filter.FilterStackObject; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.stack.Spell; +import mage.game.stack.StackObject; + +import java.util.UUID; /** - * @author BetaSteward_at_googlemail.com + * @author BetaSteward_at_googlemail.com, Susucr */ public class CantBeCounteredControlledEffect extends ContinuousRuleModifyingEffectImpl { - private FilterSpell filterTarget; - private FilterObject filterSource; + private FilterSpell filterTarget; // what can't be countered + private FilterStackObject filterSource; // can filter on what is countering - public CantBeCounteredControlledEffect(FilterSpell filterTarget, FilterObject filterSource, Duration duration) { + public CantBeCounteredControlledEffect(FilterSpell filterTarget, Duration duration) { + this(filterTarget, null, duration); + } + + public CantBeCounteredControlledEffect(FilterSpell filterTarget, FilterStackObject filterSource, Duration duration) { super(duration, Outcome.Benefit); this.filterTarget = filterTarget; this.filterSource = filterSource; setText(); } - public CantBeCounteredControlledEffect(FilterSpell filterTarget, Duration duration) { - this(filterTarget, null, duration); - } - protected CantBeCounteredControlledEffect(final CantBeCounteredControlledEffect effect) { super(effect); - if (effect.filterTarget != null) { - this.filterTarget = effect.filterTarget.copy(); - } + this.filterTarget = effect.filterTarget.copy(); if (effect.filterSource != null) { this.filterSource = effect.filterSource.copy(); } @@ -52,19 +52,13 @@ public class CantBeCounteredControlledEffect extends ContinuousRuleModifyingEffe @Override public boolean applies(GameEvent event, Ability source, Game game) { + UUID controllerId = source.getControllerId(); Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null && spell.isControlledBy(source.getControllerId()) - && filterTarget.match(spell, source.getControllerId(), source, game)) { - if (filterSource == null) { - return true; - } else { - MageObject sourceObject = game.getObject(event.getSourceId()); - if (filterSource.match(sourceObject, game)) { - return true; - } - } - } - return false; + StackObject counterSource = game.getStack().getStackObject(event.getSourceId()); + return spell != null + && spell.isControlledBy(controllerId) + && filterTarget.match(spell, controllerId, source, game) + && (filterSource == null || filterSource.match(counterSource, controllerId, source, game)); } private void setText() {