Merge branch 'master' into feature/implement-harmonize-ability

This commit is contained in:
theelk801 2025-04-08 09:20:18 -04:00
commit 2fbd7624b9
150 changed files with 5325 additions and 843 deletions

View file

@ -2621,19 +2621,19 @@
<Component class="javax.swing.JCheckBox" name="cbStopBlockWithAny"> <Component class="javax.swing.JCheckBox" name="cbStopBlockWithAny">
<Properties> <Properties>
<Property name="selected" type="boolean" value="true"/> <Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" value="STOP skips on declare blockers if ANY blockers are available"/> <Property name="text" type="java.lang.String" value="STOP skips when attacked and on declare blockers if ANY blockers are available"/>
<Property name="actionCommand" type="java.lang.String" value=""/> <Property name="actionCommand" type="java.lang.String" value=""/>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JCheckBox" name="cbStopBlockWithZero"> <Component class="javax.swing.JCheckBox" name="cbStopBlockWithZero">
<Properties> <Properties>
<Property name="text" type="java.lang.String" value="STOP skips on declare blockers if ZERO blockers are available"/> <Property name="text" type="java.lang.String" value="STOP skips when attacked if ZERO blockers are available"/>
<Property name="actionCommand" type="java.lang.String" value=""/> <Property name="actionCommand" type="java.lang.String" value=""/>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JCheckBox" name="cbStopOnNewStackObjects"> <Component class="javax.swing.JCheckBox" name="cbStopOnNewStackObjects">
<Properties> <Properties>
<Property name="text" type="java.lang.String" value="Skip to STACK resolved (F10): stop on new objects added (on) or stop until empty (off)"/> <Property name="text" type="java.lang.String" value="Skip to STACK resolved (F10): stop on new objects added (on) or stop when stack empty (off)"/>
<Property name="actionCommand" type="java.lang.String" value=""/> <Property name="actionCommand" type="java.lang.String" value=""/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[300, 25]"/> <Dimension value="[300, 25]"/>

View file

@ -2396,15 +2396,15 @@ public class PreferencesDialog extends javax.swing.JDialog {
phases_stopSettings.add(cbStopAttack); phases_stopSettings.add(cbStopAttack);
cbStopBlockWithAny.setSelected(true); cbStopBlockWithAny.setSelected(true);
cbStopBlockWithAny.setText("STOP skips on declare blockers if ANY blockers are available"); cbStopBlockWithAny.setText("STOP skips when attacked and on declare blockers if ANY blockers are available");
cbStopBlockWithAny.setActionCommand(""); cbStopBlockWithAny.setActionCommand("");
phases_stopSettings.add(cbStopBlockWithAny); phases_stopSettings.add(cbStopBlockWithAny);
cbStopBlockWithZero.setText("STOP skips on declare blockers if ZERO blockers are available"); cbStopBlockWithZero.setText("STOP skips when attacked if ZERO blockers are available");
cbStopBlockWithZero.setActionCommand(""); cbStopBlockWithZero.setActionCommand("");
phases_stopSettings.add(cbStopBlockWithZero); phases_stopSettings.add(cbStopBlockWithZero);
cbStopOnNewStackObjects.setText("Skip to STACK resolved (F10): stop on new objects added (on) or stop until empty (off)"); cbStopOnNewStackObjects.setText("Skip to STACK resolved (F10): stop on new objects added (on) or stop when stack empty (off)");
cbStopOnNewStackObjects.setActionCommand(""); cbStopOnNewStackObjects.setActionCommand("");
cbStopOnNewStackObjects.setPreferredSize(new java.awt.Dimension(300, 25)); cbStopOnNewStackObjects.setPreferredSize(new java.awt.Dimension(300, 25));
phases_stopSettings.add(cbStopOnNewStackObjects); phases_stopSettings.add(cbStopOnNewStackObjects);

View file

@ -123,6 +123,7 @@ public class ModernCardRenderer extends CardRenderer {
public static final Color ERROR_COLOR = new Color(255, 0, 255); public static final Color ERROR_COLOR = new Color(255, 0, 255);
static String SUB_TYPE_ADVENTURE = "Adventure"; static String SUB_TYPE_ADVENTURE = "Adventure";
static String SUB_TYPE_OMEN = "Omen";
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Layout metrics for modern border cards // Layout metrics for modern border cards
@ -168,8 +169,8 @@ public class ModernCardRenderer extends CardRenderer {
// Processed mana cost string // Processed mana cost string
protected String manaCostString; protected String manaCostString;
// Is an adventure // Is an adventure or omen
protected boolean isAdventure = false; protected boolean isCardWithSpellOption = false;
public ModernCardRenderer(CardView card) { public ModernCardRenderer(CardView card) {
// Pass off to parent // Pass off to parent
@ -179,12 +180,13 @@ public class ModernCardRenderer extends CardRenderer {
manaCostString = ManaSymbols.getClearManaCost(cardView.getManaCostStr()); manaCostString = ManaSymbols.getClearManaCost(cardView.getManaCostStr());
if (cardView.isSplitCard()) { if (cardView.isSplitCard()) {
isAdventure = cardView.getRightSplitTypeLine().contains(SUB_TYPE_ADVENTURE); isCardWithSpellOption = cardView.getRightSplitTypeLine().contains(SUB_TYPE_ADVENTURE)
|| cardView.getRightSplitTypeLine().contains(SUB_TYPE_OMEN);
} }
} }
protected boolean isAdventure() { protected boolean isCardWithSpellOption() {
return isAdventure; return isCardWithSpellOption;
} }
@Override @Override
@ -660,7 +662,7 @@ public class ModernCardRenderer extends CardRenderer {
drawRulesText(g, textboxKeywords, textboxRules, drawRulesText(g, textboxKeywords, textboxRules,
contentWidth / 2 + totalContentInset + 4, totalContentInset + boxHeight + 2, contentWidth / 2 + totalContentInset + 4, totalContentInset + boxHeight + 2,
contentWidth / 2 - 8, typeLineY - totalContentInset - boxHeight - 6, false); contentWidth / 2 - 8, typeLineY - totalContentInset - boxHeight - 6, false);
} else if (isAdventure) { } else if (isCardWithSpellOption) {
drawRulesText(g, textboxKeywords, textboxRules, drawRulesText(g, textboxKeywords, textboxRules,
contentWidth / 2 + totalContentInset + 4, typeLineY + boxHeight + 2, contentWidth / 2 + totalContentInset + 4, typeLineY + boxHeight + 2,
contentWidth / 2 - 8, cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3, false); contentWidth / 2 - 8, cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3, false);

View file

@ -56,7 +56,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
private boolean isAftermath = false; private boolean isAftermath = false;
private static String trimAdventure(String rule) { private static String trimAdventure(String rule) {
if (rule.startsWith("Adventure")) { if (rule.startsWith("Adventure") || rule.startsWith("Omen")) {
return rule.substring(rule.lastIndexOf("&mdash;") + 8); return rule.substring(rule.lastIndexOf("&mdash;") + 8);
} }
return rule; return rule;
@ -71,7 +71,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
rightHalf.color = new ObjectColor(cardView.getRightSplitCostsStr()); rightHalf.color = new ObjectColor(cardView.getRightSplitCostsStr());
leftHalf.color = new ObjectColor(cardView.getLeftSplitCostsStr()); leftHalf.color = new ObjectColor(cardView.getLeftSplitCostsStr());
if (isAdventure()) { if (isCardWithSpellOption()) {
List<String> trimmedRules = new ArrayList<>(); List<String> trimmedRules = new ArrayList<>();
for (String rule : view.getRightSplitRules()) { for (String rule : view.getRightSplitRules()) {
trimmedRules.add(trimAdventure(rule)); trimmedRules.add(trimAdventure(rule));
@ -95,7 +95,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
// they "rotate" in opposite directions making consquence and normal split cards // they "rotate" in opposite directions making consquence and normal split cards
// have the "right" vs "left" as the top half. // have the "right" vs "left" as the top half.
// Adventures are treated differently and not rotated at all. // Adventures are treated differently and not rotated at all.
if (isAdventure()) { if (isCardWithSpellOption()) {
manaCostString = leftHalf.manaCostString; manaCostString = leftHalf.manaCostString;
textboxKeywords = leftHalf.keywords; textboxKeywords = leftHalf.keywords;
textboxRules = leftHalf.rules; textboxRules = leftHalf.rules;
@ -159,7 +159,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
protected void drawBackground(Graphics2D g) { protected void drawBackground(Graphics2D g) {
if (cardView.isFaceDown()) { if (cardView.isFaceDown()) {
drawCardBackTexture(g); drawCardBackTexture(g);
} if (isAdventure()) { } if (isCardWithSpellOption()) {
super.drawBackground(g); super.drawBackground(g);
} else { } else {
{ // Left half background (top of the card) { // Left half background (top of the card)
@ -204,7 +204,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
@Override @Override
protected void drawArt(Graphics2D g) { protected void drawArt(Graphics2D g) {
if (isAdventure) { if (isCardWithSpellOption) {
super.drawArt(g); super.drawArt(g);
} else if (artImage != null) { } else if (artImage != null) {
if (isAftermath()) { if (isAftermath()) {
@ -318,7 +318,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
@Override @Override
protected void drawFrame(Graphics2D g, CardPanelAttributes attribs, BufferedImage image, boolean lessOpaqueRulesTextBox) { protected void drawFrame(Graphics2D g, CardPanelAttributes attribs, BufferedImage image, boolean lessOpaqueRulesTextBox) {
if (isAdventure()) { if (isCardWithSpellOption()) {
super.drawFrame(g, attribs, image, lessOpaqueRulesTextBox); super.drawFrame(g, attribs, image, lessOpaqueRulesTextBox);
CardPanelAttributes adventureAttribs = new CardPanelAttributes( CardPanelAttributes adventureAttribs = new CardPanelAttributes(

View file

@ -204,7 +204,7 @@ public enum GrabbagImageSource implements CardImageSource {
singleLinks.put("SWS/Hazard Trooper", "ZOutamG.jpeg"); singleLinks.put("SWS/Hazard Trooper", "ZOutamG.jpeg");
singleLinks.put("SWS/Head Hunting", "7OT1bGZ.jpeg"); singleLinks.put("SWS/Head Hunting", "7OT1bGZ.jpeg");
singleLinks.put("SWS/Heavy Trooper", "HhZWs2N.jpeg"); singleLinks.put("SWS/Heavy Trooper", "HhZWs2N.jpeg");
singleLinks.put("SWS/Hot Pursuit", "ih1GT5Z.jpeg"); singleLinks.put("SWS/Hot Pursuit (Star Wars)", "ih1GT5Z.jpeg");
singleLinks.put("SWS/Hungry Dragonsnake", "23v7RTm.jpeg"); singleLinks.put("SWS/Hungry Dragonsnake", "23v7RTm.jpeg");
singleLinks.put("SWS/Hunt to Extinction", "3eJyfzZ.jpeg"); singleLinks.put("SWS/Hunt to Extinction", "3eJyfzZ.jpeg");
singleLinks.put("SWS/Hutt Crime Lord", "NAzK7Hp.jpeg"); singleLinks.put("SWS/Hutt Crime Lord", "NAzK7Hp.jpeg");

View file

@ -439,7 +439,7 @@ public class ScryfallImageSupportCards {
add("ELD"); // Throne of Eldraine add("ELD"); // Throne of Eldraine
//add("PTG"); // Ponies: The Galloping //add("PTG"); // Ponies: The Galloping
add("CMB1"); // Mystery Booster Playtest Cards 2019 add("CMB1"); // Mystery Booster Playtest Cards 2019
//add("MB1"); // Mystery Booster add("MB1"); // Mystery Booster
add("GN2"); // Game Night 2019 add("GN2"); // Game Night 2019
add("HA1"); // Historic Anthology 1 add("HA1"); // Historic Anthology 1
//add("HHO"); // Happy Holidays //add("HHO"); // Happy Holidays
@ -534,7 +534,7 @@ public class ScryfallImageSupportCards {
add("ONE"); // Phyrexia: All Will Be One add("ONE"); // Phyrexia: All Will Be One
add("ONC"); // Phyrexia: All Will Be One Commander add("ONC"); // Phyrexia: All Will Be One Commander
add("PL23"); // Year of the Rabbit 2023 add("PL23"); // Year of the Rabbit 2023
add("DA1"); // Unknown Event add("UNK"); // Unknown Event
add("SIS"); // Shadows of the Past add("SIS"); // Shadows of the Past
add("SIR"); // Shadows over Innistrad Remastered add("SIR"); // Shadows over Innistrad Remastered
add("SLP"); // Secret Lair Showdown add("SLP"); // Secret Lair Showdown
@ -683,8 +683,16 @@ public class ScryfallImageSupportCards {
// CALC - custom alchemy version of cards. // CALC - custom alchemy version of cards.
put("CALC/C-Pillar of the Paruns", "https://api.scryfall.com/cards/dis/176/"); put("CALC/C-Pillar of the Paruns", "https://api.scryfall.com/cards/dis/176/");
// MB1
put("MB1/Goblin Trenches", "https://api.scryfall.com/cards/plst/EMA-203/");
put("MB1/Prophetic Bolt", "https://api.scryfall.com/cards/plst/C15-231/");
// LTR - 0 number for tokens only // LTR - 0 number for tokens only
put("LTR/The One Ring/001", "https://api.scryfall.com/cards/ltr/0/"); // Scryfall has a bug, for some reason this link doesn't work with ?format=image even though it works with ?format=json
// and ?format=text. Base url fails because language is qya and not en and alternate url fails because of this bug
// TODO: This should be reverted when Scryfall fixes the bug
// put("LTR/The One Ring/001", "https://api.scryfall.com/cards/ltr/0/");
put("LTR/The One Ring/001", "https://api.scryfall.com/cards/ltr/0/qya?format=image");
// REX - double faced lands (xmage uses two diff lands for it) // REX - double faced lands (xmage uses two diff lands for it)
put("REX/Command Tower/26b", "https://api.scryfall.com/cards/rex/26/en?format=image&face=back"); put("REX/Command Tower/26b", "https://api.scryfall.com/cards/rex/26/en?format=image&face=back");

View file

@ -39,7 +39,8 @@ public class ScryfallImageSupportTokens {
putAll(TokenRepository.instance.prepareScryfallDownloadList()); putAll(TokenRepository.instance.prepareScryfallDownloadList());
// RIX // RIX
put("RIX/City's Blessing", "https://api.scryfall.com/cards/trix/6/en?format=image"); // TODO: missing from tokens data // TODO: this should be readded when condition tokens are implemented
// put("RIX/City's Blessing", "https://api.scryfall.com/cards/trix/6/en?format=image");
put("RIX/Elemental/1", "https://api.scryfall.com/cards/trix/1/en?format=image"); put("RIX/Elemental/1", "https://api.scryfall.com/cards/trix/1/en?format=image");
put("RIX/Elemental/2", "https://api.scryfall.com/cards/trix/2/en?format=image"); put("RIX/Elemental/2", "https://api.scryfall.com/cards/trix/2/en?format=image");
put("RIX/Golem", "https://api.scryfall.com/cards/trix/4/en?format=image"); put("RIX/Golem", "https://api.scryfall.com/cards/trix/4/en?format=image");
@ -117,22 +118,6 @@ public class ScryfallImageSupportTokens {
put("AKH/Warrior", "https://api.scryfall.com/cards/takh/17/en?format=image"); put("AKH/Warrior", "https://api.scryfall.com/cards/takh/17/en?format=image");
put("AKH/Wurm", "https://api.scryfall.com/cards/takh/24/en?format=image"); put("AKH/Wurm", "https://api.scryfall.com/cards/takh/24/en?format=image");
put("AKH/Zombie", "https://api.scryfall.com/cards/takh/20/en?format=image"); put("AKH/Zombie", "https://api.scryfall.com/cards/takh/20/en?format=image");
// AKH - embalm ability (token from card)
put("AKH/Angel of Sanctions", "https://api.scryfall.com/cards/takh/1/en?format=image");
put("AKH/Anointer Priest", "https://api.scryfall.com/cards/takh/2/en?format=image");
put("AKH/Aven Initiate", "https://api.scryfall.com/cards/takh/3/en?format=image");
put("AKH/Aven Wind Guide", "https://api.scryfall.com/cards/takh/4/en?format=image");
put("AKH/Glyph Keeper", "https://api.scryfall.com/cards/takh/5/en?format=image");
put("AKH/Heart-Piercer Manticore", "https://api.scryfall.com/cards/takh/6/en?format=image");
put("AKH/Honored Hydra", "https://api.scryfall.com/cards/takh/7/en?format=image");
put("AKH/Labyrinth Guardian", "https://api.scryfall.com/cards/takh/8/en?format=image");
put("AKH/Oketra's Attendant", "https://api.scryfall.com/cards/takh/9/en?format=image");
put("AKH/Sacred Cat", "https://api.scryfall.com/cards/takh/10/en?format=image");
put("AKH/Tah-Crop Skirmisher", "https://api.scryfall.com/cards/takh/11/en?format=image");
put("AKH/Temmet, Vizier of Naktamun", "https://api.scryfall.com/cards/takh/12/en?format=image");
put("AKH/Trueheart Duelist", "https://api.scryfall.com/cards/takh/13/en?format=image");
put("AKH/Unwavering Initiate", "https://api.scryfall.com/cards/takh/14/en?format=image");
put("AKH/Vizier of Many Faces", "https://api.scryfall.com/cards/takh/15/en?format=image");
// AER // AER
put("AER/Etherium Cell", "https://api.scryfall.com/cards/taer/3/en?format=image"); put("AER/Etherium Cell", "https://api.scryfall.com/cards/taer/3/en?format=image");
@ -501,7 +486,7 @@ public class ScryfallImageSupportTokens {
put("ZNC/Elemental/1", "https://api.scryfall.com/cards/tznc/10/en?format=image"); // 5/5 put("ZNC/Elemental/1", "https://api.scryfall.com/cards/tznc/10/en?format=image"); // 5/5
put("ZNC/Elemental/2", "https://api.scryfall.com/cards/tznc/8/en?format=image"); // 2/2 put("ZNC/Elemental/2", "https://api.scryfall.com/cards/tznc/8/en?format=image"); // 2/2
put("ZNC/Faerie Rogue", "https://api.scryfall.com/cards/tznc/3/en?format=image"); put("ZNC/Faerie Rogue", "https://api.scryfall.com/cards/tznc/3/en?format=image");
put("ZNC/Germ", "https://api.scryfall.com/cards/tznc/4/en?format=image"); // must be in chest or antology put("ZNC/Phyrexian Germ", "https://api.scryfall.com/cards/tznc/4/en?format=image"); // must be in chest or antology
put("ZNC/Goblin Rogue", "https://api.scryfall.com/cards/tznc/5/en?format=image"); put("ZNC/Goblin Rogue", "https://api.scryfall.com/cards/tznc/5/en?format=image");
put("ZNC/Kor Ally", "https://api.scryfall.com/cards/tznc/2/en?format=image"); put("ZNC/Kor Ally", "https://api.scryfall.com/cards/tznc/2/en?format=image");
put("ZNC/Rat", "https://api.scryfall.com/cards/tznc/6/en?format=image"); put("ZNC/Rat", "https://api.scryfall.com/cards/tznc/6/en?format=image");
@ -596,7 +581,6 @@ public class ScryfallImageSupportTokens {
put("C21/Beast/1", "https://api.scryfall.com/cards/tc21/10/en?format=image"); // 3/3 put("C21/Beast/1", "https://api.scryfall.com/cards/tc21/10/en?format=image"); // 3/3
put("C21/Beast/2", "https://api.scryfall.com/cards/tc21/11/en?format=image"); // 4/4 put("C21/Beast/2", "https://api.scryfall.com/cards/tc21/11/en?format=image"); // 4/4
put("C21/Boar", "https://api.scryfall.com/cards/tc21/12/en?format=image"); put("C21/Boar", "https://api.scryfall.com/cards/tc21/12/en?format=image");
put("C21/Champion of Wits", "https://api.scryfall.com/cards/tc21/6/en?format=image");
put("C21/Construct/1", "https://api.scryfall.com/cards/tc21/22/en?format=image"); // x/x put("C21/Construct/1", "https://api.scryfall.com/cards/tc21/22/en?format=image"); // x/x
put("C21/Construct/2", "https://api.scryfall.com/cards/tc21/23/en?format=image"); // 0/0 put("C21/Construct/2", "https://api.scryfall.com/cards/tc21/23/en?format=image"); // 0/0
put("C21/Demon", "https://api.scryfall.com/cards/tc21/7/en?format=image"); put("C21/Demon", "https://api.scryfall.com/cards/tc21/7/en?format=image");
@ -829,17 +813,45 @@ public class ScryfallImageSupportTokens {
put("NEC/Thopter", "https://api.scryfall.com/cards/tnec/12/en?format=image"); put("NEC/Thopter", "https://api.scryfall.com/cards/tnec/12/en?format=image");
// SLD // SLD
put("SLD/Angel", "https://api.scryfall.com/cards/sld/1340?format=image");
put("SLD/Cat/1", "https://api.scryfall.com/cards/sld/1517?format=image");
put("SLD/Cat/2", "https://api.scryfall.com/cards/sld/27?format=image");
put("SLD/Cat/3", "https://api.scryfall.com/cards/sld/28?format=image");
put("SLD/Clue", "https://api.scryfall.com/cards/sld/348/en?format=image"); put("SLD/Clue", "https://api.scryfall.com/cards/sld/348/en?format=image");
put("SLD/Dog", "https://api.scryfall.com/cards/sld/1516?format=image");
put("SLD/Egg", "https://api.scryfall.com/cards/sld/1398?format=image");
put("SLD/Faerie Rogue/1", "https://api.scryfall.com/cards/sld/13/en?format=image"); put("SLD/Faerie Rogue/1", "https://api.scryfall.com/cards/sld/13/en?format=image");
put("SLD/Faerie Rogue/2", "https://api.scryfall.com/cards/sld/14/en?format=image"); put("SLD/Faerie Rogue/2", "https://api.scryfall.com/cards/sld/14/en?format=image");
put("SLD/Faerie Rogue/3", "https://api.scryfall.com/cards/sld/15/en?format=image"); put("SLD/Faerie Rogue/3", "https://api.scryfall.com/cards/sld/15/en?format=image");
put("SLD/Faerie Rogue/4", "https://api.scryfall.com/cards/sld/16/en?format=image"); put("SLD/Faerie Rogue/4", "https://api.scryfall.com/cards/sld/16/en?format=image");
put("SLD/Treasure", "https://api.scryfall.com/cards/sld/153/en?format=image"); put("SLD/Food/1", "https://api.scryfall.com/cards/sld/1938?format=image");
put("SLD/Food/2", "https://api.scryfall.com/cards/sld/2010?format=image");
put("SLD/Food/3", "https://api.scryfall.com/cards/sld/2011?format=image");
put("SLD/Food/4", "https://api.scryfall.com/cards/sld/2012?format=image");
put("SLD/Food/5", "https://api.scryfall.com/cards/sld/2013?format=image");
put("SLD/Goblin", "https://api.scryfall.com/cards/sld/219?format=image");
put("SLD/Hydra", "https://api.scryfall.com/cards/sld/1334?format=image");
put("SLD/Icingdeath, Frost Tongue", "https://api.scryfall.com/cards/sld/1018?format=image");
put("SLD/Marit Lage", "https://api.scryfall.com/cards/sld/1681?format=image");
put("SLD/Mechtitan", "https://api.scryfall.com/cards/sld/1969?format=image");
put("SLD/Saproling", "https://api.scryfall.com/cards/sld/1139?format=image");
put("SLD/Shrine", "https://api.scryfall.com/cards/sld/1835?format=image");
put("SLD/Spirit/1", "https://api.scryfall.com/cards/sld/1341?format=image");
put("SLD/Spirit/2", "https://api.scryfall.com/cards/sld/1852?format=image");
put("SLD/Squirrel", "https://api.scryfall.com/cards/sld/200?format=image");
put("SLD/Treasure/1", "https://api.scryfall.com/cards/sld/1432/en?format=image");
put("SLD/Treasure/2", "https://api.scryfall.com/cards/sld/1736/en?format=image");
put("SLD/Treasure/3", "https://api.scryfall.com/cards/sld/1507/en?format=image");
put("SLD/Treasure/4", "https://api.scryfall.com/cards/sld/153/en?format=image");
put("SLD/Walker/1", "https://api.scryfall.com/cards/sld/148/en?format=image"); put("SLD/Walker/1", "https://api.scryfall.com/cards/sld/148/en?format=image");
put("SLD/Walker/2", "https://api.scryfall.com/cards/sld/149/en?format=image"); put("SLD/Walker/2", "https://api.scryfall.com/cards/sld/149/en?format=image");
put("SLD/Walker/3", "https://api.scryfall.com/cards/sld/150/en?format=image"); put("SLD/Walker/3", "https://api.scryfall.com/cards/sld/150/en?format=image");
put("SLD/Walker/4", "https://api.scryfall.com/cards/sld/151/en?format=image"); put("SLD/Walker/4", "https://api.scryfall.com/cards/sld/151/en?format=image");
put("SLD/Walker/5", "https://api.scryfall.com/cards/sld/152/en?format=image"); put("SLD/Walker/5", "https://api.scryfall.com/cards/sld/152/en?format=image");
put("SLD/Warrior", "https://api.scryfall.com/cards/sld/1752?format=image");
put("SLD/Wolf", "https://api.scryfall.com/cards/sld/1613?format=image");
put("SLD/Wurm", "https://api.scryfall.com/cards/sld/1306?format=image");
put("SLD/Zombie", "https://api.scryfall.com/cards/sld/1357?format=image");
// 2XM // 2XM
put("2XM/Angel", "https://api.scryfall.com/cards/t2xm/3/en?format=image"); put("2XM/Angel", "https://api.scryfall.com/cards/t2xm/3/en?format=image");
@ -1707,6 +1719,7 @@ public class ScryfallImageSupportTokens {
put("CLB/Squid", "https://api.scryfall.com/cards/tclb/29/en?format=image"); put("CLB/Squid", "https://api.scryfall.com/cards/tclb/29/en?format=image");
put("CLB/Squirrel", "https://api.scryfall.com/cards/tclb/15/en?format=image"); put("CLB/Squirrel", "https://api.scryfall.com/cards/tclb/15/en?format=image");
put("CLB/Treasure", "https://api.scryfall.com/cards/tclb/17/en?format=image"); put("CLB/Treasure", "https://api.scryfall.com/cards/tclb/17/en?format=image");
put("CLB/Undercity", "https://api.scryfall.com/cards/tclb/20/en?format=image");
put("CLB/Volo's Journal", "https://api.scryfall.com/cards/tclb/18/en?format=image"); put("CLB/Volo's Journal", "https://api.scryfall.com/cards/tclb/18/en?format=image");
put("CLB/Warrior", "https://api.scryfall.com/cards/tclb/32/en?format=image"); put("CLB/Warrior", "https://api.scryfall.com/cards/tclb/32/en?format=image");
put("CLB/Emblem Will Kenrith", "https://api.scryfall.com/cards/tclb/50/en?format=image"); put("CLB/Emblem Will Kenrith", "https://api.scryfall.com/cards/tclb/50/en?format=image");
@ -2168,12 +2181,35 @@ public class ScryfallImageSupportTokens {
put("WOC/Virtuous", "https://api.scryfall.com/cards/twoc/3/en?format=image"); put("WOC/Virtuous", "https://api.scryfall.com/cards/twoc/3/en?format=image");
// WHO // WHO
put("WHO/Alien", "https://api.scryfall.com/cards/twho/2?format=image");
put("WHO/Alien Insect", "https://api.scryfall.com/cards/twho/19/en?format=image"); put("WHO/Alien Insect", "https://api.scryfall.com/cards/twho/19/en?format=image");
put("WHO/Human Noble", "https://api.scryfall.com/cards/twho/7/en?format=image"); put("WHO/Alien Rhino", "https://api.scryfall.com/cards/twho/3/en?format=image");
put("WHO/Alien Salamander", "https://api.scryfall.com/cards/twho/16?format=image");
put("WHO/Alien Warrior", "https://api.scryfall.com/cards/twho/14?format=image");
put("WHO/Beast", "https://api.scryfall.com/cards/twho/17?format=image");
put("WHO/Clue/1", "https://api.scryfall.com/cards/twho/21?format=image");
put("WHO/Clue/2", "https://api.scryfall.com/cards/twho/22?format=image");
put("WHO/Clue/3", "https://api.scryfall.com/cards/twho/23?format=image");
put("WHO/Dalek", "https://api.scryfall.com/cards/twho/12?format=image");
put("WHO/Dinosaur", "https://api.scryfall.com/cards/twho/20?format=image");
put("WHO/Fish", "https://api.scryfall.com/cards/twho/10?format=image");
put("WHO/Food/1", "https://api.scryfall.com/cards/twho/25?format=image");
put("WHO/Food/2", "https://api.scryfall.com/cards/twho/26?format=image");
put("WHO/Food/3", "https://api.scryfall.com/cards/twho/27?format=image");
put("WHO/Horse", "https://api.scryfall.com/cards/twho/4/en?format=image"); put("WHO/Horse", "https://api.scryfall.com/cards/twho/4/en?format=image");
put("WHO/Human/1", "https://api.scryfall.com/cards/twho/6/en?format=image");
put("WHO/Human/2", "https://api.scryfall.com/cards/twho/5/en?format=image");
put("WHO/Human Noble", "https://api.scryfall.com/cards/twho/7/en?format=image");
put("WHO/Mark of the Rani", "https://api.scryfall.com/cards/twho/15?format=image");
put("WHO/Soldier", "https://api.scryfall.com/cards/twho/8?format=image");
put("WHO/Treasure/1", "https://api.scryfall.com/cards/twho/28?format=image");
put("WHO/Treasure/2", "https://api.scryfall.com/cards/twho/29?format=image");
put("WHO/Treasure/3", "https://api.scryfall.com/cards/twho/30?format=image");
put("WHO/Treasure/4", "https://api.scryfall.com/cards/twho/31?format=image");
put("WHO/Warrior", "https://api.scryfall.com/cards/twho/9?format=image");
// 8ED // 8ED
put("8ED/Rukh", "https://api.scryfall.com/cards/p03/7/en?format=image"); put("8ED/Bird", "https://api.scryfall.com/cards/p03/7/en?format=image");
// LCI // LCI
put("LCI/Angel", "https://api.scryfall.com/cards/tlci/2/en?format=image"); put("LCI/Angel", "https://api.scryfall.com/cards/tlci/2/en?format=image");
@ -2494,7 +2530,18 @@ public class ScryfallImageSupportTokens {
put("BLC/Wolf/2", "https://api.scryfall.com/cards/tblc/32/en?format=image"); put("BLC/Wolf/2", "https://api.scryfall.com/cards/tblc/32/en?format=image");
// DSK // DSK
put("DSK/Beast", "https://api.scryfall.com/cards/tdsk/3?format=image");
put("DSK/Emblem Kaito", "https://api.scryfall.com/cards/tdsk/17/en?format=image"); put("DSK/Emblem Kaito", "https://api.scryfall.com/cards/tdsk/17/en?format=image");
put("DSK/Everywhere", "https://api.scryfall.com/cards/tdsk/16?format=image");
put("DSK/Glimmer", "https://api.scryfall.com/cards/tdsk/4?format=image");
put("DSK/Gremlin", "https://api.scryfall.com/cards/tdsk/11?format=image");
put("DSK/Insect/1", "https://api.scryfall.com/cards/tdsk/13?format=image");
put("DSK/Insect/2", "https://api.scryfall.com/cards/tdsk/5?format=image");
put("DSK/Primo, the Indivisible", "https://api.scryfall.com/cards/tdsk/14?format=image");
put("DSK/Shard", "https://api.scryfall.com/cards/tdsk/2?format=image");
put("DSK/Spider", "https://api.scryfall.com/cards/tdsk/12?format=image");
put("DSK/Spirit", "https://api.scryfall.com/cards/tdsk/8?format=image");
put("DSK/Treasure", "https://api.scryfall.com/cards/tdsk/15?format=image");
// DSC // DSC
put("DSC/Angel", "https://api.scryfall.com/cards/tdsc/2/en?format=image"); put("DSC/Angel", "https://api.scryfall.com/cards/tdsc/2/en?format=image");
@ -2633,18 +2680,25 @@ public class ScryfallImageSupportTokens {
// TDC // TDC
put("TDC/Angel", "https://api.scryfall.com/cards/ttdc/2/en?format=image"); put("TDC/Angel", "https://api.scryfall.com/cards/ttdc/2/en?format=image");
put("TDC/Beast", "https://api.scryfall.com/cards/ttdc/20?format=image");
put("TDC/Citizen", "https://api.scryfall.com/cards/ttdc/26/en?format=image"); put("TDC/Citizen", "https://api.scryfall.com/cards/ttdc/26/en?format=image");
put("TDC/Dog", "https://api.scryfall.com/cards/ttdc/3/en?format=image"); put("TDC/Dog", "https://api.scryfall.com/cards/ttdc/3/en?format=image");
put("TDC/Dragon/1", "https://api.scryfall.com/cards/ttdc/13?format=image");
put("TDC/Dragon/2", "https://api.scryfall.com/cards/ttdc/14?format=image");
put("TDC/Dragon Egg", "https://api.scryfall.com/cards/ttdc/12?format=image");
put("TDC/Dragon Illusion", "https://api.scryfall.com/cards/ttdc/15/en?format=image"); put("TDC/Dragon Illusion", "https://api.scryfall.com/cards/ttdc/15/en?format=image");
put("TDC/Eldrazi", "https://api.scryfall.com/cards/ttdc/1/en?format=image"); put("TDC/Eldrazi", "https://api.scryfall.com/cards/ttdc/1/en?format=image");
put("TDC/Elemental/1", "https://api.scryfall.com/cards/ttdc/16/en?format=image"); put("TDC/Elemental/1", "https://api.scryfall.com/cards/ttdc/16/en?format=image");
put("TDC/Elemental/2", "https://api.scryfall.com/cards/ttdc/17/en?format=image"); put("TDC/Elemental/2", "https://api.scryfall.com/cards/ttdc/17/en?format=image");
put("TDC/Elemental/3", "https://api.scryfall.com/cards/ttdc/27/en?format=image"); put("TDC/Elemental/3", "https://api.scryfall.com/cards/ttdc/27/en?format=image");
put("TDC/First Mate Ragavan", "https://api.scryfall.com/cards/ttdc/18/en?format=image"); put("TDC/First Mate Ragavan", "https://api.scryfall.com/cards/ttdc/18/en?format=image");
put("TDC/Frog Lizard", "https://api.scryfall.com/cards/ttdc/21?format=image");
put("TDC/Goat", "https://api.scryfall.com/cards/ttdc/4/en?format=image"); put("TDC/Goat", "https://api.scryfall.com/cards/ttdc/4/en?format=image");
put("TDC/Gold", "https://api.scryfall.com/cards/ttdc/29/en?format=image"); put("TDC/Gold", "https://api.scryfall.com/cards/ttdc/29/en?format=image");
put("TDC/Human", "https://api.scryfall.com/cards/ttdc/5/en?format=image"); put("TDC/Human", "https://api.scryfall.com/cards/ttdc/5/en?format=image");
put("TDC/Inkling", "https://api.scryfall.com/cards/ttdc/28?format=image");
put("TDC/Insect", "https://api.scryfall.com/cards/ttdc/22/en?format=image"); put("TDC/Insect", "https://api.scryfall.com/cards/ttdc/22/en?format=image");
put("TDC/Karox Bladewing", "https://api.scryfall.com/cards/ttdc/19?format=image");
put("TDC/Myr", "https://api.scryfall.com/cards/ttdc/30/en?format=image"); put("TDC/Myr", "https://api.scryfall.com/cards/ttdc/30/en?format=image");
put("TDC/Plant", "https://api.scryfall.com/cards/ttdc/24/en?format=image"); put("TDC/Plant", "https://api.scryfall.com/cards/ttdc/24/en?format=image");
put("TDC/Rat", "https://api.scryfall.com/cards/ttdc/9/en?format=image"); put("TDC/Rat", "https://api.scryfall.com/cards/ttdc/9/en?format=image");
@ -2652,9 +2706,136 @@ public class ScryfallImageSupportTokens {
put("TDC/Servo", "https://api.scryfall.com/cards/ttdc/31/en?format=image"); put("TDC/Servo", "https://api.scryfall.com/cards/ttdc/31/en?format=image");
put("TDC/Snake", "https://api.scryfall.com/cards/ttdc/10/en?format=image"); put("TDC/Snake", "https://api.scryfall.com/cards/ttdc/10/en?format=image");
put("TDC/Soldier", "https://api.scryfall.com/cards/ttdc/32/en?format=image"); put("TDC/Soldier", "https://api.scryfall.com/cards/ttdc/32/en?format=image");
put("TDC/Spider", "https://api.scryfall.com/cards/ttdc/25?format=image");
put("TDC/Spirit", "https://api.scryfall.com/cards/ttdc/6/en?format=image"); put("TDC/Spirit", "https://api.scryfall.com/cards/ttdc/6/en?format=image");
put("TDC/Thopter", "https://api.scryfall.com/cards/ttdc/33/en?format=image"); put("TDC/Thopter", "https://api.scryfall.com/cards/ttdc/33/en?format=image");
// ACR
put("ACR/Assassin", "https://api.scryfall.com/cards/tacr/4?format=image");
put("ACR/Emblem Capitoline Triad", "https://api.scryfall.com/cards/tacr/7/en?format=image");
put("ACR/Human Rogue", "https://api.scryfall.com/cards/tacr/3?format=image");
put("ACR/Phobos", "https://api.scryfall.com/cards/tacr/5?format=image");
put("ACR/Shapeshifter", "https://api.scryfall.com/cards/tacr/2?format=image");
put("ACR/Treasure", "https://api.scryfall.com/cards/tacr/6?format=image");
// DD2
put("DD2/Elemental Shaman", "https://api.scryfall.com/cards/tdd2/1?format=image");
// FIN
put("FIN/Food", "https://api.scryfall.com/cards/tfin/22?format=image");
// JVC
put("JVC/Elemental Shaman", "https://api.scryfall.com/cards/tjvc/4?format=image");
// PIP
put("PIP/Alien", "https://api.scryfall.com/cards/tpip/6?format=image");
put("PIP/Clue", "https://api.scryfall.com/cards/tpip/11?format=image");
put("PIP/Food/1", "https://api.scryfall.com/cards/tpip/12?format=image");
put("PIP/Food/2", "https://api.scryfall.com/cards/tpip/13?format=image");
put("PIP/Food/3", "https://api.scryfall.com/cards/tpip/14?format=image");
put("PIP/Human Knight", "https://api.scryfall.com/cards/tpip/2?format=image");
put("PIP/Human Soldier", "https://api.scryfall.com/cards/tpip/3?format=image");
put("PIP/Junk", "https://api.scryfall.com/cards/tpip/15?format=image");
put("PIP/Robot", "https://api.scryfall.com/cards/tpip/16?format=image");
put("PIP/Settlement", "https://api.scryfall.com/cards/tpip/8?format=image");
put("PIP/Soldier/1", "https://api.scryfall.com/cards/tpip/10?format=image");
put("PIP/Soldier/2", "https://api.scryfall.com/cards/tpip/4?format=image");
put("PIP/Squirrel", "https://api.scryfall.com/cards/tpip/9?format=image");
put("PIP/Thopter", "https://api.scryfall.com/cards/tpip/17?format=image");
put("PIP/Treasure/1", "https://api.scryfall.com/cards/tpip/18?format=image");
put("PIP/Treasure/2", "https://api.scryfall.com/cards/tpip/19?format=image");
put("PIP/Warrior", "https://api.scryfall.com/cards/tpip/5?format=image");
put("PIP/Wasteland Survival Guide", "https://api.scryfall.com/cards/tpip/20?format=image");
put("PIP/Zombie Mutant", "https://api.scryfall.com/cards/tpip/7?format=image");
// REX
put("REX/Dinosaur", "https://api.scryfall.com/cards/trex/1?format=image");
put("REX/Treasure", "https://api.scryfall.com/cards/trex/2?format=image");
// UGL
put("UGL/Goblin", "https://api.scryfall.com/cards/tugl/4?format=image");
put("UGL/Pegasus", "https://api.scryfall.com/cards/tugl/1?format=image");
put("UGL/Soldier", "https://api.scryfall.com/cards/tugl/2?format=image");
put("UGL/Squirrel", "https://api.scryfall.com/cards/tugl/6?format=image");
put("UGL/Zombie", "https://api.scryfall.com/cards/tugl/3?format=image");
// UST
put("UST/Angel", "https://api.scryfall.com/cards/tust/1?format=image");
put("UST/Beast", "https://api.scryfall.com/cards/tust/13?format=image");
put("UST/Brainiac", "https://api.scryfall.com/cards/tust/10?format=image");
put("UST/Clue", "https://api.scryfall.com/cards/tust/18?format=image");
put("UST/Dragon", "https://api.scryfall.com/cards/tust/16?format=image");
put("UST/Elemental/1", "https://api.scryfall.com/cards/tust/11?format=image");
put("UST/Elemental/2", "https://api.scryfall.com/cards/tust/17?format=image");
put("UST/Gnome", "https://api.scryfall.com/cards/tust/20?format=image");
put("UST/Goat", "https://api.scryfall.com/cards/tust/2?format=image");
put("UST/Goblin", "https://api.scryfall.com/cards/tust/12?format=image");
put("UST/Saproling", "https://api.scryfall.com/cards/tust/14?format=image");
put("UST/Spirit", "https://api.scryfall.com/cards/tust/3?format=image");
put("UST/Squirrel", "https://api.scryfall.com/cards/tust/15?format=image");
put("UST/Storm Crow", "https://api.scryfall.com/cards/tust/5?format=image");
put("UST/Thopter", "https://api.scryfall.com/cards/tust/6?format=image");
put("UST/Vampire", "https://api.scryfall.com/cards/tust/8?format=image");
put("UST/Zombie", "https://api.scryfall.com/cards/tust/9?format=image");
// F12
put("F12/Human", "https://api.scryfall.com/cards/f12/1a?format=image");
put("F12/Wolf", "https://api.scryfall.com/cards/f12/1a?format=image&face=back");
// F17
put("F17/Dinosaur", "https://api.scryfall.com/cards/f17/11?format=image");
put("F17/Pirate", "https://api.scryfall.com/cards/f17/12?format=image");
put("F17/Vampire", "https://api.scryfall.com/cards/f17/10?format=image");
put("F17/Treasure/1", "https://api.scryfall.com/cards/f17/11?format=image&face=back");
put("F17/Treasure/2", "https://api.scryfall.com/cards/f17/12?format=image&face=back");
put("F17/Treasure/3", "https://api.scryfall.com/cards/f17/10?format=image&face=back");
// HHO
put("HHO/Treasure", "https://api.scryfall.com/cards/hho/21★?format=image");
// J12
put("J12/Centaur", "https://api.scryfall.com/cards/j12/9?format=image");
// J13
put("J13/Golem", "https://api.scryfall.com/cards/j13/9?format=image");
// MPR
put("MPR/Bear", "https://api.scryfall.com/cards/mpr/7?format=image");
put("MPR/Beast", "https://api.scryfall.com/cards/mpr/8?format=image");
put("MPR/Bird", "https://api.scryfall.com/cards/mpr/4?format=image");
put("MPR/Elephant", "https://api.scryfall.com/cards/mpr/3?format=image");
put("MPR/Goblin Soldier", "https://api.scryfall.com/cards/mpr/6?format=image");
put("MPR/Saproling", "https://api.scryfall.com/cards/mpr/2?format=image");
put("MPR/Spirit", "https://api.scryfall.com/cards/mpr/5?format=image");
// P03
put("P03/Bear", "https://api.scryfall.com/cards/p03/4?format=image");
put("P03/Demon", "https://api.scryfall.com/cards/p03/6?format=image");
put("P03/Goblin", "https://api.scryfall.com/cards/p03/5?format=image");
put("P03/Insect", "https://api.scryfall.com/cards/p03/2?format=image");
put("P03/Bird", "https://api.scryfall.com/cards/p03/7?format=image");
put("P03/Sliver", "https://api.scryfall.com/cards/p03/3?format=image");
// P04
put("P04/Angel", "https://api.scryfall.com/cards/p04/2?format=image");
put("P04/Beast", "https://api.scryfall.com/cards/p04/5?format=image");
put("P04/Myr", "https://api.scryfall.com/cards/p04/4?format=image");
put("P04/Pentavite", "https://api.scryfall.com/cards/p04/3?format=image");
put("P04/Spirit", "https://api.scryfall.com/cards/p04/6?format=image");
// PEMN
put("PEMN/Zombie/1", "https://api.scryfall.com/cards/pemn/1Z?format=image");
put("PEMN/Zombie/2", "https://api.scryfall.com/cards/pemn/1Z?format=image&face=back");
// PHEL
put("PHEL/Angel", "https://api.scryfall.com/cards/phel/1★?format=image");
// PL21
put("PL21/Minotaur", "https://api.scryfall.com/cards/pl21/2★?format=image");
// PL23
put("PL23/Food", "https://api.scryfall.com/cards/pl23/2?format=image");
// generate supported sets // generate supported sets
supportedSets.clear(); supportedSets.clear();
for (String cardName : this.keySet()) { for (String cardName : this.keySet()) {

View file

@ -43,7 +43,7 @@ public class ScryfallImagesDownloadTest {
.anyMatch(c -> c.getCardNumber().equals("001")) .anyMatch(c -> c.getCardNumber().equals("001"))
); );
urls = imageSource.generateCardUrl(new CardDownloadData("The One Ring", "LTR", "001", false, 0)); urls = imageSource.generateCardUrl(new CardDownloadData("The One Ring", "LTR", "001", false, 0));
Assert.assertEquals("https://api.scryfall.com/cards/ltr/0/en?format=image", urls.getBaseUrl()); Assert.assertEquals("https://api.scryfall.com/cards/ltr/0/qya?format=image", urls.getBaseUrl());
// added same tests for small images // added same tests for small images
@ -74,6 +74,6 @@ public class ScryfallImagesDownloadTest {
.anyMatch(c -> c.getCardNumber().equals("001")) .anyMatch(c -> c.getCardNumber().equals("001"))
); );
urls = imageSourceSmall.generateCardUrl(new CardDownloadData("The One Ring", "LTR", "001", false, 0)); urls = imageSourceSmall.generateCardUrl(new CardDownloadData("The One Ring", "LTR", "001", false, 0));
Assert.assertEquals("https://api.scryfall.com/cards/ltr/0/en?format=image&version=small", urls.getBaseUrl()); Assert.assertEquals("https://api.scryfall.com/cards/ltr/0/qya?format=image&version=small", urls.getBaseUrl());
} }
} }

View file

@ -432,21 +432,21 @@ public class CardView extends SimpleCardView {
fullCardName = mainCard.getLeftHalfCard().getName() + MockCard.MODAL_DOUBLE_FACES_NAME_SEPARATOR + mainCard.getRightHalfCard().getName(); fullCardName = mainCard.getLeftHalfCard().getName() + MockCard.MODAL_DOUBLE_FACES_NAME_SEPARATOR + mainCard.getRightHalfCard().getName();
this.manaCostLeftStr = mainCard.getLeftHalfCard().getManaCostSymbols(); this.manaCostLeftStr = mainCard.getLeftHalfCard().getManaCostSymbols();
this.manaCostRightStr = mainCard.getRightHalfCard().getManaCostSymbols(); this.manaCostRightStr = mainCard.getRightHalfCard().getManaCostSymbols();
} else if (card instanceof AdventureCard) { } else if (card instanceof CardWithSpellOption) {
this.isSplitCard = true; this.isSplitCard = true;
AdventureCard adventureCard = ((AdventureCard) card); CardWithSpellOption mainCard = ((CardWithSpellOption) card);
leftSplitName = adventureCard.getName(); leftSplitName = mainCard.getName();
leftSplitCostsStr = String.join("", adventureCard.getManaCostSymbols()); leftSplitCostsStr = String.join("", mainCard.getManaCostSymbols());
leftSplitRules = adventureCard.getSharedRules(game); leftSplitRules = mainCard.getSharedRules(game);
leftSplitTypeLine = getCardTypeLine(game, adventureCard); leftSplitTypeLine = getCardTypeLine(game, mainCard);
AdventureCardSpell adventureCardSpell = adventureCard.getSpellCard(); SpellOptionCard splitCardSpell = mainCard.getSpellCard();
rightSplitName = adventureCardSpell.getName(); rightSplitName = splitCardSpell.getName();
rightSplitCostsStr = String.join("", adventureCardSpell.getManaCostSymbols()); rightSplitCostsStr = String.join("", splitCardSpell.getManaCostSymbols());
rightSplitRules = adventureCardSpell.getRules(game); rightSplitRules = splitCardSpell.getRules(game);
rightSplitTypeLine = getCardTypeLine(game, adventureCardSpell); rightSplitTypeLine = getCardTypeLine(game, splitCardSpell);
fullCardName = adventureCard.getName() + MockCard.ADVENTURE_NAME_SEPARATOR + adventureCardSpell.getName(); fullCardName = mainCard.getName() + MockCard.CARD_WITH_SPELL_OPTION_NAME_SEPARATOR + splitCardSpell.getName();
this.manaCostLeftStr = adventureCard.getManaCostSymbols(); this.manaCostLeftStr = mainCard.getManaCostSymbols();
this.manaCostRightStr = adventureCardSpell.getManaCostSymbols(); this.manaCostRightStr = splitCardSpell.getManaCostSymbols();
} else if (card instanceof MockCard) { } else if (card instanceof MockCard) {
// deck editor cards // deck editor cards
fullCardName = ((MockCard) card).getFullName(true); fullCardName = ((MockCard) card).getFullName(true);

View file

@ -64,6 +64,7 @@ public class Legacy extends Constructed {
banned.add("Sensei's Divining Top"); banned.add("Sensei's Divining Top");
banned.add("Skullclamp"); banned.add("Skullclamp");
banned.add("Sol Ring"); banned.add("Sol Ring");
banned.add("Sowing Mycospawn");
banned.add("Strip Mine"); banned.add("Strip Mine");
banned.add("Survival of the Fittest"); banned.add("Survival of the Fittest");
banned.add("Time Vault"); banned.add("Time Vault");
@ -72,6 +73,7 @@ public class Legacy extends Constructed {
banned.add("Tinker"); banned.add("Tinker");
banned.add("Tolarian Academy"); banned.add("Tolarian Academy");
banned.add("Treasure Cruise"); banned.add("Treasure Cruise");
banned.add("Troll of Khazad-dum");
banned.add("Underworld Breach"); banned.add("Underworld Breach");
banned.add("Vampiric Tutor"); banned.add("Vampiric Tutor");
banned.add("Vexing Bauble"); banned.add("Vexing Bauble");

View file

@ -69,6 +69,7 @@ public class Modern extends Constructed {
banned.add("Treasure Cruise"); banned.add("Treasure Cruise");
banned.add("Tree of Tales"); banned.add("Tree of Tales");
banned.add("Umezawa's Jitte"); banned.add("Umezawa's Jitte");
banned.add("Underworld Breach");
banned.add("Up the Beanstalk"); banned.add("Up the Beanstalk");
banned.add("Uro, Titan of Nature's Wrath"); banned.add("Uro, Titan of Nature's Wrath");
banned.add("Vault of Whispers"); banned.add("Vault of Whispers");

View file

@ -29,6 +29,7 @@ public class Pauper extends Constructed {
banned.add("All That Glitters"); banned.add("All That Glitters");
banned.add("Arcum's Astrolabe"); banned.add("Arcum's Astrolabe");
banned.add("Atog"); banned.add("Atog");
banned.add("Basking Broodscale");
banned.add("Bonder's Ornament"); banned.add("Bonder's Ornament");
banned.add("Chatterstorm"); banned.add("Chatterstorm");
banned.add("Cloud of Faeries"); banned.add("Cloud of Faeries");
@ -36,6 +37,7 @@ public class Pauper extends Constructed {
banned.add("Cranial Plating"); banned.add("Cranial Plating");
banned.add("Cranial Ram"); banned.add("Cranial Ram");
banned.add("Daze"); banned.add("Daze");
banned.add("Deadly Dispute");
banned.add("Disciple of the Vault"); banned.add("Disciple of the Vault");
banned.add("Empty the Warrens"); banned.add("Empty the Warrens");
banned.add("Fall from Favor"); banned.add("Fall from Favor");
@ -44,13 +46,12 @@ public class Pauper extends Constructed {
banned.add("Gitaxian Probe"); banned.add("Gitaxian Probe");
banned.add("Grapeshot"); banned.add("Grapeshot");
banned.add("Gush"); banned.add("Gush");
banned.add("High Tide");
banned.add("Hymn to Tourach"); banned.add("Hymn to Tourach");
banned.add("Invigorate"); banned.add("Invigorate");
banned.add("Kuldotha Rebirth");
banned.add("Monastery Swiftspear"); banned.add("Monastery Swiftspear");
banned.add("Mystic Sanctuary"); banned.add("Mystic Sanctuary");
banned.add("Peregrine Drake"); banned.add("Peregrine Drake");
banned.add("Prophetic Prism");
banned.add("Sinkhole"); banned.add("Sinkhole");
banned.add("Stirring Bard"); banned.add("Stirring Bard");
banned.add("Sojourner's Companion"); banned.add("Sojourner's Companion");

View file

@ -2072,7 +2072,6 @@ public class HumanPlayer extends PlayerImpl {
// stop skip on any/zero permanents available // stop skip on any/zero permanents available
int possibleBlockersCount = game.getBattlefield().count(filter, playerId, source, game); int possibleBlockersCount = game.getBattlefield().count(filter, playerId, source, game);
boolean canStopOnAny = possibleBlockersCount != 0 && getControllingPlayersUserData(game).getUserSkipPrioritySteps().isStopOnDeclareBlockersWithAnyPermanents(); boolean canStopOnAny = possibleBlockersCount != 0 && getControllingPlayersUserData(game).getUserSkipPrioritySteps().isStopOnDeclareBlockersWithAnyPermanents();
boolean canStopOnZero = possibleBlockersCount == 0 && getControllingPlayersUserData(game).getUserSkipPrioritySteps().isStopOnDeclareBlockersWithZeroPermanents();
// skip declare blocker step // skip declare blocker step
// as opposed to declare attacker - it can be skipped by ANY skip button TODO: make same for declare attackers and rework skip buttons (normal and forced) // as opposed to declare attacker - it can be skipped by ANY skip button TODO: make same for declare attackers and rework skip buttons (normal and forced)
@ -2081,9 +2080,11 @@ public class HumanPlayer extends PlayerImpl {
|| passedTurn || passedTurn
|| passedUntilEndOfTurn || passedUntilEndOfTurn
|| passedUntilNextMain; || passedUntilNextMain;
if (skipButtonActivated && !canStopOnAny && !canStopOnZero) { if (skipButtonActivated && !canStopOnAny) {
return; return;
} }
// Skip prompt to select blockers if player has none
if (possibleBlockersCount == 0) return;
while (canRespond()) { while (canRespond()) {
prepareForResponse(game); prepareForResponse(game);

View file

@ -370,7 +370,7 @@ public final class Main {
// no need to keep session // no need to keep session
logger.info("CLIENT DISCONNECTED - " + sessionInfo); logger.info("CLIENT DISCONNECTED - " + sessionInfo);
logger.debug("- cause: client called disconnect command"); logger.debug("- cause: client called disconnect command");
managerFactory.sessionManager().disconnect(client.getSessionId(), DisconnectReason.DisconnectedByUser, true); managerFactory.sessionManager().disconnect(client.getSessionId(), DisconnectReason.LostConnection, true);
} else if (throwable == null) { } else if (throwable == null) {
// lease timeout (ping), so server lost connection with a client // lease timeout (ping), so server lost connection with a client
// must keep tables // must keep tables

View file

@ -0,0 +1,47 @@
package mage.cards.a;
import java.util.UUID;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ExileCardYouChooseTargetOpponentEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.target.TargetPlayer;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.targetpointer.SecondTargetPointer;
/**
* Aggressive Negotiations implementation
* Author: @mikejcunn
*/
public final class AggressiveNegotiations extends CardImpl {
public AggressiveNegotiations(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}");
// Target opponent reveals their hand. You choose a nonland card from it. That player exiles that card.
Effect effect1 = new ExileCardYouChooseTargetOpponentEffect(StaticFilters.FILTER_CARD_A_NON_LAND);
this.getSpellAbility().addEffect(effect1);
this.getSpellAbility().addTarget(new TargetPlayer());
// Put a +1/+1 counter on target creature you control.
this.getSpellAbility().addEffect(new AddCountersTargetEffect(
CounterType.P1P1.createInstance()
).setTargetPointer(new SecondTargetPointer()));
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, 1));
}
private AggressiveNegotiations(final AggressiveNegotiations card) {
super(card);
}
@Override
public AggressiveNegotiations copy() {
return new AggressiveNegotiations(this);
}
}

View file

@ -90,7 +90,7 @@ class AgrusKosEternalSoldierTriggeredAbility extends TriggeredAbilityImpl {
if (!event.getTargetId().equals(getSourceId())) { if (!event.getTargetId().equals(getSourceId())) {
return false; return false;
} }
StackObject targetingObject = CardUtil.getTargetingStackObject(event, game); StackObject targetingObject = CardUtil.getTargetingStackObject(this.getId().toString(), event, game);
if (targetingObject == null || targetingObject instanceof Spell) { if (targetingObject == null || targetingObject instanceof Spell) {
return false; return false;
} }

View file

@ -144,10 +144,9 @@ class BanditsTalentDiscardEffect extends OneShotEffect {
} }
} }
enum BanditsTalentValue implements DynamicValue { enum BanditsTalentValue implements DynamicValue {
instance; instance;
private static final Hint hint = new ValueHint("opponents who have one or fewer cards in hand", instance); private static final Hint hint = new ValueHint("Opponents who have one or fewer cards in hand", instance);
public static Hint getHint() { public static Hint getHint() {
return hint; return hint;

View file

@ -52,7 +52,7 @@ public final class BrightcapBadger extends AdventureCard {
// Fungus Frolic // Fungus Frolic
// Create two 1/1 green Saproling creature tokens. // Create two 1/1 green Saproling creature tokens.
this.getSpellCard().getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), 2)); this.getSpellCard().getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), 2));
this.getSpellCard().finalizeAdventure(); this.finalizeAdventure();
} }
private BrightcapBadger(final BrightcapBadger card) { private BrightcapBadger(final BrightcapBadger card) {

View file

@ -0,0 +1,72 @@
package mage.cards.c;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.RestrictionEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class ClarionConqueror extends CardImpl {
public ClarionConqueror(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
this.subtype.add(SubType.DRAGON);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Activated abilities of artifacts, creatures, and planeswalkers can't be activated.
this.addAbility(new SimpleStaticAbility(new ClarionConquerorEffect()));
}
private ClarionConqueror(final ClarionConqueror card) {
super(card);
}
@Override
public ClarionConqueror copy() {
return new ClarionConqueror(this);
}
}
class ClarionConquerorEffect extends RestrictionEffect {
ClarionConquerorEffect() {
super(Duration.WhileOnBattlefield);
staticText = "activated abilities of artifacts, creatures, and planeswalkers can't be activated";
}
private ClarionConquerorEffect(final ClarionConquerorEffect effect) {
super(effect);
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
return permanent.isArtifact(game) || permanent.isCreature(game) || permanent.isPlaneswalker(game);
}
@Override
public boolean canUseActivatedAbilities(Permanent permanent, Ability source, Game game, boolean canUseChooseDialogs) {
return false;
}
@Override
public ClarionConquerorEffect copy() {
return new ClarionConquerorEffect(this);
}
}

View file

@ -12,7 +12,7 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.filter.common.FilterNonlandPermanent; import mage.filter.common.FilterNonlandPermanent;
import mage.game.permanent.token.CrushOfTentaclesToken; import mage.game.permanent.token.OctopusToken;
/** /**
* *
@ -25,7 +25,7 @@ public final class CrushOfTentacles extends CardImpl {
// Return all nonland permanents to their owners' hands. If Crush of Tentacles surge cost was paid, create an 8/8 blue Octopus creature token. // Return all nonland permanents to their owners' hands. If Crush of Tentacles surge cost was paid, create an 8/8 blue Octopus creature token.
getSpellAbility().addEffect(new ReturnToHandFromBattlefieldAllEffect(new FilterNonlandPermanent("nonland permanents"))); getSpellAbility().addEffect(new ReturnToHandFromBattlefieldAllEffect(new FilterNonlandPermanent("nonland permanents")));
Effect effect = new ConditionalOneShotEffect(new CreateTokenEffect(new CrushOfTentaclesToken()), SurgedCondition.instance); Effect effect = new ConditionalOneShotEffect(new CreateTokenEffect(new OctopusToken()), SurgedCondition.instance);
effect.setText("If this spell's surge cost was paid, create an 8/8 blue Octopus creature token"); effect.setText("If this spell's surge cost was paid, create an 8/8 blue Octopus creature token");
getSpellAbility().addEffect(effect); getSpellAbility().addEffect(effect);

View file

@ -17,7 +17,7 @@ import mage.constants.SuperType;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.token.SeedGuardianToken; import mage.game.permanent.token.ElementalXXGreenToken;
import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCardInLibrary;
import java.util.UUID; import java.util.UUID;
@ -83,7 +83,7 @@ class DanceOfTheTumbleweedsEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
return new SeedGuardianToken(LandsYouControlCount.instance.calculate(game, source, this)) return new ElementalXXGreenToken(LandsYouControlCount.instance.calculate(game, source, this))
.putOntoBattlefield(1, game, source); .putOntoBattlefield(1, game, source);
} }
} }

View file

@ -54,7 +54,7 @@ enum IsBeingCastFromHandCondition implements Condition {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
MageObject object = game.getObject(source); MageObject object = game.getObject(source);
if (object instanceof SplitCardHalf || object instanceof AdventureCardSpell || object instanceof ModalDoubleFacedCardHalf) { if (object instanceof SplitCardHalf || object instanceof SpellOptionCard || object instanceof ModalDoubleFacedCardHalf) {
UUID mainCardId = ((Card) object).getMainCard().getId(); UUID mainCardId = ((Card) object).getMainCard().getId();
object = game.getObject(mainCardId); object = game.getObject(mainCardId);
} }

View file

@ -0,0 +1,52 @@
package mage.cards.d;
import mage.MageInt;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.TapTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.WardAbility;
import mage.cards.CardSetInfo;
import mage.cards.OmenCard;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author Jmlundeen
*/
public final class DirgurIslandDragon extends OmenCard {
public DirgurIslandDragon(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, new CardType[]{CardType.INSTANT}, "{5}{U}", "Skimming Strike", "{1}{U}");
this.subtype.add(SubType.DRAGON);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Ward {2}
this.addAbility(new WardAbility(new ManaCostsImpl<>("{2}")));
// Skimming Strike
// Tap up to one target creature. Draw a card.
this.getSpellCard().getSpellAbility().addEffect(new TapTargetEffect());
this.getSpellCard().getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1));
this.getSpellCard().getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1));
this.finalizeOmen();
}
private DirgurIslandDragon(final DirgurIslandDragon card) {
super(card);
}
@Override
public DirgurIslandDragon copy() {
return new DirgurIslandDragon(this);
}
}

View file

@ -0,0 +1,73 @@
package mage.cards.d;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.FightTargetsEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetOpponentsCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class DragonclawStrike extends CardImpl {
public DragonclawStrike(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2/U}{2/R}{2/G}");
// Double the power and toughness of target creature you control until end of turn. Then it fights up to one target creature an opponent controls.
this.getSpellAbility().addEffect(new DragonclawStrikeEffect());
this.getSpellAbility().addEffect(new FightTargetsEffect()
.setText("Then it fights up to one target creature an opponent controls"));
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
this.getSpellAbility().addTarget(new TargetOpponentsCreaturePermanent(0, 1));
}
private DragonclawStrike(final DragonclawStrike card) {
super(card);
}
@Override
public DragonclawStrike copy() {
return new DragonclawStrike(this);
}
}
class DragonclawStrikeEffect extends OneShotEffect {
DragonclawStrikeEffect() {
super(Outcome.Benefit);
staticText = "double the power and toughness of target creature you control until end of turn";
}
private DragonclawStrikeEffect(final DragonclawStrikeEffect effect) {
super(effect);
}
@Override
public DragonclawStrikeEffect copy() {
return new DragonclawStrikeEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent == null) {
return false;
}
game.addEffect(new BoostTargetEffect(
permanent.getPower().getValue(),
permanent.getToughness().getValue()
).setTargetPointer(new FixedTarget(permanent, game)), source);
return true;
}
}

View file

@ -0,0 +1,68 @@
package mage.cards.e;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.condition.Condition;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.MenaceAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.counters.CounterType;
import mage.game.Game;
import mage.watchers.common.SpellsCastWatcher;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class EffortlessMaster extends CardImpl {
public EffortlessMaster(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{R}");
this.subtype.add(SubType.ORC);
this.subtype.add(SubType.MONK);
this.power = new MageInt(4);
this.toughness = new MageInt(3);
// Vigilance
this.addAbility(VigilanceAbility.getInstance());
// Menace
this.addAbility(new MenaceAbility());
// This creature enters with two +1/+1 counters on it if you've cast two or more spells this turn.
this.addAbility(new EntersBattlefieldAbility(
new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)),
EffortlessMasterCondition.instance, null,
"with two +1/+1 counters on it if you've cast two or more spells this turn"
));
}
private EffortlessMaster(final EffortlessMaster card) {
super(card);
}
@Override
public EffortlessMaster copy() {
return new EffortlessMaster(this);
}
}
enum EffortlessMasterCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
return game
.getState()
.getWatcher(SpellsCastWatcher.class)
.getSpellsCastThisTurn(source.getControllerId())
.size() >= 2;
}
}

View file

@ -0,0 +1,51 @@
package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.abilities.keyword.TrampleAbility;
import mage.abilities.keyword.ProwessAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.game.permanent.token.MonasteryMentorToken;
/**
*
* @author Grath
*/
public final class ElshaThreefoldMaster extends CardImpl {
public ElshaThreefoldMaster(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}{R}{W}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.DJINN);
this.subtype.add(SubType.MONK);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// Trample
this.addAbility(TrampleAbility.getInstance());
// Prowess
this.addAbility(new ProwessAbility());
// Whenever Elsha deals combat damage to a player, create that many 1/1 white Monk creature tokens with prowess.
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(
new CreateTokenEffect(new MonasteryMentorToken(), SavedDamageValue.MANY), false, true));
}
private ElshaThreefoldMaster(final ElshaThreefoldMaster card) {
super(card);
}
@Override
public ElshaThreefoldMaster copy() {
return new ElshaThreefoldMaster(this);
}
}

View file

@ -0,0 +1,74 @@
package mage.cards.e;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.effects.common.counter.AddCountersAllEffect;
import mage.abilities.effects.common.replacement.CreateTwiceThatManyTokensEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.common.FilterOpponentsCreaturePermanent;
import mage.filter.predicate.mageobject.ManaValuePredicate;
import mage.game.permanent.token.SoldierToken;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class ElspethStormSlayer extends CardImpl {
private static final FilterPermanent filter
= new FilterOpponentsCreaturePermanent("creature an opponent controls with mana value 3 or greater");
static {
filter.add(new ManaValuePredicate(ComparisonType.MORE_THAN, 2));
}
public ElspethStormSlayer(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{3}{W}{W}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.ELSPETH);
this.setStartingLoyalty(5);
// If one or more tokens would be created under your control, twice that many of those tokens are created instead.
this.addAbility(new SimpleStaticAbility(new CreateTwiceThatManyTokensEffect()));
// +1: Create a 1/1 white Soldier creature token.
this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new SoldierToken()), 1));
// 0: Put a +1/+1 counter on each creature you control. Those creatures gain flying until your next turn.
Ability ability = new LoyaltyAbility(new AddCountersAllEffect(
CounterType.P1P1.createInstance(), StaticFilters.FILTER_CONTROLLED_CREATURE
), 0);
ability.addEffect(new GainAbilityControlledEffect(
FlyingAbility.getInstance(), Duration.EndOfTurn,
StaticFilters.FILTER_CONTROLLED_CREATURE
).setText("those creatures gain flying until end of turn"));
this.addAbility(ability);
// -3: Destroy target creature an opponent controls with mana value 3 or greater.
ability = new LoyaltyAbility(new DestroyTargetEffect(), -3);
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
}
private ElspethStormSlayer(final ElspethStormSlayer card) {
super(card);
}
@Override
public ElspethStormSlayer copy() {
return new ElspethStormSlayer(this);
}
}

View file

@ -0,0 +1,156 @@
package mage.cards.e;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.hint.Hint;
import mage.abilities.keyword.TrampleAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.abilities.keyword.WardAbility;
import mage.abilities.triggers.BeginningOfCombatTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.WatcherScope;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.util.CardUtil;
import mage.watchers.Watcher;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class EshkiDragonclaw extends CardImpl {
public EshkiDragonclaw(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{U}{R}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// Vigilance
this.addAbility(VigilanceAbility.getInstance());
// Trample
this.addAbility(TrampleAbility.getInstance());
// Ward {1}
this.addAbility(new WardAbility(new ManaCostsImpl<>("{1}")));
// At the beginning of combat on your turn, if you've cast both a creature spell and a noncreature spell this turn, draw a card and put two +1/+1 counters on Eshki Dragonclaw.
Ability ability = new BeginningOfCombatTriggeredAbility(new DrawCardSourceControllerEffect(1))
.withInterveningIf(EshkiDragonclawCondition.instance);
ability.addEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)).concatBy("and"));
this.addAbility(ability.addHint(EshkiDragonclawHint.instance), new EshkiDragonclawWatcher());
}
private EshkiDragonclaw(final EshkiDragonclaw card) {
super(card);
}
@Override
public EshkiDragonclaw copy() {
return new EshkiDragonclaw(this);
}
}
enum EshkiDragonclawCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
return EshkiDragonclawWatcher.checkPlayer(source.getControllerId(), game) == 3;
}
@Override
public String toString() {
return "you've cast both a creature spell and a noncreature spell this turn";
}
}
enum EshkiDragonclawHint implements Hint {
instance;
@Override
public String getText(Game game, Ability ability) {
switch (EshkiDragonclawWatcher.checkPlayer(ability.getControllerId(), game)) {
case 0:
return null;
case 1:
return "You've cast a creature spell this turn";
case 2:
return "You've cast a noncreature spell this turn";
case 3:
return "You've cast a creature spell and a noncreature spell this turn";
}
return null;
}
@Override
public Hint copy() {
return this;
}
}
class EshkiDragonclawWatcher extends Watcher {
private final Map<UUID, Integer> creatureCount = new HashMap<>();
private final Map<UUID, Integer> nonCreatureCount = new HashMap<>();
EshkiDragonclawWatcher() {
super(WatcherScope.GAME);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() != GameEvent.EventType.SPELL_CAST) {
return;
}
Spell spell = game.getSpell(event.getTargetId());
if (spell == null) {
return;
}
if (spell.isCreature(game)) {
creatureCount.compute(spell.getControllerId(), CardUtil::setOrIncrementValue);
} else {
nonCreatureCount.compute(spell.getControllerId(), CardUtil::setOrIncrementValue);
}
}
@Override
public void reset() {
super.reset();
creatureCount.clear();
nonCreatureCount.clear();
}
private int checkCreature(UUID playerId) {
return creatureCount.getOrDefault(playerId, 0) > 0 ? 1 : 0;
}
private int checkNonCreature(UUID playerId) {
return nonCreatureCount.getOrDefault(playerId, 0) > 0 ? 2 : 0;
}
private int check(UUID playerId) {
return checkCreature(playerId) + checkNonCreature(playerId);
}
static int checkPlayer(UUID playerId, Game game) {
return game.getState().getWatcher(EshkiDragonclawWatcher.class).check(playerId);
}
}

View file

@ -0,0 +1,64 @@
package mage.cards.e;
import mage.abilities.Ability;
import mage.abilities.common.ActivateIfConditionActivatedAbility;
import mage.abilities.condition.Condition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.keyword.SurveilEffect;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.game.Game;
import mage.game.permanent.token.ZombieDruidToken;
import mage.watchers.common.CardsLeftGraveyardWatcher;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class EssenceAnchor extends CardImpl {
public EssenceAnchor(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{U}");
// At the beginning of your upkeep, surveil 1.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SurveilEffect(1)));
// {T}: Create a 2/2 black Zombie Druid creature token. Activate only during your turn and only if a card left your graveyard this turn.
this.addAbility(new ActivateIfConditionActivatedAbility(
new CreateTokenEffect(new ZombieDruidToken()),
new TapSourceCost(), EssenceAnchorCondition.instance
), new CardsLeftGraveyardWatcher());
}
private EssenceAnchor(final EssenceAnchor card) {
super(card);
}
@Override
public EssenceAnchor copy() {
return new EssenceAnchor(this);
}
}
enum EssenceAnchorCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
return game.isActivePlayer(source.getControllerId())
&& !game
.getState()
.getWatcher(CardsLeftGraveyardWatcher.class)
.getCardsThatLeftGraveyard(source.getControllerId(), game)
.isEmpty();
}
@Override
public String toString() {
return "during your turn and only if a card left your graveyard this turn";
}
}

View file

@ -12,7 +12,7 @@ import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.filter.FilterSpell; import mage.filter.FilterSpell;
import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.permanent.token.EyesOfTheWisentElementalToken; import mage.game.permanent.token.Elemental44GreenToken;
import java.util.UUID; import java.util.UUID;
@ -33,7 +33,7 @@ public final class EyesOfTheWisent extends CardImpl {
// Whenever an opponent casts a blue spell during your turn, you may create a 4/4 green Elemental creature token. // Whenever an opponent casts a blue spell during your turn, you may create a 4/4 green Elemental creature token.
this.addAbility(new ConditionalTriggeredAbility( this.addAbility(new ConditionalTriggeredAbility(
new SpellCastOpponentTriggeredAbility(new CreateTokenEffect(new EyesOfTheWisentElementalToken()), filter, true), new SpellCastOpponentTriggeredAbility(new CreateTokenEffect(new Elemental44GreenToken()), filter, true),
MyTurnCondition.instance, MyTurnCondition.instance,
"Whenever an opponent casts a blue spell during your turn, you may create a 4/4 green Elemental creature token." "Whenever an opponent casts a blue spell during your turn, you may create a 4/4 green Elemental creature token."
).addHint(MyTurnHint.instance)); ).addHint(MyTurnHint.instance));

View file

@ -0,0 +1,46 @@
package mage.cards.f;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.delayed.CopyNextSpellDelayedTriggeredAbility;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.filter.StaticFilters;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class FlameholdGrappler extends CardImpl {
public FlameholdGrappler(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}{R}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.MONK);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// First strike
this.addAbility(FirstStrikeAbility.getInstance());
// When this creature enters, copy the next spell you cast this turn when you cast it. You may choose new targets for the copy.
this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateDelayedTriggeredAbilityEffect(
new CopyNextSpellDelayedTriggeredAbility(StaticFilters.FILTER_SPELL)
)));
}
private FlameholdGrappler(final FlameholdGrappler card) {
super(card);
}
@Override
public FlameholdGrappler copy() {
return new FlameholdGrappler(this);
}
}

View file

@ -24,7 +24,7 @@ import mage.filter.StaticFilters;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.game.permanent.token.FleshCarverHorrorToken; import mage.game.permanent.token.HorrorXXBlackToken;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetControlledPermanent;
@ -110,7 +110,7 @@ class FleshCarverEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
if (controller != null) { if (controller != null) {
int xValue = (Integer) getValue("power"); int xValue = (Integer) getValue("power");
return new CreateTokenEffect(new FleshCarverHorrorToken(xValue)).apply(game, source); return new CreateTokenEffect(new HorrorXXBlackToken(xValue)).apply(game, source);
} }
return false; return false;
} }

View file

@ -0,0 +1,86 @@
package mage.cards.f;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.hint.ConditionHint;
import mage.abilities.hint.Hint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.ObjectSourcePlayer;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.filter.predicate.permanent.CounterAnyPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.Optional;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class FormationBreaker extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
private static final FilterPermanent filter2 = new FilterControlledCreaturePermanent();
static {
filter.add(FormationBreakerPredicate.instance);
filter2.add(CounterAnyPredicate.instance);
}
private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter2);
private static final Hint hint = new ConditionHint(condition, "You control a creature with a counter on it");
public FormationBreaker(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
this.subtype.add(SubType.BEAST);
this.power = new MageInt(2);
this.toughness = new MageInt(1);
// Creatures with power less than this creature's power can't block it.
this.addAbility(new SimpleStaticAbility(new CantBeBlockedByCreaturesSourceEffect(filter, Duration.WhileOnBattlefield)
.setText("creatures with power less than this creature's power can't block it")));
// As long as you control a creature with a counter on it, this creature gets +1/+2.
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
new BoostSourceEffect(1, 2, Duration.WhileOnBattlefield),
condition, "as long as you control a creature with a counter on it, this creature gets +1/+2"
)).addHint(hint));
}
private FormationBreaker(final FormationBreaker card) {
super(card);
}
@Override
public FormationBreaker copy() {
return new FormationBreaker(this);
}
}
enum FormationBreakerPredicate implements ObjectSourcePlayerPredicate<Permanent> {
instance;
@Override
public boolean apply(ObjectSourcePlayer<Permanent> input, Game game) {
return Optional
.ofNullable(input.getSource().getSourcePermanentIfItStillExists(game))
.map(MageObject::getPower)
.map(MageInt::getValue)
.map(x -> input.getObject().getPower().getValue() < x)
.orElse(false);
}
}

View file

@ -0,0 +1,41 @@
package mage.cards.f;
import mage.abilities.Mode;
import mage.abilities.dynamicvalue.common.CreaturesYouControlCount;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.game.permanent.token.GoblinToken;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class FrontlineRush extends CardImpl {
public FrontlineRush(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}{W}");
// Choose one --
// * Create two 1/1 red Goblin creature tokens.
this.getSpellAbility().addEffect(new CreateTokenEffect(new GoblinToken(), 2));
// * Target creature gets +X/+X until end of turn, where X is the number of creatures you control.
this.getSpellAbility().addMode(new Mode(new BoostTargetEffect(
CreaturesYouControlCount.instance, CreaturesYouControlCount.instance
)).addTarget(new TargetCreaturePermanent()));
}
private FrontlineRush(final FrontlineRush card) {
super(card);
}
@Override
public FrontlineRush copy() {
return new FrontlineRush(this);
}
}

View file

@ -0,0 +1,74 @@
package mage.cards.f;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.ModeChoiceSourceCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.ChooseModeEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.keyword.HasteAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.filter.StaticFilters;
/**
*
* @author androosss
*/
public final class FrostcliffSiege extends CardImpl {
private static final String rule1Trigger = "&bull; Jeskai &mdash; Whenever one or more creatures you control deal combat damage to a player, draw a card.";
public FrostcliffSiege(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}{R}");
// As this enchantment enters, choose Jeskai or Temur.
this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Jeskai or Temur?", "Jeskai", "Temur"), null,
"As {this} enters, choose Jeskai or Temur.", ""));
// * Jeskai -- Whenever one or more creatures you control deal combat damage to a player, draw a card.
this.addAbility(new ConditionalTriggeredAbility(
new OneOrMoreCombatDamagePlayerTriggeredAbility(new DrawCardSourceControllerEffect(1)),
new ModeChoiceSourceCondition("Jeskai"),
rule1Trigger));
// * Temur -- Creatures you control get +1/+0 and have trample and haste.
Ability temurAbility = new SimpleStaticAbility(new ConditionalContinuousEffect(
new BoostControlledEffect(1, 0, Duration.WhileOnBattlefield),
new ModeChoiceSourceCondition("Temur"),
"&bull; Temur &mdash; Creatures you control get +1/+0"
));
temurAbility.addEffect(new ConditionalContinuousEffect(
new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURES),
new ModeChoiceSourceCondition("Temur"),
"and have trample"
));
temurAbility.addEffect(new ConditionalContinuousEffect(
new GainAbilityControlledEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURES),
new ModeChoiceSourceCondition("Temur"),
"and haste."
));
this.addAbility(temurAbility);
}
private FrostcliffSiege(final FrostcliffSiege card) {
super(card);
}
@Override
public FrostcliffSiege copy() {
return new FrostcliffSiege(this);
}
}

View file

@ -0,0 +1,82 @@
package mage.cards.f;
import java.util.UUID;
import mage.abilities.common.SagaAbility;
import mage.abilities.costs.CompositeCost;
import mage.abilities.costs.common.ExileTargetCost;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
import mage.abilities.effects.keyword.InvestigateEffect;
import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SagaChapter;
import mage.filter.FilterCard;
import mage.filter.common.FilterControlledArtifactPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.game.permanent.token.AlienRhinoToken;
import mage.game.permanent.token.Human11WithWard2Token;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetControlledPermanent;
/**
*
* @author padfoothelix
*/
public final class FugitiveOfTheJudoon extends CardImpl {
private static final FilterCard filter = new FilterCard("a Doctor card");
private static final FilterControlledPermanent filterHuman = new FilterControlledPermanent(SubType.HUMAN,"a Human you control");
private static final FilterControlledArtifactPermanent filterArtifact = new FilterControlledArtifactPermanent("an artifact you control");
static {
filter.add(SubType.DOCTOR.getPredicate());
}
public FugitiveOfTheJudoon(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{G}");
this.subtype.add(SubType.SAGA);
// (As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)
SagaAbility sagaAbility = new SagaAbility(this);
// I -- Create a 1/1 white Human creature token with ward {2} and a 4/4 white Alien Rhino creature token.
sagaAbility.addChapterEffect(
this, SagaChapter.CHAPTER_I,
new CreateTokenEffect(new Human11WithWard2Token()).withAdditionalTokens(new AlienRhinoToken())
);
// II -- Investigate.
sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_II, new InvestigateEffect());
// III -- You may exile a Human you control and an artifact you control. If you do, search your library for a Doctor card, put it onto the battlefield, then shuffle.
sagaAbility.addChapterEffect(
this, SagaChapter.CHAPTER_III,
new DoIfCostPaid(
new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter)),
new CompositeCost(
new ExileTargetCost(new TargetControlledPermanent(1, 1, filterHuman, true)),
new ExileTargetCost(new TargetControlledPermanent(1, 1, filterArtifact, true)),
"exile a Human you control and an artifact you control"
),
"Exile a Human and an artifact ?"
)
);
this.addAbility(sagaAbility);
}
private FugitiveOfTheJudoon(final FugitiveOfTheJudoon card) {
super(card);
}
@Override
public FugitiveOfTheJudoon copy() {
return new FugitiveOfTheJudoon(this);
}
}

View file

@ -1,4 +1,3 @@
package mage.cards.f; package mage.cards.f;
import java.util.UUID; import java.util.UUID;
@ -13,12 +12,10 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterControlledPermanent;
import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreatureCard;
import mage.game.permanent.token.SaprolingToken; import mage.game.permanent.token.SaprolingToken;
import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCardInYourGraveyard;
import mage.target.common.TargetControlledPermanent;
/** /**
* *
@ -40,7 +37,7 @@ public final class FungalPlots extends CardImpl {
SimpleActivatedAbility ability = new SimpleActivatedAbility( SimpleActivatedAbility ability = new SimpleActivatedAbility(
new CreateTokenEffect(new SaprolingToken()), new CreateTokenEffect(new SaprolingToken()),
new ManaCostsImpl<>("{1}{G}")); new ManaCostsImpl<>("{1}{G}"));
ability.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(filter))); ability.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(filter)).withSourceExileZone(false));
this.addAbility(ability); this.addAbility(ability);
// Sacrifice two Saprolings: You gain 2 life and draw a card. // Sacrifice two Saprolings: You gain 2 life and draw a card.

View file

@ -0,0 +1,66 @@
package mage.cards.g;
import java.util.UUID;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.condition.common.ModeChoiceSourceCondition;
import mage.abilities.decorator.ConditionalAsThoughEffect;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.ChooseModeEffect;
import mage.abilities.effects.common.MillCardsTargetEffect;
import mage.abilities.effects.common.ruleModifying.PlayFromGraveyardControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.filter.FilterSpell;
import mage.filter.predicate.Predicates;
import mage.target.TargetPlayer;
/**
*
* @author androosss
*/
public final class GlacierwoodSiege extends CardImpl {
private static final FilterSpell filter = new FilterSpell("an instant or sorcery spell");
static {
filter.add(Predicates.or(
CardType.INSTANT.getPredicate(),
CardType.SORCERY.getPredicate()));
}
public GlacierwoodSiege(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}{U}");
// As this enchantment enters, choose Temur or Sultai.
this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Temur or Sultai?", "Temur", "Sultai"), null,
"As {this} enters, choose Temur or Sultai.", ""));
// * Temur -- Whenever you cast an instant or sorcery spell, target player mills four cards.
TriggeredAbility temurAbility = new SpellCastControllerTriggeredAbility(new MillCardsTargetEffect(4), filter, false);
temurAbility.addTarget(new TargetPlayer());
this.addAbility(new ConditionalTriggeredAbility(
temurAbility,
new ModeChoiceSourceCondition("Temur"),
"&bull; Temur &mdash; Whenever you cast an instant or sorcery spell, target player mills four cards."));
// * Sultai -- You may play lands from your graveyard.
this.addAbility(new SimpleStaticAbility(new ConditionalAsThoughEffect(
PlayFromGraveyardControllerEffect.playLands(),
new ModeChoiceSourceCondition("Sultai")).setText("&bull; Sultai &mdash; You may play lands from your graveyard.")
));
}
private GlacierwoodSiege(final GlacierwoodSiege card) {
super(card);
}
@Override
public GlacierwoodSiege copy() {
return new GlacierwoodSiege(this);
}
}

