From f7d70a7b11f517616205dbd82506f20ef3d79e6b Mon Sep 17 00:00:00 2001 From: xenohedron Date: Wed, 29 Nov 2023 20:27:30 -0500 Subject: [PATCH 01/10] refactor: AttackedThisTurnWatcher is a default watcher close #10982 --- Mage.Sets/src/mage/cards/a/Aggression.java | 3 +-- Mage.Sets/src/mage/cards/a/AngelsTrumpet.java | 2 +- Mage.Sets/src/mage/cards/a/AvatarOfSlaughter.java | 2 +- Mage.Sets/src/mage/cards/b/Berserk.java | 1 - Mage.Sets/src/mage/cards/c/ChargingCinderhorn.java | 2 +- Mage.Sets/src/mage/cards/e/ErgRaiders.java | 1 - Mage.Sets/src/mage/cards/f/FuryOfTheHorde.java | 1 - Mage.Sets/src/mage/cards/g/GrandMelee.java | 2 +- Mage.Sets/src/mage/cards/i/ImaginaryThreats.java | 1 - Mage.Sets/src/mage/cards/i/InciteWar.java | 1 - Mage.Sets/src/mage/cards/i/InfernoHellion.java | 1 - Mage.Sets/src/mage/cards/i/Instigator.java | 1 - Mage.Sets/src/mage/cards/i/InstillFuror.java | 2 +- Mage.Sets/src/mage/cards/i/Insubordination.java | 3 +-- Mage.Sets/src/mage/cards/i/InvasionOfGobakhan.java | 2 +- Mage.Sets/src/mage/cards/k/KardurDoomscourge.java | 1 - Mage.Sets/src/mage/cards/k/KeldonTwilight.java | 2 +- Mage.Sets/src/mage/cards/l/Lurker.java | 1 - Mage.Sets/src/mage/cards/m/MadDog.java | 1 - Mage.Sets/src/mage/cards/m/MaddeningImp.java | 2 +- Mage.Sets/src/mage/cards/m/MetzaliTowerOfTriumph.java | 1 - Mage.Sets/src/mage/cards/m/MoraugFuryOfAkoum.java | 2 +- Mage.Sets/src/mage/cards/n/NettlingImp.java | 2 +- Mage.Sets/src/mage/cards/n/Norritt.java | 2 +- Mage.Sets/src/mage/cards/o/OracleEnVec.java | 2 +- Mage.Sets/src/mage/cards/r/RelentlessAssault.java | 1 - Mage.Sets/src/mage/cards/r/RidersOfTheMark.java | 3 +-- Mage.Sets/src/mage/cards/r/RobberOfTheRich.java | 3 +-- Mage.Sets/src/mage/cards/s/SeasonOfTheWitch.java | 1 - Mage.Sets/src/mage/cards/s/SirensCall.java | 1 - Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java | 2 +- Mage.Sets/src/mage/cards/t/TheFifthDoctor.java | 4 ++-- Mage.Sets/src/mage/cards/v/VizierOfDeferment.java | 1 - Mage.Sets/src/mage/cards/w/WavesOfAggression.java | 1 - Mage.Sets/src/mage/cards/w/WeddingAnnouncement.java | 2 +- Mage.Sets/src/mage/cards/w/WorldAtWar.java | 2 +- .../abilities/common/AttacksFirstTimeTriggeredAbility.java | 1 - Mage/src/main/java/mage/abilities/keyword/BoastAbility.java | 1 - 38 files changed, 21 insertions(+), 43 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/Aggression.java b/Mage.Sets/src/mage/cards/a/Aggression.java index e5fd158f0a8..470f3b89da4 100644 --- a/Mage.Sets/src/mage/cards/a/Aggression.java +++ b/Mage.Sets/src/mage/cards/a/Aggression.java @@ -64,8 +64,7 @@ public final class Aggression extends CardImpl { new DestroyAttachedToEffect("enchanted"), TargetController.CONTROLLER_ATTACHED_TO), DidNotAttackThisTurnEnchantedCondition.instance, - "At the beginning of the end step of enchanted creature's controller, destroy that creature if it didn't attack this turn."), - new AttackedThisTurnWatcher()); + "At the beginning of the end step of enchanted creature's controller, destroy that creature if it didn't attack this turn.")); } diff --git a/Mage.Sets/src/mage/cards/a/AngelsTrumpet.java b/Mage.Sets/src/mage/cards/a/AngelsTrumpet.java index 0c09689fd7f..8826d33a545 100644 --- a/Mage.Sets/src/mage/cards/a/AngelsTrumpet.java +++ b/Mage.Sets/src/mage/cards/a/AngelsTrumpet.java @@ -31,7 +31,7 @@ public final class AngelsTrumpet extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(VigilanceAbility.getInstance(), Duration.WhileOnBattlefield, new FilterCreaturePermanent()))); // At the beginning of each player's end step, tap all untapped creatures that player controls that didn't attack this turn. Angel's Trumpet deals damage to the player equal to the number of creatures tapped this way. - this.addAbility(new BeginningOfEndStepTriggeredAbility(new AngelsTrumpetTapEffect(), TargetController.ANY, false), new AttackedThisTurnWatcher()); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new AngelsTrumpetTapEffect(), TargetController.ANY, false)); } private AngelsTrumpet(final AngelsTrumpet card) { diff --git a/Mage.Sets/src/mage/cards/a/AvatarOfSlaughter.java b/Mage.Sets/src/mage/cards/a/AvatarOfSlaughter.java index 7785ff2e6e3..bbc4f2ea311 100644 --- a/Mage.Sets/src/mage/cards/a/AvatarOfSlaughter.java +++ b/Mage.Sets/src/mage/cards/a/AvatarOfSlaughter.java @@ -37,7 +37,7 @@ public final class AvatarOfSlaughter extends CardImpl { effect = new AttacksIfAbleAllEffect(StaticFilters.FILTER_PERMANENT_CREATURES); effect.setText("and attack each combat if able"); ability.addEffect(effect); - this.addAbility(ability, new AttackedThisTurnWatcher()); + this.addAbility(ability); } private AvatarOfSlaughter(final AvatarOfSlaughter card) { diff --git a/Mage.Sets/src/mage/cards/b/Berserk.java b/Mage.Sets/src/mage/cards/b/Berserk.java index ec13f4322ae..f24a58c0ca0 100644 --- a/Mage.Sets/src/mage/cards/b/Berserk.java +++ b/Mage.Sets/src/mage/cards/b/Berserk.java @@ -47,7 +47,6 @@ public final class Berserk extends CardImpl { this.getSpellAbility().addEffect(effect); this.getSpellAbility().addEffect(new BerserkDestroyEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - this.getSpellAbility().addWatcher(new AttackedThisTurnWatcher()); } diff --git a/Mage.Sets/src/mage/cards/c/ChargingCinderhorn.java b/Mage.Sets/src/mage/cards/c/ChargingCinderhorn.java index 12d55ac3a33..29ae530ff93 100644 --- a/Mage.Sets/src/mage/cards/c/ChargingCinderhorn.java +++ b/Mage.Sets/src/mage/cards/c/ChargingCinderhorn.java @@ -40,7 +40,7 @@ public final class ChargingCinderhorn extends CardImpl { effect.setText("put a fury counter on {this}. Then {this} deals damage equal to the number of fury counters on it to that player"); BeginningOfEndStepTriggeredAbility ability = new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, effect, TargetController.ANY, new ChargingCinderhornCondition(), false); - this.addAbility(ability, new AttackedThisTurnWatcher()); + this.addAbility(ability); } private ChargingCinderhorn(final ChargingCinderhorn card) { diff --git a/Mage.Sets/src/mage/cards/e/ErgRaiders.java b/Mage.Sets/src/mage/cards/e/ErgRaiders.java index 5fcf9a75b64..22a7091b2fb 100644 --- a/Mage.Sets/src/mage/cards/e/ErgRaiders.java +++ b/Mage.Sets/src/mage/cards/e/ErgRaiders.java @@ -43,7 +43,6 @@ public final class ErgRaiders extends CardImpl { new BeginningOfEndStepTriggeredAbility(effect, TargetController.YOU, false), new InvertCondition(AttackedThisTurnSourceCondition.instance), "At the beginning of your end step, if {this} didn't attack this turn, {this} deals 2 damage to you unless it came under your control this turn."); - ability.addWatcher(new AttackedThisTurnWatcher()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/FuryOfTheHorde.java b/Mage.Sets/src/mage/cards/f/FuryOfTheHorde.java index f810bc6a9fd..7be92336414 100644 --- a/Mage.Sets/src/mage/cards/f/FuryOfTheHorde.java +++ b/Mage.Sets/src/mage/cards/f/FuryOfTheHorde.java @@ -36,7 +36,6 @@ public final class FuryOfTheHorde extends CardImpl { // Untap all creatures that attacked this turn. After this main phase, there is an additional combat phase followed by an additional main phase. this.getSpellAbility().addEffect(new UntapAllThatAttackedEffect()); this.getSpellAbility().addEffect(new AddCombatAndMainPhaseEffect()); - this.getSpellAbility().addWatcher(new AttackedThisTurnWatcher()); } diff --git a/Mage.Sets/src/mage/cards/g/GrandMelee.java b/Mage.Sets/src/mage/cards/g/GrandMelee.java index 82550b1a17b..d8680b3fff5 100644 --- a/Mage.Sets/src/mage/cards/g/GrandMelee.java +++ b/Mage.Sets/src/mage/cards/g/GrandMelee.java @@ -24,7 +24,7 @@ public final class GrandMelee extends CardImpl { // All creatures attack each turn if able. Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new AttacksIfAbleAllEffect(StaticFilters.FILTER_PERMANENT_CREATURES)); - this.addAbility(ability, new AttackedThisTurnWatcher()); + this.addAbility(ability); // All creatures block each turn if able. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BlocksIfAbleAllEffect(StaticFilters.FILTER_PERMANENT_CREATURES))); diff --git a/Mage.Sets/src/mage/cards/i/ImaginaryThreats.java b/Mage.Sets/src/mage/cards/i/ImaginaryThreats.java index cf37c07aa6e..3027a35d83b 100644 --- a/Mage.Sets/src/mage/cards/i/ImaginaryThreats.java +++ b/Mage.Sets/src/mage/cards/i/ImaginaryThreats.java @@ -32,7 +32,6 @@ public final class ImaginaryThreats extends CardImpl { // Creatures target opponent controls attack this turn if able. During that player's next untap step, creatures they control don't untap. getSpellAbility().addEffect(new ImaginaryThreatsEffect()); - getSpellAbility().addWatcher(new AttackedThisTurnWatcher()); getSpellAbility().addTarget(new TargetOpponent()); getSpellAbility().addEffect(new DontUntapInPlayersNextUntapStepAllEffect(new FilterCreaturePermanent()) .setText("During that player's next untap step, creatures they control don't untap")); diff --git a/Mage.Sets/src/mage/cards/i/InciteWar.java b/Mage.Sets/src/mage/cards/i/InciteWar.java index 91bba5d8a12..46960a39414 100644 --- a/Mage.Sets/src/mage/cards/i/InciteWar.java +++ b/Mage.Sets/src/mage/cards/i/InciteWar.java @@ -34,7 +34,6 @@ public final class InciteWar extends CardImpl { // Choose one - Creatures target player controls attack this turn if able; this.getSpellAbility().addEffect(new InciteWarMustAttackEffect()); this.getSpellAbility().addTarget(new TargetPlayer()); - this.getSpellAbility().addWatcher(new AttackedThisTurnWatcher()); // or creatures you control gain first strike until end of turn. Mode mode = new Mode(new GainAbilityControlledEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURES)); diff --git a/Mage.Sets/src/mage/cards/i/InfernoHellion.java b/Mage.Sets/src/mage/cards/i/InfernoHellion.java index df819ac8168..ab6e06604f5 100644 --- a/Mage.Sets/src/mage/cards/i/InfernoHellion.java +++ b/Mage.Sets/src/mage/cards/i/InfernoHellion.java @@ -45,7 +45,6 @@ public final class InfernoHellion extends CardImpl { + "if {this} attacked or blocked this turn, " + "its owner shuffles it into their library." ); - ability.addWatcher(new AttackedThisTurnWatcher()); ability.addWatcher(new BlockedThisTurnWatcher()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/i/Instigator.java b/Mage.Sets/src/mage/cards/i/Instigator.java index c516f9e5819..61cb4fb52fb 100644 --- a/Mage.Sets/src/mage/cards/i/Instigator.java +++ b/Mage.Sets/src/mage/cards/i/Instigator.java @@ -43,7 +43,6 @@ public final class Instigator extends CardImpl { ability.addCost(new TapSourceCost()); ability.addCost(new DiscardCardCost()); ability.addTarget(new TargetPlayer()); - ability.addWatcher(new AttackedThisTurnWatcher()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/i/InstillFuror.java b/Mage.Sets/src/mage/cards/i/InstillFuror.java index 31477705725..7632d6685dc 100644 --- a/Mage.Sets/src/mage/cards/i/InstillFuror.java +++ b/Mage.Sets/src/mage/cards/i/InstillFuror.java @@ -50,7 +50,7 @@ public final class InstillFuror extends CardImpl { "sacrifice this creature unless it attacked this turn"), TargetController.YOU, false); Effect effect = new GainAbilityAttachedEffect(gainedAbility, AttachmentType.AURA, Duration.WhileOnBattlefield); effect.setText("Enchanted creature has \"At the beginning of your end step, sacrifice this creature unless it attacked this turn.\""); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect), new AttackedThisTurnWatcher()); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); } diff --git a/Mage.Sets/src/mage/cards/i/Insubordination.java b/Mage.Sets/src/mage/cards/i/Insubordination.java index 531c5b72735..7e077dd2270 100644 --- a/Mage.Sets/src/mage/cards/i/Insubordination.java +++ b/Mage.Sets/src/mage/cards/i/Insubordination.java @@ -42,8 +42,7 @@ public final class Insubordination extends CardImpl { new DamageAttachedControllerEffect(2), TargetController.CONTROLLER_ATTACHED_TO), DidNotAttackThisTurnEnchantedCondition.instance, - "At the beginning of the end step of enchanted creature's controller, {this} deals 2 damage to that player unless that creature attacked this turn."), - new AttackedThisTurnWatcher()); + "At the beginning of the end step of enchanted creature's controller, {this} deals 2 damage to that player unless that creature attacked this turn.")); } private Insubordination(final Insubordination card) { diff --git a/Mage.Sets/src/mage/cards/i/InvasionOfGobakhan.java b/Mage.Sets/src/mage/cards/i/InvasionOfGobakhan.java index 633c0038f06..534e621bc6c 100644 --- a/Mage.Sets/src/mage/cards/i/InvasionOfGobakhan.java +++ b/Mage.Sets/src/mage/cards/i/InvasionOfGobakhan.java @@ -40,7 +40,7 @@ public final class InvasionOfGobakhan extends CardImpl { // When Invasion of Gobakhan enters the battlefield, look at target opponent's hand. You may exile a nonland card from it. For as long as that card remains exiled, its owner may play it. A spell cast this way costs {2} more to cast. Ability ability = new EntersBattlefieldTriggeredAbility(new InvasionOfGobakhanEffect()); ability.addTarget(new TargetOpponent()); - this.addAbility(ability, new AttackedThisTurnWatcher()); + this.addAbility(ability); } private InvasionOfGobakhan(final InvasionOfGobakhan card) { diff --git a/Mage.Sets/src/mage/cards/k/KardurDoomscourge.java b/Mage.Sets/src/mage/cards/k/KardurDoomscourge.java index 8aa552a8bf7..7572404f937 100644 --- a/Mage.Sets/src/mage/cards/k/KardurDoomscourge.java +++ b/Mage.Sets/src/mage/cards/k/KardurDoomscourge.java @@ -39,7 +39,6 @@ public final class KardurDoomscourge extends CardImpl { StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE, Duration.UntilYourNextTurn ).setText("until your next turn, creatures your opponents control attack each combat if able")); ability.addEffect(new KardurDoomscourgeEffect()); - ability.addWatcher(new AttackedThisTurnWatcher()); this.addAbility(ability); // Whenever an attacking creature dies, each opponent loses 1 life and you gain 1 life. diff --git a/Mage.Sets/src/mage/cards/k/KeldonTwilight.java b/Mage.Sets/src/mage/cards/k/KeldonTwilight.java index 33ae159fe52..e3144d2fd88 100644 --- a/Mage.Sets/src/mage/cards/k/KeldonTwilight.java +++ b/Mage.Sets/src/mage/cards/k/KeldonTwilight.java @@ -37,7 +37,7 @@ public final class KeldonTwilight extends CardImpl { effect.setText("that player sacrifices a creature they controlled since the beginning of the turn"); BeginningOfEndStepTriggeredAbility ability = new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, effect, TargetController.ANY, new KeldonTwilightCondition(), false); - this.addAbility(ability, new AttackedThisTurnWatcher()); + this.addAbility(ability); } private KeldonTwilight(final KeldonTwilight card) { diff --git a/Mage.Sets/src/mage/cards/l/Lurker.java b/Mage.Sets/src/mage/cards/l/Lurker.java index 2627aff0812..e49aa6bfe47 100644 --- a/Mage.Sets/src/mage/cards/l/Lurker.java +++ b/Mage.Sets/src/mage/cards/l/Lurker.java @@ -39,7 +39,6 @@ public final class Lurker extends CardImpl { new CantBeTargetedSourceEffect(new FilterSpell(), Duration.WhileOnBattlefield), new InvertCondition(new OrCondition(AttackedThisTurnSourceCondition.instance, BlockedThisTurnSourceCondition.instance))); Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect.setText("{this} can't be the target of spells unless it attacked or blocked this turn")); - ability.addWatcher(new AttackedThisTurnWatcher()); ability.addWatcher(new BlockedThisTurnWatcher()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MadDog.java b/Mage.Sets/src/mage/cards/m/MadDog.java index d451b2813c8..4cf9161da0d 100644 --- a/Mage.Sets/src/mage/cards/m/MadDog.java +++ b/Mage.Sets/src/mage/cards/m/MadDog.java @@ -38,7 +38,6 @@ public final class MadDog extends CardImpl { Ability ability = new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility( new SacrificeSourceEffect(), TargetController.YOU, false), condition, "At the beginning of your end step, if {this} didn't attack or come under your control this turn, sacrifice it"); - ability.addWatcher(new AttackedThisTurnWatcher()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MaddeningImp.java b/Mage.Sets/src/mage/cards/m/MaddeningImp.java index fa03f73daa0..06a989f264d 100644 --- a/Mage.Sets/src/mage/cards/m/MaddeningImp.java +++ b/Mage.Sets/src/mage/cards/m/MaddeningImp.java @@ -56,7 +56,7 @@ public final class MaddeningImp extends CardImpl { + "At the beginning of the next end step, destroy each of those creatures that didn't attack this turn. " + "Activate only during an opponent's turn and only before combat."); ability.addEffect(new MaddeningImpCreateDelayedTriggeredAbilityEffect()); - this.addAbility(ability, new AttackedThisTurnWatcher()); + this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MetzaliTowerOfTriumph.java b/Mage.Sets/src/mage/cards/m/MetzaliTowerOfTriumph.java index 01043b63781..a148866056b 100644 --- a/Mage.Sets/src/mage/cards/m/MetzaliTowerOfTriumph.java +++ b/Mage.Sets/src/mage/cards/m/MetzaliTowerOfTriumph.java @@ -50,7 +50,6 @@ public final class MetzaliTowerOfTriumph extends CardImpl { // {2}{W}, {T}: Choose a creature at random that attacked this turn. Destroy that creature. ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MetzaliTowerOfTriumphEffect(), new ManaCostsImpl<>("{2}{W}")); ability.addCost(new TapSourceCost()); - ability.addWatcher(new AttackedThisTurnWatcher()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MoraugFuryOfAkoum.java b/Mage.Sets/src/mage/cards/m/MoraugFuryOfAkoum.java index d02ea14be07..9728b92ca72 100644 --- a/Mage.Sets/src/mage/cards/m/MoraugFuryOfAkoum.java +++ b/Mage.Sets/src/mage/cards/m/MoraugFuryOfAkoum.java @@ -37,7 +37,7 @@ public final class MoraugFuryOfAkoum extends CardImpl { this.toughness = new MageInt(6); // Each creature you control gets +1/+0 for each time it has attacked this turn. - this.addAbility(new SimpleStaticAbility(new MoraugFuryOfAkoumBoostEffect()), new AttackedThisTurnWatcher()); + this.addAbility(new SimpleStaticAbility(new MoraugFuryOfAkoumBoostEffect())); // Landfall — Whenever a land enters the battlefield under your control, if it's your main phase, there's an additional combat phase after this phase. At the beginning of that combat, untap all creatures you control. this.addAbility(new ConditionalInterveningIfTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/n/NettlingImp.java b/Mage.Sets/src/mage/cards/n/NettlingImp.java index eed3ea63884..48f8a7da94b 100644 --- a/Mage.Sets/src/mage/cards/n/NettlingImp.java +++ b/Mage.Sets/src/mage/cards/n/NettlingImp.java @@ -54,7 +54,7 @@ public final class NettlingImp extends CardImpl { + "Activate only during an opponent's turn, before attackers are declared."); ability.addEffect(new NettlingImpDelayedDestroyEffect()); ability.addTarget(new TargetCreaturePermanent(filter)); - this.addAbility(ability, new AttackedThisTurnWatcher()); + this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/Norritt.java b/Mage.Sets/src/mage/cards/n/Norritt.java index 9e034364049..a12b3fdc1d9 100644 --- a/Mage.Sets/src/mage/cards/n/Norritt.java +++ b/Mage.Sets/src/mage/cards/n/Norritt.java @@ -69,7 +69,7 @@ public final class Norritt extends CardImpl { + "Activate only before attackers are declared."); ability2.addEffect(new NorrittDelayedDestroyEffect()); ability2.addTarget(new TargetCreaturePermanent(filterCreature)); - this.addAbility(ability2, new AttackedThisTurnWatcher()); + this.addAbility(ability2); } diff --git a/Mage.Sets/src/mage/cards/o/OracleEnVec.java b/Mage.Sets/src/mage/cards/o/OracleEnVec.java index 85619582235..042c879eed7 100644 --- a/Mage.Sets/src/mage/cards/o/OracleEnVec.java +++ b/Mage.Sets/src/mage/cards/o/OracleEnVec.java @@ -49,7 +49,7 @@ public final class OracleEnVec extends CardImpl { Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new OracleEnVecEffect(), new TapSourceCost(), MyTurnCondition.instance); ability.addTarget(new TargetOpponent()); ability.addHint(MyTurnHint.instance); - this.addAbility(ability, new AttackedThisTurnWatcher()); + this.addAbility(ability); } private OracleEnVec(final OracleEnVec card) { diff --git a/Mage.Sets/src/mage/cards/r/RelentlessAssault.java b/Mage.Sets/src/mage/cards/r/RelentlessAssault.java index a3679f29b51..f4ed42f3842 100644 --- a/Mage.Sets/src/mage/cards/r/RelentlessAssault.java +++ b/Mage.Sets/src/mage/cards/r/RelentlessAssault.java @@ -19,7 +19,6 @@ public final class RelentlessAssault extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{R}{R}"); // Untap all creatures that attacked this turn. After this main phase, there is an additional combat phase followed by an additional main phase. - this.getSpellAbility().addWatcher(new AttackedThisTurnWatcher()); this.getSpellAbility().addEffect(new UntapAllThatAttackedEffect()); this.getSpellAbility().addEffect(new AddCombatAndMainPhaseEffect()); } diff --git a/Mage.Sets/src/mage/cards/r/RidersOfTheMark.java b/Mage.Sets/src/mage/cards/r/RidersOfTheMark.java index 11fe9b1d576..e80086b9ea7 100644 --- a/Mage.Sets/src/mage/cards/r/RidersOfTheMark.java +++ b/Mage.Sets/src/mage/cards/r/RidersOfTheMark.java @@ -71,7 +71,6 @@ public final class RidersOfTheMark extends CardImpl { + "1/1 white Human Soldier creature tokens equal to its toughness." )); - this.getSpellAbility().addWatcher(new AttackedThisTurnWatcher()); } private RidersOfTheMark(final RidersOfTheMark card) { @@ -120,4 +119,4 @@ class RidersOfTheMarkEffect extends OneShotEffect { return true; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/r/RobberOfTheRich.java b/Mage.Sets/src/mage/cards/r/RobberOfTheRich.java index 4d8298f83d5..2ab326cebe2 100644 --- a/Mage.Sets/src/mage/cards/r/RobberOfTheRich.java +++ b/Mage.Sets/src/mage/cards/r/RobberOfTheRich.java @@ -52,7 +52,7 @@ public final class RobberOfTheRich extends CardImpl { "if defending player has more cards in hand than you, exile the top card of their library. " + "During any turn you attacked with a Rogue, you may cast that card and " + "you may spend mana as though it were mana of any color to cast that spell." - ).addHint(new ConditionHint(new RogueAttackedThisTurnCondition(null))), new AttackedThisTurnWatcher()); + ).addHint(new ConditionHint(new RogueAttackedThisTurnCondition(null)))); } private RobberOfTheRich(final RobberOfTheRich card) { @@ -163,4 +163,3 @@ class RobberOfTheRichEffect extends OneShotEffect { return false; } } - diff --git a/Mage.Sets/src/mage/cards/s/SeasonOfTheWitch.java b/Mage.Sets/src/mage/cards/s/SeasonOfTheWitch.java index 21d0518e9c7..b047f23b55a 100644 --- a/Mage.Sets/src/mage/cards/s/SeasonOfTheWitch.java +++ b/Mage.Sets/src/mage/cards/s/SeasonOfTheWitch.java @@ -43,7 +43,6 @@ public final class SeasonOfTheWitch extends CardImpl { // At the beginning of the end step, destroy all untapped creatures that didn't attack this turn, except for creatures that couldn't attack. Ability ability = new BeginningOfEndStepTriggeredAbility(new SeasonOfTheWitchEffect(), TargetController.ANY, false); - ability.addWatcher(new AttackedThisTurnWatcher()); ability.addWatcher(new CouldAttackThisTurnWatcher()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SirensCall.java b/Mage.Sets/src/mage/cards/s/SirensCall.java index b197b728aab..124398e2e98 100644 --- a/Mage.Sets/src/mage/cards/s/SirensCall.java +++ b/Mage.Sets/src/mage/cards/s/SirensCall.java @@ -42,7 +42,6 @@ public final class SirensCall extends CardImpl { // At the beginning of the next end step, destroy all non-Wall creatures that player controls that didn't attack this turn. Ignore this effect for each creature the player didn't control continuously since the beginning of the turn. this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new SirensCallDestroyEffect()))); - this.getSpellAbility().addWatcher(new AttackedThisTurnWatcher()); } private SirensCall(final SirensCall card) { diff --git a/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java b/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java index 5541b193e0c..bcacae3449c 100644 --- a/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java +++ b/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java @@ -57,7 +57,7 @@ public final class TaigamOjutaiMaster extends CardImpl { Ability ability = new ConditionalInterveningIfTriggeredAbility(new TaigamOjutaiMasterTriggeredAbility(), AttackedThisTurnSourceCondition.instance, effectText); - this.addAbility(ability, new AttackedThisTurnWatcher()); + this.addAbility(ability); } private TaigamOjutaiMaster(final TaigamOjutaiMaster card) { diff --git a/Mage.Sets/src/mage/cards/t/TheFifthDoctor.java b/Mage.Sets/src/mage/cards/t/TheFifthDoctor.java index 4fe139b6d4c..bac63d60da2 100644 --- a/Mage.Sets/src/mage/cards/t/TheFifthDoctor.java +++ b/Mage.Sets/src/mage/cards/t/TheFifthDoctor.java @@ -52,7 +52,7 @@ public final class TheFifthDoctor extends CardImpl { TargetController.YOU, false ); ability.addEffect(new UntapAllEffect(filter).setText("Untap those creatures")); - this.addAbility(ability.withFlavorWord("Peaceful Coexistence"), new AttackedThisTurnWatcher()); + this.addAbility(ability.withFlavorWord("Peaceful Coexistence")); } private TheFifthDoctor(final TheFifthDoctor card) { @@ -72,4 +72,4 @@ enum TheFifthDoctorPredicate implements Predicate { public boolean apply(Permanent input, Game game) { return !game.getState().getWatcher(AttackedThisTurnWatcher.class).checkIfAttacked(input, game); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/v/VizierOfDeferment.java b/Mage.Sets/src/mage/cards/v/VizierOfDeferment.java index efef911ca39..b77e64c3b9a 100644 --- a/Mage.Sets/src/mage/cards/v/VizierOfDeferment.java +++ b/Mage.Sets/src/mage/cards/v/VizierOfDeferment.java @@ -40,7 +40,6 @@ public final class VizierOfDeferment extends CardImpl { // When Vizier of Deferment enters the battlefield, you may exile target creature if it attacked or blocked this turn. Return that card to the battlefield under its owner's control at the beginning of the next end step. Ability ability = new EntersBattlefieldTriggeredAbility(new VizierOfDefermentEffect(), true); ability.addTarget(new TargetCreaturePermanent()); - ability.addWatcher(new AttackedThisTurnWatcher()); ability.addWatcher(new BlockedThisTurnWatcher()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WavesOfAggression.java b/Mage.Sets/src/mage/cards/w/WavesOfAggression.java index f74ca589175..96a8dac9fec 100644 --- a/Mage.Sets/src/mage/cards/w/WavesOfAggression.java +++ b/Mage.Sets/src/mage/cards/w/WavesOfAggression.java @@ -20,7 +20,6 @@ public final class WavesOfAggression extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{R/W}{R/W}"); // Untap all creatures that attacked this turn. After this main phase, there is an additional combat phase followed by an additional main phase. - this.getSpellAbility().addWatcher(new AttackedThisTurnWatcher()); this.getSpellAbility().addEffect(new UntapAllThatAttackedEffect()); this.getSpellAbility().addEffect(new AddCombatAndMainPhaseEffect()); // Retrace diff --git a/Mage.Sets/src/mage/cards/w/WeddingAnnouncement.java b/Mage.Sets/src/mage/cards/w/WeddingAnnouncement.java index b4c84d8afd7..3a4738eca62 100644 --- a/Mage.Sets/src/mage/cards/w/WeddingAnnouncement.java +++ b/Mage.Sets/src/mage/cards/w/WeddingAnnouncement.java @@ -48,7 +48,7 @@ public final class WeddingAnnouncement extends CardImpl { new SourceHasCounterCondition(CounterType.INVITATION, 3), "Then if {this} has three or more invitation counters on it, transform it" )); - this.addAbility(ability, new AttackedThisTurnWatcher()); + this.addAbility(ability); } private WeddingAnnouncement(final WeddingAnnouncement card) { diff --git a/Mage.Sets/src/mage/cards/w/WorldAtWar.java b/Mage.Sets/src/mage/cards/w/WorldAtWar.java index 5dfbbd898d5..031484aede1 100644 --- a/Mage.Sets/src/mage/cards/w/WorldAtWar.java +++ b/Mage.Sets/src/mage/cards/w/WorldAtWar.java @@ -32,7 +32,7 @@ public final class WorldAtWar extends CardImpl { this.getSpellAbility().addEffect(new WorldAtWarEffect()); // Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.) - this.addAbility(new ReboundAbility(), new AttackedThisTurnWatcher()); + this.addAbility(new ReboundAbility()); } private WorldAtWar(final WorldAtWar card) { diff --git a/Mage/src/main/java/mage/abilities/common/AttacksFirstTimeTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/AttacksFirstTimeTriggeredAbility.java index 54bedb60434..1b08b4add72 100644 --- a/Mage/src/main/java/mage/abilities/common/AttacksFirstTimeTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/AttacksFirstTimeTriggeredAbility.java @@ -17,7 +17,6 @@ public class AttacksFirstTimeTriggeredAbility extends TriggeredAbilityImpl { public AttacksFirstTimeTriggeredAbility(Effect effect, boolean optional) { super(Zone.BATTLEFIELD, effect, optional); - this.addWatcher(new AttackedThisTurnWatcher()); setTriggerPhrase("Whenever {this} attacks for the first time each turn, "); } diff --git a/Mage/src/main/java/mage/abilities/keyword/BoastAbility.java b/Mage/src/main/java/mage/abilities/keyword/BoastAbility.java index 843f862b067..5a88e50ddbd 100644 --- a/Mage/src/main/java/mage/abilities/keyword/BoastAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/BoastAbility.java @@ -28,7 +28,6 @@ public class BoastAbility extends ActivatedAbilityImpl { public BoastAbility(Effect effect, Cost cost) { super(Zone.BATTLEFIELD, effect, cost); this.maxActivationsPerTurn = 1; - this.addWatcher(new AttackedThisTurnWatcher()); this.condition = BoastCondition.instance; this.addHint(BoastHint.instance); } From 37722a58c2fba0ef8adccdb13dce7cdddef5103e Mon Sep 17 00:00:00 2001 From: xenohedron Date: Wed, 29 Nov 2023 20:32:36 -0500 Subject: [PATCH 02/10] more watcher cleanup --- Mage.Sets/src/mage/cards/d/DampingSphere.java | 2 +- Mage.Sets/src/mage/cards/e/ErtaisScorn.java | 2 +- Mage.Sets/src/mage/cards/m/MagusOfTheMind.java | 2 +- Mage.Sets/src/mage/cards/r/RevengeStarWars.java | 2 -- Mage.Sets/src/mage/cards/r/RowanScionOfWar.java | 3 +-- Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java | 2 +- .../mage/abilities/common/CastSecondSpellTriggeredAbility.java | 3 +-- .../java/mage/watchers/common/CastSpellLastTurnWatcher.java | 3 +++ Mage/src/main/java/mage/watchers/common/MorbidWatcher.java | 3 +++ .../main/java/mage/watchers/common/PlayerLostLifeWatcher.java | 3 +++ 10 files changed, 15 insertions(+), 10 deletions(-) diff --git a/Mage.Sets/src/mage/cards/d/DampingSphere.java b/Mage.Sets/src/mage/cards/d/DampingSphere.java index 85ec52afbd9..21e9b2a2ad6 100644 --- a/Mage.Sets/src/mage/cards/d/DampingSphere.java +++ b/Mage.Sets/src/mage/cards/d/DampingSphere.java @@ -34,7 +34,7 @@ public final class DampingSphere extends CardImpl { this.addAbility(new SimpleStaticAbility(new DampingSphereReplacementEffect())); // Each spell a player casts costs {1} more to cast for each other spell that player has cast this turn. - this.addAbility(new SimpleStaticAbility(new DampingSphereIncreasementAllEffect()), new CastSpellLastTurnWatcher()); + this.addAbility(new SimpleStaticAbility(new DampingSphereIncreasementAllEffect())); } private DampingSphere(final DampingSphere card) { diff --git a/Mage.Sets/src/mage/cards/e/ErtaisScorn.java b/Mage.Sets/src/mage/cards/e/ErtaisScorn.java index 478f61bf52c..22ff09843b2 100644 --- a/Mage.Sets/src/mage/cards/e/ErtaisScorn.java +++ b/Mage.Sets/src/mage/cards/e/ErtaisScorn.java @@ -32,7 +32,7 @@ public final class ErtaisScorn extends CardImpl { new ManaCostsImpl<>("{U}"), ErtaisScornCondition.instance ) - ).setRuleAtTheTop(true), new CastSpellLastTurnWatcher()); + ).setRuleAtTheTop(true)); // Counter target spell. this.getSpellAbility().addTarget(new TargetSpell()); diff --git a/Mage.Sets/src/mage/cards/m/MagusOfTheMind.java b/Mage.Sets/src/mage/cards/m/MagusOfTheMind.java index 657582f7874..de973a9816c 100644 --- a/Mage.Sets/src/mage/cards/m/MagusOfTheMind.java +++ b/Mage.Sets/src/mage/cards/m/MagusOfTheMind.java @@ -37,7 +37,7 @@ public final class MagusOfTheMind extends CardImpl { Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MagusOfTheMindEffect(), new ManaCostsImpl<>("{U}")); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); - this.addAbility(ability, new CastSpellLastTurnWatcher()); + this.addAbility(ability); } private MagusOfTheMind(final MagusOfTheMind card) { diff --git a/Mage.Sets/src/mage/cards/r/RevengeStarWars.java b/Mage.Sets/src/mage/cards/r/RevengeStarWars.java index 6434524b848..b13bd4461b0 100644 --- a/Mage.Sets/src/mage/cards/r/RevengeStarWars.java +++ b/Mage.Sets/src/mage/cards/r/RevengeStarWars.java @@ -40,8 +40,6 @@ public final class RevengeStarWars extends CardImpl { this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); this.getSpellAbility().addTarget(new TargetOpponentsCreaturePermanent()); - this.getSpellAbility().addWatcher(new PlayerLostLifeWatcher()); - } private RevengeStarWars(final RevengeStarWars card) { diff --git a/Mage.Sets/src/mage/cards/r/RowanScionOfWar.java b/Mage.Sets/src/mage/cards/r/RowanScionOfWar.java index 880baa8e242..020ed82407b 100644 --- a/Mage.Sets/src/mage/cards/r/RowanScionOfWar.java +++ b/Mage.Sets/src/mage/cards/r/RowanScionOfWar.java @@ -40,8 +40,7 @@ public final class RowanScionOfWar extends CardImpl { new ActivateAsSorceryActivatedAbility( new RowanScionOfWarEffect(), new TapSourceCost() - ).addHint(ControllerLostLifeCount.getHint()), - new PlayerLostLifeWatcher() + ).addHint(ControllerLostLifeCount.getHint()) ); } diff --git a/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java b/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java index 19cefafbc3f..c088e5696f4 100644 --- a/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java +++ b/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java @@ -44,7 +44,7 @@ public final class VancesBlastingCannons extends CardImpl { // Whenever you cast your third spell in a turn, transform Vance's Blasting Cannons. this.addAbility(new TransformAbility()); - this.addAbility(new VancesBlastingCannonsFlipTrigger(), new CastSpellLastTurnWatcher()); + this.addAbility(new VancesBlastingCannonsFlipTrigger()); } private VancesBlastingCannons(final VancesBlastingCannons card) { diff --git a/Mage/src/main/java/mage/abilities/common/CastSecondSpellTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/CastSecondSpellTriggeredAbility.java index 59e21abf841..d3918d0dfa6 100644 --- a/Mage/src/main/java/mage/abilities/common/CastSecondSpellTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/CastSecondSpellTriggeredAbility.java @@ -46,7 +46,6 @@ public class CastSecondSpellTriggeredAbility extends TriggeredAbilityImpl { public CastSecondSpellTriggeredAbility(Zone zone, Effect effect, TargetController targetController, boolean optional, SetTargetPointer setTargetPointer) { super(zone, effect, optional); - this.addWatcher(new CastSpellLastTurnWatcher()); if (targetController == TargetController.YOU) { this.addHint(hint); } @@ -147,4 +146,4 @@ enum SpellCastValue implements DynamicValue { public String getMessage() { return ""; } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/watchers/common/CastSpellLastTurnWatcher.java b/Mage/src/main/java/mage/watchers/common/CastSpellLastTurnWatcher.java index 5a6ec9fbecb..399c0af8d23 100644 --- a/Mage/src/main/java/mage/watchers/common/CastSpellLastTurnWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/CastSpellLastTurnWatcher.java @@ -19,6 +19,9 @@ public class CastSpellLastTurnWatcher extends Watcher { private int activePlayerPrevTurnCount = 0; private int activePlayerThisTurnCount = 0; + /** + * Game default watcher + */ public CastSpellLastTurnWatcher() { super(WatcherScope.GAME); } diff --git a/Mage/src/main/java/mage/watchers/common/MorbidWatcher.java b/Mage/src/main/java/mage/watchers/common/MorbidWatcher.java index 7f500cbb596..e3713c14c33 100644 --- a/Mage/src/main/java/mage/watchers/common/MorbidWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/MorbidWatcher.java @@ -13,6 +13,9 @@ import mage.watchers.Watcher; */ public class MorbidWatcher extends Watcher { + /** + * Game default watcher + */ public MorbidWatcher() { super(WatcherScope.GAME); } diff --git a/Mage/src/main/java/mage/watchers/common/PlayerLostLifeWatcher.java b/Mage/src/main/java/mage/watchers/common/PlayerLostLifeWatcher.java index 9ba85f84b6e..89c03aeda2a 100644 --- a/Mage/src/main/java/mage/watchers/common/PlayerLostLifeWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/PlayerLostLifeWatcher.java @@ -21,6 +21,9 @@ public class PlayerLostLifeWatcher extends Watcher { private final Map amountOfLifeLostThisTurn = new HashMap<>(); private final Map amountOfLifeLostLastTurn = new HashMap<>(); + /** + * Game default watcher + */ public PlayerLostLifeWatcher() { super(WatcherScope.GAME); } From f801c9851e6458958d0b40bc4a1c1a0586cc5e19 Mon Sep 17 00:00:00 2001 From: xenohedron Date: Wed, 29 Nov 2023 20:37:19 -0500 Subject: [PATCH 03/10] move watchers used only in Arboria effect --- Mage.Sets/src/mage/cards/a/Arboria.java | 107 ++++++++++++++++-- Mage/src/main/java/mage/game/GameImpl.java | 1 - .../common/CastSpellYourLastTurnWatcher.java | 59 ---------- ...EnteredBattlefieldYourLastTurnWatcher.java | 65 ----------- 4 files changed, 99 insertions(+), 133 deletions(-) delete mode 100644 Mage/src/main/java/mage/watchers/common/CastSpellYourLastTurnWatcher.java delete mode 100644 Mage/src/main/java/mage/watchers/common/PermanentsEnteredBattlefieldYourLastTurnWatcher.java diff --git a/Mage.Sets/src/mage/cards/a/Arboria.java b/Mage.Sets/src/mage/cards/a/Arboria.java index 7c09e1f4df5..7111fce0d0b 100644 --- a/Mage.Sets/src/mage/cards/a/Arboria.java +++ b/Mage.Sets/src/mage/cards/a/Arboria.java @@ -5,17 +5,14 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.RestrictionEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.SuperType; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; +import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.permanent.PermanentToken; -import mage.watchers.common.CastSpellYourLastTurnWatcher; -import mage.watchers.common.PermanentsEnteredBattlefieldYourLastTurnWatcher; +import mage.watchers.Watcher; -import java.util.UUID; +import java.util.*; /** * @author spjspj @@ -28,7 +25,10 @@ public final class Arboria extends CardImpl { this.supertype.add(SuperType.WORLD); // Creatures can't attack a player unless that player cast a spell or put a nontoken permanent onto the battlefield during their last turn. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ArboriaEffect()), new PermanentsEnteredBattlefieldYourLastTurnWatcher()); + Ability ability = new SimpleStaticAbility(new ArboriaEffect()); + ability.addWatcher(new PermanentsEnteredBattlefieldYourLastTurnWatcher()); + ability.addWatcher(new CastSpellYourLastTurnWatcher()); + this.addAbility(ability); } private Arboria(final Arboria card) { @@ -90,3 +90,94 @@ class ArboriaEffect extends RestrictionEffect { return true; } } + +class CastSpellYourLastTurnWatcher extends Watcher { + + private final Map amountOfSpellsCastOnPrevTurn = new HashMap<>(); + private final Map amountOfSpellsCastOnCurrentTurn = new HashMap<>(); + private UUID lastActivePlayer = null; + + CastSpellYourLastTurnWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + lastActivePlayer = game.getActivePlayerId(); + if (event.getType() == GameEvent.EventType.SPELL_CAST) { + UUID playerId = event.getPlayerId(); + if (playerId != null && playerId.equals(lastActivePlayer)) { + amountOfSpellsCastOnCurrentTurn.putIfAbsent(playerId, 0); + amountOfSpellsCastOnCurrentTurn.compute(playerId, (k, a) -> a + 1); + } + } + } + + @Override + public void reset() { + super.reset(); + if (lastActivePlayer != null && amountOfSpellsCastOnPrevTurn.get(lastActivePlayer) != null) { + amountOfSpellsCastOnPrevTurn.remove(lastActivePlayer); + } + + amountOfSpellsCastOnPrevTurn.putAll(amountOfSpellsCastOnCurrentTurn); + amountOfSpellsCastOnCurrentTurn.clear(); + lastActivePlayer = null; + } + + public Integer getAmountOfSpellsCastOnPlayersTurn(UUID playerId) { + return amountOfSpellsCastOnPrevTurn.getOrDefault(playerId, 0); + } + +} + +class PermanentsEnteredBattlefieldYourLastTurnWatcher extends Watcher { + + private final Map> enteringBattlefield = new HashMap<>(); + private final Map> enteringBattlefieldLastTurn = new HashMap<>(); + private UUID lastActivePlayer = null; + + PermanentsEnteredBattlefieldYourLastTurnWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + lastActivePlayer = game.getActivePlayerId(); + + if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) { + Permanent perm = game.getPermanentEntering(event.getTargetId()); + if (perm == null) { + perm = game.getPermanent(event.getTargetId()); + } + if (perm != null) { + List permanents; + if (!enteringBattlefield.containsKey(perm.getControllerId())) { + permanents = new ArrayList<>(); + enteringBattlefield.put(perm.getControllerId(), permanents); + } else { + permanents = enteringBattlefield.get(perm.getControllerId()); + } + permanents.add(perm.copy()); // copy needed because attributes like color could be changed later + } + } + } + + @Override + public void reset() { + super.reset(); + if (lastActivePlayer != null && enteringBattlefieldLastTurn.get(lastActivePlayer) != null) { + enteringBattlefieldLastTurn.remove(lastActivePlayer); + } + enteringBattlefieldLastTurn.putAll(enteringBattlefield); + enteringBattlefield.clear(); + lastActivePlayer = null; + } + + public List getPermanentsEnteringOnPlayersLastTurn(Game game, UUID playerId) { + if (game.isActivePlayer(playerId)) { + return enteringBattlefield.get(playerId); + } + return enteringBattlefieldLastTurn.get(playerId); + } +} diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 22e2e56f407..2b88e1d4b2d 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -1338,7 +1338,6 @@ public abstract class GameImpl implements Game { List newWatchers = new ArrayList<>(); newWatchers.add(new MorbidWatcher()); newWatchers.add(new CastSpellLastTurnWatcher()); - newWatchers.add(new CastSpellYourLastTurnWatcher()); newWatchers.add(new PlayerLostLifeWatcher()); newWatchers.add(new PlayerLostLifeNonCombatWatcher()); newWatchers.add(new BlockedAttackerWatcher()); diff --git a/Mage/src/main/java/mage/watchers/common/CastSpellYourLastTurnWatcher.java b/Mage/src/main/java/mage/watchers/common/CastSpellYourLastTurnWatcher.java deleted file mode 100644 index d398e8cd038..00000000000 --- a/Mage/src/main/java/mage/watchers/common/CastSpellYourLastTurnWatcher.java +++ /dev/null @@ -1,59 +0,0 @@ -package mage.watchers.common; - -import mage.constants.WatcherScope; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.watchers.Watcher; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -/** - * @author nantuko, BetaSteward_at_googlemail.com (spjspj) - */ -public class CastSpellYourLastTurnWatcher extends Watcher { - - private final Map amountOfSpellsCastOnPrevTurn = new HashMap<>(); - private final Map amountOfSpellsCastOnCurrentTurn = new HashMap<>(); - private UUID lastActivePlayer = null; - - public CastSpellYourLastTurnWatcher() { - super(WatcherScope.GAME); - } - - @Override - public void watch(GameEvent event, Game game) { - lastActivePlayer = game.getActivePlayerId(); - if (event.getType() == GameEvent.EventType.SPELL_CAST) { - UUID playerId = event.getPlayerId(); - if (playerId != null && playerId.equals(lastActivePlayer)) { - amountOfSpellsCastOnCurrentTurn.putIfAbsent(playerId, 0); - amountOfSpellsCastOnCurrentTurn.compute(playerId, (k, a) -> a + 1); - } - } - } - - @Override - public void reset() { - super.reset(); - if (amountOfSpellsCastOnPrevTurn != null - && lastActivePlayer != null - && amountOfSpellsCastOnPrevTurn.get(lastActivePlayer) != null) { - amountOfSpellsCastOnPrevTurn.remove(lastActivePlayer); - } - - amountOfSpellsCastOnPrevTurn.putAll(amountOfSpellsCastOnCurrentTurn); - amountOfSpellsCastOnCurrentTurn.clear(); - lastActivePlayer = null; - } - - public Integer getAmountOfSpellsCastOnPlayersTurn(UUID playerId) { - return amountOfSpellsCastOnPrevTurn.getOrDefault(playerId, 0); - } -// -// @Override -// public CastSpellYourLastTurnWatcher copy() { -// return new CastSpellYourLastTurnWatcher(this); -// } -} diff --git a/Mage/src/main/java/mage/watchers/common/PermanentsEnteredBattlefieldYourLastTurnWatcher.java b/Mage/src/main/java/mage/watchers/common/PermanentsEnteredBattlefieldYourLastTurnWatcher.java deleted file mode 100644 index 78a9f83a473..00000000000 --- a/Mage/src/main/java/mage/watchers/common/PermanentsEnteredBattlefieldYourLastTurnWatcher.java +++ /dev/null @@ -1,65 +0,0 @@ -package mage.watchers.common; - -import mage.constants.WatcherScope; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; -import mage.watchers.Watcher; - -import java.util.*; - -/** - * @author LevelX2 (spjspj) - */ -public class PermanentsEnteredBattlefieldYourLastTurnWatcher extends Watcher { - - private final Map> enteringBattlefield = new HashMap<>(); - private final Map> enteringBattlefieldLastTurn = new HashMap<>(); - private UUID lastActivePlayer = null; - - public PermanentsEnteredBattlefieldYourLastTurnWatcher() { - super(WatcherScope.GAME); - } - - @Override - public void watch(GameEvent event, Game game) { - lastActivePlayer = game.getActivePlayerId(); - - if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) { - Permanent perm = game.getPermanentEntering(event.getTargetId()); - if (perm == null) { - perm = game.getPermanent(event.getTargetId()); - } - if (perm != null) { - List permanents; - if (!enteringBattlefield.containsKey(perm.getControllerId())) { - permanents = new ArrayList<>(); - enteringBattlefield.put(perm.getControllerId(), permanents); - } else { - permanents = enteringBattlefield.get(perm.getControllerId()); - } - permanents.add(perm.copy()); // copy needed because attributes like color could be changed later - } - } - } - - @Override - public void reset() { - super.reset(); - if (enteringBattlefieldLastTurn != null - && lastActivePlayer != null - && enteringBattlefieldLastTurn.get(lastActivePlayer) != null) { - enteringBattlefieldLastTurn.remove(lastActivePlayer); - } - enteringBattlefieldLastTurn.putAll(enteringBattlefield); - enteringBattlefield.clear(); - lastActivePlayer = null; - } - - public List getPermanentsEnteringOnPlayersLastTurn(Game game, UUID playerId) { - if (game.isActivePlayer(playerId)) { - return enteringBattlefield.get(playerId); - } - return enteringBattlefieldLastTurn.get(playerId); - } -} From cd439ab8c87b7116a8203a88ad2aebff8048ebbb Mon Sep 17 00:00:00 2001 From: xenohedron Date: Wed, 29 Nov 2023 20:40:57 -0500 Subject: [PATCH 04/10] remove another game default watcher with one usage --- .../src/mage/cards/s/SupremeLeaderSnoke.java | 58 +++++++++++++-- Mage/src/main/java/mage/game/GameImpl.java | 1 - .../PlayerLostLifeNonCombatWatcher.java | 71 ------------------- 3 files changed, 53 insertions(+), 77 deletions(-) delete mode 100644 Mage/src/main/java/mage/watchers/common/PlayerLostLifeNonCombatWatcher.java diff --git a/Mage.Sets/src/mage/cards/s/SupremeLeaderSnoke.java b/Mage.Sets/src/mage/cards/s/SupremeLeaderSnoke.java index 9fa51777da4..96a87f2d6d9 100644 --- a/Mage.Sets/src/mage/cards/s/SupremeLeaderSnoke.java +++ b/Mage.Sets/src/mage/cards/s/SupremeLeaderSnoke.java @@ -24,11 +24,15 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.game.Game; +import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import mage.players.Player; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.TargetAdjuster; -import mage.watchers.common.PlayerLostLifeNonCombatWatcher; +import mage.watchers.Watcher; +import java.util.HashMap; +import java.util.Map; import java.util.UUID; /** @@ -91,7 +95,8 @@ enum SupremeLeaderSnokeAdjuster implements TargetAdjuster { } } -class OpponentNoncombatLostLifeCount implements DynamicValue { +enum OpponentNoncombatLostLifeCount implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -104,7 +109,7 @@ class OpponentNoncombatLostLifeCount implements DynamicValue { @Override public OpponentNoncombatLostLifeCount copy() { - return new OpponentNoncombatLostLifeCount(); + return this; } @Override @@ -132,7 +137,7 @@ class SupremeLeaderSnokeCounterEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { - int amount = new OpponentNoncombatLostLifeCount().calculate(game, source, this); + int amount = OpponentNoncombatLostLifeCount.instance.calculate(game, source, this); if (amount > 0) { Counter counterToAdd = counter.copy(); counterToAdd.add(amount - counter.getCount()); @@ -146,4 +151,47 @@ class SupremeLeaderSnokeCounterEffect extends OneShotEffect { public SupremeLeaderSnokeCounterEffect copy() { return new SupremeLeaderSnokeCounterEffect(this); } -} \ No newline at end of file +} + +class PlayerLostLifeNonCombatWatcher extends Watcher { + + private final Map amountOfLifeLostThisTurn = new HashMap<>(); + + PlayerLostLifeNonCombatWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + // non combat lose life + if (event.getType() == GameEvent.EventType.LOST_LIFE && !event.getFlag()) { + UUID playerId = event.getPlayerId(); + if (playerId != null) { + Integer amount = amountOfLifeLostThisTurn.get(playerId); + if (amount == null) { + amount = event.getAmount(); + } else { + amount = amount + event.getAmount(); + } + amountOfLifeLostThisTurn.put(playerId, amount); + } + } + } + + public int getAllOppLifeLost(UUID playerId, Game game) { + int amount = 0; + for (UUID opponentId : this.amountOfLifeLostThisTurn.keySet()) { + Player opponent = game.getPlayer(opponentId); + if (opponent != null && opponent.hasOpponent(playerId, game)) { + amount += this.amountOfLifeLostThisTurn.getOrDefault(opponentId, 0); + } + } + return amount; + } + + @Override + public void reset() { + super.reset(); + amountOfLifeLostThisTurn.clear(); + } +} diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 2b88e1d4b2d..fe5515d0cd9 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -1339,7 +1339,6 @@ public abstract class GameImpl implements Game { newWatchers.add(new MorbidWatcher()); newWatchers.add(new CastSpellLastTurnWatcher()); newWatchers.add(new PlayerLostLifeWatcher()); - newWatchers.add(new PlayerLostLifeNonCombatWatcher()); newWatchers.add(new BlockedAttackerWatcher()); newWatchers.add(new DamageDoneWatcher()); newWatchers.add(new PlanarRollWatcher()); diff --git a/Mage/src/main/java/mage/watchers/common/PlayerLostLifeNonCombatWatcher.java b/Mage/src/main/java/mage/watchers/common/PlayerLostLifeNonCombatWatcher.java deleted file mode 100644 index 2869021b238..00000000000 --- a/Mage/src/main/java/mage/watchers/common/PlayerLostLifeNonCombatWatcher.java +++ /dev/null @@ -1,71 +0,0 @@ -package mage.watchers.common; - -import mage.constants.WatcherScope; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.players.Player; -import mage.watchers.Watcher; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -/* - * Counts amount of life lost from noncombat sources current or last turn by players. - * This watcher is automatically started in gameImpl.init for each game - * - * @author NinthWorld - */ -public class PlayerLostLifeNonCombatWatcher extends Watcher { - - private final Map amountOfLifeLostThisTurn = new HashMap<>(); - private final Map amountOfLifeLostLastTurn = new HashMap<>(); - - public PlayerLostLifeNonCombatWatcher() { - super(WatcherScope.GAME); - } - - @Override - public void watch(GameEvent event, Game game) { - // non combat lose life - if (event.getType() == GameEvent.EventType.LOST_LIFE && !event.getFlag()) { - UUID playerId = event.getPlayerId(); - if (playerId != null) { - Integer amount = amountOfLifeLostThisTurn.get(playerId); - if (amount == null) { - amount = event.getAmount(); - } else { - amount = amount + event.getAmount(); - } - amountOfLifeLostThisTurn.put(playerId, amount); - } - } - } - - public int getLiveLost(UUID playerId) { - return amountOfLifeLostThisTurn.getOrDefault(playerId, 0); - } - - public int getAllOppLifeLost(UUID playerId, Game game) { - int amount = 0; - for (UUID opponentId : this.amountOfLifeLostThisTurn.keySet()) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null && opponent.hasOpponent(playerId, game)) { - amount += this.amountOfLifeLostThisTurn.getOrDefault(opponentId, 0); - } - } - return amount; - } - - public int getLiveLostLastTurn(UUID playerId) { - return amountOfLifeLostLastTurn.getOrDefault(playerId, 0); - } - - @Override - public void reset() { - super.reset(); - amountOfLifeLostLastTurn.clear(); - amountOfLifeLostLastTurn.putAll(amountOfLifeLostThisTurn); - amountOfLifeLostThisTurn.clear(); - } -} From a4cc0867752a912489b518d7cd2a2fa5c802d5e3 Mon Sep 17 00:00:00 2001 From: xenohedron Date: Wed, 29 Nov 2023 20:43:17 -0500 Subject: [PATCH 05/10] cleanup usages of BlockedAttackerWatcher --- Mage.Sets/src/mage/cards/g/GazeOfTheGorgon.java | 1 - Mage.Sets/src/mage/cards/g/GlyphOfDelusion.java | 1 - Mage.Sets/src/mage/cards/g/GlyphOfDoom.java | 1 - Mage.Sets/src/mage/cards/g/GlyphOfReincarnation.java | 1 - Mage.Sets/src/mage/cards/h/HuntDown.java | 1 - Mage.Sets/src/mage/cards/j/JovensFerrets.java | 3 +-- Mage.Sets/src/mage/cards/m/MonstrousStep.java | 1 - Mage.Sets/src/mage/cards/r/RimehornAurochs.java | 2 +- Mage.Sets/src/mage/cards/v/VenomousBreath.java | 1 - .../java/mage/watchers/common/BlockedAttackerWatcher.java | 5 +++-- 10 files changed, 5 insertions(+), 12 deletions(-) diff --git a/Mage.Sets/src/mage/cards/g/GazeOfTheGorgon.java b/Mage.Sets/src/mage/cards/g/GazeOfTheGorgon.java index 46e0b6b89dc..9be46742dda 100644 --- a/Mage.Sets/src/mage/cards/g/GazeOfTheGorgon.java +++ b/Mage.Sets/src/mage/cards/g/GazeOfTheGorgon.java @@ -34,7 +34,6 @@ public final class GazeOfTheGorgon extends CardImpl { this.getSpellAbility().addEffect(new RegenerateTargetEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addEffect(new GazeOfTheGorgonCreateDelayedTriggeredAbilityEffect()); - this.getSpellAbility().addWatcher(new BlockedAttackerWatcher()); } private GazeOfTheGorgon(final GazeOfTheGorgon card) { diff --git a/Mage.Sets/src/mage/cards/g/GlyphOfDelusion.java b/Mage.Sets/src/mage/cards/g/GlyphOfDelusion.java index 36c5488469e..662792deb71 100644 --- a/Mage.Sets/src/mage/cards/g/GlyphOfDelusion.java +++ b/Mage.Sets/src/mage/cards/g/GlyphOfDelusion.java @@ -46,7 +46,6 @@ public final class GlyphOfDelusion extends CardImpl { this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); this.getSpellAbility().addTarget(new GlyphOfDelusionSecondTarget()); this.getSpellAbility().addEffect(new GlyphOfDelusionEffect()); - this.getSpellAbility().addWatcher(new BlockedAttackerWatcher()); } private GlyphOfDelusion(final GlyphOfDelusion card) { diff --git a/Mage.Sets/src/mage/cards/g/GlyphOfDoom.java b/Mage.Sets/src/mage/cards/g/GlyphOfDoom.java index 11a62663b1a..9e56f02fdb0 100644 --- a/Mage.Sets/src/mage/cards/g/GlyphOfDoom.java +++ b/Mage.Sets/src/mage/cards/g/GlyphOfDoom.java @@ -41,7 +41,6 @@ public final class GlyphOfDoom extends CardImpl { this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); this.getSpellAbility().addEffect(new InfoEffect("Choose target Wall creature")); this.getSpellAbility().addEffect(new GlyphOfDoomCreateDelayedTriggeredAbilityEffect()); - this.getSpellAbility().addWatcher(new BlockedAttackerWatcher()); } private GlyphOfDoom(final GlyphOfDoom card) { diff --git a/Mage.Sets/src/mage/cards/g/GlyphOfReincarnation.java b/Mage.Sets/src/mage/cards/g/GlyphOfReincarnation.java index cb88460d5df..001099ec81a 100644 --- a/Mage.Sets/src/mage/cards/g/GlyphOfReincarnation.java +++ b/Mage.Sets/src/mage/cards/g/GlyphOfReincarnation.java @@ -48,7 +48,6 @@ public final class GlyphOfReincarnation extends CardImpl { // Destroy all creatures that were blocked by target Wall this turn. They can’t be regenerated. For each creature that died this way, put a creature card from the graveyard of the player who controlled that creature the last time it became blocked by that Wall onto the battlefield under its owner’s control. this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); this.getSpellAbility().addEffect(new GlyphOfReincarnationEffect()); - this.getSpellAbility().addWatcher(new BlockedAttackerWatcher()); } private GlyphOfReincarnation(final GlyphOfReincarnation card) { diff --git a/Mage.Sets/src/mage/cards/h/HuntDown.java b/Mage.Sets/src/mage/cards/h/HuntDown.java index 2819e73e7cb..cd809a01829 100644 --- a/Mage.Sets/src/mage/cards/h/HuntDown.java +++ b/Mage.Sets/src/mage/cards/h/HuntDown.java @@ -33,7 +33,6 @@ public final class HuntDown extends CardImpl { this.getSpellAbility().addEffect(new HuntDownEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent(filterMustBlock)); this.getSpellAbility().addTarget(new TargetCreaturePermanent(filterToBeBlocked)); - this.getSpellAbility().addWatcher(new BlockedAttackerWatcher()); } diff --git a/Mage.Sets/src/mage/cards/j/JovensFerrets.java b/Mage.Sets/src/mage/cards/j/JovensFerrets.java index 8e8487f4126..75aae34fff4 100644 --- a/Mage.Sets/src/mage/cards/j/JovensFerrets.java +++ b/Mage.Sets/src/mage/cards/j/JovensFerrets.java @@ -45,7 +45,6 @@ public final class JovensFerrets extends CardImpl { // At end of combat, tap all creatures that blocked Joven's Ferrets this turn. They don't untap during their controller's next untap step. Ability eocAbility = new EndOfCombatTriggeredAbility(new JovensFerretsEffect(), false); - eocAbility.addWatcher(new BlockedAttackerWatcher()); this.addAbility(eocAbility); } @@ -101,4 +100,4 @@ class JovensFerretsEffect extends OneShotEffect { } return false; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/m/MonstrousStep.java b/Mage.Sets/src/mage/cards/m/MonstrousStep.java index dde0308f408..a098f12aeb0 100644 --- a/Mage.Sets/src/mage/cards/m/MonstrousStep.java +++ b/Mage.Sets/src/mage/cards/m/MonstrousStep.java @@ -38,7 +38,6 @@ public final class MonstrousStep extends CardImpl { // Target creature gets +7/+7 until end of turn. Up to one target creature blocks it this turn if able. this.getSpellAbility().addEffect(new BoostTargetEffect(7, 7)); this.getSpellAbility().addEffect(new MonstrousStepEffect()); - this.getSpellAbility().addWatcher(new BlockedAttackerWatcher()); TargetPermanent target = new TargetCreaturePermanent(); target.setTargetTag(1); diff --git a/Mage.Sets/src/mage/cards/r/RimehornAurochs.java b/Mage.Sets/src/mage/cards/r/RimehornAurochs.java index c323906e939..e38b87c36e8 100644 --- a/Mage.Sets/src/mage/cards/r/RimehornAurochs.java +++ b/Mage.Sets/src/mage/cards/r/RimehornAurochs.java @@ -55,7 +55,7 @@ public final class RimehornAurochs extends CardImpl { Ability ability = new SimpleActivatedAbility(new RimehornAurochsEffect(), new ManaCostsImpl<>("{2}{S}")); ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature that must block"))); ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature that is to be blocked"))); - this.addAbility(ability, new BlockedAttackerWatcher()); + this.addAbility(ability); } private RimehornAurochs(final RimehornAurochs card) { diff --git a/Mage.Sets/src/mage/cards/v/VenomousBreath.java b/Mage.Sets/src/mage/cards/v/VenomousBreath.java index 71b557587fd..a1dee0dc5fe 100644 --- a/Mage.Sets/src/mage/cards/v/VenomousBreath.java +++ b/Mage.Sets/src/mage/cards/v/VenomousBreath.java @@ -33,7 +33,6 @@ public final class VenomousBreath extends CardImpl { this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addEffect(new InfoEffect("Choose target creature")); this.getSpellAbility().addEffect(new VenomousBreathCreateDelayedTriggeredAbilityEffect()); - this.getSpellAbility().addWatcher(new BlockedAttackerWatcher()); } private VenomousBreath(final VenomousBreath card) { diff --git a/Mage/src/main/java/mage/watchers/common/BlockedAttackerWatcher.java b/Mage/src/main/java/mage/watchers/common/BlockedAttackerWatcher.java index bfa3a48d237..1ceae3d0172 100644 --- a/Mage/src/main/java/mage/watchers/common/BlockedAttackerWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/BlockedAttackerWatcher.java @@ -1,4 +1,3 @@ - package mage.watchers.common; import java.util.HashMap; @@ -9,7 +8,6 @@ import mage.MageObjectReference; import mage.constants.WatcherScope; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.watchers.Watcher; @@ -21,6 +19,9 @@ public class BlockedAttackerWatcher extends Watcher { private final Map> blockData = new HashMap<>(); + /** + * Game default watcher + */ public BlockedAttackerWatcher() { super(WatcherScope.GAME); } From 1ac4fe4e4a41227ec414a6fe3e5bef8e0c0b8363 Mon Sep 17 00:00:00 2001 From: xenohedron Date: Wed, 29 Nov 2023 20:57:12 -0500 Subject: [PATCH 06/10] add doc comments for usage of default watchers --- .../dynamicvalue/common/CardsDrawnThisTurnDynamicValue.java | 3 --- Mage/src/main/java/mage/game/GameImpl.java | 6 +++--- .../java/mage/watchers/common/AttackedThisTurnWatcher.java | 3 +++ .../java/mage/watchers/common/BlockingOrBlockedWatcher.java | 3 +++ .../mage/watchers/common/CommanderPlaysCountWatcher.java | 3 +++ .../main/java/mage/watchers/common/EndStepCountWatcher.java | 3 +++ .../java/mage/watchers/common/ManaPaidSourceWatcher.java | 3 +++ .../java/mage/watchers/common/ManaSpentToCastWatcher.java | 3 +++ Mage/src/main/java/mage/watchers/common/MorbidWatcher.java | 1 + .../main/java/mage/watchers/common/SpellsCastWatcher.java | 3 +++ .../java/mage/watchers/common/TemptedByTheRingWatcher.java | 3 +++ 11 files changed, 28 insertions(+), 6 deletions(-) diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsDrawnThisTurnDynamicValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsDrawnThisTurnDynamicValue.java index a698b507011..5a28840e1cb 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsDrawnThisTurnDynamicValue.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsDrawnThisTurnDynamicValue.java @@ -8,8 +8,6 @@ import mage.game.Game; import mage.watchers.common.CardsDrawnThisTurnWatcher; /** - * Don't forget to add CardsDrawnThisTurnWatcher in card's definition - * * @author TheElk801 */ public enum CardsDrawnThisTurnDynamicValue implements DynamicValue { @@ -45,4 +43,3 @@ public enum CardsDrawnThisTurnDynamicValue implements DynamicValue { return hint; } } - diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index fe5515d0cd9..83683486830 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -1340,10 +1340,10 @@ public abstract class GameImpl implements Game { newWatchers.add(new CastSpellLastTurnWatcher()); newWatchers.add(new PlayerLostLifeWatcher()); newWatchers.add(new BlockedAttackerWatcher()); - newWatchers.add(new DamageDoneWatcher()); - newWatchers.add(new PlanarRollWatcher()); + newWatchers.add(new DamageDoneWatcher()); // TODO: no need to be default watcher + newWatchers.add(new PlanarRollWatcher()); // TODO: no need to be default watcher newWatchers.add(new AttackedThisTurnWatcher()); - newWatchers.add(new PlayersAttackedThisTurnWatcher()); + newWatchers.add(new PlayersAttackedThisTurnWatcher()); // TODO: no need to be default watcher newWatchers.add(new CardsDrawnThisTurnWatcher()); newWatchers.add(new ManaSpentToCastWatcher()); newWatchers.add(new ManaPaidSourceWatcher()); diff --git a/Mage/src/main/java/mage/watchers/common/AttackedThisTurnWatcher.java b/Mage/src/main/java/mage/watchers/common/AttackedThisTurnWatcher.java index b199c5b431a..59ce6c2f55b 100644 --- a/Mage/src/main/java/mage/watchers/common/AttackedThisTurnWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/AttackedThisTurnWatcher.java @@ -23,6 +23,9 @@ public class AttackedThisTurnWatcher extends Watcher { // issue with Robber of the Rich. it needs to check the subtype of the LKI of the permanent on the battlefield and this fails with MageObjectReference private final Set attackedThisTurnCreaturesPermanentLKI = new HashSet<>(); + /** + * Game default watcher + */ public AttackedThisTurnWatcher() { super(WatcherScope.GAME); } diff --git a/Mage/src/main/java/mage/watchers/common/BlockingOrBlockedWatcher.java b/Mage/src/main/java/mage/watchers/common/BlockingOrBlockedWatcher.java index 0e8b886c0a2..da89eacc3fd 100644 --- a/Mage/src/main/java/mage/watchers/common/BlockingOrBlockedWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/BlockingOrBlockedWatcher.java @@ -16,6 +16,9 @@ public class BlockingOrBlockedWatcher extends Watcher { private final Map> blockerMap = new HashMap<>(); + /** + * Game default watcher + */ public BlockingOrBlockedWatcher() { super(WatcherScope.GAME); } diff --git a/Mage/src/main/java/mage/watchers/common/CommanderPlaysCountWatcher.java b/Mage/src/main/java/mage/watchers/common/CommanderPlaysCountWatcher.java index 56a67a53b81..0f87de7885c 100644 --- a/Mage/src/main/java/mage/watchers/common/CommanderPlaysCountWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/CommanderPlaysCountWatcher.java @@ -24,6 +24,9 @@ public class CommanderPlaysCountWatcher extends Watcher { private final Map playsCount = new HashMap<>(); private final Map playerCount = new HashMap<>(); + /** + * Game default watcher + */ public CommanderPlaysCountWatcher() { super(WatcherScope.GAME); } diff --git a/Mage/src/main/java/mage/watchers/common/EndStepCountWatcher.java b/Mage/src/main/java/mage/watchers/common/EndStepCountWatcher.java index 2527cc48bfd..1dea7622d4e 100644 --- a/Mage/src/main/java/mage/watchers/common/EndStepCountWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/EndStepCountWatcher.java @@ -17,6 +17,9 @@ public class EndStepCountWatcher extends Watcher { private final Map playerMap = new HashMap<>(); + /** + * Game default watcher + */ public EndStepCountWatcher() { super(WatcherScope.GAME); } diff --git a/Mage/src/main/java/mage/watchers/common/ManaPaidSourceWatcher.java b/Mage/src/main/java/mage/watchers/common/ManaPaidSourceWatcher.java index 56320462c0b..c3921737ceb 100644 --- a/Mage/src/main/java/mage/watchers/common/ManaPaidSourceWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/ManaPaidSourceWatcher.java @@ -110,6 +110,9 @@ public class ManaPaidSourceWatcher extends Watcher { private static final ManaPaidTracker emptyTracker = new ManaPaidTracker(); private final Map manaMap = new HashMap<>(); + /** + * Game default watcher + */ public ManaPaidSourceWatcher() { super(WatcherScope.GAME); } diff --git a/Mage/src/main/java/mage/watchers/common/ManaSpentToCastWatcher.java b/Mage/src/main/java/mage/watchers/common/ManaSpentToCastWatcher.java index 28fc4350146..a7c6b55c755 100644 --- a/Mage/src/main/java/mage/watchers/common/ManaSpentToCastWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/ManaSpentToCastWatcher.java @@ -24,6 +24,9 @@ public class ManaSpentToCastWatcher extends Watcher { private final Map manaMap = new HashMap<>(); + /** + * Game default watcher + */ public ManaSpentToCastWatcher() { super(WatcherScope.GAME); } diff --git a/Mage/src/main/java/mage/watchers/common/MorbidWatcher.java b/Mage/src/main/java/mage/watchers/common/MorbidWatcher.java index e3713c14c33..217122b40bd 100644 --- a/Mage/src/main/java/mage/watchers/common/MorbidWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/MorbidWatcher.java @@ -15,6 +15,7 @@ public class MorbidWatcher extends Watcher { /** * Game default watcher + * TODO: Merge with CreaturesDiedWatcher */ public MorbidWatcher() { super(WatcherScope.GAME); diff --git a/Mage/src/main/java/mage/watchers/common/SpellsCastWatcher.java b/Mage/src/main/java/mage/watchers/common/SpellsCastWatcher.java index 21474f1ba8e..fd07dc2b62d 100644 --- a/Mage/src/main/java/mage/watchers/common/SpellsCastWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/SpellsCastWatcher.java @@ -24,6 +24,9 @@ public class SpellsCastWatcher extends Watcher { private final Map> spellsCastFromGraveyard = new HashMap<>(); private int nonCreatureSpells; + /** + * Game default watcher + */ public SpellsCastWatcher() { super(WatcherScope.GAME); } diff --git a/Mage/src/main/java/mage/watchers/common/TemptedByTheRingWatcher.java b/Mage/src/main/java/mage/watchers/common/TemptedByTheRingWatcher.java index f8864fd47df..0513207ac4d 100644 --- a/Mage/src/main/java/mage/watchers/common/TemptedByTheRingWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/TemptedByTheRingWatcher.java @@ -17,6 +17,9 @@ public class TemptedByTheRingWatcher extends Watcher { private final Map map = new HashMap<>(); + /** + * Game default watcher + */ public TemptedByTheRingWatcher() { super(WatcherScope.GAME); } From 1f764515f6b10fa4f8c913055005bc24f729c252 Mon Sep 17 00:00:00 2001 From: xenohedron Date: Thu, 30 Nov 2023 00:11:10 -0500 Subject: [PATCH 07/10] merge MorbidWatcher with CreaturesDiedWatcher --- .../condition/common/MorbidCondition.java | 4 +-- Mage/src/main/java/mage/game/GameImpl.java | 1 - .../watchers/common/CreaturesDiedWatcher.java | 4 +++ .../mage/watchers/common/MorbidWatcher.java | 35 ------------------- 4 files changed, 6 insertions(+), 38 deletions(-) delete mode 100644 Mage/src/main/java/mage/watchers/common/MorbidWatcher.java diff --git a/Mage/src/main/java/mage/abilities/condition/common/MorbidCondition.java b/Mage/src/main/java/mage/abilities/condition/common/MorbidCondition.java index 591bc6e416f..2f906d482e9 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/MorbidCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/MorbidCondition.java @@ -3,7 +3,7 @@ package mage.abilities.condition.common; import mage.abilities.Ability; import mage.abilities.condition.Condition; import mage.game.Game; -import mage.watchers.common.MorbidWatcher; +import mage.watchers.common.CreaturesDiedWatcher; /** * @author nantuko @@ -13,7 +13,7 @@ public enum MorbidCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - MorbidWatcher watcher = game.getState().getWatcher(MorbidWatcher.class); + CreaturesDiedWatcher watcher = game.getState().getWatcher(CreaturesDiedWatcher.class); return watcher != null && watcher.conditionMet(); } diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 83683486830..0b71172942e 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -1336,7 +1336,6 @@ public abstract class GameImpl implements Game { public void initGameDefaultWatchers() { List newWatchers = new ArrayList<>(); - newWatchers.add(new MorbidWatcher()); newWatchers.add(new CastSpellLastTurnWatcher()); newWatchers.add(new PlayerLostLifeWatcher()); newWatchers.add(new BlockedAttackerWatcher()); diff --git a/Mage/src/main/java/mage/watchers/common/CreaturesDiedWatcher.java b/Mage/src/main/java/mage/watchers/common/CreaturesDiedWatcher.java index db67353f8d4..8aa99e71cda 100644 --- a/Mage/src/main/java/mage/watchers/common/CreaturesDiedWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/CreaturesDiedWatcher.java @@ -19,6 +19,9 @@ public class CreaturesDiedWatcher extends Watcher { private final Map amountOfCreaturesThatDiedByController = new HashMap<>(); private final Map amountOfCreaturesThatDiedByOwner = new HashMap<>(); + /** + * Game default watcher + */ public CreaturesDiedWatcher() { super(WatcherScope.GAME); } @@ -34,6 +37,7 @@ public class CreaturesDiedWatcher extends Watcher { || !zEvent.getTarget().isCreature(game)) { return; } + condition = true; amountOfCreaturesThatDiedByController.compute(zEvent.getTarget().getControllerId(), CardUtil::setOrIncrementValue); amountOfCreaturesThatDiedByOwner.compute(zEvent.getTarget().getOwnerId(), CardUtil::setOrIncrementValue); } diff --git a/Mage/src/main/java/mage/watchers/common/MorbidWatcher.java b/Mage/src/main/java/mage/watchers/common/MorbidWatcher.java deleted file mode 100644 index 217122b40bd..00000000000 --- a/Mage/src/main/java/mage/watchers/common/MorbidWatcher.java +++ /dev/null @@ -1,35 +0,0 @@ - -package mage.watchers.common; - -import mage.constants.WatcherScope; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; -import mage.watchers.Watcher; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public class MorbidWatcher extends Watcher { - - /** - * Game default watcher - * TODO: Merge with CreaturesDiedWatcher - */ - public MorbidWatcher() { - super(WatcherScope.GAME); - } - - @Override - public void watch(GameEvent event, Game game) { - if (condition) { - return; - } - if (event.getType() == GameEvent.EventType.ZONE_CHANGE - && ((ZoneChangeEvent) event).isDiesEvent() - && ((ZoneChangeEvent) event).getTarget().isCreature(game)) { - condition = true; - } - } -} From c164d701352a6075d395f00ee16205e5301e1920 Mon Sep 17 00:00:00 2001 From: xenohedron Date: Thu, 30 Nov 2023 00:48:30 -0500 Subject: [PATCH 08/10] remove PlayersAttackedThisTurnWatcher from default watchers --- .../mage/cards/f/FaramirPrinceOfIthilien.java | 19 ++++++++++--------- Mage.Sets/src/mage/cards/m/MilitantAngel.java | 3 ++- .../cards/single/gnt/MilitantAngelTest.java | 2 +- .../AttackedThisTurnOpponentsCount.java | 2 ++ Mage/src/main/java/mage/game/GameImpl.java | 1 - 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Mage.Sets/src/mage/cards/f/FaramirPrinceOfIthilien.java b/Mage.Sets/src/mage/cards/f/FaramirPrinceOfIthilien.java index 7484036a920..b930af0a933 100644 --- a/Mage.Sets/src/mage/cards/f/FaramirPrinceOfIthilien.java +++ b/Mage.Sets/src/mage/cards/f/FaramirPrinceOfIthilien.java @@ -2,6 +2,7 @@ package mage.cards.f; import mage.MageInt; import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfPlayersNextEndStepDelayedTriggeredAbility; import mage.abilities.effects.Effect; @@ -40,8 +41,7 @@ public final class FaramirPrinceOfIthilien extends CardImpl { this.toughness = new MageInt(3); // At the beginning of your end step, choose an opponent. - // At the beginning of that player's next end step, - // you draw a card if they didn't attack you that turn. + // At the beginning of that player's next end step, you draw a card if they didn't attack you that turn. // Otherwise, create three 1/1 white Human Soldier creature tokens. this.addAbility(new BeginningOfYourEndStepTriggeredAbility(new FaramirPrinceOfIthilienEffect(), false)); } @@ -92,11 +92,12 @@ class FaramirPrinceOfIthilienEffect extends OneShotEffect { Effect effect = new FaramirPrinceOfIthilienDelayedEffect(); effect.setTargetPointer(new FixedTarget(opponent.getId(), game)); - game.addDelayedTriggeredAbility( - new AtTheBeginOfPlayersNextEndStepDelayedTriggeredAbility( + DelayedTriggeredAbility delayed = new AtTheBeginOfPlayersNextEndStepDelayedTriggeredAbility( effect, opponent.getId() - ), source); + ); + delayed.addWatcher(new PlayersAttackedThisTurnWatcher()); + game.addDelayedTriggeredAbility(delayed, source); return true; } @@ -123,7 +124,7 @@ class FaramirPrinceOfIthilienDelayedEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { PlayersAttackedThisTurnWatcher watcher = game.getState().getWatcher(PlayersAttackedThisTurnWatcher.class); - if(watcher == null){ + if (watcher == null) { return false; } @@ -131,14 +132,14 @@ class FaramirPrinceOfIthilienDelayedEffect extends OneShotEffect { UUID targetId = getTargetPointer().getFirst(game, source); Player controller = game.getPlayer(controllerId); - if(controller == null){ + if (controller == null) { return false; } - if(watcher.hasPlayerAttackedPlayer(targetId, controllerId)){ + if (watcher.hasPlayerAttackedPlayer(targetId, controllerId)) { return new CreateTokenEffect(new HumanSoldierToken(), 3).apply(game, source); } else { return new DrawCardSourceControllerEffect(1).apply(game, source); } } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/m/MilitantAngel.java b/Mage.Sets/src/mage/cards/m/MilitantAngel.java index 31604e0b2b2..17092af0f46 100644 --- a/Mage.Sets/src/mage/cards/m/MilitantAngel.java +++ b/Mage.Sets/src/mage/cards/m/MilitantAngel.java @@ -12,6 +12,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.game.permanent.token.KnightToken; +import mage.watchers.common.PlayersAttackedThisTurnWatcher; import java.util.UUID; @@ -35,7 +36,7 @@ public final class MilitantAngel extends CardImpl { // When Militant Angel enters the battlefield, create a number of 2/2 white Knight creature tokens with vigilance equal to the number of opponents you attacked this turn. Effect effect = new CreateTokenEffect(new KnightToken(), AttackedThisTurnOpponentsCount.instance); effect.setText("create a number of 2/2 white Knight creature tokens with vigilance equal to the number of opponents you attacked this turn"); - this.addAbility(new EntersBattlefieldTriggeredAbility(effect)); + this.addAbility(new EntersBattlefieldTriggeredAbility(effect), new PlayersAttackedThisTurnWatcher()); } private MilitantAngel(final MilitantAngel card) { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/gnt/MilitantAngelTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/gnt/MilitantAngelTest.java index f686297194f..bee291ef3e6 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/gnt/MilitantAngelTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/gnt/MilitantAngelTest.java @@ -25,7 +25,7 @@ public class MilitantAngelTest extends CardTestCommander4Players { // it's testing counter only (no need to test card -- it's same) // When Militant Angel enters the battlefield, create a number of 2/2 white Knight creature tokens // with vigilance equal to the number of opponents you attacked this turn. - //addCard(Zone.BATTLEFIELD, playerA, "Militant Angel", 2); + addCard(Zone.HAND, playerA, "Militant Angel", 1); // to add watcher addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); addCard(Zone.BATTLEFIELD, playerA, "Kitesail Corsair", 1); diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/AttackedThisTurnOpponentsCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/AttackedThisTurnOpponentsCount.java index 2435fda94a7..dd177feaf48 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/AttackedThisTurnOpponentsCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/AttackedThisTurnOpponentsCount.java @@ -8,6 +8,8 @@ import mage.game.Game; import mage.watchers.common.PlayersAttackedThisTurnWatcher; /** + * Remember to add PlayersAttackedThisTurnWatcher to card init + * * @author JayDi85 */ public enum AttackedThisTurnOpponentsCount implements DynamicValue { diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 0b71172942e..7d3aad0b462 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -1342,7 +1342,6 @@ public abstract class GameImpl implements Game { newWatchers.add(new DamageDoneWatcher()); // TODO: no need to be default watcher newWatchers.add(new PlanarRollWatcher()); // TODO: no need to be default watcher newWatchers.add(new AttackedThisTurnWatcher()); - newWatchers.add(new PlayersAttackedThisTurnWatcher()); // TODO: no need to be default watcher newWatchers.add(new CardsDrawnThisTurnWatcher()); newWatchers.add(new ManaSpentToCastWatcher()); newWatchers.add(new ManaPaidSourceWatcher()); From 6155f2d403c95db00d8a266bfb63818c6b60e144 Mon Sep 17 00:00:00 2001 From: xenohedron Date: Thu, 30 Nov 2023 00:36:31 -0500 Subject: [PATCH 09/10] remove DamageDoneWatcher from default watchers --- Mage.Sets/src/mage/cards/c/ChandraFireOfKaladesh.java | 3 ++- Mage.Sets/src/mage/cards/n/NeedleDrop.java | 2 ++ Mage.Sets/src/mage/cards/w/WaveOfRats.java | 5 +++-- .../condition/common/SourceDealtDamageCondition.java | 6 ++++-- Mage/src/main/java/mage/game/GameImpl.java | 1 - 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Mage.Sets/src/mage/cards/c/ChandraFireOfKaladesh.java b/Mage.Sets/src/mage/cards/c/ChandraFireOfKaladesh.java index bcb21310eb4..237c6fd8df3 100644 --- a/Mage.Sets/src/mage/cards/c/ChandraFireOfKaladesh.java +++ b/Mage.Sets/src/mage/cards/c/ChandraFireOfKaladesh.java @@ -21,6 +21,7 @@ import mage.constants.*; import mage.filter.FilterSpell; import mage.filter.predicate.mageobject.ColorPredicate; import mage.target.common.TargetPlayerOrPlaneswalker; +import mage.watchers.common.DamageDoneWatcher; /** * @@ -52,7 +53,7 @@ public final class ChandraFireOfKaladesh extends CardImpl { Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new TapSourceCost()); ability.addEffect(new ConditionalOneShotEffect(new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED,Pronoun.SHE), new SourceDealtDamageCondition(3))); ability.addTarget(new TargetPlayerOrPlaneswalker()); - this.addAbility(ability); + this.addAbility(ability, new DamageDoneWatcher()); } diff --git a/Mage.Sets/src/mage/cards/n/NeedleDrop.java b/Mage.Sets/src/mage/cards/n/NeedleDrop.java index 1bc8bb02d48..a9aa925262d 100644 --- a/Mage.Sets/src/mage/cards/n/NeedleDrop.java +++ b/Mage.Sets/src/mage/cards/n/NeedleDrop.java @@ -38,6 +38,8 @@ public final class NeedleDrop extends CardImpl { // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); + + this.getSpellAbility().addWatcher(new DamageDoneWatcher()); } private NeedleDrop(final NeedleDrop card) { diff --git a/Mage.Sets/src/mage/cards/w/WaveOfRats.java b/Mage.Sets/src/mage/cards/w/WaveOfRats.java index 345cc03baf7..76977bd1c24 100644 --- a/Mage.Sets/src/mage/cards/w/WaveOfRats.java +++ b/Mage.Sets/src/mage/cards/w/WaveOfRats.java @@ -37,7 +37,8 @@ public class WaveOfRats extends CardImpl { this.addAbility(new ConditionalInterveningIfTriggeredAbility( new DiesSourceTriggeredAbility(new ReturnToBattlefieldUnderOwnerControlSourceEffect()), WaveOfRatsDealtDamageToPlayerCondition.instance, - "When Wave of Rats dies, if it dealt combat damage to a player this turn, return it to the battlefield under its owner's control.") + "When Wave of Rats dies, if it dealt combat damage to a player this turn, return it to the battlefield under its owner's control."), + new DamageDoneWatcher() ); // Blitz {4}{B} (If you cast this spell for its blitz cost, it gains haste and “When this creature dies, draw a card.” Sacrifice it at the beginning of the next end step.) @@ -69,4 +70,4 @@ enum WaveOfRatsDealtDamageToPlayerCondition implements Condition { } return watcher.damagedAPlayer(waveOfRats.getId(), waveOfRats.getZoneChangeCounter(game), game); } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/abilities/condition/common/SourceDealtDamageCondition.java b/Mage/src/main/java/mage/abilities/condition/common/SourceDealtDamageCondition.java index 2f4e4423e24..5512e058588 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/SourceDealtDamageCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/SourceDealtDamageCondition.java @@ -9,10 +9,12 @@ import mage.watchers.common.DamageDoneWatcher; * * @author LevelX2 */ - public class SourceDealtDamageCondition implements Condition { private final int value; + /** + * Must add DamageDoneWatcher on card init + */ public SourceDealtDamageCondition(int value) { this.value = value; } @@ -29,4 +31,4 @@ public class SourceDealtDamageCondition implements Condition { } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 7d3aad0b462..3b813bd1d8d 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -1339,7 +1339,6 @@ public abstract class GameImpl implements Game { newWatchers.add(new CastSpellLastTurnWatcher()); newWatchers.add(new PlayerLostLifeWatcher()); newWatchers.add(new BlockedAttackerWatcher()); - newWatchers.add(new DamageDoneWatcher()); // TODO: no need to be default watcher newWatchers.add(new PlanarRollWatcher()); // TODO: no need to be default watcher newWatchers.add(new AttackedThisTurnWatcher()); newWatchers.add(new CardsDrawnThisTurnWatcher()); From 201c1ef44399c5fb429d02f583611d9f6bf7f05f Mon Sep 17 00:00:00 2001 From: xenohedron Date: Thu, 30 Nov 2023 01:00:48 -0500 Subject: [PATCH 10/10] (can't remove PlanarRollWatcher without test rework) --- Mage.Sets/src/mage/cards/f/FracturedPowerstone.java | 4 ++-- Mage/src/main/java/mage/game/GameImpl.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/cards/f/FracturedPowerstone.java b/Mage.Sets/src/mage/cards/f/FracturedPowerstone.java index 0917015c456..844b5135367 100644 --- a/Mage.Sets/src/mage/cards/f/FracturedPowerstone.java +++ b/Mage.Sets/src/mage/cards/f/FracturedPowerstone.java @@ -29,7 +29,7 @@ public final class FracturedPowerstone extends CardImpl { Ability ability = new ActivateAsSorceryActivatedAbility( new FracturedPowerstoneEffect(), new TapSourceCost() ); - this.addAbility(ability); + this.addAbility(ability, new PlanarRollWatcher()); } private FracturedPowerstone(final FracturedPowerstone card) { @@ -77,4 +77,4 @@ class FracturedPowerstoneEffect extends OneShotEffect { } return false; } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 3b813bd1d8d..811bcfe9d62 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -1339,7 +1339,7 @@ public abstract class GameImpl implements Game { newWatchers.add(new CastSpellLastTurnWatcher()); newWatchers.add(new PlayerLostLifeWatcher()); newWatchers.add(new BlockedAttackerWatcher()); - newWatchers.add(new PlanarRollWatcher()); // TODO: no need to be default watcher + newWatchers.add(new PlanarRollWatcher()); // needed for RollDiceTest (planechase code needs improves) newWatchers.add(new AttackedThisTurnWatcher()); newWatchers.add(new CardsDrawnThisTurnWatcher()); newWatchers.add(new ManaSpentToCastWatcher());