From 96b08ee6bf9c453e359f7cfffac4b3e70ed0db09 Mon Sep 17 00:00:00 2001 From: ssk97 Date: Wed, 17 Jul 2024 21:28:50 -0700 Subject: [PATCH] Fix effects where the source's controller sacrifices it (#12583) * Fix effects where the source's controller sacrifices it. Added test. Fixes #12582 * Update Evoke rules text --- .../cards/abilities/keywords/EvokeTest.java | 38 ++++++++++++++++++- ...ceIfCastAtInstantTimeTriggeredAbility.java | 3 +- .../effects/common/SacrificeSourceEffect.java | 12 +++++- .../mage/abilities/keyword/EvokeAbility.java | 4 +- 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/EvokeTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/EvokeTest.java index b3059c1445b..ab7f687ec5b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/EvokeTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/EvokeTest.java @@ -41,8 +41,16 @@ public class EvokeTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shriekmaw"); setChoice(playerA, true); - // addTarget(playerA, "Silvercoat Lion"); Autochosen, only target + setChoice(playerA, "When {this} enters the battlefield, destroy"); //Stack triggers + addTarget(playerA, "Silvercoat Lion"); // Destroy + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Exhume"); + addTarget(playerA, "Shriekmaw"); + addTarget(playerB, "Silvercoat Lion"); //Return + + addTarget(playerA, "Silvercoat Lion"); // Destroy + + setStrictChooseMode(true); setStopAt(1, PhaseStep.END_TURN); execute(); @@ -55,5 +63,31 @@ public class EvokeTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Shriekmaw", 1); } + @Test + public void testControllerSacrifices() { -} \ No newline at end of file + addCard(Zone.BATTLEFIELD, playerA, "Island", 7); + addCard(Zone.HAND, playerA, "Wrong Turn"); + addCard(Zone.HAND, playerA, "Mulldrifter"); + addCard(Zone.BATTLEFIELD, playerB, "Proper Burial"); + + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mulldrifter"); + setChoice(playerA, true); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, 1); + setChoice(playerA, "When {this} enters the battlefield, draw"); //Stack triggers + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wrong Turn"); + addTarget(playerA, playerB); + addTarget(playerA, "Mulldrifter"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, "Mulldrifter", 1); + assertGraveyardCount(playerA, "Wrong Turn", 1); + assertLife(playerB, 22); + assertHandCount(playerA, 2); + } +} diff --git a/Mage/src/main/java/mage/abilities/common/SacrificeIfCastAtInstantTimeTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/SacrificeIfCastAtInstantTimeTriggeredAbility.java index 8dc82bd667a..913964d9500 100644 --- a/Mage/src/main/java/mage/abilities/common/SacrificeIfCastAtInstantTimeTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/SacrificeIfCastAtInstantTimeTriggeredAbility.java @@ -8,7 +8,6 @@ import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.constants.Zone; import mage.game.Game; -import mage.game.events.GameEvent.EventType; import mage.game.events.GameEvent; import mage.game.stack.Spell; @@ -18,7 +17,7 @@ import mage.game.stack.Spell; public class SacrificeIfCastAtInstantTimeTriggeredAbility extends TriggeredAbilityImpl { public SacrificeIfCastAtInstantTimeTriggeredAbility() { - super(Zone.STACK, new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextCleanupDelayedTriggeredAbility(new SacrificeSourceEffect()))); + super(Zone.STACK, new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextCleanupDelayedTriggeredAbility(new SacrificeSourceEffect(true)))); } protected SacrificeIfCastAtInstantTimeTriggeredAbility(final SacrificeIfCastAtInstantTimeTriggeredAbility ability) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java index 3ec8d9ed3a7..c74c2318ea4 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java @@ -13,13 +13,21 @@ import mage.game.permanent.Permanent; */ public class SacrificeSourceEffect extends OneShotEffect { + private final boolean controllerSacrifices; + public SacrificeSourceEffect() { + this(false); + } + + public SacrificeSourceEffect(boolean controllerSacrifices) { super(Outcome.Sacrifice); - staticText = "sacrifice {this}"; + this.controllerSacrifices = controllerSacrifices; + staticText = (controllerSacrifices ? "{this}'s controller sacrifices it" : "sacrifice {this}"); } protected SacrificeSourceEffect(final SacrificeSourceEffect effect) { super(effect); + controllerSacrifices = effect.controllerSacrifices; } @Override @@ -40,7 +48,7 @@ public class SacrificeSourceEffect extends OneShotEffect { if (sourceObject instanceof Permanent) { Permanent permanent = (Permanent) sourceObject; // you can only sacrifice a permanent you control - if (source.isControlledBy(permanent.getControllerId())) { + if (controllerSacrifices || source.isControlledBy(permanent.getControllerId())) { return permanent.sacrifice(source, game); } return true; diff --git a/Mage/src/main/java/mage/abilities/keyword/EvokeAbility.java b/Mage/src/main/java/mage/abilities/keyword/EvokeAbility.java index be32bb39a97..c14e5336849 100644 --- a/Mage/src/main/java/mage/abilities/keyword/EvokeAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/EvokeAbility.java @@ -25,8 +25,8 @@ public class EvokeAbility extends AlternativeSourceCostsImpl { public EvokeAbility(Cost cost) { super(EVOKE_KEYWORD, REMINDER_TEXT, cost); Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new SacrificeSourceEffect()), - EvokedCondition.instance, "Sacrifice {this} when it enters the battlefield and was evoked."); + new EntersBattlefieldTriggeredAbility(new SacrificeSourceEffect(true)), + EvokedCondition.instance, "When this permanent enters the battlefield, if its evoke cost was paid, its controller sacrifices it."); ability.setRuleVisible(false); addSubAbility(ability); }