View file

@ -16,7 +16,7 @@ import mage.counters.CounterType;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.TokenPredicate; import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.permanent.token.GrismoldPlantToken; import mage.game.permanent.token.Plant11Token;
import java.util.UUID; import java.util.UUID;
@ -45,7 +45,7 @@ public final class GrismoldTheDreadsower extends CardImpl {
// At the beginning of your end step, each player creates a 1/1 green Plant creature token. // At the beginning of your end step, each player creates a 1/1 green Plant creature token.
this.addAbility(new BeginningOfEndStepTriggeredAbility( this.addAbility(new BeginningOfEndStepTriggeredAbility(
new CreateTokenAllEffect(new GrismoldPlantToken(), TargetController.EACH_PLAYER) new CreateTokenAllEffect(new Plant11Token(), TargetController.EACH_PLAYER)
)); ));
// Whenever a creature token dies, put a +1/+1 counter on Grismold, the Dreadsower. // Whenever a creature token dies, put a +1/+1 counter on Grismold, the Dreadsower.

View file

@ -9,7 +9,7 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.game.permanent.token.GrovetenderDruidsPlantToken; import mage.game.permanent.token.Plant11Token;
import java.util.UUID; import java.util.UUID;
@ -29,7 +29,7 @@ public final class GrovetenderDruids extends CardImpl {
// <i>Rally</i>-Whenever Grovetender Druids or another Ally you control enters, you may pay {1}. // <i>Rally</i>-Whenever Grovetender Druids or another Ally you control enters, you may pay {1}.
// If you do, create a 1/1 green Plant creature token. // If you do, create a 1/1 green Plant creature token.
this.addAbility(new AllyEntersBattlefieldTriggeredAbility(new DoIfCostPaid( this.addAbility(new AllyEntersBattlefieldTriggeredAbility(new DoIfCostPaid(
new CreateTokenEffect(new GrovetenderDruidsPlantToken()), new GenericManaCost(1) new CreateTokenEffect(new Plant11Token()), new GenericManaCost(1)
), false)); ), false));
} }

