mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
refactor: fixed dies events support in single cards (part 5);
This commit is contained in:
parent
740a9347ae
commit
6d55e4b9e6
25 changed files with 262 additions and 13 deletions
|
|
@ -65,6 +65,7 @@ class BridgeFromBelowAbility extends TriggeredAbilityImpl {
|
|||
this.filter = filter;
|
||||
this.withInterveningIf(SourceInGraveyardCondition.instance);
|
||||
setTriggerPhrase(filter.getMessage());
|
||||
setLeavesTheBattlefieldTrigger(true); // it's not required for Bridge from Below, but better to keep same code style and verify pass
|
||||
}
|
||||
|
||||
private BridgeFromBelowAbility(final BridgeFromBelowAbility ability) {
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ class LyndeCheerfulTormentorCurseDiesTriggeredAbility extends TriggeredAbilityIm
|
|||
new LyndeCheerfulTormentorReturnCurseEffect()
|
||||
)
|
||||
));
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private LyndeCheerfulTormentorCurseDiesTriggeredAbility(final LyndeCheerfulTormentorCurseDiesTriggeredAbility ability) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package mage.cards.m;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
|
|
@ -50,6 +51,7 @@ class MartyrsBondTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
public MartyrsBondTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new MartyrsBondEffect());
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private MartyrsBondTriggeredAbility(final MartyrsBondTriggeredAbility ability) {
|
||||
|
|
@ -88,6 +90,10 @@ class MartyrsBondTriggeredAbility extends TriggeredAbilityImpl {
|
|||
return "Whenever {this} or another nonland permanent you control is put into a graveyard from the battlefield, each opponent sacrifices a permanent that shares a card type with it.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
class MartyrsBondEffect extends OneShotEffect {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package mage.cards.m;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
|
|
@ -47,6 +48,7 @@ class MolderBeastTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
public MolderBeastTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new BoostSourceEffect(2, 0, Duration.EndOfTurn), false);
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private MolderBeastTriggeredAbility(final MolderBeastTriggeredAbility ability) {
|
||||
|
|
@ -74,4 +76,9 @@ class MolderBeastTriggeredAbility extends TriggeredAbilityImpl {
|
|||
public MolderBeastTriggeredAbility copy() {
|
||||
return new MolderBeastTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package mage.cards.n;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.costs.mana.ColoredManaCost;
|
||||
import mage.abilities.effects.common.DoIfCostPaid;
|
||||
|
|
@ -55,6 +56,7 @@ class NetherTraitorTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
NetherTraitorTriggeredAbility(){
|
||||
super(Zone.GRAVEYARD, new DoIfCostPaid(new ReturnSourceFromGraveyardToBattlefieldEffect(), new ColoredManaCost(ColoredManaSymbol.B)));
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private NetherTraitorTriggeredAbility(final NetherTraitorTriggeredAbility ability) {
|
||||
|
|
@ -94,4 +96,9 @@ class NetherTraitorTriggeredAbility extends TriggeredAbilityImpl {
|
|||
public String getRule() {
|
||||
return "Whenever another creature is put into your graveyard from the battlefield, you may pay {B}. If you do, return {this} from your graveyard to the battlefield.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package mage.cards.n;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
|
|
@ -72,6 +73,7 @@ class NimDeathmantleTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
NimDeathmantleTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new NimDeathmantleEffect(), false);
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private NimDeathmantleTriggeredAbility(final NimDeathmantleTriggeredAbility ability) {
|
||||
|
|
@ -108,6 +110,11 @@ class NimDeathmantleTriggeredAbility extends TriggeredAbilityImpl {
|
|||
public String getRule() {
|
||||
return "Whenever a nontoken creature is put into your graveyard from the battlefield, you may pay {4}. If you do, return that card to the battlefield and attach {this} to it.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
class NimDeathmantleEffect extends OneShotEffect {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package mage.cards.p;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
|
|
@ -97,6 +98,7 @@ class PiasRevolutionTriggeredAbility extends TriggeredAbilityImpl {
|
|||
public PiasRevolutionTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new PiasRevolutionReturnEffect(), false);
|
||||
setTriggerPhrase("Whenever a nontoken artifact is put into your graveyard from the battlefield, ");
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private PiasRevolutionTriggeredAbility(final PiasRevolutionTriggeredAbility ability) {
|
||||
|
|
@ -127,4 +129,9 @@ class PiasRevolutionTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ class PsychomancerTriggeredAbility extends TriggeredAbilityImpl {
|
|||
this.setTriggerPhrase("Whenever {this} or another nontoken artifact you control is put " +
|
||||
"into a graveyard from the battlefield or is put into exile from the battlefield, ");
|
||||
this.withFlavorWord("Harbinger of Despair");
|
||||
this.setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private PsychomancerTriggeredAbility(final PsychomancerTriggeredAbility ability) {
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ class PurgatoryTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
PurgatoryTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new PurgatoryExileEffect(), false);
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private PurgatoryTriggeredAbility(final PurgatoryTriggeredAbility ability) {
|
||||
|
|
@ -103,6 +104,11 @@ class PurgatoryTriggeredAbility extends TriggeredAbilityImpl {
|
|||
public String getRule() {
|
||||
return "Whenever a nontoken creature is put into your graveyard from the battlefield, exile that card.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
class PurgatoryExileEffect extends OneShotEffect {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -40,6 +41,7 @@ class SacredGroundTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
SacredGroundTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect());
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private SacredGroundTriggeredAbility(final SacredGroundTriggeredAbility ability) {
|
||||
|
|
@ -75,4 +77,9 @@ class SacredGroundTriggeredAbility extends TriggeredAbilityImpl {
|
|||
public String getRule() {
|
||||
return "Whenever a spell or ability an opponent controls causes a land to be put into your graveyard from the battlefield, return that card to the battlefield.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.common.ReturnToHandTargetEffect;
|
||||
|
|
@ -56,6 +57,7 @@ class ScrapTrawlerTriggeredAbility extends TriggeredAbilityImpl {
|
|||
super(Zone.BATTLEFIELD, new ReturnToHandTargetEffect());
|
||||
getEffects().get(0).setText("return to your hand target artifact card in your graveyard with lesser mana value");
|
||||
setTriggerPhrase("Whenever {this} or another artifact you control is put into a graveyard from the battlefield, ");
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private ScrapTrawlerTriggeredAbility(final ScrapTrawlerTriggeredAbility ability) {
|
||||
|
|
@ -90,4 +92,9 @@ class ScrapTrawlerTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
package mage.cards.s;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -45,12 +46,13 @@ class ScrapheapTriggeredAbility extends TriggeredAbilityImpl {
|
|||
return new ScrapheapTriggeredAbility(this);
|
||||
}
|
||||
|
||||
private ScrapheapTriggeredAbility(final ScrapheapTriggeredAbility ability){
|
||||
super(ability);
|
||||
}
|
||||
|
||||
public ScrapheapTriggeredAbility(){
|
||||
super(Zone.BATTLEFIELD, new GainLifeEffect(1));
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private ScrapheapTriggeredAbility(final ScrapheapTriggeredAbility ability){
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -76,4 +78,9 @@ class ScrapheapTriggeredAbility extends TriggeredAbilityImpl {
|
|||
public String getRule() {
|
||||
return "Whenever an artifact or enchantment is put into your graveyard from the battlefield, you gain 1 life.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package mage.cards.s;
|
|||
|
||||
import mage.MageInt;
|
||||
import mage.MageItem;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.keyword.SurveilEffect;
|
||||
import mage.abilities.keyword.MenaceAbility;
|
||||
|
|
@ -53,6 +54,7 @@ class SeerOfStolenSightTriggeredAbility extends TriggeredAbilityImpl {
|
|||
SeerOfStolenSightTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new SurveilEffect(1));
|
||||
setTriggerPhrase("Whenever one or more artifacts and/or creatures you control are put into a graveyard from the battlefield, ");
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private SeerOfStolenSightTriggeredAbility(final SeerOfStolenSightTriggeredAbility ability) {
|
||||
|
|
@ -85,4 +87,9 @@ class SeerOfStolenSightTriggeredAbility extends TriggeredAbilityImpl {
|
|||
.map(Controllable::getControllerId)
|
||||
.anyMatch(this::isControlledBy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ class ShardOfTheVoidDragonTriggeredAbility extends TriggeredAbilityImpl {
|
|||
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)));
|
||||
setTriggerPhrase("Whenever an artifact is put into a graveyard from the battlefield or is put into exile from the battlefield, ");
|
||||
withFlavorWord("Matter Absorption");
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private ShardOfTheVoidDragonTriggeredAbility(final ShardOfTheVoidDragonTriggeredAbility ability) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -40,6 +41,7 @@ class SlagstoneRefineryTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
SlagstoneRefineryTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new CreateTokenEffect(new PowerstoneToken(), 1, true));
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private SlagstoneRefineryTriggeredAbility(final SlagstoneRefineryTriggeredAbility ability) {
|
||||
|
|
@ -79,4 +81,9 @@ class SlagstoneRefineryTriggeredAbility extends TriggeredAbilityImpl {
|
|||
return "Whenever {this} or another nontoken artifact you control is put into a graveyard from the battlefield " +
|
||||
"or is put into exile from the battlefield, create a tapped Powerstone token.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ class TheSkullsporeNexusTrigger extends TriggeredAbilityImpl {
|
|||
|
||||
TheSkullsporeNexusTrigger() {
|
||||
super(Zone.BATTLEFIELD, null, false);
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private TheSkullsporeNexusTrigger(final TheSkullsporeNexusTrigger ability) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package mage.cards.t;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
|
||||
|
|
@ -65,6 +66,7 @@ class TianaShipsCaretakerTriggeredAbility extends TriggeredAbilityImpl {
|
|||
TianaShipsCaretakerTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new TianaShipsCaretakerEffect(), true);
|
||||
setTriggerPhrase("Whenever an Aura or Equipment you control is put into a graveyard from the battlefield, ");
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private TianaShipsCaretakerTriggeredAbility(final TianaShipsCaretakerTriggeredAbility ability) {
|
||||
|
|
@ -98,6 +100,11 @@ class TianaShipsCaretakerTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
}
|
||||
}
|
||||
|
||||
class TianaShipsCaretakerEffect extends OneShotEffect {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
package mage.cards.v;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.cards.Card;
|
||||
|
|
@ -40,8 +42,10 @@ public final class ViridianRevel extends CardImpl {
|
|||
}
|
||||
|
||||
class ViridianRevelTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
ViridianRevelTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), true);
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private ViridianRevelTriggeredAbility(final ViridianRevelTriggeredAbility ability) {
|
||||
|
|
@ -75,4 +79,9 @@ class ViridianRevelTriggeredAbility extends TriggeredAbilityImpl {
|
|||
public String getRule() {
|
||||
return "Whenever an artifact is put into an opponent's graveyard from the battlefield, you may draw a card.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package org.mage.test.cards.replacement;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
package org.mage.test.cards.triggers.dies;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
|
||||
public class SeerOfStolenSightTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void test_SingleDie() {
|
||||
skipInitShuffling();
|
||||
addCustomEffect_TargetDestroy(playerA);
|
||||
|
||||
// Whenever one or more artifacts and/or creatures you control are put into a graveyard from the battlefield, surveil 1.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Seer of Stolen Sight");
|
||||
addCard(Zone.LIBRARY, playerA, "Swamp", 2);
|
||||
//
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears");
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "target destroy", "Grizzly Bears");
|
||||
addTarget(playerA, "Swamp"); // surveil
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Grizzly Bears", 1);
|
||||
assertGraveyardCount(playerA, "Swamp", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_MultipleDies() {
|
||||
skipInitShuffling();
|
||||
addCustomEffect_TargetDestroy(playerA, 2);
|
||||
|
||||
// Whenever one or more artifacts and/or creatures you control are put into a graveyard from the battlefield, surveil 1.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Seer of Stolen Sight");
|
||||
addCard(Zone.LIBRARY, playerA, "Swamp", 2);
|
||||
//
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 2);
|
||||
|
||||
// must catch only one time trigger
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "target destroy", "Grizzly Bears^Grizzly Bears");
|
||||
addTarget(playerA, "Swamp"); // surveil
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Grizzly Bears", 2);
|
||||
assertGraveyardCount(playerA, "Swamp", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_OwnDie() {
|
||||
skipInitShuffling();
|
||||
addCustomEffect_TargetDestroy(playerA);
|
||||
|
||||
// Whenever one or more artifacts and/or creatures you control are put into a graveyard from the battlefield, surveil 1.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Seer of Stolen Sight");
|
||||
addCard(Zone.LIBRARY, playerA, "Swamp", 2);
|
||||
//
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1);
|
||||
|
||||
// must trigger on own die
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "target destroy", "Seer of Stolen Sight");
|
||||
addTarget(playerA, "Swamp"); // surveil
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Seer of Stolen Sight", 1);
|
||||
assertGraveyardCount(playerA, "Swamp", 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
|
|||
/**
|
||||
* Tests the {@link mage.abilities.common.DiesOneOrMoreTriggeredAbility} batching.
|
||||
*
|
||||
* @author Susucr
|
||||
* @author Susucr, JayDi85
|
||||
*/
|
||||
public class VengefulTownsfolkTest extends CardTestPlayerBase {
|
||||
|
||||
|
|
@ -145,4 +145,52 @@ public class VengefulTownsfolkTest extends CardTestPlayerBase {
|
|||
assertPermanentCount(playerA, townsfolk, 1);
|
||||
assertPowerToughness(playerA, townsfolk, 3 + 1, 3 + 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplacedDieEvent_Single() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, townsfolk);
|
||||
//
|
||||
// {T}, Sacrifice up to three permanents: If there were three or more card types among the sacrificed permanents, each opponent loses 3 life, you gain 3 life, and you draw three cards.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Baba Lysaga, Night Witch");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Angel of the God-Pharaoh"); // creature with cycle (will be exiled instead die)
|
||||
//
|
||||
// If a card with cycling would be put into your graveyard from anywhere and it wasn't cycled, exile it instead.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Abandoned Sarcophagus");
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}, Sacrifice up to three");
|
||||
setChoice(playerA, "Angel of the God-Pharaoh"); // sac cost
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertExileCount(playerA, "Angel of the God-Pharaoh", 1); // exiled instead die
|
||||
assertPermanentCount(playerA, townsfolk, 1);
|
||||
assertPowerToughness(playerA, townsfolk, 3, 3); // no triggers
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplacedDieEvent_Multiple() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, townsfolk);
|
||||
//
|
||||
// {T}, Sacrifice up to three permanents: If there were three or more card types among the sacrificed permanents, each opponent loses 3 life, you gain 3 life, and you draw three cards.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Baba Lysaga, Night Witch");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 10); // creature
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Angel of the God-Pharaoh"); // creature with cycle (will be exiled instead die)
|
||||
//
|
||||
// If a card with cycling would be put into your graveyard from anywhere and it wasn't cycled, exile it instead.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Abandoned Sarcophagus");
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}, Sacrifice up to three");
|
||||
setChoice(playerA, "Grizzly Bears^Angel of the God-Pharaoh"); // sac cost
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Grizzly Bears", 1);
|
||||
assertExileCount(playerA, "Angel of the God-Pharaoh", 1); // exiled instead die
|
||||
assertPermanentCount(playerA, townsfolk, 1);
|
||||
assertPowerToughness(playerA, townsfolk, 3 + 1, 3 + 1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -351,8 +351,15 @@ public abstract class MageTestPlayerBase {
|
|||
* Add target destroy ability that can be called by text "target destroy"
|
||||
*/
|
||||
protected void addCustomEffect_TargetDestroy(TestPlayer controller) {
|
||||
addCustomEffect_TargetDestroy(controller, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add target destroy ability that can be called by text "target destroy"
|
||||
*/
|
||||
protected void addCustomEffect_TargetDestroy(TestPlayer controller, int numberOfTargets) {
|
||||
Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect().setText("target destroy"), new ManaCostsImpl<>(""));
|
||||
ability.addTarget(new TargetPermanent());
|
||||
ability.addTarget(new TargetPermanent(numberOfTargets, StaticFilters.FILTER_PERMANENT));
|
||||
addCustomCardWithAbility(
|
||||
"target destroy for " + controller.getName(),
|
||||
controller,
|
||||
|
|
|
|||
|
|
@ -1990,12 +1990,21 @@ public class VerifyCardDataTest {
|
|||
.filter(a -> a instanceof TriggeredAbility)
|
||||
.map(a -> (TriggeredAbility) a)
|
||||
.filter(a -> !a.isLeavesTheBattlefieldTrigger())
|
||||
.filter(a -> a.getRule().contains("whenever") || a.getRule().contains("Whenever"))
|
||||
.filter(a -> a.getRule().contains("dies"))
|
||||
//.filter(a -> a.getRule().contains("whenever") || a.getRule().contains("Whenever")) // TODO: research failed cards
|
||||
.filter(a -> a.getRule().contains("die ")
|
||||
|| a.getRule().contains("dies ")
|
||||
|| a.getRule().contains("die,")
|
||||
|| a.getRule().contains("dies,")
|
||||
|| (a.getRule().contains("put into")
|
||||
&& a.getRule().contains("graveyard")
|
||||
&& a.getRule().contains("from the battlefield"))
|
||||
)
|
||||
.filter(a -> !a.getRule().contains("roll")) // ignore roll die effects
|
||||
.filter(a -> !a.getRule().contains("with \"When")) // ignore token creating effects
|
||||
.filter(a -> !a.getRule().contains("gains \"When")) // ignore token creating effects
|
||||
.filter(a -> !a.getRule().contains("and \"When")) // ignore token creating effects
|
||||
.filter(a -> !a.getRule().contains("dies while {this} is in your graveyard")) // ignore Boneyard Scourge
|
||||
.filter(a -> !a.getRule().contains("all creature cards that were put into your")) // ignore Fell Shepherd
|
||||
.filter(a -> !card.getName().equals("Massacre Girl") // delayed trigger fixed, but verify check can't find it
|
||||
&& !card.getName().equals("Infested Thrinax")
|
||||
&& !card.getName().equals("Xira, the Golden Sting")
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ import mage.constants.AbilityType;
|
|||
import mage.constants.AbilityWord;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.BatchEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeBatchEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentToken;
|
||||
|
|
@ -465,8 +467,14 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
|
|||
public static boolean isInUseableZoneDiesTrigger(TriggeredAbility source, GameEvent event, Game game) {
|
||||
// runtime check: wrong trigger settings
|
||||
if (!source.isLeavesTheBattlefieldTrigger()) {
|
||||
// TODO: enable after fix
|
||||
// throw new IllegalArgumentException("Wrong code usage: all dies triggers must use setLeavesTheBattlefieldTrigger(true)");
|
||||
throw new IllegalArgumentException("Wrong code usage: all dies triggers must use setLeavesTheBattlefieldTrigger(true) and override isInUseableZone - "
|
||||
+ source.getSourceObject(game) + " - " + source);
|
||||
}
|
||||
|
||||
// runtime check: wrong isInUseableZone for batch related triggers
|
||||
if (event instanceof BatchEvent) {
|
||||
throw new IllegalArgumentException("Wrong code usage: batch events unsupported here, possible miss of override isInUseableZone - "
|
||||
+ source.getSourceObject(game) + " - " + source);
|
||||
}
|
||||
|
||||
// Get the source permanent of the ability
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ public class DiesOneOrMoreTriggeredAbility extends TriggeredAbilityImpl implemen
|
|||
super(Zone.BATTLEFIELD, effect, optional);
|
||||
this.filter = filter;
|
||||
this.setTriggerPhrase("Whenever one or more " + filter.getMessage() + " die, ");
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private DiesOneOrMoreTriggeredAbility(final DiesOneOrMoreTriggeredAbility ability) {
|
||||
|
|
@ -59,6 +60,6 @@ public class DiesOneOrMoreTriggeredAbility extends TriggeredAbilityImpl implemen
|
|||
return ((ZoneChangeBatchEvent) event)
|
||||
.getEvents()
|
||||
.stream()
|
||||
.allMatch(e -> TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, e, game));
|
||||
.anyMatch(e -> TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, e, game));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue