cleanup CantBeCounteredControlledEffect

This commit is contained in:
Susucre 2025-05-31 17:43:25 +02:00
parent 77613ad318
commit 2034b3fe59
12 changed files with 115 additions and 58 deletions

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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) {

View file

@ -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.

View file

@ -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) {

View file

@ -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(

View file

@ -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(),

View file

@ -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);
}

View file

@ -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 cant be countered by blue or black spells this turn, and creatures you control cant 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);
}
}

View file

@ -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() {