mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
fix #13451 (Nether Traitor), add test
This commit is contained in:
parent
198fc02e0c
commit
fa88a3217d
3 changed files with 137 additions and 61 deletions
|
|
@ -1,11 +1,8 @@
|
|||
|
||||
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.common.DiesCreatureTriggeredAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.DoIfCostPaid;
|
||||
import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
|
|
@ -14,11 +11,12 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.ColoredManaSymbol;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -26,6 +24,12 @@ import mage.game.events.ZoneChangeEvent;
|
|||
*/
|
||||
public final class NetherTraitor extends CardImpl {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||
static {
|
||||
filter.add(AnotherPredicate.instance);
|
||||
filter.add(TargetController.YOU.getOwnerPredicate());
|
||||
}
|
||||
|
||||
public NetherTraitor(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{B}{B}");
|
||||
this.subtype.add(SubType.SPIRIT);
|
||||
|
|
@ -39,7 +43,11 @@ public final class NetherTraitor extends CardImpl {
|
|||
this.addAbility(ShadowAbility.getInstance());
|
||||
|
||||
// Whenever another creature is put into your graveyard from the battlefield, you may pay {B}. If you do, return Nether Traitor from your graveyard to the battlefield.
|
||||
this.addAbility(new NetherTraitorTriggeredAbility());
|
||||
this.addAbility(new DiesCreatureTriggeredAbility(Zone.GRAVEYARD, new DoIfCostPaid(
|
||||
new ReturnSourceFromGraveyardToBattlefieldEffect(),
|
||||
new ManaCostsImpl<>("{B}")
|
||||
), false, filter, false
|
||||
).setTriggerPhrase("Whenever another creature is put into your graveyard from the battlefield, "));
|
||||
}
|
||||
|
||||
private NetherTraitor(final NetherTraitor card) {
|
||||
|
|
@ -52,53 +60,3 @@ public final class NetherTraitor extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class NetherTraitorTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
NetherTraitorTriggeredAbility(){
|
||||
super(Zone.GRAVEYARD, new DoIfCostPaid(new ReturnSourceFromGraveyardToBattlefieldEffect(), new ColoredManaCost(ColoredManaSymbol.B)));
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private NetherTraitorTriggeredAbility(final NetherTraitorTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetherTraitorTriggeredAbility copy(){
|
||||
return new NetherTraitorTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||
for (Zone z : Zone.values()) {
|
||||
if (game.checkShortLivingLKI(sourceId, z) && z != Zone.GRAVEYARD) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (zEvent.isDiesEvent()) {
|
||||
if (zEvent.getTarget() != null &&
|
||||
zEvent.getTarget().isOwnedBy(this.getControllerId()) &&
|
||||
zEvent.getTarget().isCreature(game)&&
|
||||
!zEvent.getTarget().getId().equals(this.getSourceId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
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 sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,118 @@
|
|||
package org.mage.test.cards.single.tsp;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author xenohedron
|
||||
*/
|
||||
public class NetherTraitorTest extends CardTestPlayerBase {
|
||||
|
||||
private static final String nt = "Nether Traitor";
|
||||
/* Haste; shadow
|
||||
Whenever another creature is put into your graveyard from the battlefield, you may pay {B}.
|
||||
If you do, return this card from your graveyard to the battlefield.
|
||||
*/
|
||||
private static final String gb = "Goblin Bombardment"; // Sacrifice a creature: 1 damage to any target
|
||||
private static final String wg = "Warpath Ghoul"; // 3/2
|
||||
|
||||
@Test
|
||||
public void testNetherTraitorBattlefieldGhoulDies() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp");
|
||||
addCard(Zone.BATTLEFIELD, playerA, nt);
|
||||
addCard(Zone.BATTLEFIELD, playerA, gb);
|
||||
addCard(Zone.BATTLEFIELD, playerA, wg);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice");
|
||||
setChoice(playerA, wg); // to sac
|
||||
addTarget(playerA, playerB); // 1 damage
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 19);
|
||||
assertGraveyardCount(playerA, wg, 1);
|
||||
assertPermanentCount(playerA, nt, 1);
|
||||
assertTapped("Swamp", false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNetherTraitorBattlefieldAndDies() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp");
|
||||
addCard(Zone.BATTLEFIELD, playerA, nt);
|
||||
addCard(Zone.BATTLEFIELD, playerA, gb);
|
||||
addCard(Zone.BATTLEFIELD, playerA, wg);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice");
|
||||
setChoice(playerA, nt); // to sac
|
||||
addTarget(playerA, playerB); // 1 damage
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 19);
|
||||
assertGraveyardCount(playerA, nt, 1);
|
||||
assertPermanentCount(playerA, wg, 1);
|
||||
assertTapped("Swamp", false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNetherTraitorGraveyardGhoulDies() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp");
|
||||
addCard(Zone.GRAVEYARD, playerA, nt);
|
||||
addCard(Zone.BATTLEFIELD, playerA, gb);
|
||||
addCard(Zone.BATTLEFIELD, playerA, wg);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice");
|
||||
setChoice(playerA, wg); // to sac
|
||||
addTarget(playerA, playerB); // 1 damage
|
||||
setChoice(playerA, true); // yes to pay B and return
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 19);
|
||||
assertGraveyardCount(playerA, wg, 1);
|
||||
assertPermanentCount(playerA, nt, 1);
|
||||
assertTapped("Swamp", true);
|
||||
}
|
||||
|
||||
/* Ruling:
|
||||
If Nether Traitor and another creature are put into your graveyard at the same time,
|
||||
Nether Traitor's ability won't trigger.
|
||||
This is because it must be in your graveyard before the creature dies in order for its ability
|
||||
that returns it to the battlefield to trigger.
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testNetherTraitorGhoulBothDie() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp");
|
||||
addCard(Zone.BATTLEFIELD, playerA, nt);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Tooth and Claw");
|
||||
// Sacrifice two creatures: Create a 3/1 red Beast creature token named Carnivore.
|
||||
addCard(Zone.BATTLEFIELD, playerA, wg);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice two");
|
||||
setChoice(playerA, wg + "^" + nt); // to sac
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20);
|
||||
assertPermanentCount(playerA, "Carnivore", 1);
|
||||
assertGraveyardCount(playerA, wg, 1);
|
||||
assertGraveyardCount(playerA, nt, 1);
|
||||
assertTapped("Swamp", false);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ import mage.constants.SubType;
|
|||
public final class CarnivoreToken extends TokenImpl {
|
||||
|
||||
public CarnivoreToken() {
|
||||
super("Carnivore Token", "3/1 red Beast creature token");
|
||||
super("Carnivore", "3/1 red Beast creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setRed(true);
|
||||
subtype.add(SubType.BEAST);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue