Add more cards from Kaladesh and Amonkhet blocks (#1504)

* Add Aetherstorm Roc

* Add Dubious Challenge

* Fix cost event of Aetherstorm Roc

* Fix Aetherstorm Roc

* Add MagicPayEnergyEvent in Aetherstorm Roc

* Add Fateful Showdown

* Add Madcap Experiment

* Add Tezzeret's Betrayal

* Add Treasure Keeper

* Add Edifice of Authority

* Add Gate to the Afterlife

* Remove groovy ability in Gate_to_the_Afterlife.txt

* Add Gideon's Resolve

* Add requires_groovy_code line to added cards

* Move another ability of Gate to the Afterlife to groovy

* Add Harvest Season

* Fix closure in Treasure Keeper

* Fix static type checking in Treasure Keeper

* Revert predicate declaration back

* Fix negative predicate closure in Treasure Keeper

* Fix static type checking in Treasure Keeper

* Add God Pharaoh's Gift

* Add requires_groovy_code to Harvest Season

* Use MagicCardList type for event ref

* Add missing comma

* Fix wrong return type

* Add groovy script for God Pharaoh's Gift

* Fix typo

* Fix int type in Harvest Season

* Add Imaginary Threats

* Add Nicol Bolas, the Deceiver

* Remove groovy ability from Nicol_Bolas__the_Deceiver.txt

* Remove redundant player ref from Nicol Bolas, the Deceiver's event

* Add Torment of Hailfire

* Add missing parenthesis

* Add Torment of Venom

* Remove Torment of Venom's effect from txt and add requires_groovy_code
line

* Remove extra ref argument from Torment of Venom's event

* Fix shuffle in Madcap Experiment

* Fix rest.remove(it) in Dubious Challenge

* Refine Madcap Experiment

* Fix Treasure Keeper

* Add exile action in God Pharaoh's Gift

* Use constructor instead of casting in Madcap Experiment

* Add missing choice argument in Torment of Venom

* Fix variable name

* Fix Edifice of Authority

* Fix Fateful Showdown

* Fix Treasure Keeper

* Fix targeting ruling in Tezzeret's Betrayal

* Rewrite Aetherstorm Roc

* Refine Aetherstorm Roc
master
Ada Joule 2018-03-22 16:20:31 +07:00 committed by Melvin Zhang
parent 1d5e788838
commit e5ebff99b1
29 changed files with 733 additions and 26 deletions

View File

@ -0,0 +1,51 @@
def action = {
final MagicGame game, final MagicEvent event ->
if (event.isYes()) {
game.doAction(new ChangeCountersAction(event.getPlayer(), MagicCounterType.Energy, -2));
game.doAction(new ChangeCountersAction(event.getPermanent(), MagicCounterType.PlusOne, 1));
final MagicPermanent target = event.getRefPermanent();
if (target.isValid()) {
game.doAction(new TapAction(target));
}
}
}
[
new ThisAttacksTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent, final MagicPermanent attacker) {
return new MagicEvent(
permanent,
new MagicMayChoice("Choose target creature defending player controls?", TARGET_CREATURE_YOUR_OPPONENT_CONTROLS),
this,
"PN may\$ choose target creature defending player controls\$."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
if (event.getPlayer().getCounters(MagicCounterType.Energy) >= 2) {
if (event.isYes()) {
event.processTargetPermanent(game, {
game.addEvent(new MagicEvent(
event.getSource(),
new MagicMayChoice("Pay {E}{E}?"),
it,
action,
"PN may\$ pay {E}{E}. If PN does, put a +1/+1 counter on SN " +
"and tap RN."
));
});
} else {
game.addEvent(new MagicEvent(
event.getSource(),
new MagicMayChoice("Pay {E}{E}?"),
MagicPermanent.NONE,
action,
"PN may\$ pay {E}{E}. If PN does, put a +1/+1 counter on SN."
));
}
}
}
}
]

View File

@ -8,7 +8,7 @@ subtype=Bird
cost={2}{W}{W}
pt=3/3
ability=Flying;\
Whenever SN or another creature enters the battlefield under your control, you get {E}.;\
Whenever SN attacks, you may pay {E}{E}. If you do, put a +1/+1 counter on it and tap up to one target creature defending player controls.
Whenever SN or another creature enters the battlefield under your control, you get {E}.
timing=main
requires_groovy_code
oracle=Flying\nWhenever Aetherstorm Roc or another creature enters the battlefield under your control, you get {E}.\nWhenever Aetherstorm Roc attacks, you may pay {E}{E}. If you do, put a +1/+1 counter on it and tap up to one target creature defending player controls.

View File

@ -0,0 +1,65 @@
def putOntoBattlefieldAction = {
final MagicGame game, final MagicEvent event ->
final MagicPlayer controller = event.getSource().getController();
final MagicPlayer opponent = event.getPlayer();
final MagicCardList rest = new MagicCardList(event.getRefCardList());
event.processChosenCards(game, {
rest.remove(it);
game.doAction(new ReturnCardAction(MagicLocationType.Exile, it, opponent));
});
rest.each {
game.doAction(new ReturnCardAction(MagicLocationType.Exile, it, controller));
}
}
def exileAction = {
final MagicGame game, final MagicEvent event ->
final MagicPlayer controller = event.getPlayer();
final MagicCardList exiled = new MagicCardList();
event.processChosenCards(game, {
game.doAction(new ShiftCardAction(it, MagicLocationType.OwnersLibrary, MagicLocationType.Exile));
if (it.isInExile()) {
exiled.add(it);
}
});
game.doAction(new ShuffleLibraryAction(controller));
game.addEvent(new MagicEvent(
event.getSource(),
event.getRefPlayer(),
new MagicFromCardListChoice(exiled, 1, true),
exiled,
putOntoBattlefieldAction,
"Target player (PN) may choose one of the exiled cards\$ and put it onto the battlefield under his or her control. " +
"${controller} puts the rest onto the battlefield under ${controller}'s control."
));
}
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
TARGET_OPPONENT,
this,
"PN looks at the top ten cards of PN's library,"
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
final MagicPlayer player = event.getPlayer()
final MagicCardList topCards = player.getLibrary().getCardsFromTop(10);
game.doAction(new LookAction(topCards, player, "top ten cards of your library"));
event.processTargetPlayer(game, {
game.addEvent(new MagicEvent(
event.getSource(),
new MagicFromCardListChoice(topCards.findAll({ it.hasType(MagicType.Creature) }), 2, true),
it,
exileAction,
"exile up to two creature cards from among them\$, then shuffle PN's library."
));
});
}
}
]

View File

@ -5,6 +5,6 @@ value=2.500
rarity=R
type=Sorcery
cost={3}{G}
effect=Look at the top ten cards of your library, exile up to two creature cards from among them, then shuffle your library. Target opponent may choose one of the exiled cards and put it onto the battlefield under his or her control. Put the rest onto the battlefield under your control.
timing=main
requires_groovy_code
oracle=Look at the top ten cards of your library, exile up to two creature cards from among them, then shuffle your library. Target opponent may choose one of the exiled cards and put it onto the battlefield under his or her control. Put the rest onto the battlefield under your control.

View File

@ -0,0 +1,50 @@
def abilityList = MagicAbility.getAbilityList("SN can't attack or block, its activated abilities can't be activated");
def condition = {
final MagicSource source ->
return ((MagicPermanent)source).getCounters(MagicCounterType.Brick) >= 3;
}
[
new MagicPermanentActivation(
[condition],
new MagicActivationHints(MagicTiming.Tapping),
"can't attack or block"
) {
@Override
public Iterable<? extends MagicEvent> getCostEvent(final MagicPermanent source) {
return [
new MagicPayManaCostEvent(source, "{1}"),
new MagicTapEvent(source)
];
}
@Override
public MagicEvent getPermanentEvent(final MagicPermanent source,final MagicPayedCost payedCost) {
return new MagicEvent(
source,
NEG_TARGET_CREATURE,
this,
"Until PN's next turn, target creature\$ can't attack or block and its activated abilites can't be activated."
);
}
@Override
public void executeEvent(final MagicGame outerGame, final MagicEvent outerEvent) {
outerEvent.processTargetPermanent(outerGame, {
outerGame.doAction(new GainAbilityAction(it, abilityList, MagicStatic.Forever));
AtUpkeepTrigger cleanup = new AtUpkeepTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicPlayer upkeepPlayer) {
if (upkeepPlayer.getId() == outerEvent.getPlayer().getId()) {
game.addDelayedAction(new LoseAbilityAction(permanent, abilityList, MagicStatic.Forever));
game.addDelayedAction(new RemoveTriggerAction(permanent, this));
}
return MagicEvent.NONE;
}
}
outerGame.doAction(new AddTriggerAction(it, cleanup));
});
}
}
]

View File

@ -4,7 +4,7 @@ value=2.500
rarity=U
type=Artifact
cost={3}
ability={1}, {T}: Target creature can't attack this turn. Put a brick counter on SN.;\
{1}, {T}: Until your next turn, target creature can't attack or block and its activated abilities can't be activated. Activate this ability only if there are three or more brick counters on SN.
ability={1}, {T}: Target creature can't attack this turn.~Put a brick counter on SN.
timing=artifact
requires_groovy_code
oracle={1}, {T}: Target creature can't attack this turn. Put a brick counter on Edifice of Authority.\n{1}, {T}: Until your next turn, target creature can't attack or block and its activated abilities can't be activated. Activate this ability only if there are three or more brick counters on Edifice of Authority.

View File

@ -0,0 +1,24 @@
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
NEG_TARGET_CREATURE_OR_PLAYER,
this,
"SN deals damage to target creature or player\$ equal to the number of cards in PN's hand. " +
"PN discards all the cards in PN's hand, then draw that many cards."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
final int amount = event.getPlayer().getHandSize();
event.processTarget(game, {
game.doAction(new DealDamageAction(event.getSource(), it, amount));
game.addEvent(new MagicDiscardHandEvent(event.getSource()));
game.addEvent(new MagicDrawEvent(event.getSource(), event.getPlayer(), amount));
});
}
}
]

View File

@ -5,6 +5,6 @@ value=2.500
rarity=R
type=Instant
cost={2}{R}{R}
effect=SN deals damage to target creature or player equal to the number of cards in your hand. Discard all the cards in your hand, then draw that many cards.
timing=removal
requires_groovy_code
oracle=Fateful Showdown deals damage to target creature or player equal to the number of cards in your hand. Discard all the cards in your hand, then draw that many cards.

View File

@ -0,0 +1,89 @@
def drawAction = {
final MagicGame game, final MagicEvent event ->
if (event.isYes()) {
game.doAction(new DrawAction(event.getPlayer()));
game.addEvent(new MagicDiscardEvent(event.getSource()));
}
}
def condition = {
final MagicSource source ->
return source.getController().getGraveyard().count({ it.hasType(MagicType.Creature) }) >= 6;
}
def filter = new MagicCardFilterImpl() {
@Override
public boolean accept(final MagicSource source,final MagicPlayer player,final MagicCard target) {
return target.getName().equalsIgnoreCase("God-Pharaoh's Gift");
}
@Override
public boolean acceptType(final MagicTargetType targetType) {
return targetType == MagicTargetType.Graveyard ||
targetType == MagicTargetType.Hand ||
targetType == MagicTargetType.Library;
}
}
[
new OtherDiesTrigger() {
@Override
public boolean accept(final MagicPermanent permanent, final MagicPermanent died) {
return permanent.isFriend(died) && died.isNonToken();
}
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent, final MagicPermanent died) {
return new MagicEvent(
permanent,
this,
"PN gains 1 life."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
game.doAction(new ChangeLifeAction(event.getPlayer(), 1));
game.addEvent(new MagicEvent(
event.getSource(),
new MagicMayChoice("Draw a card?"),
drawAction,
"Then PN may\$ draw a card. If PN does, PN discards a card."
));
}
},
new MagicPermanentActivation(
[condition],
new MagicActivationHints(MagicTiming.Token),
"God-Pharaoh's Gift"
) {
@Override
public Iterable<? extends MagicEvent> getCostEvent(final MagicPermanent source) {
return [
new MagicPayManaCostEvent(source, "{2}"),
new MagicTapEvent(source),
new MagicSacrificeEvent(source)
];
}
@Override
public MagicEvent getPermanentEvent(final MagicPermanent source,final MagicPayedCost payedCost) {
return new MagicEvent(
source,
this,
"PN searches PN's graveyard, hand, and/or library for a card named God-Pharaoh's Gift and put it onto the battlefield. " +
"If PN searches PN's library this way, shuffle it."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
game.addEvent(new MagicSearchOntoBattlefieldEvent(
event,
new MagicFromCardFilterChoice(
filter,
1,
false,
"a card named God-Pharaoh's Gift from your graveyard, hand, and/or library"
)
));
}
}
]

View File

@ -4,7 +4,6 @@ value=2.500
rarity=U
type=Artifact
cost={3}
ability=Whenever a nontoken creature you control dies, you gain 1 life. Then you may draw a card. If you do, discard a card.;\
{2}, {T}, Sacrifice SN: Search your graveyard, hand, and/or library for a card named God-Pharaoh's Gift and put it onto the battlefield. If you search your library this way, shuffle it. Activate this ability only if there are six or more creature cards in your graveyard.
timing=artifact
requires_groovy_code
oracle=Whenever a nontoken creature you control dies, you gain 1 life. Then you may draw a card. If you do, discard a card.\n{2}, {T}, Sacrifice Gate to the Afterlife: Search your graveyard, hand, and/or library for a card named God-Pharaoh's Gift and put it onto the battlefield. If you search your library this way, shuffle it. Activate this ability only if there are six or more creature cards in your graveyard.

View File

@ -0,0 +1,37 @@
def filter = new MagicCardFilterImpl() {
@Override
public boolean accept(final MagicSource source,final MagicPlayer player,final MagicCard target) {
return target.getName().equalsIgnoreCase("Gideon, Martial Paragon");
}
public boolean acceptType(final MagicTargetType targetType) {
return targetType == MagicTargetType.Library || targetType == MagicTargetType.Graveyard;
}
}
[
new EntersBattlefieldTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent, final MagicPayedCost payedCost) {
return new MagicEvent(
permanent,
new MagicMayChoice("Search for Gideon, Martial Paragon?"),
this,
"PN may\$ search PN's library and/or graveyard for a card named Gideon, Martial Paragon, reveal it, and put it into PN's hand. If PN search PN's library this way, shuffle it."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
game.addEvent(new MagicSearchToLocationEvent(
event,
new MagicFromCardFilterChoice(
filter,
1,
false,
"a card named Gideon, Martial Paragon from your library and/or graveyard"
),
MagicLocationType.OwnersHand
));
}
}
]

View File

@ -4,7 +4,7 @@ value=2.500
rarity=R
type=Enchantment
cost={4}{W}
ability=When SN enters the battlefield, you may search your library and/or graveyard for a card named Gideon, Martial Paragon, reveal it, and put it into your hand. If you search your library this way, shuffle it.;\
Creatures you control get +1/+1.
ability=Creatures you control get +1/+1.
timing=enchantment
requires_groovy_code
oracle=When Gideon's Resolve enters the battlefield, you may search your library and/or graveyard for a card named Gideon, Martial Paragon, reveal it, and put it into your hand. If you search your library this way, shuffle it.\nCreatures you control get +1/+1.

View File

@ -0,0 +1,58 @@
def ZombieStatic = new MagicStatic(MagicLayer.Type) {
@Override
public void modSubTypeFlags(final MagicPermanent permanent, final Set<MagicSubType> flags) {
flags.removeAll(MagicSubType.ALL_CREATURES);
flags.add(MagicSubType.Zombie);
}
}
def PT = {
final MagicGame game, final MagicPermanent perm ->
game.doAction(new AddStaticAction(perm, MagicStatic.genPTSetStatic(4, 4)));
}
def Black = {
final MagicGame game, final MagicPermanent perm ->
game.doAction(new AddStaticAction(perm, MagicStatic.IsBlack));
}
def Zombie = {
final MagicGame game, final MagicPermanent perm ->
game.doAction(new AddStaticAction(perm, ZombieStatic));
}
[
new AtBeginOfCombatTrigger() {
@Override
public boolean accept(final MagicPermanent permanent, final MagicPlayer turnPlayer) {
return permanent.isController(turnPlayer);
}
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent, final MagicPlayer turnPlayer) {
return new MagicEvent(
permanent,
new MagicMayChoice(new MagicTargetChoice("a creature card from your graveyard")),
this,
"PN may\$ exile a creature card from PN's graveyard\$. " +
"If PN does, PN creates a token that's a copy of that card, except it's a 4/4 black Zombie. It gains haste until end of turn."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
if (event.isYes()) {
event.processTargetCard(game, {
game.doAction(new ShiftCardAction(it, MagicLocationType.Graveyard, MagicLocationType.Exile));
game.doAction(new PlayTokenAction(
event.getPlayer(),
it,
PT,
Black,
Zombie,
MagicPlayMod.HASTE_UEOT
));
});
}
}
}
]

View File

@ -4,6 +4,6 @@ value=2.500
rarity=R
type=Artifact
cost={7}
ability=At the beginning of combat on your turn, you may exile a creature card from your graveyard. If you do, create a token that's a copy of that card, except it's a 4/4 black Zombie. It gains haste until end of turn.
timing=artifact
requires_groovy_code
oracle=At the beginning of combat on your turn, you may exile a creature card from your graveyard. If you do, create a token that's a copy of that card, except it's a 4/4 black Zombie. It gains haste until end of turn.

View File

@ -5,21 +5,21 @@
return new MagicEvent(
cardOnStack,
this,
"PN searches his or her library for up to X basic land cards, where X is the number of tapped creatures PN controls, "+
"and puts them onto the battlefield tapped. Then PN shuffles his or her library."
"PN searches PN's library for up to X basic land cards, where X is the number of tapped creatures PN controls, " +
"and puts those cards onto the battlefield tapped. Then shuffle PN's library."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
final int lands = event.getPlayer().getNrOfPermanents(TAPPED_CREATURE_YOU_CONTROL);
game.logAppendX(event.getPlayer(),lands);
final int amount = event.getPlayer().getNrOfPermanents(TAPPED_CREATURE_YOU_CONTROL);
game.logAppendX(event.getPlayer(), amount);
game.addEvent(new MagicSearchOntoBattlefieldEvent(
event,
new MagicFromCardFilterChoice(
BASIC_LAND_CARD_FROM_LIBRARY,
lands,
amount,
true,
"to put onto the battlefield tapped"
"up to ${amount} basic land cards from your library"
),
MagicPlayMod.TAPPED
));

View File

@ -0,0 +1,25 @@
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
TARGET_OPPONENT,
this,
"Creatures target opponent\$ controls attack this turn if able. " +
"During that player's next untap step, creatures he or she controls don't untap."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPlayer(game, {
final MagicPlayer player ->
CREATURE_YOU_CONTROL.filter(player) each {
game.doAction(new GainAbilityAction(it, MagicAbility.AttacksEachTurnIfAble));
game.doAction(ChangeStateAction.DoesNotUntapDuringNext(it, player));
}
});
}
}
]

View File

@ -5,6 +5,6 @@ rarity=U
type=Instant
cost={2}{U}{U}
ability=Cycling {2}
effect=Creatures target opponent controls attack this turn if able. During that player's next untap step, creatures he or she controls don't untap.
timing=removal
requires_groovy_code
oracle=Creatures target opponent controls attack this turn if able. During that player's next untap step, creatures he or she controls don't untap.\nCycling {2}

View File

