forked from External/mage
implement [MH3] Emrakul, the World Anew
This commit is contained in:
parent
8a07ff30b9
commit
00556c4cf6
4 changed files with 272 additions and 0 deletions
97
Mage.Sets/src/mage/cards/e/EmrakulTheWorldAnew.java
Normal file
97
Mage.Sets/src/mage/cards/e/EmrakulTheWorldAnew.java
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
package mage.cards.e;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.CastSourceTriggeredAbility;
|
||||
import mage.abilities.effects.common.SacrificeAllControllerEffect;
|
||||
import mage.abilities.effects.common.continuous.GainControlAllControlledTargetEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.MadnessAbility;
|
||||
import mage.abilities.keyword.ProtectionAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetPlayer;
|
||||
import mage.watchers.common.SpellsCastWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class EmrakulTheWorldAnew extends CardImpl {
|
||||
|
||||
private static final FilterSpell filterSpell = new FilterSpell("spells");
|
||||
private static final FilterPermanent filterPermanent = new FilterPermanent();
|
||||
|
||||
static {
|
||||
filterPermanent.add(EmrakulTheWorldAnewPredicate.instance);
|
||||
}
|
||||
|
||||
public EmrakulTheWorldAnew(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{12}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.ELDRAZI);
|
||||
this.power = new MageInt(12);
|
||||
this.toughness = new MageInt(12);
|
||||
|
||||
// When you cast this spell, gain control of all creatures target player controls.
|
||||
Ability ability = new CastSourceTriggeredAbility(
|
||||
new GainControlAllControlledTargetEffect(StaticFilters.FILTER_PERMANENT_CREATURES)
|
||||
);
|
||||
ability.addTarget(new TargetPlayer());
|
||||
this.addAbility(ability);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// protection from spells and from permanents that were cast this turn
|
||||
this.addAbility(new ProtectionAbility(filterSpell));
|
||||
this.addAbility(new ProtectionAbility(filterPermanent)
|
||||
.setText("Protection from permanents that were cast this turn"));
|
||||
|
||||
// When Emrakul, the World Anew leaves the battlefield, sacrifice all creatures you control.
|
||||
this.addAbility(new LeavesBattlefieldTriggeredAbility(new SacrificeAllControllerEffect(StaticFilters.FILTER_PERMANENT_CREATURES), false));
|
||||
|
||||
// Madness--Pay six {C}.
|
||||
this.addAbility(new MadnessAbility(new ManaCostsImpl<>("{C}{C}{C}{C}{C}{C}").setText("—Pay six {C}.")));
|
||||
|
||||
}
|
||||
|
||||
private EmrakulTheWorldAnew(final EmrakulTheWorldAnew card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmrakulTheWorldAnew copy() {
|
||||
return new EmrakulTheWorldAnew(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* permanent was cast this turn
|
||||
*/
|
||||
enum EmrakulTheWorldAnewPredicate implements Predicate<Permanent> {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Permanent input, Game game) {
|
||||
SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class);
|
||||
MageObjectReference mor = new MageObjectReference(input, game, -1);
|
||||
return watcher != null && watcher
|
||||
.getAllSpellsCastThisTurn()
|
||||
.anyMatch(spell -> mor.refersTo(spell, game));
|
||||
}
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@ public final class ModernHorizons3 extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Ajani, Nacatl Avenger", 237, Rarity.MYTHIC, mage.cards.a.AjaniNacatlAvenger.class));
|
||||
cards.add(new SetCardInfo("Ajani, Nacatl Pariah", 237, Rarity.MYTHIC, mage.cards.a.AjaniNacatlPariah.class));
|
||||
cards.add(new SetCardInfo("Bloodstained Mire", 216, Rarity.RARE, mage.cards.b.BloodstainedMire.class));
|
||||
cards.add(new SetCardInfo("Emrakul, the World Anew", 6, Rarity.MYTHIC, mage.cards.e.EmrakulTheWorldAnew.class));
|
||||
cards.add(new SetCardInfo("Flare of Cultivation", 154, Rarity.RARE, mage.cards.f.FlareOfCultivation.class));
|
||||
cards.add(new SetCardInfo("Flooded Strand", 220, Rarity.RARE, mage.cards.f.FloodedStrand.class));
|
||||
cards.add(new SetCardInfo("Forest", 308, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,163 @@
|
|||
package org.mage.test.cards.single.mh3;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public class EmrakulTheWorldAnewTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* {@link mage.cards.e.EmrakulTheWorldAnew Emrakul, the World Anew} {12}
|
||||
* Legendary Creature — Eldrazi
|
||||
* When you cast this spell, gain control of all creatures target player controls.
|
||||
* Flying, protection from spells and from permanents that were cast this turn
|
||||
* When Emrakul, the World Anew leaves the battlefield, sacrifice all creatures you control.
|
||||
* Madness—Pay six {C}.
|
||||
* 12/12
|
||||
*/
|
||||
private static final String emrakul = "Emrakul, the World Anew";
|
||||
|
||||
@Test
|
||||
public void test_Madness_And_Triggers() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.HAND, playerA, emrakul, 1);
|
||||
addCard(Zone.HAND, playerA, "One with Nothing"); // Discard your hand
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Wastes", 6);
|
||||
|
||||
addCard(Zone.HAND, playerB, "Diabolic Edict"); // Target player sacrifices a creature.
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Memnite", 2);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "One with Nothing", true);
|
||||
setChoice(playerA, true); // Yes to madness trigger
|
||||
addTarget(playerA, playerB); // for cast trigger
|
||||
|
||||
checkPermanentCount("Has gained control of Memnites", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Memnite", 2);
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Diabolic Edict", playerA);
|
||||
setChoice(playerA, emrakul); // choose to sacrifice emrakul, will trigger leave effect
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, 2); // One with Nothing + Emrakul.
|
||||
assertGraveyardCount(playerB, "Memnite", 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Protection_Spells() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, emrakul);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||
|
||||
addCard(Zone.HAND, playerA, "Murder");
|
||||
addCard(Zone.HAND, playerA, "Pyroclasm");
|
||||
|
||||
checkPlayableAbility("Protected from Murder", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Murder", false);
|
||||
checkPlayableAbility("Pyroclasm can be cast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Pyroclasm", true);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pyroclasm");
|
||||
// Cast, but deals no damage to Emrakul
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertDamageReceived(playerB, emrakul, 0); // protection from spell damage
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Protection_Pacifism() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, emrakul);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
|
||||
addCard(Zone.HAND, playerA, "Pacifism");
|
||||
|
||||
// TODO: Investigate. Pacifism should not be castable at all. Probably more an Aura bug than an Emrakul bug
|
||||
checkPlayableAbility("Protected from Pacifism", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Pacifism", true);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pacifism", emrakul);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
try {
|
||||
execute();
|
||||
Assert.fail("should have failed on casting Pacifism");
|
||||
} catch (AssertionError error) {
|
||||
Assert.assertEquals("Can't find ability to activate command: Cast Pacifism$target=Emrakul, the World Anew", error.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Protection_CastThisTurn() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, emrakul);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
|
||||
addCard(Zone.HAND, playerA, "Chandra, Torch of Defiance"); // −3: Chandra, Torch of Defiance deals 4 damage to target creature.
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Chandra, Torch of Defiance", true);
|
||||
|
||||
checkPlayableAbility("Protected from Chandra the turn it was cast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "-3", false);
|
||||
checkPlayableAbility("No longer protected the turn after", 3, PhaseStep.PRECOMBAT_MAIN, playerA, "-3", true);
|
||||
|
||||
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "-3", emrakul);
|
||||
|
||||
setStopAt(3, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertDamageReceived(playerB, emrakul, 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_NoProtection_IfNotCast() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, emrakul);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Badlands", 5);
|
||||
addCard(Zone.HAND, playerA, "Flametongue Kavu"); // When Flametongue Kavu enters the battlefield, it deals 4 damage to target creature.
|
||||
addCard(Zone.HAND, playerA, "Reanimate");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Flametongue Kavu", true);
|
||||
addTarget(playerA, "Flametongue Kavu"); // only legal target.
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate", "Flametongue Kavu");
|
||||
addTarget(playerA, emrakul); // since Kavu enters from graveyard, it is valid to target emrakul
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertDamageReceived(playerB, emrakul, 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_CanBeBlockedByTokens() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, emrakul);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
|
||||
addCard(Zone.HAND, playerA, "Midnight Haunting"); // Create two 1/1 white Spirit creature tokens with flying.
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Midnight Haunting");
|
||||
attack(2, playerB, emrakul, playerA);
|
||||
block(2, playerA, "Spirit Token", emrakul);
|
||||
|
||||
setStopAt(2, PhaseStep.END_COMBAT);
|
||||
execute();
|
||||
|
||||
assertDamageReceived(playerB, emrakul, 1);
|
||||
assertLife(playerA, 20);
|
||||
}
|
||||
}
|
||||
|
|
@ -30,6 +30,7 @@ public class ProtectionAbility extends StaticAbility {
|
|||
protected boolean doesntRemoveControlled;
|
||||
protected ObjectColor fromColor;
|
||||
protected UUID auraIdNotToBeRemoved; // defines an Aura objectId that will not be removed from this protection ability
|
||||
private String staticText;
|
||||
|
||||
public ProtectionAbility(Filter filter) {
|
||||
super(Zone.BATTLEFIELD, null);
|
||||
|
|
@ -39,6 +40,7 @@ public class ProtectionAbility extends StaticAbility {
|
|||
this.doesntRemoveControlled = false;
|
||||
this.fromColor = new ObjectColor();
|
||||
this.auraIdNotToBeRemoved = null;
|
||||
this.staticText = null;
|
||||
}
|
||||
|
||||
protected ProtectionAbility(final ProtectionAbility ability) {
|
||||
|
|
@ -49,6 +51,7 @@ public class ProtectionAbility extends StaticAbility {
|
|||
this.doesntRemoveControlled = ability.doesntRemoveControlled;
|
||||
this.fromColor = ability.fromColor;
|
||||
this.auraIdNotToBeRemoved = ability.auraIdNotToBeRemoved;
|
||||
this.staticText = ability.staticText;
|
||||
}
|
||||
|
||||
public static ProtectionAbility from(ObjectColor color) {
|
||||
|
|
@ -75,10 +78,18 @@ public class ProtectionAbility extends StaticAbility {
|
|||
|
||||
@Override
|
||||
public String getRule() {
|
||||
if (this.staticText != null && !this.staticText.isEmpty()) {
|
||||
return this.staticText;
|
||||
}
|
||||
return (flavorWord == null ? "protection from " : CardUtil.italicizeWithEmDash(flavorWord) + "Protection from ")
|
||||
+ filter.getMessage() + (removeAuras ? "" : ". This effect doesn't remove Auras.");
|
||||
}
|
||||
|
||||
public ProtectionAbility setText(String text) {
|
||||
this.staticText = text;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean canTarget(MageObject source, Game game) {
|
||||
// TODO: need research, protection ability can be bugged with aura and aura permanents, spells (see below)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue