mirror of
https://github.com/magefree/mage.git
synced 2025-12-23 03:51:58 -08:00
Ketramose, the New Dawn - fixed that it doesn't trigger on itself (miss setLeavesTheBattlefieldTrigger, related to eafbd5a95c)
This commit is contained in:
parent
5b68b20a92
commit
0b4dbaabba
3 changed files with 52 additions and 28 deletions
|
|
@ -13,21 +13,14 @@ import mage.abilities.effects.common.combat.CantAttackBlockUnlessConditionSource
|
||||||
import mage.abilities.keyword.IndestructibleAbility;
|
import mage.abilities.keyword.IndestructibleAbility;
|
||||||
import mage.abilities.keyword.LifelinkAbility;
|
import mage.abilities.keyword.LifelinkAbility;
|
||||||
import mage.abilities.keyword.MenaceAbility;
|
import mage.abilities.keyword.MenaceAbility;
|
||||||
import mage.cards.Card;
|
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.*;
|
||||||
import mage.constants.ComparisonType;
|
|
||||||
import mage.constants.SubType;
|
|
||||||
import mage.constants.SuperType;
|
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.events.ZoneChangeBatchEvent;
|
import mage.game.events.ZoneChangeBatchEvent;
|
||||||
import mage.game.events.ZoneChangeEvent;
|
import mage.game.events.ZoneChangeEvent;
|
||||||
import mage.game.events.ZoneChangeGroupEvent;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -54,7 +47,7 @@ public final class KetramoseTheNewDawn extends CardImpl {
|
||||||
|
|
||||||
// Ketramose can't attack or block unless there are seven or more cards in exile.
|
// Ketramose can't attack or block unless there are seven or more cards in exile.
|
||||||
this.addAbility(new SimpleStaticAbility(
|
this.addAbility(new SimpleStaticAbility(
|
||||||
new CantAttackBlockUnlessConditionSourceEffect(new CardsInExileCondition(ComparisonType.OR_GREATER, 7))
|
new CantAttackBlockUnlessConditionSourceEffect(new CardsInExileCondition(ComparisonType.OR_GREATER, 7))
|
||||||
).addHint(CardsInExileCount.ALL.getHint()));
|
).addHint(CardsInExileCount.ALL.getHint()));
|
||||||
|
|
||||||
// Whenever one or more cards are put into exile from graveyards and/or the battlefield during your turn, you draw a card and lose 1 life.
|
// Whenever one or more cards are put into exile from graveyards and/or the battlefield during your turn, you draw a card and lose 1 life.
|
||||||
|
|
@ -72,10 +65,13 @@ public final class KetramoseTheNewDawn extends CardImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
class KetramoseTriggeredAbility extends TriggeredAbilityImpl {
|
|
||||||
|
class KetramoseTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<ZoneChangeEvent> {
|
||||||
|
|
||||||
KetramoseTriggeredAbility() {
|
KetramoseTriggeredAbility() {
|
||||||
super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), false);
|
super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), false);
|
||||||
this.addEffect(new LoseLifeSourceControllerEffect(1));
|
this.addEffect(new LoseLifeSourceControllerEffect(1));
|
||||||
|
setLeavesTheBattlefieldTrigger(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private KetramoseTriggeredAbility(final KetramoseTriggeredAbility ability) {
|
private KetramoseTriggeredAbility(final KetramoseTriggeredAbility ability) {
|
||||||
|
|
@ -84,25 +80,31 @@ class KetramoseTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
public boolean checkEventType(GameEvent event, Game game) {
|
||||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE_GROUP;
|
return event.getType() == GameEvent.EventType.ZONE_CHANGE_BATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkEvent(ZoneChangeEvent event, Game game) {
|
||||||
|
if (event.getToZone() != Zone.EXILED) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return event.getFromZone() == Zone.GRAVEYARD || event.getFromZone() == Zone.BATTLEFIELD;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
|
||||||
return game.getActivePlayerId().equals(getControllerId())
|
return game.getActivePlayerId().equals(getControllerId())
|
||||||
&& zEvent.getFromZone() == Zone.GRAVEYARD || zEvent.getFromZone() == Zone.BATTLEFIELD;
|
&& !getFilteredEvents((ZoneChangeBatchEvent) event, game).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TriggeredAbility copy()
|
public TriggeredAbility copy() {
|
||||||
{
|
|
||||||
return new KetramoseTriggeredAbility(this);
|
return new KetramoseTriggeredAbility(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRule() {
|
public String getRule() {
|
||||||
return "Whenever one or more cards are put into exile from graveyards"
|
return "Whenever one or more cards are put into exile from graveyards"
|
||||||
+ " and/or the battlefield during your turn, you draw a card and lose 1 life.";
|
+ " and/or the battlefield during your turn, you draw a card and lose 1 life.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package mage.cards.r;
|
package mage.cards.r;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -32,10 +31,11 @@ public final class RelicOfProgenitus extends CardImpl {
|
||||||
public RelicOfProgenitus(UUID ownerId, CardSetInfo setInfo) {
|
public RelicOfProgenitus(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}");
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}");
|
||||||
|
|
||||||
// {tap}: Target player exiles a card from their graveyard.
|
// {T}: Target player exiles a card from their graveyard.
|
||||||
Ability firstAbility = new SimpleActivatedAbility(new RelicOfProgenitusEffect(), new TapSourceCost());
|
Ability firstAbility = new SimpleActivatedAbility(new RelicOfProgenitusEffect(), new TapSourceCost());
|
||||||
firstAbility.addTarget(new TargetPlayer());
|
firstAbility.addTarget(new TargetPlayer());
|
||||||
this.addAbility(firstAbility);
|
this.addAbility(firstAbility);
|
||||||
|
|
||||||
// {1}, Exile Relic of Progenitus: Exile all cards from all graveyards. Draw a card.
|
// {1}, Exile Relic of Progenitus: Exile all cards from all graveyards. Draw a card.
|
||||||
Ability secondAbility = new SimpleActivatedAbility(new ExileGraveyardAllPlayersEffect(), new GenericManaCost(1));
|
Ability secondAbility = new SimpleActivatedAbility(new ExileGraveyardAllPlayersEffect(), new GenericManaCost(1));
|
||||||
secondAbility.addCost(new ExileSourceCost());
|
secondAbility.addCost(new ExileSourceCost());
|
||||||
|
|
|
||||||
|
|
@ -5,17 +5,27 @@ import mage.constants.Zone;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
public class KetramoseTheNewDawnTest extends CardTestPlayerBase {
|
public class KetramoseTheNewDawnTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whenever one or more cards are put into exile from graveyards and/or the battlefield
|
||||||
|
* during your turn, you draw a card and lose 1 life.
|
||||||
|
*/
|
||||||
private final String ketramose = "Ketramose, the New Dawn";
|
private final String ketramose = "Ketramose, the New Dawn";
|
||||||
|
/**
|
||||||
|
* {T}: Target player exiles a card from their graveyard.
|
||||||
|
* {1}, Exile Relic of Progenitus: Exile all cards from all graveyards. Draw a card.
|
||||||
|
*/
|
||||||
private final String relic = "Relic of Progenitus";
|
private final String relic = "Relic of Progenitus";
|
||||||
|
/**
|
||||||
|
* Exile target creature you control, then return it to the battlefield under its owner's control.
|
||||||
|
*/
|
||||||
private final String ephemerate = "Ephemerate";
|
private final String ephemerate = "Ephemerate";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExile() {
|
public void testExile() {
|
||||||
setStrictChooseMode(true);
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
addCard(Zone.BATTLEFIELD, playerA, ketramose);
|
addCard(Zone.BATTLEFIELD, playerA, ketramose);
|
||||||
addCard(Zone.BATTLEFIELD, playerA, relic);
|
addCard(Zone.BATTLEFIELD, playerA, relic);
|
||||||
addCard(Zone.HAND, playerA, ephemerate);
|
addCard(Zone.HAND, playerA, ephemerate);
|
||||||
|
|
@ -23,17 +33,29 @@ public class KetramoseTheNewDawnTest extends CardTestPlayerBase {
|
||||||
addCard(Zone.GRAVEYARD, playerA, "Forest", 10);
|
addCard(Zone.GRAVEYARD, playerA, "Forest", 10);
|
||||||
addCard(Zone.GRAVEYARD, playerB, "Forest", 10);
|
addCard(Zone.GRAVEYARD, playerB, "Forest", 10);
|
||||||
|
|
||||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}:");
|
// exile single
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target player");
|
||||||
addTarget(playerA, playerB);
|
addTarget(playerA, playerB);
|
||||||
addTarget(playerB, "Forest");
|
addTarget(playerB, "Forest");
|
||||||
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{1}, Exile {this}");
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
|
checkLife("exile single - after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, 20 - 1);
|
||||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, ephemerate, ketramose, true);
|
|
||||||
|
// must have two triggers: exile on cost and exile on resolve
|
||||||
|
// exile on cost
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}, Exile {this}");
|
||||||
|
checkStackSize("exile on cost - ability + trigger on stack", 1, PhaseStep.PRECOMBAT_MAIN, playerA, 2);
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, 1);
|
||||||
|
checkLife("exile on cost - after trigger", 1, PhaseStep.PRECOMBAT_MAIN, playerA, 20 - 1 - 1);
|
||||||
|
// exile on resolve
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkLife("exile on resolve - after trigger", 1, PhaseStep.PRECOMBAT_MAIN, playerA, 20 - 1 - 1 - 1);
|
||||||
|
|
||||||
|
// exile ketramose itself and return
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ephemerate, ketramose);
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkLife("exile itself - must trigger", 1, PhaseStep.PRECOMBAT_MAIN, playerA, 20 - 1 - 1 - 1 - 1);
|
||||||
|
|
||||||
setStopAt(1, PhaseStep.END_TURN);
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
assertHandCount(playerA, 4);
|
|
||||||
assertLife(playerA, 20 - 3);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue