From bfbdf6b10391270774e029dd7c226bfc1d922d93 Mon Sep 17 00:00:00 2001 From: xenohedron Date: Sun, 1 Oct 2023 22:50:14 -0400 Subject: [PATCH] reimplement "don't cause abilities to trigger" effects (#11242) --- .../cards/e/EleshNornMotherOfMachines.java | 85 +++---------- Mage.Sets/src/mage/cards/h/Hushbringer.java | 83 +------------ Mage.Sets/src/mage/cards/h/HushwingGryff.java | 69 +---------- .../src/mage/cards/t/TocatliHonorGuard.java | 5 +- Mage.Sets/src/mage/cards/t/TorporOrb.java | 69 +---------- .../test/cards/replacement/TorporOrbTest.java | 23 +++- .../mage/abilities/TriggeredAbilities.java | 2 +- .../java/mage/abilities/TriggeredAbility.java | 8 +- .../ruleModifying/DontCauseTriggerEffect.java | 116 ++++++++++++++++++ 9 files changed, 171 insertions(+), 289 deletions(-) create mode 100644 Mage/src/main/java/mage/abilities/effects/common/ruleModifying/DontCauseTriggerEffect.java diff --git a/Mage.Sets/src/mage/cards/e/EleshNornMotherOfMachines.java b/Mage.Sets/src/mage/cards/e/EleshNornMotherOfMachines.java index 0bdde989606..517e6f76d82 100644 --- a/Mage.Sets/src/mage/cards/e/EleshNornMotherOfMachines.java +++ b/Mage.Sets/src/mage/cards/e/EleshNornMotherOfMachines.java @@ -1,20 +1,18 @@ package mage.cards.e; import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.common.replacement.AdditionalTriggerControlledETBReplacementEffect; +import mage.abilities.effects.common.ruleModifying.DontCauseTriggerEffect; import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.game.Game; -import mage.game.events.EntersTheBattlefieldEvent; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.TargetController; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import java.util.UUID; @@ -23,6 +21,11 @@ import java.util.UUID; */ public final class EleshNornMotherOfMachines extends CardImpl { + private static final FilterPermanent filter = new FilterPermanent("permanents your opponents control"); + static { + filter.add(TargetController.OPPONENT.getControllerPredicate()); + } + public EleshNornMotherOfMachines(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}"); @@ -35,10 +38,10 @@ public final class EleshNornMotherOfMachines extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // If a permanent entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AdditionalTriggerControlledETBReplacementEffect())); + this.addAbility(new SimpleStaticAbility(new AdditionalTriggerControlledETBReplacementEffect())); // Permanents entering the battlefield don't cause abilities of permanents your opponents control to trigger. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new EleshNornMotherOfMachinesPreventionEffect())); + this.addAbility(new SimpleStaticAbility(new DontCauseTriggerEffect(StaticFilters.FILTER_PERMANENTS, false, filter))); } private EleshNornMotherOfMachines(final EleshNornMotherOfMachines card) {super(card);} @@ -46,63 +49,3 @@ public final class EleshNornMotherOfMachines extends CardImpl { @Override public EleshNornMotherOfMachines copy() {return new EleshNornMotherOfMachines(this);} } - -class EleshNornMotherOfMachinesPreventionEffect extends ContinuousRuleModifyingEffectImpl { - - EleshNornMotherOfMachinesPreventionEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment, false, false); - staticText = "Permanents entering the battlefield don't cause abilities of permanents your opponents control to trigger"; - } - - private EleshNornMotherOfMachinesPreventionEffect(final EleshNornMotherOfMachinesPreventionEffect effect) { - super(effect); - } - - @Override - public EleshNornMotherOfMachinesPreventionEffect copy() {return new EleshNornMotherOfMachinesPreventionEffect(this);} - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - Ability ability = (Ability) getValue("targetAbility"); - if(ability == null || ability.getAbilityType() != AbilityType.TRIGGERED) { - return false; - } - - // Elesh Norn should not prevent Bloodghast trigger from the graveyard. - // This checks that the trigger originated from a permanent. - if(ability.getSourcePermanentOrLKI(game) == null) { - return false; - } - - if (!game.getOpponents(source.getControllerId()).contains(ability.getControllerId())) { - return false; - } - - Permanent enteringPermanent = ((EntersTheBattlefieldEvent) event).getTarget(); - if (enteringPermanent == null) { - return false; - } - - return (((TriggeredAbility) ability).checkTrigger(event, game)); - } - - @Override - public String getInfoMessage(Ability source, GameEvent event, Game game) { - MageObject enteringObject = game.getObject(event.getSourceId()); - MageObject sourceObject = game.getObject(source); - Ability ability = (Ability) getValue("targetAbility"); - if (enteringObject != null && sourceObject != null && ability != null) { - MageObject abilitObject = game.getObject(ability.getSourceId()); - if (abilitObject != null) { - return sourceObject.getLogName() + " prevented ability of " + abilitObject.getLogName() - + " to trigger for " + enteringObject.getLogName() + " entering the battlefield."; - } - } - return null; - } -} diff --git a/Mage.Sets/src/mage/cards/h/Hushbringer.java b/Mage.Sets/src/mage/cards/h/Hushbringer.java index db685204da7..f9442cdd312 100644 --- a/Mage.Sets/src/mage/cards/h/Hushbringer.java +++ b/Mage.Sets/src/mage/cards/h/Hushbringer.java @@ -1,21 +1,15 @@ package mage.cards.h; import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.common.ruleModifying.DontCauseTriggerEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.LifelinkAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.game.Game; -import mage.game.events.EntersTheBattlefieldEvent; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; -import mage.game.permanent.Permanent; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.StaticFilters; import java.util.UUID; @@ -38,7 +32,7 @@ public final class Hushbringer extends CardImpl { this.addAbility(LifelinkAbility.getInstance()); // Creatures entering the battlefield or dying don't cause abilities to trigger. - this.addAbility(new SimpleStaticAbility(new HushbringerEffect())); + this.addAbility(new SimpleStaticAbility(new DontCauseTriggerEffect(StaticFilters.FILTER_PERMANENT_CREATURES, true, null))); } private Hushbringer(final Hushbringer card) { @@ -50,70 +44,3 @@ public final class Hushbringer extends CardImpl { return new Hushbringer(this); } } - -class HushbringerEffect extends ContinuousRuleModifyingEffectImpl { - - HushbringerEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment, false, false); - staticText = "Creatures entering the battlefield or dying don't cause abilities to trigger"; - } - - private HushbringerEffect(final HushbringerEffect effect) { - super(effect); - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD - || event.getType() == GameEvent.EventType.ZONE_CHANGE; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - Ability ability = (Ability) getValue("targetAbility"); - if (ability == null || ability.getAbilityType() != AbilityType.TRIGGERED) { - return false; - } - Permanent permanent; - switch (event.getType()) { - case ENTERS_THE_BATTLEFIELD: - permanent = ((EntersTheBattlefieldEvent) event).getTarget(); - break; - case ZONE_CHANGE: - ZoneChangeEvent zEvent = ((ZoneChangeEvent) event); - if (!zEvent.isDiesEvent()) { - return false; - } - permanent = zEvent.getTarget(); - break; - default: - return false; - } - - if (permanent == null || !permanent.isCreature(game)) { - return false; - } - return (((TriggeredAbility) ability).checkTrigger(event, game)); - } - - @Override - public String getInfoMessage(Ability source, GameEvent event, Game game) { - MageObject enteringObject = game.getObject(event.getSourceId()); - MageObject sourceObject = game.getObject(source); - Ability ability = (Ability) getValue("targetAbility"); - if (enteringObject == null || sourceObject == null || ability == null) { - return null; - } - MageObject abilitObject = game.getObject(ability.getSourceId()); - if (abilitObject == null) { - return null; - } - return sourceObject.getLogName() + " prevented ability of " - + abilitObject.getLogName() + " from triggering."; - } - - @Override - public HushbringerEffect copy() { - return new HushbringerEffect(this); - } -} diff --git a/Mage.Sets/src/mage/cards/h/HushwingGryff.java b/Mage.Sets/src/mage/cards/h/HushwingGryff.java index eaa80ec6e1e..33cefa5463d 100644 --- a/Mage.Sets/src/mage/cards/h/HushwingGryff.java +++ b/Mage.Sets/src/mage/cards/h/HushwingGryff.java @@ -1,27 +1,16 @@ - package mage.cards.h; -import java.util.UUID; import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.common.ruleModifying.DontCauseTriggerEffect; import mage.abilities.keyword.FlashAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AbilityType; import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; import mage.constants.SubType; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.EntersTheBattlefieldEvent; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; + +import java.util.UUID; /** * @@ -41,7 +30,7 @@ public final class HushwingGryff extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // Creatures entering the battlefield don't cause abilities to trigger. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new HushwingGryffEffect())); + this.addAbility(new SimpleStaticAbility(new DontCauseTriggerEffect())); } private HushwingGryff(final HushwingGryff card) { @@ -53,53 +42,3 @@ public final class HushwingGryff extends CardImpl { return new HushwingGryff(this); } } - -class HushwingGryffEffect extends ContinuousRuleModifyingEffectImpl { - - HushwingGryffEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment, false, true); - staticText = "Creatures entering the battlefield don't cause abilities to trigger"; - } - - private HushwingGryffEffect(final HushwingGryffEffect effect) { - super(effect); - } - - @Override - public String getInfoMessage(Ability source, GameEvent event, Game game) { - MageObject enteringObject = game.getObject(event.getSourceId()); - MageObject sourceObject = game.getObject(source); - Ability ability = (Ability) getValue("targetAbility"); - if (enteringObject != null && sourceObject != null && ability != null) { - MageObject abilitObject = game.getObject(ability.getSourceId()); - if (abilitObject != null) { - return sourceObject.getLogName() + " prevented ability of " + abilitObject.getLogName() - + " to trigger for " + enteringObject.getLogName() + " entering the battlefield."; - } - } - return null; - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - Ability ability = (Ability) getValue("targetAbility"); - if (ability != null && ability.getAbilityType() == AbilityType.TRIGGERED) { - Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget(); - if (permanent != null && permanent.isCreature(game)) { - return (((TriggeredAbility) ability).checkTrigger(event, game)); - } - } - return false; - } - - @Override - public HushwingGryffEffect copy() { - return new HushwingGryffEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/t/TocatliHonorGuard.java b/Mage.Sets/src/mage/cards/t/TocatliHonorGuard.java index 5bec83f3ab8..6849ccd0027 100644 --- a/Mage.Sets/src/mage/cards/t/TocatliHonorGuard.java +++ b/Mage.Sets/src/mage/cards/t/TocatliHonorGuard.java @@ -1,14 +1,13 @@ - package mage.cards.t; import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.ruleModifying.DontCauseTriggerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; /** * @@ -25,7 +24,7 @@ public final class TocatliHonorGuard extends CardImpl { this.toughness = new MageInt(3); // Creatures entering the battlefield don't cause abilities to trigger. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new TorporOrbEffect())); + this.addAbility(new SimpleStaticAbility(new DontCauseTriggerEffect())); } private TocatliHonorGuard(final TocatliHonorGuard card) { diff --git a/Mage.Sets/src/mage/cards/t/TorporOrb.java b/Mage.Sets/src/mage/cards/t/TorporOrb.java index 74905646adf..64216ae8272 100644 --- a/Mage.Sets/src/mage/cards/t/TorporOrb.java +++ b/Mage.Sets/src/mage/cards/t/TorporOrb.java @@ -1,23 +1,12 @@ - package mage.cards.t; -import java.util.UUID; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.common.ruleModifying.DontCauseTriggerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AbilityType; import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.EntersTheBattlefieldEvent; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; + +import java.util.UUID; /** * @@ -29,7 +18,7 @@ public final class TorporOrb extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); // Creatures entering the battlefield don't cause abilities to trigger. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new TorporOrbEffect())); + this.addAbility(new SimpleStaticAbility(new DontCauseTriggerEffect())); } private TorporOrb(final TorporOrb card) { @@ -41,53 +30,3 @@ public final class TorporOrb extends CardImpl { return new TorporOrb(this); } } - -class TorporOrbEffect extends ContinuousRuleModifyingEffectImpl { - - TorporOrbEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment, false, false); - staticText = "Creatures entering the battlefield don't cause abilities to trigger"; - } - - private TorporOrbEffect(final TorporOrbEffect effect) { - super(effect); - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - Ability ability = (Ability) getValue("targetAbility"); - if (ability != null && ability.getAbilityType() == AbilityType.TRIGGERED) { - Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget(); - if (permanent != null && permanent.isCreature(game)) { - return (((TriggeredAbility) ability).checkTrigger(event, game)); - } - } - return false; - } - - @Override - public String getInfoMessage(Ability source, GameEvent event, Game game) { - MageObject enteringObject = game.getObject(event.getSourceId()); - MageObject sourceObject = game.getObject(source); - Ability ability = (Ability) getValue("targetAbility"); - if (enteringObject != null && sourceObject != null && ability != null) { - MageObject abilitObject = game.getObject(ability.getSourceId()); - if (abilitObject != null) { - return sourceObject.getLogName() + " prevented ability of " + abilitObject.getLogName() - + " to trigger for " + enteringObject.getLogName() + " entering the battlefield."; - } - } - return null; - } - - @Override - public TorporOrbEffect copy() { - return new TorporOrbEffect(this); - } - -} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/TorporOrbTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/TorporOrbTest.java index 36b5edb5309..a93333e4c61 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/TorporOrbTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/TorporOrbTest.java @@ -40,7 +40,7 @@ public class TorporOrbTest extends CardTestPlayerBase { * Hushwing Gryff */ @Test - public void testPitTweller() { + public void testPitDweller() { // Creatures entering the battlefield don't cause abilities to trigger. addCard(Zone.BATTLEFIELD, playerB, "Hushwing Gryff"); addCard(Zone.BATTLEFIELD, playerB, "Treacherous Pit-Dweller"); // 4/3 @@ -63,4 +63,25 @@ public class TorporOrbTest extends CardTestPlayerBase { assertPowerToughness(playerB, "Treacherous Pit-Dweller", 5, 4); } + @Test + public void testHushbringer() { + // Creatures entering the battlefield or dying don't cause abilities to trigger. + addCard(Zone.BATTLEFIELD, playerA, "Hushbringer"); + addCard(Zone.BATTLEFIELD, playerA, "Highland Game"); // 2/1 + // When Highland Game dies, you gain 2 life. + addCard(Zone.HAND, playerA, "Shock"); + addCard(Zone.BATTLEFIELD, playerA, "Mountain"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shock", "Highland Game"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + + assertGraveyardCount(playerA, "Highland Game", 1); + } + } diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbilities.java b/Mage/src/main/java/mage/abilities/TriggeredAbilities.java index 38a96c38643..3279814a95e 100644 --- a/Mage/src/main/java/mage/abilities/TriggeredAbilities.java +++ b/Mage/src/main/java/mage/abilities/TriggeredAbilities.java @@ -96,7 +96,7 @@ public class TriggeredAbilities extends ConcurrentHashMap