View file

@ -0,0 +1,51 @@
package mage.cards.g;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.keyword.MenaceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetOpponentsCreaturePermanent;
import mage.target.targetpointer.SecondTargetPointer;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class GurmagRakshasa extends CardImpl {
public GurmagRakshasa(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}");
this.subtype.add(SubType.DEMON);
this.power = new MageInt(5);
this.toughness = new MageInt(5);
// Menace
this.addAbility(new MenaceAbility());
// When this creature enters, target creature an opponent controls gets -2/-2 until end of turn and target creature you control gets +2/+2 until end of turn.
Ability ability = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(-2, -2));
ability.addTarget(new TargetOpponentsCreaturePermanent());
ability.addEffect(new BoostTargetEffect(2, 2)
.setTargetPointer(new SecondTargetPointer())
.concatBy("and"));
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
}
private GurmagRakshasa(final GurmagRakshasa card) {
super(card);
}
@Override
public GurmagRakshasa copy() {
return new GurmagRakshasa(this);
}
}

View file

@ -0,0 +1,48 @@
package mage.cards.h;
import java.util.UUID;
import mage.MageInt;
import mage.constants.SubType;
import mage.filter.StaticFilters;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.YouCastExactOneSpellThisTurnCondition;
import mage.abilities.decorator.ConditionalCostModificationEffect;
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
/**
*
* @author androosss
*/
public final class HighspireBellRinger extends CardImpl {
public HighspireBellRinger(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.subtype.add(SubType.DJINN);
this.subtype.add(SubType.MONK);
this.power = new MageInt(1);
this.toughness = new MageInt(4);
// Flying
this.addAbility(FlyingAbility.getInstance());
// The second spell you cast each turn costs {1} less to cast.
this.addAbility(new SimpleStaticAbility(new ConditionalCostModificationEffect(
new SpellsCostReductionControllerEffect(StaticFilters.FILTER_CARD, 1),
YouCastExactOneSpellThisTurnCondition.instance, "the second spell you cast each turn costs {1} less to cast"
)));
}
private HighspireBellRinger(final HighspireBellRinger card) {
super(card);
}
@Override
public HighspireBellRinger copy() {
return new HighspireBellRinger(this);
}
}

View file

@ -10,7 +10,7 @@ import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.TargetController; import mage.constants.TargetController;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.token.MinionToken2; import mage.game.permanent.token.MinionToken;
import mage.game.permanent.token.Token; import mage.game.permanent.token.Token;
import mage.players.Player; import mage.players.Player;
@ -42,7 +42,7 @@ public final class InfernalGenesis extends CardImpl {
class InfernalGenesisEffect extends OneShotEffect { class InfernalGenesisEffect extends OneShotEffect {
private static final Token token = new MinionToken2(); private static final Token token = new MinionToken();
InfernalGenesisEffect() { InfernalGenesisEffect() {
super(Outcome.PutCreatureInPlay); super(Outcome.PutCreatureInPlay);

View file

@ -0,0 +1,110 @@
package mage.cards.k;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.Condition;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.HexproofAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.WatcherScope;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.watchers.Watcher;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class KarakykGuardian extends CardImpl {
public KarakykGuardian(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{U}{R}");
this.subtype.add(SubType.DRAGON);
this.power = new MageInt(6);
this.toughness = new MageInt(5);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Vigilance
this.addAbility(VigilanceAbility.getInstance());
// Trample
this.addAbility(TrampleAbility.getInstance());
// This creature has hexproof if it hasn't dealt damage yet.
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
new GainAbilitySourceEffect(HexproofAbility.getInstance()),
KarakykGuardianCondition.instance, "{this} has hexproof if it hasn't dealt damage yet"
)), new KarakykGuardianWatcher());
}
private KarakykGuardian(final KarakykGuardian card) {
super(card);
}
@Override
public KarakykGuardian copy() {
return new KarakykGuardian(this);
}
}
enum KarakykGuardianCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
KarakykGuardianWatcher watcher = game.getState().getWatcher(KarakykGuardianWatcher.class);
return permanent != null && !watcher.getDamagers().contains(new MageObjectReference(permanent, game));
}
@Override
public String toString() {
return "{this} hasn't dealt damage yet";
}
}
class KarakykGuardianWatcher extends Watcher {
private final Set<MageObjectReference> damagers = new HashSet<>();
public KarakykGuardianWatcher() {
super(WatcherScope.GAME);
}
@Override
public void watch(GameEvent event, Game game) {
switch (event.getType()) {
case DAMAGED_PERMANENT:
case DAMAGED_PLAYER:
break;
default:
return;
}
Permanent permanent = game.getPermanent(event.getSourceId());
if (permanent != null) {
damagers.add(new MageObjectReference(permanent, game));
}
}
public Set<MageObjectReference> getDamagers() {
return damagers;
}
}

View file

@ -0,0 +1,67 @@
package mage.cards.l;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.costs.common.ExileSourceFromGraveCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
import mage.abilities.dynamicvalue.common.LandsYouControlCount;
import mage.abilities.effects.common.MillCardsControllerEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AbilityWord;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class LasydProwler extends CardImpl {
private static final DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_LAND, null);
private static final Hint hint = new ValueHint("Land cards in your graveyard", xValue);
public LasydProwler(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}");
this.subtype.add(SubType.SNAKE);
this.subtype.add(SubType.RANGER);
this.power = new MageInt(5);
this.toughness = new MageInt(5);
// When this creature enters, you may mill cards equal to the number of lands you control.
this.addAbility(new EntersBattlefieldTriggeredAbility(new MillCardsControllerEffect(LandsYouControlCount.instance)
.setText("mill cards equal to the number of lands you control"), true));
// Renew -- {1}{G}, Exile this card from your graveyard: Put X +1/+1 counters on target creature, where X is the number of land cards in your graveyard. Activate only as a sorcery.
Ability ability = new ActivateAsSorceryActivatedAbility(
Zone.GRAVEYARD,
new AddCountersTargetEffect(CounterType.P1P1.createInstance(0), xValue),
new ManaCostsImpl<>("{1}{G}")
);
ability.addCost(new ExileSourceFromGraveCost());
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability.setAbilityWord(AbilityWord.RENEW).addHint(hint));
}
private LasydProwler(final LasydProwler card) {
super(card);
}
@Override
public LasydProwler copy() {
return new LasydProwler(this);
}
}

View file

@ -0,0 +1,103 @@
package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.common.FilterHistoricCard;
import mage.game.Game;
import mage.game.events.DamagedBatchForOnePlayerEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCardInYourGraveyard;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.OneOrMoreDamagePlayerTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
/**
* @author balazskristof
*/
public final class LaylaHassan extends CardImpl {
private static final FilterHistoricCard filter = new FilterHistoricCard("historic card from your graveyard");
public LaylaHassan(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.ASSASSIN);
this.power = new MageInt(3);
this.toughness = new MageInt(4);
// First strike
this.addAbility(FirstStrikeAbility.getInstance());
// When Layla Hassan enters the battlefield and whenever one or more Assassins you control deal combat damage to a player, return target historic card from your graveyard to your hand.
Ability ability = new LaylaHassanTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect());
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability);
}
private LaylaHassan(final LaylaHassan card) {
super(card);
}
@Override
public LaylaHassan copy() {
return new LaylaHassan(this);
}
}
class LaylaHassanTriggeredAbility extends OneOrMoreDamagePlayerTriggeredAbility {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Assassins");
static {
filter.add(SubType.ASSASSIN.getPredicate());
}
public LaylaHassanTriggeredAbility(Effect effect) {
super(effect, filter, true, true);
}
private LaylaHassanTriggeredAbility(final LaylaHassanTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD
|| event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD
&& event.getTargetId().equals(getSourceId())) {
return true;
}
if (event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PLAYER) {
return super.checkTrigger(event, game);
}
return false;
}
@Override
public String getRule() {
return "When {this} enters the battlefield and whenever one or more Assassins you control deal combat damage to a player, return target historic card from your graveyard to your hand.";
}
@Override
public LaylaHassanTriggeredAbility copy() {
return new LaylaHassanTriggeredAbility(this);
}
}

View file

@ -0,0 +1,86 @@
package mage.cards.l;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetCardInYourGraveyard;
import mage.target.targetpointer.EachTargetPointer;
/**
*
* @author androosss
*/
public final class LieInWait extends CardImpl {
public LieInWait(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{B}{G}{U}");
// Return target creature card from your graveyard to your hand. Lie in Wait deals damage equal to that card's power to target creature.
this.getSpellAbility().addEffect(new LieInWaitTargetEffect());
this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE));
this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_CREATURE));
}
private LieInWait(final LieInWait card) {
super(card);
}
@Override
public LieInWait copy() {
return new LieInWait(this);
}
}
class LieInWaitTargetEffect extends OneShotEffect {
LieInWaitTargetEffect() {
super(Outcome.Benefit);
staticText = "Return target creature card from your graveyard to your hand. "
+ "{this} deals damage equal to that card's power to target creature";
setTargetPointer(new EachTargetPointer());
}
private LieInWaitTargetEffect(final LieInWaitTargetEffect effect) {
super(effect);
}
@Override
public LieInWaitTargetEffect copy() {
return new LieInWaitTargetEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
List<UUID> targets = getTargetPointer().getTargets(game, source);
Card card = game.getCard(targets.get(0));
if (card == null) {
return false;
}
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
boolean result = card.moveToZone(Zone.HAND, source, game,false);
if (result && targets.size() >= 2) {
int power = card.getPower().getValue();
Permanent permanent = game.getPermanent(targets.get(1));
permanent.damage(power, source, game);
}
return result;
}
}

View file

@ -0,0 +1,135 @@
package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
import mage.abilities.Ability;
import mage.abilities.assignment.common.ColorAssignment;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.LifelinkAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
/**
*
* @author androosss
*/
public final class LotuslightDancers extends CardImpl {
public LotuslightDancers(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{G}{U}");
this.subtype.add(SubType.ZOMBIE);
this.subtype.add(SubType.BARD);
this.power = new MageInt(3);
this.toughness = new MageInt(6);
// Lifelink
this.addAbility(LifelinkAbility.getInstance());
// When this creature enters, search your library for a black card, a green card, and a blue card. Put those cards into your graveyard, then shuffle.
this.addAbility(new EntersBattlefieldTriggeredAbility(new LotuslightDancersEffect()));
}
private LotuslightDancers(final LotuslightDancers card) {
super(card);
}
@Override
public LotuslightDancers copy() {
return new LotuslightDancers(this);
}
}
class LotuslightDancersEffect extends OneShotEffect {
LotuslightDancersEffect() {
super(Outcome.Neutral);
staticText = "search your library for a black card, a green card, and a blue card. " +
"Put those cards into your graveyard, then shuffle.";
}
private LotuslightDancersEffect(final LotuslightDancersEffect effect) {
super(effect);
}
@Override
public LotuslightDancersEffect copy() {
return new LotuslightDancersEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
TargetCardInLibrary target = new LotuslightDancersTarget();
controller.searchLibrary(target, source, game);
Cards cards = new CardsImpl(target.getTargets());
cards.retainZone(Zone.LIBRARY, game);
controller.moveCards(cards, Zone.GRAVEYARD, source, game);
controller.shuffleLibrary(source, game);
return true;
}
}
class LotuslightDancersTarget extends TargetCardInLibrary {
private static final FilterCard filter
= new FilterCard("a black card, a green card, and a blue card");
static {
filter.add(Predicates.or(
new ColorPredicate(ObjectColor.BLUE),
new ColorPredicate(ObjectColor.BLACK),
new ColorPredicate(ObjectColor.GREEN)
));
}
private static final ColorAssignment colorAssigner = new ColorAssignment("U", "B", "G");
LotuslightDancersTarget() {
super(0, 3, filter);
}
private LotuslightDancersTarget(final LotuslightDancersTarget target) {
super(target);
}
@Override
public LotuslightDancersTarget copy() {
return new LotuslightDancersTarget(this);
}
@Override
public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) {
if (!super.canTarget(playerId, id, source, game)) {
return false;
}
Card card = game.getCard(id);
if (card == null) {
return false;
}
if (this.getTargets().isEmpty()) {
return true;
}
Cards cards = new CardsImpl(this.getTargets());
cards.add(card);
return colorAssigner.getRoleCount(cards, game) >= cards.size();
}
}

View file

@ -15,6 +15,7 @@ import mage.abilities.dynamicvalue.common.ManaSpentToCastCount;
import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.dynamicvalue.common.GetXValue;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect;
@ -27,11 +28,10 @@ import mage.constants.SuperType;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.game.permanent.token.MarathWillOfTheWildElementalToken;
import mage.game.permanent.token.Token;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetAnyTarget; import mage.target.common.TargetAnyTarget;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import mage.game.permanent.token.ElementalXXGreenToken;
import java.util.UUID; import java.util.UUID;
@ -110,12 +110,8 @@ class MarathWillOfTheWildCreateTokenEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId()); Player player = game.getPlayer(source.getControllerId());
if (player != null) { if (player != null) {
int amount = GetXValue.instance.calculate(game, source, this); int xvalue = GetXValue.instance.calculate(game, source, this);
Token token = new MarathWillOfTheWildElementalToken(); return new CreateTokenEffect(new ElementalXXGreenToken(xvalue)).apply(game, source);
token.setPower(amount);
token.setToughness(amount);
token.putOntoBattlefield(1, game, source, source.getControllerId());
return true;
} }
return false; return false;
} }

View file

@ -0,0 +1,136 @@
package mage.cards.m;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileUntilSourceLeavesEffect;
import mage.abilities.effects.common.SacrificeTargetEffect;
import mage.abilities.keyword.DeathtouchAbility;
import mage.abilities.keyword.HasteAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.GameState;
import mage.game.permanent.token.Token;
import mage.target.TargetCard;
import mage.target.TargetPermanent;
import mage.target.common.TargetCardInExile;
import mage.target.targetpointer.FixedTargets;
import mage.util.CardUtil;
import mage.util.functions.CopyTokenFunction;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class MarduSiegebreaker extends CardImpl {
public MarduSiegebreaker(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{W}{B}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// Deathtouch
this.addAbility(DeathtouchAbility.getInstance());
// Haste
this.addAbility(HasteAbility.getInstance());
// When this creature enters, exile up to one other target creature you control until this creature leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_OTHER_CONTROLLED_CREATURE));
this.addAbility(ability);
// Whenever this creature attacks, for each opponent, create a tapped token that's a copy of the exiled card attacking that opponent. At the beginning of your end step, sacrifice those tokens.
this.addAbility(new AttacksTriggeredAbility(new MarduSiegebreakerEffect()));
}
private MarduSiegebreaker(final MarduSiegebreaker card) {
super(card);
}
@Override
public MarduSiegebreaker copy() {
return new MarduSiegebreaker(this);
}
}
class MarduSiegebreakerEffect extends OneShotEffect {
MarduSiegebreakerEffect() {
super(Outcome.Benefit);
staticText = "for each opponent, create a tapped token that's a copy of the exiled card " +
"attacking that opponent. At the beginning of your end step, sacrifice those tokens";
}
private MarduSiegebreakerEffect(final MarduSiegebreakerEffect effect) {
super(effect);
}
@Override
public MarduSiegebreakerEffect copy() {
return new MarduSiegebreakerEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Cards cards = Optional
.ofNullable(game)
.map(Game::getState)
.map(GameState::getExile)
.map(exile -> exile.getExileZone(CardUtil.getExileZoneId(game, source)))
.orElse(null);
if (cards == null) {
return false;
}
Card card;
switch (cards.size()) {
case 0:
return false;
case 1:
card = cards.getRandom(game);
break;
default:
card = Optional.ofNullable(game.getPlayer(source.getControllerId())).map(player -> {
TargetCard target = new TargetCardInExile(StaticFilters.FILTER_CARD);
target.withNotTarget(true);
target.withChooseHint("to copy");
player.choose(Outcome.Neutral, cards, target, source, game);
return game.getCard(target.getFirstTarget());
}).orElse(null);
}
if (card == null) {
return false;
}
Set<MageObjectReference> addedTokens = new HashSet<>();
Token token = CopyTokenFunction.createTokenCopy(card, game);
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
token.putOntoBattlefield(1, game, source, source.getControllerId(), true, true, opponentId);
token.getLastAddedTokenIds()
.stream()
.map(uuid -> new MageObjectReference(uuid, game))
.forEach(addedTokens::add);
}
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(
new SacrificeTargetEffect().setTargetPointer(new FixedTargets(addedTokens))
), source);
return true;
}
}

View file

@ -0,0 +1,102 @@
package mage.cards.n;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.costs.common.ExileSourceFromGraveCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CopyPermanentEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class NagaFleshcrafter extends CardImpl {
private static final FilterPermanent filter = new FilterControlledCreaturePermanent("nonlegendary creature you control");
static {
filter.add(Predicates.not(SuperType.LEGENDARY.getPredicate()));
}
public NagaFleshcrafter(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");
this.subtype.add(SubType.SNAKE);
this.subtype.add(SubType.SHAPESHIFTER);
this.power = new MageInt(0);
this.toughness = new MageInt(0);
// You may have this creature enter as a copy of any creature on the battlefield.
this.addAbility(new EntersBattlefieldAbility(new CopyPermanentEffect(), true));
// Renew -- {2}{U}, Exile this card from your graveyard: Put a +1/+1 counter on target nonlegendary creature you control. Each other creature you control becomes a copy of that creature until end of turn. Activate only as a sorcery.
Ability ability = new ActivateAsSorceryActivatedAbility(
Zone.GRAVEYARD,
new AddCountersTargetEffect(CounterType.P1P1.createInstance()),
new ManaCostsImpl<>("{2}{U}")
);
ability.addCost(new ExileSourceFromGraveCost());
ability.addEffect(new NagaFleshcrafterEffect());
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability.setAbilityWord(AbilityWord.RENEW));
}
private NagaFleshcrafter(final NagaFleshcrafter card) {
super(card);
}
@Override
public NagaFleshcrafter copy() {
return new NagaFleshcrafter(this);
}
}
class NagaFleshcrafterEffect extends OneShotEffect {
NagaFleshcrafterEffect() {
super(Outcome.Benefit);
staticText = "each other creature you control becomes a copy of that creature until end of turn";
}
private NagaFleshcrafterEffect(final NagaFleshcrafterEffect effect) {
super(effect);
}
@Override
public NagaFleshcrafterEffect copy() {
return new NagaFleshcrafterEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent == null) {
return false;
}
for (Permanent creature : game.getBattlefield().getActivePermanents(
StaticFilters.FILTER_CONTROLLED_CREATURE,
source.getControllerId(), source, game
)) {
if (!permanent.getId().equals(creature.getId())) {
game.copyPermanent(Duration.EndOfTurn, permanent, creature.getId(), source, null);
}
}
return true;
}
}

View file

@ -96,7 +96,7 @@ class PawpatchRecruitTriggeredAbility extends TriggeredAbilityImpl {
if (permanent == null || !filterTarget.match(permanent, getControllerId(), this, game)) { if (permanent == null || !filterTarget.match(permanent, getControllerId(), this, game)) {
return false; return false;
} }
StackObject targetingObject = CardUtil.getTargetingStackObject(event, game); StackObject targetingObject = CardUtil.getTargetingStackObject(this.getId().toString(), event, game);
if (targetingObject == null || !filterStack.match(targetingObject, getControllerId(), this, game)) { if (targetingObject == null || !filterStack.match(targetingObject, getControllerId(), this, game)) {
return false; return false;
} }

View file

@ -8,6 +8,7 @@ import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -15,7 +16,7 @@ import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.game.permanent.token.MinionToken; import mage.game.permanent.token.PhyrexianMinionToken;
import mage.players.Player; import mage.players.Player;
import mage.util.CardUtil; import mage.util.CardUtil;
@ -110,12 +111,8 @@ class PhyrexianProcessorCreateTokenEffect extends OneShotEffect {
String key = CardUtil.getCardZoneString("lifePaid", source.getSourceId(), game, true); String key = CardUtil.getCardZoneString("lifePaid", source.getSourceId(), game, true);
Object object = game.getState().getValue(key); Object object = game.getState().getValue(key);
if (object instanceof Integer) { if (object instanceof Integer) {
int lifePaid = (int) object; int xvalue = (int) object;
MinionToken token = new MinionToken(); return new CreateTokenEffect(new PhyrexianMinionToken(xvalue)).apply(game, source);
token.setPower(lifePaid);
token.setToughness(lifePaid);
token.putOntoBattlefield(1, game, source, source.getControllerId());
return true;
} }
return false; return false;
} }

View file

@ -4,7 +4,6 @@ import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.triggers.BeginningOfCombatTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.CelebrationCondition; import mage.abilities.condition.common.CelebrationCondition;
import mage.abilities.decorator.ConditionalCostModificationEffect; import mage.abilities.decorator.ConditionalCostModificationEffect;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
@ -14,10 +13,9 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.*; import mage.constants.*;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.game.Game;
import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetControlledCreaturePermanent;
import mage.watchers.common.PermanentsEnteredBattlefieldWatcher; import mage.watchers.common.PermanentsEnteredBattlefieldWatcher;
import mage.watchers.common.SpellsCastWatcher; import mage.abilities.condition.common.YouCastExactOneSpellThisTurnCondition;
import java.util.UUID; import java.util.UUID;
@ -63,13 +61,3 @@ public final class RagingBattleMouse extends CardImpl {
return new RagingBattleMouse(this); return new RagingBattleMouse(this);
} }
} }
enum YouCastExactOneSpellThisTurnCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class);
return watcher != null && watcher.getSpellsCastThisTurn(source.getControllerId()).size() == 1;
}
}

View file

@ -0,0 +1,46 @@
package mage.cards.r;
import mage.MageInt;
import mage.Mana;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.dynamicvalue.common.SourcePermanentPowerValue;
import mage.abilities.effects.common.MillCardsControllerEffect;
import mage.abilities.mana.DynamicManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class RainveilRejuvenator extends CardImpl {
public RainveilRejuvenator(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}");
this.subtype.add(SubType.ELEPHANT);
this.subtype.add(SubType.DRUID);
this.power = new MageInt(2);
this.toughness = new MageInt(4);
// When this creature enters, you may mill three cards.
this.addAbility(new EntersBattlefieldTriggeredAbility(new MillCardsControllerEffect(3), true));
// {T}: Add an amount of {G} equal to this creature's power.
this.addAbility(new DynamicManaAbility(
Mana.GreenMana(1), SourcePermanentPowerValue.NOT_NEGATIVE, "Add an amount of {G} equal to {this}'s power."
));
}
private RainveilRejuvenator(final RainveilRejuvenator card) {
super(card);
}
@Override
public RainveilRejuvenator copy() {
return new RainveilRejuvenator(this);
}
}

View file

@ -12,7 +12,7 @@ import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.token.RallyTheHordeWarriorToken; import mage.game.permanent.token.RedWarriorToken;
import mage.players.Player; import mage.players.Player;
/** /**
@ -72,7 +72,7 @@ class RallyTheHordeEffect extends OneShotEffect {
nonLandCardsExiled += nonLands; nonLandCardsExiled += nonLands;
} }
} }
return new CreateTokenEffect(new RallyTheHordeWarriorToken(), nonLandCardsExiled).apply(game, source); return new CreateTokenEffect(new RedWarriorToken(), nonLandCardsExiled).apply(game, source);
} }
return false; return false;

View file

@ -0,0 +1,86 @@
package mage.cards.r;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.SagaAbility;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.DoubleStrikeAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class RediscoverTheWay extends CardImpl {
public RediscoverTheWay(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}{R}{W}");
this.subtype.add(SubType.SAGA);
// (As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)
SagaAbility sagaAbility = new SagaAbility(this);
// I, II -- Look at the top three cards of your library. Put one of them into your hand and the rest on the bottom of your library in any order.
sagaAbility.addChapterEffect(
this, SagaChapter.CHAPTER_I, SagaChapter.CHAPTER_II,
new LookLibraryAndPickControllerEffect(3, 1, PutCards.HAND, PutCards.BOTTOM_ANY)
);
// III -- Whenever you cast a noncreature spell this turn, target creature you control gains double strike until end of turn.
sagaAbility.addChapterEffect(
this, SagaChapter.CHAPTER_III,
new CreateDelayedTriggeredAbilityEffect(new RediscoverTheWayTriggeredAbility())
);
this.addAbility(sagaAbility);
}
private RediscoverTheWay(final RediscoverTheWay card) {
super(card);
}
@Override
public RediscoverTheWay copy() {
return new RediscoverTheWay(this);
}
}
class RediscoverTheWayTriggeredAbility extends DelayedTriggeredAbility {
RediscoverTheWayTriggeredAbility() {
super(new GainAbilityTargetEffect(DoubleStrikeAbility.getInstance()), Duration.EndOfTurn, false, false);
this.addTarget(new TargetControlledCreaturePermanent());
this.setTriggerPhrase("Whenever you cast a noncreature spell this turn, ");
}
private RediscoverTheWayTriggeredAbility(final RediscoverTheWayTriggeredAbility ability) {
super(ability);
}
@Override
public RediscoverTheWayTriggeredAbility copy() {
return new RediscoverTheWayTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SPELL_CAST;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!isControlledBy(event.getPlayerId())) {
return false;
}
Spell spell = game.getSpell(event.getTargetId());
return spell != null && !spell.isCreature(game);
}
}

View file

@ -0,0 +1,100 @@
package mage.cards.r;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.TapTargetEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInExile;
import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class RiverwheelSweep extends CardImpl {
public RiverwheelSweep(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2/U}{2/R}{2/W}");
// Tap target creature. Put three stun counters on it.
this.getSpellAbility().addEffect(new TapTargetEffect());
this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.STUN.createInstance(3))
.setText("put three stun counters on it"));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
// Exile the top two cards of your library. Choose one of them. Until the end of your next turn, you may play that card.
this.getSpellAbility().addEffect(new RiverwheelSweepEffect());
}
private RiverwheelSweep(final RiverwheelSweep card) {
super(card);
}
@Override
public RiverwheelSweep copy() {
return new RiverwheelSweep(this);
}
}
class RiverwheelSweepEffect extends OneShotEffect {
RiverwheelSweepEffect() {
super(Outcome.Benefit);
staticText = "Exile the top two cards of your library. Choose one of them. " +
"Until the end of your next turn, you may play that card";
this.concatBy("<br>");
}
private RiverwheelSweepEffect(final RiverwheelSweepEffect effect) {
super(effect);
}
@Override
public RiverwheelSweepEffect copy() {
return new RiverwheelSweepEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 2));
player.moveCards(cards, Zone.EXILED, source, game);
cards.retainZone(Zone.EXILED, game);
Card card;
switch (cards.size()) {
case 0:
return false;
case 1:
card = cards.getRandom(game);
break;
default:
TargetCard target = new TargetCardInExile(StaticFilters.FILTER_CARD);
target.withNotTarget(true);
player.choose(Outcome.DrawCard, cards, target, source, game);
card = game.getCard(target.getFirstTarget());
}
if (card == null) {
return false;
}
CardUtil.makeCardPlayable(
game, source, card, false,
Duration.UntilEndOfYourNextTurn, false
);
return true;
}
}

View file

@ -0,0 +1,73 @@
package mage.cards.s;
import mage.abilities.Ability;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.SacrificeTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.token.RedWarriorToken;
import mage.game.permanent.token.Token;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTargets;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class SaltRoadSkirmish extends CardImpl {
public SaltRoadSkirmish(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}");
// Destroy target creature. Create two 1/1 red Warrior creature tokens. They gain haste until end of turn. Sacrifice them at the beginning of the next end step.
this.getSpellAbility().addEffect(new DestroyTargetEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addEffect(new SaltRoadSkirmishEffect());
}
private SaltRoadSkirmish(final SaltRoadSkirmish card) {
super(card);
}
@Override
public SaltRoadSkirmish copy() {
return new SaltRoadSkirmish(this);
}
}
class SaltRoadSkirmishEffect extends OneShotEffect {
SaltRoadSkirmishEffect() {
super(Outcome.Benefit);
staticText = "";
}
private SaltRoadSkirmishEffect(final SaltRoadSkirmishEffect effect) {
super(effect);
}
@Override
public SaltRoadSkirmishEffect copy() {
return new SaltRoadSkirmishEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Token token = new RedWarriorToken();
token.putOntoBattlefield(2, game, source);
game.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance())
.setTargetPointer(new FixedTargets(token, game)), source);
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(
new SacrificeTargetEffect("sacrifice them").setTargetPointer(new FixedTargets(token, game))
), source);
return true;
}
}

View file

@ -14,7 +14,7 @@ import mage.constants.Outcome;
import mage.constants.SubType; import mage.constants.SubType;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.token.SeedGuardianToken; import mage.game.permanent.token.ElementalXXGreenToken;
import mage.players.Player; import mage.players.Player;
/** /**
@ -66,7 +66,7 @@ class SeedGuardianEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
if (controller != null) { if (controller != null) {
int creaturesInGraveyard = controller.getGraveyard().count(StaticFilters.FILTER_CARD_CREATURE, game); int creaturesInGraveyard = controller.getGraveyard().count(StaticFilters.FILTER_CARD_CREATURE, game);
return new CreateTokenEffect(new SeedGuardianToken(creaturesInGraveyard)).apply(game, source); return new CreateTokenEffect(new ElementalXXGreenToken(creaturesInGraveyard)).apply(game, source);
} }
return false; return false;
} }

View file

@ -0,0 +1,106 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.VariableCostImpl;
import mage.abilities.costs.VariableCostType;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.dynamicvalue.AdditiveDynamicValue;
import mage.abilities.dynamicvalue.common.GetXValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.constants.*;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.filter.predicate.mageobject.ManaValuePredicate;
import mage.game.Game;
import mage.target.common.TargetCardInYourGraveyard;
import mage.target.targetadjustment.ManaValueTargetAdjuster;
/**
*
* @author Grath
*/
public final class SidisiRegentOfTheMire extends CardImpl {
public SidisiRegentOfTheMire(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.ZOMBIE);
this.subtype.add(SubType.SNAKE);
this.subtype.add(SubType.WARLOCK);
this.power = new MageInt(1);
this.toughness = new MageInt(3);
// {T}, Sacrifice a creature you control with mana value X other than Sidisi: Return target creature card with mana value X plus 1 from your graveyard to the battlefield. Activate only as a sorcery.
Ability ability = new ActivateAsSorceryActivatedAbility(
Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect(), new TapSourceCost()
);
ability.addCost(new SidisiRegentOfTheMireCost());
ability.addTarget(new TargetCardInYourGraveyard(new FilterCreatureCard("creature card with mana value X plus 1 from your graveyard")));
ability.setTargetAdjuster(new SidisiRegentOfTheMireAdjuster());
this.addAbility(ability);
}
private SidisiRegentOfTheMire(final SidisiRegentOfTheMire card) {
super(card);
}
@Override
public SidisiRegentOfTheMire copy() {
return new SidisiRegentOfTheMire(this);
}
}
class SidisiRegentOfTheMireAdjuster extends ManaValueTargetAdjuster {
public SidisiRegentOfTheMireAdjuster() {
super(new AdditiveDynamicValue(GetXValue.instance, StaticValue.get(1)), ComparisonType.EQUAL_TO);
}
}
class SidisiRegentOfTheMireCost extends VariableCostImpl {
public SidisiRegentOfTheMireCost() {
super(VariableCostType.NORMAL, "mana value X");
this.text = "Sacrifice a creature with mana value X";
}
protected SidisiRegentOfTheMireCost(final SidisiRegentOfTheMireCost cost) {
super(cost);
}
@Override
public SidisiRegentOfTheMireCost copy() {
return new SidisiRegentOfTheMireCost(this);
}
@Override
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
FilterPermanent filter = new FilterControlledCreaturePermanent("another creature with mana value X");
filter.add(AnotherPredicate.instance);
filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, xValue));
return new SacrificeTargetCost(filter);
}
@Override
public int getMaxValue(Ability source, Game game) {
return game.getBattlefield().getActivePermanents(
StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE,
source.getControllerId(), source, game
).stream().mapToInt(MageObject::getManaValue).max().orElse(0);
}
}

View file

@ -17,7 +17,7 @@ import mage.constants.Duration;
import mage.constants.SuperType; import mage.constants.SuperType;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.game.command.emblems.SorinSolemnVisitorEmblem; import mage.game.command.emblems.SorinSolemnVisitorEmblem;
import mage.game.permanent.token.SorinSolemnVisitorVampireToken; import mage.game.permanent.token.VampireToken;
/** /**
* *
@ -42,7 +42,7 @@ public final class SorinSolemnVisitor extends CardImpl {
this.addAbility(loyaltyAbility); this.addAbility(loyaltyAbility);
// -2: Create a 2/2 black Vampire creature token with flying. // -2: Create a 2/2 black Vampire creature token with flying.
this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new SorinSolemnVisitorVampireToken()), -2)); this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new VampireToken()), -2));
// -6: You get an emblem with "At the beginning of each opponent's upkeep, that player sacrifices a creature." // -6: You get an emblem with "At the beginning of each opponent's upkeep, that player sacrifices a creature."
this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new SorinSolemnVisitorEmblem()), -6)); this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new SorinSolemnVisitorEmblem()), -6));

View file

@ -12,7 +12,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.token.SpoilsOfBloodHorrorToken; import mage.game.permanent.token.HorrorXXBlackToken;
import mage.players.Player; import mage.players.Player;
/** /**
@ -54,7 +54,7 @@ class SpoilsOfBloodEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
if (controller != null) { if (controller != null) {
new CreateTokenEffect( new CreateTokenEffect(
new SpoilsOfBloodHorrorToken(CreaturesDiedThisTurnCount.instance.calculate(game, source, this))) new HorrorXXBlackToken(CreaturesDiedThisTurnCount.instance.calculate(game, source, this)))
.apply(game, source); .apply(game, source);
return true; return true;
} }

View file

@ -0,0 +1,65 @@
package mage.cards.s;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.predicate.permanent.AttackingPredicate;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class StarryEyedSkyrider extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("attacking tokens");
static {
filter.add(AttackingPredicate.instance);
filter.add(TokenPredicate.TRUE);
}
public StarryEyedSkyrider(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.SCOUT);
this.power = new MageInt(1);
this.toughness = new MageInt(3);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Whenever this creature attacks, another target creature you control gains flying until end of turn.
Ability ability = new AttacksTriggeredAbility(new GainAbilityTargetEffect(FlyingAbility.getInstance()));
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL));
this.addAbility(ability);
// Attacking tokens you control have flying.
this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect(
FlyingAbility.getInstance(), Duration.WhileOnBattlefield, filter
)));
}
private StarryEyedSkyrider(final StarryEyedSkyrider card) {
super(card);
}
@Override
public StarryEyedSkyrider copy() {
return new StarryEyedSkyrider(this);
}
}

View file

@ -0,0 +1,80 @@
package mage.cards.s;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.MillCardsControllerEffect;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInYourGraveyard;
import java.util.Optional;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class StillnessInMotion extends CardImpl {
public StillnessInMotion(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}");
// At the beginning of your upkeep, mill three cards. Then if you have no cards in your library, exile this enchantment and put five cards from your graveyard on top of your library in any order.
Ability ability = new BeginningOfUpkeepTriggeredAbility(new MillCardsControllerEffect(3));
ability.addEffect(new StillnessInMotionEffect());
this.addAbility(ability);
}
private StillnessInMotion(final StillnessInMotion card) {
super(card);
}
@Override
public StillnessInMotion copy() {
return new StillnessInMotion(this);
}
}
class StillnessInMotionEffect extends OneShotEffect {
StillnessInMotionEffect() {
super(Outcome.Benefit);
staticText = "Then if you have no cards in your library, exile this enchantment " +
"and put five cards from your graveyard on top of your library in any order";
}
private StillnessInMotionEffect(final StillnessInMotionEffect effect) {
super(effect);
}
@Override
public StillnessInMotionEffect copy() {
return new StillnessInMotionEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null || player.getLibrary().hasCards()) {
return false;
}
Optional.ofNullable(source.getSourcePermanentIfItStillExists(game))
.ifPresent(permanent -> player.moveCards(permanent, Zone.EXILED, source, game));
int graveCount = Math.min(player.getGraveyard().size(), 5);
if (graveCount < 1) {
return true;
}
TargetCard target = new TargetCardInYourGraveyard(graveCount);
target.withNotTarget(true);
player.choose(outcome, target, source, game);
player.putCardsOnTopOfLibrary(new CardsImpl(target.getTargets()), game, source, true);
return true;
}
}

View file

@ -0,0 +1,95 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetControlledPermanent;
import mage.target.common.TargetOpponent;
import mage.target.targetpointer.FixedTarget;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
import mage.abilities.keyword.LifelinkAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
/**
* @author balazskristof
*/
public final class StiltzkinMoogleMerchant extends CardImpl {
public StiltzkinMoogleMerchant(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.MOOGLE);
this.power = new MageInt(1);
this.toughness = new MageInt(2);
// Lifelink
this.addAbility(LifelinkAbility.getInstance());
// {2}, {T}: Target opponent gains control of another target permanent you control. If they do, you draw a card.
Ability ability = new SimpleActivatedAbility(new StiltzkinMoogleMerchantEffect(), new GenericManaCost(2));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetOpponent());
ability.addTarget(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_PERMANENT));
this.addAbility(ability);
}
private StiltzkinMoogleMerchant(final StiltzkinMoogleMerchant card) {
super(card);
}
@Override
public StiltzkinMoogleMerchant copy() {
return new StiltzkinMoogleMerchant(this);
}
}
class StiltzkinMoogleMerchantEffect extends OneShotEffect {
StiltzkinMoogleMerchantEffect() {
super(Outcome.Benefit);
staticText = "Target opponent gains control of another target permanent you control. If they do, you draw a card.";
}
private StiltzkinMoogleMerchantEffect(StiltzkinMoogleMerchantEffect effect) {
super(effect);
}
@Override
public StiltzkinMoogleMerchantEffect copy() {
return new StiltzkinMoogleMerchantEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
if (permanent == null) {
return false;
}
UUID opponent = getTargetPointer().getFirst(game, source);
game.addEffect(new GainControlTargetEffect(
Duration.Custom, true, opponent
).setTargetPointer(new FixedTarget(permanent.getId(), game)), source);
game.processAction();
if (permanent.isControlledBy(opponent)) {
new DrawCardSourceControllerEffect(1).apply(game, source);
return true;
}
return false;
}
}

View file

@ -0,0 +1,78 @@
package mage.cards.s;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetOpponent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class StrategicBetrayal extends CardImpl {
public StrategicBetrayal(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}");
// Target opponent exiles a creature they control and their graveyard.
this.getSpellAbility().addEffect(new StrategicBetrayalEffect());
this.getSpellAbility().addTarget(new TargetOpponent());
}
private StrategicBetrayal(final StrategicBetrayal card) {
super(card);
}
@Override
public StrategicBetrayal copy() {
return new StrategicBetrayal(this);
}
}
class StrategicBetrayalEffect extends OneShotEffect {
StrategicBetrayalEffect() {
super(Outcome.Benefit);
staticText = "target opponent exiles a creature they control and their graveyard";
}
private StrategicBetrayalEffect(final StrategicBetrayalEffect effect) {
super(effect);
}
@Override
public StrategicBetrayalEffect copy() {
return new StrategicBetrayalEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
if (player == null) {
return false;
}
Cards cards = new CardsImpl(player.getGraveyard());
if (game.getBattlefield().contains(
StaticFilters.FILTER_CONTROLLED_CREATURE,
player.getId(), source, game, 1
)) {
TargetPermanent target = new TargetControlledCreaturePermanent();
target.withNotTarget(true);
player.choose(Outcome.DestroyPermanent, target, source, game);
cards.add(target.getFirstTarget());
}
return player.moveCards(cards, Zone.EXILED, source, game);
}
}

View file

@ -0,0 +1,95 @@
package mage.cards.s;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlashAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentToken;
import mage.players.Player;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class SunpearlKirin extends CardImpl {
private static final FilterPermanent filter = new FilterNonlandPermanent("other target nonland permanent you control");
static {
filter.add(AnotherPredicate.instance);
filter.add(TargetController.YOU.getControllerPredicate());
}
public SunpearlKirin(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
this.subtype.add(SubType.KIRIN);
this.power = new MageInt(2);
this.toughness = new MageInt(1);
// Flash
this.addAbility(FlashAbility.getInstance());
// Flying
this.addAbility(FlyingAbility.getInstance());
// When this creature enters, return up to one other target nonland permanent you control to its owner's hand. If it was a token, draw a card.
Ability ability = new EntersBattlefieldTriggeredAbility(new SunpearlKirinEffect());
ability.addTarget(new TargetPermanent(0, 1, filter));
this.addAbility(ability);
}
private SunpearlKirin(final SunpearlKirin card) {
super(card);
}
@Override
public SunpearlKirin copy() {
return new SunpearlKirin(this);
}
}
class SunpearlKirinEffect extends OneShotEffect {
SunpearlKirinEffect() {
super(Outcome.Benefit);
staticText = "return up to one other target nonland permanent " +
"you control to its owner's hand. If it was a token, draw a card";
}
private SunpearlKirinEffect(final SunpearlKirinEffect effect) {
super(effect);
}
@Override
public SunpearlKirinEffect copy() {
return new SunpearlKirinEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (player == null || permanent == null) {
return false;
}
boolean isToken = permanent instanceof PermanentToken;
player.moveCards(permanent, Zone.HAND, source, game);
if (isToken) {
player.drawCards(1, source, game);
}
return true;
}
}

View file

@ -0,0 +1,104 @@
package mage.cards.t;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.PowerPredicate;
import mage.game.Game;
import mage.util.CardUtil;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class TemurBattlecrier extends CardImpl {
public TemurBattlecrier(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{U}{R}");
this.subtype.add(SubType.ORC);
this.subtype.add(SubType.RANGER);
this.power = new MageInt(4);
this.toughness = new MageInt(3);
// During your turn, spells you cast cost {1} less to cast for each creature you control with power 4 or greater.
this.addAbility(new SimpleStaticAbility(new TemurBattlecrierEffect()).addHint(TemurBattlecrierEffect.getHint()));
}
private TemurBattlecrier(final TemurBattlecrier card) {
super(card);
}
@Override
public TemurBattlecrier copy() {
return new TemurBattlecrier(this);
}
}
class TemurBattlecrierEffect extends CostModificationEffectImpl {
private static final FilterPermanent filter = new FilterControlledCreaturePermanent();
static {
filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3));
}
private static final Hint hint = new ValueHint(
"Creatures you control with power 4 or greater", new PermanentsOnBattlefieldCount(filter)
);
public static Hint getHint() {
return hint;
}
TemurBattlecrierEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
staticText = "during your turn, spells you cast cost {1} less to cast " +
"for each creature you control with power 4 or greater";
}
private TemurBattlecrierEffect(final TemurBattlecrierEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source, Ability abilityToModify) {
Ability spellAbility = abilityToModify;
if (spellAbility == null) {
return false;
}
int amount = game.getBattlefield().count(filter, source.getControllerId(), source, game);
if (amount > 0) {
CardUtil.reduceCost(spellAbility, amount);
}
return true;
}
@Override
public boolean applies(Ability abilityToModify, Ability source, Game game) {
if (!(abilityToModify instanceof SpellAbility)
|| !abilityToModify.isControlledBy(source.getControllerId())
|| !game.isActivePlayer(source.getControllerId())) {
return false;
}
Card spellCard = ((SpellAbility) abilityToModify).getCharacteristics(game);
return spellCard != null;
}
@Override
public TemurBattlecrierEffect copy() {
return new TemurBattlecrierEffect(this);
}
}

View file

@ -0,0 +1,85 @@
package mage.cards.t;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.common.ThresholdCondition;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.discard.DiscardAndDrawThatManyEffect;
import mage.abilities.keyword.HasteAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class TersaLightshatter extends CardImpl {
public TersaLightshatter(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.ORC);
this.subtype.add(SubType.WIZARD);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// Haste
this.addAbility(HasteAbility.getInstance());
// When Tersa Lightshatter enters, discard up to two cards, then draw that many cards.
this.addAbility(new EntersBattlefieldTriggeredAbility(new DiscardAndDrawThatManyEffect(2)));
// Whenever Tersa Lightshatter attacks, if there are seven or more cards in your graveyard, exile a card at random from your graveyard. You may play that card this turn.
this.addAbility(new AttacksTriggeredAbility(new TersaLightshatterEffect()).withInterveningIf(ThresholdCondition.instance));
}
private TersaLightshatter(final TersaLightshatter card) {
super(card);
}
@Override
public TersaLightshatter copy() {
return new TersaLightshatter(this);
}
}
class TersaLightshatterEffect extends OneShotEffect {
TersaLightshatterEffect() {
super(Outcome.Benefit);
staticText = "exile a card at random from your graveyard. You may play that card this turn";
}
private TersaLightshatterEffect(final TersaLightshatterEffect effect) {
super(effect);
}
@Override
public TersaLightshatterEffect copy() {
return new TersaLightshatterEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Card card = player.getGraveyard().getRandom(game);
if (card == null) {
return false;
}
player.moveCards(card, Zone.EXILED, source, game);
CardUtil.makeCardPlayable(game, source, card, false, Duration.EndOfTurn, false);
return true;
}
}

View file

@ -0,0 +1,83 @@
package mage.cards.t;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.SagaAbility;
import mage.abilities.effects.common.*;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SagaChapter;
import mage.constants.SubType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class ThunderOfUnity extends CardImpl {
public ThunderOfUnity(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{R}{W}{B}");
this.subtype.add(SubType.SAGA);
// (As this Saga enters step, add a lore counter. Sacrifice after III.)
SagaAbility sagaAbility = new SagaAbility(this);
// I -- You draw two cards and you lose 2 life.
sagaAbility.addChapterEffect(
this, SagaChapter.CHAPTER_I,
new DrawCardSourceControllerEffect(2, true),
new LoseLifeSourceControllerEffect(2).concatBy("and")
);
// II, III -- Whenever a creature you control enters this turn, each opponent loses 1 life and you gain 1 life.
sagaAbility.addChapterEffect(
this, SagaChapter.CHAPTER_II, SagaChapter.CHAPTER_III,
new CreateDelayedTriggeredAbilityEffect(new ThunderOfUnityTriggeredAbility())
);
this.addAbility(sagaAbility);
}
private ThunderOfUnity(final ThunderOfUnity card) {
super(card);
}
@Override
public ThunderOfUnity copy() {
return new ThunderOfUnity(this);
}
}
class ThunderOfUnityTriggeredAbility extends DelayedTriggeredAbility {
ThunderOfUnityTriggeredAbility() {
super(new LoseLifeOpponentsEffect(1), Duration.EndOfTurn, false, false);
this.addEffect(new GainLifeEffect(1).concatBy("and"));
this.setTriggerPhrase("Whenever a creature you control enters this turn, ");
}
private ThunderOfUnityTriggeredAbility(final ThunderOfUnityTriggeredAbility ability) {
super(ability);
}
@Override
public ThunderOfUnityTriggeredAbility copy() {
return new ThunderOfUnityTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent permanent = game.getPermanent(event.getTargetId());
return permanent != null && permanent.isCreature(game) && permanent.isControlledBy(getControllerId());
}
}

View file

@ -65,7 +65,7 @@ enum ExiledCreatureSpellCondition implements Condition {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
MageObject object = game.getObject(source); MageObject object = game.getObject(source);
if (object instanceof SplitCardHalf || object instanceof AdventureCardSpell || object instanceof ModalDoubleFacedCardHalf) { if (object instanceof SplitCardHalf || object instanceof SpellOptionCard || object instanceof ModalDoubleFacedCardHalf) {
UUID mainCardId = ((Card) object).getMainCard().getId(); UUID mainCardId = ((Card) object).getMainCard().getId();
object = game.getObject(mainCardId); object = game.getObject(mainCardId);
} }

View file

@ -0,0 +1,84 @@
package mage.cards.t;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.permanent.CounterAnyPredicate;
import mage.game.Game;
import mage.players.Player;
import java.util.Optional;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class TradeRouteEnvoy extends CardImpl {
public TradeRouteEnvoy(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}");
this.subtype.add(SubType.DOG);
this.subtype.add(SubType.SOLDIER);
this.power = new MageInt(4);
this.toughness = new MageInt(3);
// When this creature enters, draw a card if you control a creature with a counter on it. If you don't draw a card this way, put a +1/+1 counter on this creature.
this.addAbility(new EntersBattlefieldTriggeredAbility(new TradeRouteEnvoyEffect()));
}
private TradeRouteEnvoy(final TradeRouteEnvoy card) {
super(card);
}
@Override
public TradeRouteEnvoy copy() {
return new TradeRouteEnvoy(this);
}
}
class TradeRouteEnvoyEffect extends OneShotEffect {
private static final FilterPermanent filter = new FilterControlledCreaturePermanent();
static {
filter.add(CounterAnyPredicate.instance);
}
TradeRouteEnvoyEffect() {
super(Outcome.Benefit);
staticText = "draw a card if you control a creature with a counter on it. " +
"If you don't draw a card this way, put a +1/+1 counter on this creature";
}
private TradeRouteEnvoyEffect(final TradeRouteEnvoyEffect effect) {
super(effect);
}
@Override
public TradeRouteEnvoyEffect copy() {
return new TradeRouteEnvoyEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
if (game.getBattlefield().contains(filter, source, game, 1)) {
Player player = game.getPlayer(source.getControllerId());
if (player != null && player.drawCards(1, source, game) > 0) {
return true;
}
}
Optional.ofNullable(source.getSourcePermanentIfItStillExists(game))
.ifPresent(permanent -> permanent.addCounters(CounterType.P1P1.createInstance(), source, game));
return true;
}
}

View file

@ -0,0 +1,88 @@
package mage.cards.t;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BecomesTappedSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class TravelingBotanist extends CardImpl {
public TravelingBotanist(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
this.subtype.add(SubType.DOG);
this.subtype.add(SubType.SCOUT);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// Whenever this creature becomes tapped, look at the top card of your library. If it's a land card, you may reveal it and put it into your hand. If you don't put the card into your hand, you may put it into your graveyard.
this.addAbility(new BecomesTappedSourceTriggeredAbility(new TravelingBotanistEffect()));
}
private TravelingBotanist(final TravelingBotanist card) {
super(card);
}
@Override
public TravelingBotanist copy() {
return new TravelingBotanist(this);
}
}
class TravelingBotanistEffect extends OneShotEffect {
TravelingBotanistEffect() {
super(Outcome.Benefit);
staticText = "look at the top card of your library. If it's a land card, you may reveal it and " +
"put it into your hand. If you don't put the card into your hand, you may put it into your graveyard";
}
private TravelingBotanistEffect(final TravelingBotanistEffect effect) {
super(effect);
}
@Override
public TravelingBotanistEffect copy() {
return new TravelingBotanistEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Card card = player.getLibrary().getFromTop(game);
if (card == null) {
return false;
}
player.lookAtCards("Top card of library", card, game);
if (card.isLand(game) && player.chooseUse(
Outcome.DrawCard, "Reveal " + card.getName() +
" and put it into your hand?", source, game
)) {
player.revealCards(source, new CardsImpl(card), game);
player.moveCards(card, Zone.HAND, source, game);
return true;
}
if (player.chooseUse(Outcome.Neutral, "Put " + card.getName() + " into your graveyard?", source, game)) {
return player.moveCards(card, Zone.GRAVEYARD, source, game);
}
return true;
}
}

View file

@ -10,7 +10,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.token.SeedGuardianToken; import mage.game.permanent.token.ElementalXXGreenToken;
import java.util.UUID; import java.util.UUID;
@ -61,6 +61,6 @@ class TumbleweedRisingEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
int xvalue = GreatestPowerAmongControlledCreaturesValue.instance.calculate(game, source, this); int xvalue = GreatestPowerAmongControlledCreaturesValue.instance.calculate(game, source, this);
return new CreateTokenEffect(new SeedGuardianToken(xvalue)).apply(game, source); return new CreateTokenEffect(new ElementalXXGreenToken(xvalue)).apply(game, source);
} }
} }

View file

@ -47,7 +47,7 @@ public final class TwiceUponATime extends AdventureCard {
// Unlikely Meeting // Unlikely Meeting
// Search your library for a Doctor card, reveal it, put it into your hand, then shuffle. // Search your library for a Doctor card, reveal it, put it into your hand, then shuffle.
this.getSpellCard().getSpellAbility().addEffect(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter2), true)); this.getSpellCard().getSpellAbility().addEffect(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter2), true));
this.getSpellCard().finalizeAdventure(); this.finalizeAdventure();
} }
private TwiceUponATime(final TwiceUponATime card) { private TwiceUponATime(final TwiceUponATime card) {

View file

@ -0,0 +1,58 @@
package mage.cards.u;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.PutCards;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.common.FilterCreatureCard;
import java.util.UUID;
/**
* @author ilyagart
*/
public final class UreniOfTheUnwritten extends CardImpl {
static final FilterCreatureCard filter = new FilterCreatureCard("Dragon creature card");
static {
filter.add(SubType.DRAGON.getPredicate());
}
public UreniOfTheUnwritten(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}{U}{R}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.SPIRIT);
this.subtype.add(SubType.DRAGON);
this.power = new MageInt(7);
this.toughness = new MageInt(7);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Trample
this.addAbility(TrampleAbility.getInstance());
// Whenever Ureni enters or attacks, look at the top eight cards of your library. You may put a Dragon creature card from among them onto the battlefield. Put the rest on the bottom of your library in a random order.
Effect effect = new LookLibraryAndPickControllerEffect(8, 1, filter, PutCards.BATTLEFIELD, PutCards.BOTTOM_RANDOM);
this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility(effect, false));
}
private UreniOfTheUnwritten(final UreniOfTheUnwritten card) {
super(card);
}
@Override
public UreniOfTheUnwritten copy() {
return new UreniOfTheUnwritten(this);
}
}

View file

@ -0,0 +1,65 @@
package mage.cards.u;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.dynamicvalue.common.LandsYouControlCount;
import mage.abilities.effects.common.DamageMultiEffect;
import mage.abilities.hint.common.LandsYouControlHint;
import mage.abilities.keyword.FlyingAbility;
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.constants.TargetController;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent;
import mage.target.common.TargetPermanentAmount;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class UreniTheSongUnending extends CardImpl {
private static final FilterPermanent filter
= new FilterCreatureOrPlaneswalkerPermanent("creatures and/or planeswalkers your opponents control");
static {
filter.add(TargetController.OPPONENT.getControllerPredicate());
}
public UreniTheSongUnending(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{G}{U}{R}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.SPIRIT);
this.subtype.add(SubType.DRAGON);
this.power = new MageInt(10);
this.toughness = new MageInt(10);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Protection from white and from black
this.addAbility(ProtectionAbility.from(ObjectColor.WHITE, ObjectColor.BLACK));
// When Ureni enters, it deals X damage divided as you choose among any number of target creatures and/or planeswalkers your opponents control, where X is the number of lands you control.
Ability ability = new EntersBattlefieldTriggeredAbility(new DamageMultiEffect("it"));
ability.addTarget(new TargetPermanentAmount(LandsYouControlCount.instance, 0, filter));
this.addAbility(ability.addHint(LandsYouControlHint.instance));
}
private UreniTheSongUnending(final UreniTheSongUnending card) {
super(card);
}
@Override
public UreniTheSongUnending copy() {
return new UreniTheSongUnending(this);
}
}

View file

@ -0,0 +1,51 @@
package mage.cards.v;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.dynamicvalue.common.SourcePermanentPowerValue;
import mage.abilities.effects.common.MillCardsTargetEffect;
import mage.abilities.keyword.CantBeBlockedSourceAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.target.TargetPlayer;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class VeteranIceClimber extends CardImpl {
public VeteranIceClimber(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.SCOUT);
this.power = new MageInt(1);
this.toughness = new MageInt(3);
// Vigilance
this.addAbility(VigilanceAbility.getInstance());
// This creature can't be blocked.
this.addAbility(new CantBeBlockedSourceAbility());
// Whenever this creature attacks, up to one target player mills cards equal to this creature's power.
Ability ability = new AttacksTriggeredAbility(new MillCardsTargetEffect(SourcePermanentPowerValue.NOT_NEGATIVE));
ability.addTarget(new TargetPlayer(0, 1, false));
this.addAbility(ability);
}
private VeteranIceClimber(final VeteranIceClimber card) {
super(card);
}
@Override
public VeteranIceClimber copy() {
return new VeteranIceClimber(this);
}
}

View file