@ -0,0 +1,35 @@
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
this,
"PN reveals cards from the top of PN's library until PN reveals an artifact card. " +
"Put that card onto the battlefield and the rest on the bottom of PN's library in a random order. " +
"SN deals damage to PN equal to the number of cards revealed this way."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
final MagicPlayer player = event.getPlayer()
final MagicCardList library = player.getLibrary();
def predicate = { final MagicCard card -> card.hasType(MagicType.Artifact) };
final MagicCardList nonTarget = new MagicCardList(library.takeWhile({ !predicate(it) }));
int amount = nonTarget.size() + (library.any(predicate) ? 1 : 0);
if (library.any(predicate)) {
final MagicCard target = library.find(predicate);
game.doAction(new RevealAction(nonTarget.plus(target)));
game.doAction(new ReturnCardAction(MagicLocationType.OwnersLibrary, target, player));
} else {
game.doAction(new RevealAction(nonTarget));
}
nonTarget.shuffle();
nonTarget.each {
game.doAction(new ShiftCardAction(it, MagicLocationType.OwnersLibrary, MagicLocationType.BottomOfOwnersLibrary))
}
game.doAction(new DealDamageAction(event.getSource(), player, amount));
}
}
]

View File

@ -5,6 +5,6 @@ value=2.500
rarity=R
type=Sorcery
cost={3}{R}
effect=Reveal cards from the top of your library until you reveal an artifact card. Put that card onto the battlefield and the rest on the bottom of your library in a random order. SN deals damage to you equal to the number of cards revealed this way.
timing=main
requires_groovy_code
oracle=Reveal cards from the top of your library until you reveal an artifact card. Put that card onto the battlefield and the rest on the bottom of your library in a random order. Madcap Experiment deals damage to you equal to the number of cards revealed this way.

View File

@ -0,0 +1,46 @@
def choice = new MagicTargetChoice("a nonland permanent to sacrifice");
[
new MagicPlaneswalkerActivation(3) {
@Override
public MagicEvent getPermanentEvent(final MagicPermanent source, final MagicPayedCost payedCost) {
return new MagicEvent(
source,
source.getOpponent(),
new MagicOrChoice(
MagicChoice.NONE,
MagicChoice.NONE,
MagicChoice.NONE
),
this,
"Choose one\$ — (1) PN lose 3 life; " +
"or (2) PN sacrifices a nonland permanent; " +
"or (3) PN discards a card."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
if (event.isMode(1)) {
game.doAction(new ChangeLifeAction(event.getPlayer(), -3));
} else if (event.isMode(2)) {
final MagicEvent sac = new MagicSacrificePermanentEvent(
event.getPlayer(),
choice
);
if (sac.isSatisfied()) {
game.addEvent(sac);
} else {
game.doAction(new ChangeLifeAction(event.getPlayer(), -3));
}
} else if (event.isMode(3)) {
final MagicEvent discard = new MagicDiscardEvent(event.getPlayer())
if (discard.isSatisfied()) {
game.addEvent(discard);
} else {
game.doAction(new ChangeLifeAction(event.getPlayer(), -3));
}
}
}
}
]

View File

@ -6,8 +6,8 @@ type=Legendary,Planeswalker
subtype=Bolas
cost={5}{U}{B}{R}
loyalty=5
ability=+3: Each opponent loses 3 life unless that player sacrifices a nonland permanent or discards a card.;\
3: Destroy target creature. Draw a card.;\
11: SN deals 7 damage to each opponent. You draw seven cards.
ability=3: Destroy target creature.~Draw a card.;\
11: SN deals 7 damage to each opponent.~You draw seven cards.
timing=main
requires_groovy_code
oracle=+3: Each opponent loses 3 life unless that player sacrifices a nonland permanent or discards a card.\n3: Destroy target creature. Draw a card.\n11: Nicol Bolas, the Deceiver deals 7 damage to each opponent. You draw seven cards.

View File

@ -0,0 +1,52 @@
def A_CARD_NAMED_TEZZERET_MASTER_OF_METAL_FROM_YOUR_LIBRARY_OR_GRAVEYARD = new MagicCardFilterImpl() {
@Override
public boolean accept(final MagicSource source,final MagicPlayer player,final MagicCard target) {
return target.getName().equalsIgnoreCase("Tezzeret, Master of Metal");
}
public boolean acceptType(final MagicTargetType targetType) {
return targetType == MagicTargetType.Library || targetType == MagicTargetType.Graveyard;
}
}
def searchAction = {
final MagicGame game, final MagicEvent event ->
if (event.isYes()) {
game.addEvent(new MagicSearchToLocationEvent(
event,
new MagicFromCardFilterChoice(
A_CARD_NAMED_TEZZERET_MASTER_OF_METAL_FROM_YOUR_LIBRARY_OR_GRAVEYARD,
1,
false,
"a card named Tezzeret, Master of Metal from your library or graveyard"
),
MagicLocationType.OwnersHand
));
}
}
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
NEG_TARGET_CREATURE,
this,
"Destroy target creature\$."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPermanent(game, {
game.doAction(new DestroyAction(it));
game.addEvent(new MagicEvent(
event.getSource(),
new MagicMayChoice("Search for Tezzeret, Master of Metal?"),
searchAction,
"PN may\$ search PN's library and/or graveyard for a card named Tezzeret, Master of Metal, reveal it, and put it into PN's hand. If PN search his or her library this way, shuffle it."
));
});
}
}
]

View File

@ -4,6 +4,6 @@ value=2.500
rarity=R
type=Sorcery
cost={3}{U}{B}
effect=Destroy target creature. You may search your library and/or graveyard for a card named Tezzeret, Master of Metal, reveal it, and put it into your hand. If you search your library this way, shuffle it.
timing=main
requires_groovy_code
oracle=Destroy target creature. You may search your library and/or graveyard for a card named Tezzeret, Master of Metal, reveal it, and put it into your hand. If you search your library this way, shuffle it.

View File

@ -0,0 +1,61 @@
def choice = new MagicTargetChoice("a nonland permanent to sacrifice");
def action = {
final MagicGame game, final MagicEvent event ->
if (event.isMode(1)) {
game.doAction(new ChangeLifeAction(event.getPlayer(), -3));
} else if (event.isMode(2)) {
final MagicEvent sac = new MagicSacrificePermanentEvent(
event.getPlayer(),
choice
);
if (sac.isSatisfied()) {
game.addEvent(sac);
} else {
game.doAction(new ChangeLifeAction(event.getPlayer(), -3));
}
} else if (event.isMode(3)) {
final MagicEvent discard = new MagicDiscardEvent(event.getPlayer())
if (discard.isSatisfied()) {
game.addEvent(discard);
} else {
game.doAction(new ChangeLifeAction(event.getPlayer(), -3));
}
}
}
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
final int x = payedCost.getX();
return new MagicEvent(
cardOnStack,
cardOnStack.getOpponent(),
x,
this,
"Repeat the following process ${x} times. " +
"PN loses 3 life unless PN sacrifices a nonland permanent or discards a card."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.getRefInt().times {
game.addEvent(new MagicEvent(
event.getSource(),
event.getPlayer(),
new MagicOrChoice(
MagicChoice.NONE,
MagicChoice.NONE,
MagicChoice.NONE
),
action,
"Choose one\$ — (1) PN lose 3 life; " +
"or (2) PN sacrifices a nonland permanent; " +
"or (3) PN discards a card."
));
}
}
}
]

View File

@ -4,6 +4,6 @@ value=2.500
rarity=R
type=Sorcery
cost={X}{B}{B}
effect=Repeat the following process X times. Each opponent loses 3 life unless that player sacrifices a nonland permanent or discards a card.
timing=main
requires_groovy_code
oracle=Repeat the following process X times. Each opponent loses 3 life unless that player sacrifices a nonland permanent or discards a card.

View File

@ -0,0 +1,60 @@
def choice = new MagicTargetChoice("a nonland permanent to sacrifice");
def action = {
final MagicGame game, final MagicEvent event ->
if (event.isMode(1)) {
game.doAction(new ChangeLifeAction(event.getPlayer(), -3));
} else if (event.isMode(2)) {
final MagicEvent sac = new MagicSacrificePermanentEvent(
event.getPlayer(),
choice
);
if (sac.isSatisfied()) {
game.addEvent(sac);
} else {
game.doAction(new ChangeLifeAction(event.getPlayer(), -3));
}
} else if (event.isMode(3)) {
final MagicEvent discard = new MagicDiscardEvent(event.getPlayer())
if (discard.isSatisfied()) {
game.addEvent(discard);
} else {
game.doAction(new ChangeLifeAction(event.getPlayer(), -3));
}
}
}
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
NEG_TARGET_CREATURE,
this,
"Put three -1/-1 counters on target creature\$. " +
"Its controller loses 3 life unless he or she sacrifices a nonland permanent or discards a card."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPermanent(game, {
game.doAction(new ChangeCountersAction(it, MagicCounterType.MinusOne, 3));
game.addEvent(new MagicEvent(
event.getSource(),
it.getController(),
new MagicOrChoice(
MagicChoice.NONE,
MagicChoice.NONE,
MagicChoice.NONE
),
action,
"Choose one\$ — (1) PN lose 3 life; " +
"or (2) PN sacrifices a nonland permanent; " +
"or (3) PN discards a card."
));
});
}
}
]

View File

@ -4,6 +4,6 @@ value=2.500
rarity=C
type=Instant
cost={2}{B}{B}
effect=Put three -1/-1 counters on target creature. Its controller loses 3 life unless he or she sacrifices another nonland permanent or discards a card.
timing=removal
requires_groovy_code
oracle=Put three -1/-1 counters on target creature. Its controller loses 3 life unless he or she sacrifices another nonland permanent or discards a card.

View File

@ -0,0 +1,55 @@
def castAction = {
final MagicGame game, final MagicEvent event ->
final MagicCardList revealed = new MagicCardList(event.getRefCardList());
if (event.isYes()) {
final MagicCard toCast = revealed.last();
revealed.remove(toCast);
game.doAction(CastCardAction.WithoutManaCost(
event.getPlayer(),
toCast,
MagicLocationType.OwnersLibrary,
MagicLocationType.Graveyard
));
}
revealed.each {
game.doAction(new ShiftCardAction(it, MagicLocationType.OwnersLibrary, MagicLocationType.BottomOfOwnersLibrary))
}
}
[
new ThisDiesTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent source, final MagicPermanent died) {
return new MagicEvent(
source,
this,
"PN reveals cards from the top of PN's library until PN reveals a nonland card with converted mana cost 3 or less."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
final MagicPlayer player = event.getPlayer();
final MagicCardList library = player.getLibrary();
def predicate = { final MagicCard card -> !card.hasType(MagicType.Land) && card.getConvertedCost() <= 3 }
final MagicCardList nonTarget = new MagicCardList(library.takeWhile({ !predicate(it) }));
if (library.any(predicate)) {
final MagicCard target = library.find(predicate);
game.doAction(new RevealAction(nonTarget.plus(target)));
game.addEvent(new MagicEvent(
event.getSource(),
new MagicMayChoice("Cast the card?"),
new MagicCardList(nonTarget.plus(target)),
castAction,
"PN may\$ cast that card without paying its mana cost. " +
"Put all revealed cards not cast this way on the bottom of PN's library in any order."
));
} else {
game.doAction(new RevealAction(nonTarget));
nonTarget.each {
game.doAction(new ShiftCardAction(it, MagicLocationType.OwnersLibrary, MagicLocationType.BottomOfOwnersLibrary))
}
}
}
}
]

View File

@ -6,6 +6,6 @@ type=Artifact,Creature
subtype=Construct
cost={4}
pt=3/3
ability=When SN dies, reveal cards from the top of your library until you reveal a nonland card with converted mana cost 3 or less. You may cast that card without paying its mana cost. Put all revealed cards not cast this way on the bottom of your library in a random order.
timing=main
requires_groovy_code
oracle=When Treasure Keeper dies, reveal cards from the top of your library until you reveal a nonland card with converted mana cost 3 or less. You may cast that card without paying its mana cost. Put all revealed cards not cast this way on the bottom of your library in a random order.