make SpellsCastWatcher a default game watcher

This commit is contained in:
xenohedron 2023-08-12 20:53:12 -04:00
parent dfb337671b
commit 7d170ef902
46 changed files with 56 additions and 70 deletions

View file

@ -1,7 +1,6 @@
package mage.cards.a;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.keyword.IndestructibleAbility;
@ -20,7 +19,7 @@ import mage.watchers.common.SpellsCastWatcher;
import java.util.*;
/**
* @author: Merlingilb
* @author Merlingilb
*/
public final class AJedisFervor extends CardImpl {
public AJedisFervor(UUID ownerId, CardSetInfo setInfo) {
@ -34,7 +33,6 @@ public final class AJedisFervor extends CardImpl {
// If an opponent cast a black spell this turn, that player sacrifices a creature or planeswalker.
this.getSpellAbility().addEffect(new AJedisFervorEffect());
this.getSpellAbility().addWatcher(new SpellsCastWatcher());
}
private AJedisFervor(final AJedisFervor card) {

View file

@ -36,7 +36,7 @@ public final class ArcboundTracker extends CardImpl {
this.addAbility(new ModularAbility(this, 2));
// Whenever you cast a spell other than your first spell each turn, put a +1/+1 counter on Arcbound Tracker.
this.addAbility(new ArcboundTrackerTriggeredAbility(), new SpellsCastWatcher());
this.addAbility(new ArcboundTrackerTriggeredAbility());
}
private ArcboundTracker(final ArcboundTracker card) {

View file

@ -42,7 +42,7 @@ public final class ArchfiendsVessel extends CardImpl {
this.addAbility(LifelinkAbility.getInstance());
// When Archfiend's Vessel enters the battlefield, if it entered from your graveyard or you cast it from your graveyard, exile it. If you do, create a 5/5 black Demon creature token with flying.
this.addAbility(new ArchfiendsVesselAbility(), new SpellsCastWatcher());
this.addAbility(new ArchfiendsVesselAbility());
}
private ArchfiendsVessel(final ArchfiendsVessel card) {

View file

@ -65,7 +65,6 @@ class BaralAndKariZevTriggeredAbility extends TriggeredAbilityImpl {
BaralAndKariZevTriggeredAbility() {
super(Zone.BATTLEFIELD, new BaralAndKariZevEffect());
this.addWatcher(new SpellsCastWatcher());
}
private BaralAndKariZevTriggeredAbility(final BaralAndKariZevTriggeredAbility ability) {

View file

@ -34,7 +34,7 @@ public final class CaptainRipleyVance extends CardImpl {
this.toughness = new MageInt(2);
// Whenever you cast your third spell each turn, put a +1/+1 counter on Captain Ripley Vance, then it deals damage equal to its power to any target.
this.addAbility(new CaptainRipleyVanceTriggeredAbility(), new SpellsCastWatcher());
this.addAbility(new CaptainRipleyVanceTriggeredAbility());
}
private CaptainRipleyVance(final CaptainRipleyVance card) {

View file

@ -45,7 +45,7 @@ public final class ConduitOfWorlds extends CardImpl {
// {T}: Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery.
Ability ability = new ActivateAsSorceryActivatedAbility(new ConduitOfWorldsEffect(), new TapSourceCost());
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability, new SpellsCastWatcher());
this.addAbility(ability);
}
private ConduitOfWorlds(final ConduitOfWorlds card) {

View file

@ -58,7 +58,6 @@ class CurseOfShakenFaithTriggeredAbility extends TriggeredAbilityImpl {
public CurseOfShakenFaithTriggeredAbility() {
super(Zone.BATTLEFIELD, new CurseOfShakenFaithEffect());
this.addWatcher(new SpellsCastWatcher());
setTriggerPhrase("Whenever enchanted player casts a spell other than the first spell they cast each turn or copies a spell, ");
}

View file

@ -44,7 +44,7 @@ public final class Demilich extends CardImpl {
// This spell costs {U} less to cast for each instant and sorcery you've cast this turn.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(
new ManaCostsImpl<>("{U}"), DemilichValue.instance
)).addHint(new ValueHint("Instants and sorceries you've cast this turn", DemilichValue.instance)), new SpellsCastWatcher());
)).addHint(new ValueHint("Instants and sorceries you've cast this turn", DemilichValue.instance)));
// Whenever Demilich attacks, exile up to one target instant or sorcery card from your graveyard. Copy it. You may cast the copy.
Ability ability = new AttacksTriggeredAbility(new ExileTargetCardCopyAndCastEffect(false).setText(

View file

@ -25,7 +25,7 @@ public final class DoubleVision extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}{R}");
// Whenever you cast your first instant or sorcery spell each turn, copy that spell. You may choose new targets for the copy.
this.addAbility(new DoubleVisionCopyTriggeredAbility(), new SpellsCastWatcher());
this.addAbility(new DoubleVisionCopyTriggeredAbility());
}
private DoubleVision(final DoubleVision card) {

View file

@ -38,8 +38,8 @@ public final class DreamThief extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Dream Thief enters the battlefield, draw a card if you've cast another blue spell this turn.
this.addAbility(new EntersBattlefieldTriggeredAbility(new ConditionalOneShotEffect(new DrawCardSourceControllerEffect(1), new CastBlueSpellThisTurnCondition(), rule)),
new SpellsCastWatcher());
this.addAbility(new EntersBattlefieldTriggeredAbility(new ConditionalOneShotEffect(
new DrawCardSourceControllerEffect(1), new CastBlueSpellThisTurnCondition(), rule)));
}

View file

@ -37,7 +37,7 @@ public final class EsperSentinel extends CardImpl {
this.toughness = new MageInt(1);
// Whenever an opponent casts their first noncreature spell each turn, draw a card unless that player pays {X}, where X is Esper Sentinel's power.
this.addAbility(new EsperSentinelTriggeredAbility(), new SpellsCastWatcher());
this.addAbility(new EsperSentinelTriggeredAbility());
}
private EsperSentinel(final EsperSentinel card) {

View file

@ -40,7 +40,7 @@ public final class FaeOffering extends CardImpl {
);
ability.addEffect(new CreateTokenEffect(new FoodToken()));
ability.addEffect(new CreateTokenEffect(new TreasureToken()));
this.addAbility(ability.addHint(FaeOfferingHint.instance), new SpellsCastWatcher());
this.addAbility(ability.addHint(FaeOfferingHint.instance));
}
private FaeOffering(final FaeOffering card) {
@ -93,7 +93,7 @@ enum FaeOfferingHint implements Hint {
.map(b -> b ? "Creature spell" : "Noncreature spell")
.sorted()
.collect(Collectors.toList());
if (messages.size() == 0) {
if (messages.isEmpty()) {
return "You have not cast any spells this turn";
}
return "You have cast a " + String.join(" and a ", messages) + " this turn";

View file

@ -46,7 +46,7 @@ public final class HallOfOracles extends CardImpl {
);
ability.addTarget(new TargetCreaturePermanent());
ability.setTiming(TimingRule.SORCERY);
this.addAbility(ability, new SpellsCastWatcher());
this.addAbility(ability);
}
private HallOfOracles(final HallOfOracles card) {

View file

@ -39,7 +39,7 @@ public final class HauntingFigment extends CardImpl {
this.addAbility(new SimpleStaticAbility(new ConditionalRestrictionEffect(
new CantBeBlockedSourceEffect(Duration.WhileOnBattlefield), HauntingFigmentCondition.instance,
"{this} can't be blocked as long as you've cast an instant or sorcery spell this turn"
)), new SpellsCastWatcher());
)));
}
private HauntingFigment(final HauntingFigment card) {

View file

@ -30,7 +30,6 @@ public final class HellishRebuke extends CardImpl {
// Until end of turn, permanents your opponents control gain "When this permanent deals damage to the player who cast Hellish Rebuke, sacrifice this permanent. You lose 2 life."
this.getSpellAbility().addEffect(new HellishRebukeEffect());
this.getSpellAbility().addWatcher(new SpellsCastWatcher());
}
private HellishRebuke(final HellishRebuke card) {
@ -111,12 +110,12 @@ class HellishRebukeTriggeredAbility extends TriggeredAbilityImpl {
+ sourceName + ", sacrifice this permanent. You lose 2 life.";
}
private static final String getSourceName(Ability source, Game game) {
private static String getSourceName(Ability source, Game game) {
MageObject object = source.getSourceObject(game);
return object != null ? object.getName() : "Hellish Rebuke";
}
private static final UUID getCasterId(Ability source, Game game) {
private static UUID getCasterId(Ability source, Game game) {
SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class);
return watcher.getCasterId(source, game);
}

View file

@ -16,7 +16,6 @@ import mage.constants.SubType;
import mage.constants.SuperType;
import mage.game.command.emblems.JaceUnravelerOfSecretsEmblem;
import mage.target.common.TargetCreaturePermanent;
import mage.watchers.common.SpellsCastWatcher;
/**
* import mage.game.command.emblems.JaceUnravelerOfSecretsEmblem;
@ -46,7 +45,7 @@ public final class JaceUnravelerOfSecrets extends CardImpl {
// -8: You get an emblem with "Whenever an opponent casts their first spell each turn, counter that spell."
LoyaltyAbility ability2 = new LoyaltyAbility(new GetEmblemEffect(new JaceUnravelerOfSecretsEmblem()), -8);
this.addAbility(ability2, new SpellsCastWatcher());
this.addAbility(ability2);
}

View file

@ -39,7 +39,7 @@ public final class KalamaxTheStormsire extends CardImpl {
this.toughness = new MageInt(4);
// Whenever you cast your first instant spell each turn, if Kalamax, the Stormsire is tapped, copy that spell. You may choose new targets for the copy.
this.addAbility(new KalamaxTheStormsireSpellCastAbility(), new SpellsCastWatcher());
this.addAbility(new KalamaxTheStormsireSpellCastAbility());
// Whenever you copy an instant spell, put a +1/+1 counter on Kalamax.
this.addAbility(new KalamaxTheStormsireCopyTriggeredAbility());
}

View file

@ -38,7 +38,7 @@ public final class Leapfrog extends CardImpl {
FlyingAbility.getInstance(), Duration.WhileOnBattlefield
), LeapfrogCondition.instance, "{this} has flying as long as " +
"you've cast an instant or sorcery spell this turn."
)), new SpellsCastWatcher());
)));
}
private Leapfrog(final Leapfrog card) {

View file

@ -39,7 +39,7 @@ public final class MageDuel extends CardImpl {
this.addAbility(new SimpleStaticAbility(
Zone.ALL,
new SpellCostReductionSourceEffect(2, MageDuelCondition.instance).setCanWorksOnStackOnly(true)
).setRuleAtTheTop(true), new SpellsCastWatcher());
).setRuleAtTheTop(true).addHint(hint));
// Target creature you control gets +1/+2 until end of turn. Then it fights target creature you don't control.
this.getSpellAbility().addEffect(new BoostTargetEffect(1, 2));
@ -48,7 +48,6 @@ public final class MageDuel extends CardImpl {
"<i>(Each deals damage equal to its power to the other.)</i>"));
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL));
this.getSpellAbility().addWatcher(new SpellsCastWatcher());
}
private MageDuel(final MageDuel card) {

View file

@ -41,7 +41,7 @@ public final class MarshlandBloodcaster extends CardImpl {
// {1}{B}, {T}: Rather than pay the mana cost of the next spell you cast this turn, you may pay life equal to that spell's mana value.
Ability ability = new SimpleActivatedAbility(new MarshlandBloodcasterEffect(), new ManaCostsImpl<>("{1}{B}"));
ability.addCost(new TapSourceCost());
this.addAbility(ability, new SpellsCastWatcher());
this.addAbility(ability);
}
private MarshlandBloodcaster(final MarshlandBloodcaster card) {

View file

@ -35,7 +35,7 @@ public final class MindsDilation extends CardImpl {
// that player exiles the top card of their library. If it's a nonland card,
// you may cast it without paying its mana cost.
this.addAbility(new MindsDilationTriggeredAbility(new MindsDilationEffect(),
false), new SpellsCastWatcher());
false));
}
private MindsDilation(final MindsDilation card) {

View file

@ -45,7 +45,7 @@ public final class MonkClass extends CardImpl {
this.addAbility(new SimpleStaticAbility(new ConditionalCostModificationEffect(
new SpellsCostReductionControllerEffect(StaticFilters.FILTER_CARD, 1),
MonkClassCondition.instance, "the second spell you cast each turn costs {1} less to cast"
)), new SpellsCastWatcher());
)));
// {W}{U}: Level 2
this.addAbility(new ClassLevelAbility(2, "{W}{U}"));
@ -142,7 +142,7 @@ class MonkClassCastEffect extends AsThoughEffectImpl {
Card card = game.getCard(sourceId);
SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class);
return card != null && watcher != null && !card.isLand(game)
&& watcher.getSpellsCastThisTurn(affectedControllerId).size() > 0;
&& !watcher.getSpellsCastThisTurn(affectedControllerId).isEmpty();
}
@Override

View file

@ -35,7 +35,7 @@ public final class NullstoneGargoyle extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// Whenever the first noncreature spell of a turn is cast, counter that spell.
this.addAbility(new NullstoneGargoyleTriggeredAbility(), new SpellsCastWatcher());
this.addAbility(new NullstoneGargoyleTriggeredAbility());
}
private NullstoneGargoyle(final NullstoneGargoyle card) {

View file

@ -54,7 +54,7 @@ public final class PainDistributor extends CardImpl {
new CreateTokenTargetEffect(new TreasureToken())
.setText("they create a Treasure token"),
filter, false, SetTargetPointer.PLAYER
), new SpellsCastWatcher());
));
// Whenever an artifact an opponent controls is put into a graveyard from the battlefield, Pain Distributor deals 1 damage to that player.
this.addAbility(new PutIntoGraveFromBattlefieldAllTriggeredAbility(

View file

@ -44,8 +44,7 @@ public final class PistonFistCyclops extends CardImpl {
), PistonFistCyclopsCondition.instance)
.setText("As long as you've cast an instant or sorcery spell this turn, "
+ "{this} can attack as though it didn't have defender")
),
new SpellsCastWatcher());
));
}
private PistonFistCyclops(final PistonFistCyclops card) {

View file

@ -67,7 +67,7 @@ class PlaneswalkersMischiefEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player opponent = game.getPlayer(source.getFirstTarget());
if (opponent != null && opponent.getHand().size() > 0) {
if (opponent != null && !opponent.getHand().isEmpty()) {
Card revealedCard = opponent.getHand().getRandom(game);
if (revealedCard == null) {
return false;
@ -84,7 +84,6 @@ class PlaneswalkersMischiefEffect extends OneShotEffect {
Condition condition = new PlaneswalkersMischiefCondition(source.getSourceId(), revealedCard.getId());
ConditionalOneShotEffect effect3 = new ConditionalOneShotEffect(effect2, condition, "if you haven't cast it, return it to its owner's hand.");
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect3);
delayedAbility.addWatcher(new SpellsCastWatcher());
game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}

View file

@ -69,7 +69,6 @@ class RashmiAndRagavanTriggeredAbility extends SpellCastControllerTriggeredAbili
RashmiAndRagavanTriggeredAbility() {
super(new CreateTokenEffect(new TreasureToken()), false);
this.addTarget(new TargetOpponent());
this.addWatcher(new SpellsCastWatcher());
this.addEffect(new RashmiAndRagavanEffect());
}
@ -152,7 +151,7 @@ class RashmiAndRagavanEffect extends OneShotEffect {
).calculate(game, source, this);
FilterCard filter = new FilterCard();
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, artifactCount));
Boolean cardWasCast = CardUtil.castSpellWithAttributesForFree(controller, source, game, new CardsImpl(card), filter);
boolean cardWasCast = CardUtil.castSpellWithAttributesForFree(controller, source, game, new CardsImpl(card), filter);
if (!cardWasCast) {
ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, TargetController.YOU, Duration.EndOfTurn, false, true);
effect.setTargetPointer(new FixedTargets(cards, game));

View file

@ -40,7 +40,7 @@ public final class RashmiEternitiesCrafter extends CardImpl {
// Whenever you cast your first spell each turn, reveal the top card of your library.
// If it's a nonland card with converted mana cost less than that spell's, you may cast it
// without paying its mana cost. If you don't cast the revealed card, put it into your hand.
this.addAbility(new RashmiEternitiesCrafterTriggeredAbility(), new SpellsCastWatcher());
this.addAbility(new RashmiEternitiesCrafterTriggeredAbility());
}
private RashmiEternitiesCrafter(final RashmiEternitiesCrafter card) {
@ -118,7 +118,7 @@ class RashmiEternitiesCrafterEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Boolean cardWasCast = false;
boolean cardWasCast = false;
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Card card = controller.getLibrary().getFromTop(game);

View file

@ -36,7 +36,7 @@ public final class RefractionTrap extends CardImpl {
this.subtype.add(SubType.TRAP);
// If an opponent cast a red instant or sorcery spell this turn, you may pay {W} rather than pay Refraction Trap's mana cost.
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl<>("{W}"), RefractionTrapCondition.instance), new SpellsCastWatcher());
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl<>("{W}"), RefractionTrapCondition.instance));
// Prevent the next 3 damage that a source of your choice would deal to you and/or permanents you control this turn. If damage is prevented this way, Refraction Trap deals that much damage to any target.
this.getSpellAbility().addEffect(new RefractionTrapPreventDamageEffect(Duration.EndOfTurn, 3));
@ -156,11 +156,9 @@ class RefractionTrapPreventDamageEffect extends PreventionEffectImpl {
// check target
// check permanent first
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent != null) {
if (permanent.isControlledBy(source.getControllerId())) {
// it's your permanent
return true;
}
if (permanent != null && (permanent.isControlledBy(source.getControllerId()))) {
// it's your permanent
return true;
}
// check player
Player player = game.getPlayer(event.getTargetId());

View file

@ -41,7 +41,7 @@ public final class RelicRunner extends CardImpl {
new CastHistoricSpellThisTurnCondition(),
"{this} can't be blocked if you've cast an historic spell this turn. <i>(Artifacts, legendaries, and Sagas are historic.)</i>"
)
), new SpellsCastWatcher());
));
}
private RelicRunner(final RelicRunner card) {

View file

@ -35,7 +35,7 @@ public final class RicochetTrap extends CardImpl {
this.subtype.add(SubType.TRAP);
// If an opponent cast a blue spell this turn, you may pay {R} rather than pay Ricochet Trap's mana cost.
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl<>("{R}"), RicochetTrapCondition.instance), new SpellsCastWatcher());
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl<>("{R}"), RicochetTrapCondition.instance));
// Change the target of target spell with a single target.
this.getSpellAbility().addEffect(new ChooseNewTargetsTargetEffect(true, true));

View file

@ -38,7 +38,7 @@ public final class RockJockey extends CardImpl {
), new PlayLandWatcher());
// You can't play lands if you've cast Rock Jockey this turn.
this.addAbility(new SimpleStaticAbility(new RockJockeyEffect()), new SpellsCastWatcher());
this.addAbility(new SimpleStaticAbility(new RockJockeyEffect()));
}
private RockJockey(final RockJockey card) {

View file

@ -37,7 +37,7 @@ public final class RugOfSmothering extends CardImpl {
this.addAbility(new SpellCastAllTriggeredAbility(
new RugOfSmotheringEffect(), StaticFilters.FILTER_SPELL_A,
false, SetTargetPointer.PLAYER
), new SpellsCastWatcher());
));
}
private RugOfSmothering(final RugOfSmothering card) {

View file

@ -28,7 +28,6 @@ public final class SeeTheTruth extends CardImpl {
// Look at the top three cards of your library. Put one of those cards into your hand and the rest on the bottom of your library in any order. If this spell was cast from anywhere other than your hand, put each of those cards into your hand instead.
this.getSpellAbility().addEffect(new SeeTheTruthEffect());
this.getSpellAbility().addWatcher(new SpellsCastWatcher());
}
private SeeTheTruth(final SeeTheTruth card) {

View file

@ -34,7 +34,6 @@ public final class Seedtime extends CardImpl {
// Take an extra turn after this one if an opponent cast a blue spell this turn.
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new AddExtraTurnControllerEffect(), OpponentCastBlueSpellThisTurnCondition.instance, rule2));
this.getSpellAbility().addWatcher(new SpellsCastWatcher());
}

View file

@ -38,8 +38,7 @@ public final class SeekerOfInsight extends CardImpl {
Zone.BATTLEFIELD,
new DrawDiscardControllerEffect(),
new TapSourceCost(),
new CastNonCreatureSpellCondition()),
new SpellsCastWatcher());
new CastNonCreatureSpellCondition()));
}
private SeekerOfInsight(final SeekerOfInsight card) {

View file

@ -46,7 +46,7 @@ public final class ShadowInTheWarp extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect), new ShadowInTheWarpWatcher());
// Whenever an opponent casts their first noncreature spell each turn, Shadow in the Warp deals 2 damage to that player.
this.addAbility(new ShadowInTheWarpTriggeredAbility(), new SpellsCastWatcher());
this.addAbility(new ShadowInTheWarpTriggeredAbility());
}
private ShadowInTheWarp(final ShadowInTheWarp card) {

View file

@ -29,7 +29,7 @@ public final class ShowOfConfidence extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
// When you cast this spell, copy it for each other instant or sorcery spell you've cast this turn. You may choose new targets for the copies.
this.addAbility(new CastSourceTriggeredAbility(new ShowOfConfidenceEffect()), new SpellsCastWatcher());
this.addAbility(new CastSourceTriggeredAbility(new ShowOfConfidenceEffect()));
// Put a +1/+1 counter on target creature. It gains vigilance until end of turn.
this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));

View file

@ -30,7 +30,7 @@ public final class SilburlindSnapper extends CardImpl {
this.toughness = new MageInt(6);
// Silburlind Snapper can't attack unless you've cast a noncreature spell this turn.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SilburlindSnapperEffect()), new SpellsCastWatcher());
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SilburlindSnapperEffect()));
}
private SilburlindSnapper(final SilburlindSnapper card) {

View file

@ -42,7 +42,7 @@ public final class StormwingEntity extends CardImpl {
// This spell costs {2}{U} less to cast if you've cast an instant or sorcery spell this turn.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(
new ManaCostsImpl<>("{2}{U}"), StormwingEntityCondition.instance
)).setRuleAtTheTop(true).addHint(hint), new SpellsCastWatcher());
)).setRuleAtTheTop(true).addHint(hint));
// Flying
this.addAbility(FlyingAbility.getInstance());

View file

@ -37,7 +37,7 @@ public final class SwordCoastSerpent extends AdventureCard {
this.addAbility(new SimpleStaticAbility(new ConditionalRestrictionEffect(
new CantBeBlockedSourceEffect(), SwordCoastSerpentCondition.instance,
"{this} can't be blocked as long as you've cast a noncreature spell this turn"
)), new SpellsCastWatcher());
)));
// Capsizing Wave
// Return target creature to its owner's hand.

View file

@ -39,7 +39,7 @@ public final class TwinningGlass extends CardImpl {
), new GenericManaCost(1)
);
ability.addCost(new TapSourceCost());
this.addAbility(ability, new SpellsCastWatcher());
this.addAbility(ability);
}
private TwinningGlass(final TwinningGlass card) {

View file

@ -54,7 +54,7 @@ public final class Urabrask extends CardImpl {
this.addAbility(new ConditionalActivatedAbility(
new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED),
new ManaCostsImpl<>("{R}"), UrabraskCondition.instance
).setTiming(TimingRule.SORCERY), new SpellsCastWatcher());
).setTiming(TimingRule.SORCERY));
}
private Urabrask(final Urabrask card) {

View file

@ -43,7 +43,7 @@ public final class VialSmasherTheFierce extends CardImpl {
this.toughness = new MageInt(3);
// Whenever you cast your first spell each turn, Vial Smasher the Fierce deals damage equal to that spell's converted mana cost to an opponent chosen at random.
this.addAbility(new VialSmasherTheFierceTriggeredAbility(), new SpellsCastWatcher());
this.addAbility(new VialSmasherTheFierceTriggeredAbility());
// Partner
this.addAbility(PartnerAbility.getInstance());
@ -136,7 +136,7 @@ class VialSmasherTheFierceEffect extends OneShotEffect {
Collections.shuffle(opponents);
Player opponent = opponents.get(0);
game.informPlayers(opponent.getLogName() + " was chosen at random.");
if (game.getBattlefield().getAllActivePermanents(new FilterPlaneswalkerPermanent(), opponent.getId(), game).size() > 0) {
if (!game.getBattlefield().getAllActivePermanents(new FilterPlaneswalkerPermanent(), opponent.getId(), game).isEmpty()) {
if (controller.chooseUse(Outcome.Damage, "Redirect to a planeswalker controlled by " + opponent.getLogName() + "?", source, game)) {
FilterPlaneswalkerPermanent filter = new FilterPlaneswalkerPermanent("a planeswalker controlled by " + opponent.getLogName());
filter.add(new ControllerIdPredicate(opponent.getId()));

View file

@ -37,7 +37,7 @@ public final class ZenithChronicler extends CardImpl {
this.toughness = new MageInt(1);
// Whenever a player casts their first multicolored spell each turn, each other player draws a card.
this.addAbility(new ZenithChroniclerTriggeredAbility(), new SpellsCastWatcher());
this.addAbility(new ZenithChroniclerTriggeredAbility());
}

View file

@ -1343,6 +1343,7 @@ public abstract class GameImpl implements Game {
newWatchers.add(new CommanderPlaysCountWatcher()); // commander plays count uses in non commander games by some cards
newWatchers.add(new CreaturesDiedWatcher());
newWatchers.add(new TemptedByTheRingWatcher());
newWatchers.add(new SpellsCastWatcher());
// runtime check - allows only GAME scope (one watcher per game)
newWatchers.forEach(watcher -> {
@ -3864,7 +3865,7 @@ public abstract class GameImpl implements Game {
return filterCommandersBySearchZone(mainCards, returnAllCardParts);
}
final protected Set<UUID> filterCommandersBySearchZone(Set<UUID> commanderMainCards, boolean returnAllCardParts) {
protected final Set<UUID> filterCommandersBySearchZone(Set<UUID> commanderMainCards, boolean returnAllCardParts) {
// filter by zone search (example: if you search commanders on battlefield then must see all sides of mdf cards)
Set<UUID> filteredCards = new HashSet<>();
if (returnAllCardParts) {