@ -0,0 +1,55 @@
package mage.cards.w;
import mage.abilities.Mode;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.TargetController;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.target.common.TargetCardInGraveyard;
import mage.target.common.TargetOpponent;
import java.util.UUID;
/**
* Represents the "Wail of War" instant card.
* Author: @mikejcunn
*/
public final class WailOfWar extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures target opponent controls");
static {
filter.add(TargetController.SOURCE_TARGETS.getControllerPredicate());
}
public WailOfWar(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}");
// Mode 1: Creatures target player controls get -1/-1 until end of turn.
this.getSpellAbility().addEffect(new BoostAllEffect(
-1, -1, Duration.EndOfTurn, filter, false
));
this.getSpellAbility().addTarget(new TargetOpponent());
// Mode 2: Return creatures from graveyard
Mode returnCreaturesFromGraveyardMode = new Mode(new ReturnFromGraveyardToHandTargetEffect());
returnCreaturesFromGraveyardMode.addTarget(new TargetCardInGraveyard(
0, 2, StaticFilters.FILTER_CARD_CREATURES_YOUR_GRAVEYARD
));
this.getSpellAbility().addMode(returnCreaturesFromGraveyardMode);
}
private WailOfWar(final WailOfWar card) {
super(card);
}
@Override
public WailOfWar copy() {
return new WailOfWar(this);
}
}

View file

@ -10,7 +10,7 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.game.permanent.token.WalkerOfTheGroveToken; import mage.game.permanent.token.Elemental44GreenToken;
/** /**
* *
@ -26,7 +26,7 @@ public final class WalkerOfTheGrove extends CardImpl {
this.toughness = new MageInt(7); this.toughness = new MageInt(7);
// When Walker of the Grove leaves the battlefield, create a 4/4 green Elemental creature token. // When Walker of the Grove leaves the battlefield, create a 4/4 green Elemental creature token.
this.addAbility(new LeavesBattlefieldTriggeredAbility(new CreateTokenEffect(new WalkerOfTheGroveToken(), 1), false)); this.addAbility(new LeavesBattlefieldTriggeredAbility(new CreateTokenEffect(new Elemental44GreenToken(), 1), false));
// Evoke {4}{G} // Evoke {4}{G}
this.addAbility(new EvokeAbility("{4}{G}")); this.addAbility(new EvokeAbility("{4}{G}"));
} }

View file

@ -0,0 +1,73 @@
package mage.cards.w;
import mage.abilities.Ability;
import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.SacrificeTargetEffect;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.token.RedWarriorToken;
import mage.game.permanent.token.Token;
import mage.target.targetpointer.FixedTargets;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class WarEffort extends CardImpl {
public WarEffort(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}");
// Creatures you control get +1/+0.
this.addAbility(new SimpleStaticAbility(new BoostControlledEffect(1, 0, Duration.WhileOnBattlefield)));
// Whenever you attack, create a 1/1 red Warrior creature token that's tapped and attacking. Sacrifice it at the beginning of the next end step.
this.addAbility(new AttacksWithCreaturesTriggeredAbility(new WarEffortEffect(), 1));
}
private WarEffort(final WarEffort card) {
super(card);
}
@Override
public WarEffort copy() {
return new WarEffort(this);
}
}
class WarEffortEffect extends OneShotEffect {
WarEffortEffect() {
super(Outcome.Benefit);
staticText = "create a 1/1 red Warrior creature token that's tapped and attacking. " +
"Sacrifice it at the beginning of the next end step";
}
private WarEffortEffect(final WarEffortEffect effect) {
super(effect);
}
@Override
public WarEffortEffect copy() {
return new WarEffortEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Token token = new RedWarriorToken();
token.putOntoBattlefield(1, game, source, source.getControllerId(), true, true);
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(
new SacrificeTargetEffect("sacrifice it").setTargetPointer(new FixedTargets(token, game))
), source);
return true;
}
}

View file

@ -0,0 +1,91 @@
package mage.cards.w;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.effects.keyword.EndureSourceEffect;
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.counters.CounterType;
import mage.counters.Counters;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.Game;
import java.util.Optional;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class WardenOfTheGrove extends CardImpl {
private static final FilterPermanent filter
= new FilterControlledCreaturePermanent("another nontoken creature you control");
static {
filter.add(AnotherPredicate.instance);
filter.add(TokenPredicate.FALSE);
}
public WardenOfTheGrove(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}");
this.subtype.add(SubType.HYDRA);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// At the beginning of your end step, put a +1/+1 counter on this creature.
this.addAbility(new BeginningOfEndStepTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance())));
// Whenever another nontoken creature you control enters, it endures X, where X is the number of counters on this creature.
this.addAbility(new EntersBattlefieldAllTriggeredAbility(
Zone.BATTLEFIELD, new WardenOfTheGroveEffect(),
filter, false, SetTargetPointer.PERMANENT
));
}
private WardenOfTheGrove(final WardenOfTheGrove card) {
super(card);
}
@Override
public WardenOfTheGrove copy() {
return new WardenOfTheGrove(this);
}
}
class WardenOfTheGroveEffect extends OneShotEffect {
WardenOfTheGroveEffect() {
super(Outcome.Benefit);
staticText = "it endures X, where X is the number of counters on {this}";
}
private WardenOfTheGroveEffect(final WardenOfTheGroveEffect effect) {
super(effect);
}
@Override
public WardenOfTheGroveEffect copy() {
return new WardenOfTheGroveEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return EndureSourceEffect.doEndure(
this.getTargetPointer().getFirstTargetPermanentOrLKI(game, source),
Optional.ofNullable(source.getSourcePermanentOrLKI(game))
.map(p -> p.getCounters(game))
.map(Counters::getTotalCount)
.orElse(0),
game, source
);
}
}

View file

@ -0,0 +1,60 @@
package mage.cards.y;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.condition.common.CastFromEverywhereSourceCondition;
import mage.abilities.costs.common.MillCardsCost;
import mage.abilities.effects.common.DoWhenCostPaid;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.mageobject.ManaValuePredicate;
import mage.target.common.TargetCardInYourGraveyard;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class YathanRoadwatcher extends CardImpl {
private static final FilterCard filter
= new FilterCreatureCard("creature card with mana value 3 or less from your graveyard");
static {
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 4));
}
public YathanRoadwatcher(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{B}{G}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.SCOUT);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// When this creature enters, if you cast it, mill four cards. When you do, return target creature card with mana value 3 or less from your graveyard to the battlefield.
ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
new ReturnFromGraveyardToBattlefieldTargetEffect(), false
);
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(new EntersBattlefieldTriggeredAbility(new DoWhenCostPaid(
ability, new MillCardsCost(4), "", false
)).withInterveningIf(CastFromEverywhereSourceCondition.instance));
}
private YathanRoadwatcher(final YathanRoadwatcher card) {
super(card);
}
@Override
public YathanRoadwatcher copy() {
return new YathanRoadwatcher(this);
}
}

View file

@ -118,7 +118,7 @@ public final class AetherdriftCommander extends ExpansionSet {
cards.add(new SetCardInfo("Maskwood Nexus", 132, Rarity.RARE, mage.cards.m.MaskwoodNexus.class)); cards.add(new SetCardInfo("Maskwood Nexus", 132, Rarity.RARE, mage.cards.m.MaskwoodNexus.class));
cards.add(new SetCardInfo("Midnight Clock", 79, Rarity.RARE, mage.cards.m.MidnightClock.class)); cards.add(new SetCardInfo("Midnight Clock", 79, Rarity.RARE, mage.cards.m.MidnightClock.class));
cards.add(new SetCardInfo("Midnight Reaper", 44, Rarity.RARE, mage.cards.m.MidnightReaper.class)); cards.add(new SetCardInfo("Midnight Reaper", 44, Rarity.RARE, mage.cards.m.MidnightReaper.class));
cards.add(new SetCardInfo("Murderous Rider // Swift End", 45, Rarity.RARE, mage.cards.m.MurderousRider.class)); cards.add(new SetCardInfo("Murderous Rider", 45, Rarity.RARE, mage.cards.m.MurderousRider.class));
cards.add(new SetCardInfo("Never // Return", 96, Rarity.RARE, mage.cards.n.NeverReturn.class)); cards.add(new SetCardInfo("Never // Return", 96, Rarity.RARE, mage.cards.n.NeverReturn.class));
cards.add(new SetCardInfo("Nissa, Worldsoul Speaker", 13, Rarity.RARE, mage.cards.n.NissaWorldsoulSpeaker.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Nissa, Worldsoul Speaker", 13, Rarity.RARE, mage.cards.n.NissaWorldsoulSpeaker.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Nissa, Worldsoul Speaker", 29, Rarity.RARE, mage.cards.n.NissaWorldsoulSpeaker.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Nissa, Worldsoul Speaker", 29, Rarity.RARE, mage.cards.n.NissaWorldsoulSpeaker.class, NON_FULL_USE_VARIOUS));

View file

@ -189,9 +189,9 @@ public final class AssassinsCreed extends ExpansionSet {
cards.add(new SetCardInfo("Kassandra, Eagle Bearer", 59, Rarity.MYTHIC, mage.cards.k.KassandraEagleBearer.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Kassandra, Eagle Bearer", 59, Rarity.MYTHIC, mage.cards.k.KassandraEagleBearer.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Keen-Eyed Raven", 279, Rarity.UNCOMMON, mage.cards.k.KeenEyedRaven.class)); cards.add(new SetCardInfo("Keen-Eyed Raven", 279, Rarity.UNCOMMON, mage.cards.k.KeenEyedRaven.class));
cards.add(new SetCardInfo("Labyrinth Adversary", 290, Rarity.UNCOMMON, mage.cards.l.LabyrinthAdversary.class)); cards.add(new SetCardInfo("Labyrinth Adversary", 290, Rarity.UNCOMMON, mage.cards.l.LabyrinthAdversary.class));
//cards.add(new SetCardInfo("Layla Hassan", 127, Rarity.RARE, mage.cards.l.LaylaHassan.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Layla Hassan", 127, Rarity.RARE, mage.cards.l.LaylaHassan.class, NON_FULL_USE_VARIOUS));
//cards.add(new SetCardInfo("Layla Hassan", 177, Rarity.RARE, mage.cards.l.LaylaHassan.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Layla Hassan", 177, Rarity.RARE, mage.cards.l.LaylaHassan.class, NON_FULL_USE_VARIOUS));
//cards.add(new SetCardInfo("Layla Hassan", 7, Rarity.RARE, mage.cards.l.LaylaHassan.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Layla Hassan", 7, Rarity.RARE, mage.cards.l.LaylaHassan.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Leonardo da Vinci", "118z", Rarity.MYTHIC, mage.cards.l.LeonardoDaVinci.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Leonardo da Vinci", "118z", Rarity.MYTHIC, mage.cards.l.LeonardoDaVinci.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Leonardo da Vinci", 118, Rarity.MYTHIC, mage.cards.l.LeonardoDaVinci.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Leonardo da Vinci", 118, Rarity.MYTHIC, mage.cards.l.LeonardoDaVinci.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Leonardo da Vinci", 193, Rarity.MYTHIC, mage.cards.l.LeonardoDaVinci.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Leonardo da Vinci", 193, Rarity.MYTHIC, mage.cards.l.LeonardoDaVinci.class, NON_FULL_USE_VARIOUS));

View file

@ -376,8 +376,8 @@ public final class DoctorWho extends ExpansionSet {
cards.add(new SetCardInfo("Frostboil Snarl", 282, Rarity.RARE, mage.cards.f.FrostboilSnarl.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Frostboil Snarl", 282, Rarity.RARE, mage.cards.f.FrostboilSnarl.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Frostboil Snarl", 498, Rarity.RARE, mage.cards.f.FrostboilSnarl.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Frostboil Snarl", 498, Rarity.RARE, mage.cards.f.FrostboilSnarl.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Frostboil Snarl", 873, Rarity.RARE, mage.cards.f.FrostboilSnarl.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Frostboil Snarl", 873, Rarity.RARE, mage.cards.f.FrostboilSnarl.class, NON_FULL_USE_VARIOUS));
//cards.add(new SetCardInfo("Fugitive of the Judoon", 103, Rarity.RARE, mage.cards.f.FugitiveOfTheJudoon.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fugitive of the Judoon", 103, Rarity.RARE, mage.cards.f.FugitiveOfTheJudoon.class, NON_FULL_USE_VARIOUS));
//cards.add(new SetCardInfo("Fugitive of the Judoon", 708, Rarity.RARE, mage.cards.f.FugitiveOfTheJudoon.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fugitive of the Judoon", 708, Rarity.RARE, mage.cards.f.FugitiveOfTheJudoon.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Furycalm Snarl", 1090, Rarity.RARE, mage.cards.f.FurycalmSnarl.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Furycalm Snarl", 1090, Rarity.RARE, mage.cards.f.FurycalmSnarl.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Furycalm Snarl", 283, Rarity.RARE, mage.cards.f.FurycalmSnarl.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Furycalm Snarl", 283, Rarity.RARE, mage.cards.f.FurycalmSnarl.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Furycalm Snarl", 499, Rarity.RARE, mage.cards.f.FurycalmSnarl.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Furycalm Snarl", 499, Rarity.RARE, mage.cards.f.FurycalmSnarl.class, NON_FULL_USE_VARIOUS));

View file

@ -26,6 +26,8 @@ public final class FinalFantasy extends ExpansionSet {
cards.add(new SetCardInfo("Sin, Spira's Punishment", 242, Rarity.RARE, mage.cards.s.SinSpirasPunishment.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sin, Spira's Punishment", 242, Rarity.RARE, mage.cards.s.SinSpirasPunishment.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Sin, Spira's Punishment", 348, Rarity.RARE, mage.cards.s.SinSpirasPunishment.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sin, Spira's Punishment", 348, Rarity.RARE, mage.cards.s.SinSpirasPunishment.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Sin, Spira's Punishment", 508, Rarity.RARE, mage.cards.s.SinSpirasPunishment.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sin, Spira's Punishment", 508, Rarity.RARE, mage.cards.s.SinSpirasPunishment.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Stiltzkin, Moogle Merchant", 34, Rarity.RARE, mage.cards.s.StiltzkinMoogleMerchant.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Stiltzkin, Moogle Merchant", 327, Rarity.RARE, mage.cards.s.StiltzkinMoogleMerchant.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Summon: Shiva", 78, Rarity.UNCOMMON, mage.cards.s.SummonShiva.class)); cards.add(new SetCardInfo("Summon: Shiva", 78, Rarity.UNCOMMON, mage.cards.s.SummonShiva.class));
cards.add(new SetCardInfo("Tonberry", 122, Rarity.UNCOMMON, mage.cards.t.Tonberry.class)); cards.add(new SetCardInfo("Tonberry", 122, Rarity.UNCOMMON, mage.cards.t.Tonberry.class));
} }

View file

@ -22,37 +22,69 @@ public class MediaAndCollaborationPromos extends ExpansionSet {
// some cards are non-English (most are Japanese, Jamuraan Lion has a German printing), but it's ok - scryfall can download it // some cards are non-English (most are Japanese, Jamuraan Lion has a German printing), but it's ok - scryfall can download it
cards.add(new SetCardInfo("Archangel", 29, Rarity.RARE, mage.cards.a.Archangel.class)); cards.add(new SetCardInfo("Ajani, Mentor of Heroes", "2024-3", Rarity.MYTHIC, mage.cards.a.AjaniMentorOfHeroes.class));
cards.add(new SetCardInfo("Ascendant Evincar", 28, Rarity.RARE, mage.cards.a.AscendantEvincar.class)); cards.add(new SetCardInfo("Ancestral Mask", "2025-2", Rarity.RARE, mage.cards.a.AncestralMask.class));
cards.add(new SetCardInfo("Blue Elemental Blast", 5, Rarity.COMMON, mage.cards.b.BlueElementalBlast.class)); cards.add(new SetCardInfo("Archangel", "2000-4", Rarity.RARE, mage.cards.a.Archangel.class));
cards.add(new SetCardInfo("Cast Down", 30, Rarity.UNCOMMON, mage.cards.c.CastDown.class)); cards.add(new SetCardInfo("Ascendant Evincar", "2000-7", Rarity.RARE, mage.cards.a.AscendantEvincar.class));
cards.add(new SetCardInfo("Chandra's Outrage", 18, Rarity.COMMON, mage.cards.c.ChandrasOutrage.class)); cards.add(new SetCardInfo("Avalanche Riders", "2023-5", Rarity.RARE, mage.cards.a.AvalancheRiders.class));
cards.add(new SetCardInfo("Chandra's Spitfire", 19, Rarity.UNCOMMON, mage.cards.c.ChandrasSpitfire.class)); cards.add(new SetCardInfo("Blue Elemental Blast", "1995-2", Rarity.COMMON, mage.cards.b.BlueElementalBlast.class));
cards.add(new SetCardInfo("Cunning Sparkmage", 17, Rarity.UNCOMMON, mage.cards.c.CunningSparkmage.class)); cards.add(new SetCardInfo("Bone Shredder", "2021-2", Rarity.RARE, mage.cards.b.BoneShredder.class));
cards.add(new SetCardInfo("Darksteel Juggernaut", 16, Rarity.RARE, mage.cards.d.DarksteelJuggernaut.class)); cards.add(new SetCardInfo("Cast Down", "2019-1", Rarity.UNCOMMON, mage.cards.c.CastDown.class));
cards.add(new SetCardInfo("Daxos, Blessed by the Sun", 36, Rarity.UNCOMMON, mage.cards.d.DaxosBlessedByTheSun.class)); cards.add(new SetCardInfo("Chandra's Outrage", "2010-3", Rarity.COMMON, mage.cards.c.ChandrasOutrage.class));
cards.add(new SetCardInfo("Diabolic Edict", 31, Rarity.RARE, mage.cards.d.DiabolicEdict.class)); cards.add(new SetCardInfo("Chandra's Spitfire", "2010-4", Rarity.UNCOMMON, mage.cards.c.ChandrasSpitfire.class));
cards.add(new SetCardInfo("Duress", 34, Rarity.RARE, mage.cards.d.Duress.class)); cards.add(new SetCardInfo("Counterspell", "2021-1", Rarity.RARE, mage.cards.c.Counterspell.class));
cards.add(new SetCardInfo("Fireball", 4, Rarity.COMMON, mage.cards.f.Fireball.class)); cards.add(new SetCardInfo("Crop Rotation", "2020-7ww", Rarity.RARE, mage.cards.c.CropRotation.class));
cards.add(new SetCardInfo("Jamuraan Lion", "10*", Rarity.COMMON, mage.cards.j.JamuraanLion.class)); cards.add(new SetCardInfo("Culling the Weak", "2023-8", Rarity.RARE, mage.cards.c.CullingTheWeak.class));
cards.add(new SetCardInfo("Kuldotha Phoenix", 20, Rarity.RARE, mage.cards.k.KuldothaPhoenix.class)); cards.add(new SetCardInfo("Cunning Sparkmage", "2010-2", Rarity.UNCOMMON, mage.cards.c.CunningSparkmage.class));
cards.add(new SetCardInfo("Lava Coil", 33, Rarity.UNCOMMON, mage.cards.l.LavaCoil.class)); cards.add(new SetCardInfo("Dark Ritual", "2020-4", Rarity.RARE, mage.cards.d.DarkRitual.class));
cards.add(new SetCardInfo("Lightning Hounds", 10, Rarity.COMMON, mage.cards.l.LightningHounds.class)); cards.add(new SetCardInfo("Darksteel Juggernaut", "2010-1", Rarity.RARE, mage.cards.d.DarksteelJuggernaut.class));
cards.add(new SetCardInfo("Parallax Dementia", 27, Rarity.COMMON, mage.cards.p.ParallaxDementia.class)); cards.add(new SetCardInfo("Daxos, Blessed by the Sun", "2020-2", Rarity.UNCOMMON, mage.cards.d.DaxosBlessedByTheSun.class));
cards.add(new SetCardInfo("Phantasmal Dragon", 21, Rarity.UNCOMMON, mage.cards.p.PhantasmalDragon.class)); cards.add(new SetCardInfo("Diabolic Edict", "2024-5", Rarity.RARE, mage.cards.d.DiabolicEdict.class));
cards.add(new SetCardInfo("Phyrexian Rager", 14, Rarity.COMMON, mage.cards.p.PhyrexianRager.class)); cards.add(new SetCardInfo("Disenchant", "2022-1", Rarity.RARE, mage.cards.d.Disenchant.class));
cards.add(new SetCardInfo("Sandbar Crocodile", 22, Rarity.COMMON, mage.cards.s.SandbarCrocodile.class)); cards.add(new SetCardInfo("Duress", "2025-7", Rarity.RARE, mage.cards.d.Duress.class));
cards.add(new SetCardInfo("Scent of Cinder", 9, Rarity.COMMON, mage.cards.s.ScentOfCinder.class)); cards.add(new SetCardInfo("Fireball", "1995-1", Rarity.COMMON, mage.cards.f.Fireball.class));
cards.add(new SetCardInfo("Shivan Dragon", 15, Rarity.RARE, mage.cards.s.ShivanDragon.class)); cards.add(new SetCardInfo("Frantic Search", "2022-4", Rarity.RARE, mage.cards.f.FranticSearch.class));
cards.add(new SetCardInfo("Shock", 32, Rarity.RARE, mage.cards.s.Shock.class)); cards.add(new SetCardInfo("Gingerbrute", "2023-3", Rarity.RARE, mage.cards.g.Gingerbrute.class));
cards.add(new SetCardInfo("Shrieking Drake", 24, Rarity.COMMON, mage.cards.s.ShriekingDrake.class)); cards.add(new SetCardInfo("Gush", "2024-4", Rarity.RARE, mage.cards.g.Gush.class));
cards.add(new SetCardInfo("Silver Drake", 13, Rarity.COMMON, mage.cards.s.SilverDrake.class)); cards.add(new SetCardInfo("Harald, King of Skemfar", "2021-3", Rarity.RARE, mage.cards.h.HaraldKingOfSkemfar.class));
cards.add(new SetCardInfo("Spined Wurm", 11, Rarity.COMMON, mage.cards.s.SpinedWurm.class)); cards.add(new SetCardInfo("Heliod's Pilgrim", "2020-6", Rarity.RARE, mage.cards.h.HeliodsPilgrim.class));
cards.add(new SetCardInfo("Staggering Insight", 37, Rarity.RARE, mage.cards.s.StaggeringInsight.class)); cards.add(new SetCardInfo("Hypnotic Sprite", "2019-5", Rarity.RARE, mage.cards.h.HypnoticSprite.class));
cards.add(new SetCardInfo("Stream of Life", 25, Rarity.COMMON, mage.cards.s.StreamOfLife.class)); cards.add(new SetCardInfo("Jace Beleren", "2009-1", Rarity.MYTHIC, mage.cards.j.JaceBeleren.class));
cards.add(new SetCardInfo("Thorn Elemental", 26, Rarity.RARE, mage.cards.t.ThornElemental.class)); cards.add(new SetCardInfo("Jace, Memory Adept", "2024-2", Rarity.MYTHIC, mage.cards.j.JaceMemoryAdept.class));
cards.add(new SetCardInfo("Voltaic Key", 35, Rarity.RARE, mage.cards.v.VoltaicKey.class)); cards.add(new SetCardInfo("Jamuraan Lion", "1996-3", Rarity.COMMON, mage.cards.j.JamuraanLion.class));
cards.add(new SetCardInfo("Warmonger", 12, Rarity.UNCOMMON, mage.cards.w.Warmonger.class)); cards.add(new SetCardInfo("Kuldotha Phoenix", "2010-5", Rarity.RARE, mage.cards.k.KuldothaPhoenix.class));
cards.add(new SetCardInfo("Zhalfirin Knight", 23, Rarity.COMMON, mage.cards.z.ZhalfirinKnight.class)); cards.add(new SetCardInfo("Lava Coil", "2019-4", Rarity.UNCOMMON, mage.cards.l.LavaCoil.class));
cards.add(new SetCardInfo("Lightning Hounds", "2000-1", Rarity.COMMON, mage.cards.l.LightningHounds.class));
cards.add(new SetCardInfo("Liliana of the Dark Realms", "2024-8", Rarity.MYTHIC, mage.cards.l.LilianaOfTheDarkRealms.class));
cards.add(new SetCardInfo("Mental Misstep", "2023-1", Rarity.RARE, mage.cards.m.MentalMisstep.class));
cards.add(new SetCardInfo("Nicol Bolas, Planeswalker", "2025-10", Rarity.MYTHIC, mage.cards.n.NicolBolasPlaneswalker.class));
cards.add(new SetCardInfo("Parallax Dementia", "2000-6", Rarity.COMMON, mage.cards.p.ParallaxDementia.class));
cards.add(new SetCardInfo("Patchwork Banner", "2024-7", Rarity.RARE, mage.cards.p.PatchworkBanner.class));
cards.add(new SetCardInfo("Phantasmal Dragon", "2011-1", Rarity.UNCOMMON, mage.cards.p.PhantasmalDragon.class));
cards.add(new SetCardInfo("Phyrexian Rager", "2000-5", Rarity.COMMON, mage.cards.p.PhyrexianRager.class));
cards.add(new SetCardInfo("Pyromancer's Gauntlet", "2023-6", Rarity.RARE, mage.cards.p.PyromancersGauntlet.class));
cards.add(new SetCardInfo("Ruin Crab", "2023-4", Rarity.RARE, mage.cards.r.RuinCrab.class));
cards.add(new SetCardInfo("Sandbar Crocodile", "1996-1", Rarity.COMMON, mage.cards.s.SandbarCrocodile.class));
cards.add(new SetCardInfo("Scent of Cinder", "1999-1", Rarity.COMMON, mage.cards.s.ScentOfCinder.class));
cards.add(new SetCardInfo("Shield Wall", "1997-3", Rarity.COMMON, mage.cards.s.ShieldWall.class));
cards.add(new SetCardInfo("Shivan Dragon", "2001-2", Rarity.RARE, mage.cards.s.ShivanDragon.class));
cards.add(new SetCardInfo("Shock", "2025-1", Rarity.RARE, mage.cards.s.Shock.class));
cards.add(new SetCardInfo("Shrieking Drake", "1997-2", Rarity.COMMON, mage.cards.s.ShriekingDrake.class));
cards.add(new SetCardInfo("Silver Drake", "2000-2", Rarity.COMMON, mage.cards.s.SilverDrake.class));
cards.add(new SetCardInfo("Snuff Out", "2024-1", Rarity.RARE, mage.cards.s.SnuffOut.class));
cards.add(new SetCardInfo("Spined Wurm", "2001-1", Rarity.COMMON, mage.cards.s.SpinedWurm.class));
cards.add(new SetCardInfo("Sprite Dragon", "2020-5", Rarity.RARE, mage.cards.s.SpriteDragon.class));
cards.add(new SetCardInfo("Staggering Insight", "2020-3", Rarity.RARE, mage.cards.s.StaggeringInsight.class));
cards.add(new SetCardInfo("Stream of Life", "1997-4", Rarity.COMMON, mage.cards.s.StreamOfLife.class));
cards.add(new SetCardInfo("Talruum Champion", "1997-1", Rarity.COMMON, mage.cards.t.TalruumChampion.class));
cards.add(new SetCardInfo("Tangled Florahedron", "2020-8", Rarity.UNCOMMON, mage.cards.t.TangledFlorahedron.class));
cards.add(new SetCardInfo("Thorn Elemental", "2000-3", Rarity.RARE, mage.cards.t.ThornElemental.class));
cards.add(new SetCardInfo("Usher of the Fallen", "2022-3", Rarity.RARE, mage.cards.u.UsherOfTheFallen.class));
cards.add(new SetCardInfo("Voltaic Key", "2024-6", Rarity.RARE, mage.cards.v.VoltaicKey.class));
cards.add(new SetCardInfo("Warmonger", "1999-2", Rarity.UNCOMMON, mage.cards.w.Warmonger.class));
cards.add(new SetCardInfo("Wild Growth", "2022-2", Rarity.RARE, mage.cards.w.WildGrowth.class));
cards.add(new SetCardInfo("Winged Boots", "2023-7", Rarity.RARE, mage.cards.w.WingedBoots.class));
cards.add(new SetCardInfo("Worn Powerstone", "2023-2", Rarity.RARE, mage.cards.w.WornPowerstone.class));
cards.add(new SetCardInfo("Zhalfirin Knight", "1996-2", Rarity.COMMON, mage.cards.z.ZhalfirinKnight.class));
} }
} }

View file

@ -25,6 +25,7 @@ public final class TarkirDragonstorm extends ExpansionSet {
cards.add(new SetCardInfo("Adorned Crocodile", 69, Rarity.COMMON, mage.cards.a.AdornedCrocodile.class)); cards.add(new SetCardInfo("Adorned Crocodile", 69, Rarity.COMMON, mage.cards.a.AdornedCrocodile.class));
cards.add(new SetCardInfo("Aegis Sculptor", 35, Rarity.UNCOMMON, mage.cards.a.AegisSculptor.class)); cards.add(new SetCardInfo("Aegis Sculptor", 35, Rarity.UNCOMMON, mage.cards.a.AegisSculptor.class));
cards.add(new SetCardInfo("Agent of Kotis", 36, Rarity.COMMON, mage.cards.a.AgentOfKotis.class)); cards.add(new SetCardInfo("Agent of Kotis", 36, Rarity.COMMON, mage.cards.a.AgentOfKotis.class));
cards.add(new SetCardInfo("Aggressive Negotiations", 70, Rarity.COMMON, mage.cards.a.AggressiveNegotiations.class));
cards.add(new SetCardInfo("Ainok Wayfarer", 134, Rarity.COMMON, mage.cards.a.AinokWayfarer.class)); cards.add(new SetCardInfo("Ainok Wayfarer", 134, Rarity.COMMON, mage.cards.a.AinokWayfarer.class));
cards.add(new SetCardInfo("Alchemist's Assistant", 71, Rarity.UNCOMMON, mage.cards.a.AlchemistsAssistant.class)); cards.add(new SetCardInfo("Alchemist's Assistant", 71, Rarity.UNCOMMON, mage.cards.a.AlchemistsAssistant.class));
cards.add(new SetCardInfo("Alesha's Legacy", 72, Rarity.COMMON, mage.cards.a.AleshasLegacy.class)); cards.add(new SetCardInfo("Alesha's Legacy", 72, Rarity.COMMON, mage.cards.a.AleshasLegacy.class));
@ -48,6 +49,7 @@ public final class TarkirDragonstorm extends ExpansionSet {
cards.add(new SetCardInfo("Caustic Exhale", 74, Rarity.COMMON, mage.cards.c.CausticExhale.class)); cards.add(new SetCardInfo("Caustic Exhale", 74, Rarity.COMMON, mage.cards.c.CausticExhale.class));
cards.add(new SetCardInfo("Champion of Dusan", 137, Rarity.COMMON, mage.cards.c.ChampionOfDusan.class)); cards.add(new SetCardInfo("Champion of Dusan", 137, Rarity.COMMON, mage.cards.c.ChampionOfDusan.class));
cards.add(new SetCardInfo("Channeled Dragonfire", 102, Rarity.UNCOMMON, mage.cards.c.ChanneledDragonfire.class)); cards.add(new SetCardInfo("Channeled Dragonfire", 102, Rarity.UNCOMMON, mage.cards.c.ChanneledDragonfire.class));
cards.add(new SetCardInfo("Clarion Conqueror", 5, Rarity.RARE, mage.cards.c.ClarionConqueror.class));
cards.add(new SetCardInfo("Constrictor Sage", 39, Rarity.UNCOMMON, mage.cards.c.ConstrictorSage.class)); cards.add(new SetCardInfo("Constrictor Sage", 39, Rarity.UNCOMMON, mage.cards.c.ConstrictorSage.class));
cards.add(new SetCardInfo("Coordinated Maneuver", 6, Rarity.COMMON, mage.cards.c.CoordinatedManeuver.class)); cards.add(new SetCardInfo("Coordinated Maneuver", 6, Rarity.COMMON, mage.cards.c.CoordinatedManeuver.class));
cards.add(new SetCardInfo("Cori Mountain Monastery", 252, Rarity.RARE, mage.cards.c.CoriMountainMonastery.class)); cards.add(new SetCardInfo("Cori Mountain Monastery", 252, Rarity.RARE, mage.cards.c.CoriMountainMonastery.class));
@ -61,6 +63,7 @@ public final class TarkirDragonstorm extends ExpansionSet {
cards.add(new SetCardInfo("Delta Bloodflies", 77, Rarity.COMMON, mage.cards.d.DeltaBloodflies.class)); cards.add(new SetCardInfo("Delta Bloodflies", 77, Rarity.COMMON, mage.cards.d.DeltaBloodflies.class));
cards.add(new SetCardInfo("Descendant of Storms", 8, Rarity.UNCOMMON, mage.cards.d.DescendantOfStorms.class)); cards.add(new SetCardInfo("Descendant of Storms", 8, Rarity.UNCOMMON, mage.cards.d.DescendantOfStorms.class));
cards.add(new SetCardInfo("Devoted Duelist", 104, Rarity.COMMON, mage.cards.d.DevotedDuelist.class)); cards.add(new SetCardInfo("Devoted Duelist", 104, Rarity.COMMON, mage.cards.d.DevotedDuelist.class));
cards.add(new SetCardInfo("Dirgur Island Dragon", 40, Rarity.COMMON, mage.cards.d.DirgurIslandDragon.class));
cards.add(new SetCardInfo("Dismal Backwater", 254, Rarity.COMMON, mage.cards.d.DismalBackwater.class)); cards.add(new SetCardInfo("Dismal Backwater", 254, Rarity.COMMON, mage.cards.d.DismalBackwater.class));
cards.add(new SetCardInfo("Dispelling Exhale", 41, Rarity.COMMON, mage.cards.d.DispellingExhale.class)); cards.add(new SetCardInfo("Dispelling Exhale", 41, Rarity.COMMON, mage.cards.d.DispellingExhale.class));
cards.add(new SetCardInfo("Dracogenesis", 105, Rarity.MYTHIC, mage.cards.d.Dracogenesis.class)); cards.add(new SetCardInfo("Dracogenesis", 105, Rarity.MYTHIC, mage.cards.d.Dracogenesis.class));
@ -69,28 +72,42 @@ public final class TarkirDragonstorm extends ExpansionSet {
cards.add(new SetCardInfo("Dragonback Assault", 179, Rarity.MYTHIC, mage.cards.d.DragonbackAssault.class)); cards.add(new SetCardInfo("Dragonback Assault", 179, Rarity.MYTHIC, mage.cards.d.DragonbackAssault.class));
cards.add(new SetCardInfo("Dragonback Lancer", 9, Rarity.COMMON, mage.cards.d.DragonbackLancer.class)); cards.add(new SetCardInfo("Dragonback Lancer", 9, Rarity.COMMON, mage.cards.d.DragonbackLancer.class));
cards.add(new SetCardInfo("Dragonbroods' Relic", 140, Rarity.UNCOMMON, mage.cards.d.DragonbroodsRelic.class)); cards.add(new SetCardInfo("Dragonbroods' Relic", 140, Rarity.UNCOMMON, mage.cards.d.DragonbroodsRelic.class));
cards.add(new SetCardInfo("Dragonclaw Strike", 180, Rarity.UNCOMMON, mage.cards.d.DragonclawStrike.class));
cards.add(new SetCardInfo("Dragonologist", 42, Rarity.RARE, mage.cards.d.Dragonologist.class)); cards.add(new SetCardInfo("Dragonologist", 42, Rarity.RARE, mage.cards.d.Dragonologist.class));
cards.add(new SetCardInfo("Dragonstorm Forecaster", 43, Rarity.UNCOMMON, mage.cards.d.DragonstormForecaster.class)); cards.add(new SetCardInfo("Dragonstorm Forecaster", 43, Rarity.UNCOMMON, mage.cards.d.DragonstormForecaster.class));
cards.add(new SetCardInfo("Dragonstorm Globe", 241, Rarity.COMMON, mage.cards.d.DragonstormGlobe.class)); cards.add(new SetCardInfo("Dragonstorm Globe", 241, Rarity.COMMON, mage.cards.d.DragonstormGlobe.class));
cards.add(new SetCardInfo("Dusyut Earthcarver", 141, Rarity.COMMON, mage.cards.d.DusyutEarthcarver.class)); cards.add(new SetCardInfo("Dusyut Earthcarver", 141, Rarity.COMMON, mage.cards.d.DusyutEarthcarver.class));
cards.add(new SetCardInfo("Duty Beyond Death", 10, Rarity.UNCOMMON, mage.cards.d.DutyBeyondDeath.class)); cards.add(new SetCardInfo("Duty Beyond Death", 10, Rarity.UNCOMMON, mage.cards.d.DutyBeyondDeath.class));
cards.add(new SetCardInfo("Effortless Master", 181, Rarity.UNCOMMON, mage.cards.e.EffortlessMaster.class));
cards.add(new SetCardInfo("Elspeth, Storm Slayer", 11, Rarity.MYTHIC, mage.cards.e.ElspethStormSlayer.class));
cards.add(new SetCardInfo("Embermouth Sentinel", 242, Rarity.COMMON, mage.cards.e.EmbermouthSentinel.class)); cards.add(new SetCardInfo("Embermouth Sentinel", 242, Rarity.COMMON, mage.cards.e.EmbermouthSentinel.class));
cards.add(new SetCardInfo("Encroaching Dragonstorm", 142, Rarity.UNCOMMON, mage.cards.e.EncroachingDragonstorm.class)); cards.add(new SetCardInfo("Encroaching Dragonstorm", 142, Rarity.UNCOMMON, mage.cards.e.EncroachingDragonstorm.class));
cards.add(new SetCardInfo("Equilibrium Adept", 106, Rarity.UNCOMMON, mage.cards.e.EquilibriumAdept.class)); cards.add(new SetCardInfo("Equilibrium Adept", 106, Rarity.UNCOMMON, mage.cards.e.EquilibriumAdept.class));
cards.add(new SetCardInfo("Eshki Dragonclaw", 182, Rarity.RARE, mage.cards.e.EshkiDragonclaw.class));
cards.add(new SetCardInfo("Essence Anchor", 44, Rarity.UNCOMMON, mage.cards.e.EssenceAnchor.class));
cards.add(new SetCardInfo("Evolving Wilds", 255, Rarity.COMMON, mage.cards.e.EvolvingWilds.class)); cards.add(new SetCardInfo("Evolving Wilds", 255, Rarity.COMMON, mage.cards.e.EvolvingWilds.class));
cards.add(new SetCardInfo("Fangkeeper's Familiar", 183, Rarity.RARE, mage.cards.f.FangkeepersFamiliar.class)); cards.add(new SetCardInfo("Fangkeeper's Familiar", 183, Rarity.RARE, mage.cards.f.FangkeepersFamiliar.class));
cards.add(new SetCardInfo("Felothar, Dawn of the Abzan", 184, Rarity.RARE, mage.cards.f.FelotharDawnOfTheAbzan.class)); cards.add(new SetCardInfo("Felothar, Dawn of the Abzan", 184, Rarity.RARE, mage.cards.f.FelotharDawnOfTheAbzan.class));
cards.add(new SetCardInfo("Fire-Rim Form", 107, Rarity.COMMON, mage.cards.f.FireRimForm.class)); cards.add(new SetCardInfo("Fire-Rim Form", 107, Rarity.COMMON, mage.cards.f.FireRimForm.class));
cards.add(new SetCardInfo("Flamehold Grappler", 185, Rarity.RARE, mage.cards.f.FlameholdGrappler.class));
cards.add(new SetCardInfo("Fleeting Effigy", 108, Rarity.UNCOMMON, mage.cards.f.FleetingEffigy.class)); cards.add(new SetCardInfo("Fleeting Effigy", 108, Rarity.UNCOMMON, mage.cards.f.FleetingEffigy.class));
cards.add(new SetCardInfo("Forest", 285, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Forest", 285, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Formation Breaker", 143, Rarity.UNCOMMON, mage.cards.f.FormationBreaker.class));
cards.add(new SetCardInfo("Fortress Kin-Guard", 12, Rarity.COMMON, mage.cards.f.FortressKinGuard.class)); cards.add(new SetCardInfo("Fortress Kin-Guard", 12, Rarity.COMMON, mage.cards.f.FortressKinGuard.class));
cards.add(new SetCardInfo("Fresh Start", 46, Rarity.UNCOMMON, mage.cards.f.FreshStart.class)); cards.add(new SetCardInfo("Fresh Start", 46, Rarity.UNCOMMON, mage.cards.f.FreshStart.class));
cards.add(new SetCardInfo("Frontier Bivouac", 256, Rarity.UNCOMMON, mage.cards.f.FrontierBivouac.class)); cards.add(new SetCardInfo("Frontier Bivouac", 256, Rarity.UNCOMMON, mage.cards.f.FrontierBivouac.class));
cards.add(new SetCardInfo("Frontline Rush", 186, Rarity.UNCOMMON, mage.cards.f.FrontlineRush.class));
cards.add(new SetCardInfo("Frostcliff Siege", 187, Rarity.RARE, mage.cards.f.FrostcliffSiege.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Frostcliff Siege", 385, Rarity.RARE, mage.cards.f.FrostcliffSiege.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Glacial Dragonhunt", 188, Rarity.UNCOMMON, mage.cards.g.GlacialDragonhunt.class)); cards.add(new SetCardInfo("Glacial Dragonhunt", 188, Rarity.UNCOMMON, mage.cards.g.GlacialDragonhunt.class));
cards.add(new SetCardInfo("Glacierwood Siege", 189, Rarity.RARE, mage.cards.g.GlacierwoodSiege.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Glacierwood Siege", 386, Rarity.RARE, mage.cards.g.GlacierwoodSiege.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Great Arashin City", 257, Rarity.RARE, mage.cards.g.GreatArashinCity.class)); cards.add(new SetCardInfo("Great Arashin City", 257, Rarity.RARE, mage.cards.g.GreatArashinCity.class));
cards.add(new SetCardInfo("Gurmag Nightwatch", 190, Rarity.COMMON, mage.cards.g.GurmagNightwatch.class)); cards.add(new SetCardInfo("Gurmag Nightwatch", 190, Rarity.COMMON, mage.cards.g.GurmagNightwatch.class));
cards.add(new SetCardInfo("Gurmag Rakshasa", 81, Rarity.UNCOMMON, mage.cards.g.GurmagRakshasa.class));
cards.add(new SetCardInfo("Hardened Tactician", 191, Rarity.UNCOMMON, mage.cards.h.HardenedTactician.class)); cards.add(new SetCardInfo("Hardened Tactician", 191, Rarity.UNCOMMON, mage.cards.h.HardenedTactician.class));
cards.add(new SetCardInfo("Heritage Reclamation", 145, Rarity.COMMON, mage.cards.h.HeritageReclamation.class)); cards.add(new SetCardInfo("Heritage Reclamation", 145, Rarity.COMMON, mage.cards.h.HeritageReclamation.class));
cards.add(new SetCardInfo("Highspire Bell-Ringer", 47, Rarity.COMMON, mage.cards.h.HighspireBellRinger.class));
cards.add(new SetCardInfo("Humbling Elder", 48, Rarity.COMMON, mage.cards.h.HumblingElder.class)); cards.add(new SetCardInfo("Humbling Elder", 48, Rarity.COMMON, mage.cards.h.HumblingElder.class));
cards.add(new SetCardInfo("Iceridge Serpent", 49, Rarity.COMMON, mage.cards.i.IceridgeSerpent.class)); cards.add(new SetCardInfo("Iceridge Serpent", 49, Rarity.COMMON, mage.cards.i.IceridgeSerpent.class));
cards.add(new SetCardInfo("Inevitable Defeat", 194, Rarity.RARE, mage.cards.i.InevitableDefeat.class)); cards.add(new SetCardInfo("Inevitable Defeat", 194, Rarity.RARE, mage.cards.i.InevitableDefeat.class));
@ -103,6 +120,7 @@ public final class TarkirDragonstorm extends ExpansionSet {
cards.add(new SetCardInfo("Jeskai Monument", 244, Rarity.UNCOMMON, mage.cards.j.JeskaiMonument.class)); cards.add(new SetCardInfo("Jeskai Monument", 244, Rarity.UNCOMMON, mage.cards.j.JeskaiMonument.class));
cards.add(new SetCardInfo("Jeskai Shrinekeeper", 197, Rarity.UNCOMMON, mage.cards.j.JeskaiShrinekeeper.class)); cards.add(new SetCardInfo("Jeskai Shrinekeeper", 197, Rarity.UNCOMMON, mage.cards.j.JeskaiShrinekeeper.class));
cards.add(new SetCardInfo("Jungle Hollow", 258, Rarity.COMMON, mage.cards.j.JungleHollow.class)); cards.add(new SetCardInfo("Jungle Hollow", 258, Rarity.COMMON, mage.cards.j.JungleHollow.class));
cards.add(new SetCardInfo("Karakyk Guardian", 198, Rarity.UNCOMMON, mage.cards.k.KarakykGuardian.class));
cards.add(new SetCardInfo("Kheru Goldkeeper", 199, Rarity.UNCOMMON, mage.cards.k.KheruGoldkeeper.class)); cards.add(new SetCardInfo("Kheru Goldkeeper", 199, Rarity.UNCOMMON, mage.cards.k.KheruGoldkeeper.class));
cards.add(new SetCardInfo("Kin-Tree Nurturer", 83, Rarity.COMMON, mage.cards.k.KinTreeNurturer.class)); cards.add(new SetCardInfo("Kin-Tree Nurturer", 83, Rarity.COMMON, mage.cards.k.KinTreeNurturer.class));
cards.add(new SetCardInfo("Kin-Tree Severance", 200, Rarity.UNCOMMON, mage.cards.k.KinTreeSeverance.class)); cards.add(new SetCardInfo("Kin-Tree Severance", 200, Rarity.UNCOMMON, mage.cards.k.KinTreeSeverance.class));
@ -112,11 +130,16 @@ public final class TarkirDragonstorm extends ExpansionSet {
cards.add(new SetCardInfo("Knockout Maneuver", 147, Rarity.UNCOMMON, mage.cards.k.KnockoutManeuver.class)); cards.add(new SetCardInfo("Knockout Maneuver", 147, Rarity.UNCOMMON, mage.cards.k.KnockoutManeuver.class));
cards.add(new SetCardInfo("Kotis, the Fangkeeper", 202, Rarity.RARE, mage.cards.k.KotisTheFangkeeper.class)); cards.add(new SetCardInfo("Kotis, the Fangkeeper", 202, Rarity.RARE, mage.cards.k.KotisTheFangkeeper.class));
cards.add(new SetCardInfo("Krotiq Nestguard", 148, Rarity.COMMON, mage.cards.k.KrotiqNestguard.class)); cards.add(new SetCardInfo("Krotiq Nestguard", 148, Rarity.COMMON, mage.cards.k.KrotiqNestguard.class));
cards.add(new SetCardInfo("Lasyd Prowler", 149, Rarity.RARE, mage.cards.l.LasydProwler.class));
cards.add(new SetCardInfo("Lie in Wait", 203, Rarity.UNCOMMON, mage.cards.l.LieInWait.class));
cards.add(new SetCardInfo("Lightfoot Technique", 14, Rarity.COMMON, mage.cards.l.LightfootTechnique.class)); cards.add(new SetCardInfo("Lightfoot Technique", 14, Rarity.COMMON, mage.cards.l.LightfootTechnique.class));
cards.add(new SetCardInfo("Lotuslight Dancers", 204, Rarity.RARE, mage.cards.l.LotuslightDancers.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Lotuslight Dancers", 363, Rarity.RARE, mage.cards.l.LotuslightDancers.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Loxodon Battle Priest", 15, Rarity.UNCOMMON, mage.cards.l.LoxodonBattlePriest.class)); cards.add(new SetCardInfo("Loxodon Battle Priest", 15, Rarity.UNCOMMON, mage.cards.l.LoxodonBattlePriest.class));
cards.add(new SetCardInfo("Mammoth Bellow", 205, Rarity.UNCOMMON, mage.cards.m.MammothBellow.class)); cards.add(new SetCardInfo("Mammoth Bellow", 205, Rarity.UNCOMMON, mage.cards.m.MammothBellow.class));
cards.add(new SetCardInfo("Mardu Devotee", 16, Rarity.COMMON, mage.cards.m.MarduDevotee.class)); cards.add(new SetCardInfo("Mardu Devotee", 16, Rarity.COMMON, mage.cards.m.MarduDevotee.class));
cards.add(new SetCardInfo("Mardu Monument", 245, Rarity.UNCOMMON, mage.cards.m.MarduMonument.class)); cards.add(new SetCardInfo("Mardu Monument", 245, Rarity.UNCOMMON, mage.cards.m.MarduMonument.class));
cards.add(new SetCardInfo("Mardu Siegebreaker", 206, Rarity.RARE, mage.cards.m.MarduSiegebreaker.class));
cards.add(new SetCardInfo("Marshal of the Lost", 207, Rarity.UNCOMMON, mage.cards.m.MarshalOfTheLost.class)); cards.add(new SetCardInfo("Marshal of the Lost", 207, Rarity.UNCOMMON, mage.cards.m.MarshalOfTheLost.class));
cards.add(new SetCardInfo("Meticulous Artisan", 112, Rarity.COMMON, mage.cards.m.MeticulousArtisan.class)); cards.add(new SetCardInfo("Meticulous Artisan", 112, Rarity.COMMON, mage.cards.m.MeticulousArtisan.class));
cards.add(new SetCardInfo("Molten Exhale", 113, Rarity.COMMON, mage.cards.m.MoltenExhale.class)); cards.add(new SetCardInfo("Molten Exhale", 113, Rarity.COMMON, mage.cards.m.MoltenExhale.class));
@ -124,6 +147,7 @@ public final class TarkirDragonstorm extends ExpansionSet {
cards.add(new SetCardInfo("Mountain", 283, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mountain", 283, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Mox Jasper", 246, Rarity.MYTHIC, mage.cards.m.MoxJasper.class)); cards.add(new SetCardInfo("Mox Jasper", 246, Rarity.MYTHIC, mage.cards.m.MoxJasper.class));
cards.add(new SetCardInfo("Mystic Monastery", 262, Rarity.UNCOMMON, mage.cards.m.MysticMonastery.class)); cards.add(new SetCardInfo("Mystic Monastery", 262, Rarity.UNCOMMON, mage.cards.m.MysticMonastery.class));
cards.add(new SetCardInfo("Naga Fleshcrafter", 52, Rarity.RARE, mage.cards.n.NagaFleshcrafter.class));
cards.add(new SetCardInfo("Narset's Rebuke", 114, Rarity.COMMON, mage.cards.n.NarsetsRebuke.class)); cards.add(new SetCardInfo("Narset's Rebuke", 114, Rarity.COMMON, mage.cards.n.NarsetsRebuke.class));
cards.add(new SetCardInfo("Narset, Jeskai Waymaster", 209, Rarity.RARE, mage.cards.n.NarsetJeskaiWaymaster.class)); cards.add(new SetCardInfo("Narset, Jeskai Waymaster", 209, Rarity.RARE, mage.cards.n.NarsetJeskaiWaymaster.class));
cards.add(new SetCardInfo("Nature's Rhythm", 150, Rarity.RARE, mage.cards.n.NaturesRhythm.class)); cards.add(new SetCardInfo("Nature's Rhythm", 150, Rarity.RARE, mage.cards.n.NaturesRhythm.class));
@ -137,15 +161,18 @@ public final class TarkirDragonstorm extends ExpansionSet {
cards.add(new SetCardInfo("Plains", 277, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plains", 277, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Poised Practitioner", 18, Rarity.COMMON, mage.cards.p.PoisedPractitioner.class)); cards.add(new SetCardInfo("Poised Practitioner", 18, Rarity.COMMON, mage.cards.p.PoisedPractitioner.class));
cards.add(new SetCardInfo("Qarsi Revenant", 86, Rarity.RARE, mage.cards.q.QarsiRevenant.class)); cards.add(new SetCardInfo("Qarsi Revenant", 86, Rarity.RARE, mage.cards.q.QarsiRevenant.class));
cards.add(new SetCardInfo("Rainveil Rejuvenator", 152, Rarity.UNCOMMON, mage.cards.r.RainveilRejuvenator.class));
cards.add(new SetCardInfo("Rakshasa's Bargain", 214, Rarity.UNCOMMON, mage.cards.r.RakshasasBargain.class)); cards.add(new SetCardInfo("Rakshasa's Bargain", 214, Rarity.UNCOMMON, mage.cards.r.RakshasasBargain.class));
cards.add(new SetCardInfo("Rally the Monastery", 19, Rarity.UNCOMMON, mage.cards.r.RallyTheMonastery.class)); cards.add(new SetCardInfo("Rally the Monastery", 19, Rarity.UNCOMMON, mage.cards.r.RallyTheMonastery.class));
cards.add(new SetCardInfo("Rebellious Strike", 20, Rarity.COMMON, mage.cards.r.RebelliousStrike.class)); cards.add(new SetCardInfo("Rebellious Strike", 20, Rarity.COMMON, mage.cards.r.RebelliousStrike.class));
cards.add(new SetCardInfo("Rediscover the Way", 215, Rarity.RARE, mage.cards.r.RediscoverTheWay.class));
cards.add(new SetCardInfo("Reigning Victor", 216, Rarity.COMMON, mage.cards.r.ReigningVictor.class)); cards.add(new SetCardInfo("Reigning Victor", 216, Rarity.COMMON, mage.cards.r.ReigningVictor.class));
cards.add(new SetCardInfo("Reputable Merchant", 217, Rarity.COMMON, mage.cards.r.ReputableMerchant.class)); cards.add(new SetCardInfo("Reputable Merchant", 217, Rarity.COMMON, mage.cards.r.ReputableMerchant.class));
cards.add(new SetCardInfo("Rescue Leopard", 116, Rarity.COMMON, mage.cards.r.RescueLeopard.class)); cards.add(new SetCardInfo("Rescue Leopard", 116, Rarity.COMMON, mage.cards.r.RescueLeopard.class));
cards.add(new SetCardInfo("Revival of the Ancestors", 218, Rarity.RARE, mage.cards.r.RevivalOfTheAncestors.class)); cards.add(new SetCardInfo("Revival of the Ancestors", 218, Rarity.RARE, mage.cards.r.RevivalOfTheAncestors.class));
cards.add(new SetCardInfo("Ringing Strike Mastery", 53, Rarity.COMMON, mage.cards.r.RingingStrikeMastery.class)); cards.add(new SetCardInfo("Ringing Strike Mastery", 53, Rarity.COMMON, mage.cards.r.RingingStrikeMastery.class));
cards.add(new SetCardInfo("Riverwalk Technique", 54, Rarity.COMMON, mage.cards.r.RiverwalkTechnique.class)); cards.add(new SetCardInfo("Riverwalk Technique", 54, Rarity.COMMON, mage.cards.r.RiverwalkTechnique.class));
cards.add(new SetCardInfo("Riverwheel Sweep", 219, Rarity.UNCOMMON, mage.cards.r.RiverwheelSweep.class));
cards.add(new SetCardInfo("Roamer's Routine", 154, Rarity.COMMON, mage.cards.r.RoamersRoutine.class)); cards.add(new SetCardInfo("Roamer's Routine", 154, Rarity.COMMON, mage.cards.r.RoamersRoutine.class));
cards.add(new SetCardInfo("Roar of Endless Song", 220, Rarity.RARE, mage.cards.r.RoarOfEndlessSong.class)); cards.add(new SetCardInfo("Roar of Endless Song", 220, Rarity.RARE, mage.cards.r.RoarOfEndlessSong.class));
cards.add(new SetCardInfo("Roiling Dragonstorm", 55, Rarity.UNCOMMON, mage.cards.r.RoilingDragonstorm.class)); cards.add(new SetCardInfo("Roiling Dragonstorm", 55, Rarity.UNCOMMON, mage.cards.r.RoilingDragonstorm.class));
@ -153,6 +180,7 @@ public final class TarkirDragonstorm extends ExpansionSet {
cards.add(new SetCardInfo("Sage of the Fang", 155, Rarity.UNCOMMON, mage.cards.s.SageOfTheFang.class)); cards.add(new SetCardInfo("Sage of the Fang", 155, Rarity.UNCOMMON, mage.cards.s.SageOfTheFang.class));
cards.add(new SetCardInfo("Sagu Pummeler", 156, Rarity.COMMON, mage.cards.s.SaguPummeler.class)); cards.add(new SetCardInfo("Sagu Pummeler", 156, Rarity.COMMON, mage.cards.s.SaguPummeler.class));
cards.add(new SetCardInfo("Salt Road Packbeast", 23, Rarity.COMMON, mage.cards.s.SaltRoadPackbeast.class)); cards.add(new SetCardInfo("Salt Road Packbeast", 23, Rarity.COMMON, mage.cards.s.SaltRoadPackbeast.class));
cards.add(new SetCardInfo("Salt Road Skirmish", 88, Rarity.UNCOMMON, mage.cards.s.SaltRoadSkirmish.class));
cards.add(new SetCardInfo("Sandskitter Outrider", 89, Rarity.COMMON, mage.cards.s.SandskitterOutrider.class)); cards.add(new SetCardInfo("Sandskitter Outrider", 89, Rarity.COMMON, mage.cards.s.SandskitterOutrider.class));
cards.add(new SetCardInfo("Sandsteppe Citadel", 266, Rarity.UNCOMMON, mage.cards.s.SandsteppeCitadel.class)); cards.add(new SetCardInfo("Sandsteppe Citadel", 266, Rarity.UNCOMMON, mage.cards.s.SandsteppeCitadel.class));
cards.add(new SetCardInfo("Sarkhan's Resolve", 158, Rarity.COMMON, mage.cards.s.SarkhansResolve.class)); cards.add(new SetCardInfo("Sarkhan's Resolve", 158, Rarity.COMMON, mage.cards.s.SarkhansResolve.class));
@ -163,6 +191,7 @@ public final class TarkirDragonstorm extends ExpansionSet {
cards.add(new SetCardInfo("Shock Brigade", 120, Rarity.COMMON, mage.cards.s.ShockBrigade.class)); cards.add(new SetCardInfo("Shock Brigade", 120, Rarity.COMMON, mage.cards.s.ShockBrigade.class));
cards.add(new SetCardInfo("Shocking Sharpshooter", 121, Rarity.UNCOMMON, mage.cards.s.ShockingSharpshooter.class)); cards.add(new SetCardInfo("Shocking Sharpshooter", 121, Rarity.UNCOMMON, mage.cards.s.ShockingSharpshooter.class));
cards.add(new SetCardInfo("Sibsig Appraiser", 56, Rarity.COMMON, mage.cards.s.SibsigAppraiser.class)); cards.add(new SetCardInfo("Sibsig Appraiser", 56, Rarity.COMMON, mage.cards.s.SibsigAppraiser.class));
cards.add(new SetCardInfo("Sidisi, Regent of the Mire", 92, Rarity.RARE, mage.cards.s.SidisiRegentOfTheMire.class));
cards.add(new SetCardInfo("Sinkhole Surveyor", 93, Rarity.RARE, mage.cards.s.SinkholeSurveyor.class)); cards.add(new SetCardInfo("Sinkhole Surveyor", 93, Rarity.RARE, mage.cards.s.SinkholeSurveyor.class));
cards.add(new SetCardInfo("Skirmish Rhino", 224, Rarity.UNCOMMON, mage.cards.s.SkirmishRhino.class)); cards.add(new SetCardInfo("Skirmish Rhino", 224, Rarity.UNCOMMON, mage.cards.s.SkirmishRhino.class));
cards.add(new SetCardInfo("Smile at Death", 24, Rarity.MYTHIC, mage.cards.s.SmileAtDeath.class)); cards.add(new SetCardInfo("Smile at Death", 24, Rarity.MYTHIC, mage.cards.s.SmileAtDeath.class));
@ -172,24 +201,33 @@ public final class TarkirDragonstorm extends ExpansionSet {
cards.add(new SetCardInfo("Sonic Shrieker", 226, Rarity.UNCOMMON, mage.cards.s.SonicShrieker.class)); cards.add(new SetCardInfo("Sonic Shrieker", 226, Rarity.UNCOMMON, mage.cards.s.SonicShrieker.class));
cards.add(new SetCardInfo("Spectral Denial", 58, Rarity.UNCOMMON, mage.cards.s.SpectralDenial.class)); cards.add(new SetCardInfo("Spectral Denial", 58, Rarity.UNCOMMON, mage.cards.s.SpectralDenial.class));
cards.add(new SetCardInfo("Stadium Headliner", 122, Rarity.RARE, mage.cards.s.StadiumHeadliner.class)); cards.add(new SetCardInfo("Stadium Headliner", 122, Rarity.RARE, mage.cards.s.StadiumHeadliner.class));
cards.add(new SetCardInfo("Starry-Eyed Skyrider", 25, Rarity.UNCOMMON, mage.cards.s.StarryEyedSkyrider.class));
cards.add(new SetCardInfo("Static Snare", 26, Rarity.UNCOMMON, mage.cards.s.StaticSnare.class)); cards.add(new SetCardInfo("Static Snare", 26, Rarity.UNCOMMON, mage.cards.s.StaticSnare.class));
cards.add(new SetCardInfo("Stillness in Motion", 59, Rarity.RARE, mage.cards.s.StillnessInMotion.class));
cards.add(new SetCardInfo("Stormbeacon Blade", 27, Rarity.UNCOMMON, mage.cards.s.StormbeaconBlade.class)); cards.add(new SetCardInfo("Stormbeacon Blade", 27, Rarity.UNCOMMON, mage.cards.s.StormbeaconBlade.class));
cards.add(new SetCardInfo("Stormplain Detainment", 28, Rarity.COMMON, mage.cards.s.StormplainDetainment.class)); cards.add(new SetCardInfo("Stormplain Detainment", 28, Rarity.COMMON, mage.cards.s.StormplainDetainment.class));
cards.add(new SetCardInfo("Stormscale Scion", 123, Rarity.MYTHIC, mage.cards.s.StormscaleScion.class)); cards.add(new SetCardInfo("Stormscale Scion", 123, Rarity.MYTHIC, mage.cards.s.StormscaleScion.class));
cards.add(new SetCardInfo("Strategic Betrayal", 94, Rarity.UNCOMMON, mage.cards.s.StrategicBetrayal.class));
cards.add(new SetCardInfo("Sultai Devotee", 160, Rarity.COMMON, mage.cards.s.SultaiDevotee.class)); cards.add(new SetCardInfo("Sultai Devotee", 160, Rarity.COMMON, mage.cards.s.SultaiDevotee.class));
cards.add(new SetCardInfo("Sultai Monument", 247, Rarity.UNCOMMON, mage.cards.s.SultaiMonument.class)); cards.add(new SetCardInfo("Sultai Monument", 247, Rarity.UNCOMMON, mage.cards.s.SultaiMonument.class));
cards.add(new SetCardInfo("Summit Intimidator", 125, Rarity.COMMON, mage.cards.s.SummitIntimidator.class)); cards.add(new SetCardInfo("Summit Intimidator", 125, Rarity.COMMON, mage.cards.s.SummitIntimidator.class));
cards.add(new SetCardInfo("Sunpearl Kirin", 29, Rarity.UNCOMMON, mage.cards.s.SunpearlKirin.class));
cards.add(new SetCardInfo("Sunset Strikemaster", 126, Rarity.UNCOMMON, mage.cards.s.SunsetStrikemaster.class)); cards.add(new SetCardInfo("Sunset Strikemaster", 126, Rarity.UNCOMMON, mage.cards.s.SunsetStrikemaster.class));
cards.add(new SetCardInfo("Swamp", 281, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Swamp", 281, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Swiftwater Cliffs", 268, Rarity.COMMON, mage.cards.s.SwiftwaterCliffs.class)); cards.add(new SetCardInfo("Swiftwater Cliffs", 268, Rarity.COMMON, mage.cards.s.SwiftwaterCliffs.class));
cards.add(new SetCardInfo("Teeming Dragonstorm", 30, Rarity.UNCOMMON, mage.cards.t.TeemingDragonstorm.class)); cards.add(new SetCardInfo("Teeming Dragonstorm", 30, Rarity.UNCOMMON, mage.cards.t.TeemingDragonstorm.class));
cards.add(new SetCardInfo("Tempest Hawk", 31, Rarity.COMMON, mage.cards.t.TempestHawk.class)); cards.add(new SetCardInfo("Tempest Hawk", 31, Rarity.COMMON, mage.cards.t.TempestHawk.class));
cards.add(new SetCardInfo("Temur Battlecrier", 228, Rarity.RARE, mage.cards.t.TemurBattlecrier.class));
cards.add(new SetCardInfo("Temur Devotee", 61, Rarity.COMMON, mage.cards.t.TemurDevotee.class)); cards.add(new SetCardInfo("Temur Devotee", 61, Rarity.COMMON, mage.cards.t.TemurDevotee.class));
cards.add(new SetCardInfo("Temur Monument", 248, Rarity.UNCOMMON, mage.cards.t.TemurMonument.class)); cards.add(new SetCardInfo("Temur Monument", 248, Rarity.UNCOMMON, mage.cards.t.TemurMonument.class));
cards.add(new SetCardInfo("Temur Tawnyback", 229, Rarity.COMMON, mage.cards.t.TemurTawnyback.class)); cards.add(new SetCardInfo("Temur Tawnyback", 229, Rarity.COMMON, mage.cards.t.TemurTawnyback.class));
cards.add(new SetCardInfo("Tersa Lightshatter", 127, Rarity.RARE, mage.cards.t.TersaLightshatter.class));
cards.add(new SetCardInfo("The Sibsig Ceremony", 91, Rarity.RARE, mage.cards.t.TheSibsigCeremony.class)); cards.add(new SetCardInfo("The Sibsig Ceremony", 91, Rarity.RARE, mage.cards.t.TheSibsigCeremony.class));
cards.add(new SetCardInfo("Thornwood Falls", 269, Rarity.COMMON, mage.cards.t.ThornwoodFalls.class)); cards.add(new SetCardInfo("Thornwood Falls", 269, Rarity.COMMON, mage.cards.t.ThornwoodFalls.class));
cards.add(new SetCardInfo("Thunder of Unity", 231, Rarity.RARE, mage.cards.t.ThunderOfUnity.class));
cards.add(new SetCardInfo("Trade Route Envoy", 163, Rarity.COMMON, mage.cards.t.TradeRouteEnvoy.class));
cards.add(new SetCardInfo("Tranquil Cove", 270, Rarity.COMMON, mage.cards.t.TranquilCove.class)); cards.add(new SetCardInfo("Tranquil Cove", 270, Rarity.COMMON, mage.cards.t.TranquilCove.class));
cards.add(new SetCardInfo("Traveling Botanist", 164, Rarity.UNCOMMON, mage.cards.t.TravelingBotanist.class));
cards.add(new SetCardInfo("Twin Bolt", 128, Rarity.COMMON, mage.cards.t.TwinBolt.class)); cards.add(new SetCardInfo("Twin Bolt", 128, Rarity.COMMON, mage.cards.t.TwinBolt.class));
cards.add(new SetCardInfo("Ugin, Eye of the Storms", 1, Rarity.MYTHIC, mage.cards.u.UginEyeOfTheStorms.class)); cards.add(new SetCardInfo("Ugin, Eye of the Storms", 1, Rarity.MYTHIC, mage.cards.u.UginEyeOfTheStorms.class));
cards.add(new SetCardInfo("Unburied Earthcarver", 95, Rarity.COMMON, mage.cards.u.UnburiedEarthcarver.class)); cards.add(new SetCardInfo("Unburied Earthcarver", 95, Rarity.COMMON, mage.cards.u.UnburiedEarthcarver.class));
@ -200,8 +238,13 @@ public final class TarkirDragonstorm extends ExpansionSet {
cards.add(new SetCardInfo("Unrooted Ancestor", 96, Rarity.UNCOMMON, mage.cards.u.UnrootedAncestor.class)); cards.add(new SetCardInfo("Unrooted Ancestor", 96, Rarity.UNCOMMON, mage.cards.u.UnrootedAncestor.class));
cards.add(new SetCardInfo("Unsparing Boltcaster", 130, Rarity.UNCOMMON, mage.cards.u.UnsparingBoltcaster.class)); cards.add(new SetCardInfo("Unsparing Boltcaster", 130, Rarity.UNCOMMON, mage.cards.u.UnsparingBoltcaster.class));
cards.add(new SetCardInfo("Ureni's Rebuff", 63, Rarity.UNCOMMON, mage.cards.u.UrenisRebuff.class)); cards.add(new SetCardInfo("Ureni's Rebuff", 63, Rarity.UNCOMMON, mage.cards.u.UrenisRebuff.class));
cards.add(new SetCardInfo("Ureni, the Song Unending", 233, Rarity.MYTHIC, mage.cards.u.UreniTheSongUnending.class));
cards.add(new SetCardInfo("Venerated Stormsinger", 97, Rarity.UNCOMMON, mage.cards.v.VeneratedStormsinger.class)); cards.add(new SetCardInfo("Venerated Stormsinger", 97, Rarity.UNCOMMON, mage.cards.v.VeneratedStormsinger.class));
cards.add(new SetCardInfo("Veteran Ice Climber", 64, Rarity.UNCOMMON, mage.cards.v.VeteranIceClimber.class));
cards.add(new SetCardInfo("Voice of Victory", 33, Rarity.RARE, mage.cards.v.VoiceOfVictory.class)); cards.add(new SetCardInfo("Voice of Victory", 33, Rarity.RARE, mage.cards.v.VoiceOfVictory.class));
cards.add(new SetCardInfo("War Effort", 131, Rarity.UNCOMMON, mage.cards.w.WarEffort.class));
cards.add(new SetCardInfo("Wail of War", 98, Rarity.UNCOMMON, mage.cards.w.WailOfWar.class));
cards.add(new SetCardInfo("Warden of the Grove", 166, Rarity.RARE, mage.cards.w.WardenOfTheGrove.class));
cards.add(new SetCardInfo("Watcher of the Wayside", 249, Rarity.COMMON, mage.cards.w.WatcherOfTheWayside.class)); cards.add(new SetCardInfo("Watcher of the Wayside", 249, Rarity.COMMON, mage.cards.w.WatcherOfTheWayside.class));
cards.add(new SetCardInfo("Wayspeaker Bodyguard", 34, Rarity.UNCOMMON, mage.cards.w.WayspeakerBodyguard.class)); cards.add(new SetCardInfo("Wayspeaker Bodyguard", 34, Rarity.UNCOMMON, mage.cards.w.WayspeakerBodyguard.class));
cards.add(new SetCardInfo("Wild Ride", 132, Rarity.COMMON, mage.cards.w.WildRide.class)); cards.add(new SetCardInfo("Wild Ride", 132, Rarity.COMMON, mage.cards.w.WildRide.class));
@ -210,6 +253,7 @@ public final class TarkirDragonstorm extends ExpansionSet {
cards.add(new SetCardInfo("Wingspan Stride", 66, Rarity.COMMON, mage.cards.w.WingspanStride.class)); cards.add(new SetCardInfo("Wingspan Stride", 66, Rarity.COMMON, mage.cards.w.WingspanStride.class));
cards.add(new SetCardInfo("Winternight Stories", 67, Rarity.RARE, mage.cards.w.WinternightStories.class)); cards.add(new SetCardInfo("Winternight Stories", 67, Rarity.RARE, mage.cards.w.WinternightStories.class));
cards.add(new SetCardInfo("Worthy Cost", 99, Rarity.COMMON, mage.cards.w.WorthyCost.class)); cards.add(new SetCardInfo("Worthy Cost", 99, Rarity.COMMON, mage.cards.w.WorthyCost.class));
cards.add(new SetCardInfo("Yathan Roadwatcher", 236, Rarity.RARE, mage.cards.y.YathanRoadwatcher.class));
cards.add(new SetCardInfo("Yathan Tombguard", 100, Rarity.UNCOMMON, mage.cards.y.YathanTombguard.class)); cards.add(new SetCardInfo("Yathan Tombguard", 100, Rarity.UNCOMMON, mage.cards.y.YathanTombguard.class));
cards.add(new SetCardInfo("Zurgo's Vanguard", 133, Rarity.UNCOMMON, mage.cards.z.ZurgosVanguard.class)); cards.add(new SetCardInfo("Zurgo's Vanguard", 133, Rarity.UNCOMMON, mage.cards.z.ZurgosVanguard.class));
cards.add(new SetCardInfo("Zurgo, Thunder's Decree", 237, Rarity.RARE, mage.cards.z.ZurgoThundersDecree.class)); cards.add(new SetCardInfo("Zurgo, Thunder's Decree", 237, Rarity.RARE, mage.cards.z.ZurgoThundersDecree.class));

View file

@ -107,6 +107,7 @@ public final class TarkirDragonstormCommander extends ExpansionSet {
cards.add(new SetCardInfo("Electrodominance", 212, Rarity.RARE, mage.cards.e.Electrodominance.class)); cards.add(new SetCardInfo("Electrodominance", 212, Rarity.RARE, mage.cards.e.Electrodominance.class));
cards.add(new SetCardInfo("Elemental Bond", 254, Rarity.UNCOMMON, mage.cards.e.ElementalBond.class)); cards.add(new SetCardInfo("Elemental Bond", 254, Rarity.UNCOMMON, mage.cards.e.ElementalBond.class));
cards.add(new SetCardInfo("Eliminate the Competition", 179, Rarity.RARE, mage.cards.e.EliminateTheCompetition.class)); cards.add(new SetCardInfo("Eliminate the Competition", 179, Rarity.RARE, mage.cards.e.EliminateTheCompetition.class));
cards.add(new SetCardInfo("Elsha, Threefold Master", 2, Rarity.MYTHIC, mage.cards.e.ElshaThreefoldMaster.class));
cards.add(new SetCardInfo("Emeria Angel", 114, Rarity.RARE, mage.cards.e.EmeriaAngel.class)); cards.add(new SetCardInfo("Emeria Angel", 114, Rarity.RARE, mage.cards.e.EmeriaAngel.class));
cards.add(new SetCardInfo("Exotic Orchard", 360, Rarity.RARE, mage.cards.e.ExoticOrchard.class)); cards.add(new SetCardInfo("Exotic Orchard", 360, Rarity.RARE, mage.cards.e.ExoticOrchard.class));
cards.add(new SetCardInfo("Expansion // Explosion", 287, Rarity.RARE, mage.cards.e.ExpansionExplosion.class)); cards.add(new SetCardInfo("Expansion // Explosion", 287, Rarity.RARE, mage.cards.e.ExpansionExplosion.class));
@ -320,6 +321,7 @@ public final class TarkirDragonstormCommander extends ExpansionSet {
cards.add(new SetCardInfo("Tree of Redemption", 97, Rarity.MYTHIC, mage.cards.t.TreeOfRedemption.class)); cards.add(new SetCardInfo("Tree of Redemption", 97, Rarity.MYTHIC, mage.cards.t.TreeOfRedemption.class));
cards.add(new SetCardInfo("Twilight Drover", 136, Rarity.RARE, mage.cards.t.TwilightDrover.class)); cards.add(new SetCardInfo("Twilight Drover", 136, Rarity.RARE, mage.cards.t.TwilightDrover.class));
cards.add(new SetCardInfo("Twilight Mire", 409, Rarity.RARE, mage.cards.t.TwilightMire.class)); cards.add(new SetCardInfo("Twilight Mire", 409, Rarity.RARE, mage.cards.t.TwilightMire.class));
cards.add(new SetCardInfo("Ureni of the Unwritten", 9, Rarity.MYTHIC, mage.cards.u.UreniOfTheUnwritten.class));
cards.add(new SetCardInfo("Vanquish the Horde", 91, Rarity.RARE, mage.cards.v.VanquishTheHorde.class)); cards.add(new SetCardInfo("Vanquish the Horde", 91, Rarity.RARE, mage.cards.v.VanquishTheHorde.class));
cards.add(new SetCardInfo("Vault of the Archangel", 410, Rarity.RARE, mage.cards.v.VaultOfTheArchangel.class)); cards.add(new SetCardInfo("Vault of the Archangel", 410, Rarity.RARE, mage.cards.v.VaultOfTheArchangel.class));
cards.add(new SetCardInfo("Velomachus Lorehold", 309, Rarity.MYTHIC, mage.cards.v.VelomachusLorehold.class)); cards.add(new SetCardInfo("Velomachus Lorehold", 309, Rarity.MYTHIC, mage.cards.v.VelomachusLorehold.class));

View file

@ -30,4 +30,54 @@ public class WardTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Solitude", 1); assertGraveyardCount(playerA, "Solitude", 1);
assertPermanentCount(playerB, "Waterfall Aerialist", 1); assertPermanentCount(playerB, "Waterfall Aerialist", 1);
} }
@Test
public void wardPanharmonicon() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, "Panharmonicon");
addCard(Zone.BATTLEFIELD, playerA, "Young Red Dragon");
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 7);
addCard(Zone.BATTLEFIELD, playerB, "Roaming Throne");
addCard(Zone.HAND, playerA, "Scourge of Valkas");
setChoice(playerB, "Dragon");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Scourge of Valkas");
setChoice(playerA, "Whenever {this} or another Dragon");
addTarget(playerA, "Roaming Throne");
addTarget(playerA, "Roaming Throne");
setChoice(playerB, "ward {2}");
setChoice(playerA, "Yes");
setChoice(playerA, "No");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerB, "Roaming Throne", 1);
assertDamageReceived(playerB, "Roaming Throne", 2);
}
@Test
public void wardPanharmoniconCounter() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, "Panharmonicon");
addCard(Zone.BATTLEFIELD, playerA, "Young Red Dragon");
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
addCard(Zone.BATTLEFIELD, playerB, "Roaming Throne");
addCard(Zone.HAND, playerA, "Scourge of Valkas");
setChoice(playerB, "Dragon");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Scourge of Valkas");
setChoice(playerA, "Whenever {this} or another Dragon");
addTarget(playerA, "Roaming Throne");
addTarget(playerA, "Roaming Throne");
setChoice(playerB, "ward {2}");
setChoice(playerA, "No");
setChoice(playerA, "No");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerB, "Roaming Throne", 1);
assertDamageReceived(playerB, "Roaming Throne", 0);
}
} }

View file

@ -0,0 +1,77 @@
package org.mage.test.cards.cost.omen;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class OmenCardsTest extends CardTestPlayerBase {
@Test
public void testDirgurIslandDragonShuffle() {
setStrictChooseMode(true);
skipInitShuffling();
removeAllCardsFromLibrary(playerA);
addCard(Zone.HAND, playerA, "Dirgur Island Dragon");
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
addCard(Zone.BATTLEFIELD, playerB, "Bear Cub");
addCard(Zone.LIBRARY, playerA, "Mountain");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Skimming Strike", "Bear Cub");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLibraryCount(playerA, "Dirgur Island Dragon", 1);
assertTapped("Bear Cub", true);
assertHandCount(playerA, 1);
}
@Test
public void testDirgurIslandDragonShuffleAndPlay() {
setStrictChooseMode(true);
skipInitShuffling();
removeAllCardsFromLibrary(playerA);
addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
addCard(Zone.BATTLEFIELD, playerB, "Bear Cub");
addCard(Zone.LIBRARY, playerA, "Mountain");
addCard(Zone.HAND, playerA, "Dirgur Island Dragon");
castSpell(2, PhaseStep.BEGIN_COMBAT, playerA, "Skimming Strike", "Bear Cub");
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Dirgur Island Dragon");
setStopAt(3, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Dirgur Island Dragon", 1);
}
@Test
public void testCounteredInGraveyard() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
addCard(Zone.BATTLEFIELD, playerB,"Island", 4);
addCard(Zone.BATTLEFIELD, playerB,"Bear Cub");
addCard(Zone.HAND, playerA, "Dirgur Island Dragon");
addCard(Zone.HAND, playerB, "Counterspell");
castSpell(2, PhaseStep.BEGIN_COMBAT, playerA, "Skimming Strike", "Bear Cub");
castSpell(2, PhaseStep.BEGIN_COMBAT, playerB, "Counterspell", "Skimming Strike", "Skimming Strike", StackClause.WHILE_ON_STACK);
attack(2, playerB, "Bear Cub");
setStopAt(2, PhaseStep.END_TURN);
execute();
assertGraveyardCount(playerA, "Dirgur Island Dragon", 1);
assertLife(playerA, 20 - 2);
}
@Test
public void testGraveyardCast() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
addCard(Zone.BATTLEFIELD, playerA, "Kess, Dissident Mage");
addCard(Zone.GRAVEYARD, playerA, "Dirgur Island Dragon");
addCard(Zone.BATTLEFIELD, playerB, "Bear Cub");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Skimming Strike", "Bear Cub");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertLibraryCount(playerA, "Dirgur Island Dragon", 1);
}
}

View file

@ -0,0 +1,41 @@
package org.mage.test.cards.single.blb;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class PawpatchRecruitTest extends CardTestPlayerBase {
private static final String paw = "Pawpatch Recruit";
private static final String cub = "Bear Cub";
private static final String panharm = "Panharmonicon";
private static final String prowler = "Chrome Prowler";
@Test
public void testCopiedTriggerAbility() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerB, paw);
addCard(Zone.BATTLEFIELD, playerB, cub);
addCard(Zone.BATTLEFIELD, playerA, panharm);
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
addCard(Zone.HAND, playerA, prowler);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, prowler);
setChoice(playerA, "When {this} enters");
addTarget(playerA, paw);
addTarget(playerA, cub);
setChoice(playerB, "Whenever a creature");
addTarget(playerB, paw);
addTarget(playerB, cub);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertTapped(paw, true);
assertTapped(cub, true);
assertCounterCount(playerB, paw, CounterType.P1P1, 1);
assertCounterCount(playerB, cub, CounterType.P1P1, 1);
}
}

View file

@ -67,4 +67,35 @@ public class AgrusKosEternalSoldierTest extends CardTestPlayerBase {
assertLife(playerB, 20); assertLife(playerB, 20);
} }
@Test
public void testCopiedTriggerAbility() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerB, agrus);
addCard(Zone.BATTLEFIELD, playerB, turtle);
addCard(Zone.BATTLEFIELD, playerB, firewalker);
addCard(Zone.BATTLEFIELD, playerB, "Plateau", 4);
addCard(Zone.BATTLEFIELD, playerA, "Panharmonicon");
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 7);
addCard(Zone.HAND, playerA, "Smoldering Werewolf");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Smoldering Werewolf");
setChoice(playerA, "When {this} enters, it deals");
addTarget(playerA, agrus);
addTarget(playerA, agrus);
setChoice(playerB, true); // gain life
setChoice(playerB, "Whenever {this} becomes");
setChoice(playerB, true); // pay to copy
setChoice(playerB, true); // pay to copy
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertDamageReceived(playerB, agrus, 2);
assertDamageReceived(playerB, turtle, 2);
assertDamageReceived(playerB, firewalker, 0);
assertLife(playerA, 20);
assertLife(playerB, 21);
}
} }

View file

@ -6,8 +6,8 @@ import mage.MageObject;
import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCost;
import mage.abilities.costs.mana.VariableManaCost; import mage.abilities.costs.mana.VariableManaCost;
import mage.abilities.keyword.FlashAbility; import mage.abilities.keyword.FlashAbility;
import mage.cards.AdventureCardSpell;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.SpellOptionCard;
import mage.cards.SplitCard; import mage.cards.SplitCard;
import mage.constants.*; import mage.constants.*;
import mage.game.Game; import mage.game.Game;
@ -99,7 +99,7 @@ public class SpellAbility extends ActivatedAbilityImpl {
// forced to cast (can be part id or main id) // forced to cast (can be part id or main id)
Set<UUID> idsToCheck = new HashSet<>(); Set<UUID> idsToCheck = new HashSet<>();
idsToCheck.add(object.getId()); idsToCheck.add(object.getId());
if (object instanceof Card && !(object instanceof AdventureCardSpell)) { if (object instanceof Card && !(object instanceof SpellOptionCard)) {
idsToCheck.add(((Card) object).getMainCard().getId()); idsToCheck.add(((Card) object).getMainCard().getId());
} }
for (UUID idToCheck : idsToCheck) { for (UUID idToCheck : idsToCheck) {

View file

@ -70,7 +70,7 @@ public class BecomesTargetAnyTriggeredAbility extends TriggeredAbilityImpl {
if (permanent == null || !filterTarget.match(permanent, getControllerId(), this, game)) { if (permanent == null || !filterTarget.match(permanent, getControllerId(), this, game)) {
return false; return false;
} }
StackObject targetingObject = CardUtil.getTargetingStackObject(event, game); StackObject targetingObject = CardUtil.getTargetingStackObject(this.getId().toString(), event, game);
if (targetingObject == null || !filterStack.match(targetingObject, getControllerId(), this, game)) { if (targetingObject == null || !filterStack.match(targetingObject, getControllerId(), this, game)) {
return false; return false;
} }

View file

@ -54,7 +54,7 @@ public class BecomesTargetAttachedTriggeredAbility extends TriggeredAbilityImpl
if (enchantment == null || enchantment.getAttachedTo() == null || !event.getTargetId().equals(enchantment.getAttachedTo())) { if (enchantment == null || enchantment.getAttachedTo() == null || !event.getTargetId().equals(enchantment.getAttachedTo())) {
return false; return false;
} }
StackObject targetingObject = CardUtil.getTargetingStackObject(event, game); StackObject targetingObject = CardUtil.getTargetingStackObject(this.getId().toString(), event, game);
if (targetingObject == null || !filter.match(targetingObject, getControllerId(), this, game)) { if (targetingObject == null || !filter.match(targetingObject, getControllerId(), this, game)) {
return false; return false;
} }

View file

@ -63,7 +63,7 @@ public class BecomesTargetControllerTriggeredAbility extends TriggeredAbilityImp
return false; return false;
} }
} }
StackObject targetingObject = CardUtil.getTargetingStackObject(event, game); StackObject targetingObject = CardUtil.getTargetingStackObject(this.getId().toString(), event, game);
if (targetingObject == null || !filterStack.match(targetingObject, getControllerId(), this, game)) { if (targetingObject == null || !filterStack.match(targetingObject, getControllerId(), this, game)) {
return false; return false;
} }

View file

@ -57,7 +57,7 @@ public class BecomesTargetSourceTriggeredAbility extends TriggeredAbilityImpl {
if (!event.getTargetId().equals(getSourceId())) { if (!event.getTargetId().equals(getSourceId())) {
return false; return false;
} }
StackObject targetingObject = CardUtil.getTargetingStackObject(event, game); StackObject targetingObject = CardUtil.getTargetingStackObject(this.getId().toString(), event, game);
if (targetingObject == null || !filter.match(targetingObject, getControllerId(), this, game)) { if (targetingObject == null || !filter.match(targetingObject, getControllerId(), this, game)) {
return false; return false;
} }

Some files were not shown because too many files have changed in this diff Show more